From 1e5f237c20310cbf6ace17b6a7b05298429aca46 Mon Sep 17 00:00:00 2001 From: Kjetil Orbekk Date: Sat, 17 Jun 2017 22:23:39 -0400 Subject: feature: Working login with authentication. --- src/server.rs | 53 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 20 deletions(-) (limited to 'src/server.rs') diff --git a/src/server.rs b/src/server.rs index 2ab4f75..3a03ea0 100644 --- a/src/server.rs +++ b/src/server.rs @@ -15,11 +15,15 @@ use router::Router; use staticfile::Static; use systemd::journal; use systemd::unit; -use persistent::Read; - -#[derive(Clone, Default, Debug)] -struct Context { - base_url: String +use persistent::Write; +use rusqlite::Connection; +use db; +use auth; + +#[derive(Debug)] +pub struct Context { + pub base_url: String, + pub conn: Connection } impl iron::typemap::Key for Context { type Value = Context; @@ -120,13 +124,14 @@ fn get_logged_in_user(r: &mut Request) -> IronResult> { fn login(r: &mut Request) -> IronResult { let renderer = make_renderer(r)?; + let is_retry = r.method == iron::method::Method::Post; Ok(Response::with((status::Ok, Header(ContentType::html()), - renderer.login_page()))) + renderer.login_page(is_retry)))) } -fn login_submit(r: &mut Request) -> IronResult { - let login = { +fn authenticate(r: &mut Request) -> IronResult { + let (user, password) = { let map = r.get_ref::().unwrap(); let user = match map.get("username") { Some(&Value::String(ref v)) => v, @@ -136,14 +141,25 @@ fn login_submit(r: &mut Request) -> IronResult { Some(&Value::String(ref v)) => v, _ => panic!("no password in params: {:?}", map) }; - Login { user: user.clone() } + (user.to_string(), password.to_string()) }; - info!("User logged in: {:?}", login); - r.session().set(login)?; - let url = Url::parse("http://localhost:8080/").unwrap(); - Ok(Response::with((status::Found, - Redirect(url)))) + let hash = { + let mutex = r.get::>().unwrap(); + let context = mutex.lock().unwrap(); + db::lookup_user(&context.conn, &user).unwrap() + }; + + if let Some(true) = hash.map(|h| auth::validate(&password, &h)) { + let login = Login{ user: user.to_string() }; // TODO Make a validated login type + info!("User logged in: {:?}", login); + r.session().set(login)?; + let url = Url::parse("http://localhost:8080/").unwrap(); + Ok(Response::with((status::Found, + Redirect(url)))) + } else { + login(r) + } } fn logout(r: &mut Request) -> IronResult { @@ -160,24 +176,21 @@ fn make_renderer(r: &mut Request) -> IronResult { }) } -pub fn serve(port: u16) -> HttpResult { +pub fn serve(context: Context, port: u16) -> HttpResult { // 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, + authenticate: post "/login" => authenticate, 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::::both(context)); + chain.link(Write::::both(context)); let bind_address = format!("{}:{}", "::", port); Iron::new(chain).http(bind_address.as_str()) } -- cgit v1.2.3