const {models} = require('vn-loopback/server/server'); module.exports = Self => { Self.remoteMethodCtx('renewToken', { description: 'Checks if the token has more than renewPeriod seconds to live and if so, renews it', accessType: 'WRITE', accepts: [], returns: { type: 'Object', root: true }, http: { path: `/renewToken`, verb: 'POST' }, accessScopes: ['DEFAULT', 'read:multimedia']}); Self.renewToken = async function(ctx) { let createTokenOptions = {}; let token; let isNotExceeded; try { token = ctx.req.accessToken; const {courtesyTime} = await models.AccessTokenConfig.findOne({ fields: ['courtesyTime'] }); isNotExceeded = await Self.validateToken(ctx); if (isNotExceeded) return token; // Schedule to remove current token setTimeout(async() => { try { await Self.logout(token.id); } catch (error) { // FIXME: Crash if do throw new Error(error) } }, courtesyTime * 1000); // Get scopes const {scopes} = token; if (scopes) createTokenOptions = {scopes: [scopes[0]]}; // Create new accessToken const user = await Self.findById(token.userId); const accessToken = await user.accessTokens.create(createTokenOptions); return {id: accessToken.id, ttl: accessToken.ttl}; } catch (error) { const body = { error: error.message, userId: token?.userId ?? null, token: token?.id, scopes: token?.scopes, createTokenOptions, isNotExceeded }; await handleError(JSON.stringify(body)); throw new Error(error); } }; }; async function handleError(body) { await models.Application.rawSql('CALL util.debugAdd(?,?);', ['renewToken', body]); }