| 
					
				 | 
			
			
				@@ -33,7 +33,7 @@ namespace Jellyfin.Server.Implementations.Users 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /// </summary> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     public class UserManager : IUserManager 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        private readonly JellyfinDbProvider _dbProvider; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        private readonly IDbContextFactory<JellyfinDb> _dbProvider; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         private readonly IEventManager _eventManager; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         private readonly ICryptoProvider _cryptoProvider; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         private readonly INetworkManager _networkManager; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -59,7 +59,7 @@ namespace Jellyfin.Server.Implementations.Users 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         /// <param name="imageProcessor">The image processor.</param> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         /// <param name="logger">The logger.</param> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         public UserManager( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            JellyfinDbProvider dbProvider, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            IDbContextFactory<JellyfinDb> dbProvider, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             IEventManager eventManager, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             ICryptoProvider cryptoProvider, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             INetworkManager networkManager, 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -83,7 +83,7 @@ namespace Jellyfin.Server.Implementations.Users 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             _defaultPasswordResetProvider = _passwordResetProviders.OfType<DefaultPasswordResetProvider>().First(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             _users = new ConcurrentDictionary<Guid, User>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            using var dbContext = _dbProvider.CreateContext(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            using var dbContext = _dbProvider.CreateDbContext(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             foreach (var user in dbContext.Users 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 .Include(user => user.Permissions) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 .Include(user => user.Preferences) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -139,31 +139,35 @@ namespace Jellyfin.Server.Implementations.Users 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 throw new ArgumentException("The new and old names must be different."); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            await using var dbContext = _dbProvider.CreateContext(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (await dbContext.Users 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                .AsQueryable() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                .AnyAsync(u => u.Username == newName && !u.Id.Equals(user.Id)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                .ConfigureAwait(false)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            var dbContext = await _dbProvider.CreateDbContextAsync().ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            await using (dbContext.ConfigureAwait(false)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                throw new ArgumentException(string.Format( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    CultureInfo.InvariantCulture, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    "A user with the name '{0}' already exists.", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    newName)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (await dbContext.Users 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        .AsQueryable() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        .AnyAsync(u => u.Username == newName && !u.Id.Equals(user.Id)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        .ConfigureAwait(false)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    throw new ArgumentException(string.Format( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        CultureInfo.InvariantCulture, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        "A user with the name '{0}' already exists.", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        newName)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.Username = newName; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                await UpdateUserInternalAsync(dbContext, user).ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.Username = newName; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            await UpdateUserAsync(user).ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             OnUserUpdated?.Invoke(this, new GenericEventArgs<User>(user)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         /// <inheritdoc/> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         public async Task UpdateUserAsync(User user) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            await using var dbContext = _dbProvider.CreateContext(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            dbContext.Users.Update(user); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            _users[user.Id] = user; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            await dbContext.SaveChangesAsync().ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            var dbContext = await _dbProvider.CreateDbContextAsync().ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            await using (dbContext.ConfigureAwait(false)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                await UpdateUserInternalAsync(dbContext, user).ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         internal async Task<User> CreateUserInternalAsync(string name, JellyfinDb dbContext) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -202,12 +206,15 @@ namespace Jellyfin.Server.Implementations.Users 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     name)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            await using var dbContext = _dbProvider.CreateContext(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            var newUser = await CreateUserInternalAsync(name, dbContext).ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            User newUser; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            var dbContext = await _dbProvider.CreateDbContextAsync().ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            await using (dbContext.ConfigureAwait(false)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                newUser = await CreateUserInternalAsync(name, dbContext).ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            dbContext.Users.Add(newUser); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            await dbContext.SaveChangesAsync().ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                dbContext.Users.Add(newUser); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                await dbContext.SaveChangesAsync().ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             await _eventManager.PublishAsync(new UserCreatedEventArgs(newUser)).ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -241,9 +248,13 @@ namespace Jellyfin.Server.Implementations.Users 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     nameof(userId)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            await using var dbContext = _dbProvider.CreateContext(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            dbContext.Users.Remove(user); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            await dbContext.SaveChangesAsync().ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            var dbContext = await _dbProvider.CreateDbContextAsync().ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            await using (dbContext.ConfigureAwait(false)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                dbContext.Users.Remove(user); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                await dbContext.SaveChangesAsync().ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             _users.Remove(userId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             await _eventManager.PublishAsync(new UserDeletedEventArgs(user)).ConfigureAwait(false); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -288,7 +299,7 @@ namespace Jellyfin.Server.Implementations.Users 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             user.EasyPassword = newPasswordSha1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             await UpdateUserAsync(user).ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            _eventManager.Publish(new UserPasswordChangedEventArgs(user)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            await _eventManager.PublishAsync(new UserPasswordChangedEventArgs(user)).ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         /// <inheritdoc/> 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -541,14 +552,17 @@ namespace Jellyfin.Server.Implementations.Users 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             _logger.LogWarning("No users, creating one with username {UserName}", defaultName); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            await using var dbContext = _dbProvider.CreateContext(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            var newUser = await CreateUserInternalAsync(defaultName, dbContext).ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            newUser.SetPermission(PermissionKind.IsAdministrator, true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            newUser.SetPermission(PermissionKind.EnableContentDeletion, true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            newUser.SetPermission(PermissionKind.EnableRemoteControlOfOtherUsers, true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            var dbContext = await _dbProvider.CreateDbContextAsync().ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            await using (dbContext.ConfigureAwait(false)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                var newUser = await CreateUserInternalAsync(defaultName, dbContext).ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                newUser.SetPermission(PermissionKind.IsAdministrator, true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                newUser.SetPermission(PermissionKind.EnableContentDeletion, true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                newUser.SetPermission(PermissionKind.EnableRemoteControlOfOtherUsers, true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            dbContext.Users.Add(newUser); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            await dbContext.SaveChangesAsync().ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                dbContext.Users.Add(newUser); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                await dbContext.SaveChangesAsync().ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         /// <inheritdoc/> 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -584,105 +598,111 @@ namespace Jellyfin.Server.Implementations.Users 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         /// <inheritdoc/> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         public async Task UpdateConfigurationAsync(Guid userId, UserConfiguration config) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            await using var dbContext = _dbProvider.CreateContext(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            var user = dbContext.Users 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                           .Include(u => u.Permissions) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                           .Include(u => u.Preferences) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                           .Include(u => u.AccessSchedules) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                           .Include(u => u.ProfileImage) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                           .FirstOrDefault(u => u.Id.Equals(userId)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                       ?? throw new ArgumentException("No user exists with given Id!"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.SubtitleMode = config.SubtitleMode; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.HidePlayedInLatest = config.HidePlayedInLatest; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.EnableLocalPassword = config.EnableLocalPassword; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.PlayDefaultAudioTrack = config.PlayDefaultAudioTrack; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.DisplayCollectionsView = config.DisplayCollectionsView; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.DisplayMissingEpisodes = config.DisplayMissingEpisodes; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.AudioLanguagePreference = config.AudioLanguagePreference; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.RememberAudioSelections = config.RememberAudioSelections; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.EnableNextEpisodeAutoPlay = config.EnableNextEpisodeAutoPlay; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.RememberSubtitleSelections = config.RememberSubtitleSelections; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.SubtitleLanguagePreference = config.SubtitleLanguagePreference; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.SetPreference(PreferenceKind.OrderedViews, config.OrderedViews); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.SetPreference(PreferenceKind.GroupedFolders, config.GroupedFolders); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.SetPreference(PreferenceKind.MyMediaExcludes, config.MyMediaExcludes); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.SetPreference(PreferenceKind.LatestItemExcludes, config.LatestItemsExcludes); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            dbContext.Update(user); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            _users[user.Id] = user; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            await dbContext.SaveChangesAsync().ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            var dbContext = await _dbProvider.CreateDbContextAsync().ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            await using (dbContext.ConfigureAwait(false)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                var user = dbContext.Users 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                               .Include(u => u.Permissions) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                               .Include(u => u.Preferences) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                               .Include(u => u.AccessSchedules) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                               .Include(u => u.ProfileImage) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                               .FirstOrDefault(u => u.Id.Equals(userId)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                           ?? throw new ArgumentException("No user exists with given Id!"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.SubtitleMode = config.SubtitleMode; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.HidePlayedInLatest = config.HidePlayedInLatest; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.EnableLocalPassword = config.EnableLocalPassword; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.PlayDefaultAudioTrack = config.PlayDefaultAudioTrack; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.DisplayCollectionsView = config.DisplayCollectionsView; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.DisplayMissingEpisodes = config.DisplayMissingEpisodes; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.AudioLanguagePreference = config.AudioLanguagePreference; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.RememberAudioSelections = config.RememberAudioSelections; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.EnableNextEpisodeAutoPlay = config.EnableNextEpisodeAutoPlay; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.RememberSubtitleSelections = config.RememberSubtitleSelections; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.SubtitleLanguagePreference = config.SubtitleLanguagePreference; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.SetPreference(PreferenceKind.OrderedViews, config.OrderedViews); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.SetPreference(PreferenceKind.GroupedFolders, config.GroupedFolders); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.SetPreference(PreferenceKind.MyMediaExcludes, config.MyMediaExcludes); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.SetPreference(PreferenceKind.LatestItemExcludes, config.LatestItemsExcludes); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                dbContext.Update(user); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                _users[user.Id] = user; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                await dbContext.SaveChangesAsync().ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         /// <inheritdoc/> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         public async Task UpdatePolicyAsync(Guid userId, UserPolicy policy) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            await using var dbContext = _dbProvider.CreateContext(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            var user = dbContext.Users 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                           .Include(u => u.Permissions) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                           .Include(u => u.Preferences) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                           .Include(u => u.AccessSchedules) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                           .Include(u => u.ProfileImage) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                           .FirstOrDefault(u => u.Id.Equals(userId)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                       ?? throw new ArgumentException("No user exists with given Id!"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            // The default number of login attempts is 3, but for some god forsaken reason it's sent to the server as "0" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            int? maxLoginAttempts = policy.LoginAttemptsBeforeLockout switch 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                -1 => null, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                0 => 3, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                _ => policy.LoginAttemptsBeforeLockout 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            var dbContext = await _dbProvider.CreateDbContextAsync().ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            await using (dbContext.ConfigureAwait(false)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                var user = dbContext.Users 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                               .Include(u => u.Permissions) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                               .Include(u => u.Preferences) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                               .Include(u => u.AccessSchedules) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                               .Include(u => u.ProfileImage) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                               .FirstOrDefault(u => u.Id.Equals(userId)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                           ?? throw new ArgumentException("No user exists with given Id!"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // The default number of login attempts is 3, but for some god forsaken reason it's sent to the server as "0" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                int? maxLoginAttempts = policy.LoginAttemptsBeforeLockout switch 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    -1 => null, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    0 => 3, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    _ => policy.LoginAttemptsBeforeLockout 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.MaxParentalAgeRating = policy.MaxParentalRating; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.EnableUserPreferenceAccess = policy.EnableUserPreferenceAccess; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.RemoteClientBitrateLimit = policy.RemoteClientBitrateLimit; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.AuthenticationProviderId = policy.AuthenticationProviderId; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.PasswordResetProviderId = policy.PasswordResetProviderId; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.InvalidLoginAttemptCount = policy.InvalidLoginAttemptCount; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.LoginAttemptsBeforeLockout = maxLoginAttempts; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.MaxActiveSessions = policy.MaxActiveSessions; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.SyncPlayAccess = policy.SyncPlayAccess; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.SetPermission(PermissionKind.IsAdministrator, policy.IsAdministrator); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.SetPermission(PermissionKind.IsHidden, policy.IsHidden); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.SetPermission(PermissionKind.IsDisabled, policy.IsDisabled); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.SetPermission(PermissionKind.EnableSharedDeviceControl, policy.EnableSharedDeviceControl); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.SetPermission(PermissionKind.EnableRemoteAccess, policy.EnableRemoteAccess); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.SetPermission(PermissionKind.EnableLiveTvManagement, policy.EnableLiveTvManagement); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.SetPermission(PermissionKind.EnableLiveTvAccess, policy.EnableLiveTvAccess); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.SetPermission(PermissionKind.EnableMediaPlayback, policy.EnableMediaPlayback); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.SetPermission(PermissionKind.EnableAudioPlaybackTranscoding, policy.EnableAudioPlaybackTranscoding); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.SetPermission(PermissionKind.EnableVideoPlaybackTranscoding, policy.EnableVideoPlaybackTranscoding); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.SetPermission(PermissionKind.EnableContentDeletion, policy.EnableContentDeletion); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.SetPermission(PermissionKind.EnableContentDownloading, policy.EnableContentDownloading); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.SetPermission(PermissionKind.EnableSyncTranscoding, policy.EnableSyncTranscoding); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.SetPermission(PermissionKind.EnableMediaConversion, policy.EnableMediaConversion); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.SetPermission(PermissionKind.EnableAllChannels, policy.EnableAllChannels); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.SetPermission(PermissionKind.EnableAllDevices, policy.EnableAllDevices); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.SetPermission(PermissionKind.EnableAllFolders, policy.EnableAllFolders); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.SetPermission(PermissionKind.EnableRemoteControlOfOtherUsers, policy.EnableRemoteControlOfOtherUsers); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.SetPermission(PermissionKind.EnablePlaybackRemuxing, policy.EnablePlaybackRemuxing); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.SetPermission(PermissionKind.ForceRemoteSourceTranscoding, policy.ForceRemoteSourceTranscoding); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.SetPermission(PermissionKind.EnablePublicSharing, policy.EnablePublicSharing); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.AccessSchedules.Clear(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            foreach (var policyAccessSchedule in policy.AccessSchedules) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                user.AccessSchedules.Add(policyAccessSchedule); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            // TODO: fix this at some point 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.SetPreference(PreferenceKind.BlockUnratedItems, policy.BlockUnratedItems ?? Array.Empty<UnratedItem>()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.SetPreference(PreferenceKind.BlockedTags, policy.BlockedTags); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.SetPreference(PreferenceKind.EnabledChannels, policy.EnabledChannels); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.SetPreference(PreferenceKind.EnabledDevices, policy.EnabledDevices); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.SetPreference(PreferenceKind.EnabledFolders, policy.EnabledFolders); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            user.SetPreference(PreferenceKind.EnableContentDeletionFromFolders, policy.EnableContentDeletionFromFolders); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            dbContext.Update(user); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            _users[user.Id] = user; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            await dbContext.SaveChangesAsync().ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.MaxParentalAgeRating = policy.MaxParentalRating; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.EnableUserPreferenceAccess = policy.EnableUserPreferenceAccess; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.RemoteClientBitrateLimit = policy.RemoteClientBitrateLimit; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.AuthenticationProviderId = policy.AuthenticationProviderId; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.PasswordResetProviderId = policy.PasswordResetProviderId; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.InvalidLoginAttemptCount = policy.InvalidLoginAttemptCount; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.LoginAttemptsBeforeLockout = maxLoginAttempts; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.MaxActiveSessions = policy.MaxActiveSessions; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.SyncPlayAccess = policy.SyncPlayAccess; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.SetPermission(PermissionKind.IsAdministrator, policy.IsAdministrator); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.SetPermission(PermissionKind.IsHidden, policy.IsHidden); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.SetPermission(PermissionKind.IsDisabled, policy.IsDisabled); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.SetPermission(PermissionKind.EnableSharedDeviceControl, policy.EnableSharedDeviceControl); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.SetPermission(PermissionKind.EnableRemoteAccess, policy.EnableRemoteAccess); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.SetPermission(PermissionKind.EnableLiveTvManagement, policy.EnableLiveTvManagement); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.SetPermission(PermissionKind.EnableLiveTvAccess, policy.EnableLiveTvAccess); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.SetPermission(PermissionKind.EnableMediaPlayback, policy.EnableMediaPlayback); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.SetPermission(PermissionKind.EnableAudioPlaybackTranscoding, policy.EnableAudioPlaybackTranscoding); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.SetPermission(PermissionKind.EnableVideoPlaybackTranscoding, policy.EnableVideoPlaybackTranscoding); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.SetPermission(PermissionKind.EnableContentDeletion, policy.EnableContentDeletion); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.SetPermission(PermissionKind.EnableContentDownloading, policy.EnableContentDownloading); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.SetPermission(PermissionKind.EnableSyncTranscoding, policy.EnableSyncTranscoding); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.SetPermission(PermissionKind.EnableMediaConversion, policy.EnableMediaConversion); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.SetPermission(PermissionKind.EnableAllChannels, policy.EnableAllChannels); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.SetPermission(PermissionKind.EnableAllDevices, policy.EnableAllDevices); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.SetPermission(PermissionKind.EnableAllFolders, policy.EnableAllFolders); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.SetPermission(PermissionKind.EnableRemoteControlOfOtherUsers, policy.EnableRemoteControlOfOtherUsers); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.SetPermission(PermissionKind.EnablePlaybackRemuxing, policy.EnablePlaybackRemuxing); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.SetPermission(PermissionKind.ForceRemoteSourceTranscoding, policy.ForceRemoteSourceTranscoding); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.SetPermission(PermissionKind.EnablePublicSharing, policy.EnablePublicSharing); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.AccessSchedules.Clear(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                foreach (var policyAccessSchedule in policy.AccessSchedules) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    user.AccessSchedules.Add(policyAccessSchedule); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // TODO: fix this at some point 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.SetPreference(PreferenceKind.BlockUnratedItems, policy.BlockUnratedItems ?? Array.Empty<UnratedItem>()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.SetPreference(PreferenceKind.BlockedTags, policy.BlockedTags); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.SetPreference(PreferenceKind.EnabledChannels, policy.EnabledChannels); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.SetPreference(PreferenceKind.EnabledDevices, policy.EnabledDevices); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.SetPreference(PreferenceKind.EnabledFolders, policy.EnabledFolders); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                user.SetPreference(PreferenceKind.EnableContentDeletionFromFolders, policy.EnableContentDeletionFromFolders); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                dbContext.Update(user); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                _users[user.Id] = user; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                await dbContext.SaveChangesAsync().ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         /// <inheritdoc/> 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -693,9 +713,13 @@ namespace Jellyfin.Server.Implementations.Users 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            await using var dbContext = _dbProvider.CreateContext(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            dbContext.Remove(user.ProfileImage); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            await dbContext.SaveChangesAsync().ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            var dbContext = await _dbProvider.CreateDbContextAsync().ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            await using (dbContext.ConfigureAwait(false)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                dbContext.Remove(user.ProfileImage); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                await dbContext.SaveChangesAsync().ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             user.ProfileImage = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             _users[user.Id] = user; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -859,5 +883,12 @@ namespace Jellyfin.Server.Implementations.Users 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             await UpdateUserAsync(user).ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        private async Task UpdateUserInternalAsync(JellyfinDb dbContext, User user) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            dbContext.Users.Update(user); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            _users[user.Id] = user; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            await dbContext.SaveChangesAsync().ConfigureAwait(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 |