Files
zero2prod/src/routes/admin.rs
Alphonse Paix 3e81c27ab3
Some checks failed
Rust / Test (push) Has been cancelled
Rust / Rustfmt (push) Has been cancelled
Rust / Clippy (push) Has been cancelled
Rust / Code coverage (push) Has been cancelled
Administrator privileges to get and delete subscribers
2025-09-30 18:28:04 +02:00

98 lines
2.6 KiB
Rust

mod change_password;
mod dashboard;
mod logout;
mod newsletters;
mod posts;
mod subscribers;
use crate::{
authentication::{AuthenticatedUser, Role},
routes::{AppError, error_chain_fmt},
session_state::TypedSession,
templates::{HtmlTemplate, MessageTemplate},
};
use anyhow::Context;
use axum::{
extract::Request,
middleware::Next,
response::{IntoResponse, Response},
};
pub use change_password::*;
pub use dashboard::*;
pub use logout::*;
pub use newsletters::*;
pub use posts::*;
pub use subscribers::*;
#[derive(thiserror::Error)]
pub enum AdminError {
#[error("Something went wrong while performing an admin action.")]
UnexpectedError(#[from] anyhow::Error),
#[error("Trying to access admin dashboard without authentication.")]
NotAuthenticated,
#[error("Updating password failed.")]
ChangePassword(anyhow::Error),
#[error("Could not publish newsletter.")]
Publish(#[source] anyhow::Error),
#[error("The idempotency key was invalid.")]
Idempotency(String),
}
impl std::fmt::Debug for AdminError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
error_chain_fmt(self, f)
}
}
pub async fn require_auth(
session: TypedSession,
mut request: Request,
next: Next,
) -> Result<Response, AppError> {
let user_id = session
.get_user_id()
.await
.map_err(|e| AdminError::UnexpectedError(e.into()))?
.ok_or(AdminError::NotAuthenticated)?;
let username = session
.get_username()
.await
.map_err(|e| AdminError::UnexpectedError(e.into()))?
.ok_or(AdminError::UnexpectedError(anyhow::anyhow!(
"Could not find username in session."
)))?;
let role = session
.get_role()
.await
.context("Error retrieving user role in session.")?
.ok_or(anyhow::anyhow!("Could not find user role in session."))?;
request.extensions_mut().insert(AuthenticatedUser {
user_id,
username,
role,
});
Ok(next.run(request).await)
}
pub async fn require_admin(
session: TypedSession,
request: Request,
next: Next,
) -> Result<Response, AppError> {
if let Role::Admin = session
.get_role()
.await
.context("Error retrieving user role in session.")?
.ok_or(anyhow::anyhow!("Could not find user role in session."))?
{
Ok(next.run(request).await)
} else {
Ok(HtmlTemplate(MessageTemplate::error(
"This action requires administrator privileges.".into(),
))
.into_response())
}
}