feat: Add password change UI to admin dashboard
NEW FEATURE: Password Change Form on Admin Dashboard TEMPLATE CHANGES (admin.ctml): - Added 'Account Security' section after System Status - Password change form with: - Current password field - New password field (min 8 characters) - Confirm password field - Submit button - Message display area for feedback JAVASCRIPT CHANGES (admin.js): - changeAdminPassword(event) function - Validates passwords match - Validates minimum length (8 chars) - Calls /api/asteroid/user/change-password - Shows success/error messages - Clears form on success - showPasswordMessage(message, type) helper - Displays success/error messages - Auto-hides success messages after 5 seconds USER EXPERIENCE: 1. Admin logs in with default password (asteroid123) 2. Sees 'Account Security' section at top of dashboard 3. Fills in current password and new password 4. Clicks 'Change Password' 5. Gets immediate feedback 6. Password is changed - use new password on next login This makes it easy for admins to change the default password without needing REPL access or curl commands. Ref: TODO.org Problem 4 - Security improvements
This commit is contained in:
parent
86eef472a9
commit
356c6fbb49
|
|
@ -658,3 +658,70 @@ async function updateLiveStreamInfo() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Password change functionality
|
||||
function changeAdminPassword(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const currentPassword = document.getElementById('current-password').value;
|
||||
const newPassword = document.getElementById('new-password').value;
|
||||
const confirmPassword = document.getElementById('confirm-password').value;
|
||||
const messageEl = document.getElementById('password-message');
|
||||
|
||||
// Clear previous messages
|
||||
messageEl.style.display = 'none';
|
||||
messageEl.className = 'message';
|
||||
|
||||
// Validate passwords match
|
||||
if (newPassword !== confirmPassword) {
|
||||
showPasswordMessage('New passwords do not match', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate password length
|
||||
if (newPassword.length < 8) {
|
||||
showPasswordMessage('Password must be at least 8 characters', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// Submit password change
|
||||
const formData = new URLSearchParams();
|
||||
formData.append('current-password', currentPassword);
|
||||
formData.append('new-password', newPassword);
|
||||
|
||||
fetch('/api/asteroid/user/change-password', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
body: formData
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.status === 'success') {
|
||||
showPasswordMessage('Password changed successfully! Please use your new password on next login.', 'success');
|
||||
// Clear form
|
||||
document.getElementById('change-password-form').reset();
|
||||
} else {
|
||||
showPasswordMessage(data.message || 'Failed to change password', 'error');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error changing password:', error);
|
||||
showPasswordMessage('Error changing password. Please try again.', 'error');
|
||||
});
|
||||
}
|
||||
|
||||
function showPasswordMessage(message, type) {
|
||||
const messageEl = document.getElementById('password-message');
|
||||
messageEl.textContent = message;
|
||||
messageEl.className = 'message ' + type;
|
||||
messageEl.style.display = 'block';
|
||||
|
||||
// Auto-hide success messages after 5 seconds
|
||||
if (type === 'success') {
|
||||
setTimeout(() => {
|
||||
messageEl.style.display = 'none';
|
||||
}, 5000);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,31 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Admin Account Security -->
|
||||
<div class="admin-section">
|
||||
<h2>🔒 Account Security</h2>
|
||||
<div class="password-change-form">
|
||||
<h3>Change Your Password</h3>
|
||||
<div id="password-message" class="message" style="display: none;"></div>
|
||||
<form id="change-password-form" onsubmit="changeAdminPassword(event)">
|
||||
<div class="form-group">
|
||||
<label for="current-password">Current Password:</label>
|
||||
<input type="password" id="current-password" name="current-password" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="new-password">New Password:</label>
|
||||
<input type="password" id="new-password" name="new-password" required minlength="8">
|
||||
<small>Minimum 8 characters</small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="confirm-password">Confirm New Password:</label>
|
||||
<input type="password" id="confirm-password" name="confirm-password" required>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Change Password</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Music Library Management -->
|
||||
<div class="admin-section">
|
||||
<h2>Music Library Management</h2>
|
||||
|
|
|
|||
Loading…
Reference in New Issue