session revoking, perm, DatabaseError (partially)
This commit is contained in:
@@ -5,6 +5,7 @@ use axum::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
database::DatabaseError,
|
||||
tags::TagError,
|
||||
users::{UserError, auth::AuthError, sessions::SessionError},
|
||||
};
|
||||
@@ -23,6 +24,7 @@ pub fn api_router() -> Router {
|
||||
.route("/api/users/{id}", get(users::get_by_id))
|
||||
.route("/api/users/@{handle}", get(users::get_by_handle))
|
||||
.route("/api/sessions/{id}", get(sessions::get_by_id))
|
||||
.route("/api/sessions/{id}/revoke", post(sessions::revoke_by_id))
|
||||
.route("/api/tags/{id}", get(tags::get_by_id))
|
||||
.route("/api/tags/#{name}", get(tags::get_by_name))
|
||||
}
|
||||
@@ -45,4 +47,4 @@ macro_rules! composite_from {
|
||||
)+
|
||||
};
|
||||
}
|
||||
composite_from!(AuthError, UserError, SessionError, TagError);
|
||||
composite_from!(AuthError, UserError, SessionError, TagError, DatabaseError);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use axum::{
|
||||
Json,
|
||||
extract::Path,
|
||||
http::HeaderMap,
|
||||
http::{HeaderMap, StatusCode},
|
||||
response::{IntoResponse, Response},
|
||||
};
|
||||
use uuid::Uuid;
|
||||
@@ -31,3 +31,29 @@ pub async fn get_by_id(
|
||||
false => Err(SessionError::NoSessionWithId(id))?,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn revoke_by_id(
|
||||
Path(id): Path<Uuid>,
|
||||
headers: HeaderMap,
|
||||
) -> Result<Response, CompositeError> {
|
||||
let u = User::authenticate(&headers)?.required()?;
|
||||
let mut s = Session::get_by_id(id)?;
|
||||
|
||||
match s.user_id == u.id
|
||||
|| u.has_permission(Permission::RevokeOthersSessions)
|
||||
.is_ok_and(|v| v)
|
||||
{
|
||||
true => {
|
||||
s.revoke(Some(&u))?;
|
||||
Ok(Json(s).into_response())
|
||||
}
|
||||
false => match u.has_permission(Permission::ListOthersSessions)? {
|
||||
true => Ok((
|
||||
StatusCode::FORBIDDEN,
|
||||
"You don't have permission to revoke this session.",
|
||||
)
|
||||
.into_response()),
|
||||
false => Err(SessionError::NoSessionWithId(id))?,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use std::{env, error::Error, sync::LazyLock};
|
||||
|
||||
use axum::{http::StatusCode, response::IntoResponse};
|
||||
use rusqlite::{Connection, OptionalExtension};
|
||||
|
||||
macro_rules! migration {
|
||||
@@ -21,6 +22,16 @@ CREATE TABLE IF NOT EXISTS migrations (
|
||||
);
|
||||
"#;
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[error("{0}")]
|
||||
pub struct DatabaseError(#[from] rusqlite::Error);
|
||||
impl IntoResponse for DatabaseError {
|
||||
fn into_response(self) -> axum::response::Response {
|
||||
println!("[DB ERROR] {}", self.to_string());
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, "Internal server error.").into_response()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn conn() -> Result<Connection, rusqlite::Error> {
|
||||
let conn = Connection::open(&*DB_URL)?;
|
||||
for pragma in CONNECTION_PRAGMAS {
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
use crate::users::User;
|
||||
use crate::{database::DatabaseError, users::User};
|
||||
|
||||
/// Infradmin and systemuser have all permissions.
|
||||
pub enum Permission {
|
||||
// All Users have the right to observe their own sessions
|
||||
ListOthersSessions,
|
||||
// All Users have the right to revoke their own sessions
|
||||
RevokeOthersSessions,
|
||||
}
|
||||
|
||||
impl User {
|
||||
pub fn has_permission(&self, permission: Permission) -> Result<bool, rusqlite::Error> {
|
||||
pub fn has_permission(&self, permission: Permission) -> Result<bool, DatabaseError> {
|
||||
if self.is_infradmin() || self.is_systemuser() {
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user