import type { ApiOrgPolicy, ApiOrgSettingsResponse } from "@/lib/api/admin-org-types" import type { OrgPolicySectionKey } from "@/lib/api/admin-org-types" import type { IntegrationEntry, OrgSettingsState, FilePolicySettings } from "@/lib/admin-settings/org-settings-types" const INTEGRATION_HREFS: Record = { authentik: "/admin/settings/authentication", nextcloud: "/admin/settings/nextcloud", onlyoffice: "/admin/settings/onlyoffice", smtp: "/admin/settings/mailing", } function mergeIntegrations( fromApi: IntegrationEntry[] | undefined ): IntegrationEntry[] { if (!fromApi?.length) return [] return fromApi.map((item) => ({ ...item, href: INTEGRATION_HREFS[item.id] ?? item.href, })) } const DEFAULT_FILE_POLICIES: FilePolicySettings = { max_upload_mib: 512, allowed_extensions: "", block_executable: true, external_sharing: "authenticated", default_link_expiry_days: 30, virus_scan_enabled: false, virustotal_api_key: "", retention_trash_days: 30, } function mergeFilePolicies(fromApi: Partial | undefined): FilePolicySettings { return { ...DEFAULT_FILE_POLICIES, ...fromApi, virustotal_api_key: fromApi?.virustotal_api_key ?? "", } } export function apiOrgPolicyToStore(policy: ApiOrgPolicy): Partial { return { authentik: { enabled: policy.authentik.enabled, api_url: policy.authentik.api_url, slug: policy.authentik.slug, client_id: policy.authentik.client_id, enforce_sso: policy.authentik.enforce_sso, allow_password_fallback: policy.authentik.allow_password_fallback, default_groups: policy.authentik.default_groups, }, twoFactor: { required_for_all: policy.two_factor.required_for_all, required_for_admins: policy.two_factor.required_for_admins, allowed_methods: policy.two_factor.allowed_methods, grace_period_days: policy.two_factor.grace_period_days, remember_device_days: policy.two_factor.remember_device_days, }, storageQuotas: { ...policy.storage_quotas }, usageQuotas: { ...policy.usage_quotas }, filePolicies: mergeFilePolicies(policy.file_policies), llm: { ...policy.llm, providers: policy.llm.providers ?? [], }, search: { ...policy.search, web_search: policy.search.web_search ?? { default_provider_id: "brave-default", providers: [], }, }, administrators: policy.administrators ?? [], nextcloud: { ...policy.nextcloud }, mailing: { ...policy.mailing }, onlyoffice: { ...policy.onlyoffice }, plugins: policy.plugins ?? [], integrations: mergeIntegrations(policy.integrations as IntegrationEntry[]), } } export function storeToApiOrgPolicy(state: OrgSettingsState): ApiOrgPolicy { return { authentik: { enabled: state.authentik.enabled, api_url: state.authentik.api_url, slug: state.authentik.slug, client_id: state.authentik.client_id, enforce_sso: state.authentik.enforce_sso, allow_password_fallback: state.authentik.allow_password_fallback, default_groups: state.authentik.default_groups, }, two_factor: { required_for_all: state.twoFactor.required_for_all, required_for_admins: state.twoFactor.required_for_admins, allowed_methods: state.twoFactor.allowed_methods, grace_period_days: state.twoFactor.grace_period_days, remember_device_days: state.twoFactor.remember_device_days, }, storage_quotas: { ...state.storageQuotas }, usage_quotas: { ...state.usageQuotas }, file_policies: { ...state.filePolicies }, llm: { default_provider_id: state.llm.default_provider_id, providers: state.llm.providers, contact_discovery_model: state.llm.contact_discovery_model, contact_discovery_provider_id: state.llm.contact_discovery_provider_id, enforce_org_providers: state.llm.enforce_org_providers, allow_user_override: state.llm.allow_user_override, }, search: { suite_engine: state.search.suite_engine, meilisearch_url: state.search.meilisearch_url, meilisearch_api_key: state.search.meilisearch_api_key, typesense_url: state.search.typesense_url, typesense_api_key: state.search.typesense_api_key, web_search: state.search.web_search, enforce_org_search: state.search.enforce_org_search, }, administrators: state.administrators, nextcloud: { ...state.nextcloud }, mailing: { ...state.mailing }, onlyoffice: { ...state.onlyoffice }, plugins: state.plugins.map(({ id, name, description, enabled, version }) => ({ id, name, description, enabled, version, })), integrations: state.integrations.map(({ id, name, description, enabled, configured }) => ({ id, name, description, enabled, configured, })), } } export function pickApiOrgPolicySections( state: OrgSettingsState, sections: OrgPolicySectionKey[] ): Partial { const full = storeToApiOrgPolicy(state) const patch: Partial = {} for (const key of sections) { patch[key] = full[key] as never } return patch } export type OrgSettingsMeta = { effective: ApiOrgSettingsResponse["effective"] secrets: ApiOrgSettingsResponse["secrets"] envVars: ApiOrgSettingsResponse["env_vars"] deployLocked: ApiOrgSettingsResponse["deploy_locked"] updatedAt: string updatedBy: string } export function apiOrgSettingsMeta(data: ApiOrgSettingsResponse): OrgSettingsMeta { return { effective: data.effective, secrets: data.secrets, envVars: data.env_vars ?? [], deployLocked: data.deploy_locked ?? {}, updatedAt: data.updated_at, updatedBy: data.updated_by, } }