refactor: satisfy linter requirements

This commit is contained in:
Marcell Fülöp 2023-02-24 21:09:21 +00:00
parent baee4641db
commit 6f98fa61e4
7 changed files with 84 additions and 89 deletions

View File

@ -88,7 +88,7 @@ module.exports = {
* @param {String} [issuer] * @param {String} [issuer]
* @returns {Promise} * @returns {Promise}
*/ */
getTokenFromOAuthClaim: (data, issuer) => { getTokenFromOAuthClaim: (data) => {
let Token = new TokenModel(); let Token = new TokenModel();
data.scope = 'user'; data.scope = 'user';
@ -101,31 +101,26 @@ module.exports = {
.andWhere('is_disabled', 0) .andWhere('is_disabled', 0)
.first() .first()
.then((user) => { .then((user) => {
if (!user) { if (!user) {
throw new error.AuthError('No relevant user found'); throw new error.AuthError('No relevant user found');
}
// Create a moment of the expiry expression
let expiry = helpers.parseDatePeriod(data.expiry);
if (expiry === null) {
throw new error.AuthError('Invalid expiry time: ' + data.expiry);
}
let iss = 'api',
attrs = { id: user.id },
scope = [ data.scope ],
expiresIn = data.expiry;
return Token.create({ iss, attrs, scope, expiresIn })
.then((signed) => {
return {
token: signed.token,
expires: expiry.toISOString()
};
});
} }
);
// Create a moment of the expiry expression
let expiry = helpers.parseDatePeriod(data.expiry);
if (expiry === null) {
throw new error.AuthError('Invalid expiry time: ' + data.expiry);
}
let iss = 'api',
attrs = { id: user.id },
scope = [ data.scope ],
expiresIn = data.expiry;
return Token.create({ iss, attrs, scope, expiresIn })
.then((signed) => {
return { token: signed.token, expires: expiry.toISOString() };
});
});
}, },
/** /**

View File

@ -27,7 +27,7 @@ router.get('/', (req, res/*, next*/) => {
router.use('/schema', require('./schema')); router.use('/schema', require('./schema'));
router.use('/tokens', require('./tokens')); router.use('/tokens', require('./tokens'));
router.use('/oidc', require('./oidc')) router.use('/oidc', require('./oidc'));
router.use('/users', require('./users')); router.use('/users', require('./users'));
router.use('/audit-log', require('./audit-log')); router.use('/audit-log', require('./audit-log'));
router.use('/reports', require('./reports')); router.use('/reports', require('./reports'));

View File

@ -3,7 +3,7 @@ const error = require('../../lib/error');
const express = require('express'); const express = require('express');
const jwtdecode = require('../../lib/express/jwt-decode'); const jwtdecode = require('../../lib/express/jwt-decode');
const oidc = require('openid-client'); const oidc = require('openid-client');
const settingModel = require('../../models/setting'); const settingModel = require('../../models/setting');
const internalToken = require('../../internal/token'); const internalToken = require('../../internal/token');
let router = express.Router({ let router = express.Router({
@ -29,15 +29,15 @@ router
* *
* Retrieve all users * Retrieve all users
*/ */
.get(jwtdecode(), async (req, res, next) => { .get(jwtdecode(), async (req, res) => {
console.log("oidc: init flow"); console.log('oidc: init flow');
settingModel settingModel
.query() .query()
.where({id: 'oidc-config'}) .where({id: 'oidc-config'})
.first() .first()
.then( row => getInitParams(req, row)) .then((row) => getInitParams(req, row))
.then( params => redirectToAuthorizationURL(res, params)) .then((params) => redirectToAuthorizationURL(res, params))
.catch( err => redirectWithError(res, err)); .catch((err) => redirectWithError(res, err));
}); });
@ -58,15 +58,15 @@ router
* *
* Retrieve a specific user * Retrieve a specific user
*/ */
.get(jwtdecode(), async (req, res, next) => { .get(jwtdecode(), async (req, res) => {
console.log("oidc: callback"); console.log('oidc: callback');
settingModel settingModel
.query() .query()
.where({id: 'oidc-config'}) .where({id: 'oidc-config'})
.first() .first()
.then( settings => validateCallback(req, settings)) .then((settings) => validateCallback(req, settings))
.then( token => redirectWithJwtToken(res, token)) .then((token) => redirectWithJwtToken(res, token))
.catch( err => redirectWithError(res, err)); .catch((err) => redirectWithError(res, err));
}); });
/** /**
@ -74,21 +74,21 @@ router
* *
* @param {Setting} row * @param {Setting} row
* */ * */
let getClient = async row => { let getClient = async (row) => {
let issuer; let issuer;
try { try {
issuer = await oidc.Issuer.discover(row.meta.issuerURL); issuer = await oidc.Issuer.discover(row.meta.issuerURL);
} catch(err) { } catch (err) {
throw new error.AuthError(`Discovery failed for the specified URL with message: ${err.message}`); throw new error.AuthError(`Discovery failed for the specified URL with message: ${err.message}`);
} }
return new issuer.Client({ return new issuer.Client({
client_id: row.meta.clientID, client_id: row.meta.clientID,
client_secret: row.meta.clientSecret, client_secret: row.meta.clientSecret,
redirect_uris: [row.meta.redirectURL], redirect_uris: [row.meta.redirectURL],
response_types: ['code'], response_types: ['code'],
}); });
} };
/** /**
* Generates state, nonce and authorization url. * Generates state, nonce and authorization url.
@ -98,18 +98,18 @@ let getClient = async row => {
* @return { {String}, {String}, {String} } state, nonce and url * @return { {String}, {String}, {String} } state, nonce and url
* */ * */
let getInitParams = async (req, row) => { let getInitParams = async (req, row) => {
let client = await getClient(row); let client = await getClient(row),
let state = crypto.randomUUID(); state = crypto.randomUUID(),
let nonce = crypto.randomUUID(); nonce = crypto.randomUUID(),
let url = client.authorizationUrl({ url = client.authorizationUrl({
scope: 'openid email profile', scope: 'openid email profile',
resource: `${req.protocol}://${req.get('host')}${req.originalUrl}`, resource: `${req.protocol}://${req.get('host')}${req.originalUrl}`,
state, state,
nonce, nonce,
}) });
return { state, nonce, url }; return { state, nonce, url };
} };
/** /**
* Parses state and nonce from cookie during the callback phase. * Parses state and nonce from cookie during the callback phase.
@ -117,21 +117,21 @@ let getInitParams = async (req, row) => {
* @param {Request} req * @param {Request} req
* @return { {String}, {String} } state and nonce * @return { {String}, {String} } state and nonce
* */ * */
let parseStateFromCookie = req => { let parseStateFromCookie = (req) => {
let state, nonce; let state, nonce;
let cookies = req.headers.cookie.split(';'); let cookies = req.headers.cookie.split(';');
for (cookie of cookies) { for (let cookie of cookies) {
if (cookie.split('=')[0].trim() === 'npm_oidc') { if (cookie.split('=')[0].trim() === 'npm_oidc') {
let raw = cookie.split('=')[1]; let raw = cookie.split('=')[1],
let val = raw.split('--'); val = raw.split('--');
state = val[0].trim(); state = val[0].trim();
nonce = val[1].trim(); nonce = val[1].trim();
break; break;
} }
} }
return { state, nonce }; return { state, nonce };
} };
/** /**
* Executes validation of callback parameters. * Executes validation of callback parameters.
@ -140,33 +140,33 @@ let parseStateFromCookie = req => {
* @param {Setting} settings * @param {Setting} settings
* @return {Promise} a promise resolving to a jwt token * @return {Promise} a promise resolving to a jwt token
* */ * */
let validateCallback = async (req, settings) => { let validateCallback = async (req, settings) => {
let client = await getClient(settings); let client = await getClient(settings);
let { state, nonce } = parseStateFromCookie(req); let { state, nonce } = parseStateFromCookie(req);
const params = client.callbackParams(req); const params = client.callbackParams(req);
const tokenSet = await client.callback(settings.meta.redirectURL, params, { state, nonce }); const tokenSet = await client.callback(settings.meta.redirectURL, params, { state, nonce });
let claims = tokenSet.claims(); let claims = tokenSet.claims();
console.log('oidc: authentication successful for email', claims.email); console.log('oidc: authentication successful for email', claims.email);
return internalToken.getTokenFromOAuthClaim({ identity: claims.email }) return internalToken.getTokenFromOAuthClaim({ identity: claims.email });
} };
let redirectToAuthorizationURL = (res, params) => { let redirectToAuthorizationURL = (res, params) => {
console.log('oidc: init flow > url > ', params.url); console.log('oidc: init flow > url > ', params.url);
res.cookie("npm_oidc", params.state + '--' + params.nonce); res.cookie('npm_oidc', params.state + '--' + params.nonce);
res.redirect(params.url); res.redirect(params.url);
} };
let redirectWithJwtToken = (res, token) => { let redirectWithJwtToken = (res, token) => {
res.cookie('npm_oidc', token.token + '---' + token.expires); res.cookie('npm_oidc', token.token + '---' + token.expires);
res.redirect('/login'); res.redirect('/login');
} };
let redirectWithError = (res, error) => { let redirectWithError = (res, error) => {
console.log('oidc: callback error: ', error); console.log('oidc: callback error: ', error);
res.cookie('npm_oidc_error', error.message); res.cookie('npm_oidc_error', error.message);
res.redirect('/login'); res.redirect('/login');
} };
module.exports = router; module.exports = router;

View File

@ -71,14 +71,14 @@ router
.then((row) => { .then((row) => {
if (row.id === 'oidc-config') { if (row.id === 'oidc-config') {
// redact oidc configuration via api // redact oidc configuration via api
let m = row.meta let m = row.meta;
row.meta = { row.meta = {
name: m.name, name: m.name,
enabled: m.enabled === true && !!(m.clientID && m.clientSecret && m.issuerURL && m.redirectURL && m.name) enabled: m.enabled === true && !!(m.clientID && m.clientSecret && m.issuerURL && m.redirectURL && m.name)
}; };
// remove these temporary cookies used during oidc authentication // remove these temporary cookies used during oidc authentication
res.clearCookie('npm_oidc') res.clearCookie('npm_oidc');
res.clearCookie('npm_oidc_error') res.clearCookie('npm_oidc_error');
} }
res.status(200) res.status(200)
.send(row); .send(row);

View File

@ -60,7 +60,7 @@ function fetch(verb, path, data, options) {
beforeSend: function (xhr) { beforeSend: function (xhr) {
// allow unauthenticated access to OIDC configuration // allow unauthenticated access to OIDC configuration
if (path === "settings/oidc-config") return; if (path === 'settings/oidc-config') return;
xhr.setRequestHeader('Authorization', 'Bearer ' + (token ? token.t : null)); xhr.setRequestHeader('Authorization', 'Bearer ' + (token ? token.t : null));
}, },

View File

@ -9,10 +9,10 @@ module.exports = Mn.View.extend({
className: 'modal-dialog wide', className: 'modal-dialog wide',
ui: { ui: {
form: 'form', form: 'form',
buttons: '.modal-footer button', buttons: '.modal-footer button',
cancel: 'button.cancel', cancel: 'button.cancel',
save: 'button.save', save: 'button.save',
}, },
events: { events: {
@ -28,16 +28,16 @@ module.exports = Mn.View.extend({
let data = this.ui.form.serializeJSON(); let data = this.ui.form.serializeJSON();
data.id = this.model.get('id'); data.id = this.model.get('id');
if (data.meta.enabled) { if (data.meta.enabled) {
data.meta.enabled = data.meta.enabled === "on" || data.meta.enabled === "true"; data.meta.enabled = data.meta.enabled === 'on' || data.meta.enabled === 'true';
} }
this.ui.buttons.prop('disabled', true).addClass('btn-disabled'); this.ui.buttons.prop('disabled', true).addClass('btn-disabled');
App.Api.Settings.update(data) App.Api.Settings.update(data)
.then(result => { .then((result) => {
view.model.set(result); view.model.set(result);
App.UI.closeModal(); App.UI.closeModal();
}) })
.catch(err => { .catch((err) => {
alert(err.message); alert(err.message);
this.ui.buttons.prop('disabled', false).removeClass('btn-disabled'); this.ui.buttons.prop('disabled', false).removeClass('btn-disabled');
}); });

View File

@ -31,12 +31,12 @@ module.exports = Mn.View.extend({
.then(() => { .then(() => {
window.location = '/'; window.location = '/';
}) })
.catch(err => { .catch((err) => {
this.ui.error.text(err.message).show(); this.ui.error.text(err.message).show();
this.ui.button.removeClass('btn-loading').prop('disabled', false); this.ui.button.removeClass('btn-loading').prop('disabled', false);
}); });
}, },
'click @ui.oidcButton': function(e) { 'click @ui.oidcButton': function() {
this.ui.identity.prop('disabled', true); this.ui.identity.prop('disabled', true);
this.ui.secret.prop('disabled', true); this.ui.secret.prop('disabled', true);
this.ui.button.prop('disabled', true); this.ui.button.prop('disabled', true);
@ -51,12 +51,12 @@ module.exports = Mn.View.extend({
let cookies = document.cookie.split(';'), let cookies = document.cookie.split(';'),
token, expiry, error; token, expiry, error;
for (cookie of cookies) { for (cookie of cookies) {
let raw = cookie.split('='), let raw = cookie.split('='),
name = raw[0].trim(), name = raw[0].trim(),
value = raw[1]; value = raw[1];
if (name === 'npm_oidc') { if (name === 'npm_oidc') {
let v = value.split('---'); let v = value.split('---');
token = v[0]; token = v[0];
expiry = v[1]; expiry = v[1];
} }
if (name === 'npm_oidc_error') { if (name === 'npm_oidc_error') {
@ -80,7 +80,7 @@ module.exports = Mn.View.extend({
} }
// fetch oidc configuration and show alternative action button if enabled // fetch oidc configuration and show alternative action button if enabled
let response = await Api.Settings.getById("oidc-config"); let response = await Api.Settings.getById('oidc-config');
if (response && response.meta && response.meta.enabled === true) { if (response && response.meta && response.meta.enabled === true) {
this.ui.oidcProvider.html(response.meta.name); this.ui.oidcProvider.html(response.meta.name);
this.ui.oidcLogin.show(); this.ui.oidcLogin.show();