Validate image upload page

This commit is contained in:
Kalle
2023-01-13 00:03:05 +02:00
parent 64874497fb
commit c6381e02fb
5 changed files with 102 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
import { sql } from "~/db/sql";
import type { UserSubmittedImage } from "~/db/types";
const stm = sql.prepare(/* sql */ `
select
"id",
"url",
"submitterUserId"
from "UnvalidatedUserSubmittedImage"
where "validatedAt" is null
limit 1
`);
type UnvalidatedImage = Pick<
UserSubmittedImage,
"id" | "url" | "submitterUserId"
>;
export function oneUnvalidatedImage(): UnvalidatedImage | null {
return stm.get();
}

View File

@@ -0,0 +1,12 @@
import { sql } from "~/db/sql";
import { dateToDatabaseTimestamp } from "~/utils/dates";
const stm = sql.prepare(/* sql */ `
update "UnvalidatedUserSubmittedImage"
set "validatedAt" = @validatedAt
where "id" = @id
`);
export function validateImage(id: number) {
stm.run({ validatedAt: dateToDatabaseTimestamp(new Date()), id });
}

View File

@@ -0,0 +1,62 @@
import type { ActionFunction, LoaderArgs } from "@remix-run/node";
import { Form, useLoaderData } from "@remix-run/react";
import { Main } from "~/components/Main";
import { SubmitButton } from "~/components/SubmitButton";
import { requireUser } from "~/modules/auth";
import { isAdmin } from "~/permissions";
import { notFoundIfFalsy, parseRequestFormData, validate } from "~/utils/remix";
import { userSubmittedImage } from "~/utils/urls";
import { oneUnvalidatedImage } from "../queries/oneUnvalidatedImage";
import { validateImage } from "../queries/validateImage";
import { validateImageSchema } from "../upload-schemas.server";
export const action: ActionFunction = async ({ request }) => {
const user = await requireUser(request);
const data = await parseRequestFormData({
schema: validateImageSchema,
request,
});
validate(isAdmin(user));
validateImage(data.imageId);
return null;
};
export const loader = async ({ request }: LoaderArgs) => {
const user = await requireUser(request);
notFoundIfFalsy(isAdmin(user));
return {
image: oneUnvalidatedImage(),
};
};
export default function ImageUploadAdminPage() {
return (
<Main>
<ImageValidator />
</Main>
);
}
function ImageValidator() {
const data = useLoaderData<typeof loader>();
if (!data.image) {
return <>All validated!</>;
}
return (
<>
<img src={userSubmittedImage(data.image.url)} alt="" />
<Form method="post">
<input type="hidden" name="imageId" value={data.image.id} />
<SubmitButton>Ok</SubmitButton>
</Form>
<div>From: {data.image.submitterUserId}</div>
</>
);
}

View File

@@ -0,0 +1,6 @@
import { z } from "zod";
import { id } from "~/utils/zod";
export const validateImageSchema = z.object({
imageId: id,
});

View File

@@ -7,6 +7,7 @@ module.exports = {
routes: async (defineRoutes) => {
return defineRoutes((route) => {
route("/upload", "features/img-upload/routes/upload.tsx");
route("/upload/admin", "features/img-upload/routes/upload.admin.tsx");
route("/plans", "features/map-planner/routes/plans.tsx");
route("/analyzer", "features/build-analyzer/routes/analyzer.tsx");
route(