From 9d84a5ac620b5931748927881c6d414477075705 Mon Sep 17 00:00:00 2001 From: Artus Date: Thu, 14 Nov 2019 12:30:57 +0100 Subject: [PATCH] adds logic for magic link authentication --- Cargo.toml | 1 + src/server.rs | 50 +++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 23835a8..0413c04 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ edition = "2018" [dependencies] actix-web = "1.0.*" actix-files = "*" +actix-identity = "*" lootalot-db = { version = "0.1", path = "./lootalot_db" } dotenv = "*" env_logger = "*" diff --git a/src/server.rs b/src/server.rs index 396b725..1463c34 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1,6 +1,10 @@ use actix_cors::Cors; use actix_files as fs; -use actix_web::{middleware, web, App, Either, Error, HttpResponse, HttpServer}; +use actix_identity::{CookieIdentityPolicy, Identity, IdentityService}; +use actix_web::{ + http::{header, StatusCode}, + middleware, web, App, Either, Error, HttpResponse, HttpServer, +}; use futures::Future; use std::env; @@ -17,7 +21,6 @@ type NewGroupLoot = web::Json; type MaybeForbidden = actix_web::Either>, HttpResponse>; - /// Wraps call to the database query and convert its result as a async HttpResponse fn db_call( pool: AppPool, @@ -136,23 +139,64 @@ fn configure_api(config: &mut web::ServiceConfig) { ); } +#[derive(Deserialize)] +struct AuthRequest { + key: i32, +} + +fn login(id: Identity, key: web::Query) -> HttpResponse { + id.remember(key.key.to_string()); + HttpResponse::build(StatusCode::TEMPORARY_REDIRECT) + .header(header::LOCATION, "/") + .finish() +} + +fn logout(id: Identity) -> HttpResponse { + id.forget(); + HttpResponse::build(StatusCode::TEMPORARY_REDIRECT) + .header(header::LOCATION, "/") + .finish() +} + +/// 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() + } +} + pub fn serve() -> std::io::Result<()> { let www_root: String = env::var("WWW_ROOT").expect("WWW_ROOT must be set"); let pool = db::create_pool(); dbg!(&www_root); + let key = [0; 32]; + let domain = "http://localhost:8088"; + HttpServer::new(move || { App::new() .data(pool.clone()) .configure(configure_api) .wrap( Cors::new() - .allowed_origin("http://localhost:8088") + .allowed_origin(domain) .allowed_methods(vec!["GET", "POST", "PUT", "DELETE", "OPTIONS"]) .max_age(3600), ) + .wrap(IdentityService::new( + CookieIdentityPolicy::new(&key) + .name("logged-in") + .secure(false), + )) //.wrap(middleware::Logger::default()) .wrap(middleware::Logger::new("%r -> %s (%{User-Agent}i)")) + .route("/session", web::get().to(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")) }) .bind("127.0.0.1:8088")?