diff --git a/apps/api/src/controllers/track.controller.ts b/apps/api/src/controllers/track.controller.ts index dd979767..34b6fc90 100644 --- a/apps/api/src/controllers/track.controller.ts +++ b/apps/api/src/controllers/track.controller.ts @@ -49,7 +49,7 @@ function getIdentity(body: TrackHandlerPayload): IdentifyPayload | undefined { return ( identity || - (body.payload.profileId + (body?.payload?.profileId ? { profileId: body.payload.profileId, } @@ -100,7 +100,11 @@ export async function handler( const projectId = request.client?.projectId; if (!projectId) { - reply.status(400).send('missing origin'); + reply.status(400).send({ + status: 400, + error: 'Bad Request', + message: 'Missing projectId', + }); return; } @@ -198,6 +202,14 @@ export async function handler( }); break; } + default: { + reply.status(400).send({ + status: 400, + error: 'Bad Request', + message: 'Invalid type', + }); + break; + } } } diff --git a/apps/api/src/index.ts b/apps/api/src/index.ts index e9b6f9bc..86772578 100644 --- a/apps/api/src/index.ts +++ b/apps/api/src/index.ts @@ -208,6 +208,12 @@ const startServer = async () => { error: 'Too Many Requests', message: 'You have exceeded the rate limit for this endpoint.', }); + } else if (error.statusCode === 400) { + reply.status(400).send({ + status: 400, + error, + message: 'The request was invalid.', + }); } else { request.log.error('request error', { error }); reply.status(500).send('Internal server error'); diff --git a/apps/api/src/routes/track.router.ts b/apps/api/src/routes/track.router.ts index 1f0de440..56d98dc4 100644 --- a/apps/api/src/routes/track.router.ts +++ b/apps/api/src/routes/track.router.ts @@ -1,12 +1,8 @@ -import { isBot } from '@/bots'; import { handler } from '@/controllers/track.controller'; -import { SdkAuthError, validateSdkRequest } from '@/utils/auth'; -import type { FastifyPluginCallback, FastifyRequest } from 'fastify'; +import type { FastifyPluginCallback } from 'fastify'; import { clientHook } from '@/hooks/client.hook'; import { isBotHook } from '@/hooks/is-bot.hook'; -import { createBotEvent } from '@openpanel/db'; -import type { TrackHandlerPayload } from '@openpanel/sdk'; const trackRouter: FastifyPluginCallback = (fastify, opts, done) => { fastify.addHook('preHandler', clientHook); @@ -16,6 +12,22 @@ const trackRouter: FastifyPluginCallback = (fastify, opts, done) => { method: 'POST', url: '/', handler: handler, + schema: { + body: { + type: 'object', + required: ['type', 'payload'], + properties: { + type: { + type: 'string', + enum: ['track', 'increment', 'decrement', 'alias', 'identify'], + }, + payload: { + type: 'object', + additionalProperties: true, + }, + }, + }, + }, }); done(); diff --git a/apps/api/src/utils/auth.ts b/apps/api/src/utils/auth.ts index 9944b49a..b32c3d65 100644 --- a/apps/api/src/utils/auth.ts +++ b/apps/api/src/utils/auth.ts @@ -66,6 +66,14 @@ export async function validateSdkRequest( throw createError('Ingestion: Missing client id'); } + if ( + !/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test( + clientId, + ) + ) { + throw createError('Ingestion: Clean ID must be a valid UUIDv4'); + } + const client = await getClientByIdCached(clientId); if (!client) { @@ -136,6 +144,15 @@ export async function validateExportRequest( ): Promise { const clientId = headers['openpanel-client-id'] as string; const clientSecret = (headers['openpanel-client-secret'] as string) || ''; + + if ( + !/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test( + clientId, + ) + ) { + throw new Error('Export: Client ID must be a valid UUIDv4'); + } + const client = await getClientByIdCached(clientId); if (!client) { @@ -162,6 +179,15 @@ export async function validateImportRequest( ): Promise { const clientId = headers['openpanel-client-id'] as string; const clientSecret = (headers['openpanel-client-secret'] as string) || ''; + + if ( + !/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test( + clientId, + ) + ) { + throw new Error('Import: Client ID must be a valid UUIDv4'); + } + const client = await getClientByIdCached(clientId); if (!client) {