IsNotAllowed_BranchLimit
This commit is contained in:
parent
4ae697600b
commit
6dae9c4e94
7 changed files with 78 additions and 8 deletions
|
|
@ -58,6 +58,10 @@ public static class PlatformSignInResultExtensions
|
||||||
{
|
{
|
||||||
return PlatformConsts.UserCannotSignInErrors.LoginNotAllowed_WorkHour;
|
return PlatformConsts.UserCannotSignInErrors.LoginNotAllowed_WorkHour;
|
||||||
}
|
}
|
||||||
|
if (resultP.IsNotAllowed_BranchLimit)
|
||||||
|
{
|
||||||
|
return PlatformConsts.UserCannotSignInErrors.LoginNotAllowed_BranchLimit;
|
||||||
|
}
|
||||||
if (resultP.IsNotAllowed_ConcurrentUserLimit)
|
if (resultP.IsNotAllowed_ConcurrentUserLimit)
|
||||||
{
|
{
|
||||||
return PlatformConsts.UserCannotSignInErrors.LoginNotAllowed_ConcurrentUserLimit;
|
return PlatformConsts.UserCannotSignInErrors.LoginNotAllowed_ConcurrentUserLimit;
|
||||||
|
|
|
||||||
|
|
@ -162,6 +162,7 @@ public static class PlatformConsts
|
||||||
public const string TenantIsPassive = GroupName + ".TenantIsPassive";
|
public const string TenantIsPassive = GroupName + ".TenantIsPassive";
|
||||||
public const string LoginNotAllowed_WorkHour = GroupName + ".LoginNotAllowed_WorkHour";
|
public const string LoginNotAllowed_WorkHour = GroupName + ".LoginNotAllowed_WorkHour";
|
||||||
public const string ConcurrentUserLimitError = GroupName + ".ConcurrentUserLimitError";
|
public const string ConcurrentUserLimitError = GroupName + ".ConcurrentUserLimitError";
|
||||||
|
public const string BranchLimitError = GroupName + ".BranchLimitError";
|
||||||
public const string CaptchaWrongCode = GroupName + ".CaptchaWrongCode";
|
public const string CaptchaWrongCode = GroupName + ".CaptchaWrongCode";
|
||||||
public const string TwoFactorWrongCode = GroupName + ".TwoFactorWrongCode";
|
public const string TwoFactorWrongCode = GroupName + ".TwoFactorWrongCode";
|
||||||
public const string SignOut = GroupName + ".SignOut";
|
public const string SignOut = GroupName + ".SignOut";
|
||||||
|
|
@ -548,6 +549,7 @@ public static class PlatformConsts
|
||||||
public static string LoginNotAllowed_TenantIsPassive { get; set; } = "UserCannotSignInTenantIsPassive";
|
public static string LoginNotAllowed_TenantIsPassive { get; set; } = "UserCannotSignInTenantIsPassive";
|
||||||
public static string LoginNotAllowed_TenantNotFound { get; set; } = "UserCannotSignInTenantNotFound";
|
public static string LoginNotAllowed_TenantNotFound { get; set; } = "UserCannotSignInTenantNotFound";
|
||||||
public static string LoginNotAllowed_WorkHour { get; set; } = "UserCannotSignInWorkHour";
|
public static string LoginNotAllowed_WorkHour { get; set; } = "UserCannotSignInWorkHour";
|
||||||
|
public static string LoginNotAllowed_BranchLimit { get; set; } = "UserCannotSignInBranchLimit";
|
||||||
public static string LoginNotAllowed_ConcurrentUserLimit { get; set; } = "UserCannotSignInConcurrentUserLimit";
|
public static string LoginNotAllowed_ConcurrentUserLimit { get; set; } = "UserCannotSignInConcurrentUserLimit";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,8 @@ public class PlatformSignInResult : SignInResult
|
||||||
|
|
||||||
public bool IsNotAllowed_WorkHour { get; set; }
|
public bool IsNotAllowed_WorkHour { get; set; }
|
||||||
|
|
||||||
|
public bool IsNotAllowed_BranchLimit { get; set; }
|
||||||
|
|
||||||
public bool IsNotAllowed_ConcurrentUserLimit { get; set; }
|
public bool IsNotAllowed_ConcurrentUserLimit { get; set; }
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
|
|
@ -42,6 +44,7 @@ public class PlatformSignInResult : SignInResult
|
||||||
ShouldChangePasswordPeriodic ? "ShouldChangePasswordPeriodic" :
|
ShouldChangePasswordPeriodic ? "ShouldChangePasswordPeriodic" :
|
||||||
IsNotAllowed_TenantIsPassive ? "NotAllowed_TenantIsPassive" :
|
IsNotAllowed_TenantIsPassive ? "NotAllowed_TenantIsPassive" :
|
||||||
IsNotAllowed_WorkHour ? "NotAllowed_WorkHour" :
|
IsNotAllowed_WorkHour ? "NotAllowed_WorkHour" :
|
||||||
|
IsNotAllowed_BranchLimit ? "NotAllowed_BranchLimit" :
|
||||||
IsNotAllowed_ConcurrentUserLimit ? "NotAllowed_ConcurrentUserLimit" :
|
IsNotAllowed_ConcurrentUserLimit ? "NotAllowed_ConcurrentUserLimit" :
|
||||||
base.ToString();
|
base.ToString();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,11 @@ public class PlatformLoginResult : AbpLoginResult
|
||||||
PResult = PlatformLoginResultType.NotAllowedWorkHour;
|
PResult = PlatformLoginResultType.NotAllowedWorkHour;
|
||||||
Description = L[PlatformConsts.AbpIdentity.User.LoginNotAllowed_WorkHour];
|
Description = L[PlatformConsts.AbpIdentity.User.LoginNotAllowed_WorkHour];
|
||||||
}
|
}
|
||||||
|
else if (resultP.IsNotAllowed_BranchLimit)
|
||||||
|
{
|
||||||
|
PResult = PlatformLoginResultType.BranchLimit;
|
||||||
|
Description = L[PlatformConsts.AbpIdentity.User.BranchLimitError];
|
||||||
|
}
|
||||||
else if (resultP.IsNotAllowed_ConcurrentUserLimit)
|
else if (resultP.IsNotAllowed_ConcurrentUserLimit)
|
||||||
{
|
{
|
||||||
PResult = PlatformLoginResultType.ConcurrentUserLimit;
|
PResult = PlatformLoginResultType.ConcurrentUserLimit;
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ public enum PlatformLoginResultType : byte
|
||||||
ShowCaptcha,
|
ShowCaptcha,
|
||||||
TenantIsPassive,
|
TenantIsPassive,
|
||||||
NotAllowedWorkHour,
|
NotAllowedWorkHour,
|
||||||
|
BranchLimit,
|
||||||
ConcurrentUserLimit
|
ConcurrentUserLimit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data.Common;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Sozsoft.Platform.Entities;
|
using Sozsoft.Platform.Entities;
|
||||||
|
|
@ -33,6 +32,8 @@ public interface IPlatformSignInManager
|
||||||
public class PlatformSignInManager : AbpSignInManager, IPlatformSignInManager
|
public class PlatformSignInManager : AbpSignInManager, IPlatformSignInManager
|
||||||
{
|
{
|
||||||
private const string UserLicenseProductName = "Public.products.userLicense";
|
private const string UserLicenseProductName = "Public.products.userLicense";
|
||||||
|
private const string BranchLicenseProductName = "Public.products.branchHosting";
|
||||||
|
|
||||||
private readonly IClock clock;
|
private readonly IClock clock;
|
||||||
private readonly IRepository<IpRestriction, Guid> repositoryIp;
|
private readonly IRepository<IpRestriction, Guid> repositoryIp;
|
||||||
private readonly IRepository<WorkHour, Guid> repositoryWorkHour;
|
private readonly IRepository<WorkHour, Guid> repositoryWorkHour;
|
||||||
|
|
@ -42,6 +43,7 @@ public class PlatformSignInManager : AbpSignInManager, IPlatformSignInManager
|
||||||
private readonly ICurrentTenant currentTenant;
|
private readonly ICurrentTenant currentTenant;
|
||||||
private readonly IUnitOfWorkManager unitOfWorkManager;
|
private readonly IUnitOfWorkManager unitOfWorkManager;
|
||||||
private readonly IRepository<Order, Guid> orderRepository;
|
private readonly IRepository<Order, Guid> orderRepository;
|
||||||
|
private readonly IRepository<Branch, Guid> branchRepository;
|
||||||
|
|
||||||
public PlatformSignInManager(
|
public PlatformSignInManager(
|
||||||
IdentityUserManager userManager,
|
IdentityUserManager userManager,
|
||||||
|
|
@ -60,7 +62,8 @@ public class PlatformSignInManager : AbpSignInManager, IPlatformSignInManager
|
||||||
IIdentitySessionRepository identitySessionRepository,
|
IIdentitySessionRepository identitySessionRepository,
|
||||||
ICurrentTenant currentTenant,
|
ICurrentTenant currentTenant,
|
||||||
IUnitOfWorkManager unitOfWorkManager,
|
IUnitOfWorkManager unitOfWorkManager,
|
||||||
IRepository<Order, Guid> orderRepository
|
IRepository<Order, Guid> orderRepository,
|
||||||
|
IRepository<Branch, Guid> branchRepository
|
||||||
) : base(
|
) : base(
|
||||||
userManager,
|
userManager,
|
||||||
contextAccessor,
|
contextAccessor,
|
||||||
|
|
@ -81,6 +84,7 @@ public class PlatformSignInManager : AbpSignInManager, IPlatformSignInManager
|
||||||
this.currentTenant = currentTenant;
|
this.currentTenant = currentTenant;
|
||||||
this.unitOfWorkManager = unitOfWorkManager;
|
this.unitOfWorkManager = unitOfWorkManager;
|
||||||
this.orderRepository = orderRepository;
|
this.orderRepository = orderRepository;
|
||||||
|
this.branchRepository = branchRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> PreSignInCheckAsync(IdentityUser user)
|
public async Task<bool> PreSignInCheckAsync(IdentityUser user)
|
||||||
|
|
@ -115,6 +119,10 @@ public class PlatformSignInManager : AbpSignInManager, IPlatformSignInManager
|
||||||
{
|
{
|
||||||
return new PlatformSignInResult() { IsNotAllowed_WorkHour = true };
|
return new PlatformSignInResult() { IsNotAllowed_WorkHour = true };
|
||||||
}
|
}
|
||||||
|
if (!await CheckBranchLicenseLimitAsync(user))
|
||||||
|
{
|
||||||
|
return new PlatformSignInResult() { IsNotAllowed_BranchLimit = true };
|
||||||
|
}
|
||||||
if (!await CheckConcurrentLimitAsync(user))
|
if (!await CheckConcurrentLimitAsync(user))
|
||||||
{
|
{
|
||||||
return new PlatformSignInResult() { IsNotAllowed_ConcurrentUserLimit = true };
|
return new PlatformSignInResult() { IsNotAllowed_ConcurrentUserLimit = true };
|
||||||
|
|
@ -284,16 +292,14 @@ public class PlatformSignInManager : AbpSignInManager, IPlatformSignInManager
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public async Task<bool> CheckConcurrentLimitAsync(IdentityUser user)
|
public async Task<bool> CheckConcurrentLimitAsync(IdentityUser user)
|
||||||
{
|
{
|
||||||
|
// Eğer tenantId yoksa, kullanıcı tenant'a bağlı değil demektir.
|
||||||
|
// Bu durumda concurrent limit kontrolü yapılmaz.
|
||||||
if (!user.TenantId.HasValue)
|
if (!user.TenantId.HasValue)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var maxConcurrentUsers = await GetActiveUserLicenseQuantityAsync(user.TenantId.Value);
|
var maxConcurrentUsers = await GetActiveUserLicenseQuantityAsync(user.TenantId.Value);
|
||||||
if (maxConcurrentUsers == 0)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tenant bağlamını explicit olarak set et — hem password hem refresh token akışlarında
|
// Tenant bağlamını explicit olarak set et — hem password hem refresh token akışlarında
|
||||||
// doğru tenant izolasyonu için güvenli bir şekilde değiştirilir.
|
// doğru tenant izolasyonu için güvenli bir şekilde değiştirilir.
|
||||||
|
|
@ -324,7 +330,47 @@ public class PlatformSignInManager : AbpSignInManager, IPlatformSignInManager
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<bool> CheckBranchLicenseLimitAsync(IdentityUser user)
|
||||||
|
{
|
||||||
|
if (!user.TenantId.HasValue)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var tenantId = user.TenantId.Value;
|
||||||
|
var activeBranchCount = await GetActiveBranchCountAsync(tenantId);
|
||||||
|
var branchLicenseQuantity = await GetActiveBranchLicenseQuantityAsync(tenantId);
|
||||||
|
|
||||||
|
if (activeBranchCount > branchLicenseQuantity)
|
||||||
|
{
|
||||||
|
Logger.LogWarning(PlatformEventIds.UserCannotSignInConcurrentUserLimit,
|
||||||
|
"Tenant {TenantId} branch license quantity of {Limit} is lower than active branch count {ActiveCount}.",
|
||||||
|
tenantId, branchLicenseQuantity, activeBranchCount);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<int> GetActiveBranchCountAsync(Guid tenantId)
|
||||||
|
{
|
||||||
|
using (currentTenant.Change(tenantId))
|
||||||
|
{
|
||||||
|
return await branchRepository.CountAsync(branch => branch.TenantId == tenantId && branch.IsActive == true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async Task<int> GetActiveUserLicenseQuantityAsync(Guid tenantId)
|
private async Task<int> GetActiveUserLicenseQuantityAsync(Guid tenantId)
|
||||||
|
{
|
||||||
|
return await GetActiveOrderItemQuantityAsync(tenantId, UserLicenseProductName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<int> GetActiveBranchLicenseQuantityAsync(Guid tenantId)
|
||||||
|
{
|
||||||
|
return await GetActiveOrderItemQuantityAsync(tenantId, BranchLicenseProductName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<int> GetActiveOrderItemQuantityAsync(Guid tenantId, string productName)
|
||||||
{
|
{
|
||||||
using (currentTenant.Change(null))
|
using (currentTenant.Change(null))
|
||||||
{
|
{
|
||||||
|
|
@ -335,7 +381,7 @@ public class PlatformSignInManager : AbpSignInManager, IPlatformSignInManager
|
||||||
|
|
||||||
return activeOrders
|
return activeOrders
|
||||||
.SelectMany(order => order.Items)
|
.SelectMany(order => order.Items)
|
||||||
.Where(item => item.ProductName == UserLicenseProductName)
|
.Where(item => item.ProductName == productName)
|
||||||
.Sum(item => item.Quantity);
|
.Sum(item => item.Quantity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -362,7 +362,16 @@ export const PaymentForm: React.FC<PaymentFormProps> = ({ onBack, onComplete, ca
|
||||||
className="h-10 w-10 shrink-0 rounded-md object-cover"
|
className="h-10 w-10 shrink-0 rounded-md object-cover"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<div className="min-w-0 font-medium">{translate('::' + item.product.name)}</div>
|
<div className="min-w-0">
|
||||||
|
<div className="truncate font-medium">
|
||||||
|
{translate('::' + item.product.name)}
|
||||||
|
</div>
|
||||||
|
{item.product.isQuantityBased && (
|
||||||
|
<div className="mt-1 text-xs font-medium text-gray-500 dark:text-gray-400">
|
||||||
|
x {item.quantity}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="font-medium text-right">{formatPrice(item.totalPrice)}</div>
|
<div className="font-medium text-right">{formatPrice(item.totalPrice)}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue