201 lines
6.5 KiB
C#
201 lines
6.5 KiB
C#
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;
|
||
}
|
||
|
||
}
|