Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 28 additions & 2 deletions adminforth/servers/express.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import path from 'path';
import fs from 'fs';
import { Express } from 'express';
import fetch from 'node-fetch';
import { IAdminForth, IExpressHttpServer } from '../types/Back.js';
import { AdminUserAuthorizeFunction, IAdminForth, IExpressHttpServer, HttpExtra } from '../types/Back.js';
import { WebSocketServer } from 'ws';
import { WebSocketClient } from './common.js';
import { AdminUser } from '../types/Common.js';
import http from 'http';
import { randomUUID } from 'crypto';
import { listify } from '../modules/utils.js';

function replaceAtStart(string, substring) {
if (string.startsWith(substring)) {
Expand Down Expand Up @@ -216,6 +217,25 @@ class ExpressServer implements IExpressHttpServer {
this.server.listen(...args);
}

async processAuthorizeCallbacks(adminUser: AdminUser, toReturn: { error?: string, allowed: boolean }, response: Response, extra: any) {
const adminUserAuthorize = this.adminforth.config.auth.adminUserAuthorize as (AdminUserAuthorizeFunction[] | undefined);

for (const hook of listify(adminUserAuthorize)) {
const resp = await hook({
adminUser,
response,
adminforth: this.adminforth,
extra,
});
if (resp?.allowed === false || resp?.error) {
// delete all items from toReturn and add these:
toReturn.allowed = resp?.allowed;
toReturn.error = resp?.error;
break;
}
}
}


authorize(handler) {
return async (req, res, next) => {
Expand Down Expand Up @@ -248,7 +268,13 @@ class ExpressServer implements IExpressHttpServer {
res.status(401).send('Unauthorized by AdminForth');
} else {
req.adminUser = adminforthUser;
handler(req, res, next);
const toReturn: { error?: string, allowed: boolean } = { allowed: true };
await this.processAuthorizeCallbacks(adminforthUser, toReturn, res, {});
if (!toReturn.allowed) {
res.status(401).send('Unauthorized by AdminForth');
} else {
handler(req, res, next);
}
}
};
}
Expand Down
18 changes: 18 additions & 0 deletions adminforth/types/Back.ts
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,19 @@ export type BeforeLoginConfirmationFunction = (params?: {
}
}>;

/**
* Allow to make extra authorization
*/
export type AdminUserAuthorizeFunction = ((params?: {
adminUser: AdminUser,
response: IAdminForthHttpResponse,
adminforth: IAdminForth,
extra?: HttpExtra,
}) => Promise<{
error?: string,
allowed?: boolean,
}>);


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

/**
* Array of functions which will be called before any request to AdminForth API.
*/
adminUserAuthorize?: AdminUserAuthorizeFunction | Array<AdminUserAuthorizeFunction>,

/**
* Optionally if your users table has a field(column) with full name, you can set it here.
* This field will be used to display user name in the top right corner of the admin panel.
Expand Down