use axum::{ Json, extract::{Path, State}, http::{HeaderMap, StatusCode}, response::{IntoResponse, Response}, }; use uuid::Uuid; use crate::{ MnemoState, error::CompositeError, logs::{LogAction, LogEntry}, users::{ User, auth::{UserAuthRequired, UserAuthenticate}, permissions::Permission, sessions::{Session, SessionError}, }, }; const CANT_REVOKE: &str = "You don't have permission to revoke this user's sessions."; pub async fn get_by_id( State(state): State, Path(id): Path, headers: HeaderMap, ) -> Result { let mut conn = state.pool.acquire().await?; let u = User::authenticate(&mut conn, &headers).await?.required()?; let s = Session::get_by_id(&mut conn, id).await?; match s.user_id == u.id || u.has_permission(&mut conn, Permission::ListOthersSessions) .await .is_ok_and(|v| v) { true => Ok(Json(s).into_response()), false => Err(SessionError::NoSessionWithId(id))?, } } pub async fn revoke_by_id( State(state): State, Path(id): Path, headers: HeaderMap, ) -> Result { let mut tx = state.pool.begin().await?; let u = User::authenticate(&mut tx, &headers).await?.required()?; let mut s = Session::get_by_id(&mut tx, id).await?; match s.user_id == u.id || u.has_permission(&mut tx, Permission::RevokeOthersSessions) .await .is_ok_and(|v| v) { true => { s.revoke(&mut tx, Some(&u)).await?; LogEntry::new(&mut tx, u, LogAction::ManuallyRevokeSession { id }).await?; tx.commit().await?; Ok(Json(s).into_response()) } false => match u .has_permission(&mut tx, Permission::ListOthersSessions) .await? { true => Ok((StatusCode::FORBIDDEN, CANT_REVOKE).into_response()), false => Err(SessionError::NoSessionWithId(id))?, }, } }