intermittent commit

This commit is contained in:
2026-07-14 13:22:09 +02:00
parent f2afcaa09c
commit ab07075a67
17 changed files with 1821 additions and 586 deletions

View File

@@ -1,47 +1,16 @@
import type { ApiSettings, DeltaDeletedItem } from "@govoplan/core-webui";
import { apiFetch } from "@govoplan/core-webui";
export type PermissionItem = {
scope: string;
label: string;
description: string;
category: string;
level: "tenant" | "system";
system_template_id?: string | null;
system_required?: boolean;
};
export type AdminOverview = {
active_tenant_id: string;
active_tenant_name: string;
tenant_count?: number | null;
system_account_count?: number | null;
system_group_template_count?: number | null;
system_role_template_count?: number | null;
user_count: number;
active_user_count: number;
group_count: number;
role_count: number;
active_api_key_count: number;
capabilities: string[];
};
export type TenantAdminItem = {
id: string;
slug: string;
name: string;
description?: string | null;
default_locale: string;
settings: Record<string, unknown>;
allow_custom_groups?: boolean | null;
allow_custom_roles?: boolean | null;
allow_api_keys?: boolean | null;
effective_governance: Record<string, boolean>;
is_active: boolean;
counts: Record<string, number>;
created_at: string;
updated_at: string;
};
import type { ApiSettings, DeltaDeletedItem, PrivacyRetentionPolicy, TenantAdminItem } from "@govoplan/core-webui";
import { apiFetch, apiGetList, apiPath, apiQuery } from "@govoplan/core-webui";
export { fetchAdminOverview, fetchPermissionCatalog, fetchTenants } from "@govoplan/core-webui";
export type {
AdminOverview,
PrivacyRetentionLimitPermissionPatch,
PrivacyRetentionLimitPermissions,
PrivacyRetentionPolicy,
PrivacyRetentionPolicyFieldKey,
PrivacyRetentionPolicyPatch,
PermissionItem,
TenantAdminItem
} from "@govoplan/core-webui";
export type TenantOwnerCandidate = {
account_id: string;
@@ -195,28 +164,6 @@ export type SystemMembershipDraft = {
is_last_active_owner?: boolean;
};
export type PrivacyRetentionPolicyFieldKey =
| "store_raw_campaign_json"
| "raw_campaign_json_retention_days"
| "generated_eml_retention_days"
| "stored_report_detail_retention_days"
| "mock_mailbox_retention_days"
| "audit_detail_retention_days"
| "audit_detail_level";
export type PrivacyRetentionLimitPermissions = Record<PrivacyRetentionPolicyFieldKey, boolean>;
export type PrivacyRetentionPolicy = {
store_raw_campaign_json: boolean;
raw_campaign_json_retention_days?: number | null;
generated_eml_retention_days?: number | null;
stored_report_detail_retention_days?: number | null;
mock_mailbox_retention_days?: number | null;
audit_detail_retention_days?: number | null;
audit_detail_level: "full" | "redacted" | "minimal";
allow_lower_level_limits: PrivacyRetentionLimitPermissions;
};
export type SystemSettingsItem = {
default_locale: string;
allow_tenant_custom_groups: boolean;
@@ -317,36 +264,18 @@ export type TenantSettingsDeltaResponse = {
} & DeltaResponseFields;
function deltaSuffix(options: { since?: string | null; limit?: number } = {}): string {
const params = new URLSearchParams();
if (options.since) params.set("since", options.since);
if (options.limit) params.set("limit", String(options.limit));
return params.toString() ? `?${params.toString()}` : "";
return apiQuery(options);
}
export function fetchAdminOverview(settings: ApiSettings): Promise<AdminOverview> {
return apiFetch(settings, "/api/v1/admin/overview");
}
export async function fetchPermissionCatalog(settings: ApiSettings): Promise<PermissionItem[]> {
const response = await apiFetch<{ permissions: PermissionItem[] }>(settings, "/api/v1/admin/permissions");
return response.permissions;
}
export async function fetchTenants(settings: ApiSettings): Promise<TenantAdminItem[]> {
const response = await apiFetch<{ tenants: TenantAdminItem[] }>(settings, "/api/v1/admin/tenants");
return response.tenants;
}
export function fetchTenantsDelta(settings: ApiSettings, options: { since?: string | null; limit?: number } = {}): Promise<TenantListDeltaResponse> {
const suffix = deltaSuffix(options);
return apiFetch(settings, `/api/v1/admin/tenants/delta${suffix}`);
}
export async function fetchTenantOwnerCandidates(settings: ApiSettings): Promise<TenantOwnerCandidate[]> {
const response = await apiFetch<{ accounts: TenantOwnerCandidate[] }>(settings, "/api/v1/admin/tenants/owner-candidates");
return response.accounts;
return apiGetList<TenantOwnerCandidate, "accounts">(settings, "/api/v1/admin/tenants/owner-candidates", "accounts");
}
export function createTenant(settings: ApiSettings, payload: {
@@ -429,19 +358,17 @@ export function fetchResourceAccessExplanation(
settings: ApiSettings,
options: { userId: string; resourceType: string; resourceId: string; action: string; tenantId?: string | null }
): Promise<ResourceAccessExplanationResponse> {
const params = new URLSearchParams({
return apiFetch(settings, apiPath("/api/v1/admin/access/resource-explanation", {
user_id: options.userId,
resource_type: options.resourceType,
resource_id: options.resourceId,
action: options.action
});
if (options.tenantId) params.set("tenant_id", options.tenantId);
return apiFetch(settings, `/api/v1/admin/access/resource-explanation?${params.toString()}`);
action: options.action,
tenant_id: options.tenantId
}));
}
export async function fetchGroups(settings: ApiSettings): Promise<GroupSummary[]> {
const response = await apiFetch<{ groups: GroupSummary[] }>(settings, "/api/v1/admin/groups");
return response.groups;
return apiGetList<GroupSummary, "groups">(settings, "/api/v1/admin/groups", "groups");
}
export function fetchGroupsDelta(settings: ApiSettings, options: { since?: string | null; limit?: number } = {}): Promise<GroupListDeltaResponse> {
@@ -471,8 +398,7 @@ export function updateGroup(settings: ApiSettings, groupId: string, payload: Par
}
export async function fetchRoles(settings: ApiSettings): Promise<RoleSummary[]> {
const response = await apiFetch<{ roles: RoleSummary[] }>(settings, "/api/v1/admin/roles");
return response.roles;
return apiGetList<RoleSummary, "roles">(settings, "/api/v1/admin/roles", "roles");
}
export function fetchRolesDelta(settings: ApiSettings, options: { since?: string | null; limit?: number } = {}): Promise<RoleListDeltaResponse> {
@@ -528,8 +454,7 @@ export function deleteExternalFunctionRoleMapping(settings: ApiSettings, mapping
}
export async function fetchSystemRoles(settings: ApiSettings): Promise<RoleSummary[]> {
const response = await apiFetch<{ roles: RoleSummary[] }>(settings, "/api/v1/admin/system/roles");
return response.roles;
return apiGetList<RoleSummary, "roles">(settings, "/api/v1/admin/system/roles", "roles");
}
export function fetchSystemRolesDelta(settings: ApiSettings, options: { since?: string | null; limit?: number } = {}): Promise<RoleListDeltaResponse> {
@@ -587,20 +512,15 @@ export function updateSystemAccountRoles(settings: ApiSettings, accountId: strin
}
export async function fetchApiKeys(settings: ApiSettings, includeRevoked = false): Promise<ApiKeyAdminItem[]> {
const params = new URLSearchParams();
if (includeRevoked) params.set("include_revoked", "true");
const suffix = params.toString() ? `?${params.toString()}` : "";
const response = await apiFetch<{ api_keys: ApiKeyAdminItem[] }>(settings, `/api/v1/admin/api-keys${suffix}`);
return response.api_keys;
return apiGetList<ApiKeyAdminItem, "api_keys">(settings, "/api/v1/admin/api-keys", "api_keys", { include_revoked: includeRevoked ? true : undefined });
}
export function fetchApiKeysDelta(settings: ApiSettings, includeRevoked = false, options: { since?: string | null; limit?: number } = {}): Promise<ApiKeyListDeltaResponse> {
const params = new URLSearchParams();
if (includeRevoked) params.set("include_revoked", "true");
if (options.since) params.set("since", options.since);
if (options.limit) params.set("limit", String(options.limit));
const suffix = params.toString() ? `?${params.toString()}` : "";
return apiFetch(settings, `/api/v1/admin/api-keys/delta${suffix}`);
return apiFetch(settings, apiPath("/api/v1/admin/api-keys/delta", {
include_revoked: includeRevoked ? true : undefined,
since: options.since,
limit: options.limit
}));
}
export function createApiKey(settings: ApiSettings, payload: {
@@ -653,9 +573,7 @@ export function updateSystemSettings(settings: ApiSettings, payload: SystemSetti
}
export async function fetchGovernanceTemplates(settings: ApiSettings, kind?: "group" | "role"): Promise<GovernanceTemplateItem[]> {
const suffix = kind ? `?kind=${encodeURIComponent(kind)}` : "";
const response = await apiFetch<{ templates: GovernanceTemplateItem[] }>(settings, `/api/v1/admin/system/governance-templates${suffix}`);
return response.templates;
return apiGetList<GovernanceTemplateItem, "templates">(settings, "/api/v1/admin/system/governance-templates", "templates", { kind });
}
export function fetchGovernanceTemplatesDelta(settings: ApiSettings, options: { since?: string | null; limit?: number } = {}): Promise<GovernanceTemplateListDeltaResponse> {