summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSanto Cariotti <santo@dcariotti.me>2022-09-13 13:51:48 +0000
committerSanto Cariotti <santo@dcariotti.me>2022-09-13 13:51:48 +0000
commit2b2b2e103028a3c3e2a0f129e5c903aa18087ebd (patch)
tree32cc9de202d4f69473b7a8e469f137ea5d762cbe
parente62c4fe11e2e9bede790b5b0df50b2e6582e5424 (diff)
Edit an user avatar
-rw-r--r--src/models/user.rs22
-rw-r--r--src/routes/user.rs39
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 {