Can sign out
This commit is contained in:
		| @@ -1,6 +1,7 @@ | ||||
| use crate::constants::StaticConstraints; | ||||
| use crate::controllers::HttpResult; | ||||
| use crate::models::{User, UserID}; | ||||
| use crate::services::login_token_service::LoginTokenValue; | ||||
| use crate::services::rate_limiter_service::RatedAction; | ||||
| use crate::services::{login_token_service, openid_service, rate_limiter_service, users_service}; | ||||
| use actix_remote_ip::RemoteIP; | ||||
| @@ -304,3 +305,10 @@ pub async fn finish_openid_login( | ||||
|  | ||||
|     finish_login(&user).await | ||||
| } | ||||
|  | ||||
| /// Logout user | ||||
| pub async fn logout(token: LoginTokenValue) -> HttpResult { | ||||
|     login_token_service::delete_token(&token).await?; | ||||
|  | ||||
|     Ok(HttpResponse::NoContent().finish()) | ||||
| } | ||||
|   | ||||
| @@ -51,6 +51,7 @@ async fn main() -> std::io::Result<()> { | ||||
|                 "/auth/finish_openid_login", | ||||
|                 web::post().to(auth_controller::finish_openid_login), | ||||
|             ) | ||||
|             .route("/auth/logout", web::get().to(auth_controller::logout)) | ||||
|             // User controller | ||||
|             .route("/user/info", web::get().to(user_controller::auth_info)) | ||||
|     }) | ||||
|   | ||||
| @@ -6,12 +6,19 @@ use crate::utils::string_utils; | ||||
| use crate::utils::time_utils::time; | ||||
| use actix_web::dev::Payload; | ||||
| use actix_web::{FromRequest, HttpRequest}; | ||||
| use std::future::{ready, Ready}; | ||||
| use std::time::Duration; | ||||
|  | ||||
| #[derive(Debug, Clone)] | ||||
| pub struct LoginTokenValue(String); | ||||
|  | ||||
| #[derive(serde::Serialize, serde::Deserialize, Debug, Clone)] | ||||
| pub struct LoginToken { | ||||
|     #[serde(rename = "e")] | ||||
|     expire: u64, | ||||
|     #[serde(rename = "h")] | ||||
|     hb: u64, | ||||
|     #[serde(rename = "u")] | ||||
|     pub user_id: UserID, | ||||
| } | ||||
|  | ||||
| @@ -64,6 +71,12 @@ pub async fn gen_new_token(user: &User) -> anyhow::Result<String> { | ||||
|     Ok(key) | ||||
| } | ||||
|  | ||||
| /// Delete a login token | ||||
| pub async fn delete_token(token: &LoginTokenValue) -> anyhow::Result<()> { | ||||
|     redis_connection::remove_value(&redis_key(&token.0)).await?; | ||||
|     Ok(()) | ||||
| } | ||||
|  | ||||
| /// Get a user information from its token | ||||
| async fn get_token(key: &str) -> anyhow::Result<Option<LoginToken>> { | ||||
|     let token = match redis_connection::get_value::<LoginToken>(&redis_key(key)).await? { | ||||
| @@ -87,6 +100,20 @@ async fn get_token(key: &str) -> anyhow::Result<Option<LoginToken>> { | ||||
|     Ok(Some(token)) | ||||
| } | ||||
|  | ||||
| impl FromRequest for LoginTokenValue { | ||||
|     type Error = actix_web::Error; | ||||
|     type Future = Ready<Result<Self, Self::Error>>; | ||||
|  | ||||
|     fn from_request(req: &HttpRequest, _payload: &mut Payload) -> Self::Future { | ||||
|         ready(match req.headers().get("X-Auth-Token") { | ||||
|             Some(v) => Ok(LoginTokenValue(v.to_str().unwrap_or("").to_string())), | ||||
|             None => Err(actix_web::error::ErrorBadRequest( | ||||
|                 "Missing auth token header!", | ||||
|             )), | ||||
|         }) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl FromRequest for LoginToken { | ||||
|     type Error = actix_web::Error; | ||||
|     type Future = futures_util::future::LocalBoxFuture<'static, Result<Self, Self::Error>>; | ||||
| @@ -94,16 +121,9 @@ impl FromRequest for LoginToken { | ||||
|     fn from_request(req: &HttpRequest, _payload: &mut Payload) -> Self::Future { | ||||
|         let req = req.clone(); | ||||
|         Box::pin(async move { | ||||
|             let token = match req.headers().get("X-Auth-Token") { | ||||
|                 Some(v) => v.to_str().unwrap_or(""), | ||||
|                 None => { | ||||
|                     return Err(actix_web::error::ErrorBadRequest( | ||||
|                         "Missing auth token header!", | ||||
|                     )); | ||||
|                 } | ||||
|             }; | ||||
|             let token = LoginTokenValue::extract(&req).await?; | ||||
|  | ||||
|             let token = match get_token(token).await { | ||||
|             let token = match get_token(&token.0).await { | ||||
|                 Err(e) => { | ||||
|                     log::error!("Failed to load auth token! {}", e); | ||||
|                     return Err(actix_web::error::ErrorInternalServerError( | ||||
|   | ||||
		Reference in New Issue
	
	Block a user