diff options
| author | Santo Cariotti <santo@dcariotti.me> | 2022-09-13 13:51:48 +0000 |
|---|---|---|
| committer | Santo Cariotti <santo@dcariotti.me> | 2022-09-13 13:51:48 +0000 |
| commit | 2b2b2e103028a3c3e2a0f129e5c903aa18087ebd (patch) | |
| tree | 32cc9de202d4f69473b7a8e469f137ea5d762cbe | |
| parent | e62c4fe11e2e9bede790b5b0df50b2e6582e5424 (diff) | |
Edit an user avatar
| -rw-r--r-- | src/models/user.rs | 22 | ||||
| -rw-r--r-- | src/routes/user.rs | 39 |
2 files changed, 58 insertions, 3 deletions
diff --git a/src/models/user.rs b/src/models/user.rs index b1427f6..7d336f9 100644 --- a/src/models/user.rs +++ b/src/models/user.rs @@ -30,7 +30,7 @@ pub struct UserList { username: String, is_staff: Option<bool>, #[serde_as(as = "NoneAsEmptyString")] - avatar: Option<String>, + pub avatar: Option<String>, } impl User { @@ -168,3 +168,23 @@ impl User { Ok(row.count.unwrap() > 0) } } + +impl UserList { + // Edit an user + pub async fn edit_avatar(&mut self, avatar: String) -> Result<(), AppError> { + let pool = unsafe { get_client() }; + sqlx::query!( + r#" + UPDATE users SET avatar = $1 WHERE id = $2 + "#, + avatar, + self.id, + ) + .execute(pool) + .await?; + + self.avatar = Some(avatar); + + Ok(()) + } +} diff --git a/src/routes/user.rs b/src/routes/user.rs index 00e2980..407f7b4 100644 --- a/src/routes/user.rs +++ b/src/routes/user.rs @@ -1,12 +1,13 @@ use crate::errors::AppError; +use crate::files::{delete_upload, upload}; use crate::models::{ auth::Claims, user::{User, UserList}, }; use crate::pagination::Pagination; use axum::{ - extract::{Path, Query}, - routing::get, + extract::{ContentLengthLimit, Multipart, Path, Query}, + routing::{get, put}, Json, Router, }; use serde::Serialize; @@ -16,6 +17,7 @@ pub fn create_route() -> Router { Router::new() .route("/", get(list_users)) .route("/me", get(get_me)) + .route("/me/avatar", put(edit_my_avatar)) .route("/:id", get(get_user)) } @@ -45,6 +47,39 @@ async fn get_me(claims: Claims) -> Result<Json<UserList>, AppError> { } } +/// Edit the avatar of the user linked to the claims +async fn edit_my_avatar( + claims: Claims, + ContentLengthLimit(multipart): ContentLengthLimit<Multipart, { 1024 * 1024 }>, +) -> Result<Json<UserList>, AppError> { + let mut user = match User::find_by_id(claims.user_id).await { + Ok(user) => user, + Err(_) => { + return Err(AppError::NotFound("User not found".to_string())); + } + }; + + if user.avatar.is_some() { + let avatar_url = user.avatar.as_ref().unwrap(); + delete_upload(&avatar_url)?; + } + + match upload( + multipart, + vec!["jpg", "jpeg", "png", "webp"], + Some(format!("avatar-{}", user.id)), + ) + .await + { + Ok(saved_file) => { + user.edit_avatar(saved_file).await?; + + Ok(Json(user)) + } + Err(e) => Err(e), + } +} + /// Get an user with id = `user_id`. Checks Authorization token async fn get_user(Path(user_id): Path<i32>, _: Claims) -> Result<Json<UserList>, AppError> { match User::find_by_id(user_id).await { |
