|  | @@ -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);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 |