diff --git a/src/handler.rs b/src/handler.rs index 2045d54..717b636 100644 --- a/src/handler.rs +++ b/src/handler.rs @@ -11,8 +11,9 @@ mod users; pub fn make_router(app_state: Repository) -> Router { let authentication_router = Router::new().route("/signup/request", post(authentication::sign_up_request)); + let users_router = Router::new() - .route("/me", get(users::get_me)) + .route("/me", get(users::get_me).put(users::put_me)) .route("/me/email", put(users::put_me_email)); Router::new() diff --git a/src/handler/users.rs b/src/handler/users.rs index 212ceb2..c47e7a7 100644 --- a/src/handler/users.rs +++ b/src/handler/users.rs @@ -3,7 +3,9 @@ use axum_extra::{headers::Cookie, TypedHeader}; use lettre::Address; use reqwest::StatusCode; use serde::Deserialize; +use validator::Validate; +use crate::repository::users::UpdateUser; use crate::repository::Repository; #[derive(Deserialize)] @@ -64,3 +66,61 @@ https://link/{jwt}" Ok(StatusCode::NO_CONTENT) } + +#[derive(serde::Deserialize, Validate, Clone)] +#[serde(rename_all = "camelCase")] +pub struct PutMeRequest { + #[validate(length(min = 1, max = 255))] + pub user_name: Option, + #[validate(length(max = 10000))] + pub icon: Option, + #[validate(length(max = 255))] + pub x_link: Option, + #[validate(length(max = 255))] + pub github_link: Option, + #[validate(length(max = 10000))] + pub self_introduction: Option, +} + +// todo とりえずの仮置き +fn encode_icon_to_icon_url(icon: String) -> String { + icon +} + +pub async fn put_me( + State(state): State, + TypedHeader(cookie): TypedHeader, + Json(body): Json, +) -> Result { + body.validate().map_err(|_| StatusCode::BAD_REQUEST)?; + + let session_id = cookie.get("session_id").ok_or(StatusCode::UNAUTHORIZED)?; + + let user_id = state + .get_user_id_by_session_id(session_id) + .await + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)? + .ok_or(StatusCode::UNAUTHORIZED)?; + + let user = state + .get_user_by_id(user_id) + .await + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; + + let new_body = UpdateUser { + user_name: body.user_name.unwrap_or(user.name), + icon_url: body.icon.map_or(user.icon_url, encode_icon_to_icon_url), + x_link: body.x_link.or(user.x_link), + github_link: body.github_link.or(user.github_link), + self_introduction: body.self_introduction.unwrap_or(user.self_introduction), + }; + + let icon_url = new_body.icon_url.clone(); + + state + .update_user(user_id, new_body) + .await + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; + + Ok(Json(serde_json::json!({"iconUrl": icon_url}))) +} diff --git a/src/repository.rs b/src/repository.rs index 9685529..b8f4156 100644 --- a/src/repository.rs +++ b/src/repository.rs @@ -5,7 +5,7 @@ use sqlx::{ }; mod signup_jwt; -mod users; +pub mod users; mod users_jwt; mod users_session; diff --git a/src/repository/users.rs b/src/repository/users.rs index 827c069..b03e890 100644 --- a/src/repository/users.rs +++ b/src/repository/users.rs @@ -31,6 +31,14 @@ pub struct User { pub updated_at: chrono::DateTime, } +pub struct UpdateUser { + pub user_name: String, + pub icon_url: String, + pub x_link: Option, + pub github_link: Option, + pub self_introduction: String, +} + impl Repository { pub async fn get_user_by_id(&self, user_id: i64) -> anyhow::Result { let user = sqlx::query_as::<_, User>("SELECT * FROM users WHERE id = ?") @@ -40,4 +48,15 @@ impl Repository { Ok(user) } + pub async fn update_user(&self, user_id: i64, body: UpdateUser) -> anyhow::Result<()> { + sqlx::query("UPDATE users SET name = ?, icon_url = ?, x_link = ?, github_link = ?, self_introduction = ? WHERE id = ?") + .bind(body.user_name) + .bind(body.icon_url) + .bind(body.x_link) + .bind(body.github_link) + .bind(body.self_introduction) + .bind(user_id) + .execute(&self.pool).await?; + Ok(()) + } }