mirror of
https://github.com/umami-software/umami.git
synced 2025-12-08 05:12:36 +01:00
add api routes for segments
This commit is contained in:
parent
f61421b742
commit
8408bbd25c
6 changed files with 11066 additions and 134 deletions
|
|
@ -1,91 +0,0 @@
|
||||||
import { z } from 'zod';
|
|
||||||
import { parseRequest } from '@/lib/request';
|
|
||||||
import { deleteReport, getReport, updateReport } from '@/queries';
|
|
||||||
import { canDeleteReport, canUpdateReport, canViewReport } from '@/lib/auth';
|
|
||||||
import { unauthorized, json, notFound, ok } from '@/lib/response';
|
|
||||||
import { reportTypeParam } from '@/lib/schema';
|
|
||||||
|
|
||||||
export async function GET(request: Request, { params }: { params: Promise<{ reportId: string }> }) {
|
|
||||||
const { auth, error } = await parseRequest(request);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return error();
|
|
||||||
}
|
|
||||||
|
|
||||||
const { reportId } = await params;
|
|
||||||
|
|
||||||
const report = await getReport(reportId);
|
|
||||||
|
|
||||||
if (!(await canViewReport(auth, report))) {
|
|
||||||
return unauthorized();
|
|
||||||
}
|
|
||||||
|
|
||||||
report.parameters = JSON.parse(report.parameters);
|
|
||||||
|
|
||||||
return json(report);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function POST(
|
|
||||||
request: Request,
|
|
||||||
{ params }: { params: Promise<{ reportId: string }> },
|
|
||||||
) {
|
|
||||||
const schema = z.object({
|
|
||||||
websiteId: z.string().uuid(),
|
|
||||||
type: reportTypeParam,
|
|
||||||
name: z.string().max(200),
|
|
||||||
description: z.string().max(500),
|
|
||||||
parameters: z.object({}).passthrough(),
|
|
||||||
});
|
|
||||||
|
|
||||||
const { auth, body, error } = await parseRequest(request, schema);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return error();
|
|
||||||
}
|
|
||||||
|
|
||||||
const { reportId } = await params;
|
|
||||||
const { websiteId, type, name, description, parameters } = body;
|
|
||||||
|
|
||||||
const report = await getReport(reportId);
|
|
||||||
|
|
||||||
if (!report) {
|
|
||||||
return notFound();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(await canUpdateReport(auth, report))) {
|
|
||||||
return unauthorized();
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await updateReport(reportId, {
|
|
||||||
websiteId,
|
|
||||||
userId: auth.user.id,
|
|
||||||
type,
|
|
||||||
name,
|
|
||||||
description,
|
|
||||||
parameters: JSON.stringify(parameters),
|
|
||||||
} as any);
|
|
||||||
|
|
||||||
return json(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function DELETE(
|
|
||||||
request: Request,
|
|
||||||
{ params }: { params: Promise<{ reportId: string }> },
|
|
||||||
) {
|
|
||||||
const { auth, error } = await parseRequest(request);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return error();
|
|
||||||
}
|
|
||||||
|
|
||||||
const { reportId } = await params;
|
|
||||||
const report = await getReport(reportId);
|
|
||||||
|
|
||||||
if (!(await canDeleteReport(auth, report))) {
|
|
||||||
return unauthorized();
|
|
||||||
}
|
|
||||||
|
|
||||||
await deleteReport(reportId);
|
|
||||||
|
|
||||||
return ok();
|
|
||||||
}
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
import { z } from 'zod';
|
|
||||||
import { hashPassword, canCreateUser } from '@/lib/auth';
|
|
||||||
import { ROLES } from '@/lib/constants';
|
|
||||||
import { uuid } from '@/lib/crypto';
|
|
||||||
import { parseRequest } from '@/lib/request';
|
|
||||||
import { unauthorized, json, badRequest } from '@/lib/response';
|
|
||||||
import { createUser, getUserByUsername } from '@/queries';
|
|
||||||
|
|
||||||
export async function POST(request: Request) {
|
|
||||||
const schema = z.object({
|
|
||||||
id: z.string().uuid().optional(),
|
|
||||||
username: z.string().max(255),
|
|
||||||
password: z.string(),
|
|
||||||
role: z.string().regex(/admin|user|view-only/i),
|
|
||||||
});
|
|
||||||
|
|
||||||
const { auth, body, error } = await parseRequest(request, schema);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return error();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(await canCreateUser(auth))) {
|
|
||||||
return unauthorized();
|
|
||||||
}
|
|
||||||
|
|
||||||
const { id, username, password, role } = body;
|
|
||||||
|
|
||||||
const existingUser = await getUserByUsername(username, { showDeleted: true });
|
|
||||||
|
|
||||||
if (existingUser) {
|
|
||||||
return badRequest('User already exists');
|
|
||||||
}
|
|
||||||
|
|
||||||
const user = await createUser({
|
|
||||||
id: id || uuid(),
|
|
||||||
username,
|
|
||||||
password: hashPassword(password),
|
|
||||||
role: role ?? ROLES.user,
|
|
||||||
});
|
|
||||||
|
|
||||||
return json(user);
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,92 @@
|
||||||
|
import { canDeleteWebsite, canUpdateWebsite, canViewWebsite } from '@/lib/auth';
|
||||||
|
import { parseRequest } from '@/lib/request';
|
||||||
|
import { json, notFound, ok, unauthorized } from '@/lib/response';
|
||||||
|
import { segmentTypeParam } from '@/lib/schema';
|
||||||
|
import { deleteSegment, getSegment, updateSegment } from '@/queries';
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
export async function GET(
|
||||||
|
request: Request,
|
||||||
|
{ params }: { params: Promise<{ websiteId: string; segmentId: string }> },
|
||||||
|
) {
|
||||||
|
const { auth, error } = await parseRequest(request);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return error();
|
||||||
|
}
|
||||||
|
|
||||||
|
const { websiteId, segmentId } = await params;
|
||||||
|
|
||||||
|
const segment = await getSegment(segmentId);
|
||||||
|
|
||||||
|
if (websiteId && !(await canViewWebsite(auth, websiteId))) {
|
||||||
|
return unauthorized();
|
||||||
|
}
|
||||||
|
|
||||||
|
return json(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function POST(
|
||||||
|
request: Request,
|
||||||
|
{ params }: { params: Promise<{ websiteId: string; segmentId: string }> },
|
||||||
|
) {
|
||||||
|
const schema = z.object({
|
||||||
|
type: segmentTypeParam,
|
||||||
|
name: z.string().max(200),
|
||||||
|
filters: z.object({}).passthrough(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const { auth, body, error } = await parseRequest(request, schema);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return error();
|
||||||
|
}
|
||||||
|
|
||||||
|
const { websiteId, segmentId } = await params;
|
||||||
|
const { type, name, filters } = body;
|
||||||
|
|
||||||
|
const segment = await getSegment(segmentId);
|
||||||
|
|
||||||
|
if (!segment) {
|
||||||
|
return notFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(await canUpdateWebsite(auth, websiteId))) {
|
||||||
|
return unauthorized();
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await updateSegment(segmentId, {
|
||||||
|
type,
|
||||||
|
name,
|
||||||
|
filters,
|
||||||
|
} as any);
|
||||||
|
|
||||||
|
return json(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function DELETE(
|
||||||
|
request: Request,
|
||||||
|
{ params }: { params: Promise<{ websiteId: string; segmentId: string }> },
|
||||||
|
) {
|
||||||
|
const { auth, error } = await parseRequest(request);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return error();
|
||||||
|
}
|
||||||
|
|
||||||
|
const { websiteId, segmentId } = await params;
|
||||||
|
|
||||||
|
const segment = await getSegment(segmentId);
|
||||||
|
|
||||||
|
if (!segment) {
|
||||||
|
return notFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(await canDeleteWebsite(auth, websiteId))) {
|
||||||
|
return unauthorized();
|
||||||
|
}
|
||||||
|
|
||||||
|
await deleteSegment(segmentId);
|
||||||
|
|
||||||
|
return ok();
|
||||||
|
}
|
||||||
67
src/app/api/websites/[websiteId]/segments/route.ts
Normal file
67
src/app/api/websites/[websiteId]/segments/route.ts
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
import { canUpdateWebsite, canViewWebsite } from '@/lib/auth';
|
||||||
|
import { uuid } from '@/lib/crypto';
|
||||||
|
import { parseRequest } from '@/lib/request';
|
||||||
|
import { json, unauthorized } from '@/lib/response';
|
||||||
|
import { segmentTypeParam } from '@/lib/schema';
|
||||||
|
import { createSegment, getWebsiteSegments } from '@/queries';
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
export async function GET(
|
||||||
|
request: Request,
|
||||||
|
{ params }: { params: Promise<{ websiteId: string }> },
|
||||||
|
) {
|
||||||
|
const schema = z.object({
|
||||||
|
type: segmentTypeParam,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { auth, query, error } = await parseRequest(request, schema);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return error();
|
||||||
|
}
|
||||||
|
|
||||||
|
const { websiteId } = await params;
|
||||||
|
const { type } = query;
|
||||||
|
|
||||||
|
if (websiteId && !(await canViewWebsite(auth, websiteId))) {
|
||||||
|
return unauthorized();
|
||||||
|
}
|
||||||
|
|
||||||
|
const segments = await getWebsiteSegments(websiteId, type);
|
||||||
|
|
||||||
|
return json(segments);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function POST(
|
||||||
|
request: Request,
|
||||||
|
{ params }: { params: Promise<{ websiteId: string }> },
|
||||||
|
) {
|
||||||
|
const schema = z.object({
|
||||||
|
type: segmentTypeParam,
|
||||||
|
name: z.string().max(200),
|
||||||
|
filters: z.object({}).passthrough(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const { auth, body, error } = await parseRequest(request, schema);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return error();
|
||||||
|
}
|
||||||
|
|
||||||
|
const { websiteId } = await params;
|
||||||
|
const { type, name, filters } = body;
|
||||||
|
|
||||||
|
if (!(await canUpdateWebsite(auth, websiteId))) {
|
||||||
|
return unauthorized();
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await createSegment({
|
||||||
|
id: uuid(),
|
||||||
|
websiteId,
|
||||||
|
type,
|
||||||
|
name,
|
||||||
|
filters,
|
||||||
|
} as any);
|
||||||
|
|
||||||
|
return json(result);
|
||||||
|
}
|
||||||
|
|
@ -76,3 +76,5 @@ export const reportParms = {
|
||||||
value: z.string().optional(),
|
value: z.string().optional(),
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const segmentTypeParam = z.enum(['segment', 'cohort']);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue