98 lines
2.6 KiB
Rust
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())
|
|
}
|
|
}
|