1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-04-24 01:18:01 +02:00

feat: added IAuditUser to request with middleware (#6857)

Adds a middleware which adds our needed audit info as a separate object
to the request.
This commit is contained in:
Christopher Kolstad 2024-04-18 10:13:40 +02:00 committed by GitHub
parent 06f2f06f38
commit 633cae6f0d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 82 additions and 2 deletions

View File

@ -29,6 +29,7 @@ import { unless } from './middleware/unless-middleware';
import { catchAllErrorHandler } from './middleware/catch-all-error-handler'; import { catchAllErrorHandler } from './middleware/catch-all-error-handler';
import NotFoundError from './error/notfound-error'; import NotFoundError from './error/notfound-error';
import { bearerTokenMiddleware } from './middleware/bearer-token-middleware'; import { bearerTokenMiddleware } from './middleware/bearer-token-middleware';
import { auditAccessMiddleware } from './middleware';
export default async function getApp( export default async function getApp(
config: IUnleashConfig, config: IUnleashConfig,
@ -176,6 +177,7 @@ export default async function getApp(
rbacMiddleware(config, stores, services.accessService), rbacMiddleware(config, stores, services.accessService),
); );
app.use(`${baseUriPath}/api/admin`, auditAccessMiddleware(config));
app.use( app.use(
`${baseUriPath}/api/admin`, `${baseUriPath}/api/admin`,
maintenanceMiddleware(config, services.maintenanceService), maintenanceMiddleware(config, services.maintenanceService),

View File

@ -0,0 +1,42 @@
import { auditAccessMiddleware } from './audit-middleware';
import { createTestConfig } from '../../test/config/test-config';
import express from 'express';
import noAuthentication from './no-authentication';
import type { IAuthRequest } from '../routes/unleash-types';
import type { IAuditUser } from '../types';
import supertest from 'supertest';
const config = createTestConfig();
describe('auditMiddleware testing', () => {
test('Adds username and id from an IAuthRequest', async () => {
const middleware = auditAccessMiddleware(config);
const app = express();
noAuthentication('', app);
app.use('', middleware);
let audit: IAuditUser | undefined;
app.get('/api/admin/test', (req: IAuthRequest, res) => {
audit = req.audit;
res.status(200).end();
});
const request = supertest(app);
await request.get('/api/admin/test').expect(200);
expect(audit).toBeDefined();
expect(audit!.id).toBe(-1);
expect(audit!.username).toBe('unknown');
expect(audit!.ip).toBe('::ffff:127.0.0.1');
});
test('If no auth in place, does not add the audit object', async () => {
const middleware = auditAccessMiddleware(config);
const app = express();
app.use('', middleware);
let audit: IAuditUser | undefined;
app.get('/api/admin/test', (req: IAuthRequest, res) => {
audit = req.audit;
res.status(200).end();
});
const request = supertest(app);
await request.get('/api/admin/test').expect(200);
expect(audit).toBeUndefined();
});
});

View File

@ -0,0 +1,17 @@
import type { IUnleashConfig } from '../types';
import type { IApiRequest, IAuthRequest } from '../routes/unleash-types';
import { extractAuditInfo } from '../util';
export const auditAccessMiddleware = ({
getLogger,
}: Pick<IUnleashConfig, 'getLogger'>): any => {
const logger = getLogger('/middleware/audit-middleware.ts');
return (req: IAuthRequest | IApiRequest, _res, next) => {
if (!req.user) {
logger.info('Could not find user');
} else {
req.audit = extractAuditInfo(req);
}
next();
};
};

View File

@ -1,4 +1,5 @@
export * from './api-token-middleware'; export * from './api-token-middleware';
export * from './audit-middleware';
export * from './conditional-middleware'; export * from './conditional-middleware';
export * from './content_type_checker'; export * from './content_type_checker';
export * from './cors-origin-middleware'; export * from './cors-origin-middleware';

View File

@ -1,5 +1,5 @@
import type { Request } from 'express'; import type { Request } from 'express';
import type { IUser } from '../types/user'; import type { IAuditUser, IUser } from '../types/user';
import type { IApiUser } from '../types'; import type { IApiUser } from '../types';
export interface IAuthRequest< export interface IAuthRequest<
@ -11,6 +11,7 @@ export interface IAuthRequest<
user: IUser; user: IUser;
logout: (() => void) | ((callback: (err?: any) => void) => void); logout: (() => void) | ((callback: (err?: any) => void) => void);
session: any; session: any;
audit?: IAuditUser;
} }
export interface IApiRequest< export interface IApiRequest<
@ -22,6 +23,7 @@ export interface IApiRequest<
user: IApiUser; user: IApiUser;
logout: (() => void) | ((callback: (err?: any) => void) => void); logout: (() => void) | ((callback: (err?: any) => void) => void);
session: any; session: any;
audit?: IAuditUser;
} }
export interface RequestBody<T> extends Express.Request { export interface RequestBody<T> extends Express.Request {

View File

@ -22,7 +22,7 @@ import {
SYSTEM_USER, SYSTEM_USER,
} from './types'; } from './types';
import User, { type IUser } from './types/user'; import User, { type IAuditUser, type IUser } from './types/user';
import ApiUser, { type IApiUser } from './types/api-user'; import ApiUser, { type IApiUser } from './types/api-user';
import { type Logger, LogLevel } from './logger'; import { type Logger, LogLevel } from './logger';
import AuthenticationRequired from './types/authentication-required'; import AuthenticationRequired from './types/authentication-required';
@ -220,6 +220,7 @@ export type {
IUnleashConfig, IUnleashConfig,
IUser, IUser,
IApiUser, IApiUser,
IAuditUser,
IUnleashServices, IUnleashServices,
IAuthRequest, IAuthRequest,
IApiRequest, IApiRequest,

View File

@ -37,6 +37,12 @@ export interface IProjectUser extends IUser {
addedAt: Date; addedAt: Date;
} }
export interface IAuditUser {
id: number;
username: string;
ip?: string;
}
export default class User implements IUser { export default class User implements IUser {
isAPI: boolean = false; isAPI: boolean = false;

View File

@ -3,6 +3,7 @@ import type {
IApiRequest, IApiRequest,
IApiUser, IApiUser,
IAuthRequest, IAuthRequest,
IAuditUser,
IUser, IUser,
} from '../server-impl'; } from '../server-impl';
@ -26,3 +27,11 @@ export const extractUserInfo = (req: IAuthRequest | IApiRequest) => ({
id: extractUserId(req), id: extractUserId(req),
username: extractUsername(req), username: extractUsername(req),
}); });
export const extractAuditInfo = (
req: IAuthRequest | IApiRequest,
): IAuditUser => ({
id: extractUserId(req),
username: extractUsername(req),
ip: req.ip,
});