unclean SPARC
This commit is contained in:
Executable
+352
@@ -0,0 +1,352 @@
|
||||
'use strict'
|
||||
/**
|
||||
__ __
|
||||
( )( ) ___ ____ ____
|
||||
)( )( / __)( ___)( _ \
|
||||
)(__)( \__ \ )__) ) /
|
||||
(______)(___/(____)(_)\_)
|
||||
By Nike
|
||||
|
||||
This file is part of EIC 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<string>}
|
||||
*/
|
||||
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
|
||||
*/
|
||||
checkAuthenticated(callBack){
|
||||
let headers = {};
|
||||
if(app.config.userLib.authForwardDomain) {
|
||||
let url = new URL(document.location.href);
|
||||
headers = { 'x-requested-path': url.pathname };
|
||||
}
|
||||
|
||||
this.identity = {
|
||||
uuid: 'nike',
|
||||
email: 'info@nicsys.eu'
|
||||
};
|
||||
this.roles = ['admin']
|
||||
return
|
||||
|
||||
fetch(app.config.userLib.authEndpoint+'?'+crypto.randomUUID(),{
|
||||
headers: headers,
|
||||
method: 'GET',
|
||||
credentials: 'include'
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(async resp => {
|
||||
if(resp.success){
|
||||
this.authenticationDone = true
|
||||
this.isAuthenticated = resp.payload.isAuthenticated;
|
||||
if(resp.payload.isAuthenticated) {
|
||||
if((!this.identity) || (!this.identity.uuid)) {
|
||||
this.logoutUrl = resp.payload.logoutUri;
|
||||
this.parseUserInfo(resp.payload.userInfo);
|
||||
}
|
||||
|
||||
this.platformRestrictions = resp.payload.platformRestrictions || null
|
||||
if((this.platformRestrictions) && (!this.isVIP())){
|
||||
this.ShowCurtain()
|
||||
this.stopKeepAlive()
|
||||
return // not triggering callback avoids any further ctrl loading by the router
|
||||
}
|
||||
|
||||
if(!app.config.api) await this.getApiServices()
|
||||
|
||||
if(app.config.userLib.keepAliveSeconds && (app.config.userLib.keepAliveSeconds>0)) this.startKeepAlive()
|
||||
|
||||
callBack();
|
||||
} else {
|
||||
console.warn('Authorizer said User was not authenticated !');
|
||||
this.authUrl = resp.payload.authUrl;
|
||||
this.logoutUrl = resp.payload.logoutUri;
|
||||
callBack();
|
||||
}
|
||||
} else {
|
||||
console.error('Server error calling authorizer checkAuthenticated (success not true)');
|
||||
this.stopKeepAlive() // Just in case KAL is active, because we arrive here from KAL itself
|
||||
document.location.href = '/eulogin-error.html';
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('Server error calling authorizer checkAuthenticated (Network error)',err);
|
||||
document.location.href = '/eulogin-error.html';
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
getMessageBusUserInfo() { return(this.identity.uuid) }
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} objects An array of URI to be checked
|
||||
* @param {*} role
|
||||
* @returns {Promise}
|
||||
*/
|
||||
getBusinessPermissions(objects, role) {
|
||||
let requestedObjects = { resources: objects }
|
||||
let uri = app.config.userLib.resourcePermissionsEndpoint.replace('{id}', this.identity.uuid);
|
||||
|
||||
// This is just to make use of the whole base model request mechanism (especially for the 401 flow)
|
||||
let fakeModel = new EICModel(null, null)
|
||||
return(
|
||||
fakeModel.request(uri, 'POST', requestedObjects)
|
||||
.then( async serverData => {
|
||||
return(serverData.payload)
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
startKeepAlive() {
|
||||
if((!app.config.userLib.keepAliveSeconds) || this.KALtimer) return
|
||||
this.KALtimer = setInterval(this.doKeepAlive.bind(this), 1000*app.config.userLib.keepAliveSeconds)
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
stopKeepAlive() {
|
||||
if(this.KALtimer) clearInterval(this.KALtimer)
|
||||
this.KALtimer = null
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
doKeepAlive() {
|
||||
this.checkAuthenticated(()=>{
|
||||
// KAL was successfull... do we care ?
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isVIP(){
|
||||
if(Array.isArray(this.platformRestrictions.allowedRoles)){
|
||||
let intersect = this.roles.filter(r => (this.platformRestrictions.allowedRoles.includes(r)) )
|
||||
if(intersect.length>0) return(true)
|
||||
}
|
||||
if((Array.isArray(this.platformRestrictions.allowedUUIDs)) &&
|
||||
(this.platformRestrictions.allowedUUIDs.includes(this.identity.uuid))){
|
||||
return(true)
|
||||
}
|
||||
return(false)
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @todo should be handled by an external view
|
||||
*/
|
||||
ShowCurtain() {
|
||||
let link = document.createElement("link");
|
||||
link.rel='stylesheet'
|
||||
link.type='text/css'
|
||||
link.href='/app/thirdparty/eicui/eicui-2.0.css'
|
||||
document.head.appendChild(link)
|
||||
|
||||
let style = document.createElement('style')
|
||||
style.innerHTML = ` .maintenance{ width: 40vw!important; text-align: center; margin: auto!important; } `
|
||||
document.head.appendChild(style)
|
||||
|
||||
let content = document.createElement('div')
|
||||
content.innerHTML = `
|
||||
<article class="maintenance" eiccard="" aria-enabled="true" >
|
||||
<header><h1>Maintenance</h1></header>
|
||||
<section>
|
||||
<alert eicalert="" danger="">
|
||||
The site is currently under maintenance.</br>
|
||||
Please come back later.
|
||||
</alert>
|
||||
</section>
|
||||
</article>
|
||||
`
|
||||
document.body.appendChild(content)
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @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
|
||||
Reference in New Issue
Block a user