diff options
Diffstat (limited to 'src/server.rs')
-rw-r--r-- | src/server.rs | 58 |
1 files changed, 50 insertions, 8 deletions
diff --git a/src/server.rs b/src/server.rs index 4816c33..54beb34 100644 --- a/src/server.rs +++ b/src/server.rs @@ -8,11 +8,14 @@ use rusqlite::Connection; use std::collections::BTreeMap; use persistent::Write; use handlebars_iron::handlebars::to_json; -use serde_json::Map; +use serde_json; use params; use error::LinoError; use chrono; use logger::Logger; +use iron_sessionstorage::{self, SessionStorage, SessionRequestExt}; +use iron_sessionstorage::backends::SignedCookieBackend; +use rand::{OsRng, Rng}; #[derive(Debug)] pub struct State { @@ -22,6 +25,41 @@ impl iron::typemap::Key for State { type Value = State; } +#[derive(Debug, Clone, Serialize)] +struct UserId(u64); +impl iron_sessionstorage::Value for UserId { + fn get_key() -> &'static str { + "user_id" + } + fn into_raw(self) -> String { + format!("{}", self.0) + } + fn from_raw(value: String) -> Option<Self> { + value.parse().ok().map(|i| UserId(i)) + } +} + +fn user_id(r: &mut Request) -> IronResult<UserId> { + if let Some(user_id) = r.session().get::<UserId>()? { + return Ok(user_id); + } + + let mut rng = OsRng::new().map_err(|e| { + // This is ugly, but I don't know how to annotate the expression. + let e: LinoError = From::from(e); + e + })?; + let user_id = UserId(rng.next_u64()); + r.session().set(user_id.clone())?; + Ok(user_id) +} + +fn make_result(r: &mut Request) -> IronResult<serde_json::Map<String, serde_json::value::Value>> { + let mut result = serde_json::Map::new(); + result.insert("user_id".to_string(), to_json(&user_id(r)?)); + Ok(result) +} + fn get_param(r: &mut Request, param: &str) -> IronResult<String> { let map = itry!(r.get_ref::<params::Params>()); match map.get(param) { @@ -67,7 +105,7 @@ fn make_renderer() -> HandlebarsEngine { } fn quotes(r: &mut Request) -> IronResult<Response> { - let mut result = Map::new(); + let mut result = make_result(r)?; let quote_id = get_param(r, "id").ok().and_then( |id| id.parse::<i64>().ok(), ); @@ -90,9 +128,9 @@ fn quotes(r: &mut Request) -> IronResult<Response> { ))) } -fn add_get(_r: &mut Request) -> IronResult<Response> { +fn add_get(r: &mut Request) -> IronResult<Response> { let date = chrono::offset::Local::now().format("%Y-%m-%d").to_string(); - let mut result = Map::new(); + let mut result = make_result(r)?; result.insert("date".to_string(), to_json(&date)); Ok(Response::with(( status::Ok, @@ -102,6 +140,7 @@ fn add_get(_r: &mut Request) -> IronResult<Response> { } fn add_post(r: &mut Request) -> IronResult<Response> { + let result = make_result(r)?; let nick = get_param(r, "nick")?; let date = get_param(r, "date")?; let quote = get_param(r, "quote")?; @@ -127,12 +166,12 @@ fn add_post(r: &mut Request) -> IronResult<Response> { Ok(Response::with(( status::Ok, Header(ContentType::html()), - Template::new("add_post", Map::new()), + Template::new("add_post", result) ))) } fn approve(r: &mut Request) -> IronResult<Response> { - let mut result = Map::new(); + let mut result = make_result(r)?; let quote_id = get_param(r, "id").ok().and_then( |id| id.parse::<i64>().ok(), ); @@ -185,7 +224,7 @@ pub fn vote(r: &mut Request) -> IronResult<Response> { data::get_quote(&state.connection, quote_id)? }; - let mut result = Map::new(); + let mut result = make_result(r)?; result.insert("quote".to_string(), to_json("e)); Ok(Response::with(( @@ -206,13 +245,16 @@ pub fn serve(state: State, port: u16) { approve: get "/approve.jsp" => approve, vote: get "/vote" => vote, ); - let (logger_before, logger_after) = Logger::new(None); let mut chain = Chain::new(router); + let (logger_before, logger_after) = Logger::new(None); chain.link_before(logger_before); + let key = data::get_key(&state.connection, "session").expect("session key"); + chain.link_around(SessionStorage::new(SignedCookieBackend::new(key))); chain.link_after(make_renderer()); chain.link(Write::<State>::both(state)); chain.link_after(logger_after); + let bind_address = format!("{}:{}", "::", port); let _server = Iron::new(chain).http(bind_address.as_str()); info!("Serving on {}", bind_address); |