using System; using System.Collections.Generic; using System.Data.Common; using System.Linq; using System.Threading.Tasks; using Kurs.Platform.Entities; using Kurs.Platform.Extensions; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Volo.Abp.Domain.Repositories; using Volo.Abp.Identity; using Volo.Abp.Identity.AspNetCore; using Volo.Abp.Settings; using Volo.Abp.TenantManagement; using Volo.Abp.Timing; using IdentityUser = Volo.Abp.Identity.IdentityUser; using SignInResult = Microsoft.AspNetCore.Identity.SignInResult; namespace Kurs.Platform.Identity; public interface IPlatformSignInManager { Task PreSignInCheckAsync(IdentityUser user); } public class PlatformSignInManager : AbpSignInManager, IPlatformSignInManager { private readonly IClock clock; private readonly IRepository repositoryIp; private readonly ITenantRepository tenantRepository; private readonly IdentityUserManager userManager; public PlatformSignInManager( IdentityUserManager userManager, IHttpContextAccessor contextAccessor, IUserClaimsPrincipalFactory claimsFactory, IOptions optionsAccessor, ILogger> logger, IAuthenticationSchemeProvider schemes, IUserConfirmation confirmation, IOptions options, ISettingProvider settingProvider, IClock clock, IRepository repositoryIp, ITenantRepository tenantRepository ) : base( userManager, contextAccessor, claimsFactory, optionsAccessor, logger, schemes, confirmation, options, settingProvider) { this.clock = clock; this.repositoryIp = repositoryIp; this.tenantRepository = tenantRepository; this.userManager = userManager; } public async Task PreSignInCheckAsync(IdentityUser user) { var result = await PreSignInCheck(user); return result?.Succeeded ?? true; } protected override async Task PreSignInCheck(IdentityUser user) { var result = await base.PreSignInCheck(user); if (result == null) { if (!await CanSignInVerifiedAsync(user)) { return new PlatformSignInResult() { IsNotAllowed_NotVerified = true }; } if (!CanSignInEndDate(user)) { return new PlatformSignInResult() { IsNotAllowed_LoginEndDateDue = true }; } if (!await CanSignInIpAsync(user)) { return new PlatformSignInResult() { IsNotAllowed_NotAllowedIp = true }; } if (!await IsTenantActiveAsync(user)) { return new PlatformSignInResult() { IsNotAllowed_TenantIsPassive = true }; } } else { // Bu kontrol modules\identity\src\Volo.Abp.Identity.AspNetCore\Volo\Abp\Identity\AspNetCore\AbpSignInManager.cs // içinde zaten yapılıyor fakat her senaryoya NotAllowed diyor, bizim ayrıt etmemiz gerektiği için tekrar yapıyoruz. if (user.ShouldChangePasswordOnNextLogin) { return new PlatformSignInResult() { ShouldChangePasswordOnNextLogin = true }; } if (await userManager.ShouldPeriodicallyChangePasswordAsync(user)) { return new PlatformSignInResult() { ShouldChangePasswordPeriodic = true }; } } return result; } /// /// Tenant IsActive /// private async Task IsTenantActiveAsync(IdentityUser user) { if (!user.TenantId.HasValue) { return true; } var tenant = await tenantRepository.FindAsync(user.TenantId.Value); if (tenant == null) { return false; } if (!tenant.GetIsActive()) { Logger.LogWarning(PlatformEventIds.UserCannotSignInTenantIsPassive, "Tenant is inactive."); return false; } return true; } /// /// Used to prevent login for additional scenarios; /// Account Not Verified /// private async Task CanSignInVerifiedAsync(IdentityUser user) { var rva = await SettingProvider.GetAsync(PlatformConsts.AbpIdentity.Profile.General.RequireVerifiedAccount); if (rva && !user.GetIsVerified()) { Logger.LogWarning(PlatformEventIds.UserCannotSignInWithoutVerifiedAccount, "User cannot sign in without a verified account."); return false; } return true; } /// /// Used to prevent login if end date is due /// private bool CanSignInEndDate(IdentityUser user) { var endDate = user.GetLoginEndDate(); if (endDate != null && clock.Now > endDate) { //izin yok Logger.LogWarning(PlatformEventIds.UserCannotSignInLoginEndDateDue, "User cannot sign in, login end date is due."); return false; } //izin ver return true; } /// /// Used to prevent login for allowed IPs; /// IP Not Allowed /// private async Task CanSignInIpAsync(IdentityUser user) { // User, Role, Global Restrictions var roles = await UserManager.GetRolesAsync(user); //var roleIds = roleManager.Roles.Where(a => roles.Contains(a.Name)).Select(a => a.Id).ToArray(); var restrictions = await repositoryIp.GetListAsync(a => (a.ResourceType == "User" && a.ResourceId == user.UserName) || (a.ResourceType == "Role" && roles.Contains(a.ResourceId)) || (a.ResourceType == "Global")); if (!restrictions.IsNullOrEmpty()) { var ip = Context.GetRemoteIPAddress(); var ipString = ip?.ToString(); if (ip == null || (ip != null && !restrictions.Select(a => a.IP).Any(a => a == ipString))) { //izin yok Logger.LogWarning(PlatformEventIds.UserCannotSignInWithoutAllowedIp, "User cannot sign in without an allowed IP."); return false; } } //izin ver return true; } }