re-implement guards using AppError returns instead of macros
This commit is contained in:
parent
7b6a84f011
commit
da38946dbd
3 changed files with 53 additions and 48 deletions
|
@ -7,6 +7,7 @@ use axum::response::{IntoResponse, Response};
|
|||
#[derive(Debug)]
|
||||
pub enum AppError {
|
||||
InternalServerError(Error),
|
||||
ForbiddenError(String),
|
||||
}
|
||||
|
||||
// Tell axum how to convert `AppError` into a response.
|
||||
|
@ -14,9 +15,13 @@ impl IntoResponse for AppError {
|
|||
fn into_response(self) -> Response {
|
||||
match self {
|
||||
Self::InternalServerError(err) => {
|
||||
tracing::error!("Application error: {:#}", err);
|
||||
tracing::error!("Application error: {}", err);
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, "Something went wrong").into_response()
|
||||
}
|
||||
Self::ForbiddenError(client_message) => {
|
||||
tracing::info!("Forbidden: {}", client_message);
|
||||
(StatusCode::FORBIDDEN, client_message).into_response()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,45 +1,45 @@
|
|||
macro_rules! require_team_membership {
|
||||
($current_user:expr, $team_id:expr, $db_conn:expr) => {{
|
||||
let current_user_id = $current_user.id.clone();
|
||||
match $db_conn
|
||||
use deadpool_diesel::postgres::Connection;
|
||||
use diesel::prelude::*;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{
|
||||
app_error::AppError, csrf::validate_csrf_token, team_memberships::TeamMembership, teams::Team,
|
||||
users::User,
|
||||
};
|
||||
|
||||
pub async fn require_team_membership(
|
||||
current_user: &User,
|
||||
team_id: &Uuid,
|
||||
db_conn: &Connection,
|
||||
) -> Result<Team, AppError> {
|
||||
let current_user_id = current_user.id.clone();
|
||||
let team_id = team_id.clone();
|
||||
match db_conn
|
||||
.interact(move |conn| {
|
||||
crate::team_memberships::TeamMembership::all()
|
||||
.filter(crate::team_memberships::TeamMembership::with_user_id(
|
||||
current_user_id,
|
||||
))
|
||||
.filter(crate::team_memberships::TeamMembership::with_team_id(
|
||||
$team_id,
|
||||
))
|
||||
TeamMembership::all()
|
||||
.filter(TeamMembership::with_user_id(current_user_id))
|
||||
.filter(TeamMembership::with_team_id(team_id))
|
||||
.first(conn)
|
||||
.optional()
|
||||
})
|
||||
.await
|
||||
.unwrap()?
|
||||
{
|
||||
Some((team, _)) => team,
|
||||
None => {
|
||||
return Ok((
|
||||
axum::http::StatusCode::FORBIDDEN,
|
||||
Some((team, _)) => Ok(team),
|
||||
None => Err(AppError::ForbiddenError(
|
||||
"not a member of requested team".to_string(),
|
||||
)
|
||||
.into_response());
|
||||
)),
|
||||
}
|
||||
}
|
||||
}};
|
||||
}
|
||||
pub(crate) use require_team_membership;
|
||||
|
||||
macro_rules! require_valid_csrf_token {
|
||||
($csrf_token:expr, $current_user:expr, $db_conn:expr) => {{
|
||||
if !crate::csrf::validate_csrf_token(&$db_conn, &$csrf_token, Some($current_user.id))
|
||||
.await?
|
||||
{
|
||||
return Ok((
|
||||
axum::http::StatusCode::FORBIDDEN,
|
||||
"invalid CSRF token".to_string(),
|
||||
)
|
||||
.into_response());
|
||||
pub async fn require_valid_csrf_token(
|
||||
csrf_token: &str,
|
||||
current_user: &User,
|
||||
db_conn: &Connection,
|
||||
) -> Result<(), AppError> {
|
||||
if validate_csrf_token(db_conn, csrf_token, Some(current_user.id.clone())).await? {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(AppError::ForbiddenError("invalid CSRF token".to_string()))
|
||||
}
|
||||
}};
|
||||
}
|
||||
pub(crate) use require_valid_csrf_token;
|
||||
|
|
|
@ -111,8 +111,8 @@ async fn post_new_api_key(
|
|||
CurrentUser(current_user): CurrentUser,
|
||||
Form(form): Form<PostNewApiKeyForm>,
|
||||
) -> Result<impl IntoResponse, AppError> {
|
||||
guards::require_valid_csrf_token!(form.csrf_token, current_user, db_conn);
|
||||
let team = guards::require_team_membership!(current_user, team_id, db_conn);
|
||||
guards::require_valid_csrf_token(&form.csrf_token, ¤t_user, &db_conn).await?;
|
||||
let team = guards::require_team_membership(¤t_user, &team_id, &db_conn).await?;
|
||||
|
||||
ApiKey::generate_for_team(&db_conn, team.id.clone()).await?;
|
||||
Ok(Redirect::to(&format!(
|
||||
|
@ -158,7 +158,7 @@ async fn post_new_team(
|
|||
CurrentUser(current_user): CurrentUser,
|
||||
Form(form): Form<PostNewTeamForm>,
|
||||
) -> Result<impl IntoResponse, AppError> {
|
||||
guards::require_valid_csrf_token!(form.csrf_token, current_user, db_conn);
|
||||
guards::require_valid_csrf_token(&form.csrf_token, ¤t_user, &db_conn).await?;
|
||||
|
||||
let team_id = Uuid::now_v7();
|
||||
let team = Team {
|
||||
|
@ -195,7 +195,7 @@ async fn projects_page(
|
|||
Path(team_id): Path<Uuid>,
|
||||
CurrentUser(current_user): CurrentUser,
|
||||
) -> Result<impl IntoResponse, AppError> {
|
||||
let team = guards::require_team_membership!(current_user, team_id, db_conn);
|
||||
let team = guards::require_team_membership(¤t_user, &team_id, &db_conn).await?;
|
||||
|
||||
let team_id = team.id.clone();
|
||||
let api_keys = db_conn
|
||||
|
|
Loading…
Add table
Reference in a new issue