Skip to content

Commit 60a808e

Browse files
authored
Merge pull request #399 from devforth/AdminForth/933
feat: add "adminUserAuthorize" hook
2 parents 07bb8f3 + bf4e311 commit 60a808e

File tree

2 files changed

+46
-2
lines changed

2 files changed

+46
-2
lines changed

adminforth/servers/express.ts

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ import path from 'path';
33
import fs from 'fs';
44
import { Express } from 'express';
55
import fetch from 'node-fetch';
6-
import { IAdminForth, IExpressHttpServer } from '../types/Back.js';
6+
import { AdminUserAuthorizeFunction, IAdminForth, IExpressHttpServer, HttpExtra } from '../types/Back.js';
77
import { WebSocketServer } from 'ws';
88
import { WebSocketClient } from './common.js';
99
import { AdminUser } from '../types/Common.js';
1010
import http from 'http';
1111
import { randomUUID } from 'crypto';
12+
import { listify } from '../modules/utils.js';
1213

1314
function replaceAtStart(string, substring) {
1415
if (string.startsWith(substring)) {
@@ -216,6 +217,25 @@ class ExpressServer implements IExpressHttpServer {
216217
this.server.listen(...args);
217218
}
218219

220+
async processAuthorizeCallbacks(adminUser: AdminUser, toReturn: { error?: string, allowed: boolean }, response: Response, extra: any) {
221+
const adminUserAuthorize = this.adminforth.config.auth.adminUserAuthorize as (AdminUserAuthorizeFunction[] | undefined);
222+
223+
for (const hook of listify(adminUserAuthorize)) {
224+
const resp = await hook({
225+
adminUser,
226+
response,
227+
adminforth: this.adminforth,
228+
extra,
229+
});
230+
if (resp?.allowed === false || resp?.error) {
231+
// delete all items from toReturn and add these:
232+
toReturn.allowed = resp?.allowed;
233+
toReturn.error = resp?.error;
234+
break;
235+
}
236+
}
237+
}
238+
219239

220240
authorize(handler) {
221241
return async (req, res, next) => {
@@ -248,7 +268,13 @@ class ExpressServer implements IExpressHttpServer {
248268
res.status(401).send('Unauthorized by AdminForth');
249269
} else {
250270
req.adminUser = adminforthUser;
251-
handler(req, res, next);
271+
const toReturn: { error?: string, allowed: boolean } = { allowed: true };
272+
await this.processAuthorizeCallbacks(adminforthUser, toReturn, res, {});
273+
if (!toReturn.allowed) {
274+
res.status(401).send('Unauthorized by AdminForth');
275+
} else {
276+
handler(req, res, next);
277+
}
252278
}
253279
};
254280
}

adminforth/types/Back.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,19 @@ export type BeforeLoginConfirmationFunction = (params?: {
611611
}
612612
}>;
613613

614+
/**
615+
* Allow to make extra authorization
616+
*/
617+
export type AdminUserAuthorizeFunction = ((params?: {
618+
adminUser: AdminUser,
619+
response: IAdminForthHttpResponse,
620+
adminforth: IAdminForth,
621+
extra?: HttpExtra,
622+
}) => Promise<{
623+
error?: string,
624+
allowed?: boolean,
625+
}>);
626+
614627

615628
/**
616629
* Data source describes database connection which will be used to fetch data for resources.
@@ -1009,6 +1022,11 @@ export interface AdminForthInputConfig {
10091022
*/
10101023
beforeLoginConfirmation?: BeforeLoginConfirmationFunction | Array<BeforeLoginConfirmationFunction>,
10111024

1025+
/**
1026+
* Array of functions which will be called before any request to AdminForth API.
1027+
*/
1028+
adminUserAuthorize?: AdminUserAuthorizeFunction | Array<AdminUserAuthorizeFunction>,
1029+
10121030
/**
10131031
* Optionally if your users table has a field(column) with full name, you can set it here.
10141032
* This field will be used to display user name in the top right corner of the admin panel.

0 commit comments

Comments
 (0)