diff options
| author | Tim Eisele <Ghost_of_Stone@web.de> | 2026-08-20 18:35:26 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-08-20 18:35:26 +0200 |
| commit | fb50b4df8b5e6dec9567772aa8baecfbccb34124 (patch) | |
| tree | 1c773cd19a387a0722fa3e205faced0f88ff6320 /Jellyfin.Server.Implementations/Users/UserManager.cs | |
| parent | c70933a23f45379557c941ebe1b98abff0cf3cb2 (diff) | |
Stop user updates from orphaning permission and preference rows (#17645)
* Stop user updates from orphaning permission and preference rows
* Make UserId non-nullable
* Remove unnecessary ToList
* Update Jellyfin.Server.Implementations/Users/UserManager.cs
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
---------
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
Diffstat (limited to 'Jellyfin.Server.Implementations/Users/UserManager.cs')
| -rw-r--r-- | Jellyfin.Server.Implementations/Users/UserManager.cs | 69 |
1 files changed, 56 insertions, 13 deletions
diff --git a/Jellyfin.Server.Implementations/Users/UserManager.cs b/Jellyfin.Server.Implementations/Users/UserManager.cs index 932ced547a..fea6084267 100644 --- a/Jellyfin.Server.Implementations/Users/UserManager.cs +++ b/Jellyfin.Server.Implementations/Users/UserManager.cs @@ -225,19 +225,8 @@ namespace Jellyfin.Server.Implementations.Users ?? throw new ResourceNotFoundException(nameof(user.Id)); dbContext.Entry(dbUser).CurrentValues.SetValues(user); - dbContext.Permissions.RemoveRange(dbUser.Permissions); - dbUser.Permissions.Clear(); - foreach (var permission in user.Permissions) - { - dbUser.Permissions.Add(new Permission(permission.Kind, permission.Value)); - } - - dbContext.Preferences.RemoveRange(dbUser.Preferences); - dbUser.Preferences.Clear(); - foreach (var preference in user.Preferences) - { - dbUser.Preferences.Add(new Preference(preference.Kind, preference.Value)); - } + SyncPermissions(dbUser, user.Permissions); + SyncPreferences(dbUser, user.Preferences); dbUser.AccessSchedules.Clear(); foreach (var accessSchedule in user.AccessSchedules) @@ -271,6 +260,60 @@ namespace Jellyfin.Server.Implementations.Users } } + private static void SyncPermissions(User dbUser, ICollection<Permission> source) + { + var incoming = new Dictionary<PermissionKind, bool>(); + foreach (var permission in source) + { + incoming[permission.Kind] = permission.Value; + } + + foreach (var existing in dbUser.Permissions) + { + if (incoming.Remove(existing.Kind, out var value)) + { + // EF only marks the row modified if the value actually differs, so an update that + // touches nothing but the user row - a session activity stamp - writes no children. + existing.Value = value; + } + else + { + dbUser.Permissions.Remove(existing); + } + } + + foreach (var (kind, value) in incoming) + { + dbUser.Permissions.Add(new Permission(kind, value)); + } + } + + private static void SyncPreferences(User dbUser, ICollection<Preference> source) + { + var incoming = new Dictionary<PreferenceKind, string>(); + foreach (var preference in source) + { + incoming[preference.Kind] = preference.Value; + } + + foreach (var existing in dbUser.Preferences) + { + if (incoming.Remove(existing.Kind, out var value)) + { + existing.Value = value; + } + else + { + dbUser.Preferences.Remove(existing); + } + } + + foreach (var (kind, value) in incoming) + { + dbUser.Preferences.Add(new Preference(kind, value)); + } + } + internal async Task<User> CreateUserInternalAsync(string name, JellyfinDbContext dbContext) { // TODO: Remove after user item data is migrated. |
