summaryrefslogtreecommitdiff
path: root/src/server.rs
diff options
context:
space:
mode:
authorKjetil Orbekk <kjetil.orbekk@gmail.com>2017-06-17 22:23:39 -0400
committerKjetil Orbekk <kjetil.orbekk@gmail.com>2017-06-17 22:23:59 -0400
commit1e5f237c20310cbf6ace17b6a7b05298429aca46 (patch)
tree61c67dc5846cec4a79e960eb4e28afa1699272de /src/server.rs
parent41025a52fe3d2e4988296bfdc1ef549b60b8b667 (diff)
feature: Working login with authentication.
Diffstat (limited to 'src/server.rs')
-rw-r--r--src/server.rs53
1 files changed, 33 insertions, 20 deletions
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<Option<Login>> {
fn login(r: &mut Request) -> IronResult<Response> {
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<Response> {
- let login = {
+fn authenticate(r: &mut Request) -> IronResult<Response> {
+ let (user, password) = {
let map = r.get_ref::<Params>().unwrap();
let user = match map.get("username") {
Some(&Value::String(ref v)) => v,
@@ -136,14 +141,25 @@ fn login_submit(r: &mut Request) -> IronResult<Response> {
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::<Write<Context>>().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<Response> {
@@ -160,24 +176,21 @@ fn make_renderer(r: &mut Request) -> IronResult<render::Renderer> {
})
}
-pub fn serve(port: u16) -> HttpResult<Listening> {
+pub fn serve(context: Context, 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,
+ 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::<Context>::both(context));
+ chain.link(Write::<Context>::both(context));
let bind_address = format!("{}:{}", "::", port);
Iron::new(chain).http(bind_address.as_str())
}