mirror of
https://github.com/umami-software/umami.git
synced 2026-02-17 11:05:36 +01:00
Boards components.
Some checks failed
Node.js CI / build (postgresql, 18.18, 10) (push) Has been cancelled
Some checks failed
Node.js CI / build (postgresql, 18.18, 10) (push) Has been cancelled
This commit is contained in:
parent
7edddf15a7
commit
a39ebffd8b
20 changed files with 450 additions and 33 deletions
78
src/app/api/boards/[boardId]/route.ts
Normal file
78
src/app/api/boards/[boardId]/route.ts
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
import { z } from 'zod';
|
||||
import { SHARE_ID_REGEX } from '@/lib/constants';
|
||||
import { parseRequest } from '@/lib/request';
|
||||
import { badRequest, json, ok, serverError, unauthorized } from '@/lib/response';
|
||||
import { canDeleteBoard, canUpdateBoard, canViewBoard } from '@/permissions';
|
||||
import { deleteBoard, getBoard, updateBoard } from '@/queries/prisma';
|
||||
|
||||
export async function GET(request: Request, { params }: { params: Promise<{ boardId: string }> }) {
|
||||
const { auth, error } = await parseRequest(request);
|
||||
|
||||
if (error) {
|
||||
return error();
|
||||
}
|
||||
|
||||
const { boardId } = await params;
|
||||
|
||||
if (!(await canViewBoard(auth, boardId))) {
|
||||
return unauthorized();
|
||||
}
|
||||
|
||||
const board = await getBoard(boardId);
|
||||
|
||||
return json(board);
|
||||
}
|
||||
|
||||
export async function POST(request: Request, { params }: { params: Promise<{ boardId: string }> }) {
|
||||
const schema = z.object({
|
||||
name: z.string().optional(),
|
||||
domain: z.string().optional(),
|
||||
shareId: z.string().regex(SHARE_ID_REGEX).nullable().optional(),
|
||||
});
|
||||
|
||||
const { auth, body, error } = await parseRequest(request, schema);
|
||||
|
||||
if (error) {
|
||||
return error();
|
||||
}
|
||||
|
||||
const { boardId } = await params;
|
||||
const { name, domain, shareId } = body;
|
||||
|
||||
if (!(await canUpdateBoard(auth, boardId))) {
|
||||
return unauthorized();
|
||||
}
|
||||
|
||||
try {
|
||||
const board = await updateBoard(boardId, { name, domain, shareId });
|
||||
|
||||
return Response.json(board);
|
||||
} catch (e: any) {
|
||||
if (e.message.toLowerCase().includes('unique constraint') && e.message.includes('slug')) {
|
||||
return badRequest({ message: 'That slug is already taken.' });
|
||||
}
|
||||
|
||||
return serverError(e);
|
||||
}
|
||||
}
|
||||
|
||||
export async function DELETE(
|
||||
request: Request,
|
||||
{ params }: { params: Promise<{ boardId: string }> },
|
||||
) {
|
||||
const { auth, error } = await parseRequest(request);
|
||||
|
||||
if (error) {
|
||||
return error();
|
||||
}
|
||||
|
||||
const { boardId } = await params;
|
||||
|
||||
if (!(await canDeleteBoard(auth, boardId))) {
|
||||
return unauthorized();
|
||||
}
|
||||
|
||||
await deleteBoard(boardId);
|
||||
|
||||
return ok();
|
||||
}
|
||||
61
src/app/api/boards/route.ts
Normal file
61
src/app/api/boards/route.ts
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
import { z } from 'zod';
|
||||
import { uuid } from '@/lib/crypto';
|
||||
import { getQueryFilters, parseRequest } from '@/lib/request';
|
||||
import { json, unauthorized } from '@/lib/response';
|
||||
import { pagingParams, searchParams } from '@/lib/schema';
|
||||
import { canCreateTeamWebsite, canCreateWebsite } from '@/permissions';
|
||||
import { createBoard, getUserBoards } from '@/queries/prisma';
|
||||
|
||||
export async function GET(request: Request) {
|
||||
const schema = z.object({
|
||||
...pagingParams,
|
||||
...searchParams,
|
||||
});
|
||||
|
||||
const { auth, query, error } = await parseRequest(request, schema);
|
||||
|
||||
if (error) {
|
||||
return error();
|
||||
}
|
||||
|
||||
const filters = await getQueryFilters(query);
|
||||
|
||||
const boards = await getUserBoards(auth.user.id, filters);
|
||||
|
||||
return json(boards);
|
||||
}
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const schema = z.object({
|
||||
type: z.string(),
|
||||
name: z.string().max(100),
|
||||
description: z.string().max(500).optional(),
|
||||
slug: z.string().max(100),
|
||||
userId: z.uuid().nullable().optional(),
|
||||
teamId: z.uuid().nullable().optional(),
|
||||
});
|
||||
|
||||
const { auth, body, error } = await parseRequest(request, schema);
|
||||
|
||||
if (error) {
|
||||
return error();
|
||||
}
|
||||
|
||||
const { teamId } = body;
|
||||
|
||||
if ((teamId && !(await canCreateTeamWebsite(auth, teamId))) || !(await canCreateWebsite(auth))) {
|
||||
return unauthorized();
|
||||
}
|
||||
|
||||
const data = {
|
||||
...body,
|
||||
id: uuid(),
|
||||
parameters: {},
|
||||
slug: uuid(),
|
||||
userId: !teamId ? auth.user.id : undefined,
|
||||
};
|
||||
|
||||
const result = await createBoard(data);
|
||||
|
||||
return json(result);
|
||||
}
|
||||
29
src/app/api/teams/[teamId]/boards/route.ts
Normal file
29
src/app/api/teams/[teamId]/boards/route.ts
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
import { z } from 'zod';
|
||||
import { getQueryFilters, parseRequest } from '@/lib/request';
|
||||
import { json, unauthorized } from '@/lib/response';
|
||||
import { pagingParams, searchParams } from '@/lib/schema';
|
||||
import { canViewTeam } from '@/permissions';
|
||||
import { getTeamPixels } from '@/queries/prisma';
|
||||
|
||||
export async function GET(request: Request, { params }: { params: Promise<{ teamId: string }> }) {
|
||||
const schema = z.object({
|
||||
...pagingParams,
|
||||
...searchParams,
|
||||
});
|
||||
const { teamId } = await params;
|
||||
const { auth, query, error } = await parseRequest(request, schema);
|
||||
|
||||
if (error) {
|
||||
return error();
|
||||
}
|
||||
|
||||
if (!(await canViewTeam(auth, teamId))) {
|
||||
return unauthorized();
|
||||
}
|
||||
|
||||
const filters = await getQueryFilters(query);
|
||||
|
||||
const websites = await getTeamPixels(teamId, filters);
|
||||
|
||||
return json(websites);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue