feat: ✨ user_and_token middleware
refactor: ♻️ getting otp from client
This commit is contained in:
parent
0bb5a0b753
commit
f4765630ee
4 changed files with 86 additions and 47 deletions
|
@ -5,7 +5,7 @@ use tokio::sync::RwLock;
|
|||
|
||||
use crate::{
|
||||
error::ForumMailError,
|
||||
mail::{MailFieldsOneTimePassword, MailTemplate},
|
||||
//mail::{MailFieldsOneTimePassword, MailTemplate},
|
||||
};
|
||||
|
||||
use super::user::User;
|
||||
|
@ -31,10 +31,11 @@ impl OneTimePassword {
|
|||
one_time_password,
|
||||
};
|
||||
|
||||
let mail_template =
|
||||
MailTemplate::OneTimePassword(MailFieldsOneTimePassword::new(&user.name, &new_self));
|
||||
|
||||
mail_template.send_mail(user_email).await?;
|
||||
//todo vice versa comments :D
|
||||
// let mail_template =
|
||||
// MailTemplate::OneTimePassword(MailFieldsOneTimePassword::new(&user.name, &new_self));
|
||||
println!("{}", user_email);
|
||||
//mail_template.send_mail(user_email).await?;
|
||||
|
||||
let mut one_time_passwords = ONE_TIME_PASSWORDS.write().await;
|
||||
one_time_passwords.push(new_self);
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use axum::{
|
||||
extract::Path,
|
||||
http::StatusCode,
|
||||
response::IntoResponse,
|
||||
routing::{delete, get, patch, post},
|
||||
Json, Router,
|
||||
Extension, Json, Router,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::feature::{auth::OneTimePassword, login::Login, user::User, user_contact::UserContact};
|
||||
|
||||
use super::middleware::{self, UserAndToken};
|
||||
|
||||
const CONTACT_EMAIL_DEFAULT_ID: i64 = 0;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
|
@ -18,13 +22,8 @@ struct CreateOneTimePassword {
|
|||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct CreateLogin {
|
||||
pub one_time_password: OneTimePassword,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct UpdateLogin {
|
||||
pub user_id: i64,
|
||||
pub token: String,
|
||||
user_id: i64,
|
||||
one_time_password: String,
|
||||
}
|
||||
|
||||
pub fn route() -> Router {
|
||||
|
@ -32,7 +31,10 @@ pub fn route() -> Router {
|
|||
.route("/one_time_password", post(create_one_time_password))
|
||||
.route("/", post(create))
|
||||
.route("/users/{user_id}/tokens/{token}", get(read))
|
||||
.route("/", patch(update))
|
||||
.route(
|
||||
"/",
|
||||
patch(update).route_layer(axum::middleware::from_fn(middleware::user_and_token)),
|
||||
)
|
||||
.route("/users/{user_id}/tokens/{token}", delete(delete_))
|
||||
.route("/users/{user_id}", get(read_all_for_user))
|
||||
.route("/users/{user_id}", delete(delete_all_for_user))
|
||||
|
@ -58,8 +60,13 @@ async fn create_one_time_password(
|
|||
}
|
||||
}
|
||||
async fn create(Json(create_login): Json<CreateLogin>) -> impl IntoResponse {
|
||||
match OneTimePassword::verify(&create_login.one_time_password).await {
|
||||
true => match Login::create(&create_login.one_time_password.user_id).await {
|
||||
let one_time_password = OneTimePassword {
|
||||
user_id: create_login.user_id,
|
||||
one_time_password: create_login.one_time_password,
|
||||
};
|
||||
|
||||
match OneTimePassword::verify(&one_time_password).await {
|
||||
true => match Login::create(&one_time_password.user_id).await {
|
||||
Ok(login) => (StatusCode::CREATED, Json(serde_json::json!(login))),
|
||||
Err(err_val) => (
|
||||
StatusCode::BAD_REQUEST,
|
||||
|
@ -85,8 +92,8 @@ async fn read(Path((user_id, token)): Path<(i64, String)>) -> impl IntoResponse
|
|||
}
|
||||
}
|
||||
|
||||
async fn update(Json(update_login): Json<UpdateLogin>) -> impl IntoResponse {
|
||||
match Login::update(&update_login.user_id, &update_login.token).await {
|
||||
async fn update(Extension(user_and_token): Extension<Arc<UserAndToken>>) -> impl IntoResponse {
|
||||
match Login::update(&user_and_token.user.user_id, &user_and_token.token).await {
|
||||
Ok(login) => (StatusCode::ACCEPTED, Json(serde_json::json!(login))),
|
||||
Err(err_val) => (
|
||||
StatusCode::BAD_REQUEST,
|
||||
|
|
|
@ -3,10 +3,11 @@ use std::sync::Arc;
|
|||
use axum::{
|
||||
body::{to_bytes, Body},
|
||||
extract::Request,
|
||||
http::{self, Method, StatusCode},
|
||||
http::{self, HeaderMap, Method, StatusCode},
|
||||
middleware::Next,
|
||||
response::IntoResponse,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::feature::{login::TokenMeta, user::User};
|
||||
|
||||
|
@ -29,22 +30,18 @@ struct UserAndTargetUserAndRequest {
|
|||
request: Request,
|
||||
}
|
||||
|
||||
async fn user_extraction(request: Request) -> Option<UserAndRequest> {
|
||||
if let Some(authorization_header) = request.headers().get(http::header::AUTHORIZATION) {
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct UserAndToken {
|
||||
pub user: User,
|
||||
pub token: String,
|
||||
}
|
||||
|
||||
async fn authorization_token_extraction(request_headers: &HeaderMap) -> Option<String> {
|
||||
if let Some(authorization_header) = request_headers.get(http::header::AUTHORIZATION) {
|
||||
if let Ok(authorization_header) = authorization_header.to_str() {
|
||||
if let Some((bearer, authorization_header)) = authorization_header.split_once(' ') {
|
||||
if let Some((bearer, authorization_token)) = authorization_header.split_once(' ') {
|
||||
if bearer.to_lowercase() == "bearer" {
|
||||
match TokenMeta::verify_token(&authorization_header.to_string()).await {
|
||||
Ok(claims) => {
|
||||
return Some(UserAndRequest {
|
||||
user: User::read(&claims.custom.user_id).await.ok()?,
|
||||
request,
|
||||
});
|
||||
}
|
||||
Err(err_val) => {
|
||||
eprintln!("Verify Token | {}", err_val);
|
||||
}
|
||||
}
|
||||
return Some(authorization_token.to_owned());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -52,6 +49,23 @@ async fn user_extraction(request: Request) -> Option<UserAndRequest> {
|
|||
None
|
||||
}
|
||||
|
||||
async fn user_extraction(request: Request) -> Option<UserAndRequest> {
|
||||
if let Some(authorization_token) = authorization_token_extraction(&request.headers()).await {
|
||||
match TokenMeta::verify_token(&authorization_token.to_string()).await {
|
||||
Ok(claims) => {
|
||||
return Some(UserAndRequest {
|
||||
user: User::read(&claims.custom.user_id).await.ok()?,
|
||||
request,
|
||||
});
|
||||
}
|
||||
Err(err_val) => {
|
||||
eprintln!("Verify Token | {}", err_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
async fn target_user_extraction_from_uri(request: Request) -> Option<TargetUserAndRequest> {
|
||||
let uri_parts = request.uri().path().split('/').collect::<Vec<&str>>();
|
||||
for (index, uri_part) in uri_parts.iter().enumerate() {
|
||||
|
@ -213,3 +227,17 @@ pub async fn pass_higher_or_self(
|
|||
}
|
||||
Err(StatusCode::FORBIDDEN)
|
||||
}
|
||||
|
||||
pub async fn user_and_token(request: Request, next: Next) -> Result<impl IntoResponse, StatusCode> {
|
||||
if let Some(token) = authorization_token_extraction(&request.headers()).await {
|
||||
if let Some(user_and_request) = user_extraction(request).await {
|
||||
let user = user_and_request.user;
|
||||
let mut request = user_and_request.request;
|
||||
let user_and_token = Arc::new(UserAndToken { user, token });
|
||||
|
||||
request.extensions_mut().insert(user_and_token);
|
||||
return Ok(next.run(request).await);
|
||||
}
|
||||
}
|
||||
Err(StatusCode::FORBIDDEN)
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ struct CreateUser {
|
|||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct UpdateUser {
|
||||
id: i64,
|
||||
user_id: i64,
|
||||
name: String,
|
||||
surname: String,
|
||||
gender: bool,
|
||||
|
@ -34,7 +34,7 @@ pub fn route() -> Router {
|
|||
Router::new()
|
||||
.route("/", post(create))
|
||||
.route(
|
||||
"/{id}",
|
||||
"/{user_id}",
|
||||
get(read).route_layer(axum::middleware::from_fn(middleware::pass)),
|
||||
)
|
||||
.route(
|
||||
|
@ -42,7 +42,7 @@ pub fn route() -> Router {
|
|||
patch(update).route_layer(axum::middleware::from_fn(middleware::pass_higher_or_self)),
|
||||
)
|
||||
.route(
|
||||
"/{id}",
|
||||
"/{user_id}",
|
||||
delete(delete_).route_layer(axum::middleware::from_fn(middleware::pass_higher_or_self)),
|
||||
)
|
||||
.route(
|
||||
|
@ -54,15 +54,18 @@ pub fn route() -> Router {
|
|||
.route("/birth_dates/{birth_date}", get(read_all_for_birth_date))
|
||||
.route("/roles/{role}", get(read_all_for_role))
|
||||
.route("/genders/{gender}", get(read_all_for_gender))
|
||||
.route("/ids", get(read_all_id))
|
||||
.route("/ids/names/{name}", get(read_all_id_for_name))
|
||||
.route("/ids/surnames/{surname}", get(read_all_id_for_surname))
|
||||
.route("/users_ids", get(read_all_id))
|
||||
.route("/users_ids/names/{name}", get(read_all_id_for_name))
|
||||
.route(
|
||||
"/ids/birth_dates/{birth_date}",
|
||||
"/users_ids/surnames/{surname}",
|
||||
get(read_all_id_for_surname),
|
||||
)
|
||||
.route(
|
||||
"/users_ids/birth_dates/{birth_date}",
|
||||
get(read_all_id_for_birth_date),
|
||||
)
|
||||
.route("/ids/roles/{role}", get(read_all_id_for_role))
|
||||
.route("/ids/genders/{gender}", get(read_all_id_for_gender))
|
||||
.route("/users_ids/roles/{role}", get(read_all_id_for_role))
|
||||
.route("/users_ids/genders/{gender}", get(read_all_id_for_gender))
|
||||
.route("/count", get(count_all))
|
||||
.route("/count/names/{name}", get(count_all_for_name))
|
||||
.route("/count/surnames/{surname}", get(count_all_for_surname))
|
||||
|
@ -91,8 +94,8 @@ async fn create(Json(create_user): Json<CreateUser>) -> impl IntoResponse {
|
|||
}
|
||||
}
|
||||
|
||||
async fn read(Path(id): Path<i64>) -> impl IntoResponse {
|
||||
match User::read(&id).await {
|
||||
async fn read(Path(user_id): Path<i64>) -> impl IntoResponse {
|
||||
match User::read(&user_id).await {
|
||||
Ok(user) => (StatusCode::OK, Json(serde_json::json!(user))),
|
||||
Err(err_val) => (
|
||||
StatusCode::BAD_REQUEST,
|
||||
|
@ -103,7 +106,7 @@ async fn read(Path(id): Path<i64>) -> impl IntoResponse {
|
|||
|
||||
async fn update(Json(update_user): Json<UpdateUser>) -> impl IntoResponse {
|
||||
match User::update(
|
||||
&update_user.id,
|
||||
&update_user.user_id,
|
||||
&update_user.name,
|
||||
&update_user.surname,
|
||||
&update_user.gender,
|
||||
|
@ -120,8 +123,8 @@ async fn update(Json(update_user): Json<UpdateUser>) -> impl IntoResponse {
|
|||
}
|
||||
}
|
||||
|
||||
async fn delete_(Path(id): Path<i64>) -> impl IntoResponse {
|
||||
match User::delete(&id).await {
|
||||
async fn delete_(Path(user_id): Path<i64>) -> impl IntoResponse {
|
||||
match User::delete(&user_id).await {
|
||||
Ok(user) => (StatusCode::NO_CONTENT, Json(serde_json::json!(user))),
|
||||
Err(err_val) => (
|
||||
StatusCode::BAD_REQUEST,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue