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;
|
||||
}
|
||||
if (resultP.IsNotAllowed_BranchLimit)
|
||||
{
|
||||
return PlatformConsts.UserCannotSignInErrors.LoginNotAllowed_BranchLimit;
|
||||
}
|
||||
if (resultP.IsNotAllowed_ConcurrentUserLimit)
|
||||
{
|
||||
return PlatformConsts.UserCannotSignInErrors.LoginNotAllowed_ConcurrentUserLimit;
|
||||
|
|
|
|||
|
|
@ -162,6 +162,7 @@ public static class PlatformConsts
|
|||
public const string TenantIsPassive = GroupName + ".TenantIsPassive";
|
||||
public const string LoginNotAllowed_WorkHour = GroupName + ".LoginNotAllowed_WorkHour";
|
||||
public const string ConcurrentUserLimitError = GroupName + ".ConcurrentUserLimitError";
|
||||
public const string BranchLimitError = GroupName + ".BranchLimitError";
|
||||
public const string CaptchaWrongCode = GroupName + ".CaptchaWrongCode";
|
||||
public const string TwoFactorWrongCode = GroupName + ".TwoFactorWrongCode";
|
||||
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_TenantNotFound { get; set; } = "UserCannotSignInTenantNotFound";
|
||||
public static string LoginNotAllowed_WorkHour { get; set; } = "UserCannotSignInWorkHour";
|
||||
public static string LoginNotAllowed_BranchLimit { get; set; } = "UserCannotSignInBranchLimit";
|
||||
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_BranchLimit { get; set; }
|
||||
|
||||
public bool IsNotAllowed_ConcurrentUserLimit { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
|
|
@ -42,6 +44,7 @@ public class PlatformSignInResult : SignInResult
|
|||
ShouldChangePasswordPeriodic ? "ShouldChangePasswordPeriodic" :
|
||||
IsNotAllowed_TenantIsPassive ? "NotAllowed_TenantIsPassive" :
|
||||
IsNotAllowed_WorkHour ? "NotAllowed_WorkHour" :
|
||||
IsNotAllowed_BranchLimit ? "NotAllowed_BranchLimit" :
|
||||
IsNotAllowed_ConcurrentUserLimit ? "NotAllowed_ConcurrentUserLimit" :
|
||||
base.ToString();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,6 +64,11 @@ public class PlatformLoginResult : AbpLoginResult
|
|||
PResult = PlatformLoginResultType.NotAllowedWorkHour;
|
||||
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)
|
||||
{
|
||||
PResult = PlatformLoginResultType.ConcurrentUserLimit;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ public enum PlatformLoginResultType : byte
|
|||
ShowCaptcha,
|
||||
TenantIsPassive,
|
||||
NotAllowedWorkHour,
|
||||
BranchLimit,
|
||||
ConcurrentUserLimit
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Common;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Sozsoft.Platform.Entities;
|
||||
|
|
@ -33,6 +32,8 @@ public interface IPlatformSignInManager
|
|||
public class PlatformSignInManager : AbpSignInManager, IPlatformSignInManager
|
||||
{
|
||||
private const string UserLicenseProductName = "Public.products.userLicense";
|
||||
private const string BranchLicenseProductName = "Public.products.branchHosting";
|
||||
|
||||
private readonly IClock clock;
|
||||
private readonly IRepository<IpRestriction, Guid> repositoryIp;
|
||||
private readonly IRepository<WorkHour, Guid> repositoryWorkHour;
|
||||
|
|
@ -42,6 +43,7 @@ public class PlatformSignInManager : AbpSignInManager, IPlatformSignInManager
|
|||
private readonly ICurrentTenant currentTenant;
|
||||
private readonly IUnitOfWorkManager unitOfWorkManager;
|
||||
private readonly IRepository<Order, Guid> orderRepository;
|
||||
private readonly IRepository<Branch, Guid> branchRepository;
|
||||
|
||||
public PlatformSignInManager(
|
||||
IdentityUserManager userManager,
|
||||
|
|
@ -60,7 +62,8 @@ public class PlatformSignInManager : AbpSignInManager, IPlatformSignInManager
|
|||
IIdentitySessionRepository identitySessionRepository,
|
||||
ICurrentTenant currentTenant,
|
||||
IUnitOfWorkManager unitOfWorkManager,
|
||||
IRepository<Order, Guid> orderRepository
|
||||
IRepository<Order, Guid> orderRepository,
|
||||
IRepository<Branch, Guid> branchRepository
|
||||
) : base(
|
||||
userManager,
|
||||
contextAccessor,
|
||||
|
|
@ -81,6 +84,7 @@ public class PlatformSignInManager : AbpSignInManager, IPlatformSignInManager
|
|||
this.currentTenant = currentTenant;
|
||||
this.unitOfWorkManager = unitOfWorkManager;
|
||||
this.orderRepository = orderRepository;
|
||||
this.branchRepository = branchRepository;
|
||||
}
|
||||
|
||||
public async Task<bool> PreSignInCheckAsync(IdentityUser user)
|
||||
|
|
@ -115,6 +119,10 @@ public class PlatformSignInManager : AbpSignInManager, IPlatformSignInManager
|
|||
{
|
||||
return new PlatformSignInResult() { IsNotAllowed_WorkHour = true };
|
||||
}
|
||||
if (!await CheckBranchLicenseLimitAsync(user))
|
||||
{
|
||||
return new PlatformSignInResult() { IsNotAllowed_BranchLimit = true };
|
||||
}
|
||||
if (!await CheckConcurrentLimitAsync(user))
|
||||
{
|
||||
return new PlatformSignInResult() { IsNotAllowed_ConcurrentUserLimit = true };
|
||||
|
|
@ -284,16 +292,14 @@ public class PlatformSignInManager : AbpSignInManager, IPlatformSignInManager
|
|||
/// </summary>
|
||||
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)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
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
|
||||
// doğru tenant izolasyonu için güvenli bir şekilde değiştirilir.
|
||||
|
|
@ -324,7 +330,47 @@ public class PlatformSignInManager : AbpSignInManager, IPlatformSignInManager
|
|||
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)
|
||||
{
|
||||
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))
|
||||
{
|
||||
|
|
@ -335,7 +381,7 @@ public class PlatformSignInManager : AbpSignInManager, IPlatformSignInManager
|
|||
|
||||
return activeOrders
|
||||
.SelectMany(order => order.Items)
|
||||
.Where(item => item.ProductName == UserLicenseProductName)
|
||||
.Where(item => item.ProductName == productName)
|
||||
.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"
|
||||
/>
|
||||
)}
|
||||
<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 className="font-medium text-right">{formatPrice(item.totalPrice)}</div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in a new issue