mirror of
https://github.com/logto-io/logto.git
synced 2025-03-24 22:41:28 -05:00
refactor: update comments and fix tests
This commit is contained in:
parent
981ca84b9b
commit
93f4ae10ec
18 changed files with 120 additions and 61 deletions
|
@ -21,6 +21,15 @@ export class LogEntry {
|
|||
};
|
||||
}
|
||||
|
||||
/** Update payload by spreading `data` first, then spreading `this.payload`. */
|
||||
prepend(data: Readonly<LogPayload>) {
|
||||
this.payload = {
|
||||
...removeUndefinedKeys(data),
|
||||
...this.payload,
|
||||
};
|
||||
}
|
||||
|
||||
/** Update payload by spreading `this.payload` first, then spreading `data`. */
|
||||
append(data: Readonly<LogPayload>) {
|
||||
this.payload = {
|
||||
...this.payload,
|
||||
|
@ -33,6 +42,7 @@ export type LogPayload = Partial<LogContextPayload> & Record<string, unknown>;
|
|||
|
||||
export type LogContext = {
|
||||
createLog: (key: LogKey) => LogEntry;
|
||||
prependAllLogEntries: (payload: LogPayload) => void;
|
||||
};
|
||||
|
||||
export type WithLogContext<ContextT extends IRouterParamContext = IRouterParamContext> = ContextT &
|
||||
|
@ -40,46 +50,54 @@ export type WithLogContext<ContextT extends IRouterParamContext = IRouterParamCo
|
|||
|
||||
/**
|
||||
* The factory to create a new audit log middleware function.
|
||||
* It will inject a {@link LogFunction} property named `log` to the context to enable audit logging.
|
||||
* It will inject a `createLog` function the context to enable audit logging.
|
||||
*
|
||||
* #### Set log key
|
||||
* #### Create a log entry
|
||||
*
|
||||
* You need to explicitly call `ctx.log.setKey()` to set a {@link LogKey} thus the log can be categorized and indexed in database:
|
||||
* You need to explicitly call `ctx.createLog()` to create a new {@link LogEntry} instance,
|
||||
* which accepts a read-only parameter {@link LogKey} thus the log can be categorized and indexed in database.
|
||||
*
|
||||
* ```ts
|
||||
* ctx.log.setKey('SignIn.Submit'); // Key is typed
|
||||
* const log = ctx.createLog('Interaction.Create'); // Key is typed
|
||||
* ```
|
||||
*
|
||||
* If log key is {@link LogKeyUnknown} in the end, it will not be recorded to the persist storage.
|
||||
* Note every time you call `ctx.createLog()`, it will create a new log entry instance for inserting. So multiple log entries may be inserted within one request.
|
||||
*
|
||||
* Remember to keep the log entry instance properly if you want to collect log data from multiple places.
|
||||
*
|
||||
* #### Log data
|
||||
*
|
||||
* To log data, call `ctx.log()`. It'll use object spread operators to update data (i.e. merge with one-level overwrite and shallow copy).
|
||||
* To update log payload, call `log.append()`. It will use object spread operators to update payload (i.e. merge with one-level overwrite and shallow copy).
|
||||
*
|
||||
* ```ts
|
||||
* ctx.log({ applicationId: 'foo' });
|
||||
* log.append({ applicationId: 'foo' });
|
||||
* ```
|
||||
*
|
||||
* The data has a initial value:
|
||||
* This function can be called multiple times.
|
||||
*
|
||||
* #### Log context
|
||||
*
|
||||
* By default, before inserting the logs, it will extract the request context and prepend request IP and User Agent to every log entry:
|
||||
*
|
||||
* ```ts
|
||||
* {
|
||||
* key: LogKeyUnknown,
|
||||
* result: LogResult.Success,
|
||||
* ip, // Extract from request
|
||||
* userAgent, // Extract from request
|
||||
* ip: 'request-ip-addr',
|
||||
* userAgent: 'request-user-agent',
|
||||
* ...log.payload,
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Note: Both of the functions can be called multiple times.
|
||||
* To add more common data to log entries, try to create another middleware function after this one, and call `ctx.prependAllLogEntries()`.
|
||||
*
|
||||
* @returns An audit log middleware function.
|
||||
* @see {@link LogKey} for all available log keys, and {@link LogResult} for result enums.
|
||||
* @see {@link LogContextPayload} for the basic type suggestion of log data.
|
||||
* @returns An audit log middleware function.
|
||||
*/
|
||||
export default function koaAuditLog<StateT, ContextT extends IRouterParamContext, ResponseBodyT>(
|
||||
dumpLogContext?: (ctx: ContextT) => Promise<Record<string, unknown>> | Record<string, unknown>
|
||||
): MiddlewareType<StateT, WithLogContext<ContextT>, ResponseBodyT> {
|
||||
export default function koaAuditLog<
|
||||
StateT,
|
||||
ContextT extends IRouterParamContext,
|
||||
ResponseBodyT
|
||||
>(): MiddlewareType<StateT, WithLogContext<ContextT>, ResponseBodyT> {
|
||||
return async (ctx, next) => {
|
||||
const entries: LogEntry[] = [];
|
||||
|
||||
|
@ -91,6 +109,12 @@ export default function koaAuditLog<StateT, ContextT extends IRouterParamContext
|
|||
return entry;
|
||||
};
|
||||
|
||||
ctx.prependAllLogEntries = (payload) => {
|
||||
for (const entry of entries) {
|
||||
entry.prepend(payload);
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
await next();
|
||||
} catch (error: unknown) {
|
||||
|
@ -111,13 +135,12 @@ export default function koaAuditLog<StateT, ContextT extends IRouterParamContext
|
|||
headers: { 'user-agent': userAgent },
|
||||
} = ctx.request;
|
||||
|
||||
const logContext = { ip, userAgent, ...(await dumpLogContext?.(ctx)) };
|
||||
await Promise.all(
|
||||
entries.map(async ({ payload }) => {
|
||||
return insertLog({
|
||||
id: nanoid(),
|
||||
type: payload.key,
|
||||
payload: { ...logContext, ...payload },
|
||||
payload: { ip, userAgent, ...payload },
|
||||
});
|
||||
})
|
||||
);
|
||||
|
|
|
@ -12,6 +12,7 @@ import snakecaseKeys from 'snakecase-keys';
|
|||
|
||||
import envSet from '#src/env-set/index.js';
|
||||
import { addOidcEventListeners } from '#src/event-listeners/index.js';
|
||||
import koaAuditLog from '#src/middleware/koa-audit-log.js';
|
||||
import postgresAdapter from '#src/oidc/adapter.js';
|
||||
import { isOriginAllowed, validateCustomClientMetadata } from '#src/oidc/utils.js';
|
||||
import { findApplicationById } from '#src/queries/application.js';
|
||||
|
@ -188,6 +189,9 @@ export default async function initOidc(app: Koa): Promise<Provider> {
|
|||
|
||||
addOidcEventListeners(oidc);
|
||||
|
||||
// Provide audit log context for event listeners
|
||||
oidc.use(koaAuditLog());
|
||||
|
||||
app.use(mount('/oidc', oidc.app));
|
||||
|
||||
return oidc;
|
||||
|
|
|
@ -4,9 +4,7 @@ import mount from 'koa-mount';
|
|||
import Router from 'koa-router';
|
||||
import type { Provider } from 'oidc-provider';
|
||||
|
||||
import { extractInteractionContext } from '#src/event-listeners/utils.js';
|
||||
import koaAuditLogLegacy from '#src/middleware/koa-audit-log-legacy.js';
|
||||
import koaAuditLog from '#src/middleware/koa-audit-log.js';
|
||||
|
||||
import koaAuth from '../middleware/koa-auth.js';
|
||||
import koaLogSessionLegacy from '../middleware/koa-log-session-legacy.js';
|
||||
|
@ -36,7 +34,6 @@ const createRouters = (provider: Provider) => {
|
|||
sessionRoutes(sessionRouter, provider);
|
||||
|
||||
const interactionRouter: AnonymousRouter = new Router();
|
||||
interactionRouter.use(koaAuditLog(extractInteractionContext));
|
||||
interactionRoutes(interactionRouter, provider);
|
||||
|
||||
const managementRouter: AuthedRouter = new Router();
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { Event } from '@logto/schemas';
|
||||
import { mockEsm, pickDefault } from '@logto/shared/esm';
|
||||
|
||||
import { createMockLogContext } from '#src/test-utils/koa-log.js';
|
||||
import { createMockProvider } from '#src/test-utils/oidc-provider.js';
|
||||
import { createContextWithRouteParameters } from '#src/utils/test-utils.js';
|
||||
|
||||
|
@ -51,10 +52,9 @@ jest.useFakeTimers().setSystemTime(now);
|
|||
|
||||
describe('submit action', () => {
|
||||
const provider = createMockProvider();
|
||||
const log = jest.fn();
|
||||
const ctx: InteractionContext = {
|
||||
...createContextWithRouteParameters(),
|
||||
log,
|
||||
...createMockLogContext(),
|
||||
interactionPayload: { event: Event.SignIn },
|
||||
};
|
||||
const profile = {
|
||||
|
|
|
@ -5,6 +5,8 @@ import { mockEsm, mockEsmDefault, mockEsmWithActual, pickDefault } from '@logto/
|
|||
|
||||
import { mockSignInExperience } from '#src/__mocks__/sign-in-experience.js';
|
||||
import RequestError from '#src/errors/RequestError/index.js';
|
||||
import type koaAuditLog from '#src/middleware/koa-audit-log.js';
|
||||
import { createMockLogContext } from '#src/test-utils/koa-log.js';
|
||||
import { createMockProvider } from '#src/test-utils/oidc-provider.js';
|
||||
import { createRequester } from '#src/utils/test-utils.js';
|
||||
|
||||
|
@ -76,7 +78,17 @@ const { getInteractionStorage } = mockEsm('./utils/interaction.js', () => ({
|
|||
getInteractionStorage: jest.fn(),
|
||||
}));
|
||||
|
||||
const log = jest.fn();
|
||||
const { createLog, prependAllLogEntries } = createMockLogContext();
|
||||
mockEsmDefault(
|
||||
'#src/middleware/koa-audit-log.js',
|
||||
// eslint-disable-next-line unicorn/consistent-function-scoping
|
||||
(): typeof koaAuditLog => () => async (ctx, next) => {
|
||||
ctx.createLog = createLog;
|
||||
ctx.prependAllLogEntries = prependAllLogEntries;
|
||||
|
||||
return next();
|
||||
}
|
||||
);
|
||||
|
||||
const koaInteractionBodyGuard = await pickDefault(
|
||||
import('./middleware/koa-interaction-body-guard.js')
|
||||
|
@ -107,14 +119,6 @@ describe('session -> interactionRoutes', () => {
|
|||
provider: createMockProvider(
|
||||
jest.fn().mockResolvedValue({ params: {}, jti: 'jti', client_id: demoAppApplicationId })
|
||||
),
|
||||
middlewares: [
|
||||
async (ctx, next) => {
|
||||
ctx.addLogContext = jest.fn();
|
||||
ctx.log = log;
|
||||
|
||||
return next();
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
@ -244,7 +248,7 @@ describe('session -> interactionRoutes', () => {
|
|||
};
|
||||
|
||||
const response = await sessionRequest.post(path).send(body);
|
||||
expect(sendPasscodeToIdentifier).toBeCalledWith(body, 'jti', log);
|
||||
expect(sendPasscodeToIdentifier).toBeCalledWith(body, 'jti', createLog);
|
||||
expect(response.status).toEqual(204);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import type { LogtoErrorCode } from '@logto/phrases';
|
||||
import { Event } from '@logto/schemas';
|
||||
import { conditional } from '@silverhand/essentials';
|
||||
import type { Provider } from 'oidc-provider';
|
||||
|
||||
import RequestError from '#src/errors/RequestError/index.js';
|
||||
import { assignInteractionResults } from '#src/libraries/session.js';
|
||||
import koaAuditLog from '#src/middleware/koa-audit-log.js';
|
||||
import koaGuard from '#src/middleware/koa-guard.js';
|
||||
import assertThat from '#src/utils/assert-that.js';
|
||||
|
||||
|
@ -28,6 +30,24 @@ export default function interactionRoutes<T extends AnonymousRouter>(
|
|||
router: T,
|
||||
provider: Provider
|
||||
) {
|
||||
router.use(koaAuditLog(), async (ctx, next) => {
|
||||
await next();
|
||||
|
||||
// Prepend interaction context to log entries
|
||||
try {
|
||||
const {
|
||||
jti,
|
||||
params: { client_id },
|
||||
} = await provider.interactionDetails(ctx.req, ctx.res);
|
||||
ctx.prependAllLogEntries({
|
||||
sessionId: jti,
|
||||
applicationId: conditional(typeof client_id === 'string' && client_id),
|
||||
});
|
||||
} catch (error: unknown) {
|
||||
console.error(`Failed to get oidc provider interaction details`, error);
|
||||
}
|
||||
});
|
||||
|
||||
router.put(
|
||||
interactionPrefix,
|
||||
koaInteractionBodyGuard(),
|
||||
|
@ -117,7 +137,7 @@ export default function interactionRoutes<T extends AnonymousRouter>(
|
|||
async (ctx, next) => {
|
||||
// Check interaction session
|
||||
const { jti } = await provider.interactionDetails(ctx.req, ctx.res);
|
||||
await sendPasscodeToIdentifier(ctx.guard.body, jti, ctx.log);
|
||||
await sendPasscodeToIdentifier(ctx.guard.body, jti, ctx.createLog);
|
||||
|
||||
ctx.status = 204;
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import type { IRouterParamContext } from 'koa-router';
|
|||
import type { z } from 'zod';
|
||||
|
||||
import type { SocialUserInfo } from '#src/connectors/types.js';
|
||||
import type { WithLogContext } from '#src/middleware/koa-audit-log.js';
|
||||
|
||||
import type { WithGuardedIdentifierPayloadContext } from '../middleware/koa-interaction-body-guard.js';
|
||||
import type {
|
||||
|
@ -108,7 +109,9 @@ export type VerifiedInteractionResult =
|
|||
| VerifiedSignInInteractionResult
|
||||
| VerifiedForgotPasswordInteractionResult;
|
||||
|
||||
export type InteractionContext = WithGuardedIdentifierPayloadContext<IRouterParamContext & Context>;
|
||||
export type InteractionContext = WithGuardedIdentifierPayloadContext<
|
||||
WithLogContext<IRouterParamContext & Context>
|
||||
>;
|
||||
|
||||
export type UserIdentity =
|
||||
| { username: string }
|
||||
|
|
|
@ -2,6 +2,7 @@ import { Event } from '@logto/schemas';
|
|||
import { mockEsm, mockEsmDefault, mockEsmWithActual, pickDefault } from '@logto/shared/esm';
|
||||
|
||||
import RequestError from '#src/errors/RequestError/index.js';
|
||||
import { createMockLogContext } from '#src/test-utils/koa-log.js';
|
||||
import { createMockProvider } from '#src/test-utils/oidc-provider.js';
|
||||
import { createContextWithRouteParameters } from '#src/utils/test-utils.js';
|
||||
|
||||
|
@ -31,10 +32,10 @@ const identifierPayloadVerification = await pickDefault(
|
|||
import('./identifier-payload-verification.js')
|
||||
);
|
||||
|
||||
const log = jest.fn();
|
||||
const logContext = createMockLogContext();
|
||||
|
||||
describe('identifier verification', () => {
|
||||
const baseCtx = { ...createContextWithRouteParameters(), log };
|
||||
const baseCtx = { ...createContextWithRouteParameters(), ...logContext };
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
|
@ -152,7 +153,7 @@ describe('identifier verification', () => {
|
|||
expect(verifyIdentifierByPasscode).toBeCalledWith(
|
||||
{ ...identifier, event: Event.SignIn },
|
||||
'jti',
|
||||
log
|
||||
logContext.createLog
|
||||
);
|
||||
|
||||
expect(result).toEqual({
|
||||
|
@ -176,7 +177,7 @@ describe('identifier verification', () => {
|
|||
expect(verifyIdentifierByPasscode).toBeCalledWith(
|
||||
{ ...identifier, event: Event.SignIn },
|
||||
'jti',
|
||||
log
|
||||
logContext.createLog
|
||||
);
|
||||
|
||||
expect(result).toEqual({
|
||||
|
@ -198,7 +199,7 @@ describe('identifier verification', () => {
|
|||
|
||||
const result = await identifierPayloadVerification(ctx, createMockProvider());
|
||||
|
||||
expect(verifySocialIdentity).toBeCalledWith(identifier, log);
|
||||
expect(verifySocialIdentity).toBeCalledWith(identifier, logContext.createLog);
|
||||
expect(findUserByIdentifier).not.toBeCalled();
|
||||
|
||||
expect(result).toEqual({
|
||||
|
@ -323,7 +324,7 @@ describe('identifier verification', () => {
|
|||
expect(verifyIdentifierByPasscode).toBeCalledWith(
|
||||
{ ...identifier, event: Event.SignIn },
|
||||
'jti',
|
||||
log
|
||||
logContext.createLog
|
||||
);
|
||||
|
||||
expect(result).toEqual({
|
||||
|
|
|
@ -46,7 +46,7 @@ const verifyPasscodeIdentifier = async (
|
|||
): Promise<VerifiedEmailIdentifier | VerifiedPhoneIdentifier> => {
|
||||
const { jti } = await provider.interactionDetails(ctx.req, ctx.res);
|
||||
|
||||
await verifyIdentifierByPasscode({ ...identifier, event }, jti, ctx.log);
|
||||
await verifyIdentifierByPasscode({ ...identifier, event }, jti, ctx.createLog);
|
||||
|
||||
return 'email' in identifier
|
||||
? { key: 'emailVerified', value: identifier.email }
|
||||
|
@ -57,7 +57,7 @@ const verifySocialIdentifier = async (
|
|||
identifier: SocialConnectorPayload,
|
||||
ctx: InteractionContext
|
||||
): Promise<SocialIdentifier> => {
|
||||
const userInfo = await verifySocialIdentity(identifier, ctx.log);
|
||||
const userInfo = await verifySocialIdentity(identifier, ctx.createLog);
|
||||
|
||||
return { key: 'social', connectorId: identifier.connectorId, userInfo };
|
||||
};
|
||||
|
|
|
@ -2,6 +2,7 @@ import { Event } from '@logto/schemas';
|
|||
import { mockEsm, mockEsmWithActual, pickDefault } from '@logto/shared/esm';
|
||||
|
||||
import RequestError from '#src/errors/RequestError/index.js';
|
||||
import { createMockLogContext } from '#src/test-utils/koa-log.js';
|
||||
import { createMockProvider } from '#src/test-utils/oidc-provider.js';
|
||||
import { createContextWithRouteParameters } from '#src/utils/test-utils.js';
|
||||
|
||||
|
@ -25,7 +26,7 @@ const verifyProfile = await pickDefault(import('./profile-verification.js'));
|
|||
|
||||
describe('forgot password interaction profile verification', () => {
|
||||
const provider = createMockProvider();
|
||||
const baseCtx = createContextWithRouteParameters();
|
||||
const baseCtx = { ...createContextWithRouteParameters(), ...createMockLogContext() };
|
||||
|
||||
const interaction = {
|
||||
event: Event.ForgotPassword,
|
||||
|
|
|
@ -2,6 +2,7 @@ import { Event } from '@logto/schemas';
|
|||
import { mockEsm, mockEsmWithActual, pickDefault } from '@logto/shared/esm';
|
||||
|
||||
import RequestError from '#src/errors/RequestError/index.js';
|
||||
import { createMockLogContext } from '#src/test-utils/koa-log.js';
|
||||
import { createMockProvider } from '#src/test-utils/oidc-provider.js';
|
||||
import { createContextWithRouteParameters } from '#src/utils/test-utils.js';
|
||||
|
||||
|
@ -32,7 +33,7 @@ const verifyProfile = await pickDefault(import('./profile-verification.js'));
|
|||
|
||||
describe('Should throw when providing existing identifiers in profile', () => {
|
||||
const provider = createMockProvider();
|
||||
const baseCtx = createContextWithRouteParameters();
|
||||
const baseCtx = { ...createContextWithRouteParameters(), ...createMockLogContext() };
|
||||
const identifiers: Identifier[] = [
|
||||
{ key: 'accountId', value: 'foo' },
|
||||
{ key: 'emailVerified', value: 'email' },
|
||||
|
|
|
@ -2,6 +2,7 @@ import { Event } from '@logto/schemas';
|
|||
import { mockEsm, mockEsmWithActual, pickDefault } from '@logto/shared/esm';
|
||||
|
||||
import RequestError from '#src/errors/RequestError/index.js';
|
||||
import { createMockLogContext } from '#src/test-utils/koa-log.js';
|
||||
import { createMockProvider } from '#src/test-utils/oidc-provider.js';
|
||||
import { createContextWithRouteParameters } from '#src/utils/test-utils.js';
|
||||
|
||||
|
@ -34,7 +35,7 @@ mockEsm('#src/connectors/index.js', () => ({
|
|||
|
||||
const verifyProfile = await pickDefault(import('./profile-verification.js'));
|
||||
|
||||
const baseCtx = createContextWithRouteParameters();
|
||||
const baseCtx = { ...createContextWithRouteParameters(), ...createMockLogContext() };
|
||||
const identifiers: Identifier[] = [
|
||||
{ key: 'accountId', value: 'foo' },
|
||||
{ key: 'emailVerified', value: 'email@logto.io' },
|
||||
|
|
|
@ -2,6 +2,7 @@ import { Event } from '@logto/schemas';
|
|||
import { mockEsm, mockEsmWithActual, pickDefault } from '@logto/shared/esm';
|
||||
|
||||
import RequestError from '#src/errors/RequestError/index.js';
|
||||
import { createMockLogContext } from '#src/test-utils/koa-log.js';
|
||||
import { createMockProvider } from '#src/test-utils/oidc-provider.js';
|
||||
import { createContextWithRouteParameters } from '#src/utils/test-utils.js';
|
||||
|
||||
|
@ -29,7 +30,7 @@ mockEsm('#src/connectors/index.js', () => ({
|
|||
const verifyProfile = await pickDefault(import('./profile-verification.js'));
|
||||
|
||||
describe('profile protected identifier verification', () => {
|
||||
const baseCtx = createContextWithRouteParameters();
|
||||
const baseCtx = { ...createContextWithRouteParameters(), ...createMockLogContext() };
|
||||
const interaction = { event: Event.SignIn, accountId: 'foo' };
|
||||
const provider = createMockProvider();
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ import { Event } from '@logto/schemas';
|
|||
import { mockEsm, mockEsmDefault, mockEsmWithActual, pickDefault } from '@logto/shared/esm';
|
||||
|
||||
import RequestError from '#src/errors/RequestError/index.js';
|
||||
import { createMockLogContext } from '#src/test-utils/koa-log.js';
|
||||
import { createMockProvider } from '#src/test-utils/oidc-provider.js';
|
||||
import { createContextWithRouteParameters } from '#src/utils/test-utils.js';
|
||||
|
||||
|
@ -26,6 +27,7 @@ describe('userAccountVerification', () => {
|
|||
|
||||
const ctx: InteractionContext = {
|
||||
...createContextWithRouteParameters(),
|
||||
...createMockLogContext(),
|
||||
interactionPayload: {
|
||||
event: Event.SignIn,
|
||||
},
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
import type { ExtendableContext } from 'koa';
|
||||
import type Router from 'koa-router';
|
||||
import type { KoaContextWithOIDC } from 'oidc-provider';
|
||||
|
||||
import type { WithLogContextLegacy } from '#src/middleware/koa-audit-log-legacy.js';
|
||||
import type { WithLogContext } from '#src/middleware/koa-audit-log.js';
|
||||
import type { WithAuthContext } from '#src/middleware/koa-auth.js';
|
||||
import type { WithI18nContext } from '#src/middleware/koa-i18next.js';
|
||||
|
||||
export type AnonymousRouter = Router<
|
||||
unknown,
|
||||
WithLogContext & WithI18nContext & KoaContextWithOIDC
|
||||
>;
|
||||
export type AnonymousRouter = Router<unknown, WithLogContext & WithI18nContext & ExtendableContext>;
|
||||
|
||||
/** @deprecated This will be removed soon. Use `kua-log-session.js` instead. */
|
||||
export type AnonymousRouterLegacy = Router<unknown, WithLogContextLegacy & WithI18nContext>;
|
||||
|
||||
export type AuthedRouter = Router<unknown, WithAuthContext & WithLogContext & WithI18nContext>;
|
||||
export type AuthedRouter = Router<
|
||||
unknown,
|
||||
WithAuthContext & WithLogContext & WithI18nContext & ExtendableContext
|
||||
>;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import type { LogContext } from '#src/middleware/koa-audit-log.js';
|
||||
import { LogEntry } from '#src/middleware/koa-audit-log.js';
|
||||
|
||||
const { jest } = import.meta;
|
||||
|
@ -6,8 +7,12 @@ class MockLogEntry extends LogEntry {
|
|||
append = jest.fn();
|
||||
}
|
||||
|
||||
export const createMockLogContext = () => {
|
||||
export const createMockLogContext = (): LogContext & { mockAppend: jest.Mock } => {
|
||||
const mockLogEntry = new MockLogEntry('Unknown');
|
||||
|
||||
return { createLog: jest.fn(() => mockLogEntry), mockAppend: mockLogEntry.append };
|
||||
return {
|
||||
createLog: jest.fn(() => mockLogEntry),
|
||||
prependAllLogEntries: jest.fn(),
|
||||
mockAppend: mockLogEntry.append,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -20,9 +20,7 @@ describe('admin console logs (legacy)', () => {
|
|||
const logs = await getLogs();
|
||||
|
||||
const registerLog = logs.filter(
|
||||
({ type, payload }) =>
|
||||
type === 'RegisterUsernamePassword' &&
|
||||
(payload as Record<string, unknown>).username === username
|
||||
({ type, payload }) => type === 'RegisterUsernamePassword' && payload.username === username
|
||||
);
|
||||
|
||||
expect(registerLog.length).toBeGreaterThan(0);
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import type { Event } from '../interactions.js';
|
||||
|
||||
export { Event } from '../interactions.js';
|
||||
|
||||
export type Prefix = 'Interaction';
|
||||
|
||||
export const prefix: Prefix = 'Interaction';
|
||||
|
|
Loading…
Add table
Reference in a new issue