mirror of
https://github.com/umami-software/umami.git
synced 2025-12-06 01:18:00 +01:00
Fixed uuid references in schemas.
Some checks are pending
Node.js CI / build (postgresql, 18.18) (push) Waiting to run
Some checks are pending
Node.js CI / build (postgresql, 18.18) (push) Waiting to run
This commit is contained in:
parent
f40e1b44f3
commit
303947fe9b
16 changed files with 36 additions and 27 deletions
|
|
@ -82,7 +82,7 @@
|
||||||
"@react-spring/web": "^10.0.1",
|
"@react-spring/web": "^10.0.1",
|
||||||
"@svgr/cli": "^8.1.0",
|
"@svgr/cli": "^8.1.0",
|
||||||
"@tanstack/react-query": "^5.85.5",
|
"@tanstack/react-query": "^5.85.5",
|
||||||
"@umami/react-zen": "^0.179.0",
|
"@umami/react-zen": "^0.180.0",
|
||||||
"@umami/redis-client": "^0.29.0",
|
"@umami/redis-client": "^0.29.0",
|
||||||
"bcryptjs": "^3.0.2",
|
"bcryptjs": "^3.0.2",
|
||||||
"chalk": "^5.6.0",
|
"chalk": "^5.6.0",
|
||||||
|
|
|
||||||
10
pnpm-lock.yaml
generated
10
pnpm-lock.yaml
generated
|
|
@ -45,8 +45,8 @@ importers:
|
||||||
specifier: ^5.85.5
|
specifier: ^5.85.5
|
||||||
version: 5.85.5(react@19.1.1)
|
version: 5.85.5(react@19.1.1)
|
||||||
'@umami/react-zen':
|
'@umami/react-zen':
|
||||||
specifier: ^0.179.0
|
specifier: ^0.180.0
|
||||||
version: 0.179.0(@babel/core@7.28.3)(@types/react@19.1.12)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@10.1.1)(use-sync-external-store@1.5.0(react@19.1.1))
|
version: 0.180.0(@babel/core@7.28.3)(@types/react@19.1.12)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@10.1.1)(use-sync-external-store@1.5.0(react@19.1.1))
|
||||||
'@umami/redis-client':
|
'@umami/redis-client':
|
||||||
specifier: ^0.29.0
|
specifier: ^0.29.0
|
||||||
version: 0.29.0
|
version: 0.29.0
|
||||||
|
|
@ -2735,8 +2735,8 @@ packages:
|
||||||
'@prisma/client': ^6.1.0
|
'@prisma/client': ^6.1.0
|
||||||
'@prisma/extension-read-replicas': ^0.4.1
|
'@prisma/extension-read-replicas': ^0.4.1
|
||||||
|
|
||||||
'@umami/react-zen@0.179.0':
|
'@umami/react-zen@0.180.0':
|
||||||
resolution: {integrity: sha512-OS6Xa1tMO2PfXYXEB98XyOBctvnw/gE2eO3gK5mkJF5P3Ati6Z9KpTpj28Fxi7PgJiWYqcQ5enFzQqHXjYy/3A==}
|
resolution: {integrity: sha512-/kkSeJ/D3WeW577Jb4W0/P6eBjWfGn6E4GHYS0W3K1RgNScz46bEcZe2HJc/l/ssiNoQcSE0vt63t0dUzUaqMQ==}
|
||||||
|
|
||||||
'@umami/redis-client@0.29.0':
|
'@umami/redis-client@0.29.0':
|
||||||
resolution: {integrity: sha512-Jaqh++jskqDB7ny75pfC02OvKp1JTS4asGDsFrRL3qy8sxL3PAl9+/mybCJe4/6vWrXDJKqpgkSfUDJq2bFjyw==}
|
resolution: {integrity: sha512-Jaqh++jskqDB7ny75pfC02OvKp1JTS4asGDsFrRL3qy8sxL3PAl9+/mybCJe4/6vWrXDJKqpgkSfUDJq2bFjyw==}
|
||||||
|
|
@ -10333,7 +10333,7 @@ snapshots:
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@umami/react-zen@0.179.0(@babel/core@7.28.3)(@types/react@19.1.12)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@10.1.1)(use-sync-external-store@1.5.0(react@19.1.1))':
|
'@umami/react-zen@0.180.0(@babel/core@7.28.3)(@types/react@19.1.12)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@10.1.1)(use-sync-external-store@1.5.0(react@19.1.1))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@fontsource/jetbrains-mono': 5.2.6
|
'@fontsource/jetbrains-mono': 5.2.6
|
||||||
'@internationalized/date': 3.9.0
|
'@internationalized/date': 3.9.0
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ export function TeamsSettingsPage() {
|
||||||
<Column gap="6">
|
<Column gap="6">
|
||||||
<TeamsHeader />
|
<TeamsHeader />
|
||||||
<Panel>
|
<Panel>
|
||||||
<TeamsDataTable />
|
<TeamsDataTable showActions={true} />
|
||||||
</Panel>
|
</Panel>
|
||||||
</Column>
|
</Column>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { ReactNode } from 'react';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { DataGrid } from '@/components/common/DataGrid';
|
import { DataGrid } from '@/components/common/DataGrid';
|
||||||
import { TeamsTable } from './TeamsTable';
|
import { TeamsTable } from './TeamsTable';
|
||||||
import { useLoginQuery, useUserTeamsQuery } from '@/components/hooks';
|
import { useLoginQuery, useNavigation, useUserTeamsQuery } from '@/components/hooks';
|
||||||
|
|
||||||
export function TeamsDataTable({
|
export function TeamsDataTable({
|
||||||
showActions,
|
showActions,
|
||||||
|
|
@ -13,10 +13,12 @@ export function TeamsDataTable({
|
||||||
}) {
|
}) {
|
||||||
const { user } = useLoginQuery();
|
const { user } = useLoginQuery();
|
||||||
const query = useUserTeamsQuery(user.id);
|
const query = useUserTeamsQuery(user.id);
|
||||||
|
const { pathname } = useNavigation();
|
||||||
|
const isSettings = pathname.includes('/settings');
|
||||||
|
|
||||||
const renderLink = (row: any) => {
|
const renderLink = (row: any) => {
|
||||||
return (
|
return (
|
||||||
<Link key={row.id} href={`/teams/${row.id}`}>
|
<Link key={row.id} href={`${isSettings ? '/settings' : ''}/teams/${row.id}`}>
|
||||||
{row.name}
|
{row.name}
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ export async function POST(request: Request) {
|
||||||
url: z.string().max(500),
|
url: z.string().max(500),
|
||||||
slug: z.string().max(100),
|
slug: z.string().max(100),
|
||||||
teamId: z.string().nullable().optional(),
|
teamId: z.string().nullable().optional(),
|
||||||
id: z.string().uuid().nullable().optional(),
|
id: z.uuid().nullable().optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
const { auth, body, error } = await parseRequest(request, schema);
|
const { auth, body, error } = await parseRequest(request, schema);
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ export async function POST(request: Request) {
|
||||||
name: z.string().max(100),
|
name: z.string().max(100),
|
||||||
slug: z.string().max(100),
|
slug: z.string().max(100),
|
||||||
teamId: z.string().nullable().optional(),
|
teamId: z.string().nullable().optional(),
|
||||||
id: z.string().uuid().nullable().optional(),
|
id: z.uuid().nullable().optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
const { auth, body, error } = await parseRequest(request, schema);
|
const { auth, body, error } = await parseRequest(request, schema);
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import { getReports, createReport } from '@/queries';
|
||||||
|
|
||||||
export async function GET(request: Request) {
|
export async function GET(request: Request) {
|
||||||
const schema = z.object({
|
const schema = z.object({
|
||||||
websiteId: z.string().uuid().optional(),
|
websiteId: z.uuid().optional(),
|
||||||
type: z.string().optional(),
|
type: z.string().optional(),
|
||||||
...pagingParams,
|
...pagingParams,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -27,9 +27,9 @@ const schema = z.object({
|
||||||
type: z.enum(['event', 'identify']),
|
type: z.enum(['event', 'identify']),
|
||||||
payload: z
|
payload: z
|
||||||
.object({
|
.object({
|
||||||
website: z.string().uuid().optional(),
|
website: z.uuid().optional(),
|
||||||
link: z.string().uuid().optional(),
|
link: z.uuid().optional(),
|
||||||
pixel: z.string().uuid().optional(),
|
pixel: z.uuid().optional(),
|
||||||
data: anyObjectParam.optional(),
|
data: anyObjectParam.optional(),
|
||||||
hostname: z.string().max(100).optional(),
|
hostname: z.string().max(100).optional(),
|
||||||
language: z.string().max(35).optional(),
|
language: z.string().max(35).optional(),
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ export async function GET(request: Request, { params }: { params: Promise<{ team
|
||||||
|
|
||||||
export async function POST(request: Request, { params }: { params: Promise<{ teamId: string }> }) {
|
export async function POST(request: Request, { params }: { params: Promise<{ teamId: string }> }) {
|
||||||
const schema = z.object({
|
const schema = z.object({
|
||||||
userId: z.string().uuid(),
|
userId: z.uuid(),
|
||||||
role: teamRoleParam,
|
role: teamRoleParam,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import { createUser, getUserByUsername } from '@/queries';
|
||||||
|
|
||||||
export async function POST(request: Request) {
|
export async function POST(request: Request) {
|
||||||
const schema = z.object({
|
const schema = z.object({
|
||||||
id: z.string().uuid().optional(),
|
id: z.uuid().optional(),
|
||||||
username: z.string().max(255),
|
username: z.string().max(255),
|
||||||
password: z.string(),
|
password: z.string(),
|
||||||
role: z.string().regex(/admin|user|view-only/i),
|
role: z.string().regex(/admin|user|view-only/i),
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,8 @@ export async function POST(
|
||||||
{ params }: { params: Promise<{ websiteId: string }> },
|
{ params }: { params: Promise<{ websiteId: string }> },
|
||||||
) {
|
) {
|
||||||
const schema = z.object({
|
const schema = z.object({
|
||||||
userId: z.string().uuid().optional(),
|
userId: z.uuid().optional(),
|
||||||
teamId: z.string().uuid().optional(),
|
teamId: z.uuid().optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
const { auth, body, error } = await parseRequest(request, schema);
|
const { auth, body, error } = await parseRequest(request, schema);
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ export async function POST(request: Request) {
|
||||||
domain: z.string().max(500),
|
domain: z.string().max(500),
|
||||||
shareId: z.string().max(50).nullable().optional(),
|
shareId: z.string().max(50).nullable().optional(),
|
||||||
teamId: z.string().nullable().optional(),
|
teamId: z.string().nullable().optional(),
|
||||||
id: z.string().uuid().nullable().optional(),
|
id: z.uuid().nullable().optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
const { auth, body, error } = await parseRequest(request, schema);
|
const { auth, body, error } = await parseRequest(request, schema);
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ export function DataGrid({
|
||||||
const { data, error, isLoading, isFetching } = query;
|
const { data, error, isLoading, isFetching } = query;
|
||||||
const { router, updateParams, query: queryParams } = useNavigation();
|
const { router, updateParams, query: queryParams } = useNavigation();
|
||||||
const [search, setSearch] = useState(queryParams?.search || data?.search || '');
|
const [search, setSearch] = useState(queryParams?.search || data?.search || '');
|
||||||
|
const showPager = allowPaging && data && data.count > data.pageSize;
|
||||||
|
|
||||||
const handleSearch = (value: string) => {
|
const handleSearch = (value: string) => {
|
||||||
if (value !== search) {
|
if (value !== search) {
|
||||||
|
|
@ -73,7 +74,7 @@ export function DataGrid({
|
||||||
{data && (
|
{data && (
|
||||||
<>
|
<>
|
||||||
<Column>{typeof children === 'function' ? children(data) : children}</Column>
|
<Column>{typeof children === 'function' ? children(data) : children}</Column>
|
||||||
{allowPaging && data && (
|
{showPager && (
|
||||||
<Row marginTop="6">
|
<Row marginTop="6">
|
||||||
<Pager
|
<Pager
|
||||||
page={data.page}
|
page={data.page}
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,14 @@ export function checkPassword(password: string, passwordHash: string) {
|
||||||
return bcrypt.compareSync(password, passwordHash);
|
return bcrypt.compareSync(password, passwordHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getBearerToken(request: Request) {
|
||||||
|
const auth = request.headers.get('authorization');
|
||||||
|
|
||||||
|
return auth?.split(' ')[1];
|
||||||
|
}
|
||||||
|
|
||||||
export async function checkAuth(request: Request) {
|
export async function checkAuth(request: Request) {
|
||||||
const token = request.headers.get('authorization')?.split(' ')?.[1];
|
const token = getBearerToken(request);
|
||||||
const payload = parseSecureToken(token, secret());
|
const payload = parseSecureToken(token, secret());
|
||||||
const shareToken = await parseShareToken(request.headers);
|
const shareToken = await parseShareToken(request.headers);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { z } from 'zod';
|
||||||
import { checkAuth } from '@/lib/auth';
|
import { checkAuth } from '@/lib/auth';
|
||||||
import { DEFAULT_PAGE_SIZE, FILTER_COLUMNS } from '@/lib/constants';
|
import { DEFAULT_PAGE_SIZE, FILTER_COLUMNS } from '@/lib/constants';
|
||||||
import { getAllowedUnits, getMinimumUnit, maxDate, parseDateRange } from '@/lib/date';
|
import { getAllowedUnits, getMinimumUnit, maxDate, parseDateRange } from '@/lib/date';
|
||||||
|
|
@ -5,7 +6,6 @@ import { fetchWebsite } from '@/lib/load';
|
||||||
import { badRequest, unauthorized } from '@/lib/response';
|
import { badRequest, unauthorized } from '@/lib/response';
|
||||||
import { QueryFilters } from '@/lib/types';
|
import { QueryFilters } from '@/lib/types';
|
||||||
import { getWebsiteSegment } from '@/queries';
|
import { getWebsiteSegment } from '@/queries';
|
||||||
import { z } from 'zod/v4';
|
|
||||||
import { filtersArrayToObject } from '@/lib/params';
|
import { filtersArrayToObject } from '@/lib/params';
|
||||||
|
|
||||||
export async function parseRequest(
|
export async function parseRequest(
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,8 @@ export const filterParams = {
|
||||||
hostname: z.string().optional(),
|
hostname: z.string().optional(),
|
||||||
language: z.string().optional(),
|
language: z.string().optional(),
|
||||||
event: z.string().optional(),
|
event: z.string().optional(),
|
||||||
segment: z.string().uuid().optional(),
|
segment: z.uuid().optional(),
|
||||||
cohort: z.string().uuid().optional(),
|
cohort: z.uuid().optional(),
|
||||||
eventType: z.coerce.number().int().positive().optional(),
|
eventType: z.coerce.number().int().positive().optional(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -198,7 +198,7 @@ export const breakdownReportSchema = z.object({
|
||||||
});
|
});
|
||||||
|
|
||||||
export const reportBaseSchema = z.object({
|
export const reportBaseSchema = z.object({
|
||||||
websiteId: z.string().uuid(),
|
websiteId: z.uuid(),
|
||||||
type: reportTypeParam,
|
type: reportTypeParam,
|
||||||
name: z.string().max(200),
|
name: z.string().max(200),
|
||||||
description: z.string().max(500).optional(),
|
description: z.string().max(500).optional(),
|
||||||
|
|
@ -220,7 +220,7 @@ export const reportSchema = reportBaseSchema;
|
||||||
|
|
||||||
export const reportResultSchema = z.intersection(
|
export const reportResultSchema = z.intersection(
|
||||||
z.object({
|
z.object({
|
||||||
websiteId: z.string().uuid(),
|
websiteId: z.uuid(),
|
||||||
filters: z.object({ ...filterParams }),
|
filters: z.object({ ...filterParams }),
|
||||||
}),
|
}),
|
||||||
reportTypeSchema,
|
reportTypeSchema,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue