using Dlhis.Entity.Basic.Entity; using Dlhis.Entity.Sys.Entities; using Dlhis.Sys.Identity.Request; using Dlhis.Sys.Identity.Response; using Kurisu.AspNetCore.Authentication.Abstractions; using Kurisu.AspNetCore.DataAccess.Dto; using Kurisu.AspNetCore.DataAccess.SqlSugar.Extensions; using Kurisu.AspNetCore.DataAccess.SqlSugar.Services; using Kurisu.AspNetCore.Utils.Extensions; using Microsoft.AspNetCore.Identity; using SqlSugar; namespace Dlhis.Sys.Identity.Services.Implements; public class UserService : IUserService { private readonly IDbContext _dbContext; private readonly ICurrentUser _currentUser; private readonly ITenantService _tenantService; private readonly IDbContext _identityDbContext; public UserService(IDbContext dbContext, ICurrentUser currentUser, ITenantService tenantService) { _dbContext = dbContext; _currentUser = currentUser; _tenantService = tenantService; _identityDbContext = dbContext.ChangeDb("identity"); } public async Task> GetPageAsync(UserPageRequest request) { var tenant = _currentUser.GetStringTenantId(); var roleUserCodes = await _identityDbContext.Queryable() .LeftJoin((x, u) => x.UserId == u.Id) .Select((x, u) => u.UserName) .ToListAsync(); var userCodes = await _dbContext.Queryable().Where(x => x.Factory == tenant).Select(x => x.Code).ToListAsync(); var userLeaveCodes = await _dbContext.Queryable() .Where(x => x.Factory == tenant) .Where(x => roleUserCodes.Contains(x.Code)) .Where(x => SqlFunc.Subqueryable().Where(p => p.Code == x.Code).NotAny()) .Select(x => x.Code) .ToListAsync(); var expectUserIds = await _identityDbContext.Queryable().Where(x => userLeaveCodes.Contains(x.UserName)).Select(x => x.Id).ToListAsync(); var userIds = await _identityDbContext.Queryable().Where(x => x.TenantCode == tenant).Select(x => x.UserId).Distinct().ToListAsync(); var page = await _identityDbContext.Queryable() .LeftJoin((x, ur) => x.Id == ur.UserId) .LeftJoin((x, ur, r) => ur.RoleId == r.Id) .LeftJoin((x, ur, r, c) => x.Id == c.UserId && c.ClaimType == "preferred_username") .Where(x => x.UserName != "admin") .WhereIF(request.IsOperator, (x, ur, r, c) => !SqlFunc.IsNullOrEmpty(r.Name)) .WhereIF(!request.IsOperator, (x, ur, r, c) => SqlFunc.IsNullOrEmpty(r.Name)) .WhereIF(request.Search.IsPresent(), (x, ur, r, c) => x.UserName == request.Search || x.Email == request.Search || x.PhoneNumber == request.Search || c.ClaimValue == request.Search ) .Where(x => !expectUserIds.Contains(x.Id) && (userIds.Contains(x.Id) || userCodes.Contains(x.UserName))) .Select((x, ur, r, c) => new UserResponse { Id = x.Id, RoleId = ur.RoleId, Role = r.Name, OperatorName = c.ClaimValue, }, true) .ToPageListAsync(request); return page; } public async Task ResetAccessFailedCountAsync(int id) { var user = await _identityDbContext.Queryable().Where(x => x.Id == id).FirstAsync(); user.ThrowIfNull("用户不存在,无法重置"); user.AccessFailedCount = 0; await _identityDbContext.UpdateAsync(user); } public async Task> GetUsersAsync() { var users = await _identityDbContext.Queryable() .Where(x => x.UserName != "admin") .Select() .ToListAsync(); return users; } public async Task GetUserByIdAsync(int id) { var user = await _identityDbContext.Queryable() .LeftJoin((x, ur) => x.Id == ur.UserId) .LeftJoin((x, ur, r) => ur.RoleId == r.Id) .LeftJoin((x, ur, r, c) => x.Id == c.UserId && c.ClaimType == "preferred_username") .Where(x => x.Id == id) .Select((x, ur, r, c) => new UserResponse { Id = x.Id, RoleId = ur.RoleId, Role = r.Name, OperatorName = c.ClaimValue, }, true) .SingleAsync(); return user; } public async Task UploadUserAvatarAsync(UserAvatarUploadRequest request) { var user = await _identityDbContext.Queryable().Where(x => x.Id == request.UserId).Select().FirstAsync(); } public async Task UnlockAsync(int userId) { var user = await _identityDbContext.Queryable().SingleAsync(x => x.Id == userId); user.ThrowIfNull("用户不存在"); user.LockoutEnd = null; await _identityDbContext.UpdateAsync(user); } public async Task> GetUserByIdsAsync(List ids) { return await _identityDbContext.Queryable() .LeftJoin((x, ur) => x.Id == ur.UserId) .LeftJoin((x, ur, r) => ur.RoleId == r.Id) .LeftJoin((x, ur, r, c) => x.Id == c.UserId && c.ClaimType == "preferred_username") .Where(x => ids.Contains(x.Id)) .Select((x, ur, r, c) => new UserResponse { Id = x.Id, RoleId = ur.RoleId, Role = r.Name, OperatorName = c.ClaimValue, }, true) .ToListAsync(); } public async Task CreateUserAsync(UserCreateRequest request) { var hasher = new PasswordHasher(); var user = new UserEntity { UserName = request.Username, NormalizedUserName = request.Username.ToUpper(), ConcurrencyStamp = Guid.NewGuid().ToString(), SecurityStamp = Guid.NewGuid().ToString(), LockoutEnabled = true }; request.Password = hasher.HashPassword(user, request.Password); user.PasswordHash = request.Password; var id = (int)await _identityDbContext.InsertReturnIdentityAsync(user); await _identityDbContext.InsertAsync(request.Tenants.Select(x => new UserTenantEntity { TenantCode = x, UserId = id }).ToList()); if (request.Name.IsPresent()) { await _identityDbContext.InsertAsync(new UserClaimEntity { ClaimType = "preferred_username", ClaimValue = request.Name, UserId = id }); } } public async Task ResetLoginTenantAsync(UserResetLoginTenantRequest request) { var tenants = await _tenantService.GetMyTenantsAsync(); tenants.All(x => x.Code != request.Tenant).ThrowIfTrue($"不可切换登陆:{request.Tenant}"); var userId = _currentUser.GetIntSubjectId(); await _identityDbContext.Updateable() .SetColumns(x => x.ClaimValue == request.Tenant) .Where(x => x.UserId == userId) .Where(x => x.ClaimType == "tenant") .ExecuteCommandAsync(); var tenantStr = tenants.Select(x => x.Code).Join(","); await _identityDbContext.Updateable() .SetColumns(x => x.ClaimValue == tenantStr) .Where(x => x.UserId == userId) .Where(x => x.ClaimType == "tenants") .ExecuteCommandAsync(); } /// public async Task ResetPasswordAsync(UserResetPasswordRequest request) { request.Password ??= "123456"; var user = await _identityDbContext.Queryable().SingleAsync(x => x.Id == request.UserId); if (user != null) { var hasher = new PasswordHasher(); var password = hasher.HashPassword(user, request.Password); user.PasswordHash = password; await _identityDbContext.UpdateAsync(user); } } }