Merge pull request '#7272 - BUG Redirect To Login when ACL not exists' (!2371) from 7272_bug_redirectToLogin into dev
gitea/salix/pipeline/head There was a failure building this commit Details

Reviewed-on: #2371
Reviewed-by: Javi Gallego <jgallego@verdnatura.es>
Reviewed-by: Alex Moreno <alexm@verdnatura.es>
This commit is contained in:
Javier Segarra 2024-05-27 06:56:19 +00:00
commit 50ef375c6b
7 changed files with 78 additions and 26 deletions

View File

@ -18,15 +18,10 @@ module.exports = Self => {
Self.renewToken = async function(ctx) { Self.renewToken = async function(ctx) {
const {accessToken: token} = ctx.req; const {accessToken: token} = ctx.req;
// Check if current token is valid const {courtesyTime} = await models.AccessTokenConfig.findOne({
fields: ['courtesyTime']
const {renewPeriod, courtesyTime} = await models.AccessTokenConfig.findOne({
fields: ['renewPeriod', 'courtesyTime']
}); });
const now = Date.now(); const isNotExceeded = await Self.validateToken(ctx);
const differenceMilliseconds = now - token.created;
const differenceSeconds = Math.floor(differenceMilliseconds / 1000);
const isNotExceeded = differenceSeconds < renewPeriod - courtesyTime;
if (isNotExceeded) if (isNotExceeded)
return token; return token;

View File

@ -0,0 +1,30 @@
const {models} = require('vn-loopback/server/server');
module.exports = Self => {
Self.remoteMethodCtx('validateToken', {
description: 'Validates the current logged user token',
accepts: [],
accessType: 'READ',
returns: {
type: 'Boolean',
root: true
},
http: {
path: `/validateToken`,
verb: 'GET'
}
});
Self.validateToken = async function(ctx) {
const {accessToken: token} = ctx.req;
// Check if current token is valid
const {renewPeriod, courtesyTime} = await models.AccessTokenConfig.findOne({
fields: ['renewPeriod', 'courtesyTime']
});
const now = Date.now();
const differenceMilliseconds = now - token.created;
const differenceSeconds = Math.floor(differenceMilliseconds / 1000);
const isNotExceeded = differenceSeconds < renewPeriod - courtesyTime;
return isNotExceeded;
};
};

View File

@ -15,6 +15,7 @@ module.exports = function(Self) {
require('../methods/vn-user/renew-token')(Self); require('../methods/vn-user/renew-token')(Self);
require('../methods/vn-user/share-token')(Self); require('../methods/vn-user/share-token')(Self);
require('../methods/vn-user/update-user')(Self); require('../methods/vn-user/update-user')(Self);
require('../methods/vn-user/validate-token')(Self);
Self.definition.settings.acls = Self.definition.settings.acls.filter(acl => acl.property !== 'create'); Self.definition.settings.acls = Self.definition.settings.acls.filter(acl => acl.property !== 'create');

View File

@ -113,6 +113,13 @@
"principalId": "$everyone", "principalId": "$everyone",
"permission": "ALLOW" "permission": "ALLOW"
}, },
{
"property": "validateToken",
"accessType": "EXECUTE",
"principalType": "ROLE",
"principalId": "$authenticated",
"permission": "ALLOW"
},
{ {
"property": "privileges", "property": "privileges",
"accessType": "*", "accessType": "*",

View File

@ -69,3 +69,4 @@ Send cau: Enviar cau
By sending this ticket, all the data related to the error, the section, the user, etc., are already sent.: Al enviar este cau ya se envían todos los datos relacionados con el error, la sección, el usuario, etc By sending this ticket, all the data related to the error, the section, the user, etc., are already sent.: Al enviar este cau ya se envían todos los datos relacionados con el error, la sección, el usuario, etc
ExplainReason: Explique el motivo por el que no deberia aparecer este fallo ExplainReason: Explique el motivo por el que no deberia aparecer este fallo
You already have the mailAlias: Ya tienes este alias de correo You already have the mailAlias: Ya tienes este alias de correo
Error loading ACLs: Error al cargar los ACLs

View File

@ -7,16 +7,17 @@ import UserError from 'core/lib/user-error';
* @property {Boolean} loggedIn Whether the user is currently logged * @property {Boolean} loggedIn Whether the user is currently logged
*/ */
export default class Auth { export default class Auth {
constructor($http, $q, $state, $transitions, $window, vnToken, vnModules, aclService) { constructor($http, $q, vnApp, $translate, $state, $transitions, $window, vnToken, vnModules) {
Object.assign(this, { Object.assign(this, {
$http, $http,
$q, $q,
vnApp,
$translate,
$state, $state,
$transitions, $transitions,
$window, $window,
vnToken, vnToken,
vnModules, vnModules,
aclService,
loggedIn: false loggedIn: false
}); });
} }
@ -39,9 +40,26 @@ export default class Auth {
}; };
if (this.vnToken.token) { if (this.vnToken.token) {
return this.loadAcls() const loadWithRetry = () => {
return this.validateToken()
.then(() => true) .then(() => true)
.catch(redirectToLogin); .catch(err => {
switch (err.status) {
case 400:
case 401:
return redirectToLogin();
default:
return new Promise(resolve => {
setTimeout(() => {
this.vnApp.showMessage(this.$translate.instant('Loading...'));
resolve(loadWithRetry());
}, 2000);
});
}
});
};
return loadWithRetry();
} else } else
return redirectToLogin(); return redirectToLogin();
}); });
@ -87,13 +105,11 @@ export default class Auth {
headers: {Authorization: json.data.token} headers: {Authorization: json.data.token}
}).then(({data}) => { }).then(({data}) => {
this.vnToken.set(json.data.token, data.multimediaToken.id, now, json.data.ttl, remember); this.vnToken.set(json.data.token, data.multimediaToken.id, now, json.data.ttl, remember);
this.loadAcls().then(() => {
let continueHash = this.$state.params.continue; let continueHash = this.$state.params.continue;
if (continueHash) if (continueHash)
this.$window.location = continueHash; this.$window.location = continueHash;
else else
this.$state.go('home'); this.$state.go('home');
});
}).catch(() => {}); }).catch(() => {});
} }
@ -107,24 +123,25 @@ export default class Auth {
this.vnToken.unset(); this.vnToken.unset();
this.loggedIn = false; this.loggedIn = false;
this.vnModules.reset(); this.vnModules.reset();
this.aclService.reset(); this.vnModules.aclService.reset();
this.$state.go('login'); this.$state.go('login');
return promise; return promise;
} }
loadAcls() { validateToken() {
return this.aclService.load() return this.$http.get('VnUsers/validateToken')
.then(() => { .then(() => {
this.loggedIn = true; this.loggedIn = true;
this.vnModules.reset(); this.vnModules.reset();
}) })
.catch(err => { .catch(err => {
this.vnToken.unset();
throw err; throw err;
}); });
} }
} }
Auth.$inject = ['$http', '$q', '$state', '$transitions', '$window', 'vnToken', 'vnModules', 'aclService']; Auth.$inject = [
'$http', '$q', 'vnApp', '$translate', '$state',
'$transitions', '$window', 'vnToken', 'vnModules'];
ngModule.service('vnAuth', Auth); ngModule.service('vnAuth', Auth);

View File

@ -12,7 +12,8 @@ function config($stateProvider, $urlRouterProvider) {
template: '<vn-layout></vn-layout>', template: '<vn-layout></vn-layout>',
resolve: { resolve: {
config: ['vnConfig', vnConfig => vnConfig.initialize()], config: ['vnConfig', vnConfig => vnConfig.initialize()],
token: ['vnToken', vnToken => vnToken.fetchConfig()] token: ['vnToken', vnToken => vnToken.fetchConfig()],
acl: ['aclService', aclService => aclService.load()]
} }
}) })
.state('outLayout', { .state('outLayout', {