diff --git a/src/components/settings/pages/security-settings-content.tsx b/src/components/settings/pages/security-settings-content.tsx index 05718669..f0d63fda 100644 --- a/src/components/settings/pages/security-settings-content.tsx +++ b/src/components/settings/pages/security-settings-content.tsx @@ -1,3 +1,188 @@ +import React, { useState } from 'react'; +import { createAuthClient } from 'better-auth/client'; +import { Button } from '@/components/ui/button'; +import { Input } from '@/components/ui/input'; +import { Label } from '@/components/ui/label'; +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; +import { Separator } from '@/components/ui/separator'; +import { AlertCircle, LogOut, Shield, Lock } from 'lucide-react'; +import { Alert, AlertDescription } from '@/components/ui/alert'; +import { forceLogout } from "@/lib/auth/logout"; + + export function SecuritySettingsContent() { - return <>Security coming soon...; -} + const [currentPassword, setCurrentPassword] = useState(''); + const [newPassword, setNewPassword] = useState(''); + const [confirmPassword, setConfirmPassword] = useState(''); + const [loading, setLoading] = useState(false); + const [message, setMessage] = useState<{ type: 'success' | 'error'; text: string } | null>(null); + + const authClient = createAuthClient() + + const handleLogout = async () => { + await forceLogout(); + }; + + const handleRevokeAllSessions = async () => { + try { + setLoading(true); + await authClient.revokeOtherSessions(); + setMessage({ type: 'success', text: 'All other sessions have been revoked' }); + } catch (error) { + setMessage({ type: 'error', text: 'Failed to revoke sessions. Please try again.' }); + } finally { + setLoading(false); + } + }; + + const handleChangePassword = async () => { + setMessage(null); + + if (newPassword !== confirmPassword) { + setMessage({ type: 'error', text: 'New passwords do not match' }); + return; + } + + if (newPassword.length < 8) { + setMessage({ type: 'error', text: 'Password must be at least 8 characters long' }); + return; + } + + try { + setLoading(true); + await authClient.changePassword({ + currentPassword, + newPassword, + revokeOtherSessions: false, + }); + setMessage({ type: 'success', text: 'Password changed successfully' }); + setCurrentPassword(''); + setNewPassword(''); + setConfirmPassword(''); + } catch (error) { + setMessage({ type: 'error', text: 'Failed to change password. Please check your current password.' }); + } finally { + setLoading(false); + } + }; + + return ( +
+
+

Security

+

+ Manage your account security and sessions +

+
+ + + {message && ( + + + {message.text} + + )} + + + + + + Change Password + + + Update your password to keep your account secure + + + +
+
+ + setCurrentPassword(e.target.value)} + disabled={loading} + /> +
+
+ + setNewPassword(e.target.value)} + disabled={loading} + /> +
+
+ + setConfirmPassword(e.target.value)} + disabled={loading} + /> +
+ +
+
+
+ + + + + + Session Management + + + Manage your active sessions across all devices + + + +
+
+

Logout from all devices

+

+ End all sessions except the current one +

+
+ +
+
+
+ + + + + + Logout + + + Sign out of your account on this device + + + + + + +
+ ); +} \ No newline at end of file diff --git a/src/components/settings/settings-dialog.tsx b/src/components/settings/settings-dialog.tsx index 6c4a9e03..c1715091 100644 --- a/src/components/settings/settings-dialog.tsx +++ b/src/components/settings/settings-dialog.tsx @@ -56,7 +56,7 @@ export const SettingsDialog = NiceModal.create(() => {