feat: add middleware
This commit is contained in:
@@ -0,0 +1,65 @@
|
|||||||
|
use crate::{common_response, decode_access_token, AppState};
|
||||||
|
use axum::{
|
||||||
|
extract::Request,
|
||||||
|
http::{header::AUTHORIZATION, StatusCode},
|
||||||
|
middleware::Next,
|
||||||
|
response::Response,
|
||||||
|
Extension,
|
||||||
|
};
|
||||||
|
use std::convert::Infallible;
|
||||||
|
|
||||||
|
use super::{AuthQueryByEmailResponse, AuthRepository};
|
||||||
|
|
||||||
|
pub async fn auth_middleware(
|
||||||
|
Extension(state): Extension<AppState>,
|
||||||
|
mut req: Request,
|
||||||
|
next: Next,
|
||||||
|
) -> Result<Response, Infallible> {
|
||||||
|
let auth_header = match req.headers().get(AUTHORIZATION) {
|
||||||
|
Some(h) => h.to_str().unwrap_or_default(),
|
||||||
|
None => {
|
||||||
|
return Ok(common_response(
|
||||||
|
StatusCode::UNAUTHORIZED,
|
||||||
|
"You are not authorized",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let token = auth_header.strip_prefix("Bearer ").unwrap_or("");
|
||||||
|
|
||||||
|
let token_data = match decode_access_token(token) {
|
||||||
|
Ok(data) => data,
|
||||||
|
Err(err) => {
|
||||||
|
return Ok(common_response(
|
||||||
|
StatusCode::UNAUTHORIZED,
|
||||||
|
&format!("Invalid or expired token: {}", &err.to_string()),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let repository = AuthRepository::new(&state);
|
||||||
|
|
||||||
|
let user: Option<AuthQueryByEmailResponse> = match repository
|
||||||
|
.query_user_by_email(token_data.claims.sub.clone())
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(user) => Some(user),
|
||||||
|
Err(err) => {
|
||||||
|
return Ok(common_response(
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
&format!("DB error: {}", err),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if user.is_none() {
|
||||||
|
return Ok(common_response(
|
||||||
|
StatusCode::UNAUTHORIZED,
|
||||||
|
"Unauthorized user",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
req.extensions_mut().insert(user.unwrap());
|
||||||
|
|
||||||
|
Ok(next.run(req).await)
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use super::{
|
|||||||
use crate::{
|
use crate::{
|
||||||
common_response, encode_access_token, encode_refresh_token, hash_password,
|
common_response, encode_access_token, encode_refresh_token, hash_password,
|
||||||
success_response, v1::UsersItemDto, verify_password, AppState,
|
success_response, v1::UsersItemDto, verify_password, AppState,
|
||||||
ResponseSuccessDto, TokenSub,
|
ResponseSuccessDto,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct AuthService;
|
pub struct AuthService;
|
||||||
@@ -31,15 +31,8 @@ impl AuthService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let access_token = encode_access_token(TokenSub {
|
let access_token = encode_access_token(payload.email.clone());
|
||||||
email: payload.email.clone(),
|
let refresh_token = encode_refresh_token(payload.email.clone());
|
||||||
role_name: "Admin".to_string(),
|
|
||||||
});
|
|
||||||
|
|
||||||
let refresh_token = encode_refresh_token(TokenSub {
|
|
||||||
email: payload.email.clone(),
|
|
||||||
role_name: "Admin".to_string(),
|
|
||||||
});
|
|
||||||
|
|
||||||
let response = ResponseSuccessDto {
|
let response = ResponseSuccessDto {
|
||||||
data: AuthLoginResponsetDto {
|
data: AuthLoginResponsetDto {
|
||||||
|
|||||||
+5
-4
@@ -1,5 +1,4 @@
|
|||||||
use axum::Router;
|
use axum::{middleware::from_fn, Router};
|
||||||
|
|
||||||
pub mod auth;
|
pub mod auth;
|
||||||
pub mod docs;
|
pub mod docs;
|
||||||
pub mod gacha;
|
pub mod gacha;
|
||||||
@@ -11,7 +10,9 @@ pub use gacha::*;
|
|||||||
pub use users::*;
|
pub use users::*;
|
||||||
|
|
||||||
pub async fn routes() -> Router {
|
pub async fn routes() -> Router {
|
||||||
Router::new()
|
let public_routes = Router::new().nest("/auth", auth_router());
|
||||||
.nest("/auth", auth_router())
|
let protected_routes = Router::new()
|
||||||
.nest("/gacha", gacha_router())
|
.nest("/gacha", gacha_router())
|
||||||
|
.layer(from_fn(auth::auth_middleware::auth_middleware));
|
||||||
|
Router::new().merge(public_routes).merge(protected_routes)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ use utoipa::ToSchema;
|
|||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)]
|
#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)]
|
||||||
pub struct UsersSchema {
|
pub struct UsersSchema {
|
||||||
pub id: String,
|
|
||||||
pub email: String,
|
pub email: String,
|
||||||
pub fullname: String,
|
pub fullname: String,
|
||||||
pub password: String,
|
pub password: String,
|
||||||
|
|||||||
@@ -6,20 +6,14 @@ use jsonwebtoken::{
|
|||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
pub struct TokenSub {
|
|
||||||
pub email: String,
|
|
||||||
pub role_name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct Claims {
|
pub struct Claims {
|
||||||
pub exp: usize,
|
pub exp: usize,
|
||||||
pub iat: usize,
|
pub iat: usize,
|
||||||
pub sub: TokenSub,
|
pub sub: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn encode_access_token(sub: TokenSub) -> Result<String, StatusCode> {
|
pub fn encode_access_token(sub: String) -> Result<String, StatusCode> {
|
||||||
let env = Env::new();
|
let env = Env::new();
|
||||||
let secret: String = env.access_token_secret;
|
let secret: String = env.access_token_secret;
|
||||||
let now = Utc::now();
|
let now = Utc::now();
|
||||||
@@ -49,7 +43,7 @@ pub fn decode_access_token(
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn encode_refresh_token(sub: TokenSub) -> Result<String, StatusCode> {
|
pub fn encode_refresh_token(sub: String) -> Result<String, StatusCode> {
|
||||||
let env = Env::new();
|
let env = Env::new();
|
||||||
let secret: String = env.refresh_token_secret;
|
let secret: String = env.refresh_token_secret;
|
||||||
let now = Utc::now();
|
let now = Utc::now();
|
||||||
|
|||||||
Reference in New Issue
Block a user