summaryrefslogtreecommitdiff
path: root/src/server.rs
diff options
context:
space:
mode:
authorKjetil Orbekk <kjetil.orbekk@gmail.com>2017-06-17 20:08:31 -0400
committerKjetil Orbekk <kjetil.orbekk@gmail.com>2017-06-17 20:08:31 -0400
commit41025a52fe3d2e4988296bfdc1ef549b60b8b667 (patch)
tree8c0110b59bfc98a290a8806cb6a7759765b77129 /src/server.rs
parent651bfc36a8aa5a83c9143e62859623ef35f31c7f (diff)
Add login / logout functionality.
Adds the ability to log in, but doesn't yet authenticate against the database.
Diffstat (limited to 'src/server.rs')
-rw-r--r--src/server.rs106
1 files changed, 83 insertions, 23 deletions
diff --git a/src/server.rs b/src/server.rs
index f34489f..2ab4f75 100644
--- a/src/server.rs
+++ b/src/server.rs
@@ -1,19 +1,31 @@
-extern crate iron_sessionstorage;
-use iron_sessionstorage::traits::*;
+use iron;
+use iron::error::{HttpResult};
+use iron::headers::ContentType;
+use iron::modifiers::{Header, Redirect};
+use iron::status;
+use iron::{Iron, IronError, Request, IronResult, Response, Chain, Listening, Plugin, Url};
use iron_sessionstorage::SessionStorage;
use iron_sessionstorage::backends::SignedCookieBackend;
-use iron::status;
-use iron::modifiers::Header;
-use iron::headers::ContentType;
-use iron::{Iron, IronError, Request, IronResult, Response, Chain, Listening};
-use iron::error::{HttpResult};
-use router::Router;
-use systemd::unit;
-use systemd::journal;
+use iron_sessionstorage::traits::*;
+use iron_sessionstorage;
+use params::{Params, Value};
+use regex::Regex;
use render;
+use router::Router;
use staticfile::Static;
-use regex::Regex;
+use systemd::journal;
+use systemd::unit;
+use persistent::Read;
+#[derive(Clone, Default, Debug)]
+struct Context {
+ base_url: String
+}
+impl iron::typemap::Key for Context {
+ type Value = Context;
+}
+
+#[derive(Default, Debug, Clone)]
struct Login {
user: String,
}
@@ -52,9 +64,10 @@ fn overview(r: &mut Request) -> IronResult<Response> {
// info!("Updating session value. Current value: {}", session_value.0);
// session_value.0.push('a');
// try!(r.session().set(session_value));
+ let renderer = make_renderer(r)?;
Ok(Response::with((status::Ok,
Header(ContentType::html()),
- render::system_status(&units_by_section))))
+ renderer.system_status(&units_by_section))))
}
fn journal(r: &mut Request) -> IronResult<Response> {
@@ -77,47 +90,94 @@ fn unit_status(r: &mut Request) -> IronResult<Response> {
let unit_name = iexpect!(r.extensions
.get::<Router>()
.unwrap()
- .find("unit"), status::BadRequest);
+ .find("unit"), status::BadRequest).to_string();
let re = Regex::new(r"[-_\w\d]*").unwrap();
- if !re.is_match(unit_name) {
+ if !re.is_match(&unit_name) {
return Ok(Response::with(
(status::BadRequest,
format!("Unit ({}) does not match {}",
unit_name, re))));
}
- let ref unit = itry!(unit::get_units(unit_name))[0];
- let log = itry!(journal::get_log(unit_name, 15));
+ let ref unit = itry!(unit::get_units(&unit_name))[0];
+ let log = itry!(journal::get_log(&unit_name, 15));
+ let renderer = make_renderer(r)?;
Ok(Response::with((status::Ok,
Header(ContentType::html()),
- render::unit_status(&unit, &log))))
+ renderer.unit_status(&unit, &log))))
+}
+
+fn get_logged_in_user(r: &mut Request) -> IronResult<Option<Login>> {
+ let login = r.session().get::<Login>()?;
+ // Session storage doesn't have a way to delete its cookie,
+ // so we set the username to empty on logout.
+ if let &Some(Login { ref user }) = &login {
+ if user.is_empty() {
+ return Ok(None)
+ }
+ }
+ Ok(login)
}
fn login(r: &mut Request) -> IronResult<Response> {
+ let renderer = make_renderer(r)?;
Ok(Response::with((status::Ok,
Header(ContentType::html()),
- render::login_page())))
+ renderer.login_page())))
}
fn login_submit(r: &mut Request) -> IronResult<Response> {
- Ok(Response::with((status::Ok,
- Header(ContentType::plaintext()),
- "login")))
- // TODO: Need this to get params:
- // https://github.com/iron/params
+ let login = {
+ let map = r.get_ref::<Params>().unwrap();
+ let user = match map.get("username") {
+ Some(&Value::String(ref v)) => v,
+ _ => panic!("no username in params: {:?}", map)
+ };
+ let password = match map.get("password") {
+ Some(&Value::String(ref v)) => v,
+ _ => panic!("no password in params: {:?}", map)
+ };
+ Login { user: user.clone() }
+ };
+
+ info!("User logged in: {:?}", login);
+ r.session().set(login)?;
+ let url = Url::parse("http://localhost:8080/").unwrap();
+ Ok(Response::with((status::Found,
+ Redirect(url))))
+}
+
+fn logout(r: &mut Request) -> IronResult<Response> {
+ r.session().set::<Login>(Default::default());
+ let url = Url::parse("http://localhost:8080/").unwrap();
+ Ok(Response::with((status::Found,
+ Redirect(url))))
+}
+
+fn make_renderer(r: &mut Request) -> IronResult<render::Renderer> {
+ let user = get_logged_in_user(r)?.map(|u| u.user);
+ Ok(render::Renderer {
+ user: user
+ })
}
pub fn serve(port: u16) -> HttpResult<Listening> {
+ // TODO: Use a real secret.
let secret = b"secret2".to_vec();
let router = router!(
root: get "/" => overview,
login: get "/login" => login,
login_submit: post "/login" => login_submit,
+ logout: get "/logout" => logout,
details: get "/status/:unit" => unit_status,
journal: get "/journal/:unit" => journal,
css: get "/static/main.css" => Static::new(""),
);
let mut chain = Chain::new(router);
+ let context = Context {
+ base_url: String::from("http://localhost:8080/"),
+ };
chain.link_around(SessionStorage::new(SignedCookieBackend::new(secret)));
+ chain.link(Read::<Context>::both(context));
let bind_address = format!("{}:{}", "::", port);
Iron::new(chain).http(bind_address.as_str())
}