470 lines
28 KiB
C#
470 lines
28 KiB
C#
using Microsoft.EntityFrameworkCore;
|
|
using Tiku.Application.PlatformAdmin;
|
|
using Tiku.Application.Security;
|
|
using Tiku.Domain.Common;
|
|
using Tiku.Domain.Operations;
|
|
using Tiku.Domain.Platform;
|
|
using Tiku.Domain.Tenancy;
|
|
using Tiku.Infrastructure.Persistence;
|
|
|
|
namespace Tiku.Infrastructure.Bootstrap;
|
|
|
|
public sealed class BuiltinBackofficeCatalogSeeder(TikuDbContext dbContext)
|
|
{
|
|
private static readonly BuiltinFeature[] Features =
|
|
[
|
|
new(SaasFeatureCatalog.CoreBackoffice, "后台基础能力", "core", true, 0),
|
|
new(SaasFeatureCatalog.PrivateQuestionBank, "私有题库", "question_bank", false, 10),
|
|
new(SaasFeatureCatalog.Practice, "题库练习", "learning", false, 20),
|
|
new(SaasFeatureCatalog.Assignment, "作业", "learning", false, 30),
|
|
new(SaasFeatureCatalog.Exam, "考试", "learning", false, 40),
|
|
new(SaasFeatureCatalog.Vocabulary, "词汇", "content", false, 50),
|
|
new(SaasFeatureCatalog.Handbook, "知识手册", "content", false, 60),
|
|
new(SaasFeatureCatalog.Video, "视频", "content", false, 70),
|
|
new(SaasFeatureCatalog.Scoreline, "分数线", "content", false, 80),
|
|
new(SaasFeatureCatalog.SiteContent, "站点运营内容", "marketing", false, 90),
|
|
new(SaasFeatureCatalog.StudentManagement, "学生管理", "student", false, 100),
|
|
new(SaasFeatureCatalog.StudentStore, "学生商城", "commerce", false, 110),
|
|
new(SaasFeatureCatalog.Crm, "学生跟进", "crm", false, 120),
|
|
new(SaasFeatureCatalog.ReferralCommission, "推广与分佣", "growth", false, 130),
|
|
new(SaasFeatureCatalog.TeacherAi, "教师 AI 助手", "ai", false, 140)
|
|
];
|
|
|
|
private static readonly BuiltinPermissionModule[] PermissionModules =
|
|
[
|
|
new("tenant_dashboard", "租户总览", BackendPermissionArea.Tenant, null, 10),
|
|
new("tenant_staff", "员工与角色", BackendPermissionArea.Tenant, null, 20),
|
|
new("tenant_settings", "租户设置", BackendPermissionArea.Tenant, null, 30),
|
|
new("tenant_provider", "外部服务", BackendPermissionArea.Tenant, null, 40),
|
|
new("tenant_job", "后台任务", BackendPermissionArea.Tenant, null, 50),
|
|
new("tenant_billing", "SaaS 账务", BackendPermissionArea.Tenant, null, 60),
|
|
new("tenant_student", "学生管理", BackendPermissionArea.Tenant, SaasFeatureCatalog.StudentManagement, 100),
|
|
new("tenant_question_bank", "私有题库", BackendPermissionArea.Tenant, SaasFeatureCatalog.PrivateQuestionBank, 110),
|
|
new("tenant_vocabulary", "词汇", BackendPermissionArea.Tenant, SaasFeatureCatalog.Vocabulary, 120),
|
|
new("tenant_handbook", "知识手册", BackendPermissionArea.Tenant, SaasFeatureCatalog.Handbook, 130),
|
|
new("tenant_video", "视频", BackendPermissionArea.Tenant, SaasFeatureCatalog.Video, 140),
|
|
new("tenant_scoreline", "分数线", BackendPermissionArea.Tenant, SaasFeatureCatalog.Scoreline, 150),
|
|
new("tenant_site_content", "站点运营内容", BackendPermissionArea.Tenant, SaasFeatureCatalog.SiteContent, 160),
|
|
new("tenant_commerce", "学生商城", BackendPermissionArea.Tenant, SaasFeatureCatalog.StudentStore, 170),
|
|
new("tenant_crm", "学生跟进", BackendPermissionArea.Tenant, SaasFeatureCatalog.Crm, 180),
|
|
new("tenant_commission", "推广分佣", BackendPermissionArea.Tenant, SaasFeatureCatalog.ReferralCommission, 190),
|
|
new("platform_dashboard", "平台总览", BackendPermissionArea.Platform, null, 200),
|
|
new("platform_tenant", "平台租户", BackendPermissionArea.Platform, null, 210),
|
|
new("platform_staff", "平台员工", BackendPermissionArea.Platform, null, 220),
|
|
new("platform_content", "公共题库", BackendPermissionArea.Platform, null, 230),
|
|
new("platform_audit", "平台审计", BackendPermissionArea.Platform, null, 240),
|
|
new("platform_billing", "平台 SaaS 商城", BackendPermissionArea.Platform, null, 250),
|
|
new("platform_crm", "CRM 接入代管", BackendPermissionArea.Platform, null, 260),
|
|
new("platform_sms", "短信服务", BackendPermissionArea.Platform, null, 270),
|
|
new("platform_payment", "支付设置", BackendPermissionArea.Platform, null, 280),
|
|
new("platform_operations", "平台运维", BackendPermissionArea.Platform, null, 290),
|
|
new("platform_governance", "平台治理", BackendPermissionArea.Platform, null, 295),
|
|
new("commerce", "交易运营", BackendPermissionArea.Both, SaasFeatureCatalog.StudentStore, 300)
|
|
];
|
|
|
|
private static readonly BuiltinPermission[] Permissions =
|
|
[
|
|
new(BackendPermissions.TenantDashboardView, "租户总览", BackendPermissionArea.Tenant, "tenant_dashboard"),
|
|
new(BackendPermissions.TenantStaffManage, "租户员工管理", BackendPermissionArea.Tenant, "tenant_staff"),
|
|
new(BackendPermissions.TenantRoleManage, "租户角色权限管理", BackendPermissionArea.Tenant, "tenant_staff"),
|
|
new(BackendPermissions.TenantStudentManage, "学生与班级管理", BackendPermissionArea.Tenant, "tenant_student"),
|
|
new(BackendPermissions.TenantContentManage, "租户题库管理", BackendPermissionArea.Tenant, "tenant_question_bank"),
|
|
new(BackendPermissions.TenantVocabularyManage, "租户词汇管理", BackendPermissionArea.Tenant, "tenant_vocabulary"),
|
|
new(BackendPermissions.TenantHandbookManage, "租户手册管理", BackendPermissionArea.Tenant, "tenant_handbook"),
|
|
new(BackendPermissions.TenantVideoManage, "租户视频管理", BackendPermissionArea.Tenant, "tenant_video"),
|
|
new(BackendPermissions.TenantScorelineManage, "租户分数线管理", BackendPermissionArea.Tenant, "tenant_scoreline"),
|
|
new(BackendPermissions.TenantSiteContentManage, "租户运营内容管理", BackendPermissionArea.Tenant,
|
|
"tenant_site_content"),
|
|
new(BackendPermissions.TenantSettingsManage, "租户设置管理", BackendPermissionArea.Tenant, "tenant_settings"),
|
|
new(BackendPermissions.TenantProviderManage, "租户外部服务配置", BackendPermissionArea.Tenant, "tenant_provider"),
|
|
new(BackendPermissions.TenantCommerceOperate, "租户交易运营", BackendPermissionArea.Tenant, "tenant_commerce"),
|
|
new(BackendPermissions.TenantCrmManage, "租户客户管理", BackendPermissionArea.Tenant, "tenant_crm"),
|
|
new(BackendPermissions.TenantCommissionManage, "租户佣金管理", BackendPermissionArea.Tenant, "tenant_commission"),
|
|
new(BackendPermissions.TenantJobManage, "租户任务管理", BackendPermissionArea.Tenant, "tenant_job"),
|
|
new(BackendPermissions.TenantBillingManage, "租户 SaaS 账务", BackendPermissionArea.Tenant, "tenant_billing"),
|
|
new(BackendPermissions.PlatformDashboardView, "平台总览", BackendPermissionArea.Platform, "platform_dashboard"),
|
|
new(BackendPermissions.PlatformTenantManage, "平台租户管理", BackendPermissionArea.Platform, "platform_tenant"),
|
|
new(BackendPermissions.PlatformStaffManage, "平台员工管理", BackendPermissionArea.Platform, "platform_staff"),
|
|
new(BackendPermissions.PlatformRoleManage, "平台角色权限管理", BackendPermissionArea.Platform, "platform_staff"),
|
|
new(BackendPermissions.PlatformQuestionBankManage, "平台公共题库运营", BackendPermissionArea.Platform,
|
|
"platform_content"),
|
|
new(BackendPermissions.PlatformAuditView, "平台审计查询", BackendPermissionArea.Platform, "platform_audit"),
|
|
new(BackendPermissions.PlatformBillingNotification, "平台催缴通知", BackendPermissionArea.Platform,
|
|
"platform_billing"),
|
|
new(BackendPermissions.PlatformSaasCatalogManage, "SaaS 商品管理", BackendPermissionArea.Platform,
|
|
"platform_billing"),
|
|
new(BackendPermissions.PlatformSaasBillingManage, "SaaS 交易管理", BackendPermissionArea.Platform,
|
|
"platform_billing"),
|
|
new(BackendPermissions.PlatformCrmRead, "平台 CRM 查询", BackendPermissionArea.Platform, "platform_crm"),
|
|
new(BackendPermissions.PlatformCrmWrite, "平台 CRM 管理", BackendPermissionArea.Platform, "platform_crm"),
|
|
new(BackendPermissions.PlatformSmsRead, "平台短信查询", BackendPermissionArea.Platform, "platform_sms"),
|
|
new(BackendPermissions.PlatformSmsWrite, "平台短信管理", BackendPermissionArea.Platform, "platform_sms"),
|
|
new(BackendPermissions.PlatformPaymentRead, "平台支付查询", BackendPermissionArea.Platform, "platform_payment"),
|
|
new(BackendPermissions.PlatformPaymentWrite, "平台支付管理", BackendPermissionArea.Platform, "platform_payment"),
|
|
new(BackendPermissions.PlatformOperationsView, "平台运维查询", BackendPermissionArea.Platform, "platform_operations"),
|
|
new(BackendPermissions.PlatformOperationsManage, "平台运维管理", BackendPermissionArea.Platform,
|
|
"platform_operations"),
|
|
new(BackendPermissions.PlatformApprovalView, "平台审批查询", BackendPermissionArea.Platform, "platform_governance"),
|
|
new(BackendPermissions.PlatformApprovalDecide, "平台审批决策", BackendPermissionArea.Platform, "platform_governance"),
|
|
new(BackendPermissions.PlatformApprovalPolicyManage, "平台审批策略管理", BackendPermissionArea.Platform,
|
|
"platform_governance"),
|
|
new(BackendPermissions.PlatformConfigurationManage, "平台配置中心管理", BackendPermissionArea.Platform,
|
|
"platform_governance"),
|
|
new(BackendPermissions.PlatformNotificationManage, "平台通知中心管理", BackendPermissionArea.Platform,
|
|
"platform_governance"),
|
|
new("commerce:refund:approve", "退款审核", BackendPermissionArea.Both, "commerce"),
|
|
new("commerce:reconciliation:manage", "对账管理", BackendPermissionArea.Both, "commerce"),
|
|
new("commerce:adjustment:manage", "调账管理", BackendPermissionArea.Both, "commerce")
|
|
];
|
|
|
|
private static readonly BuiltinMenu[] Menus =
|
|
[
|
|
new("tenant.dashboard", null, "租户总览", BackendPermissionArea.Tenant, "/tenant/dashboard",
|
|
"tenant:dashboard:view", 10),
|
|
new("tenant.staff", null, "员工与权限", BackendPermissionArea.Tenant, "/tenant/staff", "tenant:staff:manage", 20),
|
|
new("tenant.students", null, "班级与学生", BackendPermissionArea.Tenant, "/tenant/students", "tenant:student:manage",
|
|
30),
|
|
new("tenant.question-bank", null, "私有题库", BackendPermissionArea.Tenant, "/tenant/question-bank",
|
|
BackendPermissions.TenantContentManage, 40),
|
|
new("tenant.vocabulary", null, "词汇", BackendPermissionArea.Tenant, "/tenant/vocabulary",
|
|
BackendPermissions.TenantVocabularyManage, 50),
|
|
new("tenant.handbook", null, "知识手册", BackendPermissionArea.Tenant, "/tenant/handbook",
|
|
BackendPermissions.TenantHandbookManage, 60),
|
|
new("tenant.video", null, "视频", BackendPermissionArea.Tenant, "/tenant/video",
|
|
BackendPermissions.TenantVideoManage, 70),
|
|
new("tenant.scoreline", null, "分数线", BackendPermissionArea.Tenant, "/tenant/scoreline",
|
|
BackendPermissions.TenantScorelineManage, 80),
|
|
new("tenant.site-content", null, "运营内容", BackendPermissionArea.Tenant, "/tenant/site-content",
|
|
BackendPermissions.TenantSiteContentManage, 90),
|
|
new("tenant.providers", null, "外部服务", BackendPermissionArea.Tenant, "/tenant/providers",
|
|
BackendPermissions.TenantProviderManage, 100),
|
|
new("tenant.commerce", null, "交易运营", BackendPermissionArea.Tenant, "/tenant/commerce",
|
|
BackendPermissions.TenantCommerceOperate, 110),
|
|
new("tenant.billing", null, "SaaS 账务", BackendPermissionArea.Tenant, "/tenant/billing",
|
|
BackendPermissions.TenantBillingManage, 120),
|
|
new("platform.dashboard", null, "经营概览", BackendPermissionArea.Platform, "/",
|
|
BackendPermissions.PlatformDashboardView, 10),
|
|
new("platform.tenants", null, "租户管理", BackendPermissionArea.Platform, "/tenants",
|
|
BackendPermissions.PlatformTenantManage, 20),
|
|
new("platform.subscriptions", null, "订阅与应收", BackendPermissionArea.Platform, "/subscriptions",
|
|
BackendPermissions.PlatformSaasBillingManage, 30),
|
|
new("platform.usage", null, "用量计费", BackendPermissionArea.Platform, "/usage",
|
|
BackendPermissions.PlatformSaasBillingManage, 40),
|
|
new("platform.dunning", null, "收款与催缴", BackendPermissionArea.Platform, "/dunning",
|
|
BackendPermissions.PlatformBillingNotification, 50),
|
|
new("platform.refunds", null, "退款处理", BackendPermissionArea.Platform, "/refunds",
|
|
BackendPermissions.PlatformSaasBillingManage, 60),
|
|
new("platform.content", null, "公共题库", BackendPermissionArea.Platform, "/question-banks",
|
|
BackendPermissions.PlatformQuestionBankManage, 70),
|
|
new("platform.crm", null, "CRM 服务", BackendPermissionArea.Platform, "/crm", BackendPermissions.PlatformCrmRead,
|
|
80),
|
|
new("platform.sms", null, "短信服务", BackendPermissionArea.Platform, "/sms", BackendPermissions.PlatformSmsRead,
|
|
90),
|
|
new("platform.payment", null, "支付服务", BackendPermissionArea.Platform, "/payments",
|
|
BackendPermissions.PlatformPaymentRead, 100),
|
|
new("platform.staff", null, "员工与角色", BackendPermissionArea.Platform, "/staff",
|
|
BackendPermissions.PlatformStaffManage, 110),
|
|
new("platform.audit", null, "审计日志", BackendPermissionArea.Platform, "/audit",
|
|
BackendPermissions.PlatformAuditView, 120),
|
|
new("platform.alerts", null, "审计告警", BackendPermissionArea.Platform, "/alerts",
|
|
BackendPermissions.PlatformAuditView, 130),
|
|
new("platform.operations", null, "运行中心", BackendPermissionArea.Platform, "/operations",
|
|
BackendPermissions.PlatformOperationsView, 140),
|
|
new("platform.approvals", null, "审批中心", BackendPermissionArea.Platform, "/approvals",
|
|
BackendPermissions.PlatformApprovalView, 150),
|
|
new("platform.configuration", null, "配置中心", BackendPermissionArea.Platform, "/configuration",
|
|
BackendPermissions.PlatformConfigurationManage, 160),
|
|
new("platform.notifications", null, "通知中心", BackendPermissionArea.Platform, "/notifications",
|
|
BackendPermissions.PlatformNotificationManage, 170)
|
|
];
|
|
|
|
private static readonly BuiltinPlatformRole[] PlatformRoles =
|
|
[
|
|
new("platform_customer_service", "客服运营", "租户开通、客户服务与只读渠道排障",
|
|
[
|
|
BackendPermissions.PlatformDashboardView, BackendPermissions.PlatformTenantManage,
|
|
BackendPermissions.PlatformCrmRead, BackendPermissions.PlatformSmsRead,
|
|
BackendPermissions.PlatformApprovalView, BackendPermissions.PlatformNotificationManage
|
|
],
|
|
[
|
|
"platform.dashboard", "platform.tenants", "platform.crm", "platform.sms", "platform.approvals",
|
|
"platform.notifications"
|
|
]),
|
|
new("platform_finance", "财务运营", "套餐、订阅、应收、催缴、退款与支付查询",
|
|
[
|
|
BackendPermissions.PlatformDashboardView, BackendPermissions.PlatformSaasCatalogManage,
|
|
BackendPermissions.PlatformSaasBillingManage, BackendPermissions.PlatformBillingNotification,
|
|
BackendPermissions.PlatformPaymentRead, BackendPermissions.PlatformApprovalView,
|
|
BackendPermissions.PlatformApprovalDecide
|
|
],
|
|
[
|
|
"platform.dashboard", "platform.subscriptions", "platform.usage", "platform.dunning",
|
|
"platform.refunds", "platform.payment", "platform.approvals"
|
|
]),
|
|
new("platform_content_operator", "内容运营", "平台公共题库运营",
|
|
[BackendPermissions.PlatformDashboardView, BackendPermissions.PlatformQuestionBankManage],
|
|
["platform.dashboard", "platform.content"]),
|
|
new("platform_technical_operations", "技术运维", "依赖健康、Worker 与后台任务治理",
|
|
[
|
|
BackendPermissions.PlatformDashboardView, BackendPermissions.PlatformOperationsView,
|
|
BackendPermissions.PlatformOperationsManage, BackendPermissions.PlatformConfigurationManage
|
|
],
|
|
["platform.dashboard", "platform.operations", "platform.configuration"]),
|
|
new("platform_security_admin", "安全管理员", "平台员工、角色、审计与安全告警治理",
|
|
[
|
|
BackendPermissions.PlatformDashboardView, BackendPermissions.PlatformStaffManage,
|
|
BackendPermissions.PlatformRoleManage, BackendPermissions.PlatformAuditView,
|
|
BackendPermissions.PlatformApprovalView, BackendPermissions.PlatformApprovalDecide,
|
|
BackendPermissions.PlatformApprovalPolicyManage, BackendPermissions.PlatformConfigurationManage
|
|
],
|
|
[
|
|
"platform.dashboard", "platform.staff", "platform.audit", "platform.alerts", "platform.approvals",
|
|
"platform.configuration"
|
|
])
|
|
];
|
|
|
|
public async Task SeedAsync(CancellationToken cancellationToken = default)
|
|
{
|
|
var platformOwnedTenant = await dbContext.Tenants
|
|
.SingleOrDefaultAsync(item => item.Mode == TenantMode.PlatformOwned, cancellationToken);
|
|
if (platformOwnedTenant is null)
|
|
{
|
|
var tenant = new Tenant
|
|
{
|
|
Slug = "platform-public-content",
|
|
Name = "平台公共内容",
|
|
Status = TenantStatus.Active,
|
|
Mode = TenantMode.PlatformOwned,
|
|
BillingStatus = BillingStatus.Active,
|
|
Metadata = JsonDefaults.Object()
|
|
};
|
|
dbContext.Tenants.Add(tenant);
|
|
dbContext.AuthorizationScopeVersions.Add(new AuthorizationScopeVersion
|
|
{
|
|
Realm = AuthRealm.Tenant,
|
|
TenantId = tenant.Id
|
|
});
|
|
}
|
|
|
|
var featureCodes = Features.Select(item => item.Code).ToArray();
|
|
var existingFeatureCodes = await dbContext.SaasFeatures.AsNoTracking()
|
|
.Where(item => featureCodes.Contains(item.Code))
|
|
.Select(item => item.Code)
|
|
.ToHashSetAsync(StringComparer.Ordinal, cancellationToken);
|
|
|
|
var moduleCodes = PermissionModules.Select(item => item.Code).ToArray();
|
|
var existingModuleCodes = await dbContext.PermissionModules.AsNoTracking()
|
|
.Where(item => moduleCodes.Contains(item.Code))
|
|
.Select(item => item.Code)
|
|
.ToHashSetAsync(StringComparer.Ordinal, cancellationToken);
|
|
|
|
var permissionCodes = Permissions.Select(item => item.Code).ToArray();
|
|
var existingPermissionCodes = await dbContext.BackendPermissions.AsNoTracking()
|
|
.Where(item => permissionCodes.Contains(item.Code))
|
|
.Select(item => item.Code)
|
|
.ToHashSetAsync(StringComparer.Ordinal, cancellationToken);
|
|
|
|
var menuCodes = Menus.Select(item => item.Code).ToArray();
|
|
var existingMenus = await dbContext.BackendMenus
|
|
.Where(item => menuCodes.Contains(item.Code))
|
|
.ToDictionaryAsync(item => item.Code, StringComparer.Ordinal, cancellationToken);
|
|
|
|
dbContext.SaasFeatures.AddRange(Features
|
|
.Where(item => !existingFeatureCodes.Contains(item.Code))
|
|
.Select(item => new SaasFeature
|
|
{
|
|
Code = item.Code,
|
|
Name = item.Name,
|
|
Category = item.Category,
|
|
IsCore = item.IsCore,
|
|
Status = SaasFeatureStatus.Active,
|
|
SortOrder = item.SortOrder
|
|
}));
|
|
dbContext.PermissionModules.AddRange(PermissionModules
|
|
.Where(item => !existingModuleCodes.Contains(item.Code))
|
|
.Select(item => new PermissionModule
|
|
{
|
|
Code = item.Code,
|
|
Name = item.Name,
|
|
Area = item.Area,
|
|
RequiredFeatureCode = item.RequiredFeatureCode,
|
|
SortOrder = item.SortOrder
|
|
}));
|
|
dbContext.BackendPermissions.AddRange(Permissions
|
|
.Where(item => !existingPermissionCodes.Contains(item.Code))
|
|
.Select(item => new BackendPermission
|
|
{
|
|
Code = item.Code,
|
|
Name = item.Name,
|
|
Area = item.Area,
|
|
PermissionModuleCode = item.PermissionModuleCode,
|
|
IsSystem = true
|
|
}));
|
|
dbContext.BackendMenus.AddRange(Menus
|
|
.Where(item => !existingMenus.ContainsKey(item.Code))
|
|
.Select(item => new BackendMenu
|
|
{
|
|
Code = item.Code,
|
|
ParentCode = item.ParentCode,
|
|
Title = item.Title,
|
|
Area = item.Area,
|
|
Path = item.Path,
|
|
PermissionCode = item.PermissionCode,
|
|
SortOrder = item.SortOrder,
|
|
IsActive = true
|
|
}));
|
|
var roleCodes = PlatformRoles.Select(item => item.Code).ToArray();
|
|
var existingRoles = await dbContext.PlatformBackendRoles
|
|
.Where(role => roleCodes.Contains(role.Code))
|
|
.ToDictionaryAsync(role => role.Code, StringComparer.Ordinal, cancellationToken);
|
|
foreach (var builtin in PlatformRoles)
|
|
{
|
|
if (!existingRoles.TryGetValue(builtin.Code, out var role))
|
|
{
|
|
role = new PlatformBackendRole { Code = builtin.Code, IsSystem = true };
|
|
dbContext.PlatformBackendRoles.Add(role);
|
|
existingRoles[builtin.Code] = role;
|
|
}
|
|
|
|
role.Name = builtin.Name;
|
|
role.Description = builtin.Description;
|
|
role.Status = BackendRoleStatus.Active;
|
|
role.IsSystem = true;
|
|
}
|
|
|
|
var approvalPolicies = new[]
|
|
{
|
|
new PlatformApprovalPolicy
|
|
{
|
|
Code = PlatformApprovalPolicyCodes.TenantArchive, Name = "终止租户",
|
|
RequiredPermission = BackendPermissions.PlatformTenantManage, AlwaysRequireApproval = true
|
|
},
|
|
new PlatformApprovalPolicy
|
|
{
|
|
Code = PlatformApprovalPolicyCodes.SuperAdminGrant, Name = "平台超级权限变更",
|
|
RequiredPermission = BackendPermissions.PlatformRoleManage, AlwaysRequireApproval = true
|
|
},
|
|
new PlatformApprovalPolicy
|
|
{
|
|
Code = PlatformApprovalPolicyCodes.PaymentChannelChange, Name = "支付渠道或密钥引用变更",
|
|
RequiredPermission = BackendPermissions.PlatformPaymentWrite, AlwaysRequireApproval = true
|
|
},
|
|
new PlatformApprovalPolicy
|
|
{
|
|
Code = PlatformApprovalPolicyCodes.FinancialAdjustment, Name = "大额退款及手工收款",
|
|
RequiredPermission = BackendPermissions.PlatformSaasBillingManage, AmountThresholdCents = 5_000_000
|
|
}
|
|
};
|
|
var approvalPolicyCodes = approvalPolicies.Select(item => item.Code).ToArray();
|
|
var existingPolicyCodes = await dbContext.PlatformApprovalPolicies.AsNoTracking()
|
|
.Where(policy => approvalPolicyCodes.Contains(policy.Code))
|
|
.Select(policy => policy.Code)
|
|
.ToHashSetAsync(StringComparer.Ordinal, cancellationToken);
|
|
dbContext.PlatformApprovalPolicies.AddRange(approvalPolicies.Where(policy =>
|
|
!existingPolicyCodes.Contains(policy.Code)));
|
|
|
|
var configurationDefinitions = new[]
|
|
{
|
|
new PlatformConfigurationDefinition
|
|
{
|
|
Code = "platform.support-contact", Name = "平台支持联系方式", Category = "platform",
|
|
ValueType = PlatformConfigurationValueType.String
|
|
},
|
|
new PlatformConfigurationDefinition
|
|
{
|
|
Code = "operations.notification-retention-days", Name = "通知投递保留天数", Category = "operations",
|
|
ValueType = PlatformConfigurationValueType.Number
|
|
},
|
|
new PlatformConfigurationDefinition
|
|
{
|
|
Code = "security.jwt-key-ring", Name = "JWT 密钥环", Category = "security",
|
|
ValueType = PlatformConfigurationValueType.SecretReference, IsSensitive = true,
|
|
AllowRuntimeManagement = false, Description = "安全配置只能通过部署环境变更。"
|
|
}
|
|
};
|
|
var configurationCodes = configurationDefinitions.Select(item => item.Code).ToArray();
|
|
var existingConfigurationCodes = await dbContext.PlatformConfigurationDefinitions.AsNoTracking()
|
|
.Where(item => configurationCodes.Contains(item.Code)).Select(item => item.Code)
|
|
.ToHashSetAsync(StringComparer.Ordinal, cancellationToken);
|
|
dbContext.PlatformConfigurationDefinitions.AddRange(
|
|
configurationDefinitions.Where(item => !existingConfigurationCodes.Contains(item.Code)));
|
|
await dbContext.SaveChangesAsync(cancellationToken);
|
|
|
|
foreach (var builtin in PlatformRoles)
|
|
{
|
|
var role = existingRoles[builtin.Code];
|
|
var boundPermissions = await dbContext.PlatformBackendRolePermissions
|
|
.Where(binding => binding.RoleId == role.Id)
|
|
.ToArrayAsync(cancellationToken);
|
|
dbContext.PlatformBackendRolePermissions.RemoveRange(boundPermissions
|
|
.Where(binding => !builtin.PermissionCodes.Contains(binding.PermissionCode, StringComparer.Ordinal)));
|
|
var boundPermissionCodes = boundPermissions.Select(binding => binding.PermissionCode)
|
|
.ToHashSet(StringComparer.Ordinal);
|
|
dbContext.PlatformBackendRolePermissions.AddRange(builtin.PermissionCodes
|
|
.Where(code => !boundPermissionCodes.Contains(code))
|
|
.Select(code => new PlatformBackendRolePermission { RoleId = role.Id, PermissionCode = code }));
|
|
|
|
var boundMenus = await dbContext.PlatformBackendRoleMenus
|
|
.Where(binding => binding.RoleId == role.Id)
|
|
.ToArrayAsync(cancellationToken);
|
|
dbContext.PlatformBackendRoleMenus.RemoveRange(boundMenus
|
|
.Where(binding => !builtin.MenuCodes.Contains(binding.MenuCode, StringComparer.Ordinal)));
|
|
var boundMenuCodes = boundMenus.Select(binding => binding.MenuCode).ToHashSet(StringComparer.Ordinal);
|
|
dbContext.PlatformBackendRoleMenus.AddRange(builtin.MenuCodes
|
|
.Where(code => !boundMenuCodes.Contains(code))
|
|
.Select(code => new PlatformBackendRoleMenu { RoleId = role.Id, MenuCode = code }));
|
|
}
|
|
|
|
var superAdminRoleId = await dbContext.PlatformBackendRoles.AsNoTracking()
|
|
.Where(role => role.Code == PlatformAdminBootstrapper.SuperAdminRoleCode && role.IsSystem)
|
|
.Select(role => (Guid?)role.Id)
|
|
.SingleOrDefaultAsync(cancellationToken);
|
|
if (superAdminRoleId.HasValue)
|
|
{
|
|
var boundPermissionCodes = await dbContext.PlatformBackendRolePermissions.AsNoTracking()
|
|
.Where(binding => binding.RoleId == superAdminRoleId.Value)
|
|
.Select(binding => binding.PermissionCode)
|
|
.ToHashSetAsync(StringComparer.Ordinal, cancellationToken);
|
|
dbContext.PlatformBackendRolePermissions.AddRange(BackendPermissions.Platform
|
|
.Where(code => !boundPermissionCodes.Contains(code))
|
|
.Select(code => new PlatformBackendRolePermission
|
|
{
|
|
RoleId = superAdminRoleId.Value,
|
|
PermissionCode = code
|
|
}));
|
|
}
|
|
|
|
await dbContext.SaveChangesAsync(cancellationToken);
|
|
}
|
|
|
|
private sealed record BuiltinFeature(string Code, string Name, string Category, bool IsCore, int SortOrder);
|
|
|
|
private sealed record BuiltinPermissionModule(
|
|
string Code,
|
|
string Name,
|
|
BackendPermissionArea Area,
|
|
string? RequiredFeatureCode,
|
|
int SortOrder);
|
|
|
|
private sealed record BuiltinPermission(
|
|
string Code,
|
|
string Name,
|
|
BackendPermissionArea Area,
|
|
string PermissionModuleCode);
|
|
|
|
private sealed record BuiltinMenu(
|
|
string Code,
|
|
string? ParentCode,
|
|
string Title,
|
|
BackendPermissionArea Area,
|
|
string Path,
|
|
string PermissionCode,
|
|
int SortOrder);
|
|
|
|
private sealed record BuiltinPlatformRole(
|
|
string Code,
|
|
string Name,
|
|
string Description,
|
|
string[] PermissionCodes,
|
|
string[] MenuCodes);
|
|
} |