|
|
@@ -180,6 +180,70 @@
|
|
|
color: #666;
|
|
|
}
|
|
|
|
|
|
+ .change-password-section {
|
|
|
+ background: white;
|
|
|
+ padding: 20px;
|
|
|
+ border-radius: 8px;
|
|
|
+ margin-bottom: 15px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .change-password-section h3 {
|
|
|
+ color: #333;
|
|
|
+ margin-bottom: 15px;
|
|
|
+ font-size: 1.1rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .action-buttons {
|
|
|
+ margin-bottom: 15px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .action-btn {
|
|
|
+ width: 100%;
|
|
|
+ padding: 12px;
|
|
|
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
|
+ color: white;
|
|
|
+ border: none;
|
|
|
+ border-radius: 8px;
|
|
|
+ font-size: 0.95rem;
|
|
|
+ font-weight: 500;
|
|
|
+ cursor: pointer;
|
|
|
+ transition: all 0.3s ease;
|
|
|
+ }
|
|
|
+
|
|
|
+ .action-btn:hover {
|
|
|
+ transform: translateY(-1px);
|
|
|
+ box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
|
|
|
+ }
|
|
|
+
|
|
|
+ .form-buttons {
|
|
|
+ display: flex;
|
|
|
+ gap: 10px;
|
|
|
+ margin-top: 15px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .form-buttons .submit-btn {
|
|
|
+ flex: 1;
|
|
|
+ margin: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .cancel-btn {
|
|
|
+ flex: 1;
|
|
|
+ padding: 12px;
|
|
|
+ background: #6c757d;
|
|
|
+ color: white;
|
|
|
+ border: none;
|
|
|
+ border-radius: 8px;
|
|
|
+ font-size: 1rem;
|
|
|
+ font-weight: 600;
|
|
|
+ cursor: pointer;
|
|
|
+ transition: all 0.3s ease;
|
|
|
+ }
|
|
|
+
|
|
|
+ .cancel-btn:hover {
|
|
|
+ background: #5a6268;
|
|
|
+ transform: translateY(-1px);
|
|
|
+ }
|
|
|
+
|
|
|
.logout-btn {
|
|
|
width: 100%;
|
|
|
padding: 10px;
|
|
|
@@ -260,6 +324,33 @@
|
|
|
<p><strong>Roles:</strong> <span id="currentRoles"></span></p>
|
|
|
<p><strong>Token Expires:</strong> <span id="tokenExpiration"></span></p>
|
|
|
</div>
|
|
|
+
|
|
|
+ <div class="action-buttons">
|
|
|
+ <button class="action-btn" id="showChangePasswordBtn" onclick="toggleChangePasswordForm()">Change Password</button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="change-password-section" id="changePasswordSection" style="display: none;">
|
|
|
+ <h3>Change Password</h3>
|
|
|
+ <form id="changePasswordForm">
|
|
|
+ <div class="form-group">
|
|
|
+ <label for="currentPassword">Current Password</label>
|
|
|
+ <input type="password" id="currentPassword" name="currentPassword" required>
|
|
|
+ </div>
|
|
|
+ <div class="form-group">
|
|
|
+ <label for="newPassword">New Password</label>
|
|
|
+ <input type="password" id="newPassword" name="newPassword" required>
|
|
|
+ </div>
|
|
|
+ <div class="form-group">
|
|
|
+ <label for="confirmPassword">Confirm New Password</label>
|
|
|
+ <input type="password" id="confirmPassword" name="confirmPassword" required>
|
|
|
+ </div>
|
|
|
+ <div class="form-buttons">
|
|
|
+ <button type="submit" class="submit-btn" id="changePasswordBtn">Change Password</button>
|
|
|
+ </div>
|
|
|
+ <div id="changePasswordMessage" class="message" style="display: none;"></div>
|
|
|
+ </form>
|
|
|
+ </div>
|
|
|
+
|
|
|
<button class="logout-btn" onclick="logout()">Logout</button>
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -314,7 +405,13 @@
|
|
|
button.innerHTML = '<span class="loading"></span>Processing...';
|
|
|
button.disabled = true;
|
|
|
} else {
|
|
|
- button.innerHTML = buttonId.includes('login') ? 'Sign In' : 'Create Account';
|
|
|
+ if (buttonId.includes('login')) {
|
|
|
+ button.innerHTML = 'Sign In';
|
|
|
+ } else if (buttonId.includes('register')) {
|
|
|
+ button.innerHTML = 'Create Account';
|
|
|
+ } else if (buttonId.includes('changePassword')) {
|
|
|
+ button.innerHTML = 'Change Password';
|
|
|
+ }
|
|
|
button.disabled = false;
|
|
|
}
|
|
|
}
|
|
|
@@ -397,10 +494,65 @@
|
|
|
}
|
|
|
});
|
|
|
|
|
|
- function showUserSection() {
|
|
|
- document.getElementById('authSection').style.display = 'none';
|
|
|
- document.getElementById('userSection').classList.add('active');
|
|
|
+ document.getElementById('changePasswordForm').addEventListener('submit', async function(e) {
|
|
|
+ e.preventDefault();
|
|
|
+
|
|
|
+ const currentPassword = document.getElementById('currentPassword').value;
|
|
|
+ const newPassword = document.getElementById('newPassword').value;
|
|
|
+ const confirmPassword = document.getElementById('confirmPassword').value;
|
|
|
+
|
|
|
+ // Validate password confirmation
|
|
|
+ if (newPassword !== confirmPassword) {
|
|
|
+ showMessage('changePasswordMessage', 'New passwords do not match.', 'error');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Validate password length
|
|
|
+ if (newPassword.length < 6) {
|
|
|
+ showMessage('changePasswordMessage', 'New password must be at least 6 characters long.', 'error');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ setButtonLoading('changePasswordBtn', true);
|
|
|
+ clearPasswordChangeMessages();
|
|
|
+
|
|
|
+ try {
|
|
|
+ const response = await fetch(`${API_BASE_URL}/users/change-password`, {
|
|
|
+ method: 'POST',
|
|
|
+ headers: {
|
|
|
+ 'Content-Type': 'application/json',
|
|
|
+ 'Authorization': `Bearer ${localStorage.getItem('authToken')}`
|
|
|
+ },
|
|
|
+ body: JSON.stringify({ currentPassword, newPassword })
|
|
|
+ });
|
|
|
+
|
|
|
+ if (response.ok) {
|
|
|
+ const data = await response.json();
|
|
|
+
|
|
|
+ showMessage('changePasswordMessage', 'Password changed successfully! Please log in with your new password.', 'success');
|
|
|
+
|
|
|
+ // Clear the form and force logout after a brief delay
|
|
|
+ document.getElementById('changePasswordForm').reset();
|
|
|
+ logout();
|
|
|
+ } else {
|
|
|
+ const errorText = await response.text();
|
|
|
+ showMessage('changePasswordMessage', errorText || 'Failed to change password. Please try again.', 'error');
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('Change password error:', error);
|
|
|
+ showMessage('changePasswordMessage', 'Network error. Please check if the auth service is running.', 'error');
|
|
|
+ } finally {
|
|
|
+ setButtonLoading('changePasswordBtn', false);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ function clearPasswordChangeMessages() {
|
|
|
+ const messageElement = document.getElementById('changePasswordMessage');
|
|
|
+ messageElement.style.display = 'none';
|
|
|
+ messageElement.textContent = '';
|
|
|
+ }
|
|
|
|
|
|
+ function updateUserDisplay() {
|
|
|
document.getElementById('currentUsername').textContent = currentUser.username;
|
|
|
document.getElementById('currentUserId').textContent = maskUserId(currentUser.id);
|
|
|
document.getElementById('currentRoles').textContent = currentUser.roles.join(', ');
|
|
|
@@ -409,6 +561,12 @@
|
|
|
document.getElementById('tokenExpiration').textContent = expirationDate.toLocaleString();
|
|
|
}
|
|
|
|
|
|
+ function showUserSection() {
|
|
|
+ document.getElementById('authSection').style.display = 'none';
|
|
|
+ document.getElementById('userSection').classList.add('active');
|
|
|
+ updateUserDisplay();
|
|
|
+ }
|
|
|
+
|
|
|
function maskUserId(id) {
|
|
|
const parts = id.split("-");
|
|
|
return parts[0] + "-****-" + parts[4];
|
|
|
@@ -424,10 +582,51 @@
|
|
|
|
|
|
document.getElementById('loginForm').reset();
|
|
|
document.getElementById('registerForm').reset();
|
|
|
+
|
|
|
+ // Reset password change form and hide it
|
|
|
+ hideChangePasswordForm();
|
|
|
+
|
|
|
clearMessages();
|
|
|
|
|
|
switchTab('login');
|
|
|
}
|
|
|
+
|
|
|
+ function toggleChangePasswordForm() {
|
|
|
+ const formSection = document.getElementById('changePasswordSection');
|
|
|
+ const isVisible = formSection.style.display === 'block';
|
|
|
+
|
|
|
+ if (isVisible) {
|
|
|
+ hideChangePasswordForm();
|
|
|
+ } else {
|
|
|
+ showChangePasswordForm();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ function showChangePasswordForm() {
|
|
|
+ const formSection = document.getElementById('changePasswordSection');
|
|
|
+ const actionBtn = document.getElementById('showChangePasswordBtn');
|
|
|
+
|
|
|
+ formSection.style.display = 'block';
|
|
|
+ actionBtn.textContent = 'Hide Change Password';
|
|
|
+
|
|
|
+ // Clear any previous messages
|
|
|
+ clearPasswordChangeMessages();
|
|
|
+
|
|
|
+ // Focus on first input
|
|
|
+ document.getElementById('currentPassword').focus();
|
|
|
+ }
|
|
|
+
|
|
|
+ function hideChangePasswordForm() {
|
|
|
+ const formSection = document.getElementById('changePasswordSection');
|
|
|
+ const actionBtn = document.getElementById('showChangePasswordBtn');
|
|
|
+
|
|
|
+ formSection.style.display = 'none';
|
|
|
+ actionBtn.textContent = 'Change Password';
|
|
|
+
|
|
|
+ // Clear form and messages
|
|
|
+ document.getElementById('changePasswordForm').reset();
|
|
|
+ clearPasswordChangeMessages();
|
|
|
+ }
|
|
|
</script>
|
|
|
</body>
|
|
|
</html>
|