feat(auth): implement user registration and login with JWT authentication
- Added `bcrypt`, `jsonwebtoken`, and `once_cell` dependencies to manage password hashing and JWT handling. - Created `Claims` struct for JWT claims and implemented token generation in the login route. - Implemented user registration and authentication logic in the `auth` module. - Updated error handling to include validation errors. - Created new routes for user registration and login, and integrated them into the main router. - Added tests for the authentication flow, including registration and login scenarios. - Updated user model to include a password hash field. - Refactored user creation logic to include password validation. - Adjusted feed and user routes to utilize JWT for authentication.
This commit is contained in:
@@ -5,50 +5,22 @@ use axum::{
|
||||
routing::{get, post},
|
||||
Router,
|
||||
};
|
||||
use sea_orm::{DbErr, TryIntoModel};
|
||||
|
||||
use app::persistence::{
|
||||
follow,
|
||||
thought::get_thoughts_by_user,
|
||||
user::{create_user, get_user, search_users},
|
||||
user::{get_user, search_users},
|
||||
};
|
||||
use app::state::AppState;
|
||||
use app::{error::UserError, persistence::user::get_user_by_username};
|
||||
use models::schemas::thought::ThoughtListSchema;
|
||||
use models::schemas::user::{UserListSchema, UserSchema};
|
||||
use models::{params::user::CreateUserParams, schemas::thought::ThoughtListSchema};
|
||||
use models::{queries::user::UserQuery, schemas::thought::ThoughtSchema};
|
||||
|
||||
use crate::extractor::{Json, Valid};
|
||||
use crate::models::{ApiErrorResponse, ParamsErrorResponse};
|
||||
use crate::extractor::Json;
|
||||
use crate::models::ApiErrorResponse;
|
||||
use crate::{error::ApiError, extractor::AuthUser};
|
||||
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "",
|
||||
request_body = CreateUserParams,
|
||||
responses(
|
||||
(status = 201, description = "User created", body = UserSchema),
|
||||
(status = 400, description = "Bad request", body = ApiErrorResponse),
|
||||
(status = 409, description = "Username already exists", body = ApiErrorResponse),
|
||||
(status = 422, description = "Validation error", body = ParamsErrorResponse),
|
||||
(status = 500, description = "Internal server error", body = ApiErrorResponse),
|
||||
)
|
||||
)]
|
||||
async fn users_post(
|
||||
state: State<AppState>,
|
||||
Valid(Json(params)): Valid<Json<CreateUserParams>>,
|
||||
) -> Result<impl IntoResponse, ApiError> {
|
||||
let result = create_user(&state.conn, params).await;
|
||||
match result {
|
||||
Ok(user) => {
|
||||
let user = user.try_into_model().unwrap();
|
||||
Ok((StatusCode::CREATED, Json(UserSchema::from(user))))
|
||||
}
|
||||
Err(DbErr::UnpackInsertId) => Err(UserError::UsernameTaken.into()),
|
||||
Err(e) => Err(e.into()),
|
||||
}
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "",
|
||||
@@ -195,7 +167,7 @@ async fn user_follow_delete(
|
||||
|
||||
pub fn create_user_router() -> Router<AppState> {
|
||||
Router::new()
|
||||
.route("/", post(users_post).get(users_get))
|
||||
.route("/", get(users_get))
|
||||
.route("/{id}", get(users_id_get))
|
||||
.route("/{username}/thoughts", get(user_thoughts_get))
|
||||
.route(
|
||||
|
Reference in New Issue
Block a user