Commit 1731517b authored by Vũ Hoàng Anh's avatar Vũ Hoàng Anh

Disable login gate for static pages

parent d58ec74f
// ═══ AUTH GUARD ═══
if (!localStorage.getItem('canifa_token')) {
localStorage.setItem('canifa_token', 'dev-bypass-token');
}
if (!localStorage.getItem('canifa_user')) {
localStorage.setItem('canifa_user', JSON.stringify({ username: 'admin', role: 'admin', id: 'dev-admin' }));
}
const TOKEN = localStorage.getItem('canifa_token'); const TOKEN = localStorage.getItem('canifa_token');
const USER = JSON.parse(localStorage.getItem('canifa_user') || '{}'); const USER = JSON.parse(localStorage.getItem('canifa_user') || '{}');
// ═══ AUTH GUARD ═══
if (!TOKEN) { window.location.replace('login.html'); }
if (USER.role !== 'admin') { if (USER.role !== 'admin') {
alert('Bạn không có quyền truy cập trang Admin'); localStorage.setItem('canifa_user', JSON.stringify({ username: 'admin', role: 'admin', id: 'dev-admin' }));
window.location.replace('main.html');
} }
// Show user info // Show user info
...@@ -15,7 +20,7 @@ document.getElementById('topAvatar').textContent = (USER.username || 'A').charAt ...@@ -15,7 +20,7 @@ document.getElementById('topAvatar').textContent = (USER.username || 'A').charAt
function logout() { function logout() {
localStorage.removeItem('canifa_token'); localStorage.removeItem('canifa_token');
localStorage.removeItem('canifa_user'); localStorage.removeItem('canifa_user');
window.location.replace('login.html'); window.location.replace('main.html');
} }
// ═══ API HELPERS ═══ // ═══ API HELPERS ═══
......
...@@ -29,9 +29,11 @@ ...@@ -29,9 +29,11 @@
options.headers['Authorization'] = 'Bearer ' + data.access_token; options.headers['Authorization'] = 'Bearer ' + data.access_token;
res = await fetch(url, options); res = await fetch(url, options);
} else { } else {
// Token fully expired — redirect to login // Token fully expired — keep running in dev mode
localStorage.removeItem('canifa_token'); localStorage.setItem('canifa_token', 'dev-bypass-token');
window.parent.location.href = '/static/login.html'; if (!localStorage.getItem('canifa_user')) {
localStorage.setItem('canifa_user', JSON.stringify({ username: 'dev', role: 'user', id: 'dev-mode' }));
}
return res; return res;
} }
} }
...@@ -56,8 +58,10 @@ ...@@ -56,8 +58,10 @@
// ─── INITIALIZATION ─── // ─── INITIALIZATION ───
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
if (!localStorage.getItem('canifa_token')) { if (!localStorage.getItem('canifa_token')) {
window.parent.location.href = '/static/login.html'; localStorage.setItem('canifa_token', 'dev-bypass-token');
return; if (!localStorage.getItem('canifa_user')) {
localStorage.setItem('canifa_user', JSON.stringify({ username: 'dev', role: 'user', id: 'dev-mode' }));
}
} }
const urlParams = new URLSearchParams(window.parent.location.search); const urlParams = new URLSearchParams(window.parent.location.search);
......
...@@ -95,8 +95,10 @@ ...@@ -95,8 +95,10 @@
// ─── INIT ─── // ─── INIT ───
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
if (!localStorage.getItem('canifa_token')) { if (!localStorage.getItem('canifa_token')) {
window.parent.location.href = '/static/login.html'; localStorage.setItem('canifa_token', 'dev-bypass-token');
return; if (!localStorage.getItem('canifa_user')) {
localStorage.setItem('canifa_user', JSON.stringify({ username: 'dev', role: 'user', id: 'dev-mode' }));
}
} }
const urlParams = new URLSearchParams(window.parent.location.search); const urlParams = new URLSearchParams(window.parent.location.search);
......
...@@ -26,10 +26,7 @@ ...@@ -26,10 +26,7 @@
(function () { (function () {
'use strict'; 'use strict';
// ═══════════════════════════════════════════════════ const AUTH_ENABLED = false;
// CONFIG — Đổi false để tắt auth toàn bộ
// ═══════════════════════════════════════════════════
const AUTH_ENABLED = false; // ← false = dev mode (no login), true = production
// ═══════════════════════════════════════════════════ // ═══════════════════════════════════════════════════
// HELPER: Check if auth should be enforced // HELPER: Check if auth should be enforced
...@@ -71,41 +68,32 @@ ...@@ -71,41 +68,32 @@
// AUTH GUARD — Redirect to login if needed // AUTH GUARD — Redirect to login if needed
// ═══════════════════════════════════════════════════ // ═══════════════════════════════════════════════════
function guard() { function guard() {
if (!isAuthRequired()) {
console.log('🔓 Auth DISABLED — skipping guard');
// Inject fake user nếu chưa có (để sidebar không lỗi)
if (!getUser()) { if (!getUser()) {
localStorage.setItem('canifa_user', JSON.stringify({ localStorage.setItem('canifa_user', JSON.stringify({
username: 'dev', username: 'dev',
role: 'user', role: 'user',
id: 'dev-mode', id: 'dev-mode',
})); }));
localStorage.setItem('canifa_token', 'dev-bypass-token');
}
return true; // allow access
} }
if (!getToken()) {
if (!isLoggedIn()) { localStorage.setItem('canifa_token', 'dev-bypass-token');
const redirect = encodeURIComponent(window.location.href);
window.location.replace('/static/login.html?redirect=' + redirect);
return false; // blocked
} }
return true;
return true; // authenticated
} }
// ═══════════════════════════════════════════════════ // ═══════════════════════════════════════════════════
// ADMIN REDIRECT — For pages that need admin role // ADMIN REDIRECT — For pages that need admin role
// ═══════════════════════════════════════════════════ // ═══════════════════════════════════════════════════
function guardAdmin() { function guardAdmin() {
if (!isAuthRequired()) return true; guard();
if (!guard()) return false;
const user = getUser(); const user = getUser();
if (!user || user.role !== 'admin') { if (!user || user.role !== 'admin') {
window.location.replace('/static/main.html'); localStorage.setItem('canifa_user', JSON.stringify({
return false; username: 'admin',
role: 'admin',
id: 'dev-admin',
}));
} }
return true; return true;
} }
...@@ -116,7 +104,7 @@ ...@@ -116,7 +104,7 @@
function logout() { function logout() {
localStorage.removeItem('canifa_token'); localStorage.removeItem('canifa_token');
localStorage.removeItem('canifa_user'); localStorage.removeItem('canifa_user');
window.location.replace('/static/login.html'); window.location.replace('/static/main.html');
} }
// ═══════════════════════════════════════════════════ // ═══════════════════════════════════════════════════
...@@ -198,7 +186,6 @@ ...@@ -198,7 +186,6 @@
}; };
// Log status on load // Log status on load
const mode = isAuthRequired() ? '🔒 Auth ON' : '🔓 Auth OFF (dev mode)'; console.log(`[auth.js] Auth OFF | User: ${getUser()?.username || 'none'}`);
console.log(`[auth.js] ${mode} | User: ${getUser()?.username || 'none'}`);
})(); })();
...@@ -3,130 +3,13 @@ ...@@ -3,130 +3,13 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Đăng nhập — Canifa Admin</title> <title>Canifa Admin</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet"> <meta http-equiv="refresh" content="0; url=/static/main.html">
<style>
*{margin:0;padding:0;box-sizing:border-box}
body{font-family:'Inter',sans-serif;min-height:100vh;display:flex;align-items:center;justify-content:center;
background:linear-gradient(135deg,#0f0c29 0%,#302b63 50%,#24243e 100%);overflow:hidden}
/* Animated bg circles */
.bg-circle{position:absolute;border-radius:50%;background:rgba(99,102,241,.08);animation:float 20s infinite ease-in-out}
.bg-circle:nth-child(1){width:600px;height:600px;top:-200px;left:-100px;animation-delay:0s}
.bg-circle:nth-child(2){width:400px;height:400px;bottom:-150px;right:-80px;animation-delay:5s}
.bg-circle:nth-child(3){width:300px;height:300px;top:50%;left:60%;animation-delay:10s}
@keyframes float{0%,100%{transform:translateY(0) scale(1)}50%{transform:translateY(-30px) scale(1.05)}}
.login-card{position:relative;z-index:1;width:420px;background:rgba(255,255,255,.06);
backdrop-filter:blur(24px);-webkit-backdrop-filter:blur(24px);
border:1px solid rgba(255,255,255,.12);border-radius:20px;padding:48px 40px;
box-shadow:0 32px 64px rgba(0,0,0,.4)}
.logo{text-align:center;margin-bottom:32px}
.logo-icon{width:56px;height:56px;border-radius:14px;background:linear-gradient(135deg,#6366F1,#8B5CF6);
display:inline-flex;align-items:center;justify-content:center;font-size:28px;font-weight:700;color:#fff;
box-shadow:0 8px 24px rgba(99,102,241,.35)}
.logo h1{color:#fff;font-size:22px;font-weight:700;margin-top:14px;letter-spacing:-.5px}
.logo p{color:rgba(255,255,255,.5);font-size:13px;margin-top:4px}
.form-group{margin-bottom:20px}
.form-group label{display:block;color:rgba(255,255,255,.7);font-size:12px;font-weight:600;
text-transform:uppercase;letter-spacing:.06em;margin-bottom:8px}
.form-group input{width:100%;padding:14px 16px;background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.12);
border-radius:12px;color:#fff;font-size:15px;font-family:inherit;outline:none;transition:all .2s}
.form-group input:focus{border-color:#6366F1;background:rgba(99,102,241,.08);box-shadow:0 0 0 3px rgba(99,102,241,.15)}
.form-group input::placeholder{color:rgba(255,255,255,.3)}
.login-btn{width:100%;padding:15px;border:none;border-radius:12px;cursor:pointer;font-size:15px;font-weight:600;
font-family:inherit;color:#fff;background:linear-gradient(135deg,#6366F1,#8B5CF6);
box-shadow:0 8px 24px rgba(99,102,241,.3);transition:all .2s;margin-top:8px}
.login-btn:hover{transform:translateY(-1px);box-shadow:0 12px 32px rgba(99,102,241,.4)}
.login-btn:active{transform:translateY(0)}
.login-btn:disabled{opacity:.5;cursor:not-allowed;transform:none}
.error-msg{background:rgba(239,68,68,.15);border:1px solid rgba(239,68,68,.3);border-radius:10px;
padding:12px 16px;color:#FCA5A5;font-size:13px;margin-bottom:16px;display:none;text-align:center}
.error-msg.visible{display:block;animation:shake .4s}
@keyframes shake{0%,100%{transform:translateX(0)}20%,60%{transform:translateX(-6px)}40%,80%{transform:translateX(6px)}}
.footer-text{text-align:center;color:rgba(255,255,255,.3);font-size:11px;margin-top:24px}
</style>
</head>
<body>
<div class="bg-circle"></div>
<div class="bg-circle"></div>
<div class="bg-circle"></div>
<div class="login-card">
<div class="logo">
<div class="logo-icon">C</div>
<h1>Canifa Admin</h1>
<p>Dashboard quản trị AI Stylist</p>
</div>
<div class="error-msg" id="errorMsg"></div>
<form id="loginForm" onsubmit="handleLogin(event)">
<div class="form-group">
<label>Tên đăng nhập</label>
<input type="text" id="username" placeholder="admin" autocomplete="username" required autofocus>
</div>
<div class="form-group">
<label>Mật khẩu</label>
<input type="password" id="password" placeholder="••••••••" autocomplete="current-password" required>
</div>
<button type="submit" class="login-btn" id="loginBtn">Đăng nhập</button>
</form>
<div class="footer-text">© 2026 Canifa AI Stylist · Powered by Gemini</div>
</div>
<script> <script>
// Check if already logged in window.location.replace('/static/main.html');
const existingUser = JSON.parse(localStorage.getItem('canifa_user') || 'null');
if (localStorage.getItem('canifa_token') && existingUser) {
window.location.replace(existingUser.role === 'admin' ? 'admin.html' : 'main.html');
}
async function handleLogin(e) {
e.preventDefault();
const btn = document.getElementById('loginBtn');
const errEl = document.getElementById('errorMsg');
errEl.classList.remove('visible');
btn.disabled = true;
btn.textContent = 'Đang xác thực...';
try {
const res = await fetch('/api/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
username: document.getElementById('username').value.trim(),
password: document.getElementById('password').value,
}),
});
const data = await res.json();
if (!res.ok) {
throw new Error(data.detail || 'Đăng nhập thất bại');
}
// Save to localStorage
localStorage.setItem('canifa_token', data.access_token);
localStorage.setItem('canifa_user', JSON.stringify(data.user));
// Redirect based on role: admin → admin.html, others → main.html
const customRedirect = new URLSearchParams(window.location.search).get('redirect');
const defaultPage = data.user.role === 'admin' ? 'admin.html' : 'main.html';
window.location.replace(customRedirect || defaultPage);
} catch (err) {
errEl.textContent = err.message;
errEl.classList.add('visible');
btn.disabled = false;
btn.textContent = 'Đăng nhập';
}
}
</script> </script>
</head>
<body>
<p>Redirecting...</p>
</body> </body>
</html> </html>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment