86 lines
2.8 KiB
JavaScript
86 lines
2.8 KiB
JavaScript
/**
|
|
* tenantLoader.js — Dynamically applies branding. Reads tenantId from JWT in localStorage.
|
|
*/
|
|
|
|
async function loadTenantBranding() {
|
|
// Try to extract tenantId from JWT stored by login
|
|
let tenantId = 'default';
|
|
|
|
const token = localStorage.getItem('curio_token');
|
|
if (token) {
|
|
try {
|
|
const payload = JSON.parse(atob(token.split('.')[1]));
|
|
if (payload.tenantId) tenantId = payload.tenantId;
|
|
} catch (_) { /* malformed token */ }
|
|
}
|
|
|
|
// URL param override (for white-label previews)
|
|
const urlParams = new URLSearchParams(window.location.search);
|
|
const urlTenant = urlParams.get('tenant');
|
|
if (urlTenant) tenantId = urlTenant;
|
|
|
|
localStorage.setItem('Curio_tenant', tenantId);
|
|
|
|
try {
|
|
const headers = {};
|
|
if (token) headers['Authorization'] = `Bearer ${token}`;
|
|
|
|
const response = await fetch(`/api/config/${tenantId}`, { headers });
|
|
if (response.ok) {
|
|
const config = await response.json();
|
|
applyBranding(config);
|
|
}
|
|
} catch (error) {
|
|
console.error('Failed to load tenant branding:', error);
|
|
}
|
|
}
|
|
|
|
function applyBranding(config) {
|
|
if (config.primaryColor) document.documentElement.style.setProperty('--primary', config.primaryColor);
|
|
if (config.secondaryColor) document.documentElement.style.setProperty('--secondary', config.secondaryColor);
|
|
|
|
document.querySelectorAll('.logo-icon').forEach(el => el.innerText = config.logo || 'C');
|
|
document.querySelectorAll('[data-tenant-name]').forEach(el => el.innerText = config.name);
|
|
|
|
if (config.name) document.title = `${config.name} | Curio`;
|
|
|
|
console.log(`Branding applied for: ${config.name}`);
|
|
}
|
|
|
|
/**
|
|
* Returns the JWT auth header object for fetch calls.
|
|
*/
|
|
function getAuthHeaders() {
|
|
const token = localStorage.getItem('curio_token');
|
|
return token ? { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }
|
|
: { 'Content-Type': 'application/json' };
|
|
}
|
|
|
|
/**
|
|
* Redirects to login if no valid token is present.
|
|
* Call on protected pages.
|
|
*/
|
|
function requireLogin(allowedRoles) {
|
|
const token = localStorage.getItem('curio_token');
|
|
if (!token) { window.location.href = '/'; return null; }
|
|
try {
|
|
const payload = JSON.parse(atob(token.split('.')[1]));
|
|
// Simple expiry check
|
|
if (payload.exp && Date.now() / 1000 > payload.exp) {
|
|
localStorage.clear();
|
|
window.location.href = '/';
|
|
return null;
|
|
}
|
|
if (allowedRoles && !allowedRoles.includes(payload.role)) {
|
|
window.location.href = '/';
|
|
return null;
|
|
}
|
|
return payload;
|
|
} catch (_) {
|
|
window.location.href = '/';
|
|
return null;
|
|
}
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', loadTenantBranding);
|