feat: rehashdoc

This commit is contained in:
monoid 2024-10-13 02:00:43 +09:00
parent 58adb46323
commit f543ad1cf4
3 changed files with 52 additions and 3 deletions

View File

@ -1,7 +1,17 @@
import useSWR from "swr"; import useSWR, { useSWRConfig } from "swr";
import type { Document } from "dbtype"; import type { Document } from "dbtype";
import { fetcher } from "./fetcher"; import { fetcher } from "./fetcher";
export function useGalleryDoc(id: string) { export function useGalleryDoc(id: string) {
return useSWR<Document>(`/api/doc/${id}`, fetcher); return useSWR<Document>(`/api/doc/${id}`, fetcher);
} }
export function useRehashDoc() {
const { mutate } = useSWRConfig();
return async (id: string) => {
await fetch(`/api/doc/${id}/_rehash`, {
method: "POST",
});
mutate(`/api/doc/${id}`);
};
}

View File

@ -1,10 +1,11 @@
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { useGalleryDoc } from "../hook/useGalleryDoc.ts"; import { useGalleryDoc, useRehashDoc } from "../hook/useGalleryDoc.ts";
import TagBadge from "@/components/gallery/TagBadge"; import TagBadge from "@/components/gallery/TagBadge";
import StyledLink from "@/components/gallery/StyledLink"; import StyledLink from "@/components/gallery/StyledLink";
import { Link } from "wouter"; import { Link } from "wouter";
import { classifyTags } from "../lib/classifyTags.tsx"; import { classifyTags } from "../lib/classifyTags.tsx";
import { DescTagItem, DescItem } from "../components/gallery/DescItem.tsx"; import { DescTagItem, DescItem } from "../components/gallery/DescItem.tsx";
import { Button } from "@/components/ui/button.tsx";
export interface ContentInfoPageProps { export interface ContentInfoPageProps {
params: { params: {
@ -14,6 +15,7 @@ export interface ContentInfoPageProps {
export function ContentInfoPage({ params }: ContentInfoPageProps) { export function ContentInfoPage({ params }: ContentInfoPageProps) {
const { data, error, isLoading } = useGalleryDoc(params.id); const { data, error, isLoading } = useGalleryDoc(params.id);
const rehashDoc = useRehashDoc();
if (isLoading) { if (isLoading) {
return <div className="p-4">Loading...</div> return <div className="p-4">Loading...</div>
@ -43,7 +45,13 @@ export function ContentInfoPage({ params }: ContentInfoPageProps) {
alt={data.title} /> alt={data.title} />
</div> </div>
</Link> </Link>
<Card className="flex-1"> <Card className="flex-1 relative">
<div className="absolute top-0 right-0 p-2">
<Button variant="ghost" onClick={async () => {
// Rehash
await rehashDoc(params.id);
}}>Rehash</Button>
</div>
<CardHeader> <CardHeader>
<CardTitle> <CardTitle>
<StyledLink to={contentLocation}> <StyledLink to={contentLocation}>

View File

@ -15,6 +15,8 @@ import { AllContentRouter } from "./all.ts";
import type { ContentLocation } from "./context.ts"; import type { ContentLocation } from "./context.ts";
import { sendError } from "./error_handler.ts"; import { sendError } from "./error_handler.ts";
import { ParseQueryArgString, ParseQueryArray, ParseQueryBoolean, ParseQueryNumber } from "./util.ts"; import { ParseQueryArgString, ParseQueryArray, ParseQueryBoolean, ParseQueryNumber } from "./util.ts";
import { oshash } from "src/util/oshash.ts";
const ContentIDHandler = (controller: DocumentAccessor) => async (ctx: Context, next: Next) => { const ContentIDHandler = (controller: DocumentAccessor) => async (ctx: Context, next: Next) => {
const num = Number.parseInt(ctx.params.num); const num = Number.parseInt(ctx.params.num);
@ -154,6 +156,34 @@ const ContentHandler = (controller: DocumentAccessor) => async (ctx: Context, ne
await next(); await next();
}; };
function RehashContentHandler(controller: DocumentAccessor) {
return async (ctx: Context, next: Next) => {
const num = Number.parseInt(ctx.params.num);
const c = await controller.findById(num);
if (c === undefined || c.deleted_at !== null) {
return sendError(404);
}
const filepath = join(c.basepath, c.filename);
let new_hash: string;
try {
new_hash = (await oshash(filepath)).toString();
}
catch (e) {
// if file is not found, return 404
if ( (e as NodeJS.ErrnoException).code === "ENOENT") {
return sendError(404, "file not found");
}
throw e;
}
const r = await controller.update({
id: num,
content_hash: new_hash,
});
ctx.body = JSON.stringify(r);
ctx.type = "json";
};
}
export const getContentRouter = (controller: DocumentAccessor) => { export const getContentRouter = (controller: DocumentAccessor) => {
const ret = new Router(); const ret = new Router();
ret.get("/search", PerCheck(Per.QueryContent), ContentQueryHandler(controller)); ret.get("/search", PerCheck(Per.QueryContent), ContentQueryHandler(controller));
@ -167,6 +197,7 @@ export const getContentRouter = (controller: DocumentAccessor) => {
ret.del("/:num(\\d+)", AdminOnly, DeleteContentHandler(controller)); ret.del("/:num(\\d+)", AdminOnly, DeleteContentHandler(controller));
ret.all("/:num(\\d+)/(.*)", PerCheck(Per.QueryContent), ContentHandler(controller)); ret.all("/:num(\\d+)/(.*)", PerCheck(Per.QueryContent), ContentHandler(controller));
ret.use("/:num(\\d+)", PerCheck(Per.QueryContent), new AllContentRouter().routes()); ret.use("/:num(\\d+)", PerCheck(Per.QueryContent), new AllContentRouter().routes());
ret.post("/:num(\\d+)/_rehash", AdminOnly, RehashContentHandler(controller));
return ret; return ret;
}; };