mirror of
https://github.com/Drop-OSS/drop.git
synced 2025-11-13 00:02:37 +10:00
feat: fs object metadata cache and validation
This commit is contained in:
@ -1,5 +1,5 @@
|
|||||||
import type { ObjectMetadata, ObjectReference, Source } from "./objectHandler";
|
import type { ObjectMetadata, ObjectReference, Source } from "./objectHandler";
|
||||||
import { ObjectBackend } from "./objectHandler";
|
import { ObjectBackend, objectMetadata } from "./objectHandler";
|
||||||
|
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
@ -8,12 +8,15 @@ import { createHash } from "crypto";
|
|||||||
import prisma from "../db/database";
|
import prisma from "../db/database";
|
||||||
import cacheHandler from "../cache";
|
import cacheHandler from "../cache";
|
||||||
import { systemConfig } from "../config/sys-conf";
|
import { systemConfig } from "../config/sys-conf";
|
||||||
|
import { type } from "arktype";
|
||||||
|
|
||||||
export class FsObjectBackend extends ObjectBackend {
|
export class FsObjectBackend extends ObjectBackend {
|
||||||
private baseObjectPath: string;
|
private baseObjectPath: string;
|
||||||
private baseMetadataPath: string;
|
private baseMetadataPath: string;
|
||||||
|
|
||||||
private hashStore = new FsHashStore();
|
private hashStore = new FsHashStore();
|
||||||
|
private metadataCache =
|
||||||
|
cacheHandler.createCache<ObjectMetadata>("ObjectMetadata");
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -102,17 +105,27 @@ export class FsObjectBackend extends ObjectBackend {
|
|||||||
const metadataPath = path.join(this.baseMetadataPath, `${id}.json`);
|
const metadataPath = path.join(this.baseMetadataPath, `${id}.json`);
|
||||||
if (!fs.existsSync(metadataPath)) return true;
|
if (!fs.existsSync(metadataPath)) return true;
|
||||||
fs.rmSync(metadataPath);
|
fs.rmSync(metadataPath);
|
||||||
// remove item from cache
|
// remove item from caches
|
||||||
|
await this.metadataCache.remove(id);
|
||||||
await this.hashStore.delete(id);
|
await this.hashStore.delete(id);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
async fetchMetadata(
|
async fetchMetadata(
|
||||||
id: ObjectReference,
|
id: ObjectReference,
|
||||||
): Promise<ObjectMetadata | undefined> {
|
): Promise<ObjectMetadata | undefined> {
|
||||||
|
const cacheResult = await this.metadataCache.get(id);
|
||||||
|
if (cacheResult !== null) return cacheResult;
|
||||||
|
|
||||||
const metadataPath = path.join(this.baseMetadataPath, `${id}.json`);
|
const metadataPath = path.join(this.baseMetadataPath, `${id}.json`);
|
||||||
if (!fs.existsSync(metadataPath)) return undefined;
|
if (!fs.existsSync(metadataPath)) return undefined;
|
||||||
const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf-8"));
|
const metadataRaw = JSON.parse(fs.readFileSync(metadataPath, "utf-8"));
|
||||||
return metadata as ObjectMetadata;
|
const metadata = objectMetadata(metadataRaw);
|
||||||
|
if (metadata instanceof type.errors) {
|
||||||
|
console.error("FsObjectBackend#fetchMetadata", metadata.summary);
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
await this.metadataCache.set(id, metadata);
|
||||||
|
return metadata;
|
||||||
}
|
}
|
||||||
async writeMetadata(
|
async writeMetadata(
|
||||||
id: ObjectReference,
|
id: ObjectReference,
|
||||||
@ -121,6 +134,7 @@ export class FsObjectBackend extends ObjectBackend {
|
|||||||
const metadataPath = path.join(this.baseMetadataPath, `${id}.json`);
|
const metadataPath = path.join(this.baseMetadataPath, `${id}.json`);
|
||||||
if (!fs.existsSync(metadataPath)) return false;
|
if (!fs.existsSync(metadataPath)) return false;
|
||||||
fs.writeFileSync(metadataPath, JSON.stringify(metadata));
|
fs.writeFileSync(metadataPath, JSON.stringify(metadata));
|
||||||
|
await this.metadataCache.set(id, metadata);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
async fetchHash(id: ObjectReference): Promise<string | undefined> {
|
async fetchHash(id: ObjectReference): Promise<string | undefined> {
|
||||||
|
|||||||
@ -14,17 +14,22 @@
|
|||||||
* anotherUserId:write
|
* anotherUserId:write
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { type } from "arktype";
|
||||||
import { parse as getMimeTypeBuffer } from "file-type-mime";
|
import { parse as getMimeTypeBuffer } from "file-type-mime";
|
||||||
import type { Writable } from "stream";
|
import type { Writable } from "stream";
|
||||||
import { Readable } from "stream";
|
import { Readable } from "stream";
|
||||||
import { getMimeType as getMimeTypeStream } from "stream-mime-type";
|
import { getMimeType as getMimeTypeStream } from "stream-mime-type";
|
||||||
|
|
||||||
export type ObjectReference = string;
|
export type ObjectReference = string;
|
||||||
export type ObjectMetadata = {
|
|
||||||
mime: string;
|
export const objectMetadata = type({
|
||||||
permissions: string[];
|
mime: "string",
|
||||||
userMetadata: { [key: string]: string };
|
permissions: "string[]",
|
||||||
};
|
userMetadata: {
|
||||||
|
"[string]": "string",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
export type ObjectMetadata = typeof objectMetadata.infer;
|
||||||
|
|
||||||
export enum ObjectPermission {
|
export enum ObjectPermission {
|
||||||
Read = "read",
|
Read = "read",
|
||||||
|
|||||||
Reference in New Issue
Block a user