* feat: add type to privilege maps

deprecate old hooks that are used for adding new privileges, new hooks are static:privileges.global.init/static:privileges.categories.init

* deprecate admin priv hooks

* fix: if type doesnt exist default to 'other'

* remove filter

* fix: copy privilege functions to use new filter instead of indices

allow static hooks to use sync functions

* fix: openapi

* test: fix template helper
This commit is contained in:
Barış Soner Uşaklı
2023-09-25 20:42:18 -04:00
committed by GitHub
parent c1f873b302
commit f1a80d48cc
15 changed files with 607 additions and 402 deletions

View File

@@ -1,6 +1,5 @@
'use strict';
const util = require('util');
const winston = require('winston');
const plugins = require('.');
const utils = require('../utils');
@@ -38,6 +37,67 @@ Hooks._deprecated = new Map([
since: 'v2.7.0',
until: 'v3.0.0',
}],
['filter:privileges.global.list', {
new: 'static:privileges.global.init',
since: 'v3.5.0',
until: 'v4.0.0',
}],
['filter:privileges.global.groups.list', {
new: 'static:privileges.global.init',
since: 'v3.5.0',
until: 'v4.0.0',
}],
['filter:privileges.global.list_human', {
new: 'static:privileges.global.init',
since: 'v3.5.0',
until: 'v4.0.0',
}],
['filter:privileges.global.groups.list_human', {
new: 'static:privileges.global.init',
since: 'v3.5.0',
until: 'v4.0.0',
}],
['filter:privileges.list', {
new: 'static:privileges.categories.init',
since: 'v3.5.0',
until: 'v4.0.0',
}],
['filter:privileges.groups.list', {
new: 'static:privileges.categories.init',
since: 'v3.5.0',
until: 'v4.0.0',
}],
['filter:privileges.list_human', {
new: 'static:privileges.categories.init',
since: 'v3.5.0',
until: 'v4.0.0',
}],
['filter:privileges.groups.list_human', {
new: 'static:privileges.categories.init',
since: 'v3.5.0',
until: 'v4.0.0',
}],
['filter:privileges.admin.list', {
new: 'static:privileges.admin.init',
since: 'v3.5.0',
until: 'v4.0.0',
}],
['filter:privileges.admin.groups.list', {
new: 'static:privileges.admin.init',
since: 'v3.5.0',
until: 'v4.0.0',
}],
['filter:privileges.admin.list_human', {
new: 'static:privileges.admin.init',
since: 'v3.5.0',
until: 'v4.0.0',
}],
['filter:privileges.admin.groups.list_human', {
new: 'static:privileges.admin.init',
since: 'v3.5.0',
until: 'v4.0.0',
}],
]);
Hooks.internals = {
@@ -213,41 +273,6 @@ async function fireActionHook(hook, hookList, params) {
}
}
async function fireStaticHook(hook, hookList, params) {
if (!Array.isArray(hookList) || !hookList.length) {
return;
}
// don't bubble errors from these hooks, so bad plugins don't stop startup
const noErrorHooks = ['static:app.load', 'static:assets.prepare', 'static:app.preload'];
for (const hookObj of hookList) {
if (typeof hookObj.method !== 'function') {
if (global.env === 'development') {
winston.warn(`[plugins] Expected method for hook '${hook}' in plugin '${hookObj.id}' not found, skipping.`);
}
} else {
let hookFn = hookObj.method;
if (hookFn.constructor && hookFn.constructor.name !== 'AsyncFunction') {
hookFn = util.promisify(hookFn);
}
try {
// eslint-disable-next-line
await timeout(hookFn(params), 10000, 'timeout');
} catch (err) {
if (err && err.message === 'timeout') {
winston.warn(`[plugins] Callback timed out, hook '${hook}' in plugin '${hookObj.id}'`);
} else {
winston.error(`[plugins] Error executing '${hook}' in plugin '${hookObj.id}'\n${err.stack}`);
if (!noErrorHooks.includes(hook)) {
throw err;
}
}
}
}
}
}
// https://advancedweb.hu/how-to-add-timeout-to-a-promise-in-javascript/
const timeout = (prom, time, error) => {
let timer;
@@ -259,6 +284,66 @@ const timeout = (prom, time, error) => {
]).finally(() => clearTimeout(timer));
};
async function fireStaticHook(hook, hookList, params) {
if (!Array.isArray(hookList) || !hookList.length) {
return;
}
// don't bubble errors from these hooks, so bad plugins don't stop startup
const noErrorHooks = ['static:app.load', 'static:assets.prepare', 'static:app.preload'];
async function fireMethod(hookObj, params) {
if (typeof hookObj.method !== 'function') {
if (global.env === 'development') {
winston.warn(`[plugins] Expected method for hook '${hook}' in plugin '${hookObj.id}' not found, skipping.`);
}
return params;
}
if (hookObj.method.constructor && hookObj.method.constructor.name === 'AsyncFunction') {
return timeout(hookObj.method(params), 10000, 'timeout');
}
return new Promise((resolve, reject) => {
let resolved = false;
function _resolve(result) {
if (resolved) {
return;
}
resolved = true;
resolve(result);
}
const returned = hookObj.method(params, (err, result) => {
if (err) reject(err); else _resolve(result);
});
if (utils.isPromise(returned)) {
returned.then(
payload => _resolve(payload),
err => reject(err)
);
return;
}
_resolve();
});
}
for (const hookObj of hookList) {
try {
// eslint-disable-next-line
await fireMethod(hookObj, params);
} catch (err) {
if (err && err.message === 'timeout') {
winston.warn(`[plugins] Callback timed out, hook '${hook}' in plugin '${hookObj.id}'`);
} else {
winston.error(`[plugins] Error executing '${hook}' in plugin '${hookObj.id}'\n${err.stack}`);
if (!noErrorHooks.includes(hook)) {
throw err;
}
}
}
}
}
async function fireResponseHook(hook, hookList, params) {
if (!Array.isArray(hookList) || !hookList.length) {
return;