Fix Invalid input in Track Analytics (#12421)

Fix #12231
This commit is contained in:
Félix Malfait
2025-06-03 08:50:44 +02:00
committed by GitHub
parent c4ffd38435
commit 8c2da395bb
5 changed files with 87 additions and 7 deletions

View File

@ -0,0 +1,23 @@
import { Catch, ExceptionFilter } from '@nestjs/common';
import {
AuditException,
AuditExceptionCode,
} from 'src/engine/core-modules/audit/audit.exception';
import { UserInputError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
@Catch(AuditException)
export class AuditExceptionFilter implements ExceptionFilter {
catch(exception: AuditException) {
switch (exception.code) {
case AuditExceptionCode.INVALID_TYPE:
case AuditExceptionCode.INVALID_INPUT:
throw new UserInputError(exception.message);
default: {
const _exhaustiveCheck: never = exception.code;
throw exception;
}
}
}
}

View File

@ -1,6 +1,7 @@
import { CustomException } from 'src/utils/custom-exception';
export class AuditException extends CustomException {
declare code: AuditExceptionCode;
constructor(message: string, code: AuditExceptionCode) {
super(message, code);
}

View File

@ -1,5 +1,7 @@
import { UseFilters } from '@nestjs/common';
import { Args, Mutation, Resolver } from '@nestjs/graphql';
import { AuditExceptionFilter } from 'src/engine/core-modules/audit/audit-exception-filter';
import {
AuditException,
AuditExceptionCode,
@ -19,6 +21,7 @@ import { Analytics } from './entities/analytics.entity';
import { AuditService } from './services/audit.service';
@Resolver(() => Analytics)
@UseFilters(AuditExceptionFilter)
export class AuditResolver {
constructor(private readonly auditService: AuditService) {}

View File

@ -0,0 +1,53 @@
import { makePageview } from './analytics.utils';
describe('makePageview', () => {
it('should create a pageview with default properties when none are provided', () => {
const result = makePageview('test-page');
expect(result.name).toBe('test-page');
expect(result.type).toBe('page');
expect(result.properties).toEqual({
href: '',
locale: '',
pathname: '',
referrer: '',
sessionId: '',
timeZone: '',
userAgent: '',
});
expect(result.timestamp).toBeDefined();
expect(result.version).toBe('1');
});
it('should create a pageview with provided properties and fill in defaults for missing ones', () => {
const providedProperties = {
href: 'https://example.com',
sessionId: 'test-session-id',
};
const result = makePageview('test-page', providedProperties);
expect(result.name).toBe('test-page');
expect(result.type).toBe('page');
expect(result.properties).toEqual({
href: 'https://example.com',
locale: '',
pathname: '',
referrer: '',
sessionId: 'test-session-id',
timeZone: '',
userAgent: '',
});
expect(result.timestamp).toBeDefined();
expect(result.version).toBe('1');
});
it('should handle empty properties object', () => {
const result = makePageview('test-page', {});
expect(result.name).toBe('test-page');
expect(result.type).toBe('page');
expect(result.properties.sessionId).toBe('');
expect(result.properties.href).toBe('');
});
});

View File

@ -6,13 +6,13 @@ export const pageviewSchema = baseEventSchema.extend({
type: z.literal('page'),
name: z.string(),
properties: z.object({
href: z.string(),
locale: z.string(),
pathname: z.string(),
referrer: z.string(),
sessionId: z.string(),
timeZone: z.string(),
userAgent: z.string(),
href: z.string().optional().default(''),
locale: z.string().optional().default(''),
pathname: z.string().optional().default(''),
referrer: z.string().optional().default(''),
sessionId: z.string().optional().default(''),
timeZone: z.string().optional().default(''),
userAgent: z.string().optional().default(''),
}),
});