From 722026c938e4268b1f7ec319a9995c877e5e941d Mon Sep 17 00:00:00 2001 From: bytedream <bytedream@protonmail.com> Date: Fri, 29 Sep 2023 02:08:34 +0200 Subject: [PATCH] add report admin panel --- src/lib/components/Input/Input.svelte | 2 +- src/lib/components/Input/Select.svelte | 6 +- src/lib/components/Input/Textarea.svelte | 10 +- src/lib/permissions.ts | 12 +- src/lib/server/database.ts | 23 +- src/lib/stores.ts | 1 + src/routes/admin/+layout.server.ts | 8 +- src/routes/admin/+layout.svelte | 16 +- src/routes/admin/reports/+page.server.ts | 17 ++ src/routes/admin/reports/+page.svelte | 229 ++++++++++++++++++ src/routes/admin/reports/+server.ts | 106 ++++++++ src/routes/report/+server.ts | 9 +- .../+layout.svelte | 0 .../+page.server.ts | 4 +- .../+page.svelte | 2 +- .../{[...url_id] => [...url_hash]}/+server.ts | 2 +- .../ReportCompleted.svelte | 0 .../ReportDraft.svelte | 2 +- .../ReportSubmitted.svelte | 0 19 files changed, 423 insertions(+), 26 deletions(-) create mode 100644 src/routes/admin/reports/+page.server.ts create mode 100644 src/routes/admin/reports/+page.svelte create mode 100644 src/routes/admin/reports/+server.ts rename src/routes/report/{[...url_id] => [...url_hash]}/+layout.svelte (100%) rename src/routes/report/{[...url_id] => [...url_hash]}/+page.server.ts (90%) rename src/routes/report/{[...url_id] => [...url_hash]}/+page.svelte (95%) rename src/routes/report/{[...url_id] => [...url_hash]}/+server.ts (80%) rename src/routes/report/{[...url_id] => [...url_hash]}/ReportCompleted.svelte (100%) rename src/routes/report/{[...url_id] => [...url_hash]}/ReportDraft.svelte (99%) rename src/routes/report/{[...url_id] => [...url_hash]}/ReportSubmitted.svelte (100%) diff --git a/src/lib/components/Input/Input.svelte b/src/lib/components/Input/Input.svelte index b65d5b0..2764ed3 100644 --- a/src/lib/components/Input/Input.svelte +++ b/src/lib/components/Input/Input.svelte @@ -4,7 +4,7 @@ export let id: string | null = null; export let name: string | null = null; - export let type: string; + export let type = 'text'; export let value: string | null = null; export let placeholder: string | null = null; export let required = false; diff --git a/src/lib/components/Input/Select.svelte b/src/lib/components/Input/Select.svelte index 19f9c98..f7c1f1a 100644 --- a/src/lib/components/Input/Select.svelte +++ b/src/lib/components/Input/Select.svelte @@ -1,7 +1,9 @@ <script lang="ts"> - export let id: string; + import { createEventDispatcher } from 'svelte'; + + export let id: string | null = null; export let name: string | null = null; - export let value: string | null = null; + export let value: any | null = null; export let label: string | null = null; export let notice: string | null = null; export let required = false; diff --git a/src/lib/components/Input/Textarea.svelte b/src/lib/components/Input/Textarea.svelte index c5583d1..7ee8e14 100644 --- a/src/lib/components/Input/Textarea.svelte +++ b/src/lib/components/Input/Textarea.svelte @@ -1,4 +1,6 @@ <script lang="ts"> + import { createEventDispatcher } from 'svelte'; + export let id: string | null = null; export let name: string | null = null; export let value: string | null = null; @@ -6,8 +8,11 @@ export let notice: string | null = null; export let required = false; export let disabled = false; + export let readonly = false; export let size: 'xs' | 'sm' | 'md' | 'lg' = 'md'; export let rows = 2; + + const dispatch = createEventDispatcher(); </script> <div> @@ -22,17 +27,20 @@ </label> {/if} <textarea - class="textarea textarea-bordered w-full" + class="textarea w-full" class:textarea-xs={size === 'xs'} class:textarea-sm={size === 'sm'} class:textarea-md={size === 'md'} class:textarea-lg={size === 'lg'} + class:textarea-bordered={!readonly} {id} {name} {required} {disabled} + {readonly} {rows} bind:value + on:click={(e) => dispatch('click', e)} /> {#if notice} <label class="label" for={id}> diff --git a/src/lib/permissions.ts b/src/lib/permissions.ts index 6e96bb8..d6d4238 100644 --- a/src/lib/permissions.ts +++ b/src/lib/permissions.ts @@ -3,6 +3,8 @@ export class Permissions { static readonly AdminWrite = 4; static readonly UserRead = 8; static readonly UserWrite = 16; + static readonly ReportRead = 32; + static readonly ReportWrite = 64; readonly value: number; @@ -29,7 +31,9 @@ export class Permissions { Permissions.AdminRead, Permissions.AdminWrite, Permissions.UserRead, - Permissions.UserWrite + Permissions.UserWrite, + Permissions.ReportRead, + Permissions.ReportWrite ]; } @@ -45,6 +49,12 @@ export class Permissions { userWrite(): boolean { return (this.value & Permissions.UserWrite) != 0; } + reportRead(): boolean { + return (this.value & Permissions.ReportRead) != 0; + } + reportWrite(): boolean { + return (this.value & Permissions.ReportWrite) != 0; + } asArray(): number[] { const array = []; diff --git a/src/lib/server/database.ts b/src/lib/server/database.ts index 0325a46..4f293c3 100644 --- a/src/lib/server/database.ts +++ b/src/lib/server/database.ts @@ -40,26 +40,35 @@ export class User extends Model { export class Report extends Model { @Column({ type: DataTypes.STRING, allowNull: false, unique: true }) @Index - declare url_id: string; + declare url_hash: string; @Column({ type: DataTypes.STRING, allowNull: false }) declare subject: string; @Column({ type: DataTypes.STRING }) declare body: string; @Column({ type: DataTypes.BOOLEAN, allowNull: false }) declare draft: boolean; - @Column({ type: DataTypes.BOOLEAN, allowNull: false }) - declare completed: boolean; + @Column({ type: DataTypes.ENUM('java', 'bedrock', 'cracked'), allowNull: false }) + declare status: 'none' | 'review' | 'reviewed'; + @Column({ type: DataTypes.STRING }) + declare notice: string; + @Column({ type: DataTypes.STRING }) + declare statement: string; @Column({ type: DataTypes.INTEGER, allowNull: false }) @ForeignKey(() => User) - declare reporter_user_id: number; + declare reporter_id: number; @Column({ type: DataTypes.INTEGER, allowNull: false }) @ForeignKey(() => User) - declare reported_user_id: number; + declare reported_id: number; + @Column({ type: DataTypes.INTEGER }) + @ForeignKey(() => Admin) + declare auditor_id: number; - @BelongsTo(() => User) + @BelongsTo(() => User, 'reporter_id') declare reporter: User; - @BelongsTo(() => User) + @BelongsTo(() => User, 'reported_id') declare reported: User; + @BelongsTo(() => Admin, 'auditor_id') + declare auditor: Admin; } @Table({ modelName: 'admin', underscored: true }) diff --git a/src/lib/stores.ts b/src/lib/stores.ts index 67598cd..cdf8bcd 100644 --- a/src/lib/stores.ts +++ b/src/lib/stores.ts @@ -4,4 +4,5 @@ import { writable } from 'svelte/store'; export const playAudio: Writable<boolean> = persisted('playAudio', false); +export const reportCount: Writable<number> = writable(0); export const adminCount: Writable<number> = writable(0); diff --git a/src/routes/admin/+layout.server.ts b/src/routes/admin/+layout.server.ts index fc357e3..878fc49 100644 --- a/src/routes/admin/+layout.server.ts +++ b/src/routes/admin/+layout.server.ts @@ -1,5 +1,5 @@ import type { LayoutServerLoad } from './$types'; -import { Admin, User } from '$lib/server/database'; +import { Admin, Report, User } from '$lib/server/database'; import { getSession } from '$lib/server/session'; import { redirect } from '@sveltejs/kit'; import { env } from '$env/dynamic/public'; @@ -12,6 +12,10 @@ export const load: LayoutServerLoad = async ({ route, cookies }) => { return { userCount: session?.permissions.userRead() ? await User.count() : null, - adminCount: session?.permissions.adminRead() ? await Admin.count() : null + reportCount: session?.permissions.reportRead() + ? await Report.count({ where: { draft: false, status: ['none', 'review'] } }) + : null, + adminCount: session?.permissions.adminRead() ? await Admin.count() : null, + self: session ? await Admin.findOne({ where: { id: session.userId } }) : null }; }; diff --git a/src/routes/admin/+layout.svelte b/src/routes/admin/+layout.svelte index 97dc7e9..bab7137 100644 --- a/src/routes/admin/+layout.svelte +++ b/src/routes/admin/+layout.svelte @@ -5,7 +5,7 @@ import { buttonTriggeredRequest } from '$lib/components/utils'; import { goto } from '$app/navigation'; import type { LayoutData } from './$types'; - import { adminCount } from '$lib/stores'; + import { adminCount, reportCount } from '$lib/stores'; async function logout() { const response = await fetch(`${env.PUBLIC_BASE_PATH}/admin/logout`, { @@ -19,11 +19,12 @@ } export let data: LayoutData; + if (data.reportCount) $reportCount = data.reportCount; if (data.adminCount) $adminCount = data.adminCount; </script> {#if $page.url.pathname !== `${env.PUBLIC_BASE_PATH}/admin/login`} - <div class="flex h-screen"> + <div class="flex h-screen w-screen"> <div class="h-full"> <ul class="menu p-4 w-max h-full bg-base-200 text-base-content"> {#if data.userCount != null} @@ -35,6 +36,15 @@ </a> </li> {/if} + {#if data.reportCount != null} + <li> + <a href="{env.PUBLIC_BASE_PATH}/admin/reports"> + <IconOutline name="flag-outline" /> + <span class="ml-1">Reports</span> + <div class="badge">{$reportCount}</div> + </a> + </li> + {/if} {#if data.adminCount != null} <li> <a href="{env.PUBLIC_BASE_PATH}/admin/admin"> @@ -52,7 +62,7 @@ </li> </ul> </div> - <div class="h-full w-full overflow-scroll"> + <div class="h-full w-full overflow-y-scroll overflow-x-hidden"> <slot /> </div> </div> diff --git a/src/routes/admin/reports/+page.server.ts b/src/routes/admin/reports/+page.server.ts new file mode 100644 index 0000000..9023020 --- /dev/null +++ b/src/routes/admin/reports/+page.server.ts @@ -0,0 +1,17 @@ +import type { PageServerLoad } from './$types'; +import { redirect } from '@sveltejs/kit'; +import { env } from '$env/dynamic/public'; +import { getSession } from '$lib/server/session'; +import { Permissions } from '$lib/permissions'; + +export const load: PageServerLoad = async ({ parent, cookies }) => { + const { reportCount } = await parent(); + if (reportCount == null) throw redirect(302, `${env.PUBLIC_BASE_PATH}/admin`); + + const { self } = await parent(); + + return { + count: getSession(cookies, { permissions: [Permissions.UserRead] }) != null ? reportCount : 0, + self: self + }; +}; diff --git a/src/routes/admin/reports/+page.svelte b/src/routes/admin/reports/+page.svelte new file mode 100644 index 0000000..e667846 --- /dev/null +++ b/src/routes/admin/reports/+page.svelte @@ -0,0 +1,229 @@ +<script lang="ts"> + import { fly } from 'svelte/transition'; + import type { PageData } from './$types'; + import type { Report } from '$lib/server/database'; + import { browser } from '$app/environment'; + import { env } from '$env/dynamic/public'; + import Select from '$lib/components/Input/Select.svelte'; + import Input from '$lib/components/Input/Input.svelte'; + import Textarea from '$lib/components/Input/Textarea.svelte'; + import { reportCount } from '$lib/stores'; + + export let data: PageData; + + let currentPageReports: (typeof Report.prototype.dataValues)[] = []; + let reportsPerPage = 50; + let reportPage = 0; + let reportFilter = { draft: false, status: null, reporter: null, reported: null }; + let activeReport: typeof Report.prototype.dataValues | null = null; + + async function fetchPageReports( + page: number, + filter: any + ): Promise<(typeof Report.prototype.dataValues)[]> { + if (!browser) return []; + + const response = await fetch(`${env.PUBLIC_BASE_PATH}/admin/reports`, { + method: 'POST', + body: JSON.stringify({ ...filter, limit: reportsPerPage, from: reportPage * page }) + }); + + return await response.json(); + } + + $: fetchPageReports(reportPage, reportFilter).then((r) => (currentPageReports = r)); + + async function updateActiveReport() { + await fetch(`${env.PUBLIC_BASE_PATH}/admin/reports`, { + method: 'PATCH', + body: JSON.stringify({ + id: activeReport.id, + auditor: data.self?.id || -1, + notice: activeReport.notice || '', + statement: activeReport.statement || '', + status: activeReport.status + }) + }); + } + + let saveActiveReportChangesModal: HTMLDialogElement; +</script> + +<div class="h-screen flex flex-row"> + <div class="w-full flex flex-col"> + <form class="flex flex-row justify-center space-x-4 mx-4 my-2"> + <Input size="sm" placeholder="Alle" bind:value={reportFilter.reporter}> + <span slot="label">Report Ersteller</span> + </Input> + <Input size="sm" placeholder="Alle" bind:value={reportFilter.reported}> + <span slot="label">Reportete Spieler</span> + </Input> + <Select label="Bearbeitungsstatus" size="sm" bind:value={reportFilter.status}> + <option value="none">Unbearbeitet</option> + <option value="review">In Bearbeitung</option> + <option value={null}>Unbearbeitet & In Bearbeitung</option> + <option value="reviewed">Bearbeitet</option> + </Select> + <Select label="Reportstatus" size="sm" bind:value={reportFilter.draft}> + <option value={false}>Erstellt</option> + <option value={true}>Entwurf</option> + <option value={null}>Erstellt & Entwurf</option> + </Select> + </form> + <hr class="divider my-1 mx-8 border-none" /> + <table class="table table-fixed h-fit"> + <colgroup> + <col style="width: 20%" /> + <col style="width: 15%" /> + <col style="width: 15%" /> + <col style="width: 20%" /> + <col style="width: 15%" /> + <col style="width: 15%" /> + </colgroup> + <thead> + <tr> + <th>Grund</th> + <th>Ersteller</th> + <th>Reporteter User</th> + <th>Datum</th> + <th>Bearbeitungsstatus</th> + <th>Reportstatus</th> + </tr> + </thead> + <tbody> + {#each currentPageReports as report} + <tr + class="hover [&>*]:text-sm cursor-pointer" + class:bg-base-200={activeReport === report} + on:click={() => { + activeReport = report; + activeReport.originalStatus = report.status; + }} + > + <td title={report.subject}><div class="overflow-scroll">{report.subject}</div></td> + <td>{report.reporter.username}</td> + <td>{report.reported.username}</td> + <td + >{new Intl.DateTimeFormat('de-DE', { + year: 'numeric', + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit' + }).format(new Date(report.createdAt))} Uhr</td + > + <td> + {report.status === 'none' + ? 'Unbearbeitet' + : report.status === 'review' + ? 'In Bearbeitung' + : report.status === 'reviewed' + ? 'Bearbeitet' + : ''} + </td> + <td>{report.draft ? 'Entwurf' : 'Erstellt'}</td> + </tr> + {/each} + </tbody> + </table> + </div> + {#if activeReport} + <div + class="relative flex flex-col w-2/5 bg-base-200/50 px-4 py-6 overflow-scroll" + transition:fly={{ x: 200, duration: 200 }} + > + <button + class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2" + on:click={() => (activeReport = null)}>✕</button + > + <h3 class="font-roboto font-semibold text-2xl">Report</h3> + <div class="break-words my-2"> + <i class="font-medium">{activeReport.reporter.username}</i> hat + <i class="font-medium">{activeReport.reported.username}</i> + am {new Intl.DateTimeFormat('de-DE', { + year: 'numeric', + month: 'long', + day: '2-digit', + hour: '2-digit', + minute: '2-digit' + }).format(new Date(activeReport.createdAt))} Uhr reportet. + </div> + <div class="w-full"> + <Textarea readonly={true} rows={1} label="Report Grund" value={activeReport.subject} /> + <Textarea readonly={true} rows={4} label="Report Details" value={activeReport.body} /> + </div> + <div class="divider mx-4" /> + <div> + <div + class="w-full" + title={activeReport.status === 'none' + ? 'Zum Bearbeiten den Bearbeitungsstatus ändern' + : ''} + > + <Textarea + label="Interne Notizen" + readonly={activeReport.auditor === null && activeReport.notice === null} + rows={1} + bind:value={activeReport.notice} + /> + </div> + <div + class="w-full" + title={activeReport.status === 'none' + ? 'Zum Bearbeiten den Bearbeitungsstatus ändern' + : ''} + > + <Textarea + label="(Öffentliche) Report Antwort" + readonly={activeReport.auditor === null && activeReport.notice === null} + rows={3} + bind:value={activeReport.statement} + /> + </div> + <Select label="Bearbeitungsstatus" size="sm" bind:value={activeReport.status}> + <option value="none" disabled={activeReport.auditor != null || activeReport.notice} + >Unbearbeitet</option + > + <option value="review">In Bearbeitung</option> + <option value="reviewed">Bearbeitet</option> + </Select> + </div> + <div class="self-end mt-auto pt-6 w-full flex justify-center"> + <Input + type="submit" + value="Speichern" + on:click={() => saveActiveReportChangesModal.show()} + /> + </div> + </div> + {/if} +</div> + +<dialog class="modal" bind:this={saveActiveReportChangesModal}> + <form method="dialog" class="modal-box"> + <button class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2">✕</button> + <h3 class="font-roboto text-xl">Änderungen Speichern?</h3> + <div class="flex flex-row space-x-2 mt-6"> + <Input + type="submit" + value="Speichern" + on:click={async () => { + await updateActiveReport(); + currentPageReports = [...currentPageReports]; + if (activeReport.originalStatus !== 'reviewed' && activeReport.status === 'reviewed') { + $reportCount -= 1; + } else if ( + activeReport.originalStatus === 'reviewed' && + activeReport.status !== 'reviewed' + ) { + $reportCount += 1; + } + }} + /> + <Input type="submit" value="Abbrechen" /> + </div> + </form> + <form method="dialog" class="modal-backdrop bg-[rgba(0,0,0,.3)]"> + <button>close</button> + </form> +</dialog> diff --git a/src/routes/admin/reports/+server.ts b/src/routes/admin/reports/+server.ts new file mode 100644 index 0000000..784d161 --- /dev/null +++ b/src/routes/admin/reports/+server.ts @@ -0,0 +1,106 @@ +import type { RequestHandler } from '@sveltejs/kit'; +import { getSession } from '$lib/server/session'; +import { Permissions } from '$lib/permissions'; +import { Admin, Report, User } from '$lib/server/database'; +import type { Attributes } from 'sequelize'; +import { Op } from 'sequelize'; +import { env } from '$env/dynamic/private'; + +export const POST = (async ({ request, cookies }) => { + if (getSession(cookies, { permissions: [Permissions.ReportRead] }) == null) { + return new Response(null, { + status: 401 + }); + } + + const data: { + limit: number | null; + from: number | null; + + draft: boolean | null; + status: 'none' | 'review' | 'reviewed' | null; + reporter: string | null; + reported: string | null; + } = await request.json(); + + const reportFindOptions: Attributes<Report> = {}; + if (data.draft != null) reportFindOptions.draft = data.draft; + reportFindOptions.status = data.status == null ? ['none', 'review'] : data.status; + if (data.reporter != null) { + const reporter_ids = await User.findAll({ + attributes: ['id'], + where: { username: { [Op.like]: `%${data.reporter}%` } } + }); + reportFindOptions.reporter_id = reporter_ids.map((u) => u.id); + } + if (data.reported != null) { + const reported_ids = await User.findAll({ + attributes: ['id'], + where: { username: { [Op.like]: `%${data.reported}%` } } + }); + reportFindOptions.reported_id = reported_ids.map((u) => u.id); + } + let reports = await Report.findAll({ + where: reportFindOptions, + include: [ + { model: User, as: 'reporter' }, + { model: User, as: 'reported' }, + { model: Admin, as: 'auditor' } + ], + order: ['created_at'], + offset: data.from || 0, + limit: data.limit || 100 + }); + reports = reports.map((r) => { + if (r.auditor_id === null && r.status != 'none') { + // if the report was edited by the admin account set by the env variable, it has no relation to the admin + // table in the database, so it gets manually created here. we just assume that the auditor_id is never null + // when not edited by the env admin account + r.auditor_id = -1; + r.dataValues.auditor = { + id: -1, + username: env.ADMIN_USER, + permissions: new Permissions(Permissions.allPermissions()), + createdAt: 0, + updatedAt: 0 + }; + } else if (r.auditor) { + delete r.dataValues.auditor.password; + } + return r; + }); + + return new Response(JSON.stringify(reports)); +}) satisfies RequestHandler; + +export const PATCH = (async ({ request, cookies }) => { + if (getSession(cookies, { permissions: [Permissions.ReportWrite] }) == null) { + return new Response(null, { + status: 401 + }); + } + + const data: { + id: number; + auditor: number; + notice: string | null; + statement: string | null; + status: 'none' | 'review' | 'reviewed' | null; + } = await request.json(); + + if (data.id === null || data.auditor === null) return new Response(null, { status: 400 }); + + const report = await Report.findOne({ where: { id: data.id } }); + const admin = await Admin.findOne({ where: { id: data.auditor } }); + if (report === null || (admin === null && data.auditor != -1)) + return new Response(null, { status: 400 }); + + if (data.notice != null) report.notice = data.notice; + if (data.statement != null) report.statement = data.statement; + if (data.status != null) report.status = data.status; + if (admin != null) report.auditor_id = admin.id; + + await report.save(); + + return new Response(); +}) satisfies RequestHandler; diff --git a/src/routes/report/+server.ts b/src/routes/report/+server.ts index cc026f3..9bc074f 100644 --- a/src/routes/report/+server.ts +++ b/src/routes/report/+server.ts @@ -17,14 +17,15 @@ export const POST = (async ({ request, url }) => { subject: data.reason, body: null, draft: true, - url_id: crypto.randomBytes(18).toString('hex'), + status: 'none', + url_hash: crypto.randomBytes(18).toString('hex'), completed: false, - reporter_user_id: reporter.id, - reported_user_id: reported.id + reporter_id: reporter.id, + reported_id: reported.id }); return new Response( - JSON.stringify({ url: `${url.toString().replace(/\/$/, '')}/${report.url_id}` }), + JSON.stringify({ url: `${url.toString().replace(/\/$/, '')}/${report.url_hash}` }), { status: 201 } diff --git a/src/routes/report/[...url_id]/+layout.svelte b/src/routes/report/[...url_hash]/+layout.svelte similarity index 100% rename from src/routes/report/[...url_id]/+layout.svelte rename to src/routes/report/[...url_hash]/+layout.svelte diff --git a/src/routes/report/[...url_id]/+page.server.ts b/src/routes/report/[...url_hash]/+page.server.ts similarity index 90% rename from src/routes/report/[...url_id]/+page.server.ts rename to src/routes/report/[...url_hash]/+page.server.ts index 22c71f4..139199f 100644 --- a/src/routes/report/[...url_id]/+page.server.ts +++ b/src/routes/report/[...url_hash]/+page.server.ts @@ -5,7 +5,7 @@ import { env } from '$env/dynamic/public'; export const load: PageServerLoad = async ({ params }) => { const report = await Report.findOne({ - where: { url_id: params.url_id }, + where: { url_hash: params.url_hash }, include: [ { model: User, as: 'reporter' }, { model: User, as: 'reported' } @@ -16,7 +16,7 @@ export const load: PageServerLoad = async ({ params }) => { return { draft: report.draft, - completed: report.completed, + status: report.status, reason: report.subject, reporter: { name: report.reporter.username diff --git a/src/routes/report/[...url_id]/+page.svelte b/src/routes/report/[...url_hash]/+page.svelte similarity index 95% rename from src/routes/report/[...url_id]/+page.svelte rename to src/routes/report/[...url_hash]/+page.svelte index dffb35c..6938b40 100644 --- a/src/routes/report/[...url_id]/+page.svelte +++ b/src/routes/report/[...url_hash]/+page.svelte @@ -22,7 +22,7 @@ on:submit={() => (data.draft = false)} /> </div> - {:else if data.completed} + {:else if data.status === 'reviewed'} <ReportCompleted /> {:else} <div class="col-[1] row-[1]" transition:fly={{ x: 200, duration: 300 }}> diff --git a/src/routes/report/[...url_id]/+server.ts b/src/routes/report/[...url_hash]/+server.ts similarity index 80% rename from src/routes/report/[...url_id]/+server.ts rename to src/routes/report/[...url_hash]/+server.ts index f51e70e..02cb0d9 100644 --- a/src/routes/report/[...url_id]/+server.ts +++ b/src/routes/report/[...url_hash]/+server.ts @@ -2,7 +2,7 @@ import type { RequestHandler } from '@sveltejs/kit'; import { Report } from '$lib/server/database'; export const POST = (async ({ params }) => { - const report = await Report.findOne({ where: { url_id: params.url_id } }); + const report = await Report.findOne({ where: { url_hash: params.url_hash } }); if (report == null) return new Response(null, { status: 400 }); diff --git a/src/routes/report/[...url_id]/ReportCompleted.svelte b/src/routes/report/[...url_hash]/ReportCompleted.svelte similarity index 100% rename from src/routes/report/[...url_id]/ReportCompleted.svelte rename to src/routes/report/[...url_hash]/ReportCompleted.svelte diff --git a/src/routes/report/[...url_id]/ReportDraft.svelte b/src/routes/report/[...url_hash]/ReportDraft.svelte similarity index 99% rename from src/routes/report/[...url_id]/ReportDraft.svelte rename to src/routes/report/[...url_hash]/ReportDraft.svelte index e3b8793..9bfdd3f 100644 --- a/src/routes/report/[...url_id]/ReportDraft.svelte +++ b/src/routes/report/[...url_hash]/ReportDraft.svelte @@ -9,7 +9,7 @@ export let reason: string; async function submitReport() { - await fetch(`${env.PUBLIC_BASE_PATH}/report/${$page.params.url_id}`, { + await fetch(`${env.PUBLIC_BASE_PATH}/report/${$page.params.url_hash}`, { method: 'POST' }); } diff --git a/src/routes/report/[...url_id]/ReportSubmitted.svelte b/src/routes/report/[...url_hash]/ReportSubmitted.svelte similarity index 100% rename from src/routes/report/[...url_id]/ReportSubmitted.svelte rename to src/routes/report/[...url_hash]/ReportSubmitted.svelte