diff options
| -rw-r--r-- | src/models/auth.rs | 11 | ||||
| -rw-r--r-- | src/models/user.rs | 30 | ||||
| -rw-r--r-- | src/routes/auth.rs | 34 |
3 files changed, 72 insertions, 3 deletions
diff --git a/src/models/auth.rs b/src/models/auth.rs index 8a70244..651bf26 100644 --- a/src/models/auth.rs +++ b/src/models/auth.rs @@ -32,13 +32,22 @@ pub struct AuthBody { token_type: String, } -/// Payload used for user creation +/// Payload used for login #[derive(Deserialize)] pub struct LoginCredentials { pub username: String, pub password: String, } +/// Paylod used for user creation +#[derive(Deserialize)] +pub struct SignUpForm { + pub email: String, + pub username: String, + pub password1: String, + pub password2: String, +} + static KEYS: Lazy<Keys> = Lazy::new(|| { let secret = &crate::config::CONFIG.jwt_secret; Keys::new(secret.as_bytes()) diff --git a/src/models/user.rs b/src/models/user.rs index ba2df8f..56ae307 100644 --- a/src/models/user.rs +++ b/src/models/user.rs @@ -131,4 +131,34 @@ impl User { Ok(row.count.unwrap()) } + + /// Prevent the "uniquess" Postgres fields check. Check if username has been taken + pub async fn username_has_taken(username: &String) -> Result<bool, AppError> { + let pool = unsafe { get_client() }; + let row = sqlx::query!( + r#" + SELECT COUNT(id) as count FROM users WHERE username = $1 + "#, + username, + ) + .fetch_one(pool) + .await?; + + Ok(row.count.unwrap() > 0) + } + + /// Prevent the "uniquess" Postgres fields check. Check if email has been taken + pub async fn email_has_taken(email: &String) -> Result<bool, AppError> { + let pool = unsafe { get_client() }; + let row = sqlx::query!( + r#" + SELECT COUNT(id) as count FROM users WHERE email = $1 + "#, + email, + ) + .fetch_one(pool) + .await?; + + Ok(row.count.unwrap() > 0) + } } diff --git a/src/routes/auth.rs b/src/routes/auth.rs index b667b97..5c9b293 100644 --- a/src/routes/auth.rs +++ b/src/routes/auth.rs @@ -1,13 +1,15 @@ use crate::errors::AppError; use crate::models::{ - auth::{AuthBody, Claims, LoginCredentials}, + auth::{AuthBody, Claims, LoginCredentials, SignUpForm}, user::User, }; use axum::{routing::post, Json, Router}; /// Create routes for `/v1/auth/` namespace pub fn create_route() -> Router { - Router::new().route("/login", post(make_login)) + Router::new() + .route("/login", post(make_login)) + .route("/signup", post(signup)) } /// Make login. Check if a user with the email and password passed in request body exists into the @@ -23,3 +25,31 @@ async fn make_login(Json(payload): Json<LoginCredentials>) -> Result<Json<AuthBo Err(_) => Err(AppError::NotFound("User not found".to_string())), } } + +/// Create a new user +async fn signup(Json(payload): Json<SignUpForm>) -> Result<Json<AuthBody>, AppError> { + if payload.password1 != payload.password2 { + return Err(AppError::BadRequest( + "The inserted passwords do not match".to_string(), + )); + } + + if User::email_has_taken(&payload.email).await? { + return Err(AppError::BadRequest( + "An user with this email already exists".to_string(), + )); + } + + if User::username_has_taken(&payload.username).await? { + return Err(AppError::BadRequest( + "An user with this username already exists".to_string(), + )); + } + + let user = User::new(payload.email, payload.username, payload.password1); + let user = User::create(user).await?; + + let claims = Claims::new(user.id); + let token = claims.get_token()?; + Ok(Json(AuthBody::new(token))) +} |
