feat: add organization policy center
This commit is contained in:
+37
-6
@@ -140,6 +140,8 @@ db.exec("CREATE INDEX IF NOT EXISTS idx_generation_jobs_model_approval ON genera
|
||||
db.exec("CREATE INDEX IF NOT EXISTS idx_commercial_approvals_org_status ON commercial_approval_requests(organization_id, status, updated_at DESC)");
|
||||
db.exec("CREATE INDEX IF NOT EXISTS idx_commercial_approvals_requester ON commercial_approval_requests(requester_user_id, status, created_at DESC)");
|
||||
db.exec("CREATE INDEX IF NOT EXISTS idx_commercial_approvals_target ON commercial_approval_requests(organization_id, request_type, target_key, status)");
|
||||
db.exec("CREATE INDEX IF NOT EXISTS idx_organization_policies_org_category ON organization_policies(organization_id, category, policy_key)");
|
||||
db.exec("CREATE INDEX IF NOT EXISTS idx_organization_policy_evaluations_scope ON organization_policy_evaluations(organization_id, workspace_id, project_id, result, created_at DESC)");
|
||||
db.exec("CREATE INDEX IF NOT EXISTS idx_asset_versions_governance ON asset_versions(asset_id, rights_status, expires_at)");
|
||||
db.exec("CREATE INDEX IF NOT EXISTS idx_asset_governance_reviews_asset ON asset_governance_reviews(asset_id, created_at DESC)");
|
||||
db.exec("CREATE INDEX IF NOT EXISTS idx_asset_governance_reviews_scope ON asset_governance_reviews(organization_id, workspace_id, project_id, risk_status, created_at DESC)");
|
||||
@@ -237,6 +239,8 @@ function seedRoles() {
|
||||
["organization:manage", "修改组织设置"],
|
||||
["organization:members:invite", "邀请组织成员"],
|
||||
["organization:roles:manage", "管理组织角色权限策略"],
|
||||
["policy:read", "查看组织生产、安全和合规策略"],
|
||||
["policy:manage", "管理组织生产、安全和合规策略"],
|
||||
["workspace:create", "创建工作区"],
|
||||
["workspace:manage", "管理工作区设置"],
|
||||
["workspace:members:manage", "管理工作区成员"],
|
||||
@@ -285,14 +289,14 @@ function seedRoles() {
|
||||
org_admin: [
|
||||
"organization:manage", "organization:members:invite", "workspace:create", "workspace:manage",
|
||||
"workspace:members:manage", "project:create", "project:manage", "project:members:manage",
|
||||
"workflow:manage", "task:view", "task:manage", "task:complete", "style:read", "style:manage", "model:manage", "model:approve", "usage:view", "billing:manage", "quota:manage", "qa:review", "delivery:approve", "delivery:view", "compliance:manage", "audit:view", "queue:manage", "voice:approve",
|
||||
"workflow:manage", "task:view", "task:manage", "task:complete", "policy:read", "policy:manage", "style:read", "style:manage", "model:manage", "model:approve", "usage:view", "billing:manage", "quota:manage", "qa:review", "delivery:approve", "delivery:view", "compliance:manage", "audit:view", "queue:manage", "voice:approve",
|
||||
"system:settings:view", "service:health:view", "organization:roles:manage"
|
||||
],
|
||||
producer: ["project:create", "project:manage", "project:members:manage", "workflow:manage", "task:view", "task:manage", "task:complete", "style:read", "style:manage", "script:read", "job:create", "job:prioritize", "usage:view", "delivery:approve", "delivery:view", "voice:approve"],
|
||||
writer: ["script:read", "script:edit", "task:view", "task:complete", "style:read", "job:create"],
|
||||
art_director: ["asset:edit", "prompt:edit", "task:view", "task:complete", "style:read", "style:manage", "job:create"],
|
||||
voice_editor: ["voice:edit", "voice:approve", "task:view", "task:complete", "style:read", "job:create"],
|
||||
reviewer: ["script:read", "task:view", "task:complete", "style:read", "qa:review", "voice:approve", "delivery:view"],
|
||||
producer: ["project:create", "project:manage", "project:members:manage", "workflow:manage", "task:view", "task:manage", "task:complete", "policy:read", "style:read", "style:manage", "script:read", "job:create", "job:prioritize", "usage:view", "delivery:approve", "delivery:view", "voice:approve"],
|
||||
writer: ["script:read", "script:edit", "task:view", "task:complete", "policy:read", "style:read", "job:create"],
|
||||
art_director: ["asset:edit", "prompt:edit", "task:view", "task:complete", "policy:read", "style:read", "style:manage", "job:create"],
|
||||
voice_editor: ["voice:edit", "voice:approve", "task:view", "task:complete", "policy:read", "style:read", "job:create"],
|
||||
reviewer: ["script:read", "task:view", "task:complete", "policy:read", "style:read", "qa:review", "voice:approve", "delivery:view"],
|
||||
project_guest: ["script:read", "task:view", "style:read", "delivery:view"],
|
||||
project_editor: ["script:read", "script:edit", "asset:edit", "prompt:edit", "voice:edit", "task:view", "task:manage", "task:complete", "style:read", "job:create", "delivery:view"],
|
||||
project_viewer: ["script:read", "task:view", "style:read", "delivery:view"]
|
||||
@@ -355,6 +359,32 @@ function seedOrganization({ id, name, slug, ownerUserId, description, workspaceI
|
||||
insertIgnore("INSERT OR IGNORE INTO quota_allocations(id, organization_id, workspace_id, metric, limit_value, used_value, unit, period_start, period_end, created_at, updated_at) VALUES (?, ?, ?, 'storage', 1024, 128, 'GB', ?, ?, ?, ?)", [`quota-${workspaceId}-storage`, id, workspaceId, monthStart(), monthEnd(), timestamp, timestamp]);
|
||||
}
|
||||
|
||||
function rollQuotaPeriods() {
|
||||
const start = monthStart();
|
||||
const end = monthEnd();
|
||||
const timestamp = now();
|
||||
const rows = dbAll("SELECT * FROM quota_allocations");
|
||||
for (const row of rows) {
|
||||
const current = dbGet(
|
||||
"SELECT julianday(?) <= julianday('now') AND julianday(?) >= julianday('now') AS active",
|
||||
[row.period_start, row.period_end]
|
||||
);
|
||||
if (current?.active) continue;
|
||||
const usedValue = row.metric === "clip"
|
||||
? Number(dbGet(
|
||||
`SELECT COALESCE(SUM(units), 0) AS units
|
||||
FROM usage_events
|
||||
WHERE organization_id = ?
|
||||
AND (workspace_id = ? OR (? IS NULL AND workspace_id IS NULL))
|
||||
AND unit_name IN ('job', 'clip', 'clips')
|
||||
AND created_at >= datetime('now', 'start of month')`,
|
||||
[row.organization_id, row.workspace_id, row.workspace_id]
|
||||
)?.units || 0)
|
||||
: Number(row.used_value || 0);
|
||||
dbRun("UPDATE quota_allocations SET used_value = ?, period_start = ?, period_end = ?, updated_at = ? WHERE id = ?", [usedValue, start, end, timestamp, row.id]);
|
||||
}
|
||||
}
|
||||
|
||||
function commercialEntitlementDefaults(billing = {}) {
|
||||
const clipLimit = Number(billing.monthly_clip_quota || 2400);
|
||||
const storageGb = Number(billing.storage_gb || 1024);
|
||||
@@ -1239,6 +1269,7 @@ withTransaction(() => {
|
||||
insertIgnore("INSERT OR IGNORE INTO workspaces(id, organization_id, name, slug, description, status, created_at, updated_at) VALUES ('ws-pilot', 'org-studio-lab', '素材实验室', 'asset-lab', '角色、场景和模型试验空间', 'active', ?, ?)", [now(), now()]);
|
||||
seedCommercialPlans();
|
||||
seedOrganizationEntitlements();
|
||||
rollQuotaPeriods();
|
||||
seedCommercialApprovals();
|
||||
seedMembersAndProjects();
|
||||
seedModels();
|
||||
|
||||
Reference in New Issue
Block a user