erp-platform/api/src/Kurs.Platform.HttpApi.Host/Identity/PlatformSignInManager.cs
Sedat ÖZTÜRK 8cc8ed07f9 Düzenleme
2025-08-11 09:34:44 +03:00

201 lines
6.5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<bool> PreSignInCheckAsync(IdentityUser user);
}
public class PlatformSignInManager : AbpSignInManager, IPlatformSignInManager
{
private readonly IClock clock;
private readonly IRepository<IpRestriction, Guid> repositoryIp;
private readonly ITenantRepository tenantRepository;
private readonly IdentityUserManager userManager;
public PlatformSignInManager(
IdentityUserManager userManager,
IHttpContextAccessor contextAccessor,
IUserClaimsPrincipalFactory<IdentityUser> claimsFactory,
IOptions<IdentityOptions> optionsAccessor,
ILogger<SignInManager<IdentityUser>> logger,
IAuthenticationSchemeProvider schemes,
IUserConfirmation<IdentityUser> confirmation,
IOptions<AbpIdentityOptions> options,
ISettingProvider settingProvider,
IClock clock,
IRepository<IpRestriction, Guid> 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<bool> PreSignInCheckAsync(IdentityUser user)
{
var result = await PreSignInCheck(user);
return result?.Succeeded ?? true;
}
protected override async Task<SignInResult> 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;
}
/// <summary>
/// Tenant IsActive
/// </summary>
private async Task<bool> 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;
}
/// <summary>
/// Used to prevent login for additional scenarios;
/// Account Not Verified
/// </summary>
private async Task<bool> CanSignInVerifiedAsync(IdentityUser user)
{
var rva = await SettingProvider.GetAsync<bool>(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;
}
/// <summary>
/// Used to prevent login if end date is due
/// </summary>
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;
}
/// <summary>
/// Used to prevent login for allowed IPs;
/// IP Not Allowed
/// </summary>
private async Task<bool> 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;
}
}