From ac83788f1ae8e9cc236340560d1266d34ab9a1a2 Mon Sep 17 00:00:00 2001 From: vicent Date: Thu, 29 Jun 2023 10:45:02 +0200 Subject: [PATCH] refs #5554 fix: solo se llama al back cuando de va a renovar, i no se solapan las llamadas --- back/methods/vn-user/renew-token.js | 19 ++- back/models/access-token-config.json | 4 + db/changes/232601/00-salix.sql | 5 +- front/core/services/interceptor.js | 12 +- front/core/services/token.js | 133 +++++++++++++++----- front/salix/components/layout/index.html | 4 +- front/salix/components/layout/index.js | 47 +------ front/salix/components/layout/index.spec.js | 45 ------- front/salix/routes.js | 3 +- 9 files changed, 132 insertions(+), 140 deletions(-) diff --git a/back/methods/vn-user/renew-token.js b/back/methods/vn-user/renew-token.js index c3b25bf96..9850267d6 100644 --- a/back/methods/vn-user/renew-token.js +++ b/back/methods/vn-user/renew-token.js @@ -17,23 +17,22 @@ module.exports = Self => { Self.renewToken = async function(ctx) { const models = Self.app.models; - const userId = ctx.req.accessToken.userId; - const created = ctx.req.accessToken.created; - const tokenId = ctx.req.accessToken.id; + const token = ctx.req.accessToken; const now = new Date(); - const differenceMilliseconds = now - created; + const differenceMilliseconds = now - token.created; const differenceSeconds = Math.floor(differenceMilliseconds / 1000); - const accessTokenConfig = await models.AccessTokenConfig.findOne({fields: ['renewPeriod']}); + const fields = ['renewPeriod', 'courtesyTime']; + const accessTokenConfig = await models.AccessTokenConfig.findOne({fields}); - if (differenceSeconds < accessTokenConfig.renewPeriod) - throw new UserError(`The renew period has not been exceeded`); + if (differenceSeconds < accessTokenConfig.renewPeriod - accessTokenConfig.courtesyTime) + throw new UserError(`The renew period has not been exceeded`, 'periodNotExceeded'); - await Self.logout(tokenId); - const user = await Self.findById(userId); + await Self.logout(token.id); + const user = await Self.findById(token.userId); const accessToken = await user.createAccessToken(); - return {token: accessToken.id}; + return {id: accessToken.id, ttl: accessToken.ttl}; }; }; diff --git a/back/models/access-token-config.json b/back/models/access-token-config.json index 6d90a0f4d..d5838a158 100644 --- a/back/models/access-token-config.json +++ b/back/models/access-token-config.json @@ -16,6 +16,10 @@ "type": "number", "required": true }, + "courtesyTime": { + "type": "number", + "required": true + }, "renewInterval": { "type": "number", "required": true diff --git a/db/changes/232601/00-salix.sql b/db/changes/232601/00-salix.sql index dc1ed69be..44366abce 100644 --- a/db/changes/232601/00-salix.sql +++ b/db/changes/232601/00-salix.sql @@ -1,10 +1,11 @@ CREATE TABLE `salix`.`accessTokenConfig` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `renewPeriod` int(10) unsigned DEFAULT NULL, + `courtesyTime` int(10) unsigned DEFAULT NULL, `renewInterval` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -INSERT IGNORE INTO `salix`.`accessTokenConfig` (`id`, `renewPeriod`, `renewInterval`) +INSERT IGNORE INTO `salix`.`accessTokenConfig` (`id`, `renewPeriod`, `courtesyTime`, `renewInterval`) VALUES - (1, 21600, 300); + (1, 21600, 5, 300); diff --git a/front/core/services/interceptor.js b/front/core/services/interceptor.js index 3f3d9912b..1c7b1a460 100644 --- a/front/core/services/interceptor.js +++ b/front/core/services/interceptor.js @@ -1,11 +1,15 @@ import ngModule from '../module'; import HttpError from 'core/lib/http-error'; -interceptor.$inject = ['$q', 'vnApp', 'vnToken', '$translate']; -function interceptor($q, vnApp, vnToken, $translate) { +interceptor.$inject = ['$q', 'vnApp', '$translate']; +function interceptor($q, vnApp, $translate) { let apiPath = 'api/'; + let token; return { + setToken(newToken) { + token = newToken; + }, setApiPath(path) { apiPath = path; }, @@ -14,8 +18,8 @@ function interceptor($q, vnApp, vnToken, $translate) { if (config.url.charAt(0) !== '/' && apiPath) config.url = `${apiPath}${config.url}`; - if (vnToken.token) - config.headers.Authorization = vnToken.token; + if (token) + config.headers.Authorization = token; if ($translate.use()) config.headers['Accept-Language'] = $translate.use(); if (config.filter) { diff --git a/front/core/services/token.js b/front/core/services/token.js index 12696faec..d0e0b7ced 100644 --- a/front/core/services/token.js +++ b/front/core/services/token.js @@ -6,43 +6,114 @@ import ngModule from '../module'; * @property {String} token The current login token or %null */ export default class Token { - constructor() { - try { - this.token = sessionStorage.getItem('vnToken'); - this.created = sessionStorage.getItem('vnTokenCreated'); - this.renewPeriod = sessionStorage.getItem('vnTokenRenewPeriod'); - if (!this.token) { - this.token = localStorage.getItem('vnToken'); - this.created = localStorage.getItem('vnTokenCreated'); - this.renewPeriod = localStorage.getItem('vnTokenRenewPeriod'); - } - } catch (e) {} - } - set(token, created, renewPeriod, remember) { - this.unset(); - try { - if (remember) { - localStorage.setItem('vnToken', token); - localStorage.setItem('vnTokenCreated', created); - localStorage.setItem('vnTokenRenewPeriod', renewPeriod); - } else { - sessionStorage.setItem('vnToken', token); - sessionStorage.setItem('vnTokenCreated', created); - sessionStorage.setItem('vnTokenRenewPeriod', renewPeriod); - } - } catch (e) {} + constructor(vnInterceptor, $http, $rootScope) { + Object.assign(this, { + vnInterceptor, + $http, + $rootScope + }); - this.token = token; - this.created = created; - this.renewPeriod = renewPeriod; + try { + this.getStorage(sessionStorage); + this.remember = true; + + if (!this.token) { + this.getStorage(localStorage); + this.remember = false; + } + } catch (e) {} } + + set(token, created, ttl, remember) { + this.unset(); + + Object.assign(this, { + token, + created, + ttl, + remember + }); + this.vnInterceptor.setToken(token); + + try { + if (remember) + this.setStorage(localStorage, token, created, ttl); + else + this.setStorage(sessionStorage, token, created, ttl); + } catch (e) {} + } + unset() { - localStorage.removeItem('vnToken'); - sessionStorage.removeItem('vnToken'); this.token = null; this.created = null; - this.renewPeriod = null; + this.ttl = null; + this.remember = null; + this.vnInterceptor.setToken(null); + + this.removeStorage(localStorage); + this.removeStorage(sessionStorage); + } + + getStorage(storage) { + this.token = storage.getItem('vnToken'); + this.created = storage.getItem('vnTokenCreated'); + this.renewPeriod = storage.getItem('vnTokenRenewPeriod'); + } + + setStorage(storage, token, created, ttl) { + storage.setItem('vnToken', token); + storage.setItem('vnTokenCreated', created); + storage.setItem('vnTokenTtl', ttl); + } + + removeStorage(storage) { + storage.removeItem('vnToken'); + storage.removeItem('vnTokenCreated'); + storage.removeItem('vnTokenTtl'); + } + + fetchConfig() { + const filter = {fields: ['renewInterval', 'renewPeriod']}; + this.$http.get('AccessTokenConfigs/findOne', {filter}).then(res => { + const data = res.data; + if (!data) return; + this.renewPeriod = data.renewPeriod; + this.stopRenewer(); + this.inservalId = setInterval(() => this.checkValidity(), data.renewInterval * 1000); + this.checkValidity(); + }); + } + + checkValidity() { + if (this.checking) return; + this.checking = true; + const renewPeriod = Math.min(this.ttl, this.renewPeriod) * 1000; + const maxDate = this.created.getTime() + renewPeriod; + const now = new Date(); + + if (now.getTime() <= maxDate) { + this.checking = false; + return; + } + + this.$http.post('VnUsers/renewToken') + .then(res => { + const token = res.data; + this.set(token.id, now, token.ttl, this.remember); + }) + .catch(res => { + if (res.data?.error?.code !== 'periodNotExceeded') + throw res; + }) + .finally(() => { + this.checking = false; + }); + } + + stopRenewer() { + clearInterval(this.inservalId); } } +Token.$inject = ['vnInterceptor', '$http', '$rootScope']; ngModule.service('vnToken', Token); diff --git a/front/salix/components/layout/index.html b/front/salix/components/layout/index.html index 5a525ef77..972defaa1 100644 --- a/front/salix/components/layout/index.html +++ b/front/salix/components/layout/index.html @@ -42,7 +42,7 @@