#6264 - renewToken #1824
|
@ -1,5 +1,14 @@
|
|||
const UserError = require('vn-loopback/util/user-error');
|
||||
const {models} = require('vn-loopback/server/server');
|
||||
|
||||
const handlePromiseLogout = (Self, {id}, courtesyTime) => {
|
||||
jsegarra marked this conversation as resolved
Outdated
|
||||
new Promise(res => {
|
||||
jsegarra marked this conversation as resolved
Outdated
jgallego
commented
tras la conversación asumimos que courtesy estará en la tabla definido tras la conversación asumimos que courtesy estará en la tabla definido
|
||||
setTimeout(() => {
|
||||
res(Self.logout(id));
|
||||
}
|
||||
, courtesyTime * 1000);
|
||||
});
|
||||
};
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('renewToken', {
|
||||
description: 'Checks if the token has more than renewPeriod seconds to live and if so, renews it',
|
||||
|
@ -16,23 +25,32 @@ module.exports = Self => {
|
|||
});
|
||||
|
||||
Self.renewToken = async function(ctx) {
|
||||
const models = Self.app.models;
|
||||
const token = ctx.req.accessToken;
|
||||
const {accessToken: token} = ctx.req;
|
||||
|
||||
const now = new Date();
|
||||
const differenceMilliseconds = now - token.created;
|
||||
const differenceSeconds = Math.floor(differenceMilliseconds / 1000);
|
||||
// Check if current token is valid
|
||||
const isValid = await validateToken(token);
|
||||
if (isValid)
|
||||
jsegarra marked this conversation as resolved
Outdated
juan
commented
El método validateToken solo se llama desde aquí en toda la aplicación, puede eliminarse y poner su código directamente aquí. El método validateToken solo se llama desde aquí en toda la aplicación, puede eliminarse y poner su código directamente aquí.
jsegarra
commented
Era la idea, pero no la seguí porque había un remoteMethod de validateToken y asumí que si existía seria por algo y había que aprovecharlo. Consideras que deberíamos mover la lógica de ese método a este y eliminarlo? Era la idea, pero no la seguí porque había un remoteMethod de validateToken y asumí que si existía seria por algo y había que aprovecharlo.
Consideras que deberíamos mover la lógica de ese método a este y eliminarlo?
jgallego
commented
Si ves que sólo se llama desde aquí sí. Si ves que sólo se llama desde aquí sí.
|
||||
return token;
|
||||
|
||||
const fields = ['renewPeriod', 'courtesyTime'];
|
||||
const accessTokenConfig = await models.AccessTokenConfig.findOne({fields});
|
||||
const {courtesyTime} = await models.AccessTokenConfig.findOne({fields: ['courtesyTime']});
|
||||
jsegarra marked this conversation as resolved
Outdated
juan
commented
Para que se selecciona Para que se selecciona `renewPeriod` si luego no se utiliza?
jsegarra
commented
Oh, tienes razón la línea venia heredada de otro sitio Oh, tienes razón la línea venia heredada de otro sitio
|
||||
|
||||
if (differenceSeconds < accessTokenConfig.renewPeriod - accessTokenConfig.courtesyTime)
|
||||
throw new UserError(`The renew period has not been exceeded`, 'periodNotExceeded');
|
||||
// Schedule to remove current token
|
||||
handlePromiseLogout(Self, token, courtesyTime);
|
||||
|
||||
await Self.logout(token.id);
|
||||
// Create new accessToken
|
||||
const user = await Self.findById(token.userId);
|
||||
const accessToken = await user.createAccessToken();
|
||||
|
||||
return {id: accessToken.id, ttl: accessToken.ttl};
|
||||
};
|
||||
|
||||
async function validateToken(token) {
|
||||
const accessTokenConfig = await models.AccessTokenConfig.findOne({fields: ['renewPeriod', 'courtesyTime']});
|
||||
const now = Date.now();
|
||||
const differenceMilliseconds = now - token.created;
|
||||
const differenceSeconds = Math.floor(differenceMilliseconds / 1000);
|
||||
const isValid = differenceSeconds < accessTokenConfig.renewPeriod - accessTokenConfig.courtesyTime;
|
||||
|
||||
return isValid;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
const {models} = require('vn-loopback/server/server');
|
||||
describe('Renew Token', () => {
|
||||
const startingTime = Date.now();
|
||||
let ctx = null;
|
||||
beforeAll(async() => {
|
||||
const unAuthCtx = {
|
||||
req: {
|
||||
headers: {},
|
||||
connection: {
|
||||
remoteAddress: '127.0.0.1'
|
||||
},
|
||||
getLocale: () => 'en'
|
||||
},
|
||||
args: {}
|
||||
};
|
||||
let login = await models.VnUser.signIn(unAuthCtx, 'salesAssistant', 'nightmare');
|
||||
let accessToken = await models.AccessToken.findById(login.token);
|
||||
ctx = {req: {accessToken: accessToken}};
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
jasmine.clock().install();
|
||||
jasmine.clock().mockDate(new Date(startingTime));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jasmine.clock().uninstall();
|
||||
});
|
||||
|
||||
it('should renew process', async() => {
|
||||
jasmine.clock().mockDate(new Date(startingTime + 21600000));
|
||||
const {id} = await models.VnUser.renewToken(ctx);
|
||||
|
||||
expect(id).not.toEqual(ctx.req.accessToken.id);
|
||||
});
|
||||
|
||||
it('NOT should renew', async() => {
|
||||
let error;
|
||||
let response;
|
||||
try {
|
||||
response = await models.VnUser.renewToken(ctx);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
|
||||
expect(error).toBeUndefined();
|
||||
expect(response.id).toEqual(ctx.req.accessToken.id);
|
||||
});
|
||||
});
|
|
@ -1,17 +0,0 @@
|
|||
module.exports = Self => {
|
||||
Self.remoteMethod('validateToken', {
|
||||
description: 'Validates the current logged user token',
|
||||
returns: {
|
||||
type: 'Boolean',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/validateToken`,
|
||||
verb: 'GET'
|
||||
}
|
||||
});
|
||||
|
||||
Self.validateToken = async function() {
|
||||
return true;
|
||||
};
|
||||
};
|
|
@ -10,7 +10,6 @@ module.exports = function(Self) {
|
|||
require('../methods/vn-user/sign-in')(Self);
|
||||
require('../methods/vn-user/acl')(Self);
|
||||
require('../methods/vn-user/recover-password')(Self);
|
||||
require('../methods/vn-user/validate-token')(Self);
|
||||
require('../methods/vn-user/privileges')(Self);
|
||||
require('../methods/vn-user/validate-auth')(Self);
|
||||
require('../methods/vn-user/renew-token')(Self);
|
||||
|
|
|
@ -104,13 +104,6 @@
|
|||
"permission": "ALLOW"
|
||||
},
|
||||
{
|
||||
"property": "validateToken",
|
||||
"accessType": "EXECUTE",
|
||||
"principalType": "ROLE",
|
||||
"principalId": "$authenticated",
|
||||
"permission": "ALLOW"
|
||||
},
|
||||
{
|
||||
"property": "validateAuth",
|
||||
"accessType": "EXECUTE",
|
||||
"principalType": "ROLE",
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
-- Auto-generated SQL script #202311061003
|
||||
UPDATE salix.accessTokenConfig
|
||||
SET courtesyTime=60
|
||||
WHERE id=1;
|
|
@ -2967,9 +2967,9 @@ INSERT INTO `vn`.`wagonTypeTray` (`id`, `typeFk`, `height`, `colorFk`)
|
|||
(2, 1, 50, 2),
|
||||
(3, 1, 0, 3);
|
||||
|
||||
INSERT INTO `salix`.`accessTokenConfig` (`id`, `renewPeriod`, `renewInterval`)
|
||||
INSERT INTO `salix`.`accessTokenConfig` (`id`, `renewPeriod`, `courtesyTime`, `renewInterval`)
|
||||
VALUES
|
||||
(1, 21600, 300);
|
||||
(1, 21600, 60, 300);
|
||||
|
||||
INSERT INTO `vn`.`travelConfig` (`id`, `warehouseInFk`, `warehouseOutFk`, `agencyFk`, `companyFk`)
|
||||
VALUES
|
||||
|
|
|
@ -82,7 +82,7 @@ export default class Token {
|
|||
if (!data) return;
|
||||
this.renewPeriod = data.renewPeriod;
|
||||
this.stopRenewer();
|
||||
this.inservalId = setInterval(() => this.checkValidity(), data.renewInterval * 1000);
|
||||
this.intervalId = setInterval(() => this.checkValidity(), data.renewInterval * 1000);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -103,17 +103,13 @@ export default class Token {
|
|||
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);
|
||||
clearInterval(this.intervalId);
|
||||
}
|
||||
}
|
||||
Token.$inject = ['vnInterceptor', '$http', '$rootScope'];
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
module.exports = () => {
|
||||
Date.vnUTC = () => {
|
||||
const env = process.env.NODE_ENV;
|
||||
Date.vnUTC = (env = process.env.NODE_ENV) => {
|
||||
if (!env || env === 'development')
|
||||
return new Date(Date.UTC(2001, 0, 1, 11));
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
"./middleware/salix-version": {}
|
||||
},
|
||||
"parse": {
|
||||
"body-parser#json":{}
|
||||
"body-parser#json":{}
|
||||
},
|
||||
"routes": {
|
||||
"loopback#rest": {
|
||||
|
|
|
@ -2,7 +2,7 @@ const {models} = require('vn-loopback/server/server');
|
|||
|
||||
describe('account changePassword()', () => {
|
||||
const userId = 70;
|
||||
const unauthCtx = {
|
||||
const unAuthCtx = {
|
||||
req: {
|
||||
headers: {},
|
||||
connection: {
|
||||
|
@ -79,7 +79,7 @@ describe('account changePassword()', () => {
|
|||
passExpired: yesterday
|
||||
}
|
||||
, options);
|
||||
await models.VnUser.signIn(unauthCtx, 'trainee', 'nightmare', options);
|
||||
await models.VnUser.signIn(unAuthCtx, 'trainee', 'nightmare', options);
|
||||
} catch (e) {
|
||||
if (e.message != 'Pass expired')
|
||||
throw e;
|
||||
|
|
Loading…
Reference in New Issue
he visto el accessTokenConfig = 60 en las fixtures, no conviene quitarlo de aquí para no tener valores en el código?
Se utiliza como valor por defecto del parámetro courtesyTime de una línea más abajo.
Esto se hace, por si, se diese el caso que el valor en BD está a nulo.