'use strict' /** __ __ ( )( ) ___ ____ ____ )( )( / __)( ___)( _ \ )(__)( \__ \ )__) ) / (______)(___/(____)(_)\_) By Nike This file is part of P42 implementation of SPARC. * @category MyEic * @subcategory Libraries * @extends User */ class myUser extends app.LoadedClasses.User { authUrl = ''; preferences = {} /** * */ constructor() { super(); } /** * Checks if user belongs to a role * @param {string} role * @returns {boolean} */ hasRole(role) { return(this.roles.indexOf(role)>-1); } /** * * @returns {Array} */ getRoles() { return(app.User.roles); } /** * @async * @returns {string} * */ fetchServices() { let host = new URL(app.config.userLib.apiDiscoveryEndpoint).host let stage = (host.split('.')[1] != 'eismea') ? '.'+host.split('.')[1] : '' return(fetch('/app/assets/json/global/services.json?'+crypto.randomUUID(), { method: 'GET' }) .then(response=>response.text()) .then(response=>JSON.parse(response.replace(/__host__/g, host).replace(/__stage__/g, stage))) ) } /** * Candidate for deprecation * @returns {Promise} */ getApiServices() { return( this.fetchServices() .then(response => { if(response.success) { // Was to much to ask to respect existing code & existing contract, so do the cleanup here let api = {}; for(let entry of response.payload){ api[entry.resource] = entry.actions.reduce( (acc, v)=>{ acc[v.action]=v.availableMethod; return(acc); }, {} ); } // Now override with exceptions from config. (also creates from exceptions) for(let resource in app.config.userLib.apiStageExceptions){ if(!api.hasOwnProperty(resource)) api[resource] = []; for(let action in app.config.userLib.apiStageExceptions[resource]) { api[resource][action] = app.config.userLib.apiStageExceptions[resource][action]; console.warn(`Replacing / adding existing API with exception for resource: ${resource} action: ${action}`) } } app.config.api = api; } } ) ) } /** * * @param {*} callBack */ async checkAuthenticated(callBack){ const startbtn = document.querySelector('#startbtn') const gobtn = document.querySelector('#login-dialog button') gobtn.addEventListener('click', async () => { gobtn.disabled = true if(await this.login()) { document.querySelector('div.loginerr').classList.remove('show') console.log('Successful login !!!') callBack() } else { gobtn.disabled = false } }) startbtn.addEventListener('click', async () => { startbtn.disabled = true this.isAuthenticated = false const response = await fetch(app.config.userLib.checkauthEndpoint+'?'+crypto.randomUUID()) let jsonresp = null if(response.ok) { jsonresp = await response.json() } if(!jsonresp ||(!jsonresp.payload)) { console.error('No valid response from checkauth !?') startbtn.disabled = false } else if(!jsonresp.payload.authenticated){ document.querySelector('div.loginerr').classList.remove('show') document.getElementById('login-dialog').classList.add('show') if(jsonresp.payload.locked){ document.querySelector('div.loginerr').classList.add('show') document.querySelector('div.loginerr').innerHTML = ` The account has been locked !
(Ask an admin to unlock it.) ` } } else { console.log('authenticated!') this.isAuthenticated = true callBack() } }) } /** * * @returns {string} */ getMessageBusUserInfo() { return(this.identity.uuid) } async login(){ const response = await fetch(app.config.userLib.loginEndpoint+'?'+crypto.randomUUID(), { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username: document.querySelector('input[name="username"]').value, passwd: document.querySelector('input[name="password"]').value, }) }) let jsonresp = null if(response.ok) { jsonresp = await response.json() } if(jsonresp && jsonresp.success && jsonresp.payload){ if(jsonresp.payload.authenticated){ this.isAuthenticated = true this.userInfos = jsonresp.payload.userInfos return(true) } else { document.querySelector('div.loginerr').classList.add('show') if(!jsonresp.payload.locked){ document.querySelector('div.loginerr').innerHTML = ` Bad username or password !
(${jsonresp.payload.trials} trials left.) ` } else { document.querySelector('div.loginerr').innerHTML = ` The account has been locked !
(Ask an admin to unlock it.) ` } } } this.isAuthenticated = false this.userInfos = null return(false) } /** * * @param {string} jumpTo */ logout(jumpTo='') { jumpTo = jumpTo ? jumpTo : this.logoutUrl fetch(app.config.userLib.logoutEndpoint+'?'+crypto.randomUUID(),{ method: 'GET', credentials: 'include' }).then((resp) =>{ window.onbeforeunload = null // If user confirmed to logout, not need to have him confirm he's leaving the app ! document.location.href = jumpTo; }); } /** * This is separated, so that upper layer has a chance to use a login button, or avoid redirection loops. */ gotoLogin() { window.onbeforeunload = null // If user asks to relogin, not need to have him confirm he's leaving the app ! document.location.href = this.authUrl; } /** * * @param {*} info */ async parseUserInfo(info) { this.identity = { uuid: info.euLoginId, firstname: info.family_name, lastname: info.given_name, email: info.email }; this.roles = info.userRoles || [] } loadPreferences() { if(app.MessageBus) { app.MessageBus.requestWssGwAction('GET', { key: `${this.identity.uuid}:userPrefs`}) .then(settings => { this.preferences = settings.value; }) } } savePreferences() { if(app.MessageBus) { app.MessageBus.requestWssGwAction('SET', { key: `${this.identity.uuid}:userPrefs`, value: this.preferences }) } } getPreference(path) { let value = null; if(app.MessageBus) { let segments = path.split('.'); let pointer = this.preferences; if(pointer) { for(let segment of segments) { if(pointer[segment]) { if(typeof pointer[segment] == 'object') { pointer = pointer[segment]; } else { value = pointer[segment]; } } else { break; } } } } return value; } setPreference(path, value) { if(app.MessageBus) { let segments = path.split('.'); let pointer = this.preferences; for(let i = 0; i < segments.length - 1; i++) { let segment = segments[i]; if(!pointer[segment]) { pointer[segment] = {}; } pointer = pointer[segment]; } pointer[segments[segments.length - 1]] = value; } this.savePreferences(); } } app.registerClass('User', myUser, true); // for Sparc to use app.registerClass('myUser', myUser, true); // Just to avoid double-loading if squeezed