adds SessionKind and mocks impl of key checks

This commit is contained in:
2019-12-05 16:17:33 +01:00
parent d1a85ed1d0
commit 108470c5d1
2 changed files with 60 additions and 9 deletions

View File

@@ -15,6 +15,7 @@ env_logger = "*"
futures = "0.1" futures = "0.1"
diesel = "*" diesel = "*"
serde = "*" serde = "*"
serde_json = "*"
actix-cors = "0.1.0" actix-cors = "0.1.0"
[workspace] [workspace]

View File

@@ -12,6 +12,8 @@ use futures::{
Future, Future,
}; };
use std::env; use std::env;
use serde_json;
use crate::api; use crate::api;
use lootalot_db as db; use lootalot_db as db;
@@ -215,14 +217,40 @@ fn configure_api(config: &mut web::ServiceConfig) {
#[derive(Deserialize)] #[derive(Deserialize)]
struct AuthRequest { 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<SessionKind> {
db.get(&key).map(Clone::clone)
} }
fn login(id: Identity, key: web::Query<AuthRequest>) -> HttpResponse { fn login(id: Identity, key: web::Query<AuthRequest>) -> 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::<HashMap<&str, SessionKind>>()
)
{
id.remember(serde_json::to_string(&session_kind).expect("Serialize SessionKind error"));
HttpResponse::build(StatusCode::TEMPORARY_REDIRECT) HttpResponse::build(StatusCode::TEMPORARY_REDIRECT)
.header(header::LOCATION, "/") .header(header::LOCATION, "/")
.finish() .finish()
} else {
HttpResponse::Forbidden().finish()
}
} }
fn logout(id: Identity) -> HttpResponse { fn logout(id: Identity) -> HttpResponse {
@@ -235,12 +263,34 @@ fn logout(id: Identity) -> HttpResponse {
/// This endpoint shall be called by client, /// This endpoint shall be called by client,
/// at initialization, to retrieve the current /// at initialization, to retrieve the current
/// logging session info. /// logging session info.
fn enter_session(id: Identity) -> HttpResponse { ///
if let Some(user_id) = id.identity() { /// # Returns
HttpResponse::Ok().json(user_id) ///
} else { /// The player data if a player is logged in
HttpResponse::Forbidden().finish() /// The admin data if the admin is logged in
/// A Forbidden response otherwise
fn enter_session(id: Identity, pool: AppPool) -> impl Future<Item = HttpResponse, Error = Error> {
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<()> { pub fn serve() -> std::io::Result<()> {
@@ -248,7 +298,7 @@ pub fn serve() -> std::io::Result<()> {
let pool = db::create_pool(); let pool = db::create_pool();
dbg!(&www_root); dbg!(&www_root);
let key = [0; 32]; let key = [0; 32]; // TODO: Use a real key
let domain = "http://localhost:8088"; let domain = "http://localhost:8088";
HttpServer::new(move || { HttpServer::new(move || {
@@ -268,7 +318,7 @@ pub fn serve() -> std::io::Result<()> {
)) ))
//.wrap(middleware::Logger::default()) //.wrap(middleware::Logger::default())
.wrap(middleware::Logger::new("%r -> %s (%{User-Agent}i)")) .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("/login", web::get().to(login))
.route("/logout", web::get().to(logout)) .route("/logout", web::get().to(logout))
.service(fs::Files::new("/", www_root.clone()).index_file("index.html")) .service(fs::Files::new("/", www_root.clone()).index_file("index.html"))