diff options
author | Kjetil Orbekk <kjetil.orbekk@gmail.com> | 2017-06-17 20:08:31 -0400 |
---|---|---|
committer | Kjetil Orbekk <kjetil.orbekk@gmail.com> | 2017-06-17 20:08:31 -0400 |
commit | 41025a52fe3d2e4988296bfdc1ef549b60b8b667 (patch) | |
tree | 8c0110b59bfc98a290a8806cb6a7759765b77129 /src/server.rs | |
parent | 651bfc36a8aa5a83c9143e62859623ef35f31c7f (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.rs | 106 |
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()) } |