aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorm0g3r <87276771+m0g3r@users.noreply.github.com>2026-08-18 18:16:48 +0200
committerGitHub <noreply@github.com>2026-08-18 18:16:48 +0200
commit46be43ad245d8f01026bf08f7d3a57c8c726a826 (patch)
tree97113344faba948e8638100b5615798ce37da4ad
parent3fe35fcbc1f7d2677e9c8d7be324db0d6f2a1f63 (diff)
Prevent orphaned user permissions and preferences (#17643)
Prevent orphaned user permissions and preferences
-rw-r--r--CONTRIBUTORS.md1
-rw-r--r--Jellyfin.Server.Implementations/Users/UserManager.cs2
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/Users/UserManagerProfileImageTests.cs23
3 files changed, 26 insertions, 0 deletions
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index f6a725853d..b3bd573215 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -238,6 +238,7 @@
- [elio42](https://github.com/elio42)
- [rwebster85](https://github.com/rwebster85)
- [Florin-Popescu](https://github.com/Florin-Popescu)
+ - [m0g3r](https://github.com/m0g3r)
- [martin-77](https://github.com/martin-77)
# Emby Contributors
diff --git a/Jellyfin.Server.Implementations/Users/UserManager.cs b/Jellyfin.Server.Implementations/Users/UserManager.cs
index 81408d9aa8..932ced547a 100644
--- a/Jellyfin.Server.Implementations/Users/UserManager.cs
+++ b/Jellyfin.Server.Implementations/Users/UserManager.cs
@@ -225,12 +225,14 @@ 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)
{
diff --git a/tests/Jellyfin.Server.Implementations.Tests/Users/UserManagerProfileImageTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Users/UserManagerProfileImageTests.cs
index cb714a4014..778b888735 100644
--- a/tests/Jellyfin.Server.Implementations.Tests/Users/UserManagerProfileImageTests.cs
+++ b/tests/Jellyfin.Server.Implementations.Tests/Users/UserManagerProfileImageTests.cs
@@ -1,5 +1,6 @@
using System;
using System.IO;
+using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Database.Implementations;
@@ -92,6 +93,28 @@ namespace Jellyfin.Server.Implementations.Tests.Users
}
[Fact]
+ public async Task UpdateUserAsync_DoesNotLeaveOrphanedPermissionsOrPreferences()
+ {
+ var user = await _userManager.CreateUserAsync("updateduser");
+ var permissionCount = user.Permissions.Count;
+ var preferenceCount = user.Preferences.Count;
+
+ user.LastActivityDate = DateTime.UtcNow;
+ await _userManager.UpdateUserAsync(user);
+ await _userManager.UpdateUserAsync(user);
+
+ await using var context = CreateDbContext();
+ Assert.Empty(await context.Permissions
+ .Where(permission => !permission.UserId.HasValue)
+ .ToListAsync(TestContext.Current.CancellationToken));
+ Assert.Empty(await context.Preferences
+ .Where(preference => !preference.UserId.HasValue)
+ .ToListAsync(TestContext.Current.CancellationToken));
+ Assert.Equal(permissionCount, await context.Permissions.CountAsync(TestContext.Current.CancellationToken));
+ Assert.Equal(preferenceCount, await context.Preferences.CountAsync(TestContext.Current.CancellationToken));
+ }
+
+ [Fact]
public async Task ClearProfileImageAsync_WhenInMemoryImageHasTemporaryKey_RemovesPersistedImage()
{
var user = await _userManager.CreateUserAsync("profileimageuser");