Some checks are pending
E2E / Playwright e2e (push) Waiting to run
- Added support for managing AI models within the AI assistant settings. - Introduced new hosted mail setup component for streamlined email configuration. - Updated environment variables for local development and proxy settings. - Enhanced error handling and user feedback in the chat page for API connectivity issues. - Improved routing for AI-related API calls in the Next.js configuration. - Added documentation for local development and agent management in CLAUDE.md.
406 lines
12 KiB
TypeScript
406 lines
12 KiB
TypeScript
"use client"
|
|
|
|
import { create } from "zustand"
|
|
import type { OrgSettingsMeta } from "@/lib/admin-settings/map-api-org-settings"
|
|
import type {
|
|
Administrator,
|
|
AuthentikSettings,
|
|
FilePolicySettings,
|
|
IntegrationEntry,
|
|
MailingSettings,
|
|
NextcloudSettings,
|
|
OnlyOfficeSettings,
|
|
RichTextSettings,
|
|
AiAssistantSettings,
|
|
AgendaOrgPolicySettings,
|
|
MeetOrgPolicySettings,
|
|
OrgLLMSettings,
|
|
OrgSearchSettings,
|
|
OrgStorageQuotas,
|
|
PluginEntry,
|
|
TwoFactorPolicy,
|
|
UsageQuotaDefaults,
|
|
IdentityProvidersPolicy,
|
|
} from "@/lib/admin-settings/org-settings-types"
|
|
import { DEFAULT_MEET_POLICY } from "@/lib/meet/meet-settings-types"
|
|
|
|
const DEFAULT_AUTHENTIK: AuthentikSettings = {
|
|
enabled: true,
|
|
api_url: "",
|
|
slug: "ulti-suite",
|
|
client_id: "",
|
|
enforce_sso: true,
|
|
allow_password_fallback: false,
|
|
default_groups: "ulti-users",
|
|
}
|
|
|
|
const DEFAULT_IDENTITY_PROVIDERS: IdentityProvidersPolicy = {
|
|
allow_self_enrollment: true,
|
|
default_login_source: "",
|
|
providers: [],
|
|
}
|
|
|
|
const DEFAULT_TWO_FACTOR: TwoFactorPolicy = {
|
|
required_for_all: false,
|
|
required_for_admins: true,
|
|
allowed_methods: ["totp", "webauthn"],
|
|
grace_period_days: 7,
|
|
remember_device_days: 30,
|
|
}
|
|
|
|
const DEFAULT_STORAGE_QUOTAS: OrgStorageQuotas = {
|
|
default_mail_gib: 5,
|
|
default_drive_gib: 5,
|
|
default_photos_gib: 5,
|
|
warn_threshold_pct: 90,
|
|
}
|
|
|
|
const DEFAULT_USAGE_QUOTAS: UsageQuotaDefaults = {
|
|
llm_requests_per_day: 100,
|
|
llm_tokens_per_month: 500_000,
|
|
search_requests_per_day: 50,
|
|
max_api_tokens_per_user: 10,
|
|
max_webhooks_per_user: 20,
|
|
}
|
|
|
|
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,
|
|
mount_oauth: {
|
|
redirect_uri: "",
|
|
google: { enabled: false, client_id: "", client_secret: "" },
|
|
dropbox: { enabled: false, client_id: "", client_secret: "" },
|
|
microsoft: { enabled: false, client_id: "", client_secret: "" },
|
|
},
|
|
}
|
|
|
|
const DEFAULT_LLM: OrgLLMSettings = {
|
|
default_provider_id: "",
|
|
providers: [],
|
|
enforce_org_providers: false,
|
|
allow_user_override: true,
|
|
}
|
|
|
|
const DEFAULT_SEARCH: OrgSearchSettings = {
|
|
suite_engine: "postgres",
|
|
meilisearch_url: "",
|
|
meilisearch_api_key: "",
|
|
typesense_url: "",
|
|
typesense_api_key: "",
|
|
web_search: { default_provider_id: "brave-default", providers: [] },
|
|
enforce_org_search: false,
|
|
}
|
|
|
|
const DEFAULT_NEXTCLOUD: NextcloudSettings = {
|
|
enabled: false,
|
|
base_url: "",
|
|
admin_user: "",
|
|
admin_password: "",
|
|
drive_enabled: true,
|
|
calendar_enabled: true,
|
|
contacts_enabled: true,
|
|
talk_enabled: false,
|
|
}
|
|
|
|
const DEFAULT_MAILING: MailingSettings = {
|
|
enabled: false,
|
|
smtp_host: "",
|
|
smtp_port: 587,
|
|
smtp_user: "",
|
|
smtp_password: "",
|
|
from_email: "noreply@example.com",
|
|
from_name: "Ulti Suite",
|
|
tls_mode: "starttls",
|
|
}
|
|
|
|
const DEFAULT_ONLYOFFICE: OnlyOfficeSettings = {
|
|
enabled: false,
|
|
document_server_url: "",
|
|
jwt_secret: "",
|
|
jwt_header: "Authorization",
|
|
}
|
|
|
|
const DEFAULT_RICHTEXT: RichTextSettings = {
|
|
enabled: true,
|
|
storage_mode: "sidecar",
|
|
export_mirror_format: "",
|
|
hocuspocus_url: "",
|
|
}
|
|
|
|
const DEFAULT_AI_ASSISTANT: AiAssistantSettings = {
|
|
enabled: false,
|
|
openwebui_internal_url: "",
|
|
public_path: "/ai",
|
|
embed_default_temporary: true,
|
|
default_model: "",
|
|
enabled_tools: ["mail", "drive", "contacts", "search"],
|
|
chat_sync_enabled: true,
|
|
chat_nc_path: "/.ultimail/ai/chats",
|
|
models: [],
|
|
}
|
|
|
|
const DEFAULT_AGENDA: AgendaOrgPolicySettings = {
|
|
default_theme_mode: "system",
|
|
enforce_org_theme: false,
|
|
default_video_provider: "ultimeet",
|
|
enforce_org_video_provider: false,
|
|
video_provider_api_keys: {},
|
|
}
|
|
|
|
const DEFAULT_MEET: MeetOrgPolicySettings = DEFAULT_MEET_POLICY
|
|
|
|
const DEFAULT_PLUGINS: PluginEntry[] = [
|
|
{
|
|
id: "mail-automation",
|
|
name: "Automatisations mail",
|
|
description: "Règles, webhooks et tri IA sur la réception.",
|
|
enabled: true,
|
|
version: "1.0.0",
|
|
},
|
|
{
|
|
id: "contact-discovery",
|
|
name: "Découverte contacts",
|
|
description: "Enrichissement IA et signatures détectées.",
|
|
enabled: true,
|
|
version: "1.0.0",
|
|
},
|
|
{
|
|
id: "public-share",
|
|
name: "Partage public Drive",
|
|
description: "Liens publics et partages externes.",
|
|
enabled: true,
|
|
version: "1.0.0",
|
|
},
|
|
{
|
|
id: "office-editor",
|
|
name: "Édition OnlyOffice",
|
|
description: "Édition collaborative de documents.",
|
|
enabled: false,
|
|
version: "1.0.0",
|
|
},
|
|
{
|
|
id: "richtext-editor",
|
|
name: "Édition rich text TipTap",
|
|
description: "Édition rich text TipTap pour documents Word.",
|
|
enabled: true,
|
|
version: "1.0.0",
|
|
},
|
|
{
|
|
id: "ai-assistant",
|
|
name: "UltiAI",
|
|
description: "Assistant IA intégré avec tools mail, drive et contacts.",
|
|
enabled: false,
|
|
version: "1.0.0",
|
|
},
|
|
]
|
|
|
|
const DEFAULT_INTEGRATIONS: IntegrationEntry[] = [
|
|
{
|
|
id: "authentik",
|
|
name: "Authentik",
|
|
description: "SSO, groupes et provisionnement des comptes.",
|
|
enabled: true,
|
|
configured: false,
|
|
href: "/admin/settings/authentication",
|
|
},
|
|
{
|
|
id: "nextcloud",
|
|
name: "Nextcloud",
|
|
description: "Drive, agenda, contacts et Talk.",
|
|
enabled: false,
|
|
configured: false,
|
|
href: "/admin/settings/nextcloud",
|
|
},
|
|
{
|
|
id: "onlyoffice",
|
|
name: "OnlyOffice",
|
|
description: "Édition de documents dans le navigateur.",
|
|
enabled: false,
|
|
configured: false,
|
|
href: "/admin/settings/onlyoffice",
|
|
},
|
|
{
|
|
id: "smtp",
|
|
name: "Mailing unifié",
|
|
description: "SMTP pour notifications suite (partages, mentions).",
|
|
enabled: false,
|
|
configured: false,
|
|
href: "/admin/settings/mailing",
|
|
},
|
|
]
|
|
|
|
type OrgSettingsActions = {
|
|
setAuthentik: (patch: Partial<AuthentikSettings>) => void
|
|
setIdentityProviders: (patch: Partial<IdentityProvidersPolicy>) => void
|
|
setTwoFactor: (patch: Partial<TwoFactorPolicy>) => void
|
|
setStorageQuotas: (patch: Partial<OrgStorageQuotas>) => void
|
|
setUsageQuotas: (patch: Partial<UsageQuotaDefaults>) => void
|
|
setFilePolicies: (patch: Partial<FilePolicySettings>) => void
|
|
setLlm: (patch: Partial<OrgLLMSettings>) => void
|
|
setSearch: (patch: Partial<OrgSearchSettings>) => void
|
|
setNextcloud: (patch: Partial<NextcloudSettings>) => void
|
|
setMailing: (patch: Partial<MailingSettings>) => void
|
|
setOnlyoffice: (patch: Partial<OnlyOfficeSettings>) => void
|
|
setRichtext: (patch: Partial<RichTextSettings>) => void
|
|
setAiAssistant: (patch: Partial<AiAssistantSettings>) => void
|
|
setAgenda: (patch: Partial<AgendaOrgPolicySettings>) => void
|
|
setAdministrators: (admins: Administrator[]) => void
|
|
addAdministrator: (admin: Administrator) => void
|
|
removeAdministrator: (id: string) => void
|
|
updateAdministrator: (id: string, patch: Partial<Administrator>) => void
|
|
setPlugins: (plugins: PluginEntry[]) => void
|
|
togglePlugin: (id: string, enabled: boolean) => void
|
|
setIntegrations: (integrations: IntegrationEntry[]) => void
|
|
toggleIntegration: (id: string, enabled: boolean) => void
|
|
hydrateFromApi: (patch: Partial<{
|
|
authentik: AuthentikSettings
|
|
identityProviders: IdentityProvidersPolicy
|
|
twoFactor: TwoFactorPolicy
|
|
storageQuotas: OrgStorageQuotas
|
|
usageQuotas: UsageQuotaDefaults
|
|
filePolicies: FilePolicySettings
|
|
llm: OrgLLMSettings
|
|
search: OrgSearchSettings
|
|
administrators: Administrator[]
|
|
nextcloud: NextcloudSettings
|
|
mailing: MailingSettings
|
|
onlyoffice: OnlyOfficeSettings
|
|
richtext: RichTextSettings
|
|
aiAssistant: AiAssistantSettings
|
|
agenda: AgendaOrgPolicySettings
|
|
meet: MeetOrgPolicySettings
|
|
plugins: PluginEntry[]
|
|
integrations: IntegrationEntry[]
|
|
}>, meta?: OrgSettingsMeta) => void
|
|
setMeet: (patch: Partial<MeetOrgPolicySettings>) => void
|
|
}
|
|
|
|
export const useOrgSettingsStore = create<
|
|
{
|
|
authentik: AuthentikSettings
|
|
identityProviders: IdentityProvidersPolicy
|
|
twoFactor: TwoFactorPolicy
|
|
storageQuotas: OrgStorageQuotas
|
|
usageQuotas: UsageQuotaDefaults
|
|
filePolicies: FilePolicySettings
|
|
llm: OrgLLMSettings
|
|
search: OrgSearchSettings
|
|
administrators: Administrator[]
|
|
nextcloud: NextcloudSettings
|
|
mailing: MailingSettings
|
|
onlyoffice: OnlyOfficeSettings
|
|
richtext: RichTextSettings
|
|
aiAssistant: AiAssistantSettings
|
|
agenda: AgendaOrgPolicySettings
|
|
meet: MeetOrgPolicySettings
|
|
plugins: PluginEntry[]
|
|
integrations: IntegrationEntry[]
|
|
meta: OrgSettingsMeta | null
|
|
apiSynced: boolean
|
|
} & OrgSettingsActions
|
|
>()((set) => ({
|
|
authentik: DEFAULT_AUTHENTIK,
|
|
identityProviders: DEFAULT_IDENTITY_PROVIDERS,
|
|
twoFactor: DEFAULT_TWO_FACTOR,
|
|
storageQuotas: DEFAULT_STORAGE_QUOTAS,
|
|
usageQuotas: DEFAULT_USAGE_QUOTAS,
|
|
filePolicies: DEFAULT_FILE_POLICIES,
|
|
llm: DEFAULT_LLM,
|
|
search: DEFAULT_SEARCH,
|
|
administrators: [],
|
|
nextcloud: DEFAULT_NEXTCLOUD,
|
|
mailing: DEFAULT_MAILING,
|
|
onlyoffice: DEFAULT_ONLYOFFICE,
|
|
richtext: DEFAULT_RICHTEXT,
|
|
aiAssistant: DEFAULT_AI_ASSISTANT,
|
|
agenda: DEFAULT_AGENDA,
|
|
meet: DEFAULT_MEET,
|
|
plugins: DEFAULT_PLUGINS,
|
|
integrations: DEFAULT_INTEGRATIONS,
|
|
meta: null,
|
|
apiSynced: false,
|
|
|
|
setAuthentik: (patch) =>
|
|
set((s) => ({ authentik: { ...s.authentik, ...patch } })),
|
|
setIdentityProviders: (patch) =>
|
|
set((s) => ({
|
|
identityProviders: { ...s.identityProviders, ...patch },
|
|
})),
|
|
setTwoFactor: (patch) =>
|
|
set((s) => ({ twoFactor: { ...s.twoFactor, ...patch } })),
|
|
setStorageQuotas: (patch) =>
|
|
set((s) => ({ storageQuotas: { ...s.storageQuotas, ...patch } })),
|
|
setUsageQuotas: (patch) =>
|
|
set((s) => ({ usageQuotas: { ...s.usageQuotas, ...patch } })),
|
|
setFilePolicies: (patch) =>
|
|
set((s) => ({ filePolicies: { ...s.filePolicies, ...patch } })),
|
|
setLlm: (patch) => set((s) => ({ llm: { ...s.llm, ...patch } })),
|
|
setSearch: (patch) => set((s) => ({ search: { ...s.search, ...patch } })),
|
|
setNextcloud: (patch) =>
|
|
set((s) => ({ nextcloud: { ...s.nextcloud, ...patch } })),
|
|
setMailing: (patch) =>
|
|
set((s) => ({ mailing: { ...s.mailing, ...patch } })),
|
|
setOnlyoffice: (patch) =>
|
|
set((s) => ({ onlyoffice: { ...s.onlyoffice, ...patch } })),
|
|
setRichtext: (patch) =>
|
|
set((s) => ({ richtext: { ...s.richtext, ...patch } })),
|
|
setAiAssistant: (patch) =>
|
|
set((s) => ({ aiAssistant: { ...s.aiAssistant, ...patch } })),
|
|
setAgenda: (patch) => set((s) => ({ agenda: { ...s.agenda, ...patch } })),
|
|
setMeet: (patch) =>
|
|
set((s) => ({
|
|
meet: {
|
|
...s.meet,
|
|
...patch,
|
|
post_actions: patch.post_actions
|
|
? { ...s.meet.post_actions, ...patch.post_actions }
|
|
: s.meet.post_actions,
|
|
},
|
|
})),
|
|
setAdministrators: (administrators) => set({ administrators }),
|
|
addAdministrator: (admin) =>
|
|
set((s) => ({ administrators: [...s.administrators, admin] })),
|
|
removeAdministrator: (id) =>
|
|
set((s) => ({
|
|
administrators: s.administrators.filter((a) => a.id !== id),
|
|
})),
|
|
updateAdministrator: (id, patch) =>
|
|
set((s) => ({
|
|
administrators: s.administrators.map((a) =>
|
|
a.id === id ? { ...a, ...patch } : a
|
|
),
|
|
})),
|
|
setPlugins: (plugins) => set({ plugins }),
|
|
togglePlugin: (id, enabled) =>
|
|
set((s) => {
|
|
const plugins = s.plugins.map((p) => (p.id === id ? { ...p, enabled } : p))
|
|
if (id === "ai-assistant") {
|
|
return {
|
|
plugins,
|
|
aiAssistant: { ...s.aiAssistant, enabled },
|
|
}
|
|
}
|
|
return { plugins }
|
|
}),
|
|
setIntegrations: (integrations) => set({ integrations }),
|
|
toggleIntegration: (id, enabled) =>
|
|
set((s) => ({
|
|
integrations: s.integrations.map((i) =>
|
|
i.id === id ? { ...i, enabled } : i
|
|
),
|
|
})),
|
|
hydrateFromApi: (patch, meta) =>
|
|
set((s) => ({
|
|
...s,
|
|
...patch,
|
|
meta: meta ?? s.meta,
|
|
apiSynced: true,
|
|
})),
|
|
}))
|