Skip to content

Commit

Permalink
refactor(middleware): harmonise app response syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
Ahmard committed Dec 28, 2023
1 parent d369287 commit 04f3d1f
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 85 deletions.
12 changes: 12 additions & 0 deletions core/src/helpers/auth.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use actix_web::http::StatusCode;
use actix_web::web::Data;
use actix_web::HttpRequest;
use jsonwebtoken::{decode, DecodingKey, TokenData, Validation};
Expand All @@ -6,6 +7,7 @@ use crate::app_state::AppState;
use crate::enums::app_message::AppMessage::{UnAuthorized, WarningMessage};
use crate::enums::auth_permission::AuthPermission;
use crate::helpers::request::RequestHelper;
use crate::helpers::responder::{JsonResponse, JsonResponseEmptyMessage};
use crate::results::{AppResult, HttpResult};
use crate::services::auth_service::TokenClaims;
use crate::services::role_service::RoleService;
Expand Down Expand Up @@ -65,3 +67,13 @@ pub(crate) fn decode_auth_token(
&Validation::default(),
)
}

pub(crate) fn make_unauthorized_message(msg: &str) -> JsonResponse<JsonResponseEmptyMessage> {
JsonResponse {
code: 401,
success: false,
status: StatusCode::UNAUTHORIZED.to_string(),
message: Some(msg.to_string()),
data: JsonResponseEmptyMessage {},
}
}
33 changes: 22 additions & 11 deletions core/src/helpers/responder.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
use actix_web::http::StatusCode;
use actix_web::HttpResponse;
use serde::Serialize;
use std::fmt::{Display, Formatter};

use crate::helpers::db_pagination::PageData;

#[derive(Serialize)]
#[derive(Debug, Serialize)]
pub(crate) struct JsonResponseEmptyMessage {}

#[derive(Debug, Serialize)]
pub struct JsonResponse<T: Serialize> {
code: u16,
success: bool,
status: String,
message: Option<String>,
data: T,
pub(crate) code: u16,
pub(crate) success: bool,
pub(crate) status: String,
pub(crate) message: Option<String>,
pub(crate) data: T,
}

impl<T: Serialize> Display for JsonResponse<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str(serde_json::to_string(self).unwrap().as_str())
}
}

#[derive(Serialize)]
Expand All @@ -22,9 +32,6 @@ pub struct PaginationResponse<T: Serialize> {
pub(crate) data: Vec<T>,
}

#[derive(Serialize)]
pub struct JsonMessageResponse {}

pub fn json<T: Serialize>(data: T, status: StatusCode) -> HttpResponse {
HttpResponse::build(status).json(data)
}
Expand Down Expand Up @@ -77,11 +84,15 @@ pub fn json_error_message(message: &str) -> HttpResponse {
}

pub fn json_error_message_status(message: &str, status: StatusCode) -> HttpResponse {
json_error(JsonMessageResponse {}, status, Some(message.to_string()))
json_error(
JsonResponseEmptyMessage {},
status,
Some(message.to_string()),
)
}

pub fn json_success_message(message: &str) -> HttpResponse {
json_success(JsonMessageResponse {}, Some(message.to_string()))
json_success(JsonResponseEmptyMessage {}, Some(message.to_string()))
}

#[allow(dead_code)]
Expand Down
64 changes: 19 additions & 45 deletions core/src/http/middlewares/auth_middleware.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,18 @@ use actix_web::{
};
use futures_util::future::LocalBoxFuture;
use log::error;
use serde::Serialize;
use uuid::Uuid;

use crate::app_state::AppState;
use crate::enums::auth_role::AuthRole;
use crate::helpers::auth::decode_auth_token;
use crate::helpers::auth::{decode_auth_token, make_unauthorized_message};
use crate::helpers::uuid::UniqueIdentifier;
use crate::models::user::User;
use crate::repositories::personal_access_token_repository::PersonaAccessTokenRepository;
use crate::repositories::user_repository::UserRepository;
use crate::repositories::user_role_repository::UserRoleRepository;
use crate::results::http_result::ErroneousOptionResponse;

#[derive(Debug, Serialize)]
struct ErrorResponse<'a> {
success: bool,
status: i32,
message: &'a str,
}

