fix: ensure job id is a clean string

This commit is contained in:
Carl-Gerhard Lindesvärd
2025-12-08 20:32:29 +01:00
parent 4e42689115
commit 969c0bc8fe
4 changed files with 27 additions and 10 deletions

View File

@@ -5,7 +5,7 @@ import { getSalts } from '@openpanel/db';
import { getEventsGroupQueueShard } from '@openpanel/queue'; import { getEventsGroupQueueShard } from '@openpanel/queue';
import type { PostEventPayload } from '@openpanel/sdk'; import type { PostEventPayload } from '@openpanel/sdk';
import { generateId } from '@openpanel/common'; import { generateId, slug } from '@openpanel/common';
import { getGeoLocation } from '@openpanel/geo'; import { getGeoLocation } from '@openpanel/geo';
import { getStringHeaders, getTimestamp } from './track.controller'; import { getStringHeaders, getTimestamp } from './track.controller';
@@ -54,7 +54,7 @@ export async function postEvent(
: `${projectId}:${generateId()}` : `${projectId}:${generateId()}`
: currentDeviceId; : currentDeviceId;
const jobId = [ const jobId = [
request.body.name, slug(request.body.name),
timestamp, timestamp,
projectId, projectId,
currentDeviceId, currentDeviceId,

View File

@@ -1,7 +1,7 @@
import type { FastifyReply, FastifyRequest } from 'fastify'; import type { FastifyReply, FastifyRequest } from 'fastify';
import { assocPath, pathOr, pick } from 'ramda'; import { assocPath, pathOr, pick } from 'ramda';
import { generateId } from '@openpanel/common'; import { generateId, slug } from '@openpanel/common';
import { generateDeviceId, parseUserAgent } from '@openpanel/common/server'; import { generateDeviceId, parseUserAgent } from '@openpanel/common/server';
import { getProfileById, getSalts, upsertProfile } from '@openpanel/db'; import { getProfileById, getSalts, upsertProfile } from '@openpanel/db';
import { type GeoLocation, getGeoLocation } from '@openpanel/geo'; import { type GeoLocation, getGeoLocation } from '@openpanel/geo';
@@ -254,7 +254,13 @@ async function track({
? `${projectId}:${payload.profileId}` ? `${projectId}:${payload.profileId}`
: `${projectId}:${generateId()}` : `${projectId}:${generateId()}`
: currentDeviceId; : currentDeviceId;
const jobId = [payload.name, timestamp, projectId, currentDeviceId, groupId] const jobId = [
slug(payload.name),
timestamp,
projectId,
currentDeviceId,
groupId,
]
.filter(Boolean) .filter(Boolean)
.join('-'); .join('-');
await getEventsGroupQueueShard(groupId).add({ await getEventsGroupQueueShard(groupId).add({

View File

@@ -0,0 +1,10 @@
import { describe, expect, it } from 'vitest';
import { slug } from './slug';
describe('slug', () => {
it('should remove pipes from string', () => {
expect(slug('Hello || World, | Test å å ä ä')).toBe(
'hello-world-test-a-a-a-a',
);
});
});

View File

@@ -3,12 +3,13 @@ import _slugify from 'slugify';
const slugify = (str: string) => { const slugify = (str: string) => {
return _slugify( return _slugify(
str str
.replace('å', 'a') .replaceAll('å', 'a')
.replace('ä', 'a') .replaceAll('ä', 'a')
.replace('ö', 'o') .replaceAll('ö', 'o')
.replace('Å', 'A') .replaceAll('Å', 'A')
.replace('Ä', 'A') .replaceAll('Ä', 'A')
.replace('Ö', 'O'), .replaceAll('Ö', 'O')
.replace(/\|+/g, '-'),
{ lower: true, strict: true, trim: true }, { lower: true, strict: true, trim: true },
); );
}; };