import { Component, createSignal, Show } from 'solid-js'; import { Portal } from 'solid-js/web'; import { showSuccess, showError } from '@/utils/toast'; import { SectionHeader } from '@/components/shared/SectionHeader'; import { formField, labelClass, controlClass, formHelpText } from '@/components/shared/Form'; interface ChangePasswordModalProps { isOpen: boolean; onClose: () => void; } export const ChangePasswordModal: Component = (props) => { const [currentPassword, setCurrentPassword] = createSignal(''); const [newPassword, setNewPassword] = createSignal(''); const [confirmPassword, setConfirmPassword] = createSignal(''); const [loading, setLoading] = createSignal(false); const [error, setError] = createSignal(''); const handleSubmit = async (e: Event) => { e.preventDefault(); setError(''); // Validation if (!currentPassword() || !newPassword() || !confirmPassword()) { setError('All fields are required'); return; } if (newPassword() !== confirmPassword()) { setError('New passwords do not match'); return; } if (newPassword().length < 8) { setError('Password must be at least 8 characters'); return; } setLoading(true); try { // Get CSRF token from cookie const csrfToken = document.cookie .split('; ') .find((row) => row.startsWith('pulse_csrf=')) ?.split('=')[1]; // Get the actual username from sessionStorage or use 'admin' as fallback const authUser = sessionStorage.getItem('pulse_auth_user') || 'admin'; const headers: Record = { 'Content-Type': 'application/json', Authorization: `Basic ${btoa(`${authUser}:${currentPassword()}`)}`, }; // Add CSRF token if available if (csrfToken) { headers['X-CSRF-Token'] = csrfToken; } const response = await fetch('/api/security/change-password', { method: 'POST', headers, body: JSON.stringify({ currentPassword: currentPassword(), newPassword: newPassword(), }), credentials: 'include', }); if (!response.ok) { const text = await response.text(); if (response.status === 401) { throw new Error('Current password is incorrect'); } throw new Error(text || 'Failed to change password'); } showSuccess('Password changed successfully. Please log in with your new password.'); // Clear form setCurrentPassword(''); setNewPassword(''); setConfirmPassword(''); // Close modal and trigger re-authentication props.onClose(); // Reload page to force re-login with new password setTimeout(() => { window.location.reload(); }, 2000); } catch (err) { const errorMessage = err instanceof Error ? err.message : 'Failed to change password'; setError(errorMessage); showError(errorMessage); } finally { setLoading(false); } }; const handleClose = () => { if (!loading()) { setCurrentPassword(''); setNewPassword(''); setConfirmPassword(''); setError(''); props.onClose(); } }; return (
setCurrentPassword(e.currentTarget.value)} class={controlClass('shadow-sm')} required disabled={loading()} />
setNewPassword(e.currentTarget.value)} class={controlClass('shadow-sm')} required disabled={loading()} minLength={8} />

Minimum 8 characters

setConfirmPassword(e.currentTarget.value)} class={controlClass('shadow-sm')} required disabled={loading()} />

{error()}

); };