115 lines
3.3 KiB
TypeScript
115 lines
3.3 KiB
TypeScript
"use client"
|
|
|
|
import { ExternalLink, KeyRound, LogOut, Smartphone } from "lucide-react"
|
|
import { SettingsSectionHeader } from "@/components/gmail/settings/settings-section-header"
|
|
import { Button } from "@/components/ui/button"
|
|
import { useAuthLogout } from "@/components/auth/auth-provider"
|
|
import { authentikUserSettingsUrl } from "@/lib/auth/authentik-user-url"
|
|
|
|
export function CompteSecuritySection() {
|
|
const signOut = useAuthLogout()
|
|
const idpUrl = authentikUserSettingsUrl()
|
|
|
|
return (
|
|
<>
|
|
<SettingsSectionHeader
|
|
title="Sécurité"
|
|
description="Paramètres de connexion et de protection de votre compte Ulti."
|
|
/>
|
|
|
|
<div className="space-y-4">
|
|
<SecurityCard
|
|
icon={<KeyRound className="size-5" aria-hidden />}
|
|
title="Mot de passe"
|
|
description="Modifiez votre mot de passe depuis le portail d'identité de votre organisation."
|
|
action={
|
|
idpUrl ? (
|
|
<ExternalAction href={idpUrl} label="Changer le mot de passe" />
|
|
) : (
|
|
<UnavailableNote />
|
|
)
|
|
}
|
|
/>
|
|
|
|
<SecurityCard
|
|
icon={<Smartphone className="size-5" aria-hidden />}
|
|
title="Validation en deux étapes"
|
|
description="Ajoutez ou gérez vos appareils de validation (application TOTP, WebAuthn, clés de sécurité)."
|
|
action={
|
|
idpUrl ? (
|
|
<ExternalAction href={idpUrl} label="Gérer la validation" />
|
|
) : (
|
|
<UnavailableNote />
|
|
)
|
|
}
|
|
/>
|
|
|
|
<SecurityCard
|
|
icon={<LogOut className="size-5" aria-hidden />}
|
|
title="Session sur cet appareil"
|
|
description="Met fin à votre session Ulti sur ce navigateur. Vous devrez vous reconnecter."
|
|
action={
|
|
<Button
|
|
type="button"
|
|
variant="outline"
|
|
className="h-9 rounded-full px-4 text-sm font-medium"
|
|
onClick={() => void signOut()}
|
|
>
|
|
Se déconnecter
|
|
</Button>
|
|
}
|
|
/>
|
|
</div>
|
|
</>
|
|
)
|
|
}
|
|
|
|
function SecurityCard({
|
|
icon,
|
|
title,
|
|
description,
|
|
action,
|
|
}: {
|
|
icon: React.ReactNode
|
|
title: string
|
|
description: string
|
|
action: React.ReactNode
|
|
}) {
|
|
return (
|
|
<div className="flex flex-col gap-3 rounded-2xl border border-border bg-background p-5 sm:flex-row sm:items-center sm:gap-4">
|
|
<span className="flex size-10 shrink-0 items-center justify-center rounded-full bg-accent text-muted-foreground">
|
|
{icon}
|
|
</span>
|
|
<div className="min-w-0 flex-1">
|
|
<h3 className="text-sm font-medium text-foreground">{title}</h3>
|
|
<p className="mt-0.5 text-sm text-muted-foreground">{description}</p>
|
|
</div>
|
|
<div className="shrink-0">{action}</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
function ExternalAction({ href, label }: { href: string; label: string }) {
|
|
return (
|
|
<Button
|
|
type="button"
|
|
variant="outline"
|
|
className="h-9 rounded-full px-4 text-sm font-medium"
|
|
asChild
|
|
>
|
|
<a href={href} target="_blank" rel="noreferrer">
|
|
{label}
|
|
<ExternalLink className="size-3.5" aria-hidden />
|
|
</a>
|
|
</Button>
|
|
)
|
|
}
|
|
|
|
function UnavailableNote() {
|
|
return (
|
|
<span className="text-xs text-muted-foreground">
|
|
Portail d'identité non configuré
|
|
</span>
|
|
)
|
|
}
|