From 108470c5d1abac3fa777dbcfb81b3ed7a434590b Mon Sep 17 00:00:00 2001 From: Artus Date: Thu, 5 Dec 2019 16:17:33 +0100 Subject: [PATCH] adds SessionKind and mocks impl of key checks --- Cargo.toml | 1 + src/server.rs | 68 ++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 60 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5465714..5a120a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ env_logger = "*" futures = "0.1" diesel = "*" serde = "*" +serde_json = "*" actix-cors = "0.1.0" [workspace] diff --git a/src/server.rs b/src/server.rs index 5a75d33..8097f7a 100644 --- a/src/server.rs +++ b/src/server.rs @@ -12,6 +12,8 @@ use futures::{ Future, }; use std::env; +use serde_json; + use crate::api; use lootalot_db as db; @@ -215,14 +217,40 @@ fn configure_api(config: &mut web::ServiceConfig) { #[derive(Deserialize)] struct AuthRequest { - key: i32, + key: String, +} + +#[derive(Debug,Copy,Clone, Serialize, Deserialize)] +enum SessionKind { + Player(i32), + Admin +} + +use std::collections::HashMap; + +fn check_key(key: &str, db: HashMap<&str, SessionKind>) -> Option { + db.get(&key).map(Clone::clone) } fn login(id: Identity, key: web::Query) -> HttpResponse { - id.remember(key.key.to_string()); + if let Some(session_kind) = + check_key( + &key.key.to_string(), + [("0", SessionKind::Player(0)), + ("1", SessionKind::Player(1)), + ("2", SessionKind::Player(2)), + ("admin", SessionKind::Admin), + ].iter().cloned().collect::>() + ) + { + id.remember(serde_json::to_string(&session_kind).expect("Serialize SessionKind error")); HttpResponse::build(StatusCode::TEMPORARY_REDIRECT) .header(header::LOCATION, "/") .finish() + } else { + HttpResponse::Forbidden().finish() + } + } fn logout(id: Identity) -> HttpResponse { @@ -235,12 +263,34 @@ fn logout(id: Identity) -> HttpResponse { /// This endpoint shall be called by client, /// at initialization, to retrieve the current /// logging session info. -fn enter_session(id: Identity) -> HttpResponse { - if let Some(user_id) = id.identity() { - HttpResponse::Ok().json(user_id) - } else { - HttpResponse::Forbidden().finish() +/// +/// # Returns +/// +/// The player data if a player is logged in +/// The admin data if the admin is logged in +/// A Forbidden response otherwise +fn enter_session(id: Identity, pool: AppPool) -> impl Future { + let conn = pool.get().unwrap(); + let logged: SessionKind = id + .identity() + .map(|s| serde_json::from_str(&s).expect("Deserialize SessionKind error")) + // This will fail, fastest way to handle + // unlogged case with web::block below + .unwrap_or(SessionKind::Player(-1)); + + web::block(move || api::execute(&conn, match logged { + SessionKind::Player(id) => api::ApiActions::FetchPlayer(id), + SessionKind::Admin => api::ApiActions::FetchPlayers } + )).then( + |res| match res { + Ok(r) => HttpResponse::Ok().json(r.value), + Err(e) => { + dbg!(&e); + HttpResponse::Forbidden().finish() + } + }, + ) } pub fn serve() -> std::io::Result<()> { @@ -248,7 +298,7 @@ pub fn serve() -> std::io::Result<()> { let pool = db::create_pool(); dbg!(&www_root); - let key = [0; 32]; + let key = [0; 32]; // TODO: Use a real key let domain = "http://localhost:8088"; HttpServer::new(move || { @@ -268,7 +318,7 @@ pub fn serve() -> std::io::Result<()> { )) //.wrap(middleware::Logger::default()) .wrap(middleware::Logger::new("%r -> %s (%{User-Agent}i)")) - .route("/session", web::get().to(enter_session)) + .route("/session", web::get().to_async(enter_session)) .route("/login", web::get().to(login)) .route("/logout", web::get().to(logout)) .service(fs::Files::new("/", www_root.clone()).index_file("index.html"))