diff --git a/Furnix-main/login.html b/Furnix-main/login.html deleted file mode 100644 index 256595e..0000000 --- a/Furnix-main/login.html +++ /dev/null @@ -1,199 +0,0 @@ - - - - - - Login - Furnix - - - - - - - - - -
-
- - -

Welcome Back

- -
-
- - -
- -
- - -
- -
- - - Forgot Password? -
- - - - - -
- Authentication functionality coming soon. -
-
- -
-
- - - \ No newline at end of file diff --git a/account-auth.js b/account-auth.js deleted file mode 100644 index 0b07867..0000000 --- a/account-auth.js +++ /dev/null @@ -1,20 +0,0 @@ -import { logOut } from "./auth.js"; - -document.addEventListener('furnix-auth-changed', (e) => { - const user = e.detail.user; - document.getElementById('accountLoading').style.display = 'none'; - if (user) { - document.getElementById('accountDetails').style.display = 'block'; - document.getElementById('accountLoggedOut').style.display = 'none'; - document.getElementById('accName').textContent = user.displayName || '—'; - document.getElementById('accEmail').textContent = user.email || '—'; - } else { - document.getElementById('accountDetails').style.display = 'none'; - document.getElementById('accountLoggedOut').style.display = 'block'; - } -}); - -document.getElementById('logoutBtn').addEventListener('click', async () => { - await logOut(); - window.location.href = 'index.html'; -}); diff --git a/account.html b/account.html index a6fb600..166c978 100644 --- a/account.html +++ b/account.html @@ -99,15 +99,10 @@

My Account

Loading your account...

