'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); } /** * * @returns {Promise} */ fetchServices() { return(fetch('/app/assets/json/global/services.json?'+crypto.randomUUID(), { method: 'GET' }) .then(response => response.text()) .then(response => JSON.parse(response)) .then(response => app.config.api = response.payload) ) } /** * * @param {*} callBack */ async checkAuthenticated(callBack){ const startbtn = document.querySelector('#startbtn') const gobtn = document.querySelector('#login-dialog button') gobtn.addEventListener('click', () => this.launchLogin(callBack)) 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') document.querySelector('input[name="username"]').focus() document.getElementById('login-dialog').addEventListener('keyup',(event)=>{ if(event.key=='Enter') this.launchLogin(callBack) }) 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 this.identity = jsonresp.payload.userInfos.identity this.roles = jsonresp.payload.userInfos.roles this.loadUserModel() callBack() } }) } async launchLogin(callBack){ const gobtn = document.querySelector('#login-dialog button') gobtn.disabled = true if(await this.login()) { document.querySelector('div.loginerr').classList.remove('show') console.log('Successful login !!!') this.loadUserModel() callBack() } else { gobtn.disabled = false } } loadUserModel(){ app.events.addEvent('core.mvcReady', async () => { await Loader.loadScripts({ 'scripts':[app.config.userLib.modelPath], 'dependencies':[], }) this.model = new MyUserModleModel() this.loadPreferences() this.fetchServices() }, 'myUser') } /** * * @returns {string} */ getMessageBusUserInfo() { return(this.identity.username) } 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.identity = jsonresp.payload.userInfos.identity this.roles = jsonresp.payload.userInfos.roles 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.identity = 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() { this.model.getPreferences().then(settings => { this.preferences = settings.value || {} }) } savePreferences() { this.model.setPreferences({ key: `${this.identity.uuid}:userPrefs`, value: this.preferences }) } getPreference(path) { let value = null; 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) { const segments = path.split('.') let pointer = this.preferences for (let i = 0; i < segments.length - 1; i++) { const segment = segments[i] if (!pointer[segment] || typeof pointer[segment] !== 'object') { pointer[segment] = {} } pointer = pointer[segment] } const lastKey = segments.at(-1) const existing = pointer[lastKey] if ((typeof(value) == 'object') && (value !== null) && (typeof(existing) == 'object') && (existing !== null)) { // merge instead of overwrite Object.assign(existing, value) } else { pointer[lastKey] = value } this.savePreferences() } } app.registerClass('User', myUser, true); // for Sparc to use app.registerClass('myUser', myUser, true); // Just to avoid double-loading if squeezed