修复Mysql

This commit is contained in:
2026-07-26 10:19:46 +08:00 Unverified
parent 634ef69a27
commit 72297aa23f
31 changed files with 1642 additions and 1192 deletions
+117 -65
View File
@@ -25,8 +25,14 @@ public sealed class UsersController(
.OrderBy(x => x.UserName)
.Select(x => new
{
x.Id, x.UserName, x.DisplayName, x.StaffNumber,
x.CollegeId, x.IsEnabled, x.LastLoginAt, x.CreatedAt
x.Id,
x.UserName,
x.DisplayName,
x.StaffNumber,
x.CollegeId,
x.IsEnabled,
x.LastLoginAt,
x.CreatedAt
})
.ToListAsync(cancellationToken);
@@ -36,8 +42,14 @@ public sealed class UsersController(
var identityUser = await userManager.FindByIdAsync(user.Id.ToString());
result.Add(new
{
user.Id, user.UserName, user.DisplayName, user.StaffNumber,
user.CollegeId, user.IsEnabled, user.LastLoginAt, user.CreatedAt,
user.Id,
user.UserName,
user.DisplayName,
user.StaffNumber,
user.CollegeId,
user.IsEnabled,
user.LastLoginAt,
user.CreatedAt,
Roles = identityUser is null
? []
: await userManager.GetRolesAsync(identityUser)
@@ -54,38 +66,50 @@ public sealed class UsersController(
.ToListAsync(cancellationToken));
[HttpPost]
public async Task<ActionResult> Create(CreateUserRequest request)
public async Task<ActionResult> Create(
CreateUserRequest request,
CancellationToken cancellationToken)
{
var roles = request.Roles.Distinct(StringComparer.OrdinalIgnoreCase).ToArray();
var invalidRoles = ValidateRoles(roles);
if (invalidRoles is not null) return invalidRoles;
var staffNumber = Normalize(request.StaffNumber);
var profiles = await ResolveProfilesAsync(staffNumber, roles);
if (profiles.Error is not null) return profiles.Error;
return await db.ExecuteInRetriableTransactionAsync<ActionResult>(
async transaction =>
{
db.ChangeTracker.Clear();
var profiles = await ResolveProfilesAsync(staffNumber, roles);
if (profiles.Error is not null) return profiles.Error;
var user = new ApplicationUser
{
UserName = request.UserName.Trim(),
DisplayName = request.DisplayName.Trim(),
StaffNumber = staffNumber,
CollegeId = request.CollegeId,
LockoutEnabled = true,
IsEnabled = true
};
await using var transaction = await db.Database.BeginTransactionAsync();
var result = await userManager.CreateAsync(user, request.Password);
if (!result.Succeeded)
return IdentityValidationProblem(result);
var user = new ApplicationUser
{
UserName = request.UserName.Trim(),
DisplayName = request.DisplayName.Trim(),
StaffNumber = staffNumber,
CollegeId = request.CollegeId,
LockoutEnabled = true,
IsEnabled = true
};
var result = await userManager.CreateAsync(user, request.Password);
if (!result.Succeeded)
return IdentityValidationProblem(result);
result = await userManager.AddToRolesAsync(user, roles);
if (!result.Succeeded)
return IdentityValidationProblem(result);
result = await userManager.AddToRolesAsync(user, roles);
if (!result.Succeeded)
return IdentityValidationProblem(result);
if (profiles.Teacher is not null) profiles.Teacher.UserId = user.Id;
if (profiles.Student is not null) profiles.Student.UserId = user.Id;
await db.SaveChangesAsync();
await transaction.CommitAsync();
return CreatedAtAction(nameof(GetUsers), new { id = user.Id }, new { user.Id });
if (profiles.Teacher is not null)
profiles.Teacher.UserId = user.Id;
if (profiles.Student is not null)
profiles.Student.UserId = user.Id;
await db.SaveChangesAsync(cancellationToken);
await transaction.CommitAsync(cancellationToken);
return CreatedAtAction(
nameof(GetUsers),
new { id = user.Id },
new { user.Id });
},
cancellationToken);
}
[HttpPut("{id:guid}/status")]
@@ -103,51 +127,79 @@ public sealed class UsersController(
}
[HttpPut("{id:guid}/roles")]
public async Task<IActionResult> SetRoles(Guid id, SetRolesRequest request)
public async Task<IActionResult> SetRoles(
Guid id,
SetRolesRequest request,
CancellationToken cancellationToken)
{
var user = await userManager.FindByIdAsync(id.ToString());
if (user is null) return NotFound();
var roles = request.Roles.Distinct(StringComparer.OrdinalIgnoreCase).ToArray();
var invalidRoles = ValidateRoles(roles);
if (invalidRoles is not null) return invalidRoles;
var staffNumber = Normalize(request.StaffNumber);
var profiles = await ResolveProfilesAsync(staffNumber, roles, user.Id);
if (profiles.Error is not null) return profiles.Error;
return await db.ExecuteInRetriableTransactionAsync<IActionResult>(
async transaction =>
{
db.ChangeTracker.Clear();
var user = await userManager.FindByIdAsync(id.ToString());
if (user is null) return NotFound();
var profiles = await ResolveProfilesAsync(
staffNumber,
roles,
user.Id);
if (profiles.Error is not null) return profiles.Error;
var existing = await userManager.GetRolesAsync(user);
if (User.FindFirstValue(ClaimTypes.NameIdentifier) == id.ToString() &&
existing.Contains(SystemRoles.SuperAdmin) &&
!roles.Contains(SystemRoles.SuperAdmin, StringComparer.OrdinalIgnoreCase))
{
return ValidationProblem("不能移除当前账号的超级管理员角色。");
}
var existing = await userManager.GetRolesAsync(user);
if (User.FindFirstValue(ClaimTypes.NameIdentifier) == id.ToString() &&
existing.Contains(SystemRoles.SuperAdmin) &&
!roles.Contains(
SystemRoles.SuperAdmin,
StringComparer.OrdinalIgnoreCase))
{
return ValidationProblem(
"不能移除当前账号的超级管理员角色。");
}
await using var transaction = await db.Database.BeginTransactionAsync();
user.StaffNumber = staffNumber;
user.CollegeId = request.CollegeId;
var updateResult = await userManager.UpdateAsync(user);
if (!updateResult.Succeeded) return IdentityValidationProblem(updateResult);
var removeResult = await userManager.RemoveFromRolesAsync(
user,
existing.Except(roles, StringComparer.OrdinalIgnoreCase));
if (!removeResult.Succeeded) return IdentityValidationProblem(removeResult);
var addResult = await userManager.AddToRolesAsync(
user,
roles.Except(existing, StringComparer.OrdinalIgnoreCase));
if (!addResult.Succeeded) return IdentityValidationProblem(addResult);
user.StaffNumber = staffNumber;
user.CollegeId = request.CollegeId;
var updateResult = await userManager.UpdateAsync(user);
if (!updateResult.Succeeded)
return IdentityValidationProblem(updateResult);
var removeResult = await userManager.RemoveFromRolesAsync(
user,
existing.Except(roles, StringComparer.OrdinalIgnoreCase));
if (!removeResult.Succeeded)
return IdentityValidationProblem(removeResult);
var addResult = await userManager.AddToRolesAsync(
user,
roles.Except(existing, StringComparer.OrdinalIgnoreCase));
if (!addResult.Succeeded)
return IdentityValidationProblem(addResult);
var linkedTeachers = await db.Teachers.Where(x => x.UserId == id).ToListAsync();
var linkedStudents = await db.Students.Where(x => x.UserId == id).ToListAsync();
if (!roles.Contains(SystemRoles.Teacher, StringComparer.OrdinalIgnoreCase))
foreach (var teacher in linkedTeachers) teacher.UserId = null;
if (!roles.Contains(SystemRoles.Student, StringComparer.OrdinalIgnoreCase))
foreach (var student in linkedStudents) student.UserId = null;
if (profiles.Teacher is not null) profiles.Teacher.UserId = id;
if (profiles.Student is not null) profiles.Student.UserId = id;
await db.SaveChangesAsync();
await transaction.CommitAsync();
return NoContent();
var linkedTeachers = await db.Teachers
.Where(x => x.UserId == id)
.ToListAsync();
var linkedStudents = await db.Students
.Where(x => x.UserId == id)
.ToListAsync();
if (!roles.Contains(
SystemRoles.Teacher,
StringComparer.OrdinalIgnoreCase))
foreach (var teacher in linkedTeachers)
teacher.UserId = null;
if (!roles.Contains(
SystemRoles.Student,
StringComparer.OrdinalIgnoreCase))
foreach (var student in linkedStudents)
student.UserId = null;
if (profiles.Teacher is not null)
profiles.Teacher.UserId = id;
if (profiles.Student is not null)
profiles.Student.UserId = id;
await db.SaveChangesAsync(cancellationToken);
await transaction.CommitAsync(cancellationToken);
return NoContent();
},
cancellationToken);
}
private ActionResult? ValidateRoles(IReadOnlyCollection<string> roles)