71 lines
2.0 KiB
Rust
71 lines
2.0 KiB
Rust
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<MnemoState>,
|
|
Path(id): Path<Uuid>,
|
|
headers: HeaderMap,
|
|
) -> Result<Response, CompositeError> {
|
|
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<MnemoState>,
|
|
Path(id): Path<Uuid>,
|
|
headers: HeaderMap,
|
|
) -> Result<Response, CompositeError> {
|
|
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))?,
|
|
},
|
|
}
|
|
}
|