mirror of
https://github.com/umami-software/umami.git
synced 2026-02-16 10:35:35 +01:00
Compare commits
4 commits
ddc7affa6a
...
f98e683979
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f98e683979 | ||
|
|
b7747b33e4 | ||
|
|
06230ad2e9 | ||
|
|
d8fdba77db |
10 changed files with 399 additions and 385 deletions
20
package.json
20
package.json
|
|
@ -72,8 +72,8 @@
|
|||
"@dicebear/core": "^9.2.3",
|
||||
"@fontsource/inter": "^5.2.8",
|
||||
"@hello-pangea/dnd": "^17.0.0",
|
||||
"@prisma/adapter-pg": "^6.16.3",
|
||||
"@prisma/client": "^6.16.3",
|
||||
"@prisma/adapter-pg": "^6.17.1",
|
||||
"@prisma/client": "^6.17.1",
|
||||
"@prisma/extension-read-replicas": "^0.4.1",
|
||||
"@react-spring/web": "^10.0.3",
|
||||
"@svgr/cli": "^8.1.0",
|
||||
|
|
@ -113,7 +113,7 @@
|
|||
"npm-run-all": "^4.1.5",
|
||||
"papaparse": "^5.5.3",
|
||||
"pg": "^8.16.3",
|
||||
"prisma": "6.16.3",
|
||||
"prisma": "6.17.1",
|
||||
"pure-rand": "^7.0.1",
|
||||
"react": "^19.2.0",
|
||||
"react-dom": "^19.2.0",
|
||||
|
|
@ -133,7 +133,7 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@formatjs/cli": "^4.2.29",
|
||||
"@netlify/plugin-nextjs": "^5.14.0",
|
||||
"@netlify/plugin-nextjs": "^5.14.2",
|
||||
"@rollup/plugin-alias": "^5.0.0",
|
||||
"@rollup/plugin-commonjs": "^25.0.4",
|
||||
"@rollup/plugin-json": "^6.0.0",
|
||||
|
|
@ -142,12 +142,12 @@
|
|||
"@rollup/plugin-terser": "^0.4.4",
|
||||
"@rollup/plugin-typescript": "^12.1.4",
|
||||
"@types/jest": "^30.0.0",
|
||||
"@types/node": "^24.8.1",
|
||||
"@types/node": "^24.9.1",
|
||||
"@types/react": "^19.2.2",
|
||||
"@types/react-dom": "^19.2.2",
|
||||
"@types/react-window": "^1.8.8",
|
||||
"@typescript-eslint/eslint-plugin": "^8.46.1",
|
||||
"@typescript-eslint/parser": "^8.46.1",
|
||||
"@typescript-eslint/eslint-plugin": "^8.46.2",
|
||||
"@typescript-eslint/parser": "^8.46.2",
|
||||
"babel-plugin-react-compiler": "19.1.0-rc.2",
|
||||
"cross-env": "^10.1.0",
|
||||
"cypress": "^13.6.6",
|
||||
|
|
@ -163,14 +163,14 @@
|
|||
"extract-react-intl-messages": "^4.1.1",
|
||||
"husky": "^9.1.7",
|
||||
"jest": "^29.7.0",
|
||||
"lint-staged": "^16.2.4",
|
||||
"lint-staged": "^16.2.5",
|
||||
"postcss": "^8.5.6",
|
||||
"postcss-flexbugs-fixes": "^5.0.2",
|
||||
"postcss-import": "^15.1.0",
|
||||
"postcss-preset-env": "7.8.3",
|
||||
"prettier": "^3.6.2",
|
||||
"prompts": "2.4.2",
|
||||
"rollup": "^4.52.4",
|
||||
"rollup": "^4.52.5",
|
||||
"rollup-plugin-copy": "^3.4.0",
|
||||
"rollup-plugin-delete": "^3.0.1",
|
||||
"rollup-plugin-dts": "^6.2.3",
|
||||
|
|
@ -182,7 +182,7 @@
|
|||
"stylelint-config-prettier": "^9.0.3",
|
||||
"stylelint-config-recommended": "^14.0.0",
|
||||
"tar": "^6.1.2",
|
||||
"ts-jest": "^29.4.0",
|
||||
"ts-jest": "^29.4.5",
|
||||
"ts-node": "^10.9.1",
|
||||
"tsup": "^8.5.0",
|
||||
"typescript": "^5.9.3"
|
||||
|
|
|
|||
690
pnpm-lock.yaml
generated
690
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
|
|
@ -1,15 +1,21 @@
|
|||
import { json, unauthorized } from '@/lib/response';
|
||||
import { getRealtimeData } from '@/queries/sql';
|
||||
import { canViewWebsite } from '@/permissions';
|
||||
import { startOfMinute, subMinutes } from 'date-fns';
|
||||
import { REALTIME_RANGE } from '@/lib/constants';
|
||||
import { parseRequest, getQueryFilters } from '@/lib/request';
|
||||
import { getQueryFilters, parseRequest } from '@/lib/request';
|
||||
import { json, unauthorized } from '@/lib/response';
|
||||
import { timezoneParam } from '@/lib/schema';
|
||||
import { canViewWebsite } from '@/permissions';
|
||||
import { getRealtimeData } from '@/queries/sql';
|
||||
import { startOfMinute, subMinutes } from 'date-fns';
|
||||
import z from 'zod';
|
||||
|
||||
export async function GET(
|
||||
request: Request,
|
||||
{ params }: { params: Promise<{ websiteId: string }> },
|
||||
) {
|
||||
const { auth, query, error } = await parseRequest(request);
|
||||
const schema = z.object({
|
||||
timezone: timezoneParam,
|
||||
});
|
||||
|
||||
const { auth, query, error } = await parseRequest(request, schema);
|
||||
|
||||
if (error) {
|
||||
return error();
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ export async function POST(request: Request, { params }: { params: Promise<{ tea
|
|||
const { teamId } = await params;
|
||||
|
||||
if (!(await canUpdateTeam(auth, teamId))) {
|
||||
return unauthorized({ message: 'You must be the owner of this team.' });
|
||||
return unauthorized({ message: 'You must be the owner/manager of this team.' });
|
||||
}
|
||||
|
||||
const team = await updateTeam(teamId, body);
|
||||
|
|
@ -62,7 +62,7 @@ export async function DELETE(
|
|||
const { teamId } = await params;
|
||||
|
||||
if (!(await canDeleteTeam(auth, teamId))) {
|
||||
return unauthorized({ message: 'You must be the owner of this team.' });
|
||||
return unauthorized({ message: 'You must be the owner/manager of this team.' });
|
||||
}
|
||||
|
||||
await deleteTeam(teamId);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { parseRequest } from '@/lib/request';
|
|||
import { badRequest, json, ok, unauthorized } from '@/lib/response';
|
||||
import { deleteTeamUser, getTeamUser, updateTeamUser } from '@/queries/prisma';
|
||||
import { z } from 'zod';
|
||||
import { teamRoleParam } from '@/lib/schema';
|
||||
|
||||
export async function GET(
|
||||
request: Request,
|
||||
|
|
@ -17,7 +18,7 @@ export async function GET(
|
|||
const { teamId, userId } = await params;
|
||||
|
||||
if (!(await canUpdateTeam(auth, teamId))) {
|
||||
return unauthorized({ message: 'You must be the owner of this team.' });
|
||||
return unauthorized({ message: 'You must be the owner/manager of this team.' });
|
||||
}
|
||||
|
||||
const teamUser = await getTeamUser(teamId, userId);
|
||||
|
|
@ -30,7 +31,7 @@ export async function POST(
|
|||
{ params }: { params: Promise<{ teamId: string; userId: string }> },
|
||||
) {
|
||||
const schema = z.object({
|
||||
role: z.string().regex(/team-member|team-view-only|team-manager/),
|
||||
role: teamRoleParam,
|
||||
});
|
||||
|
||||
const { auth, body, error } = await parseRequest(request, schema);
|
||||
|
|
@ -42,7 +43,7 @@ export async function POST(
|
|||
const { teamId, userId } = await params;
|
||||
|
||||
if (!(await canUpdateTeam(auth, teamId))) {
|
||||
return unauthorized({ message: 'You must be the owner of this team.' });
|
||||
return unauthorized({ message: 'You must be the owner/manager of this team.' });
|
||||
}
|
||||
|
||||
const teamUser = await getTeamUser(teamId, userId);
|
||||
|
|
@ -69,7 +70,7 @@ export async function DELETE(
|
|||
const { teamId, userId } = await params;
|
||||
|
||||
if (!(await canDeleteTeamUser(auth, teamId, userId))) {
|
||||
return unauthorized({ message: 'You must be the owner of this team.' });
|
||||
return unauthorized({ message: 'You must be the owner/manager of this team.' });
|
||||
}
|
||||
|
||||
const teamUser = await getTeamUser(teamId, userId);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { z } from 'zod';
|
||||
import { unauthorized, json, badRequest } from '@/lib/response';
|
||||
import { canAddUserToTeam, canViewTeam } from '@/permissions';
|
||||
import { getQueryFilters, parseRequest } from '@/lib/request';
|
||||
import { pagingParams, teamRoleParam, searchParams } from '@/lib/schema';
|
||||
import { badRequest, json, unauthorized } from '@/lib/response';
|
||||
import { pagingParams, searchParams, teamRoleParam } from '@/lib/schema';
|
||||
import { canUpdateTeam, canViewTeam } from '@/permissions';
|
||||
import { createTeamUser, getTeamUser, getTeamUsers } from '@/queries/prisma';
|
||||
import { z } from 'zod';
|
||||
|
||||
export async function GET(request: Request, { params }: { params: Promise<{ teamId: string }> }) {
|
||||
const schema = z.object({
|
||||
|
|
@ -20,7 +20,7 @@ export async function GET(request: Request, { params }: { params: Promise<{ team
|
|||
const { teamId } = await params;
|
||||
|
||||
if (!(await canViewTeam(auth, teamId))) {
|
||||
return unauthorized({ message: 'You must be the owner of this team.' });
|
||||
return unauthorized({ message: 'You must be a member of this team.' });
|
||||
}
|
||||
|
||||
const filters = await getQueryFilters(query);
|
||||
|
|
@ -65,8 +65,8 @@ export async function POST(request: Request, { params }: { params: Promise<{ tea
|
|||
|
||||
const { teamId } = await params;
|
||||
|
||||
if (!(await canAddUserToTeam(auth))) {
|
||||
return unauthorized();
|
||||
if (!(await canUpdateTeam(auth, teamId))) {
|
||||
return unauthorized({ message: 'You must be the owner/manager of this team.' });
|
||||
}
|
||||
|
||||
const { userId, role } = body;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ export async function GET(
|
|||
{ params }: { params: Promise<{ websiteId: string }> },
|
||||
) {
|
||||
const schema = z.object({
|
||||
compare: z.string().optional(),
|
||||
...dateRangeParams,
|
||||
...filterParams,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ export function useWebsiteExpandedMetricsQuery(
|
|||
options?: ReactQueryOptions<WebsiteExpandedMetricsData>,
|
||||
) {
|
||||
const { get, useQuery } = useApi();
|
||||
const date = useDateParameters();
|
||||
const { startAt, endAt, unit, timezone } = useDateParameters();
|
||||
const filters = useFilterParameters();
|
||||
|
||||
return useQuery<WebsiteExpandedMetricsData>({
|
||||
|
|
@ -27,14 +27,20 @@ export function useWebsiteExpandedMetricsQuery(
|
|||
'websites:metrics:expanded',
|
||||
{
|
||||
websiteId,
|
||||
...date,
|
||||
startAt,
|
||||
endAt,
|
||||
unit,
|
||||
timezone,
|
||||
...filters,
|
||||
...params,
|
||||
},
|
||||
],
|
||||
queryFn: async () =>
|
||||
get(`/websites/${websiteId}/metrics/expanded`, {
|
||||
...date,
|
||||
startAt,
|
||||
endAt,
|
||||
unit,
|
||||
timezone,
|
||||
...filters,
|
||||
...params,
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -6,15 +6,21 @@ import { useFilterParameters } from '@/components/hooks/useFilterParameters';
|
|||
export function useWeeklyTrafficQuery(websiteId: string, params?: Record<string, string | number>) {
|
||||
const { get, useQuery } = useApi();
|
||||
const { modified } = useModified(`sessions`);
|
||||
const date = useDateParameters();
|
||||
const { startAt, endAt, unit, timezone } = useDateParameters();
|
||||
const filters = useFilterParameters();
|
||||
|
||||
return useQuery({
|
||||
queryKey: ['sessions', { websiteId, modified, ...params, ...date, ...filters }],
|
||||
queryKey: [
|
||||
'sessions',
|
||||
{ websiteId, modified, startAt, endAt, unit, timezone, ...params, ...filters },
|
||||
],
|
||||
queryFn: () => {
|
||||
return get(`/websites/${websiteId}/sessions/weekly`, {
|
||||
startAt,
|
||||
endAt,
|
||||
unit,
|
||||
timezone,
|
||||
...params,
|
||||
...date,
|
||||
...filters,
|
||||
});
|
||||
},
|
||||
|
|
|
|||
|
|
@ -39,10 +39,6 @@ export async function canDeleteTeam({ user }: Auth, teamId: string) {
|
|||
return teamUser && hasPermission(teamUser.role, PERMISSIONS.teamDelete);
|
||||
}
|
||||
|
||||
export async function canAddUserToTeam({ user }: Auth) {
|
||||
return user.isAdmin;
|
||||
}
|
||||
|
||||
export async function canDeleteTeamUser({ user }: Auth, teamId: string, removeUserId: string) {
|
||||
if (user.isAdmin) {
|
||||
return true;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue