| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616 |
- const API_BASE_URL = '/api';
- let currentUser = null;
- let resetToken = null;
- // Theme management
- function initializeTheme() {
- const savedTheme = localStorage.getItem('theme') || 'light';
- document.documentElement.setAttribute('data-theme', savedTheme);
- }
- function toggleTheme() {
- const currentTheme = document.documentElement.getAttribute('data-theme') || 'light';
- const newTheme = currentTheme === 'light' ? 'dark' : 'light';
- document.documentElement.setAttribute('data-theme', newTheme);
- localStorage.setItem('theme', newTheme);
- }
- function parseURLParams() {
- const urlParams = new URLSearchParams(window.location.search);
- const hasResetFlag = urlParams.has('reset-password');
- const token = urlParams.get('token');
- return {
- isResetMode: hasResetFlag && token,
- resetToken: token
- };
- }
- document.addEventListener('DOMContentLoaded', function() {
- // Initialize theme before anything else
- initializeTheme();
- // Ensure user section is hidden by default
- const userSection = document.getElementById('userSection');
- if (userSection) {
- userSection.classList.remove('active');
- userSection.style.display = 'none';
- }
- const urlInfo = parseURLParams();
- if (urlInfo.isResetMode) {
- resetToken = urlInfo.resetToken;
- showResetPasswordSection();
- return;
- }
- const token = localStorage.getItem('authToken');
- const userData = localStorage.getItem('userData');
- if (token && userData) {
- try {
- currentUser = JSON.parse(userData);
- // Only show user section if we have valid user data
- if (currentUser && currentUser.username) {
- showUserSection();
- } else {
- throw new Error('Invalid user data structure');
- }
- } catch (e) {
- console.error('Invalid user data in localStorage', e);
- localStorage.removeItem('authToken');
- localStorage.removeItem('userData');
- currentUser = null;
- // Make sure user section stays hidden
- if (userSection) {
- userSection.classList.remove('active');
- userSection.style.display = 'none';
- }
- }
- } else {
- // No auth data, make sure user section is hidden
- currentUser = null;
- if (userSection) {
- userSection.classList.remove('active');
- userSection.style.display = 'none';
- }
- }
- const forgotPasswordLink = document.getElementById('forgotPasswordLink');
- if (forgotPasswordLink) {
- forgotPasswordLink.addEventListener('click', handleForgotPassword);
- }
- });
- function switchTab(tab) {
- document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
- document.querySelector(`.tab:nth-child(${tab === 'login' ? '1' : '2'})`).classList.add('active');
- document.querySelectorAll('.form').forEach(f => f.classList.remove('active'));
- document.getElementById(tab + 'Form').classList.add('active');
- clearMessages();
- }
- function clearMessages() {
- document.querySelectorAll('.message').forEach(msg => {
- msg.style.display = 'none';
- msg.textContent = '';
- });
- }
- function showMessage(elementId, message, type) {
- const element = document.getElementById(elementId);
- element.textContent = message;
- element.className = `message ${type}`;
- element.style.display = 'block';
- }
- function setButtonLoading(buttonId, loading) {
- const button = document.getElementById(buttonId);
- if (loading) {
- button.innerHTML = '<span class="loading"></span>Processing...';
- button.disabled = true;
- } else {
- if (buttonId.includes('login')) {
- button.innerHTML = 'Sign In';
- } else if (buttonId.includes('register')) {
- button.innerHTML = 'Create Account';
- } else if (buttonId.includes('editProfile')) {
- button.innerHTML = 'Update Profile';
- } else if (buttonId.includes('resetPassword')) {
- button.innerHTML = 'Reset Password';
- }
- button.disabled = false;
- }
- }
- // Only add event listeners if elements exist (for index.html)
- const loginForm = document.getElementById('loginForm');
- if (loginForm) {
- loginForm.addEventListener('submit', async function(e) {
- e.preventDefault();
- const username = document.getElementById('loginUsername').value;
- const password = document.getElementById('loginPassword').value;
- setButtonLoading('loginBtn', true);
- clearMessages();
- try {
- const response = await fetch(`${API_BASE_URL}/authenticate`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify({ username, password })
- });
- if (response.ok) {
- const data = await response.json();
- localStorage.setItem('authToken', data.token);
- localStorage.setItem('userData', JSON.stringify(data));
- currentUser = data;
- setButtonLoading('loginBtn', false);
- showUserSection();
- } else {
- try {
- const errorData = await response.json();
- const errorMessage = errorData.message || 'Login failed. Please check your credentials.';
- showMessage('loginMessage', errorMessage, 'error');
- } catch (parseError) {
- // If response is not JSON, fall back to text
- const errorText = await response.text();
- showMessage('loginMessage', errorText || 'Login failed. Please check your credentials.', 'error');
- }
- }
- } catch (error) {
- console.error('Login error:', error);
- showMessage('loginMessage', 'Network error. Please check if the auth service is running.', 'error');
- } finally {
- setButtonLoading('loginBtn', false);
- }
- });
- }
- const registerForm = document.getElementById('registerForm');
- if (registerForm) {
- registerForm.addEventListener('submit', async function(e) {
- e.preventDefault();
- const username = document.getElementById('registerUsername').value;
- const password = document.getElementById('registerPassword').value;
- const email = document.getElementById('registerEmail').value;
- if (username.length < 4) {
- showMessage('registerMessage', "Username must be at least 4 characters long.", 'error');
- return;
- }
- if (password.length < 4) {
- showMessage('registerMessage', "Password must be at least 4 characters long.", 'error');
- return;
- }
- setButtonLoading('registerBtn', true);
- clearMessages();
- try {
- const response = await fetch(`${API_BASE_URL}/register`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify({ username, email, password })
- });
- if (response.ok) {
- const data = await response.json();
- localStorage.setItem('authToken', data.token);
- localStorage.setItem('userData', JSON.stringify(data));
- currentUser = data;
- setButtonLoading('registerBtn', false);
- showUserSection();
- } else {
- try {
- const errorData = await response.json();
- const errorMessage = errorData.message || 'Registration failed. Please try again.';
- showMessage('registerMessage', errorMessage, 'error');
- } catch (parseError) {
- const errorText = await response.text();
- showMessage('registerMessage', errorText || 'Registration failed. Please try again.', 'error');
- }
- }
- } catch (error) {
- console.error('Registration error:', error);
- showMessage('registerMessage', 'Network error. Please check if the auth service is running.', 'error');
- } finally {
- setButtonLoading('registerBtn', false);
- }
- });
- }
- const resetPasswordForm = document.getElementById('resetPasswordForm');
- if (resetPasswordForm) {
- resetPasswordForm.addEventListener('submit', async function(e) {
- e.preventDefault();
- const newPassword = document.getElementById('resetNewPassword').value;
- const confirmPassword = document.getElementById('resetConfirmPassword').value;
- if (newPassword !== confirmPassword) {
- showMessage('resetPasswordMessage', 'New passwords do not match.', 'error');
- return;
- }
- if (newPassword.length < 4) {
- showMessage('resetPasswordMessage', 'New password must be at least 4 characters long.', 'error');
- return;
- }
- setButtonLoading('resetPasswordBtn', true);
- clearResetPasswordMessages();
- try {
- const response = await fetch(`${API_BASE_URL}/users/reset-password`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- 'Authorization': 'Bearer ' + resetToken
- },
- body: JSON.stringify({
- newPassword: newPassword
- })
- });
- if (response.ok) {
- showMessage('resetPasswordMessage', 'Password reset successfully!', 'success');
- document.getElementById('resetPasswordForm').reset();
- setTimeout(() => {
- window.location.href = window.location.pathname;
- }, 1000);
- } else {
- try {
- const errorData = await response.json();
- const errorMessage = errorData.message || 'Failed to reset password. Please try again.';
- showMessage('resetPasswordMessage', errorMessage, 'error');
- } catch (parseError) {
- // If response is not JSON, fall back to text
- const errorText = await response.text();
- showMessage('resetPasswordMessage', errorText || 'Failed to reset password. Please try again.', 'error');
- }
- }
- } catch (error) {
- console.error('Reset password error:', error);
- showMessage('resetPasswordMessage', 'Network error. Please check if the auth service is running.', 'error');
- } finally {
- setButtonLoading('resetPasswordBtn', false);
- }
- });
- }
- const editProfileForm = document.getElementById('editProfileForm');
- if (editProfileForm) {
- editProfileForm.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;
- const email = document.getElementById('editEmail').value;
- // Validate that at least one field is being updated
- const isPasswordChange = newPassword.trim() !== '';
- const currentEmail = currentUser.email || '';
- const newEmail = email.trim();
- const isEmailChange = newEmail !== currentEmail;
- if (!isPasswordChange && !isEmailChange) {
- showMessage('editProfileMessage', 'Please make at least one change: update your email address or change your password.', 'error');
- return;
- }
- if (isPasswordChange && newPassword !== confirmPassword) {
- showMessage('editProfileMessage', 'New passwords do not match.', 'error');
- return;
- }
- if (isPasswordChange && newPassword.length < 4) {
- showMessage('editProfileMessage', 'New password must be at least 4 characters long.', 'error');
- return;
- }
- setButtonLoading('editProfileBtn', true);
- clearEditProfileMessages();
- try {
- const requestBody = { currentPassword };
- if (isPasswordChange) {
- requestBody.newPassword = newPassword;
- }
- if (isEmailChange) {
- requestBody.email = newEmail;
- }
- const response = await fetch(`${API_BASE_URL}/users/update-profile`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- 'Authorization': `Bearer ${localStorage.getItem('authToken')}`
- },
- body: JSON.stringify(requestBody)
- });
- if (response.ok) {
- const data = await response.json();
- let message = '';
- if (isPasswordChange && isEmailChange) {
- message = 'Email and password updated successfully! Please log in with your new password.';
- document.getElementById('editProfileForm').reset();
- setTimeout(() => logout(), 1500);
- } else if (isPasswordChange) {
- message = 'Password updated successfully! Please log in with your new password.';
- document.getElementById('editProfileForm').reset();
- setTimeout(() => logout(), 1500);
- } else if (isEmailChange) {
- message = 'Email updated successfully!';
- // Update the stored user data with new email
- currentUser.email = newEmail;
- localStorage.setItem('userData', JSON.stringify(currentUser));
- updateUserDisplay(); // Refresh the displayed email
- document.getElementById('editProfileForm').reset();
- setTimeout(() => hideEditProfileForm(), 1000);
- }
- showMessage('editProfileMessage', message, 'success');
- } else {
- try {
- const errorData = await response.json();
- const errorMessage = errorData.message || 'Failed to update profile. Please try again.';
- showMessage('editProfileMessage', errorMessage, 'error');
- } catch (parseError) {
- // If response is not JSON, fall back to text
- const errorText = await response.text();
- showMessage('editProfileMessage', errorText || 'Failed to update profile. Please try again.', 'error');
- }
- }
- } catch (error) {
- console.error('Update profile error:', error);
- showMessage('editProfileMessage', 'Network error. Please check if the auth service is running.', 'error');
- } finally {
- setButtonLoading('editProfileBtn', false);
- }
- });
- }
- function clearEditProfileMessages() {
- const messageElement = document.getElementById('editProfileMessage');
- messageElement.style.display = 'none';
- messageElement.textContent = '';
- }
- function clearResetPasswordMessages() {
- const messageElement = document.getElementById('resetPasswordMessage');
- messageElement.style.display = 'none';
- messageElement.textContent = '';
- }
- function updateUserDisplay() {
- if (!currentUser) {
- console.log('updateUserDisplay called but no currentUser');
- return;
- }
- const usernameEl = document.getElementById('currentUsername');
- const emailEl = document.getElementById('currentEmail');
- const userIdEl = document.getElementById('currentUserId');
- const rolesEl = document.getElementById('currentRoles');
- if (usernameEl) usernameEl.textContent = currentUser.username || '';
- if (emailEl) emailEl.textContent = maskUserEmail(currentUser.email) || '-';
- if (userIdEl) userIdEl.textContent = maskUserId(currentUser.id) || '';
- if (rolesEl) rolesEl.textContent = (currentUser.roles || []).join(', ');
- // Show/hide admin panel button based on user role
- updateAdminPanelVisibility();
- }
- function showUserSection() {
- const authSection = document.getElementById('authSection');
- const userSection = document.getElementById('userSection');
- const header = document.querySelector('.header');
- if (authSection) authSection.style.display = 'none';
- if (userSection) {
- userSection.classList.add('active');
- userSection.style.display = 'block';
- }
- if (header) header.style.display = 'block';
- updateUserDisplay();
- }
- function showResetPasswordSection() {
- document.getElementById('authSection').style.display = 'none';
- document.getElementById('userSection').classList.remove('active');
- document.getElementById('resetPasswordSection').style.display = 'block';
- document.querySelector('.header').style.display = 'none';
- document.getElementById('resetNewPassword').focus();
- }
- function maskUserId(id) {
- const parts = id.split("-");
- return parts[0] + "-****-" + parts[4];
- }
- function maskUserEmail(email) {
- if (!email.includes("@")) {
- return email;
- }
- const [user, domain] = email.split("@");
- if (user.length <= 2) {
- return user[0] + "*@" + domain;
- }
- const first = user[0];
- const last = user[user.length - 1];
- const maskedPart = "*".repeat(user.length - 2);
- return `${first}${maskedPart}${last}@${domain}`;
- }
- function logout() {
- localStorage.removeItem('authToken');
- localStorage.removeItem('userData');
- currentUser = null;
- const userSection = document.getElementById('userSection');
- const authSection = document.getElementById('authSection');
- const header = document.querySelector('.header');
- const loginForm = document.getElementById('loginForm');
- const registerForm = document.getElementById('registerForm');
- if (userSection) {
- userSection.classList.remove('active');
- userSection.style.display = 'none';
- }
- if (authSection) authSection.style.display = 'block';
- if (header) header.style.display = 'block';
- if (loginForm) loginForm.reset();
- if (registerForm) registerForm.reset();
- hideEditProfileForm();
- clearMessages();
- switchTab('login');
- }
- function toggleEditProfileForm() {
- const formSection = document.getElementById('editProfileSection');
- const isVisible = formSection.style.display === 'block';
- if (isVisible) {
- hideEditProfileForm();
- } else {
- showEditProfileForm();
- }
- }
- function showEditProfileForm() {
- const formSection = document.getElementById('editProfileSection');
- const actionBtn = document.getElementById('showEditProfileBtn');
- if (formSection) formSection.style.display = 'block';
- // Add active styling to button
- if (actionBtn) actionBtn.classList.add('active');
- // Clear any previous messages
- clearEditProfileMessages();
- // Pre-populate email field with current user's email
- if (currentUser) {
- const editEmail = document.getElementById('editEmail');
- if (editEmail) editEmail.value = currentUser.email || '';
- }
- // Focus on email input first since that's the most common change
- setTimeout(() => {
- const editEmail = document.getElementById('editEmail');
- if (editEmail) editEmail.focus();
- }, 100);
- }
- function hideEditProfileForm() {
- const formSection = document.getElementById('editProfileSection');
- const actionBtn = document.getElementById('showEditProfileBtn');
- if (formSection) formSection.style.display = 'none';
- // Remove active styling from button
- if (actionBtn) actionBtn.classList.remove('active');
- // Clear form and messages
- const editForm = document.getElementById('editProfileForm');
- if (editForm) editForm.reset();
- clearEditProfileMessages();
- }
- // Admin panel functions
- function hasAdminRole() {
- return currentUser && Array.isArray(currentUser.roles) && currentUser.roles.includes('ADMIN');
- }
- function updateAdminPanelVisibility() {
- const adminBtn = document.getElementById('adminPanelBtn');
- if (adminBtn) {
- adminBtn.style.display = hasAdminRole() ? 'block' : 'none';
- }
- }
- function openAdminPanel() {
- if (!hasAdminRole()) {
- alert('Access denied. Admin privileges required.');
- return;
- }
- window.location.href = 'admin.html';
- }
- async function handleForgotPassword(e) {
- e.preventDefault();
- const username = document.getElementById('loginUsername').value.trim();
- if (!username) {
- showMessage('loginMessage', 'Please enter your username above and then click "Forgot password" again.', 'error');
- document.getElementById('loginUsername').focus();
- return;
- }
- clearMessages();
- const link = document.getElementById('forgotPasswordLink');
- const originalText = link.textContent;
- link.textContent = 'Sending email...';
- link.style.pointerEvents = 'none';
- try {
- const response = await fetch(`${API_BASE_URL}/forgot-password?username=${encodeURIComponent(username)}`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json'
- }
- });
- if (response.ok) {
- showMessage('loginMessage', 'Password reset email sent! Please check your inbox.', 'success');
- document.getElementById('loginUsername').value = '';
- } else {
- try {
- const errorData = await response.json();
- const errorMessage = errorData.message || 'Failed to send reset email. Please try again.';
- showMessage('loginMessage', errorMessage, 'error');
- } catch (parseError) {
- const errorText = await response.text();
- showMessage('loginMessage', errorText || 'Failed to send reset email. Please try again.', 'error');
- }
- }
- } catch (error) {
- console.error('Forgot password error:', error);
- showMessage('loginMessage', 'Network error. Please check if the auth service is running.', 'error');
- } finally {
- link.textContent = originalText;
- link.style.pointerEvents = 'auto';
- }
- }
|