@c8y/bootstrap
Version:
Bootstrap layer
178 lines • 6.16 kB
JavaScript
export const TOKEN_KEY = '_tcy8';
export const TFATOKEN_KEY = 'TFAToken';
export const queryParamsThatRequireRedirectToLoginApp = [
// in case of password reset
'email',
'token',
// others
'code',
'session_state',
'error',
'error_description'
];
function getClientLib() {
return import('@c8y/client');
}
export async function loadManifest(client, options) {
try {
const contextPath = getCurrentContextPath(options);
const normalizedContextPath = contextPath?.split('@')[0];
const { data: applicationManifest } = await client.application.getManifestOfContextPath(normalizedContextPath);
const { data: application } = await client.application.detail(applicationManifest.id);
return application;
}
catch (ex) {
throw ex;
}
}
const attributes = ['key', 'name', 'contextPath'];
export function addCssClassesForApp(app) {
if (!app) {
return;
}
for (const attr of attributes) {
const value = app[attr];
if (!value || typeof value !== 'string') {
continue;
}
const normalizedValue = value.toLowerCase().replace(/[^a-z0-9\-\_]+/g, '-');
document.body.classList.add(`c8y-app-${attr}_${normalizedValue}`);
}
}
export function addCssVariablesForApp(app) {
if (!app) {
return;
}
let content = '';
for (const attr of attributes) {
const value = app[attr];
if (!value || typeof value !== 'string') {
continue;
}
content += `--c8y-app-${attr}: '${value}';\n`;
}
if (!content) {
return;
}
const style = document.createElement('style');
style.setAttribute('id', 'app-css-variables');
style.appendChild(document.createTextNode(`:root {\n${content}\n}`));
document.querySelector('body').appendChild(style);
}
export function redirectToLoginApp(options) {
// to redirect back to the current page after login
const pathWithSearch = window.location.pathname + window.location.search + window.location.hash;
sessionStorage.setItem('c8yRedirectAfterLoginPath', pathWithSearch);
const basePathOfLoginApp = options?.loginRedirectPath || '/apps/public/login/';
// use the same query params on login app
window.location.href = basePathOfLoginApp + window.location.search;
}
/**
* Redirects to the login application in case the user is not logged in.
*/
export async function ensureLoggedInIfRequired(options) {
const clientAndCurrentUser = await getCurrentUser();
const parsedQuery = new URLSearchParams(window.location.search);
const requiresRedirect = queryParamsThatRequireRedirectToLoginApp.some(param => parsedQuery.has(param));
if ((!clientAndCurrentUser && !options?.noLogin) || requiresRedirect) {
redirectToLoginApp(options);
return false;
}
let currentTenant = null;
if (clientAndCurrentUser) {
try {
const { data } = await clientAndCurrentUser.client.tenant.current({
withParent: true
});
clientAndCurrentUser.client.core.tenant = data.name;
currentTenant = data;
}
catch (ex) {
console.warn('Error while getting current tenant', ex);
}
}
let currentApp = {
name: options.name,
contextPath: getCurrentContextPath(),
icon: options.icon
};
if (clientAndCurrentUser) {
try {
currentApp = await loadManifest(clientAndCurrentUser.client, options);
}
catch (ex) {
if (!(ex.res && ex.res.status === 404 && isLocal())) {
// User was most likely already logged in, but does not have access to the app
console.warn('Error while getting current app', ex);
console.warn('You probably do not have access to this app');
redirectToLoginApp(options);
return false;
}
}
}
addCssClassesForApp(currentApp);
addCssVariablesForApp(currentApp);
return { ...clientAndCurrentUser, currentApp, currentTenant };
}
export function isLocal() {
const hostname = window.location.hostname;
const localhostRegExp = new RegExp('localhost');
const localhostIpRegExp = new RegExp('127.0.0.1');
return localhostIpRegExp.test(hostname) || localhostRegExp.test(hostname);
}
export function getCurrentContextPath(options = {}) {
const match = window.location.pathname.match(/\/apps\/(public\/){0,1}(.+?)(\/|\?|#|$)/);
return (match && match[2]) || options.contextPath;
}
export async function getCurrentUser() {
let client;
let currentUser;
try {
const clientLib = await getClientLib();
client = new clientLib.Client(await getAuthStrategy());
try {
const { data } = await client.user.current();
currentUser = data;
}
catch (e) {
if (e.res?.status === 403) {
const { data } = await client.user.currentWithEffectiveRoles();
currentUser = data;
}
else {
throw e;
}
}
}
catch (e) {
return null;
}
return { client, currentUser };
}
export function pickAuthStrategy(bearer, basic, cookie) {
try {
const authStrategy = new bearer();
console.log(`Using BearerAuthFromSessionStorage`);
return authStrategy;
}
catch (e) {
// do nothing
}
const token = getStoredToken();
const tfa = getStoredTfaToken();
if (token) {
return new basic({ token, tfa });
}
return new cookie();
}
export async function getAuthStrategy() {
const clientLib = await getClientLib();
return pickAuthStrategy(clientLib.BearerAuthFromSessionStorage, clientLib.BasicAuth, clientLib.CookieAuth);
}
export function getStoredToken() {
return localStorage.getItem(TOKEN_KEY) || sessionStorage.getItem(TOKEN_KEY);
}
export function getStoredTfaToken() {
return localStorage.getItem(TFATOKEN_KEY) || sessionStorage.getItem(TFATOKEN_KEY);
}
//# sourceMappingURL=login-check.js.map