feat: enhance error handling and user follow functionality, update tests for user context
This commit is contained in:
@@ -18,6 +18,9 @@ impl HTTPError for DbErr {
|
||||
fn to_status_code(&self) -> StatusCode {
|
||||
match self {
|
||||
DbErr::ConnectionAcquire(_) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
DbErr::UnpackInsertId => StatusCode::CONFLICT,
|
||||
DbErr::RecordNotFound(_) => StatusCode::NOT_FOUND,
|
||||
DbErr::Custom(s) if s == "Users cannot follow themselves" => StatusCode::BAD_REQUEST,
|
||||
_ => StatusCode::INTERNAL_SERVER_ERROR, // TODO:: more granularity
|
||||
}
|
||||
}
|
||||
@@ -27,7 +30,7 @@ impl HTTPError for UserError {
|
||||
fn to_status_code(&self) -> StatusCode {
|
||||
match self {
|
||||
UserError::NotFound => StatusCode::NOT_FOUND,
|
||||
UserError::NotFollowing => StatusCode::BAD_REQUEST,
|
||||
UserError::NotFollowing => StatusCode::NOT_FOUND,
|
||||
UserError::Forbidden => StatusCode::FORBIDDEN,
|
||||
UserError::UsernameTaken => StatusCode::BAD_REQUEST,
|
||||
UserError::AlreadyFollowing => StatusCode::BAD_REQUEST,
|
||||
|
@@ -15,7 +15,7 @@ impl FromRequestParts<AppState> for AuthUser {
|
||||
type Rejection = (StatusCode, &'static str);
|
||||
|
||||
async fn from_request_parts(
|
||||
_parts: &mut Parts,
|
||||
parts: &mut Parts,
|
||||
_state: &AppState,
|
||||
) -> Result<Self, Self::Rejection> {
|
||||
// For now, we'll just return a hardcoded user.
|
||||
@@ -24,6 +24,12 @@ impl FromRequestParts<AppState> for AuthUser {
|
||||
// 2. Validate the JWT.
|
||||
// 3. Extract the user ID from the token claims.
|
||||
// 4. Return an error if the token is invalid or missing.
|
||||
Ok(AuthUser { id: 1 }) // Assume user with ID 1 is always authenticated.
|
||||
if let Some(user_id_header) = parts.headers.get("x-test-user-id") {
|
||||
let user_id_str = user_id_header.to_str().unwrap_or("1");
|
||||
let user_id = user_id_str.parse::<i32>().unwrap_or(1);
|
||||
return Ok(AuthUser { id: user_id });
|
||||
} else {
|
||||
return Ok(AuthUser { id: 1 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -38,12 +38,15 @@ async fn users_post(
|
||||
state: State<AppState>,
|
||||
Valid(Json(params)): Valid<Json<CreateUserParams>>,
|
||||
) -> Result<impl IntoResponse, ApiError> {
|
||||
let user = create_user(&state.conn, params)
|
||||
.await
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
let user = user.try_into_model().unwrap();
|
||||
Ok((StatusCode::CREATED, Json(UserSchema::from(user))))
|
||||
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(
|
||||
@@ -111,6 +114,7 @@ async fn user_thoughts_get(
|
||||
.ok_or(UserError::NotFound)?;
|
||||
|
||||
let thoughts_with_authors = get_thoughts_by_user(&state.conn, user.id).await?;
|
||||
|
||||
let thoughts_schema: Vec<ThoughtSchema> = thoughts_with_authors
|
||||
.into_iter()
|
||||
.map(ThoughtSchema::from)
|
||||
@@ -148,7 +152,14 @@ async fn user_follow_post(
|
||||
|
||||
match result {
|
||||
Ok(_) => Ok(StatusCode::NO_CONTENT),
|
||||
Err(DbErr::UnpackInsertId) => Err(UserError::AlreadyFollowing.into()),
|
||||
Err(e)
|
||||
if matches!(
|
||||
e.sql_err(),
|
||||
Some(sea_orm::SqlErr::UniqueConstraintViolation { .. })
|
||||
) =>
|
||||
{
|
||||
Err(UserError::AlreadyFollowing.into())
|
||||
}
|
||||
Err(e) => Err(e.into()),
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user