feat(metadata): add per-field locking to protect fields from overwrites

This commit is contained in:
neon
2026-04-03 21:31:02 -06:00
parent abd06c5ccd
commit bab3813ff8
52 changed files with 3551 additions and 502 deletions
+1
View File
@@ -29,6 +29,7 @@ export enum AuditAction {
BookUpload = "book.upload",
BookMetadataUpdate = "book.metadata.update",
BookMetadataLocksUpdate = "book.metadata.locks.update",
BookDelete = "book.delete",
BookBulkMetadataRefresh = "book.bulk.metadata_refresh",
BookBulkDelete = "book.bulk.delete",
+2
View File
@@ -1,4 +1,5 @@
import type { MetadataProviderKey } from "./metadata-fetch";
import type { BookMetadataLockField } from "./metadata-lock";
import type { AudiobookChapter, NarratorRef } from "./audiobook";
import type { ComicMetadataFields } from "./metadata-fetch";
@@ -95,6 +96,7 @@ export type BookDetail = {
audioMetadata: AudioMetadata | null;
formatPriority: string[];
comicMetadata: ComicMetadataFields | null;
lockedFields: BookMetadataLockField[];
collections: { id: number; name: string }[];
};
+1
View File
@@ -2,6 +2,7 @@ export * from "./audit";
export * from "./auth";
export * from "./permissions";
export * from "./metadata-preferences";
export * from "./metadata-lock";
export * from "./dashboard";
export * from "./book";
export * from "./audiobook";
+100
View File
@@ -0,0 +1,100 @@
export const BOOK_METADATA_LOCK_FIELDS = [
"title",
"subtitle",
"authors",
"description",
"publisher",
"publishedYear",
"language",
"pageCount",
"seriesName",
"seriesIndex",
"isbn13",
"isbn10",
"genres",
"tags",
"rating",
"narrators",
"durationSeconds",
"abridged",
"googleBooksId",
"goodreadsId",
"amazonId",
"hardcoverId",
"openLibraryId",
"itunesId",
"audibleId",
"comicvineId",
"comicIssueNumber",
"comicVolumeName",
"comicStoryArcs",
"comicPencillers",
"comicInkers",
"comicColorists",
"comicLetterers",
"comicCoverArtists",
"comicCharacters",
"comicTeams",
"comicLocations",
"cover",
] as const;
export type BookMetadataLockField = (typeof BOOK_METADATA_LOCK_FIELDS)[number];
export type BookMetadataLockGroupKey = "core" | "series" | "classification" | "audio" | "providers" | "comic" | "assets";
export interface BookMetadataLockGroup {
key: BookMetadataLockGroupKey;
label: string;
fields: BookMetadataLockField[];
}
export const BOOK_METADATA_LOCK_GROUPS: BookMetadataLockGroup[] = [
{
key: "core",
label: "Core metadata",
fields: ["title", "subtitle", "authors", "description", "publisher", "publishedYear", "language", "pageCount", "isbn13", "isbn10", "rating"],
},
{
key: "series",
label: "Series",
fields: ["seriesName", "seriesIndex"],
},
{
key: "classification",
label: "Classification",
fields: ["genres", "tags"],
},
{
key: "audio",
label: "Audio",
fields: ["narrators", "durationSeconds", "abridged"],
},
{
key: "providers",
label: "Provider IDs",
fields: ["googleBooksId", "goodreadsId", "amazonId", "hardcoverId", "openLibraryId", "itunesId", "audibleId", "comicvineId"],
},
{
key: "comic",
label: "Comic",
fields: [
"comicIssueNumber",
"comicVolumeName",
"comicStoryArcs",
"comicPencillers",
"comicInkers",
"comicColorists",
"comicLetterers",
"comicCoverArtists",
"comicCharacters",
"comicTeams",
"comicLocations",
],
},
{
key: "assets",
label: "Assets",
fields: ["cover"],
},
];