268 lines
7.8 KiB
JavaScript
268 lines
7.8 KiB
JavaScript
(function() {
|
|
var STORAGE_KEY = 'crank_user';
|
|
var sessionCache = null;
|
|
var sessionPromise = null;
|
|
function tKey(key) {
|
|
return typeof t === 'function' ? t(key) : key;
|
|
}
|
|
function tfKey(key, vars) {
|
|
return typeof tf === 'function' ? tf(key, vars) : key;
|
|
}
|
|
function roleLabel(role) {
|
|
var normalized = String(role || 'viewer').toLowerCase();
|
|
if (normalized === 'operator') return tKey('workspace_setup.role.operator');
|
|
if (normalized === 'owner') return tKey('workspace_setup.role.owner');
|
|
if (normalized === 'admin') return tKey('workspace_setup.role.admin');
|
|
if (normalized === 'viewer') return tKey('workspace_setup.role.viewer');
|
|
return normalized.replace(/^\w/, function(char) { return char.toUpperCase(); });
|
|
}
|
|
|
|
function currentWorkspaceLabel() {
|
|
if (window.getCurrentWorkspace) {
|
|
var workspace = window.getCurrentWorkspace();
|
|
if (workspace && workspace.name) {
|
|
return workspace.name;
|
|
}
|
|
}
|
|
try {
|
|
return localStorage.getItem('crank_workspace_slug') || tKey('settings.nav.workspace');
|
|
} catch (_error) {
|
|
return tKey('settings.nav.workspace');
|
|
}
|
|
}
|
|
|
|
function isLoginPage() {
|
|
return /\/(?:html\/login\.html|login)\/?$/.test(window.location.pathname);
|
|
}
|
|
|
|
function loginUrl() {
|
|
return (window.CrankRoutes && window.CrankRoutes.login) || '/login';
|
|
}
|
|
|
|
function homeUrl() {
|
|
return (window.CrankRoutes && window.CrankRoutes.home) || '/';
|
|
}
|
|
|
|
function clearUserMirror() {
|
|
sessionCache = null;
|
|
sessionPromise = null;
|
|
try {
|
|
localStorage.removeItem(STORAGE_KEY);
|
|
} catch (_error) {}
|
|
renderShellIdentity(null);
|
|
}
|
|
|
|
function primaryMembership(session) {
|
|
if (!(session && session.memberships && session.memberships.length)) {
|
|
return null;
|
|
}
|
|
if (session.current_workspace_id) {
|
|
var currentMembership = session.memberships.find(function(item) {
|
|
return item.workspace && item.workspace.id === session.current_workspace_id;
|
|
});
|
|
if (currentMembership) {
|
|
return currentMembership;
|
|
}
|
|
}
|
|
if (window.getCurrentWorkspace) {
|
|
var currentWorkspace = window.getCurrentWorkspace();
|
|
if (currentWorkspace) {
|
|
var matched = session.memberships.find(function(item) {
|
|
return item.workspace && item.workspace.id === currentWorkspace.id;
|
|
});
|
|
if (matched) {
|
|
return matched;
|
|
}
|
|
}
|
|
}
|
|
return session.memberships[0];
|
|
}
|
|
|
|
function initials(displayName, email) {
|
|
var source = safeIdentityText(displayName, 80, '') || safeIdentityText(email, 254, '') || 'Crank';
|
|
return source
|
|
.split(/\s+/)
|
|
.filter(Boolean)
|
|
.slice(0, 2)
|
|
.map(function(part) { return part.charAt(0).toUpperCase(); })
|
|
.join('') || 'CR';
|
|
}
|
|
|
|
function safeIdentityText(value, maxLength, fallback) {
|
|
var text = String(value || '')
|
|
.replace(/[\r\n\t]+/g, ' ')
|
|
.replace(/\s{2,}/g, ' ')
|
|
.trim();
|
|
if (!text || /<\s*(?:!doctype|html|head|body|nav|script)\b/i.test(text)) {
|
|
return fallback || '';
|
|
}
|
|
if (text.length > maxLength) {
|
|
return fallback || '';
|
|
}
|
|
return text;
|
|
}
|
|
|
|
function persistUserMirror(session) {
|
|
var membership = primaryMembership(session);
|
|
var user = {
|
|
id: session.user.id,
|
|
name: safeIdentityText(session.user.display_name, 80, 'Crank'),
|
|
email: safeIdentityText(session.user.email, 254, ''),
|
|
role: membership ? roleLabel(membership.role) : tKey('workspace_setup.role.viewer'),
|
|
workspace: membership ? membership.workspace.slug : '',
|
|
workspaceId: membership ? membership.workspace.id : '',
|
|
initials: initials(session.user.display_name, session.user.email),
|
|
};
|
|
|
|
try {
|
|
localStorage.setItem(STORAGE_KEY, JSON.stringify(user));
|
|
} catch (_error) {}
|
|
}
|
|
|
|
function mirroredUser() {
|
|
try {
|
|
return JSON.parse(localStorage.getItem(STORAGE_KEY));
|
|
} catch (_error) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function renderShellIdentity(session) {
|
|
var membership = primaryMembership(session);
|
|
var fallbackUser = mirroredUser();
|
|
var displayName = session && session.user
|
|
? (safeIdentityText(session.user.display_name, 80, '') || safeIdentityText(session.user.email, 254, '') || 'Crank')
|
|
: safeIdentityText(fallbackUser && fallbackUser.name, 80, 'Crank');
|
|
var email = session && session.user
|
|
? safeIdentityText(session.user.email, 254, '')
|
|
: safeIdentityText(fallbackUser && fallbackUser.email, 254, '');
|
|
var role = membership
|
|
? roleLabel(membership.role)
|
|
: (fallbackUser && fallbackUser.role) || tKey('workspace_setup.role.viewer');
|
|
var workspace = membership && membership.workspace
|
|
? (membership.workspace.display_name || membership.workspace.slug || membership.workspace.id)
|
|
: currentWorkspaceLabel();
|
|
var avatarValue = initials(displayName, email);
|
|
|
|
document.querySelectorAll('.nav-avatar').forEach(function(element) {
|
|
element.textContent = avatarValue;
|
|
});
|
|
document.querySelectorAll('.user-dropdown-name').forEach(function(element) {
|
|
element.textContent = displayName;
|
|
});
|
|
document.querySelectorAll('.user-dropdown-role').forEach(function(element) {
|
|
element.textContent = role + ' · ' + workspace;
|
|
});
|
|
if (window.CrankDiagnostics && typeof window.CrankDiagnostics.ensureShellTestIds === 'function') {
|
|
window.CrankDiagnostics.ensureShellTestIds();
|
|
}
|
|
}
|
|
|
|
function replaceSession(session) {
|
|
sessionCache = session;
|
|
persistUserMirror(session);
|
|
renderShellIdentity(session);
|
|
window.dispatchEvent(new CustomEvent('crank:sessionchange', { detail: session }));
|
|
return session;
|
|
}
|
|
|
|
async function fetchSession(force) {
|
|
if (!force && sessionCache) {
|
|
return sessionCache;
|
|
}
|
|
if (!force && sessionPromise) {
|
|
return sessionPromise;
|
|
}
|
|
|
|
sessionPromise = window.CrankApi.getSession()
|
|
.then(function(session) {
|
|
return replaceSession(session);
|
|
})
|
|
.catch(function(error) {
|
|
clearUserMirror();
|
|
throw error;
|
|
})
|
|
.finally(function() {
|
|
sessionPromise = null;
|
|
});
|
|
|
|
return sessionPromise;
|
|
}
|
|
|
|
async function guardProtectedPage() {
|
|
try {
|
|
return await fetchSession(false);
|
|
} catch (error) {
|
|
if (error && error.status === 401) {
|
|
window.location.replace(loginUrl());
|
|
return null;
|
|
}
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
async function guardLoginPage() {
|
|
try {
|
|
await fetchSession(false);
|
|
window.location.replace(homeUrl());
|
|
} catch (error) {
|
|
if (!error || error.status !== 401) {
|
|
throw error;
|
|
}
|
|
}
|
|
}
|
|
|
|
async function login(email, password) {
|
|
var session = await window.CrankApi.login({
|
|
email: email,
|
|
password: password,
|
|
});
|
|
replaceSession(session);
|
|
window.location.href = homeUrl();
|
|
}
|
|
|
|
async function logout() {
|
|
try {
|
|
await window.CrankApi.logout();
|
|
} finally {
|
|
clearUserMirror();
|
|
window.location.href = loginUrl();
|
|
}
|
|
}
|
|
|
|
function handleUnauthorized() {
|
|
if (isLoginPage()) {
|
|
clearUserMirror();
|
|
return;
|
|
}
|
|
clearUserMirror();
|
|
window.location.replace(loginUrl());
|
|
}
|
|
|
|
window.CrankAuth = {
|
|
fetchSession: fetchSession,
|
|
replaceSession: replaceSession,
|
|
getCachedSession: function() { return sessionCache; },
|
|
renderShellIdentity: function() {
|
|
renderShellIdentity(sessionCache);
|
|
},
|
|
guardProtectedPage: guardProtectedPage,
|
|
guardLoginPage: guardLoginPage,
|
|
login: login,
|
|
logout: logout,
|
|
handleUnauthorized: handleUnauthorized,
|
|
};
|
|
|
|
window.addEventListener('crank:workspacechange', function() {
|
|
renderShellIdentity(sessionCache);
|
|
});
|
|
|
|
window.addEventListener('crank:sessionchange', function(event) {
|
|
renderShellIdentity(event.detail || sessionCache);
|
|
});
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
renderShellIdentity(sessionCache);
|
|
});
|
|
}());
|