feat(user-avatar): users can now edit there image (image is taken from OIDC picture)
This commit is contained in:
@@ -42,6 +42,28 @@ impl UserPgRepository {
|
||||
_ => UserRepositoryError::DatabaseError(format!("Database error: {}", err)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Updates a user's profile image (URL or data URI). Not part of the
|
||||
/// `UserRepository` trait — called directly from `AuthApplicationService`.
|
||||
pub async fn update_image(
|
||||
&self,
|
||||
user_id: Uuid,
|
||||
image: Option<String>,
|
||||
) -> UserRepositoryResult<()> {
|
||||
sqlx::query(
|
||||
r#"
|
||||
UPDATE auth.users
|
||||
SET image = $2, updated_at = NOW()
|
||||
WHERE id = $1
|
||||
"#,
|
||||
)
|
||||
.bind(user_id)
|
||||
.bind(&image)
|
||||
.execute(&*self.pool)
|
||||
.await
|
||||
.map_err(Self::map_sqlx_error)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl UserRepository for UserPgRepository {
|
||||
@@ -105,11 +127,11 @@ impl UserRepository for UserPgRepository {
|
||||
async fn get_user_by_id(&self, id: Uuid) -> UserRepositoryResult<User> {
|
||||
let row = sqlx::query(
|
||||
r#"
|
||||
SELECT
|
||||
id, username, email, password_hash, role::text as role_text,
|
||||
storage_quota_bytes, storage_used_bytes,
|
||||
SELECT
|
||||
id, username, email, password_hash, role::text as role_text,
|
||||
storage_quota_bytes, storage_used_bytes,
|
||||
created_at, updated_at, last_login_at, active,
|
||||
oidc_provider, oidc_subject
|
||||
oidc_provider, oidc_subject, image
|
||||
FROM auth.users
|
||||
WHERE id = $1
|
||||
"#,
|
||||
@@ -140,6 +162,7 @@ impl UserRepository for UserPgRepository {
|
||||
row.get("active"),
|
||||
row.get("oidc_provider"),
|
||||
row.get("oidc_subject"),
|
||||
row.get("image"),
|
||||
))
|
||||
}
|
||||
|
||||
@@ -147,11 +170,11 @@ impl UserRepository for UserPgRepository {
|
||||
async fn get_user_by_username(&self, username: &str) -> UserRepositoryResult<User> {
|
||||
let row = sqlx::query(
|
||||
r#"
|
||||
SELECT
|
||||
id, username, email, password_hash, role::text as role_text,
|
||||
storage_quota_bytes, storage_used_bytes,
|
||||
SELECT
|
||||
id, username, email, password_hash, role::text as role_text,
|
||||
storage_quota_bytes, storage_used_bytes,
|
||||
created_at, updated_at, last_login_at, active,
|
||||
oidc_provider, oidc_subject
|
||||
oidc_provider, oidc_subject, image
|
||||
FROM auth.users
|
||||
WHERE username = $1
|
||||
"#,
|
||||
@@ -182,6 +205,7 @@ impl UserRepository for UserPgRepository {
|
||||
row.get("active"),
|
||||
row.get("oidc_provider"),
|
||||
row.get("oidc_subject"),
|
||||
row.get("image"),
|
||||
))
|
||||
}
|
||||
|
||||
@@ -189,11 +213,11 @@ impl UserRepository for UserPgRepository {
|
||||
async fn get_user_by_email(&self, email: &str) -> UserRepositoryResult<User> {
|
||||
let row = sqlx::query(
|
||||
r#"
|
||||
SELECT
|
||||
id, username, email, password_hash, role::text as role_text,
|
||||
storage_quota_bytes, storage_used_bytes,
|
||||
SELECT
|
||||
id, username, email, password_hash, role::text as role_text,
|
||||
storage_quota_bytes, storage_used_bytes,
|
||||
created_at, updated_at, last_login_at, active,
|
||||
oidc_provider, oidc_subject
|
||||
oidc_provider, oidc_subject, image
|
||||
FROM auth.users
|
||||
WHERE email = $1
|
||||
"#,
|
||||
@@ -224,6 +248,7 @@ impl UserRepository for UserPgRepository {
|
||||
row.get("active"),
|
||||
row.get("oidc_provider"),
|
||||
row.get("oidc_subject"),
|
||||
row.get("image"),
|
||||
))
|
||||
}
|
||||
|
||||
@@ -238,7 +263,7 @@ impl UserRepository for UserPgRepository {
|
||||
sqlx::query(
|
||||
r#"
|
||||
UPDATE auth.users
|
||||
SET
|
||||
SET
|
||||
username = $2,
|
||||
email = $3,
|
||||
password_hash = $4,
|
||||
@@ -247,7 +272,8 @@ impl UserRepository for UserPgRepository {
|
||||
storage_used_bytes = $7,
|
||||
updated_at = $8,
|
||||
last_login_at = $9,
|
||||
active = $10
|
||||
active = $10,
|
||||
image = $11
|
||||
WHERE id = $1
|
||||
"#,
|
||||
)
|
||||
@@ -261,6 +287,7 @@ impl UserRepository for UserPgRepository {
|
||||
.bind(user_clone.updated_at())
|
||||
.bind(user_clone.last_login_at())
|
||||
.bind(user_clone.is_active())
|
||||
.bind(user_clone.image())
|
||||
.execute(&mut **tx)
|
||||
.await
|
||||
.map_err(Self::map_sqlx_error)?;
|
||||
@@ -323,11 +350,11 @@ impl UserRepository for UserPgRepository {
|
||||
async fn list_users(&self, limit: i64, offset: i64) -> UserRepositoryResult<Vec<User>> {
|
||||
let rows = sqlx::query(
|
||||
r#"
|
||||
SELECT
|
||||
id, username, email, password_hash, role::text as role_text,
|
||||
storage_quota_bytes, storage_used_bytes,
|
||||
SELECT
|
||||
id, username, email, password_hash, role::text as role_text,
|
||||
storage_quota_bytes, storage_used_bytes,
|
||||
created_at, updated_at, last_login_at, active,
|
||||
oidc_provider, oidc_subject
|
||||
oidc_provider, oidc_subject, image
|
||||
FROM auth.users
|
||||
ORDER BY created_at DESC
|
||||
LIMIT $1 OFFSET $2
|
||||
@@ -363,6 +390,7 @@ impl UserRepository for UserPgRepository {
|
||||
row.get("active"),
|
||||
row.get("oidc_provider"),
|
||||
row.get("oidc_subject"),
|
||||
row.get("image"),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
@@ -378,7 +406,7 @@ impl UserRepository for UserPgRepository {
|
||||
id, username, email, password_hash, role::text as role_text,
|
||||
storage_quota_bytes, storage_used_bytes,
|
||||
created_at, updated_at, last_login_at, active,
|
||||
oidc_provider, oidc_subject
|
||||
oidc_provider, oidc_subject, image
|
||||
FROM auth.users
|
||||
WHERE username ILIKE $1 OR email ILIKE $1
|
||||
ORDER BY username
|
||||
@@ -414,6 +442,7 @@ impl UserRepository for UserPgRepository {
|
||||
row.get("active"),
|
||||
row.get("oidc_provider"),
|
||||
row.get("oidc_subject"),
|
||||
row.get("image"),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
@@ -496,11 +525,11 @@ impl UserRepository for UserPgRepository {
|
||||
async fn list_users_by_role(&self, role: &str) -> UserRepositoryResult<Vec<User>> {
|
||||
let rows = sqlx::query(
|
||||
r#"
|
||||
SELECT
|
||||
id, username, email, password_hash, role::text as role_text,
|
||||
storage_quota_bytes, storage_used_bytes,
|
||||
SELECT
|
||||
id, username, email, password_hash, role::text as role_text,
|
||||
storage_quota_bytes, storage_used_bytes,
|
||||
created_at, updated_at, last_login_at, active,
|
||||
oidc_provider, oidc_subject
|
||||
oidc_provider, oidc_subject, image
|
||||
FROM auth.users
|
||||
WHERE role::text = $1
|
||||
ORDER BY created_at DESC
|
||||
@@ -535,6 +564,7 @@ impl UserRepository for UserPgRepository {
|
||||
row.get("active"),
|
||||
row.get("oidc_provider"),
|
||||
row.get("oidc_subject"),
|
||||
row.get("image"),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
@@ -566,11 +596,11 @@ impl UserRepository for UserPgRepository {
|
||||
) -> UserRepositoryResult<User> {
|
||||
let row = sqlx::query(
|
||||
r#"
|
||||
SELECT
|
||||
id, username, email, password_hash, role::text as role_text,
|
||||
storage_quota_bytes, storage_used_bytes,
|
||||
SELECT
|
||||
id, username, email, password_hash, role::text as role_text,
|
||||
storage_quota_bytes, storage_used_bytes,
|
||||
created_at, updated_at, last_login_at, active,
|
||||
oidc_provider, oidc_subject
|
||||
oidc_provider, oidc_subject, image
|
||||
FROM auth.users
|
||||
WHERE oidc_provider = $1 AND oidc_subject = $2
|
||||
"#,
|
||||
@@ -601,6 +631,7 @@ impl UserRepository for UserPgRepository {
|
||||
row.get("active"),
|
||||
row.get("oidc_provider"),
|
||||
row.get("oidc_subject"),
|
||||
row.get("image"),
|
||||
))
|
||||
}
|
||||
|
||||
|
||||
@@ -67,6 +67,7 @@ struct IdTokenClaims {
|
||||
name: Option<String>,
|
||||
groups: Option<Vec<String>>,
|
||||
nonce: Option<String>,
|
||||
picture: Option<String>,
|
||||
// Standard JWT fields
|
||||
#[allow(dead_code)]
|
||||
iss: Option<String>,
|
||||
@@ -90,6 +91,7 @@ struct UserInfoResponse {
|
||||
preferred_username: Option<String>,
|
||||
name: Option<String>,
|
||||
groups: Option<Vec<String>>,
|
||||
picture: Option<String>,
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
@@ -460,6 +462,7 @@ impl OidcServicePort for OidcService {
|
||||
preferred_username: claims.preferred_username,
|
||||
name: claims.name,
|
||||
groups: claims.groups.unwrap_or_default(),
|
||||
picture: claims.picture,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -511,6 +514,7 @@ impl OidcServicePort for OidcService {
|
||||
preferred_username: info.preferred_username,
|
||||
name: info.name,
|
||||
groups: info.groups.unwrap_or_default(),
|
||||
picture: info.picture,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user