diff --git a/src/app/(main)/UpdateNotice.tsx b/src/app/(main)/UpdateNotice.tsx index 7504943b..17c2bce7 100644 --- a/src/app/(main)/UpdateNotice.tsx +++ b/src/app/(main)/UpdateNotice.tsx @@ -14,6 +14,7 @@ export function UpdateNotice({ user, config }) { const pathname = usePathname(); const [dismissed, setDismissed] = useState(checked); const allowUpdate = + process.env.NODE_ENV === 'production' && user?.isAdmin && !config?.updatesDisabled && !pathname.includes('/share/') && diff --git a/src/app/api/send/route.ts b/src/app/api/send/route.ts index cf62d4ad..2d220f38 100644 --- a/src/app/api/send/route.ts +++ b/src/app/api/send/route.ts @@ -7,7 +7,7 @@ import { badRequest, json, forbidden, serverError } from '@/lib/response'; import { fetchSession, fetchWebsite } from '@/lib/load'; import { getClientInfo, hasBlockedIp } from '@/lib/detect'; import { secret, uuid, visitSalt } from '@/lib/crypto'; -import { COLLECTION_TYPE } from '@/lib/constants'; +import { COLLECTION_TYPE, DOMAIN_REGEX } from '@/lib/constants'; import { createSession, saveEvent, saveSessionData } from '@/queries'; import { urlOrPathParam } from '@/lib/schema'; @@ -16,7 +16,7 @@ const schema = z.object({ payload: z.object({ website: z.string().uuid(), data: z.object({}).passthrough().optional(), - hostname: z.string().max(100).optional(), + hostname: z.string().regex(DOMAIN_REGEX).max(100).optional(), language: z.string().max(35).optional(), referrer: urlOrPathParam.optional(), screen: z.string().max(11).optional(), diff --git a/src/components/hooks/queries/useSessionDataProperties.ts b/src/components/hooks/queries/useSessionDataProperties.ts index 45590b39..ca3798f0 100644 --- a/src/components/hooks/queries/useSessionDataProperties.ts +++ b/src/components/hooks/queries/useSessionDataProperties.ts @@ -10,7 +10,7 @@ export function useSessionDataProperties( const params = useFilterParams(websiteId); return useQuery({ - queryKey: ['websites:event-data:properties', { websiteId, ...params }], + queryKey: ['websites:session-data:properties', { websiteId, ...params }], queryFn: () => get(`/websites/${websiteId}/session-data/properties`, { ...params }), enabled: !!websiteId, ...options, diff --git a/src/components/hooks/usePagedQuery.ts b/src/components/hooks/usePagedQuery.ts index bd59189a..b6b06e1c 100644 --- a/src/components/hooks/usePagedQuery.ts +++ b/src/components/hooks/usePagedQuery.ts @@ -12,7 +12,7 @@ export function usePagedQuery({ const { query: queryParams } = useNavigation(); const [params, setParams] = useState({ search: '', - page: queryParams.page || '1', + page: +queryParams.page || 1, }); const { useQuery } = useApi(); diff --git a/src/lib/constants.ts b/src/lib/constants.ts index 545f86c8..a64210ec 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -241,12 +241,6 @@ export const CHART_COLORS = [ export const DOMAIN_REGEX = /^(localhost(:[1-9]\d{0,4})?|((?=[a-z0-9-_]{1,63}\.)(xn--)?[a-z0-9-_]+(-[a-z0-9-_]+)*\.)+(xn--)?[a-z0-9-_]{2,63})$/; export const SHARE_ID_REGEX = /^[a-zA-Z0-9]{8,16}$/; -export const UUID_REGEX = - /^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/; -export const HOSTNAME_REGEX = - /^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-_]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9-_]*[A-Za-z0-9])$/; -export const IP_REGEX = - /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$|^(?:(?:[0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,7}:|(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|(?:[0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|(?:[0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|(?:[0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:(?:(:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]+|::(ffff(:0{1,4})?:)?((25[0-5]|(2[0-4]|1?[0-9])?[0-9])\.){3}(25[0-5]|(2[0-4]|1?[0-9])?[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1?[0-9])?[0-9])\.){3}(25[0-5]|(2[0-4]|1?[0-9])?[0-9]))$/; export const DATETIME_REGEX = /^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\.[0-9]{3}(Z|\+[0-9]{2}:[0-9]{2})?)?$/; diff --git a/src/lib/types.ts b/src/lib/types.ts index c385fa53..bcc05479 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -24,7 +24,7 @@ export type ReportType = ObjectValues; export interface PageParams { search?: string; - page?: string; + page?: string | number; pageSize?: string; orderBy?: string; sortDescending?: boolean; diff --git a/src/queries/sql/sessions/getSessionDataProperties.ts b/src/queries/sql/sessions/getSessionDataProperties.ts index da02c97e..bfa6a269 100644 --- a/src/queries/sql/sessions/getSessionDataProperties.ts +++ b/src/queries/sql/sessions/getSessionDataProperties.ts @@ -24,13 +24,16 @@ async function relationalQuery( return rawQuery( ` select - data_key as "propertyName", - count(*) as "total" - from session_data - where website_id = {{websiteId::uuid}} - and created_at between {{startDate}} and {{endDate}} - ${filterQuery} - group by data_key + data_key as "propertyName", + count(*) as "total" + from website_event e + left join session_data d + on d.session_id = e.session_id + where e.website_id = {{websiteId:uuid}} + and e.created_at between {{startDate}} and {{endDate}} + and d.data_key is not null + ${filterQuery} + group by 1 order by 2 desc limit 500 `, @@ -52,11 +55,14 @@ async function clickhouseQuery( select data_key as propertyName, count(*) as total - from session_data final - where website_id = {websiteId:UUID} - and created_at between {startDate:DateTime64} and {endDate:DateTime64} + from website_event e + left join session_data d + on d.session_id = e.session_id + where e.website_id = {websiteId:UUID} + and e.created_at between {startDate:DateTime64} and {endDate:DateTime64} + and d.data_key != '' ${filterQuery} - group by data_key + group by 1 order by 2 desc limit 500 `,