#[derive(Clone)]
pub struct AuthMiddleware {
pub roles: Vec<AuthRole>,
Expand Down Expand Up @@ -93,11 +85,9 @@ where
if token.is_none() {
//You are not logged in, please provide token
let response = HttpResponse::Unauthorized()
.json(ErrorResponse {
success: false,
status: 401,
message: "you are not logged in, please provide token",
})
.json(make_unauthorized_message(
"you are not logged in, please provide token",
))
.map_into_right_body();

let (req, _pl) = request.into_parts();
Expand All @@ -117,11 +107,7 @@ where

if decoded.is_err() {
let response = HttpResponse::Unauthorized()
.json(ErrorResponse {
success: false,
status: 401,
message: "invalid authentication token",
})
.json(make_unauthorized_message("invalid authentication token"))
.map_into_right_body();

let (req, _pl) = request.into_parts();
Expand All @@ -138,17 +124,13 @@ where
true => match PersonaAccessTokenRepository.find_by_token(app.database(), raw_token) {
Ok(pat) => {
if !pat.is_usable() {
let message = Box::leak(Box::new(format!(
let msg = Box::leak(Box::new(format!(
"personal access token has expired on {:?}",
pat.expired_at
)));

let response = HttpResponse::Unauthorized()
.json(ErrorResponse {
success: false,
status: 401,
message,
})
.json(make_unauthorized_message(msg))
.map_into_right_body();

let (req, _pl) = request.into_parts();
Expand All @@ -160,11 +142,9 @@ where
Err(err) => {
error!("pat error: {:?}", err);
let response = HttpResponse::Unauthorized()
.json(ErrorResponse {
success: false,
status: 401,
message: "failed to authenticate personal access token",
})
.json(make_unauthorized_message(
"failed to authenticate personal access token",
))
.map_into_right_body();

let (req, _pl) = request.into_parts();
Expand All @@ -175,11 +155,9 @@ where

if user_lookup.is_error_or_empty() {
let response = HttpResponse::Unauthorized()
.json(ErrorResponse {
success: false,
status: 401,
message: "Invalid auth token, user not found",
})
.json(make_unauthorized_message(
"Invalid auth token, user not found",
))
.map_into_right_body();

let (req, _pl) = request.into_parts();
Expand All @@ -193,11 +171,9 @@ where
UserRoleRepository.list_role_names_by_user_id(app.database(), user.user_id);
if roles_result.is_error_or_empty() {
let response = HttpResponse::Unauthorized()
.json(ErrorResponse {
success: false,
status: 401,
message: "Something went wrong trying to authenticate you",
})
.json(make_unauthorized_message(
"Something went wrong trying to authenticate you",
))
.map_into_right_body();

error!(
Expand All @@ -220,11 +196,9 @@ where

if !has_access {
let response = HttpResponse::Unauthorized()
.json(ErrorResponse {
success: false,
status: 401,
message: "You are not authorised to access requested resource(s)",
})
.json(make_unauthorized_message(
"You are not authorised to access requested resource(s)",
))
.map_into_right_body();

let (req, _pl) = request.into_parts();
Expand Down
35 changes: 6 additions & 29 deletions core/src/http/middlewares/manual_auth_middleware.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,21 @@
use std::fmt;
use std::future::{ready, Ready};

use actix_web::error::ErrorUnauthorized;
use actix_web::web::Data;
use actix_web::{dev::Payload, Error as ActixWebError};
use actix_web::{http, FromRequest, HttpMessage, HttpRequest};
use log::error;
use serde::Serialize;
use uuid::Uuid;

use crate::app_state::AppState;
use crate::enums::app_message::AppMessage;
use crate::helpers::auth::decode_auth_token;
use crate::helpers::auth::{decode_auth_token, make_unauthorized_message};
use crate::helpers::uuid::UniqueIdentifier;
use crate::models::user::User;
use crate::repositories::personal_access_token_repository::PersonaAccessTokenRepository;
use crate::repositories::user_repository::UserRepository;
use crate::results::http_result::ErroneousOptionResponse;

#[derive(Debug, Serialize)]
struct ErrorResponse<'a> {
success: bool,
status: i32,
message: &'a str,
}

impl fmt::Display for ErrorResponse<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", serde_json::to_string(&self).unwrap())
}
}

pub struct ManualAuthMiddleware {
pub user_id: Uuid,
}
Expand All @@ -49,7 +34,7 @@ impl FromRequest for ManualAuthMiddleware {
});

if token.is_none() {
return ready(Err(ErrorUnauthorized(make_unauthorized_response(
return ready(Err(ErrorUnauthorized(make_unauthorized_message(
"You are not logged in, please provide token",
))));
}
Expand All @@ -69,7 +54,7 @@ impl FromRequest for ManualAuthMiddleware {
let claims = match decoded {
Ok(c) => c.claims,
Err(_) => {
return ready(Err(ErrorUnauthorized(make_unauthorized_response(
return ready(Err(ErrorUnauthorized(make_unauthorized_message(
"Invalid auth token",
))));
}
Expand All @@ -85,7 +70,7 @@ impl FromRequest for ManualAuthMiddleware {
"personal access token has expired on {:?}",
pat.expired_at
)));
return ready(Err(ErrorUnauthorized(make_unauthorized_response(message))));
return ready(Err(ErrorUnauthorized(make_unauthorized_message(message))));
}

UserRepository.find_by_id(app.database(), pat.user_id)
Expand All @@ -96,15 +81,15 @@ impl FromRequest for ManualAuthMiddleware {
_ => error!("pat error: {:?}", error),
}

return ready(Err(ErrorUnauthorized(make_unauthorized_response(
return ready(Err(ErrorUnauthorized(make_unauthorized_message(
"failed to authenticate personal access token",
))));
}
},
};

if user_lookup.is_error_or_empty() {
return ready(Err(ErrorUnauthorized(make_unauthorized_response(
return ready(Err(ErrorUnauthorized(make_unauthorized_message(
"Invalid auth token, user not found",
))));
}
Expand All @@ -118,11 +103,3 @@ impl FromRequest for ManualAuthMiddleware {
ready(Ok(ManualAuthMiddleware { user_id }))
}
}

fn make_unauthorized_response(message: &str) -> ErrorResponse {
ErrorResponse {
success: false,
status: 401,
message,
}
}

0 comments on commit 04f3d1f

Please sign in to comment.