fix(api): chemins de bibliothèques — validation dédiée, alias et unicité

Validation des chemins externalisée (library-path) avec codes d'erreur
explicites, support d'alias LIBRARY_PATH_ALIASES pour traduire un chemin
hôte vers le montage conteneur, rejet des doublons de chemin entre
bibliothèques, documentation README/.env.example et docker-compose
paramétrable via READABOOK_LIBRARY_HOST_PATH.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Git Agent
2026-08-23 16:23:57 +02:00
parent 0fa2f99289
commit 7b72cc0d83
8 changed files with 194 additions and 16 deletions

View File

@ -11,6 +11,7 @@ export type AppConfig = {
cookieName: string;
cookieSecure: boolean;
openLibraryEnabled: boolean;
libraryPathAliases: Array<{ from: string; to: string }>;
initialAdminEmail: string;
initialAdminPassword: string;
initialAdminPasswordIsDefault: boolean;
@ -36,8 +37,25 @@ export function loadConfig(): AppConfig {
cookieName: process.env.AUTH_COOKIE_NAME ?? "readabook_session",
cookieSecure: process.env.COOKIE_SECURE === "true",
openLibraryEnabled: process.env.OPEN_LIBRARY_ENABLED !== "false",
libraryPathAliases: parseLibraryPathAliases(process.env.LIBRARY_PATH_ALIASES),
initialAdminEmail: process.env.INITIAL_ADMIN_EMAIL ?? DEFAULT_INITIAL_ADMIN_EMAIL,
initialAdminPassword: process.env.INITIAL_ADMIN_PASSWORD ?? DEFAULT_INITIAL_ADMIN_PASSWORD,
initialAdminPasswordIsDefault: !process.env.INITIAL_ADMIN_PASSWORD
};
}
function parseLibraryPathAliases(value: string | undefined): Array<{ from: string; to: string }> {
if (!value) return [];
return value
.split(";")
.map((entry) => entry.trim())
.filter(Boolean)
.map((entry) => {
const separator = entry.indexOf("=");
if (separator === -1) return null;
const from = entry.slice(0, separator).trim();
const to = entry.slice(separator + 1).trim();
return from && to ? { from, to } : null;
})
.filter((entry): entry is { from: string; to: string } => Boolean(entry));
}