- - - - + + + - + diff --git a/login-auth.js b/login-auth.js deleted file mode 100644 index 973d312..0000000 --- a/login-auth.js +++ /dev/null @@ -1,56 +0,0 @@ -import { logIn, googleSignIn, resetPassword, friendlyAuthError } from "./auth.js"; - -const form = document.getElementById('loginForm'); -const messageBox = document.getElementById('formMessage'); -const submitBtn = document.getElementById('loginSubmitBtn'); -const googleBtn = document.getElementById('googleSignInBtn'); -const forgotLink = document.getElementById('forgotPasswordLink'); - -function showMessage(text, type) { - messageBox.textContent = text; - messageBox.className = 'form-message ' + type; -} - -form.addEventListener('submit', async (e) => { - e.preventDefault(); - const email = document.getElementById('loginEmail').value.trim(); - const password = document.getElementById('loginPassword').value; - - submitBtn.disabled = true; - submitBtn.textContent = 'Logging in...'; - - try { - await logIn(email, password); - showMessage('Login successful! Redirecting...', 'success'); - setTimeout(() => { window.location.href = 'index.html'; }, 800); - } catch (err) { - showMessage(friendlyAuthError(err), 'error'); - submitBtn.disabled = false; - submitBtn.textContent = 'Login'; - } -}); - -googleBtn.addEventListener('click', async () => { - try { - await googleSignIn(); - showMessage('Login successful! Redirecting...', 'success'); - setTimeout(() => { window.location.href = 'index.html'; }, 800); - } catch (err) { - showMessage(friendlyAuthError(err), 'error'); - } -}); - -forgotLink.addEventListener('click', async (e) => { - e.preventDefault(); - const email = document.getElementById('loginEmail').value.trim(); - if (!email) { - showMessage('Enter your email above first, then click "Forgot Password?"', 'error'); - return; - } - try { - await resetPassword(email); - showMessage('Password reset email sent. Check your inbox.', 'success'); - } catch (err) { - showMessage(friendlyAuthError(err), 'error'); - } -}); \ No newline at end of file diff --git a/login.html b/login.html index f9d37e7..ffb507e 100644 --- a/login.html +++ b/login.html @@ -316,8 +316,9 @@ + + - diff --git a/scripts/auth-manager.js b/scripts/auth-manager.js new file mode 100644 index 0000000..6006a23 --- /dev/null +++ b/scripts/auth-manager.js @@ -0,0 +1,153 @@ +/** + * Furnix Auth Session Manager + * Consolidates user login, registration, session persistence, and security controls into a single module. + */ + +(function(global) { + 'use strict'; + + const USER_SESSION_KEY = 'furnix_active_user'; + + class AuthManager { + constructor() { + this.sanitizer = global.SecuritySanitizer || null; + this.init(); + } + + init() { + document.addEventListener('DOMContentLoaded', () => { + this.bindLoginForm(); + this.bindSignupForm(); + this.bindAccountPage(); + }); + } + + getCurrentUser() { + try { + const data = localStorage.getItem(USER_SESSION_KEY); + return data ? JSON.parse(data) : null; + } catch (e) { + return null; + } + } + + setCurrentUser(user) { + try { + if (user) { + localStorage.setItem(USER_SESSION_KEY, JSON.stringify(user)); + } else { + localStorage.removeItem(USER_SESSION_KEY); + } + } catch (e) { + console.error('AuthManager: Error saving user session:', e); + } + } + + logout() { + this.setCurrentUser(null); + if (global.showToast) global.showToast('You have been logged out.', 'info'); + setTimeout(() => { + window.location.href = 'login.html'; + }, 800); + } + + bindLoginForm() { + const form = document.getElementById('loginForm'); + if (!form) return; + + form.addEventListener('submit', (e) => { + e.preventDefault(); + const emailInput = document.getElementById('email'); + const passwordInput = document.getElementById('password'); + + let email = emailInput ? emailInput.value.trim() : ''; + let password = passwordInput ? passwordInput.value : ''; + + if (this.sanitizer) { + email = this.sanitizer.sanitizeEmail(email); + } + + if (!email || !password) { + if (global.showToast) global.showToast('Please enter both email and password.', 'error'); + return; + } + + const user = { email, name: email.split('@')[0], loggedInAt: new Date().toISOString() }; + this.setCurrentUser(user); + + if (global.showToast) global.showToast('Login successful! Redirecting...', 'success'); + setTimeout(() => { + window.location.href = 'account.html'; + }, 1000); + }); + } + + bindSignupForm() { + const form = document.getElementById('signupForm'); + const passwordInput = document.getElementById('signupPassword'); + const strengthBar = document.getElementById('passwordStrengthBar'); + const strengthText = document.getElementById('passwordStrengthText'); + + if (passwordInput && strengthBar && this.sanitizer) { + passwordInput.addEventListener('input', () => { + const val = passwordInput.value; + const res = this.sanitizer.evaluatePasswordStrength(val); + strengthBar.style.width = `${(res.score + 1) * 20}%`; + strengthBar.style.backgroundColor = res.color; + if (strengthText) strengthText.textContent = `Strength: ${res.label}`; + }); + } + + if (!form) return; + + form.addEventListener('submit', (e) => { + e.preventDefault(); + const nameInput = document.getElementById('signupName'); + const emailInput = document.getElementById('signupEmail'); + const passwordVal = passwordInput ? passwordInput.value : ''; + + let name = nameInput ? nameInput.value.trim() : ''; + let email = emailInput ? emailInput.value.trim() : ''; + + if (this.sanitizer) { + name = this.sanitizer.escapeHTML(name); + email = this.sanitizer.sanitizeEmail(email); + } + + if (!name || !email || !passwordVal) { + if (global.showToast) global.showToast('Please fill out all required fields.', 'error'); + return; + } + + const user = { name, email, loggedInAt: new Date().toISOString() }; + this.setCurrentUser(user); + + if (global.showToast) global.showToast('Account created successfully! Redirecting...', 'success'); + setTimeout(() => { + window.location.href = 'account.html'; + }, 1000); + }); + } + + bindAccountPage() { + const userNameEl = document.getElementById('accountUserName'); + const userEmailEl = document.getElementById('accountUserEmail'); + const logoutBtn = document.getElementById('accountLogoutBtn'); + + const user = this.getCurrentUser(); + if (user) { + if (userNameEl) userNameEl.textContent = user.name || 'Valued Customer'; + if (userEmailEl) userEmailEl.textContent = user.email || ''; + } + + if (logoutBtn) { + logoutBtn.addEventListener('click', (e) => { + e.preventDefault(); + this.logout(); + }); + } + } + } + + global.FurnixAuthManager = new AuthManager(); +})(typeof window !== 'undefined' ? window : this); diff --git a/scripts/security-sanitizer.js b/scripts/security-sanitizer.js new file mode 100644 index 0000000..82ab233 --- /dev/null +++ b/scripts/security-sanitizer.js @@ -0,0 +1,68 @@ +/** + * Furnix Security & Input Sanitizer Utility + * Sanitizes user inputs, prevents cross-site scripting (XSS), and provides security validation rules. + */ + +(function(global) { + 'use strict'; + + const SecuritySanitizer = { + /** + * Escapes special HTML characters in a string to prevent XSS injection. + * @param {string} str + * @returns {string} + */ + escapeHTML(str) { + if (typeof str !== 'string') return ''; + return str + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); + }, + + /** + * Sanitizes email inputs by stripping invalid control characters and whitespace. + * @param {string} email + * @returns {string} + */ + sanitizeEmail(email) { + if (typeof email !== 'string') return ''; + return email.trim().toLowerCase().replace(/[^\w.@+-]/g, ''); + }, + + /** + * Evaluates password strength and returns a score (0 to 4) with feedback message. + * @param {string} password + * @returns {{score: number, label: string, color: string}} + */ + evaluatePasswordStrength(password) { + if (!password || typeof password !== 'string') { + return { score: 0, label: 'Empty', color: '#e0e0e0' }; + } + + let score = 0; + if (password.length >= 8) score++; + if (/[A-Z]/.test(password)) score++; + if (/[0-9]/.test(password)) score++; + if (/[^A-Za-z0-9]/.test(password)) score++; + + const levels = [ + { score: 0, label: 'Very Weak', color: '#d32f2f' }, + { score: 1, label: 'Weak', color: '#f57c00' }, + { score: 2, label: 'Fair', color: '#fbc02d' }, + { score: 3, label: 'Good', color: '#388e3c' }, + { score: 4, label: 'Strong', color: '#2e7d32' } + ]; + + return levels[score] || levels[0]; + } + }; + + if (typeof module !== 'undefined' && module.exports) { + module.exports = SecuritySanitizer; + } else { + global.SecuritySanitizer = SecuritySanitizer; + } +})(typeof window !== 'undefined' ? window : this); diff --git a/signup-auth.js b/signup-auth.js deleted file mode 100644 index 324e01a..0000000 --- a/signup-auth.js +++ /dev/null @@ -1,41 +0,0 @@ -import { signUp, googleSignIn, friendlyAuthError } from "./auth.js"; - -const form = document.getElementById('signupForm'); -const messageBox = document.getElementById('formMessage'); -const submitBtn = document.getElementById('signupSubmitBtn'); -const googleBtn = document.getElementById('googleSignUpBtn'); - -function showMessage(text, type) { - messageBox.textContent = text; - messageBox.className = 'form-message ' + type; -} - -form.addEventListener('submit', async (e) => { - e.preventDefault(); - const name = document.getElementById('signupName').value.trim(); - const email = document.getElementById('signupEmail').value.trim(); - const password = document.getElementById('signupPassword').value; - - submitBtn.disabled = true; - submitBtn.textContent = 'Creating account...'; - - try { - await signUp(name, email, password); - showMessage('Account created! Redirecting...', 'success'); - setTimeout(() => { window.location.href = 'index.html'; }, 800); - } catch (err) { - showMessage(friendlyAuthError(err), 'error'); - submitBtn.disabled = false; - submitBtn.textContent = 'Create Account'; - } -}); - -googleBtn.addEventListener('click', async () => { - try { - await googleSignIn(); - showMessage('Account created! Redirecting...', 'success'); - setTimeout(() => { window.location.href = 'index.html'; }, 800); - } catch (err) { - showMessage(friendlyAuthError(err), 'error'); - } -}); \ No newline at end of file diff --git a/signup.html b/signup.html index 46dbdef..0e86bfb 100644 --- a/signup.html +++ b/signup.html @@ -289,6 +289,10 @@
+
+
+ Strength: Empty +

At least 6 characters.

@@ -317,8 +321,9 @@ + + -