Merge pull request #673 from EdouardVanbelle/fix/user-preferences
fix(user-pref): permit edition of user prefs for OIDC account
This commit is contained in:
@@ -406,6 +406,23 @@ pub struct UpdateProfileDto {
|
||||
pub ui_preferences: Option<serde_json::Value>,
|
||||
}
|
||||
|
||||
impl UpdateProfileDto {
|
||||
/// True when the patch touches at least one field whose source of
|
||||
/// truth is an external identity provider — currently `given_name`
|
||||
/// and `family_name`. For OIDC-managed users the auth service
|
||||
/// refuses the whole patch when this returns true (IdP pushes those
|
||||
/// fields on every login; editing them here would be silently
|
||||
/// overwritten). Local-only fields — `ui_preferences`,
|
||||
/// `notify_on_share`, `preferred_locale`, the claim-once `username`
|
||||
/// (never re-synced from the IdP) — return `false` so an OIDC user
|
||||
/// can still change their view mode, share-mail opt-in, locale,
|
||||
/// etc. Add future IdP-authoritative fields (e.g. `email`, `image`)
|
||||
/// here if they land in this DTO.
|
||||
pub fn touches_idp_managed_fields(&self) -> bool {
|
||||
self.given_name.is_some() || self.family_name.is_some()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||
pub struct AuthResponseDto {
|
||||
pub user: UserDto,
|
||||
|
||||
@@ -2446,7 +2446,13 @@ impl AuthApplicationService {
|
||||
) -> Result<UserDto, DomainError> {
|
||||
let mut user = self.user_storage.get_user_by_id(caller_id).await?;
|
||||
|
||||
if user.is_oidc_user() {
|
||||
// For OIDC-managed users, refuse the patch ONLY when it touches
|
||||
// a field the IdP owns (currently `given_name` / `family_name`
|
||||
// — see `UpdateProfileDto::touches_idp_managed_fields`). Local-
|
||||
// only fields (ui_preferences, notify_on_share, preferred_locale,
|
||||
// claim-once username) stay editable — those are personal
|
||||
// OxiCloud preferences, not identity data pushed by the IdP.
|
||||
if user.is_oidc_user() && dto.touches_idp_managed_fields() {
|
||||
tracing::info!(
|
||||
target: "audit",
|
||||
event = "auth.profile_update_rejected",
|
||||
@@ -2457,7 +2463,7 @@ impl AuthApplicationService {
|
||||
return Err(DomainError::new(
|
||||
ErrorKind::AccessDenied,
|
||||
"User",
|
||||
"Your profile is managed by the identity provider and \
|
||||
"Your name is managed by the identity provider and \
|
||||
cannot be edited here. Update it at the IdP — changes \
|
||||
will propagate on your next sign-in.",
|
||||
));
|
||||
|
||||
Reference in New Issue
Block a user