diff --git a/.github/workflows/gitleaks.yml b/.github/workflows/gitleaks.yml index 5e64b8a85..6cd6386f5 100644 --- a/.github/workflows/gitleaks.yml +++ b/.github/workflows/gitleaks.yml @@ -19,7 +19,7 @@ jobs: fetch-depth: 0 - name: Run Gitleaks - uses: gitleaks/gitleaks-action@v3 + uses: gitleaks/gitleaks-action@e0c47f4f8be36e29cdc102c57e68cb5cbf0e8d1e # v3.0.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Required for organization-owned repositories. diff --git a/package.json b/package.json index 099891a72..d8c88195a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "umami", - "version": "3.3.1", + "version": "3.4.0", "description": "A modern, privacy-focused alternative to Google Analytics.", "author": "Umami Software, Inc. ", "license": "MIT", diff --git a/packages/api-client/src/client.test.ts b/packages/api-client/src/client.test.ts index e37d1107b..77cd6f6d1 100644 --- a/packages/api-client/src/client.test.ts +++ b/packages/api-client/src/client.test.ts @@ -77,7 +77,6 @@ describe('UmamiClient', () => { expect(calls[0].method).toBe('POST'); expect(calls[0].url.pathname).toBe('/api/websites/w1/funnels'); expect(JSON.parse(calls[0].body as string)).toEqual({ - websiteId: 'w1', name: 'Signup funnel', parameters: { window: 60, steps: [] }, }); diff --git a/packages/api-client/src/generated/operations.ts b/packages/api-client/src/generated/operations.ts index 1f2324761..fde9f5c08 100644 --- a/packages/api-client/src/generated/operations.ts +++ b/packages/api-client/src/generated/operations.ts @@ -4,7 +4,7 @@ import type { RequestOptions } from '../types'; import type { components, operations as OperationTypes } from './types'; -export const API_VERSION = '3.3.1'; +export const API_VERSION = '3.4.0'; export type HttpMethod = 'get' | 'post' | 'put' | 'patch' | 'delete'; diff --git a/packages/api-client/src/http.test.ts b/packages/api-client/src/http.test.ts index aa690ab26..b6528c3a3 100644 --- a/packages/api-client/src/http.test.ts +++ b/packages/api-client/src/http.test.ts @@ -109,7 +109,7 @@ describe('splitInput', () => { }); }); - test('routes unknown keys to the body for operations with a request body', () => { + test('routes unknown keys to the body and keeps path params out of it', () => { expect( splitInput(funnelOperation, { websiteId: 'w', @@ -119,7 +119,7 @@ describe('splitInput', () => { ).toEqual({ path: { websiteId: 'w' }, query: {}, - body: { websiteId: 'w', name: 'Signup', parameters: { steps: [] } }, + body: { name: 'Signup', parameters: { steps: [] } }, }); }); }); diff --git a/packages/api-client/src/http.ts b/packages/api-client/src/http.ts index 5e7b60412..1a88e2f40 100644 --- a/packages/api-client/src/http.ts +++ b/packages/api-client/src/http.ts @@ -87,8 +87,9 @@ export interface SplitInput { /** * Splits a flat input object into path params, query params and body according to the operation - * definition. Unknown keys go to the query string for body-less operations (dynamic filter params - * such as `browser1` or `pf_*`) and to the body otherwise. + * definition. Path parameters are only used to build the URL and are never sent in the query + * string or JSON body. Unknown keys go to the query string for body-less operations (dynamic + * filter params such as `browser1` or `pf_*`) and to the body otherwise. */ export function splitInput( operation: OperationDefinition, @@ -103,17 +104,11 @@ export function splitInput( for (const [key, value] of Object.entries(input)) { if (pathParams.has(key)) { path[key] = value; - - if (!operation.hasBody) { - continue; - } - } - - if (queryParams.has(key)) { + } else if (queryParams.has(key)) { query[key] = value; } else if (operation.hasBody) { body[key] = value; - } else if (!pathParams.has(key)) { + } else { query[key] = value; } } diff --git a/src/app/api/websites/[websiteId]/annotations/route.ts b/src/app/api/websites/[websiteId]/annotations/route.ts index 6393d41df..27a78cf30 100644 --- a/src/app/api/websites/[websiteId]/annotations/route.ts +++ b/src/app/api/websites/[websiteId]/annotations/route.ts @@ -34,7 +34,8 @@ export async function GET( search, page, pageSize, - ...(startAt && endAt && { startDate: new Date(startAt), endDate: new Date(endAt) }), + ...(startAt != null && + endAt != null && { startDate: new Date(startAt), endDate: new Date(endAt) }), }); return json(annotations);