forked from gongxuegit/tiku-backend.net
feat(saas): implement marketplace and tenant onboarding
This commit is contained in:
@@ -76,7 +76,7 @@ internal sealed class CurrentAccessAuthorizationHandler(ICurrentAccessContext ac
|
||||
|
||||
internal sealed class TenantPermissionAuthorizationHandler(
|
||||
ICurrentAccessContext accessContext,
|
||||
ICapabilityAccessEvaluator capabilityAccessEvaluator,
|
||||
IFeatureAccessService featureAccessService,
|
||||
IHttpContextAccessor httpContextAccessor) :
|
||||
AuthorizationHandler<TenantPermissionRequirement>
|
||||
{
|
||||
@@ -90,24 +90,18 @@ internal sealed class TenantPermissionAuthorizationHandler(
|
||||
}
|
||||
|
||||
var access = await accessContext.GetAsync();
|
||||
var moduleCode = ResolveModuleCode(requirement.PermissionCode);
|
||||
var operation = IsSafeMethod(httpContextAccessor.HttpContext?.Request.Method)
|
||||
? CapabilityOperation.Read
|
||||
: CapabilityOperation.Write;
|
||||
? FeatureAccessOperation.Read
|
||||
: FeatureAccessOperation.Write;
|
||||
if (access.TenantId is { } tenantId &&
|
||||
access.HasTenantPermission(requirement.PermissionCode) &&
|
||||
await capabilityAccessEvaluator.IsAllowedAsync(tenantId, moduleCode, operation))
|
||||
(await featureAccessService.FilterPermissionCodesAsync(
|
||||
tenantId, [requirement.PermissionCode], operation)).Contains(requirement.PermissionCode))
|
||||
{
|
||||
context.Succeed(requirement);
|
||||
}
|
||||
}
|
||||
|
||||
private static string ResolveModuleCode(string permissionCode)
|
||||
{
|
||||
var parts = permissionCode.Split(':', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
||||
return parts.Length >= 2 ? parts[1].ToLowerInvariant() : permissionCode.ToLowerInvariant();
|
||||
}
|
||||
|
||||
private static bool IsSafeMethod(string? method) =>
|
||||
method is not null &&
|
||||
(HttpMethods.IsGet(method) || HttpMethods.IsHead(method) || HttpMethods.IsOptions(method));
|
||||
@@ -197,7 +191,7 @@ public static class AccessAuthorizationServiceCollectionExtensions
|
||||
public static IServiceCollection AddTikuRbacAuthorization(this IServiceCollection services)
|
||||
{
|
||||
services.AddHttpContextAccessor();
|
||||
services.TryAddScoped<ICapabilityAccessEvaluator, CompatibilityCapabilityAccessEvaluator>();
|
||||
services.TryAddScoped<IFeatureAccessService, CompatibilityFeatureAccessService>();
|
||||
services.AddScoped<IAuthorizationHandler, CurrentAccessAuthorizationHandler>();
|
||||
services.AddScoped<IAuthorizationHandler, CurrentPlatformAccessAuthorizationHandler>();
|
||||
services.AddScoped<IAuthorizationHandler, TenantPermissionAuthorizationHandler>();
|
||||
@@ -241,6 +235,13 @@ public static class AccessAuthorizationServiceCollectionExtensions
|
||||
new CurrentTenantMemberRequirement(),
|
||||
new TenantPermissionRequirement(BackendPermissions.TenantContentManage),
|
||||
new AllDataScopeRequirement()));
|
||||
options.AddPolicy(
|
||||
TikuPolicies.TenantAllDataScope,
|
||||
policy => policy
|
||||
.RequireAuthenticatedUser()
|
||||
.AddRequirements(
|
||||
new CurrentTenantMemberRequirement(),
|
||||
new AllDataScopeRequirement()));
|
||||
options.AddPolicy(
|
||||
TikuPolicies.TenantCommerceOperateAllScope,
|
||||
policy => policy
|
||||
@@ -275,17 +276,21 @@ public static class AccessAuthorizationServiceCollectionExtensions
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class CompatibilityCapabilityAccessEvaluator : ICapabilityAccessEvaluator
|
||||
internal sealed class CompatibilityFeatureAccessService : IFeatureAccessService
|
||||
{
|
||||
public Task<bool> IsAllowedAsync(
|
||||
Guid tenantId,
|
||||
string moduleCode,
|
||||
CapabilityOperation operation,
|
||||
CancellationToken cancellationToken = default) => Task.FromResult(true);
|
||||
public Task<FeatureAccessDecision> EvaluateAsync(Guid tenantId, string featureCode, FeatureAccessOperation operation, CancellationToken cancellationToken = default) =>
|
||||
Task.FromResult(new FeatureAccessDecision(true, null, featureCode, operation));
|
||||
|
||||
public Task<IReadOnlySet<string>> GetEnabledModulesAsync(
|
||||
Guid tenantId,
|
||||
CapabilityOperation operation = CapabilityOperation.Read,
|
||||
CancellationToken cancellationToken = default) =>
|
||||
Task.FromResult<IReadOnlySet<string>>(new HashSet<string>(StringComparer.Ordinal));
|
||||
public Task<IReadOnlySet<string>> GetEnabledFeaturesAsync(Guid tenantId, FeatureAccessOperation operation = FeatureAccessOperation.Read, CancellationToken cancellationToken = default) =>
|
||||
Task.FromResult<IReadOnlySet<string>>(new HashSet<string>(SaasFeatureCatalog.All, StringComparer.Ordinal));
|
||||
|
||||
public Task<IReadOnlySet<string>> FilterPermissionCodesAsync(Guid tenantId, IEnumerable<string> permissionCodes, FeatureAccessOperation operation = FeatureAccessOperation.Read, CancellationToken cancellationToken = default) =>
|
||||
Task.FromResult<IReadOnlySet<string>>(permissionCodes.ToHashSet(StringComparer.Ordinal));
|
||||
|
||||
public Task<IReadOnlyCollection<FeatureQuotaSnapshot>> GetQuotaSummaryAsync(Guid tenantId, CancellationToken cancellationToken = default) =>
|
||||
Task.FromResult<IReadOnlyCollection<FeatureQuotaSnapshot>>([]);
|
||||
|
||||
public Task<bool> TryConsumeQuotaAsync(Guid tenantId, string metricCode, long amount, CancellationToken cancellationToken = default) => Task.FromResult(true);
|
||||
|
||||
public Task ReleaseQuotaAsync(Guid tenantId, string metricCode, long amount, CancellationToken cancellationToken = default) => Task.CompletedTask;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user