UNPKG

@frank-auth/react

Version:

Flexible and customizable React UI components for Frank Authentication

1 lines 31.2 kB
{"version":3,"file":"security-panel.cjs","sources":["../../../../../src/components/auth/user-profile/security-panel.tsx"],"sourcesContent":["/**\n * @frank-auth/react - Security Panel Component\n *\n * Security settings panel for password management, session control,\n * and account security configuration.\n */\n\n\"use client\";\n\nimport {\n\tButton,\n\tCard,\n\tCardBody,\n\tCardHeader,\n\tChip,\n\tDivider,\n\tModal,\n\tModalBody,\n\tModalContent,\n\tModalHeader,\n\tSwitch,\n\tuseDisclosure,\n} from \"@heroui/react\";\nimport React from \"react\";\nimport { useAuth } from \"../../../hooks/use-auth\";\nimport { useConfig } from \"../../../hooks/use-config\";\nimport { useSession } from \"../../../hooks/use-session\";\nimport { useUser } from \"../../../hooks/use-user\";\nimport { PasswordField } from \"../../forms/password-field\";\n\n// ============================================================================\n// Security Panel Interface\n// ============================================================================\n\nexport interface SecurityPanelProps {\n\t/**\n\t * Success callback\n\t */\n\tonSuccess?: (message: string) => void;\n\n\t/**\n\t * Error callback\n\t */\n\tonError?: (error: string) => void;\n\n\t/**\n\t * Show password change section\n\t */\n\tshowPasswordChange?: boolean;\n\n\t/**\n\t * Show session management\n\t */\n\tshowSessionManagement?: boolean;\n\n\t/**\n\t * Show security preferences\n\t */\n\tshowSecurityPreferences?: boolean;\n\n\t/**\n\t * Show activity log\n\t */\n\tshowActivityLog?: boolean;\n\n\t/**\n\t * Custom className\n\t */\n\tclassName?: string;\n\n\t/**\n\t * Whether panel is disabled\n\t */\n\tisDisabled?: boolean;\n\n\t/**\n\t * Panel variant\n\t */\n\tvariant?: \"flat\" | \"bordered\" | \"shadow\";\n\n\t/**\n\t * Panel size\n\t */\n\tsize?: \"sm\" | \"md\" | \"lg\";\n\n\t/**\n\t * Custom sections\n\t */\n\tcustomSections?: SecurityPanelSection[];\n\n\t/**\n\t * Hide default sections\n\t */\n\thideSections?: string[];\n}\n\nexport interface SecurityPanelSection {\n\tkey: string;\n\ttitle: string;\n\tdescription?: string;\n\ticon?: React.ReactNode;\n\tcontent: React.ReactNode;\n}\n\n// ============================================================================\n// Change Password Form Interface\n// ============================================================================\n\ninterface ChangePasswordFormProps {\n\tonSuccess: (message: string) => void;\n\tonError: (error: string) => void;\n\tonClose: () => void;\n\tisOpen: boolean;\n}\n\n// ============================================================================\n// Device Info Interface\n// ============================================================================\n\ninterface DeviceInfo {\n\tbrowser: string;\n\tos: string;\n\tdevice: string;\n\tlocation?: string;\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\nfunction getDeviceIcon(deviceInfo: any) {\n\tconst device = deviceInfo?.device?.toLowerCase() || \"\";\n\tconst os = deviceInfo?.os?.toLowerCase() || \"\";\n\n\tif (\n\t\tdevice.includes(\"mobile\") ||\n\t\tos.includes(\"ios\") ||\n\t\tos.includes(\"android\")\n\t) {\n\t\treturn (\n\t\t\t<svg\n\t\t\t\tclassName=\"w-5 h-5 text-default-400\"\n\t\t\t\tfill=\"none\"\n\t\t\t\tstroke=\"currentColor\"\n\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t>\n\t\t\t\t<path\n\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\tstrokeWidth={2}\n\t\t\t\t\td=\"M12 18h.01M8 21h8a1 1 0 001-1V4a1 1 0 00-1-1H8a1 1 0 00-1 1v16a1 1 0 001 1z\"\n\t\t\t\t/>\n\t\t\t</svg>\n\t\t);\n\t}\n\n\treturn (\n\t\t<svg\n\t\t\tclassName=\"w-5 h-5 text-default-400\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t>\n\t\t\t<path\n\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\tstrokeWidth={2}\n\t\t\t\td=\"M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z\"\n\t\t\t/>\n\t\t</svg>\n\t);\n}\n\nfunction formatLastActive(date: Date | null): string {\n\tif (!date) return \"Never\";\n\n\tconst now = new Date();\n\tconst diff = now.getTime() - date.getTime();\n\tconst minutes = Math.floor(diff / (1000 * 60));\n\tconst hours = Math.floor(diff / (1000 * 60 * 60));\n\tconst days = Math.floor(diff / (1000 * 60 * 60 * 24));\n\n\tif (minutes < 1) return \"Just now\";\n\tif (minutes < 60) return `${minutes}m ago`;\n\tif (hours < 24) return `${hours}h ago`;\n\treturn `${days}d ago`;\n}\n\n// ============================================================================\n// Change Password Form Component\n// ============================================================================\n\nfunction ChangePasswordForm({\n\tonSuccess,\n\tonError,\n\tonClose,\n\tisOpen,\n}: ChangePasswordFormProps) {\n\tconst { changePassword } = useUser();\n\n\tconst [currentPassword, setCurrentPassword] = React.useState(\"\");\n\tconst [newPassword, setNewPassword] = React.useState(\"\");\n\tconst [confirmPassword, setConfirmPassword] = React.useState(\"\");\n\tconst [isLoading, setIsLoading] = React.useState(false);\n\tconst [errors, setErrors] = React.useState<Record<string, string>>({});\n\n\t// Reset form when modal opens/closes\n\tReact.useEffect(() => {\n\t\tif (!isOpen) {\n\t\t\tsetCurrentPassword(\"\");\n\t\t\tsetNewPassword(\"\");\n\t\t\tsetConfirmPassword(\"\");\n\t\t\tsetErrors({});\n\t\t}\n\t}, [isOpen]);\n\n\t// Validate form\n\tconst validateForm = () => {\n\t\tconst newErrors: Record<string, string> = {};\n\n\t\tif (!currentPassword) {\n\t\t\tnewErrors.currentPassword = \"Current password is required\";\n\t\t}\n\n\t\tif (!newPassword) {\n\t\t\tnewErrors.newPassword = \"New password is required\";\n\t\t} else if (newPassword.length < 8) {\n\t\t\tnewErrors.newPassword = \"Password must be at least 8 characters\";\n\t\t}\n\n\t\tif (!confirmPassword) {\n\t\t\tnewErrors.confirmPassword = \"Please confirm your new password\";\n\t\t} else if (newPassword !== confirmPassword) {\n\t\t\tnewErrors.confirmPassword = \"Passwords do not match\";\n\t\t}\n\n\t\tsetErrors(newErrors);\n\t\treturn Object.keys(newErrors).length === 0;\n\t};\n\n\t// Handle form submission\n\tconst handleSubmit = async (e: React.FormEvent) => {\n\t\te.preventDefault();\n\n\t\tif (!validateForm()) return;\n\n\t\ttry {\n\t\t\tsetIsLoading(true);\n\n\t\t\tawait changePassword({\n\t\t\t\tcurrentPassword,\n\t\t\t\tnewPassword,\n\t\t\t});\n\n\t\t\tonSuccess(\"Password changed successfully\");\n\t\t\tonClose();\n\t\t} catch (error) {\n\t\t\tconst message =\n\t\t\t\terror instanceof Error ? error.message : \"Failed to change password\";\n\t\t\tonError(message);\n\t\t} finally {\n\t\t\tsetIsLoading(false);\n\t\t}\n\t};\n\n\treturn (\n\t\t<form onSubmit={handleSubmit} className=\"space-y-4\">\n\t\t\t<PasswordField\n\t\t\t\tlabel=\"Current Password\"\n\t\t\t\tplaceholder=\"Enter your current password\"\n\t\t\t\tvalue={currentPassword}\n\t\t\t\tonChange={setCurrentPassword}\n\t\t\t\terror={errors.currentPassword}\n\t\t\t\trequired\n\t\t\t/>\n\n\t\t\t<PasswordField\n\t\t\t\tlabel=\"New Password\"\n\t\t\t\tplaceholder=\"Enter your new password\"\n\t\t\t\tvalue={newPassword}\n\t\t\t\tonChange={setNewPassword}\n\t\t\t\terror={errors.newPassword}\n\t\t\t\tshowStrength\n\t\t\t\trequired\n\t\t\t/>\n\n\t\t\t<PasswordField\n\t\t\t\tlabel=\"Confirm New Password\"\n\t\t\t\tplaceholder=\"Confirm your new password\"\n\t\t\t\tvalue={confirmPassword}\n\t\t\t\tonChange={setConfirmPassword}\n\t\t\t\terror={errors.confirmPassword}\n\t\t\t\trequired\n\t\t\t/>\n\n\t\t\t<div className=\"flex justify-end gap-2 pt-4\">\n\t\t\t\t<Button variant=\"light\" onPress={onClose} isDisabled={isLoading}>\n\t\t\t\t\tCancel\n\t\t\t\t</Button>\n\t\t\t\t<Button\n\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\tcolor=\"primary\"\n\t\t\t\t\tisLoading={isLoading}\n\t\t\t\t\tisDisabled={!currentPassword || !newPassword || !confirmPassword}\n\t\t\t\t>\n\t\t\t\t\tChange Password\n\t\t\t\t</Button>\n\t\t\t</div>\n\t\t</form>\n\t);\n}\n\n// ============================================================================\n// Security Panel Component\n// ============================================================================\n\nexport function SecurityPanel({\n\tonSuccess,\n\tonError,\n\tshowPasswordChange = true,\n\tshowSessionManagement = true,\n\tshowSecurityPreferences = false,\n\tshowActivityLog = false,\n\tclassName = \"\",\n\tisDisabled = false,\n\tvariant = \"bordered\",\n\tsize = \"md\",\n\tcustomSections = [],\n\thideSections = [],\n}: SecurityPanelProps) {\n\tconst { user } = useAuth();\n\tconst {\n\t\tsessions,\n\t\tisCurrentDevice,\n\t\thasMultipleSessions,\n\t\trevokeSession,\n\t\trevokeAllSessions,\n\t} = useSession();\n\tconst { components } = useConfig();\n\n\tconst changePasswordModal = useDisclosure();\n\n\t// Custom component override\n\tconst CustomSecurityPanel = components.SecurityPanel;\n\tif (CustomSecurityPanel) {\n\t\treturn (\n\t\t\t<CustomSecurityPanel\n\t\t\t\t{...{\n\t\t\t\t\tonSuccess,\n\t\t\t\t\tonError,\n\t\t\t\t\tshowPasswordChange,\n\t\t\t\t\tshowSessionManagement,\n\t\t\t\t\tshowSecurityPreferences,\n\t\t\t\t\tshowActivityLog,\n\t\t\t\t\tclassName,\n\t\t\t\t\tisDisabled,\n\t\t\t\t\tvariant,\n\t\t\t\t\tsize,\n\t\t\t\t\tcustomSections,\n\t\t\t\t\thideSections,\n\t\t\t\t}}\n\t\t\t/>\n\t\t);\n\t}\n\n\t// Handle session revocation\n\tconst handleRevokeSession = async (sessionId: string) => {\n\t\ttry {\n\t\t\tawait revokeSession(sessionId);\n\t\t\tonSuccess?.(\"Session revoked successfully\");\n\t\t} catch (error) {\n\t\t\tconst message =\n\t\t\t\terror instanceof Error ? error.message : \"Failed to revoke session\";\n\t\t\tonError?.(message);\n\t\t}\n\t};\n\n\t// Handle revoking all other sessions\n\tconst handleRevokeAllOthers = async () => {\n\t\ttry {\n\t\t\tawait revokeAllSessions(true);\n\t\t\tonSuccess?.(\"All other sessions revoked successfully\");\n\t\t} catch (error) {\n\t\t\tconst message =\n\t\t\t\terror instanceof Error ? error.message : \"Failed to revoke sessions\";\n\t\t\tonError?.(message);\n\t\t}\n\t};\n\n\t// Don't render if no user\n\tif (!user) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<div className={`space-y-6 ${className}`}>\n\t\t\t{/* Password Security */}\n\t\t\t{showPasswordChange && !hideSections.includes(\"password\") && (\n\t\t\t\t<Card variant={variant}>\n\t\t\t\t\t<CardHeader>\n\t\t\t\t\t\t<div className=\"flex items-center gap-3\">\n\t\t\t\t\t\t\t<div className=\"flex items-center justify-center w-10 h-10 bg-primary/10 rounded-lg\">\n\t\t\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\t\t\tclassName=\"w-5 h-5 text-primary\"\n\t\t\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<path\n\t\t\t\t\t\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\t\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\t\t\t\t\t\tstrokeWidth={2}\n\t\t\t\t\t\t\t\t\t\td=\"M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z\"\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t<h4 className=\"text-md font-semibold\">Password</h4>\n\t\t\t\t\t\t\t\t<p className=\"text-sm text-default-500\">\n\t\t\t\t\t\t\t\t\tManage your password and account security\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</CardHeader>\n\t\t\t\t\t<Divider />\n\t\t\t\t\t<CardBody>\n\t\t\t\t\t\t<div className=\"flex items-center justify-between\">\n\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t<p className=\"text-sm font-medium\">Password</p>\n\t\t\t\t\t\t\t\t<p className=\"text-xs text-default-500\">\n\t\t\t\t\t\t\t\t\tLast changed:{\" \"}\n\t\t\t\t\t\t\t\t\t{user.passwordUpdatedAt\n\t\t\t\t\t\t\t\t\t\t? new Date(user.passwordUpdatedAt).toLocaleDateString()\n\t\t\t\t\t\t\t\t\t\t: \"Unknown\"}\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\tvariant=\"bordered\"\n\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\tonPress={changePasswordModal.onOpen}\n\t\t\t\t\t\t\t\tisDisabled={isDisabled}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tChange Password\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</CardBody>\n\t\t\t\t</Card>\n\t\t\t)}\n\n\t\t\t{/* Active Sessions */}\n\t\t\t{showSessionManagement && !hideSections.includes(\"sessions\") && (\n\t\t\t\t<Card variant={variant}>\n\t\t\t\t\t<CardHeader>\n\t\t\t\t\t\t<div className=\"flex items-center justify-between w-full\">\n\t\t\t\t\t\t\t<div className=\"flex items-center gap-3\">\n\t\t\t\t\t\t\t\t<div className=\"flex items-center justify-center w-10 h-10 bg-warning/10 rounded-lg\">\n\t\t\t\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\t\t\t\tclassName=\"w-5 h-5 text-warning\"\n\t\t\t\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<path\n\t\t\t\t\t\t\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\t\t\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\t\t\t\t\t\t\tstrokeWidth={2}\n\t\t\t\t\t\t\t\t\t\t\td=\"M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z\"\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t\t<h4 className=\"text-md font-semibold\">Active Sessions</h4>\n\t\t\t\t\t\t\t\t\t<p className=\"text-sm text-default-500\">\n\t\t\t\t\t\t\t\t\t\tManage devices that are signed into your account\n\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t{hasMultipleSessions && (\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\tvariant=\"light\"\n\t\t\t\t\t\t\t\t\tcolor=\"danger\"\n\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\tonPress={handleRevokeAllOthers}\n\t\t\t\t\t\t\t\t\tisDisabled={isDisabled}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tSign out all others\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</CardHeader>\n\t\t\t\t\t<Divider />\n\t\t\t\t\t<CardBody>\n\t\t\t\t\t\t<div className=\"space-y-3\">\n\t\t\t\t\t\t\t{sessions.map((session, index) => {\n\t\t\t\t\t\t\t\tconst isCurrent = index === 0; // Assuming first session is current\n\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tkey={session.id}\n\t\t\t\t\t\t\t\t\t\tclassName=\"flex items-center justify-between p-3 border border-default-200 rounded-lg\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<div className=\"flex items-center gap-3\">\n\t\t\t\t\t\t\t\t\t\t\t{getDeviceIcon(session.deviceInfo)}\n\n\t\t\t\t\t\t\t\t\t\t\t<div className=\"flex flex-col\">\n\t\t\t\t\t\t\t\t\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"text-sm font-medium\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{session.deviceInfo?.browser || \"Unknown Browser\"}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{isCurrent && (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<Chip size=\"sm\" color=\"success\" variant=\"flat\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tCurrent\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</Chip>\n\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t\t\t\t\t<div className=\"flex items-center gap-2 text-xs text-default-500\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span>{session.deviceInfo?.os || \"Unknown OS\"}</span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span>•</span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{session.deviceInfo?.location || \"Unknown Location\"}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span>•</span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tActive {formatLastActive(session.lastActiveAt)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t\t\t{!isCurrent && (\n\t\t\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\t\t\tvariant=\"light\"\n\t\t\t\t\t\t\t\t\t\t\t\tcolor=\"danger\"\n\t\t\t\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\t\t\t\tonPress={() => handleRevokeSession(session.id)}\n\t\t\t\t\t\t\t\t\t\t\t\tisDisabled={isDisabled}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\tSign out\n\t\t\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</CardBody>\n\t\t\t\t</Card>\n\t\t\t)}\n\n\t\t\t{/* Security Preferences */}\n\t\t\t{showSecurityPreferences && !hideSections.includes(\"preferences\") && (\n\t\t\t\t<Card variant={variant}>\n\t\t\t\t\t<CardHeader>\n\t\t\t\t\t\t<div className=\"flex items-center gap-3\">\n\t\t\t\t\t\t\t<div className=\"flex items-center justify-center w-10 h-10 bg-secondary/10 rounded-lg\">\n\t\t\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\t\t\tclassName=\"w-5 h-5 text-secondary\"\n\t\t\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<path\n\t\t\t\t\t\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\t\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\t\t\t\t\t\tstrokeWidth={2}\n\t\t\t\t\t\t\t\t\t\td=\"M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z\"\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t<h4 className=\"text-md font-semibold\">Security Preferences</h4>\n\t\t\t\t\t\t\t\t<p className=\"text-sm text-default-500\">\n\t\t\t\t\t\t\t\t\tConfigure your security and privacy settings\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</CardHeader>\n\t\t\t\t\t<Divider />\n\t\t\t\t\t<CardBody>\n\t\t\t\t\t\t<div className=\"space-y-4\">\n\t\t\t\t\t\t\t<div className=\"flex items-center justify-between\">\n\t\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t\t<p className=\"text-sm font-medium\">\n\t\t\t\t\t\t\t\t\t\tEmail notifications for sign-ins\n\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t\t<p className=\"text-xs text-default-500\">\n\t\t\t\t\t\t\t\t\t\tGet notified when someone signs into your account\n\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<Switch defaultSelected size=\"sm\" isDisabled={isDisabled} />\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t<div className=\"flex items-center justify-between\">\n\t\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t\t<p className=\"text-sm font-medium\">\n\t\t\t\t\t\t\t\t\t\tTwo-factor authentication\n\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t\t<p className=\"text-xs text-default-500\">\n\t\t\t\t\t\t\t\t\t\tAdd an extra layer of security to your account\n\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<Switch\n\t\t\t\t\t\t\t\t\tisSelected={user.mfaEnabled}\n\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\tisDisabled={isDisabled}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t<div className=\"flex items-center justify-between\">\n\t\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t\t<p className=\"text-sm font-medium\">Session timeout</p>\n\t\t\t\t\t\t\t\t\t<p className=\"text-xs text-default-500\">\n\t\t\t\t\t\t\t\t\t\tAutomatically sign out after inactivity\n\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<Switch defaultSelected size=\"sm\" isDisabled={isDisabled} />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</CardBody>\n\t\t\t\t</Card>\n\t\t\t)}\n\n\t\t\t{/* Custom Sections */}\n\t\t\t{customSections.map(\n\t\t\t\t(section) =>\n\t\t\t\t\t!hideSections.includes(section.key) && (\n\t\t\t\t\t\t<Card key={section.key} variant={variant}>\n\t\t\t\t\t\t\t<CardHeader>\n\t\t\t\t\t\t\t\t<div className=\"flex items-center gap-3\">\n\t\t\t\t\t\t\t\t\t{section.icon && (\n\t\t\t\t\t\t\t\t\t\t<div className=\"flex items-center justify-center w-10 h-10 bg-default/10 rounded-lg\">\n\t\t\t\t\t\t\t\t\t\t\t{section.icon}\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t\t\t<h4 className=\"text-md font-semibold\">{section.title}</h4>\n\t\t\t\t\t\t\t\t\t\t{section.description && (\n\t\t\t\t\t\t\t\t\t\t\t<p className=\"text-sm text-default-500\">\n\t\t\t\t\t\t\t\t\t\t\t\t{section.description}\n\t\t\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</CardHeader>\n\t\t\t\t\t\t\t<Divider />\n\t\t\t\t\t\t\t<CardBody>{section.content}</CardBody>\n\t\t\t\t\t\t</Card>\n\t\t\t\t\t),\n\t\t\t)}\n\n\t\t\t{/* Change Password Modal */}\n\t\t\t<Modal\n\t\t\t\tisOpen={changePasswordModal.isOpen}\n\t\t\t\tonOpenChange={changePasswordModal.onOpenChange}\n\t\t\t\tplacement=\"center\"\n\t\t\t\tsize=\"md\"\n\t\t\t>\n\t\t\t\t<ModalContent>\n\t\t\t\t\t{(onClose) => (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<ModalHeader>\n\t\t\t\t\t\t\t\t<h3 className=\"text-lg font-semibold\">Change Password</h3>\n\t\t\t\t\t\t\t</ModalHeader>\n\t\t\t\t\t\t\t<ModalBody>\n\t\t\t\t\t\t\t\t<ChangePasswordForm\n\t\t\t\t\t\t\t\t\tonSuccess={(message) => {\n\t\t\t\t\t\t\t\t\t\tonSuccess?.(message);\n\t\t\t\t\t\t\t\t\t\tonClose();\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\tonError={(error) => onError?.(error)}\n\t\t\t\t\t\t\t\t\tonClose={onClose}\n\t\t\t\t\t\t\t\t\tisOpen={changePasswordModal.isOpen}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</ModalBody>\n\t\t\t\t\t\t</>\n\t\t\t\t\t)}\n\t\t\t\t</ModalContent>\n\t\t\t</Modal>\n\t\t</div>\n\t);\n}\n\n// ============================================================================\n// Export\n// ============================================================================\n\nexport default SecurityPanel;\n"],"names":["getDeviceIcon","deviceInfo","device","os","jsx","formatLastActive","date","diff","minutes","hours","days","ChangePasswordForm","onSuccess","onError","onClose","isOpen","changePassword","useUser","currentPassword","setCurrentPassword","React","newPassword","setNewPassword","confirmPassword","setConfirmPassword","isLoading","setIsLoading","errors","setErrors","validateForm","newErrors","handleSubmit","e","error","message","jsxs","PasswordField","Button","SecurityPanel","showPasswordChange","showSessionManagement","showSecurityPreferences","showActivityLog","className","isDisabled","variant","size","customSections","hideSections","user","useAuth","sessions","isCurrentDevice","hasMultipleSessions","revokeSession","revokeAllSessions","useSession","components","useConfig","changePasswordModal","useDisclosure","CustomSecurityPanel","handleRevokeSession","sessionId","handleRevokeAllOthers","Card","CardHeader","Divider","CardBody","session","index","isCurrent","Chip","Switch","section","Modal","ModalContent","Fragment","ModalHeader","ModalBody"],"mappings":"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"}