mirror of
https://github.com/danbulant/Portfolio
synced 2026-07-05 19:11:06 +00:00
feat: logout only current session, admin logout endpoint
This commit is contained in:
parent
35f591fb67
commit
492fc5618f
5 changed files with 41 additions and 9 deletions
|
|
@ -68,6 +68,7 @@ pub fn rocket() -> Rocket<Build>{
|
||||||
"/admin/",
|
"/admin/",
|
||||||
routes![
|
routes![
|
||||||
routes::admin::login,
|
routes::admin::login,
|
||||||
|
routes::admin::logout,
|
||||||
routes::admin::whoami,
|
routes::admin::whoami,
|
||||||
routes::admin::hello,
|
routes::admin::hello,
|
||||||
routes::admin::create_candidate,
|
routes::admin::create_candidate,
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use std::net::{SocketAddr, IpAddr, Ipv4Addr};
|
||||||
|
|
||||||
use portfolio_core::{
|
use portfolio_core::{
|
||||||
crypto::random_8_char_string,
|
crypto::random_8_char_string,
|
||||||
services::{admin_service::AdminService, candidate_service::CandidateService, application_service::ApplicationService, portfolio_service::PortfolioService}, responses::CandidateResponse, candidate_details::ApplicationDetails,
|
services::{admin_service::AdminService, candidate_service::CandidateService, application_service::ApplicationService, portfolio_service::PortfolioService}, responses::CandidateResponse, candidate_details::ApplicationDetails, sea_orm::prelude::Uuid,
|
||||||
};
|
};
|
||||||
use requests::{AdminLoginRequest, RegisterRequest};
|
use requests::{AdminLoginRequest, RegisterRequest};
|
||||||
use rocket::http::{Cookie, Status, CookieJar};
|
use rocket::http::{Cookie, Status, CookieJar};
|
||||||
|
|
@ -51,6 +51,25 @@ pub async fn login(
|
||||||
return Ok(response);
|
return Ok(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[post("/logout")]
|
||||||
|
pub async fn logout(conn: Connection<'_, Db>, _session: AdminAuth, cookies: &CookieJar<'_>,) -> Result<(), Custom<String>> {
|
||||||
|
let db = conn.into_inner();
|
||||||
|
|
||||||
|
let cookie = cookies.get_private("id") // unwrap would be safe here because of the auth guard
|
||||||
|
.ok_or(Custom(Status::Unauthorized, "No session cookie".to_string()))?;
|
||||||
|
let session_id = Uuid::try_parse(cookie.value()) // unwrap would be safe here because of the auth guard
|
||||||
|
.map_err(|e| Custom(Status::BadRequest, e.to_string()))?;
|
||||||
|
|
||||||
|
let res = AdminService::logout(db, session_id)
|
||||||
|
.await
|
||||||
|
.map_err(|e| Custom(Status::from_code(e.code()).unwrap_or(Status::InternalServerError), e.to_string()))?;
|
||||||
|
|
||||||
|
cookies.remove_private(Cookie::named("id"));
|
||||||
|
cookies.remove_private(Cookie::named("key"));
|
||||||
|
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[get("/whoami")]
|
#[get("/whoami")]
|
||||||
pub async fn whoami(session: AdminAuth) -> Result<String, Custom<String>> {
|
pub async fn whoami(session: AdminAuth) -> Result<String, Custom<String>> {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||||
|
|
||||||
use portfolio_core::candidate_details::ApplicationDetails;
|
use portfolio_core::candidate_details::ApplicationDetails;
|
||||||
|
use portfolio_core::sea_orm::prelude::Uuid;
|
||||||
use portfolio_core::services::application_service::ApplicationService;
|
use portfolio_core::services::application_service::ApplicationService;
|
||||||
use portfolio_core::services::candidate_service::CandidateService;
|
use portfolio_core::services::candidate_service::CandidateService;
|
||||||
use portfolio_core::services::portfolio_service::{PortfolioService, SubmissionProgress};
|
use portfolio_core::services::portfolio_service::{PortfolioService, SubmissionProgress};
|
||||||
|
|
@ -52,16 +53,22 @@ pub async fn login(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/logout")]
|
#[post("/logout")]
|
||||||
pub async fn logout(conn: Connection<'_, Db>, session: CandidateAuth, cookies: &CookieJar<'_>,) -> Result<(), Custom<String>> {
|
pub async fn logout(conn: Connection<'_, Db>, _session: CandidateAuth, cookies: &CookieJar<'_>,) -> Result<(), Custom<String>> {
|
||||||
let db = conn.into_inner();
|
let db = conn.into_inner();
|
||||||
let candidate: entity::candidate::Model = session.into();
|
|
||||||
|
let cookie = cookies.get_private("id") // unwrap would be safe here because of the auth guard
|
||||||
|
.ok_or(Custom(Status::Unauthorized, "No session cookie".to_string()))?;
|
||||||
|
let session_id = Uuid::try_parse(cookie.value()) // unwrap would be safe here because of the auth guard
|
||||||
|
.map_err(|e| Custom(Status::BadRequest, e.to_string()))?;
|
||||||
|
|
||||||
|
let res = CandidateService::logout(db, session_id)
|
||||||
|
.await
|
||||||
|
.map_err(|e| Custom(Status::from_code(e.code()).unwrap_or(Status::InternalServerError), e.to_string()))?;
|
||||||
|
|
||||||
cookies.remove_private(Cookie::named("id"));
|
cookies.remove_private(Cookie::named("id"));
|
||||||
cookies.remove_private(Cookie::named("key"));
|
cookies.remove_private(Cookie::named("key"));
|
||||||
|
|
||||||
CandidateService::logout(db, candidate.application)
|
Ok(res)
|
||||||
.await
|
|
||||||
.map_err(|e| Custom(Status::from_code(e.code()).unwrap_or(Status::InternalServerError), e.to_string()))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/whoami")]
|
#[get("/whoami")]
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use entity::admin;
|
use entity::admin;
|
||||||
use sea_orm::{prelude::Uuid, DbConn};
|
use sea_orm::{prelude::Uuid, DbConn};
|
||||||
|
|
||||||
use crate::{crypto, error::ServiceError, Query};
|
use crate::{crypto, error::ServiceError, Query, Mutation};
|
||||||
|
|
||||||
use super::session_service::{AdminUser, SessionService};
|
use super::session_service::{AdminUser, SessionService};
|
||||||
|
|
||||||
|
|
@ -38,6 +38,11 @@ impl AdminService {
|
||||||
Ok((session_id, private_key))
|
Ok((session_id, private_key))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn logout(db: &DbConn, session_id: Uuid) -> Result<(), ServiceError> {
|
||||||
|
Mutation::delete_session(db, session_id).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn auth(db: &DbConn, session_uuid: Uuid) -> Result<admin::Model, ServiceError> {
|
pub async fn auth(db: &DbConn, session_uuid: Uuid) -> Result<admin::Model, ServiceError> {
|
||||||
match SessionService::auth_user_session(db, session_uuid).await? {
|
match SessionService::auth_user_session(db, session_uuid).await? {
|
||||||
AdminUser::Admin(admin) => Ok(admin),
|
AdminUser::Admin(admin) => Ok(admin),
|
||||||
|
|
|
||||||
|
|
@ -131,8 +131,8 @@ impl CandidateService {
|
||||||
Ok(new_password_plain)
|
Ok(new_password_plain)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn logout(db: &DbConn, id: i32) -> Result<(), ServiceError> {
|
pub async fn logout(db: &DbConn, session_id: Uuid) -> Result<(), ServiceError> {
|
||||||
SessionService::revoke_all_sessions(db, Some(id), None).await?;
|
Mutation::delete_session(db, session_id).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue