"use client"; import { useState } from "react"; import { Button } from "@/components/ui/button"; import { Separator } from "@/components/ui/separator"; import { Badge } from "@/components/ui/badge"; import { Globe, LogOut, Loader2, Fingerprint, Trash2, Plus, } from "lucide-react"; import { useMutation, useQuery } from "@tanstack/react-query"; import { toast } from "sonner"; import { revokeAllSessionsAction, revokeSessionAction, getPasskeysAction, revokePasskeyAction, } from "./security.action"; import { useRouter } from "next/navigation"; import { ResetPasswordProfileProviderModal } from "./reset-password-modal"; import { SetPasswordProfileProviderModal } from "./set-password-modal"; import { Setup2FAProfileProviderModal } from "./setup-2fa-modal"; import { Disable2FAProfileProviderModal } from "./disable-2fa-modal"; import { ViewBackupCodesModal } from "./view-backup-codes-modal"; import { getDeviceDetails } from "@/utils/detection"; import { timeAgo } from "@/utils/date-formatting"; import { authClient } from "@/lib/auth/auth-client"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Account, Session, User } from "@/db/schema/02_user"; import { Icon } from "@iconify/react"; import Image from "next/image"; import type { AuthProviderConfig } from "@/lib/auth/config"; import { is } from "date-fns/locale"; interface ProfileSecurityProps { user: User; sessions: Session[]; credentialAccount: Account; currentSession: Session; isPasswordEnabled?: boolean; isPasskeyEnabled?: boolean; providers: AuthProviderConfig[]; } export function ProfileSecurity({ user, sessions, credentialAccount, currentSession, isPasswordEnabled = false, isPasskeyEnabled = false, providers, }: ProfileSecurityProps) { const router = useRouter(); const [isBackupCodesDialogOpen, setIsBackupCodesDialogOpen] = useState(false); const [isPasswordDialogOpen, setIsPasswordDialogOpen] = useState(false); const [isSetup2FADialogOpen, setIsSetup2FADialogOpen] = useState(false); const [isDisable2FADialogOpen, setIsDisable2FADialogOpen] = useState(false); const [isAddPasskeyOpen, setIsAddPasskeyOpen] = useState(false); const [passkeyName, setPasskeyName] = useState(""); const { mutate: revokeSession, isPending: isRevoking } = useMutation({ mutationFn: async (token: string) => { const result = await revokeSessionAction({ token }); const inner = result?.data; if (inner?.success) { toast.success("Session successfully revoked"); router.refresh(); } else { toast.error("An error occurred while revoking session"); } }, }); const { mutate: revokeOthers, isPending: isRevokingOthers } = useMutation({ mutationFn: async () => { const result = await revokeAllSessionsAction(); const inner = result?.data; if (inner?.success) { toast.success("Revoking all sessions successfully done."); router.refresh(); } else { toast.error("An error occurred while revoking all sessions"); } }, }); const { data: passkeys, isLoading: isLoadingPasskeys, refetch: refetchPasskeys, } = useQuery({ queryKey: ["passkeys"], queryFn: async () => { const result = await getPasskeysAction(); if (result?.data?.success) { return result.data.value; } throw new Error("Failed to fetch passkeys"); }, }); const { mutate: revokePasskey, isPending: isRevokingPasskey } = useMutation({ mutationFn: async (id: string) => { const result = await revokePasskeyAction({ id }); if (!result?.data?.success) { throw new Error("Failed to revoke passkey"); } }, onSuccess: () => { toast.success("Passkey revoked successfully"); refetchPasskeys(); }, onError: () => { toast.error("Failed to revoke passkey"); }, }); const { mutate: addPasskey, isPending: isAddingPasskey } = useMutation({ mutationFn: async () => { const result = await authClient.passkey.addPasskey({ name: passkeyName || "My Passkey", }); if (result?.error) { throw result.error; } return result; }, onSuccess: () => { toast.success("Passkey added successfully"); setIsAddPasskeyOpen(false); setPasskeyName(""); refetchPasskeys(); }, onError: (error: any) => { toast.error(error.message || "Failed to add passkey"); }, }); return (
Manage your password, two-factor authentication and sessions.