ultisuite-client/components/admin/settings/sections/authentication-section.tsx
R3D347HR4Y 9e9fd208ad
Some checks are pending
E2E / Playwright e2e (push) Waiting to run
feat(admin-settings): enhance admin settings with new components and layout improvements
- Introduced new components for managing admin settings, including AdminListControls, AdminSettingsCard, and TechBrandSelectLabel.
- Implemented dynamic loading for admin settings sections to optimize performance.
- Enhanced the layout of various admin settings sections for better user experience.
- Updated the AiAssistantSection to include LLM provider management and improved model selection.
- Refactored authentication settings to streamline configuration and improve accessibility.
2026-06-15 00:22:20 +02:00

145 lines
6.2 KiB
TypeScript

"use client"
import { useCallback, useRef } from "react"
import { OrgSettingsSection } from "@/components/admin/settings/org-settings-form"
import { AdminSettingsCard } from "@/components/admin/settings/admin-settings-card"
import { FieldGroup } from "@/components/admin/settings/field-group"
import { IdentityProvidersPanel } from "@/components/admin/settings/sections/identity-providers-section"
import { AutomationTabMasonry } from "@/components/gmail/settings/automation/automation-tab-masonry"
import { DeployLockedHint, useDeployFieldLocked } from "@/components/admin/settings/deploy-locked-hint"
import { useOrgSettingsStore } from "@/lib/admin-settings/org-settings-store"
import { Card, CardContent } from "@/components/ui/card"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { Switch } from "@/components/ui/switch"
export function AuthenticationSection() {
const authentik = useOrgSettingsStore((s) => s.authentik)
const setAuthentik = useOrgSettingsStore((s) => s.setAuthentik)
const effective = useOrgSettingsStore((s) => s.meta?.effective.authentik)
const enabledLocked = useDeployFieldLocked("authentik", "enabled")
const apiLocked = useDeployFieldLocked("authentik", "api_url")
const clientLocked = useDeployFieldLocked("authentik", "client_id")
const enabled = enabledLocked ? (effective?.enabled ?? authentik.enabled) : authentik.enabled
const apiURL = apiLocked ? (effective?.api_url ?? authentik.api_url) : authentik.api_url
const clientID = clientLocked ? (effective?.client_id ?? authentik.client_id) : authentik.client_id
const identityBeforeSaveRef = useRef<(() => void) | null>(null)
const registerIdentityBeforeSave = useCallback((fn: (() => void) | null) => {
identityBeforeSaveRef.current = fn
}, [])
return (
<OrgSettingsSection
title="Authentification"
description="SSO Authentik, provisionnement des comptes Ultimail et fournisseurs d'identité upstream."
policySection={["authentik", "identity_providers"]}
beforeSave={async () => {
identityBeforeSaveRef.current?.()
}}
>
<AutomationTabMasonry columns={2}>
<Card className="gap-0 py-0">
<CardContent className="py-4">
<div className="flex items-start gap-4">
<div className="min-w-0 flex-1">
<p className="font-medium">Authentik</p>
<p className="mt-1 text-sm text-muted-foreground">
Connexion via le fournisseur d&apos;identité organisationnel.
</p>
{enabledLocked ? <DeployLockedHint section="authentik" field="enabled" /> : null}
</div>
<Switch
checked={enabled}
disabled={enabledLocked}
onCheckedChange={(v) => setAuthentik({ enabled: v })}
/>
</div>
<div className="mt-4 space-y-4 border-t pt-4">
<FieldGroup>
<Label>URL API Authentik</Label>
<Input
className="h-9"
value={apiURL}
disabled={apiLocked}
onChange={(e) => setAuthentik({ api_url: e.target.value })}
placeholder="https://auth.example.com/api/v3"
/>
{apiLocked ? <DeployLockedHint section="authentik" field="api_url" /> : null}
</FieldGroup>
<div className="grid min-w-0 gap-4">
<FieldGroup>
<Label>Slug application</Label>
<Input
className="h-9"
value={authentik.slug}
onChange={(e) => setAuthentik({ slug: e.target.value })}
/>
</FieldGroup>
<FieldGroup>
<Label>Client ID OIDC</Label>
<Input
className="h-9"
value={clientID}
disabled={clientLocked}
onChange={(e) => setAuthentik({ client_id: e.target.value })}
/>
{clientLocked ? <DeployLockedHint section="authentik" field="client_id" /> : null}
</FieldGroup>
</div>
<FieldGroup>
<Label>Groupes par défaut (séparés par des virgules)</Label>
<Input
className="h-9"
value={authentik.default_groups}
onChange={(e) => setAuthentik({ default_groups: e.target.value })}
/>
</FieldGroup>
<label className="flex items-center justify-between gap-4 rounded-lg border p-3">
<FieldGroup>
<p className="text-sm font-medium">Forcer le SSO</p>
<p className="text-xs text-muted-foreground">
Désactive la connexion locale sauf pour les administrateurs.
</p>
</FieldGroup>
<Switch
checked={authentik.enforce_sso}
onCheckedChange={(enforce_sso) => setAuthentik({ enforce_sso })}
/>
</label>
<label className="flex items-center justify-between gap-4 rounded-lg border p-3">
<FieldGroup>
<p className="text-sm font-medium">Mot de passe local de secours</p>
<p className="text-xs text-muted-foreground">
Autoriser un fallback mot de passe si Authentik est indisponible.
</p>
</FieldGroup>
<Switch
checked={authentik.allow_password_fallback}
onCheckedChange={(allow_password_fallback) =>
setAuthentik({ allow_password_fallback })
}
/>
</label>
</div>
</CardContent>
</Card>
<AdminSettingsCard
title="Fournisseurs d'identité"
description="Sources upstream Authentik (OAuth, SAML, LDAP) avec restrictions d'accès."
>
<IdentityProvidersPanel onRegisterBeforeSave={registerIdentityBeforeSave} />
</AdminSettingsCard>
</AutomationTabMasonry>
</OrgSettingsSection>
)
}