using System; using System.Collections.Generic; using System.Linq; using System.Security.Claims; using System.Threading.Tasks; using Sozsoft.Platform.BlobStoring; using Sozsoft.Platform.Entities; using Sozsoft.Platform.Extensions; using Sozsoft.Platform.Identity.Dto; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using OpenIddict.Abstractions; using Volo.Abp.Application.Services; using Volo.Abp.Domain.Repositories; using Volo.Abp.Guids; using Volo.Abp.Identity; using Volo.Abp.PermissionManagement; namespace Sozsoft.Platform.Identity; [Authorize] public class PlatformIdentityAppService : ApplicationService { public IIdentityUserAppService IdentityUserAppService { get; } private readonly IIdentityUserRepository identityUserRepository; private readonly IIdentityRoleRepository identityRoleRepository; private readonly IIdentitySessionRepository identitySessionRepository; private readonly IOpenIddictTokenManager openIddictTokenManager; private readonly IPermissionGrantRepository permissionGrantRepository; public IRepository permissionRepository { get; } public IRepository branchRepository { get; } public IRepository branchUsersRepository { get; } public IRepository claimTypesRepository { get; } public IGuidGenerator guidGenerator { get; } public IdentityUserManager UserManager { get; set; } public IRepository workHourRepository { get; } public IRepository departmentRepository { get; } public IRepository jobPositionRepository { get; } public BlobManager BlobCdnManager { get; } public PlatformIdentityAppService( IIdentityUserAppService identityUserAppService, IIdentityUserRepository identityUserRepository, IIdentityRoleRepository identityRoleRepository, IIdentitySessionRepository identitySessionRepository, IOpenIddictTokenManager openIddictTokenManager, IPermissionGrantRepository permissionGrantRepository, IRepository permissionRepository, IRepository branchRepository, IRepository branchUsersRepository, IRepository claimTypesRepository, IRepository workHourRepository, IRepository departmentRepository, IRepository jobPositionRepository, BlobManager blobCdnManager, IGuidGenerator guidGenerator ) { this.IdentityUserAppService = identityUserAppService; this.identityUserRepository = identityUserRepository; this.identityRoleRepository = identityRoleRepository; this.identitySessionRepository = identitySessionRepository; this.openIddictTokenManager = openIddictTokenManager; this.permissionGrantRepository = permissionGrantRepository; this.workHourRepository = workHourRepository; this.departmentRepository = departmentRepository; this.jobPositionRepository = jobPositionRepository; this.BlobCdnManager = blobCdnManager; this.permissionRepository = permissionRepository; this.branchRepository = branchRepository; this.branchUsersRepository = branchUsersRepository; this.claimTypesRepository = claimTypesRepository; this.guidGenerator = guidGenerator; } public async Task GetByIdAsync(Guid UserId) { var user = await identityUserRepository.GetAsync(UserId); var userRoleNames = (await IdentityUserAppService.GetRolesAsync(user.Id)).Items.Select(r => r.Name).ToList(); var roles = ObjectMapper.Map, AssignedRoleViewModel[]>((await IdentityUserAppService.GetAssignableRolesAsync()).Items); foreach (var role in roles) { if (userRoleNames.Contains(role.Name)) { role.IsAssigned = true; } } var currentTenantId = CurrentTenant.Id.HasValue ? CurrentTenant.Id : null; //Branch var queryBranch = await branchUsersRepository.GetQueryableAsync(); var branchUsers = queryBranch.Where(a => a.UserId == UserId).Select(r => r.BranchId).ToList(); var branchList = await branchRepository.GetListAsync(a => a.TenantId == currentTenantId); var branches = branchList.Select(branch => new AssignedBranchViewModel { Id = branch.Id, Name = branch.Name, IsAssigned = branchUsers.Contains(branch.Id) }) .ToArray(); //Claim var claimUsers = user.Claims; var claimList = await claimTypesRepository.GetListAsync(); var claims = claimList.Select(claim => { var userClaim = claimUsers.FirstOrDefault(c => c.ClaimType == claim.Name); return new AssignedClaimViewModel { Id = userClaim?.Id ?? Guid.Empty, ClaimType = claim.Name, ClaimValue = userClaim?.ClaimValue, IsAssigned = userClaim != null }; }).ToArray(); var workHourList = await workHourRepository.GetListAsync(); var workHours = workHourList.Select(workHour => new AssignedWorkHourViewModel { Id = workHour.Id, Name = workHour.Name, IsAssigned = workHourList.Contains(workHour) }).ToArray(); var departmentList = await departmentRepository.GetListAsync(); var departments = (await departmentRepository.GetListAsync()).Select(department => new AssignedDepartmentViewModel { Id = department.Id, Name = department.Name, IsAssigned = departmentList.Contains(department) }).ToArray(); var jobPositionList = await jobPositionRepository.GetListAsync(); var jobPositions = (await jobPositionRepository.GetListAsync()).Select(jobPosition => new AssignedJobPoisitionViewModel { Id = jobPosition.Id, Name = jobPosition.Name, DepartmentId = jobPosition.DepartmentId, IsAssigned = jobPositionList.Contains(jobPosition) }).ToArray(); return new UserInfoViewModel() { Id = user.Id, TenantId = user.TenantId, UserName = user.UserName, Name = user.Name, Surname = user.Surname, Roles = roles, Branches = branches, Departments = departments, JobPositions = jobPositions, Claims = claims, WorkHours = workHours, Email = user.Email, PhoneNumber = user.PhoneNumber, IsActive = user.IsActive, TwoFactorEnabled = user.TwoFactorEnabled, IsVerified = (bool)user.ExtraProperties["IsVerified"], userRoleNames = userRoleNames, LockoutEnabled = user.LockoutEnabled, LockoutEnd = user.LockoutEnd, LockUser = user.LockoutEnabled && user.LockoutEnd.HasValue && user.LockoutEnd.Value.DateTime > DateTime.Now, LoginEndDate = user.GetLoginEndDate(), ConcurrencyStamp = user.ConcurrencyStamp, LastPasswordChangeTime = user.LastPasswordChangeTime, EmailConfirmed = user.EmailConfirmed, PhoneNumberConfirmed = user.PhoneNumberConfirmed, AccessFailedCount = user.AccessFailedCount, ShouldChangePasswordOnNextLogin = user.ShouldChangePasswordOnNextLogin, CreationTime = user.CreationTime, LastModificationTime = user.LastModificationTime, }.MapIdentityExtraProperties(user); } public async Task UpdatePermissionAsync(UserInfoViewModel UserInfo) { var roles = UserInfo.Roles.Where(r => r.IsAssigned).Select(r => r.Name).ToArray(); var user = await UserManager.GetByIdAsync(UserInfo.Id); await UserManager.SetRolesAsync(user, roles); //Braches bu kısımda güncelleniyor. var existingBranches = await branchUsersRepository.GetListAsync(x => x.UserId == user.Id); foreach (var item in existingBranches) { await branchUsersRepository.DeleteAsync(item); } // 2. Yeni atamaları ekle var assignedBranchIds = UserInfo.Branches .Where(b => b.IsAssigned) .Select(b => b.Id) .ToList(); foreach (var branchId in assignedBranchIds) { var branchUser = new BranchUsers { UserId = user.Id, BranchId = branchId }; await branchUsersRepository.InsertAsync(branchUser); } } public async Task UpdateLockoutAsync(UserInfoViewModel UserInfo) { var user = await UserManager.GetByIdAsync(UserInfo.Id); if (UserInfo.LockUser) { await UserManager.SetLockoutEnabledAsync(user, true); await UserManager.SetLockoutEndDateAsync(user, DateTime.Now.AddYears(1000)); } else { await UserManager.SetLockoutEndDateAsync(user, null); } //Admin Verification user.SetIsVerified(UserInfo.IsVerified); //Two Factor Enabled await UserManager.SetTwoFactorEnabledAsync(user, UserInfo.TwoFactorEnabled); //LoginEndDate user.SetLoginEndDate(UserInfo.LoginEndDate); user.SetWorkHour(UserInfo.WorkHour); user.SetIsActive(UserInfo.IsActive); user.SetLastPasswordChangeTime(UserInfo.LastPasswordChangeTime); user.SetEmailConfirmed(UserInfo.EmailConfirmed); user.SetPhoneNumberConfirmed(UserInfo.PhoneNumberConfirmed); user.SetShouldChangePasswordOnNextLogin(UserInfo.ShouldChangePasswordOnNextLogin); if (UserInfo.AccessFailedCount == 0 && user.AccessFailedCount > 0) { await UserManager.ResetAccessFailedCountAsync(user); } await UserManager.SetLockoutEnabledAsync(user, UserInfo.LockoutEnabled); await UserManager.UpdateAsync(user); } public async Task UpdateUserAsync(UserInfoViewModel UserInfo) { var user = await UserManager.GetByIdAsync(UserInfo.Id); user.Name = UserInfo.Name; user.Surname = UserInfo.Surname; user.SetPhoneNumber(UserInfo.PhoneNumber, user.PhoneNumberConfirmed); user.SetRocketUsername(UserInfo.RocketUsername); user.SetWorkHour(UserInfo.WorkHour); user.SetDepartmentId(UserInfo.DepartmentId); user.SetJobPositionId(UserInfo.JobPositionId); user.SetNationality(UserInfo.Nationality); user.SetSskNo(UserInfo.SskNo); user.SetHireDate(UserInfo.HireDate); user.SetTerminationDate(UserInfo.TerminationDate); user.SetIdentityNumber(UserInfo.IdentityNumber); user.SetSerialNo(UserInfo.SerialNo); user.SetProvince(UserInfo.Province); user.SetDistrict(UserInfo.District); user.SetVillage(UserInfo.Village); user.SetVolumeNo(UserInfo.VolumeNo); user.SetFamilySequenceNo(UserInfo.FamilySequenceNo); user.SetSequenceNo(UserInfo.SequenceNo); user.SetIssuedPlace(UserInfo.IssuedPlace); user.SetIssuedDate(UserInfo.IssuedDate); user.SetBirthPlace(UserInfo.BirthPlace); user.SetBirthDate(UserInfo.BirthDate); user.SetFatherName(UserInfo.FatherName); user.SetMotherName(UserInfo.MotherName); user.SetMaritalStatus(UserInfo.MaritalStatus); user.SetMarriageDate(UserInfo.MarriageDate); user.SetHomeAddress(UserInfo.HomeAddress); user.SetEducationLevel(UserInfo.EducationLevel); user.SetGraduationSchool(UserInfo.GraduationSchool); user.SetBloodType(UserInfo.BloodType); await UserManager.UpdateAsync(user); } [Authorize(IdentityPermissions.Users.Update)] public async Task UpdateAvatarAsync([FromForm] UserAvatarUpdateInput input) { var user = await UserManager.GetByIdAsync(input.UserId); var fileName = $"{user.Id}.jpg"; if (input.Avatar is null || input.Avatar.ContentLength == 0) { await BlobCdnManager.DeleteAsync(BlobContainerNames.Avatar, fileName); } else { await BlobCdnManager.SaveAsync(BlobContainerNames.Avatar, fileName, input.Avatar.GetStream()); } } public async Task> GetPermissionList() { var list = await permissionRepository.GetListAsync(); return [.. list.OrderBy(p => p.Name)]; } public async Task> GetPermissionGrantedUsersAsync(string permissionName) { if (string.IsNullOrWhiteSpace(permissionName)) { return []; } permissionName = permissionName.Trim(); var permissions = (await permissionRepository.GetListAsync()) .Where(p => p.Name == permissionName || p.ParentName == permissionName) .OrderBy(p => p.ParentName == null ? 0 : 1) .ThenBy(p => p.Name) .Take(200) .ToList(); var permissionNames = permissions.Select(p => p.Name).ToHashSet(); if (permissionNames.Count == 0) { return []; } var grants = (await permissionGrantRepository.GetListAsync()) .Where(g => permissionNames.Contains(g.Name) && (g.ProviderName == "R" || g.ProviderName == "U")) .ToList(); var roleNames = grants .Where(g => g.ProviderName == "R") .Select(g => g.ProviderKey) .Where(key => !string.IsNullOrWhiteSpace(key)) .Distinct() .ToList(); var roles = roleNames.Count == 0 ? [] : (await identityRoleRepository.GetListAsync()) .Where(r => roleNames.Contains(r.Name)) .ToList(); var roleIdByName = roles.ToDictionary(r => r.Name, r => r.Id); var roleNameById = roles.ToDictionary(r => r.Id, r => r.Name); var roleIds = roleIdByName.Values.ToHashSet(); var directUserIds = grants .Where(g => g.ProviderName == "U" && Guid.TryParse(g.ProviderKey, out _)) .Select(g => Guid.Parse(g.ProviderKey)) .ToHashSet(); var users = (await identityUserRepository.GetListAsync(includeDetails: true)) .Where(user => directUserIds.Contains(user.Id) || (user.Roles?.Any(userRole => roleIds.Contains(userRole.RoleId)) ?? false)) .ToList(); return permissions.Select(permission => { var permissionGrants = grants.Where(g => g.Name == permission.Name).ToList(); var permissionRoleNames = permissionGrants .Where(g => g.ProviderName == "R") .Select(g => g.ProviderKey) .Where(roleName => !string.IsNullOrWhiteSpace(roleName) && roleIdByName.ContainsKey(roleName)) .Distinct() .OrderBy(roleName => roleName) .ToList(); var permissionRoleIds = permissionRoleNames.Select(roleName => roleIdByName[roleName]).ToHashSet(); var permissionDirectUserIds = permissionGrants .Where(g => g.ProviderName == "U" && Guid.TryParse(g.ProviderKey, out _)) .Select(g => Guid.Parse(g.ProviderKey)) .ToHashSet(); var permissionUsers = users .Where(user => permissionDirectUserIds.Contains(user.Id) || (user.Roles?.Any(userRole => permissionRoleIds.Contains(userRole.RoleId)) ?? false)) .Select(user => { var userRoleNames = (user.Roles ?? []) .Where(userRole => permissionRoleIds.Contains(userRole.RoleId)) .Select(userRole => roleNameById[userRole.RoleId]) .Distinct() .OrderBy(roleName => roleName) .ToList(); return new PermissionGrantedUserDto { TenantId = user.TenantId, Id = user.Id, UserName = user.UserName, Name = user.Name, Surname = user.Surname, FullName = $"{user.Name} {user.Surname}".Trim(), Email = user.Email, IsActive = user.IsActive, IsDirectGrant = permissionDirectUserIds.Contains(user.Id), RoleNames = userRoleNames }; }) .OrderBy(user => user.UserName) .ToList(); return new PermissionGrantedUsersDto { Name = permission.Name, ParentName = permission.ParentName, DisplayName = permission.DisplayName, IsEnabled = permission.IsEnabled, RoleNames = permissionRoleNames, Users = permissionUsers }; }).ToList(); } public async Task CreateClaimUserAsync(UserClaimModel input) { var user = await identityUserRepository.GetAsync(input.UserId); user.AddClaim(guidGenerator, new Claim(input.ClaimType, input.ClaimValue)); } public async Task DeleteClaimUser(Guid id, Guid userId) { var user = await identityUserRepository.GetAsync(userId); var claim = user.Claims.FirstOrDefault(a => a.Id == id); user.Claims.Remove(claim); } public async Task KickUserAsync(Guid userId) { using (CurrentTenant.Change(CurrentTenant.Id)) { // 1. AbpSessions temizle var sessions = await identitySessionRepository.GetListAsync(userId: userId); foreach (var session in sessions) await identitySessionRepository.DeleteAsync(session); // 2. OpenIddict tokenlarını revoke et await foreach (var token in openIddictTokenManager.FindBySubjectAsync(userId.ToString())) await openIddictTokenManager.TryRevokeAsync(token); } } }