取消新增/Excel 导入档案时自动创建账号。
取消修改人员档案时同步登录账号。 Excel 人员模板恢复为不含“初始密码”。 登录页新增“学生首次登录?自助激活账号”入口。 公开激活地址:http://127.0.0.1:5255/activate
This commit is contained in:
@@ -1,144 +0,0 @@
|
||||
using Jiaowu.Api.Domain.Academic;
|
||||
using Jiaowu.Api.Domain.Identity;
|
||||
using Jiaowu.Api.Infrastructure.Persistence;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Jiaowu.Api.Infrastructure.Auth;
|
||||
|
||||
public sealed class PersonnelAccountService(
|
||||
AppDbContext db,
|
||||
UserManager<ApplicationUser> userManager)
|
||||
{
|
||||
public Task<PersonnelAccountResult> EnsureTeacherAccountAsync(
|
||||
Teacher teacher,
|
||||
string? initialPassword,
|
||||
CancellationToken cancellationToken) =>
|
||||
EnsureAccountAsync(
|
||||
teacher.Id,
|
||||
teacher.UserId,
|
||||
teacher.TeacherNumber,
|
||||
teacher.Name,
|
||||
teacher.CollegeId,
|
||||
teacher.Status == TeacherStatus.Active,
|
||||
SystemRoles.Teacher,
|
||||
initialPassword,
|
||||
userId => teacher.UserId = userId,
|
||||
cancellationToken);
|
||||
|
||||
public async Task<PersonnelAccountResult> EnsureStudentAccountAsync(
|
||||
Student student,
|
||||
string? initialPassword,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var collegeId = await db.AdministrativeClasses.AsNoTracking()
|
||||
.Where(x => x.Id == student.AdministrativeClassId)
|
||||
.Select(x => (Guid?)x.Major!.CollegeId)
|
||||
.FirstOrDefaultAsync(cancellationToken);
|
||||
if (!collegeId.HasValue)
|
||||
return PersonnelAccountResult.Failed("学生所在行政班或学院不存在。");
|
||||
|
||||
return await EnsureAccountAsync(
|
||||
student.Id,
|
||||
student.UserId,
|
||||
student.StudentNumber,
|
||||
student.Name,
|
||||
collegeId.Value,
|
||||
student.Status == StudentStatus.Active,
|
||||
SystemRoles.Student,
|
||||
initialPassword,
|
||||
userId => student.UserId = userId,
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
private async Task<PersonnelAccountResult> EnsureAccountAsync(
|
||||
Guid profileId,
|
||||
Guid? linkedUserId,
|
||||
string number,
|
||||
string displayName,
|
||||
Guid collegeId,
|
||||
bool isEnabled,
|
||||
string role,
|
||||
string? initialPassword,
|
||||
Action<Guid> linkProfile,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var normalizedNumber = number.Trim();
|
||||
ApplicationUser? user = null;
|
||||
if (linkedUserId.HasValue)
|
||||
user = await userManager.FindByIdAsync(linkedUserId.Value.ToString());
|
||||
user ??= await userManager.FindByNameAsync(normalizedNumber);
|
||||
|
||||
if (user is null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(initialPassword))
|
||||
return PersonnelAccountResult.Failed("请填写至少 8 位初始密码,以便同时创建登录账号。");
|
||||
|
||||
user = new ApplicationUser
|
||||
{
|
||||
UserName = normalizedNumber,
|
||||
DisplayName = displayName.Trim(),
|
||||
StaffNumber = normalizedNumber,
|
||||
CollegeId = collegeId,
|
||||
IsEnabled = isEnabled,
|
||||
LockoutEnabled = true
|
||||
};
|
||||
var createResult = await userManager.CreateAsync(user, initialPassword);
|
||||
if (!createResult.Succeeded) return Failed(createResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
var occupied = role == SystemRoles.Teacher
|
||||
? await db.Teachers.AsNoTracking().AnyAsync(
|
||||
x =>
|
||||
x.Id != profileId &&
|
||||
x.UserId == user.Id &&
|
||||
x.TeacherNumber != normalizedNumber,
|
||||
cancellationToken)
|
||||
: await db.Students.AsNoTracking().AnyAsync(
|
||||
x =>
|
||||
x.Id != profileId &&
|
||||
x.UserId == user.Id &&
|
||||
x.StudentNumber != normalizedNumber,
|
||||
cancellationToken);
|
||||
if (occupied)
|
||||
return PersonnelAccountResult.Failed($"登录账号“{normalizedNumber}”已关联其他人员档案。");
|
||||
|
||||
user.UserName = normalizedNumber;
|
||||
user.DisplayName = displayName.Trim();
|
||||
user.StaffNumber = normalizedNumber;
|
||||
user.CollegeId = collegeId;
|
||||
user.IsEnabled = isEnabled;
|
||||
var updateResult = await userManager.UpdateAsync(user);
|
||||
if (!updateResult.Succeeded) return Failed(updateResult);
|
||||
}
|
||||
|
||||
if (!await userManager.IsInRoleAsync(user, role))
|
||||
{
|
||||
var roleResult = await userManager.AddToRoleAsync(user, role);
|
||||
if (!roleResult.Succeeded) return Failed(roleResult);
|
||||
}
|
||||
|
||||
linkProfile(user.Id);
|
||||
await db.SaveChangesAsync(cancellationToken);
|
||||
return PersonnelAccountResult.Succeeded(user.Id, normalizedNumber);
|
||||
}
|
||||
|
||||
private static PersonnelAccountResult Failed(IdentityResult result) =>
|
||||
PersonnelAccountResult.Failed(string.Join(
|
||||
";",
|
||||
result.Errors.Select(x => x.Description)));
|
||||
}
|
||||
|
||||
public sealed record PersonnelAccountResult(
|
||||
bool Success,
|
||||
Guid? UserId,
|
||||
string? UserName,
|
||||
string? Error)
|
||||
{
|
||||
public static PersonnelAccountResult Succeeded(Guid userId, string userName) =>
|
||||
new(true, userId, userName, null);
|
||||
|
||||
public static PersonnelAccountResult Failed(string error) =>
|
||||
new(false, null, null, error);
|
||||
}
|
||||
Reference in New Issue
Block a user