From 2c6434e0b89e93ab6bdddb28bcd059b48638cb0d Mon Sep 17 00:00:00 2001 From: Santo Cariotti Date: Sat, 3 Sep 2022 12:10:20 +0200 Subject: Users has username and use it for login --- src/main.rs | 2 +- src/models/auth.rs | 7 +++++++ src/models/user.rs | 33 +++++++++++++++++++++------------ src/routes/auth.rs | 10 +++++----- src/routes/user.rs | 4 ++-- 5 files changed, 36 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/main.rs b/src/main.rs index 508d6cd..4a211fd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,7 +18,7 @@ use tracing::Span; async fn main() { let app = create_app().await; - /// By default the server is bind at "127.0.0.1:3000" + // By default the server is bind at "127.0.0.1:3000" let addr = std::env::var("ALLOWED_HOST").unwrap_or_else(|_| "127.0.0.1:3000".to_string()); tracing::info!("Listening on {}", addr); diff --git a/src/models/auth.rs b/src/models/auth.rs index 8b8f61c..7f9ae00 100644 --- a/src/models/auth.rs +++ b/src/models/auth.rs @@ -32,6 +32,13 @@ pub struct AuthBody { token_type: String, } +/// Payload used for user creation +#[derive(Deserialize)] +pub struct LoginCredentials { + pub username: String, + pub password: String, +} + static KEYS: Lazy = Lazy::new(|| { let secret = std::env::var("JWT_SECRET").expect("JWT_SECRET must be set"); Keys::new(secret.as_bytes()) diff --git a/src/models/user.rs b/src/models/user.rs index 06cde0a..71b35b6 100644 --- a/src/models/user.rs +++ b/src/models/user.rs @@ -8,8 +8,10 @@ use validator::Validate; #[derive(Deserialize, Serialize, Validate)] pub struct User { id: i32, - #[validate(length(min = 1, message = "Can not be empty"))] + #[validate(length(min = 4, message = "Can not be empty"))] email: String, + #[validate(length(min = 2, message = "Can not be empty"))] + username: String, #[validate(length(min = 8, message = "Must be min 8 chars length"))] password: String, is_staff: Option, @@ -21,6 +23,7 @@ pub struct UserList { // It is public because it used by `Claims` creation pub id: i32, email: String, + username: String, is_staff: Option, } @@ -28,15 +31,17 @@ pub struct UserList { #[derive(Deserialize)] pub struct UserCreate { pub email: String, + pub username: String, pub password: String, } impl User { /// By default an user has id = 0. It is not created yet - pub fn new(email: String, password: String) -> Self { + pub fn new(email: String, username: String, password: String) -> Self { Self { id: 0, email, + username, password, is_staff: Some(false), } @@ -54,11 +59,12 @@ impl User { let rec = sqlx::query_as!( UserList, r#" - INSERT INTO users (email, password) - VALUES ( $1, $2 ) - RETURNING id, email, is_staff + INSERT INTO users (email, username, password) + VALUES ( $1, $2, $3) + RETURNING id, email, username, is_staff "#, user.email, + user.username, crypted_password ) .fetch_one(pool) @@ -76,10 +82,10 @@ impl User { let rec = sqlx::query_as!( UserList, r#" - SELECT id, email, is_staff FROM "users" - WHERE email = $1 AND password = $2 + SELECT id, email, username, is_staff FROM "users" + WHERE username = $1 AND password = $2 "#, - user.email, + user.username, crypted_password ) .fetch_one(pool) @@ -95,7 +101,7 @@ impl User { let rec = sqlx::query_as!( UserList, r#" - SELECT id, email, is_staff FROM "users" + SELECT id, email, username, is_staff FROM "users" WHERE id = $1 "#, user_id @@ -109,9 +115,12 @@ impl User { /// List all users pub async fn list() -> Result, AppError> { let pool = unsafe { get_client() }; - let rows = sqlx::query_as!(UserList, r#"SELECT id, email, is_staff FROM users"#) - .fetch_all(pool) - .await?; + let rows = sqlx::query_as!( + UserList, + r#"SELECT id, email, username, is_staff FROM users"# + ) + .fetch_all(pool) + .await?; Ok(rows) } diff --git a/src/routes/auth.rs b/src/routes/auth.rs index 37c41b2..b667b97 100644 --- a/src/routes/auth.rs +++ b/src/routes/auth.rs @@ -1,7 +1,7 @@ use crate::errors::AppError; use crate::models::{ - auth::{AuthBody, Claims}, - user::{User, UserCreate}, + auth::{AuthBody, Claims, LoginCredentials}, + user::User, }; use axum::{routing::post, Json, Router}; @@ -12,14 +12,14 @@ pub fn create_route() -> Router { /// Make login. Check if a user with the email and password passed in request body exists into the /// database -async fn make_login(Json(payload): Json) -> Result, AppError> { - let user = User::new(payload.email, payload.password); +async fn make_login(Json(payload): Json) -> Result, AppError> { + let user = User::new(String::new(), payload.username, payload.password); match User::find(user).await { Ok(user) => { let claims = Claims::new(user.id); let token = claims.get_token()?; Ok(Json(AuthBody::new(token))) } - Err(_) => Err(AppError::NotFound), + Err(_) => Err(AppError::NotFound("User not found".to_string())), } } diff --git a/src/routes/user.rs b/src/routes/user.rs index d44df66..3dfb73a 100644 --- a/src/routes/user.rs +++ b/src/routes/user.rs @@ -24,7 +24,7 @@ async fn create_user( Json(payload): Json, _: Claims, ) -> Result, AppError> { - let user = User::new(payload.email, payload.password); + let user = User::new(payload.email, payload.username, payload.password); let user_new = User::create(user).await?; Ok(Json(user_new)) @@ -34,6 +34,6 @@ async fn create_user( async fn get_user(Path(user_id): Path, _: Claims) -> Result, AppError> { match User::find_by_id(user_id).await { Ok(user) => Ok(Json(user)), - Err(_) => Err(AppError::NotFound), + Err(_) => Err(AppError::NotFound("User not found".to_string())), } } -- cgit v1.2.3-71-g8e6c