mirror of
https://github.com/DefectingCat/phthonus
synced 2025-07-15 16:41:32 +00:00
feat: add user registry
add hash password
This commit is contained in:
1
frameworks/Rust/axum/Cargo.lock
generated
1
frameworks/Rust/axum/Cargo.lock
generated
@ -958,6 +958,7 @@ dependencies = [
|
|||||||
"dotenvy",
|
"dotenvy",
|
||||||
"jsonwebtoken",
|
"jsonwebtoken",
|
||||||
"rand",
|
"rand",
|
||||||
|
"regex",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_repr",
|
"serde_repr",
|
||||||
|
@ -18,6 +18,7 @@ thiserror = "2.0.0"
|
|||||||
dotenvy = "0.15.7"
|
dotenvy = "0.15.7"
|
||||||
argon2 = "0.5.3"
|
argon2 = "0.5.3"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
|
regex = "1.11.1"
|
||||||
serde = { version = "1.0.214", features = ["derive", "serde_derive"] }
|
serde = { version = "1.0.214", features = ["derive", "serde_derive"] }
|
||||||
serde_json = { version = "1.0.132" }
|
serde_json = { version = "1.0.132" }
|
||||||
serde_repr = "0.1.19"
|
serde_repr = "0.1.19"
|
||||||
|
@ -15,6 +15,8 @@ pub enum AppError {
|
|||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
Any(#[from] anyhow::Error),
|
Any(#[from] anyhow::Error),
|
||||||
|
|
||||||
|
#[error(transparent)]
|
||||||
|
ValidationError(#[from] validator::ValidationErrors),
|
||||||
// axum
|
// axum
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
AxumFormRejection(#[from] FormRejection),
|
AxumFormRejection(#[from] FormRejection),
|
||||||
@ -80,11 +82,14 @@ impl IntoResponse for AppError {
|
|||||||
ParameterIncorrect,
|
ParameterIncorrect,
|
||||||
self.to_string(),
|
self.to_string(),
|
||||||
),
|
),
|
||||||
// route
|
AppError::ValidationError(_) => {
|
||||||
// AppError::AuthorizeFailed(err) => {
|
let message = format!("Input validation error: [{self}]").replace('\n', ", ");
|
||||||
// (StatusCode::UNAUTHORIZED, AuthorizeFailed, err.to_string())
|
(StatusCode::BAD_REQUEST, ParameterIncorrect, message)
|
||||||
// }
|
} // route
|
||||||
// AppError::UserConflict(err) => (StatusCode::CONFLICT, UserConflict, err.to_string()),
|
// AppError::AuthorizeFailed(err) => {
|
||||||
|
// (StatusCode::UNAUTHORIZED, AuthorizeFailed, err.to_string())
|
||||||
|
// }
|
||||||
|
// AppError::UserConflict(err) => (StatusCode::CONFLICT, UserConflict, err.to_string()),
|
||||||
};
|
};
|
||||||
let body = Json(json!({
|
let body = Json(json!({
|
||||||
"code": code,
|
"code": code,
|
||||||
|
@ -1,12 +1,22 @@
|
|||||||
|
use crate::utils::password::hash;
|
||||||
use axum::{routing::post, Json, Router};
|
use axum::{routing::post, Json, Router};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use validator::Validate;
|
||||||
|
|
||||||
|
use crate::utils::validator::EMAIL_REGEX;
|
||||||
|
|
||||||
use super::{RouteResponse, RouteResult};
|
use super::{RouteResponse, RouteResult};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize, Validate)]
|
||||||
pub struct UserResigtry {
|
pub struct UserResigtry {
|
||||||
|
#[validate(length(min = 1, message = "Can not be empty"))]
|
||||||
pub username: String,
|
pub username: String,
|
||||||
|
#[validate(regex(
|
||||||
|
path = *EMAIL_REGEX,
|
||||||
|
message = "邮箱格式不正确"
|
||||||
|
))]
|
||||||
pub email: String,
|
pub email: String,
|
||||||
|
#[validate(length(min = 6, max = 100, message = "Can not be empty"))]
|
||||||
pub password: String,
|
pub password: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -14,13 +24,23 @@ pub struct UserResigtry {
|
|||||||
pub struct UserResigtryRes {
|
pub struct UserResigtryRes {
|
||||||
pub username: String,
|
pub username: String,
|
||||||
pub email: String,
|
pub email: String,
|
||||||
|
pub password: String,
|
||||||
pub token: String,
|
pub token: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn registry(Json(user_param): Json<UserResigtry>) -> RouteResult<UserResigtryRes> {
|
pub async fn registry(Json(user_param): Json<UserResigtry>) -> RouteResult<UserResigtryRes> {
|
||||||
|
let UserResigtry {
|
||||||
|
email,
|
||||||
|
password,
|
||||||
|
username,
|
||||||
|
} = user_param;
|
||||||
|
|
||||||
|
let hashed = hash(password).await?;
|
||||||
|
|
||||||
let data = UserResigtryRes {
|
let data = UserResigtryRes {
|
||||||
username: "xfy".to_string(),
|
username,
|
||||||
email: "i@rua.plus".to_string(),
|
email,
|
||||||
|
password: hashed,
|
||||||
token: "abc".to_string(),
|
token: "abc".to_string(),
|
||||||
};
|
};
|
||||||
let res = RouteResponse {
|
let res = RouteResponse {
|
||||||
|
@ -3,6 +3,7 @@ use tracing_subscriber::{fmt, prelude::*, registry, EnvFilter};
|
|||||||
|
|
||||||
pub mod jwt;
|
pub mod jwt;
|
||||||
pub mod password;
|
pub mod password;
|
||||||
|
pub mod validator;
|
||||||
|
|
||||||
/// Initializes the logger for tracing.
|
/// Initializes the logger for tracing.
|
||||||
pub fn init_logger() {
|
pub fn init_logger() {
|
||||||
|
57
frameworks/Rust/axum/src/utils/validator.rs
Normal file
57
frameworks/Rust/axum/src/utils/validator.rs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
use std::sync::LazyLock;
|
||||||
|
|
||||||
|
use axum::{
|
||||||
|
async_trait,
|
||||||
|
extract::{
|
||||||
|
rejection::{FormRejection, JsonRejection},
|
||||||
|
FromRequest, Request,
|
||||||
|
},
|
||||||
|
Form, Json,
|
||||||
|
};
|
||||||
|
use regex::Regex;
|
||||||
|
use serde::de::DeserializeOwned;
|
||||||
|
use validator::Validate;
|
||||||
|
|
||||||
|
use crate::error::AppError;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Default)]
|
||||||
|
pub struct ValidatedForm<T>(pub T);
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl<T, S> FromRequest<S> for ValidatedForm<T>
|
||||||
|
where
|
||||||
|
T: DeserializeOwned + Validate,
|
||||||
|
S: Send + Sync,
|
||||||
|
Form<T>: FromRequest<S, Rejection = FormRejection>,
|
||||||
|
{
|
||||||
|
type Rejection = AppError;
|
||||||
|
|
||||||
|
async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
|
||||||
|
let Form(value) = Form::<T>::from_request(req, state).await?;
|
||||||
|
value.validate()?;
|
||||||
|
Ok(ValidatedForm(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Default)]
|
||||||
|
pub struct ValidatedJson<T>(pub T);
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl<T, S> FromRequest<S> for ValidatedJson<T>
|
||||||
|
where
|
||||||
|
T: DeserializeOwned + Validate,
|
||||||
|
S: Send + Sync,
|
||||||
|
Json<T>: FromRequest<S, Rejection = JsonRejection>,
|
||||||
|
{
|
||||||
|
type Rejection = AppError;
|
||||||
|
|
||||||
|
async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
|
||||||
|
let Json(value) = Json::<T>::from_request(req, state).await?;
|
||||||
|
value.validate()?;
|
||||||
|
Ok(ValidatedJson(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub static EMAIL_REGEX: LazyLock<Regex> = LazyLock::new(|| {
|
||||||
|
Regex::new(r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$").expect("Regex is valid")
|
||||||
|
});
|
Reference in New Issue
Block a user