Update Reset method to not rely on externally available entity

This commit is contained in:
JPVenson
2026-05-01 11:05:33 +00:00
parent 1ae45519d0
commit 511f90d6d3
5 changed files with 23 additions and 29 deletions

View File

@@ -151,7 +151,7 @@ public class StartupController : BaseJellyfinApiController
if (!string.IsNullOrEmpty(startupUserDto.Password))
{
await _userManager.ChangePassword(user, startupUserDto.Password).ConfigureAwait(false);
await _userManager.ChangePassword(user.Id, startupUserDto.Password).ConfigureAwait(false);
}
return NoContent();

View File

@@ -288,7 +288,7 @@ public class UserController : BaseJellyfinApiController
if (request.ResetPassword)
{
await _userManager.ResetPassword(user).ConfigureAwait(false);
await _userManager.ResetPassword(user.Id).ConfigureAwait(false);
}
else
{
@@ -306,7 +306,7 @@ public class UserController : BaseJellyfinApiController
}
}
await _userManager.ChangePassword(user, request.NewPw ?? string.Empty).ConfigureAwait(false);
await _userManager.ChangePassword(user.Id, request.NewPw ?? string.Empty).ConfigureAwait(false);
var currentToken = User.GetToken();
@@ -545,7 +545,7 @@ public class UserController : BaseJellyfinApiController
// no need to authenticate password for new user
if (request.Password is not null)
{
await _userManager.ChangePassword(newUser, request.Password).ConfigureAwait(false);
await _userManager.ChangePassword(newUser.Id, request.Password).ConfigureAwait(false);
}
var result = _userManager.GetUserDto(newUser, HttpContext.GetNormalizedRemoteIP().ToString());

View File

@@ -74,7 +74,7 @@ namespace Jellyfin.Server.Implementations.Users
var resetUser = userManager.GetUserByName(spr.UserName)
?? throw new ResourceNotFoundException($"User with a username of {spr.UserName} not found");
await userManager.ChangePassword(resetUser, pin).ConfigureAwait(false);
await userManager.ChangePassword(resetUser.Id, pin).ConfigureAwait(false);
usersReset.Add(resetUser.Username);
File.Delete(resetFile);
}

View File

@@ -335,43 +335,37 @@ namespace Jellyfin.Server.Implementations.Users
}
/// <inheritdoc/>
public Task ResetPassword(User user)
public Task ResetPassword(Guid userId)
{
return ChangePassword(user, string.Empty);
return ChangePassword(userId, string.Empty);
}
/// <inheritdoc/>
public async Task ChangePassword(User user, string newPassword)
public async Task ChangePassword(Guid userId, string newPassword)
{
ArgumentNullException.ThrowIfNull(user);
if (user.HasPermission(PermissionKind.IsAdministrator) && string.IsNullOrWhiteSpace(newPassword))
{
throw new ArgumentException("Admin user passwords must not be empty", nameof(newPassword));
}
using (await _userLock.LockAsync(user.Id).ConfigureAwait(false))
User dbUser = null!;
using (await _userLock.LockAsync(userId).ConfigureAwait(false))
{
var dbContext = await _dbProvider.CreateDbContextAsync().ConfigureAwait(false);
await using (dbContext.ConfigureAwait(false))
{
// Reload the user inside the lock to get the current RowVersion.
// The incoming user may have been loaded with AsNoTracking() before this
// lock was acquired; a concurrent write (e.g. a login updating LastLoginDate)
// could have incremented RowVersion in the database in the meantime.
// Since we now hold the per-user lock, no other write can race with us, so
// the freshly loaded RowVersion is guaranteed to be current.
var dbUser = await UserQuery(dbContext)
dbUser = await UserQuery(dbContext)
.AsTracking()
.FirstOrDefaultAsync(u => u.Id == user.Id)
.FirstOrDefaultAsync(u => u.Id == userId)
.ConfigureAwait(false)
?? throw new ResourceNotFoundException(nameof(user.Id));
?? throw new ResourceNotFoundException(nameof(userId));
if (dbUser.HasPermission(PermissionKind.IsAdministrator) && string.IsNullOrWhiteSpace(newPassword))
{
throw new ArgumentException("Admin user passwords must not be empty", nameof(newPassword));
}
await GetAuthenticationProvider(dbUser).ChangePassword(dbUser, newPassword).ConfigureAwait(false);
await dbContext.SaveChangesAsync().ConfigureAwait(false);
}
}
await _eventManager.PublishAsync(new UserPasswordChangedEventArgs(user)).ConfigureAwait(false);
await _eventManager.PublishAsync(new UserPasswordChangedEventArgs(dbUser)).ConfigureAwait(false);
}
/// <inheritdoc/>

View File

@@ -99,17 +99,17 @@ namespace MediaBrowser.Controller.Library
/// <summary>
/// Resets the password.
/// </summary>
/// <param name="user">The user.</param>
/// <param name="userId">The users Id.</param>
/// <returns>Task.</returns>
Task ResetPassword(User user);
Task ResetPassword(Guid userId);
/// <summary>
/// Changes the password.
/// </summary>
/// <param name="user">The user.</param>
/// <param name="userId">The users id.</param>
/// <param name="newPassword">New password to use.</param>
/// <returns>Awaitable task.</returns>
Task ChangePassword(User user, string newPassword);
Task ChangePassword(Guid userId, string newPassword);
/// <summary>
/// Gets the user dto.