Files
image/node-hook/src/config.mjs
T

84 lines
2.9 KiB
JavaScript

import { readFileSync } from 'node:fs';
function text(name, fallback) {
const value = process.env[name];
return value === undefined || value === '' ? fallback : value;
}
function secret(name, fileName) {
const direct = process.env[name];
if (direct) {
return direct;
}
const path = process.env[fileName];
if (!path) {
throw new Error(`${name} or ${fileName} is required`);
}
return readFileSync(path, 'utf8').trim();
}
function clientSecrets(variableName) {
const entries = text(variableName, '')
.split(',')
.map((entry) => entry.trim())
.filter(Boolean);
if (entries.length === 0) {
throw new Error(`${variableName} is required`);
}
const result = Object.create(null);
for (const entry of entries) {
const separator = entry.indexOf('=');
const client = entry.slice(0, separator);
const path = entry.slice(separator + 1);
if (separator < 1 || !/^[a-z0-9][a-z0-9_-]{1,31}$/.test(client) || !path) {
throw new Error(`Invalid ${variableName} client entry: ${entry}`);
}
const value = readFileSync(path, 'utf8').trim();
if (value.length < 32) {
throw new Error(`${variableName} secret for ${client} must be at least 32 characters`);
}
if (result[client]) {
throw new Error(`Duplicate ${variableName} client: ${client}`);
}
result[client] = value;
}
return result;
}
export function loadConfig() {
const webhookSecret = secret('GITEA_WEBHOOK_SECRET', 'GITEA_WEBHOOK_SECRET_FILE');
const adminSecret = secret('IMAGE_ADMIN_SECRET', 'IMAGE_ADMIN_SECRET_FILE');
if (webhookSecret.length < 32 || adminSecret.length < 32) {
throw new Error('Webhook and admin secrets must be at least 32 characters');
}
const allowedBranches = text('IMAGE_ALLOWED_BRANCHES', 'master')
.split(',')
.map((branch) => branch.trim())
.filter(Boolean);
return {
port: Number(text('PORT', '8081')),
repositoryPath: text('IMAGE_REPOSITORY_PATH', '/data/image'),
remoteUrl: text('IMAGE_REMOTE_URL', 'https://gitea.hided.net/devsam/image.git'),
repositoryFullName: text('IMAGE_REPOSITORY_FULL_NAME', 'devsam/image'),
defaultBranch: text('IMAGE_DEFAULT_BRANCH', 'master'),
allowedBranches,
statePath: text('IMAGE_STATE_PATH', '/var/lib/image-hook/state.json'),
publicBases: text('IMAGE_PUBLIC_BASES', 'https://sam.hided.net/image,https://sam-image.hided.net')
.split(',')
.map((base) => base.trim().replace(/\/$/, ''))
.filter(Boolean),
webhookSecret,
adminSecret,
syncClientSecrets: clientSecrets('IMAGE_SYNC_CLIENT_SECRET_FILES'),
uploadClientSecrets: clientSecrets('IMAGE_UPLOAD_CLIENT_SECRET_FILES'),
maxBodyBytes: Number(text('MAX_BODY_BYTES', '1048576')),
maxUploadBytes: Number(text('MAX_UPLOAD_BYTES', '51200')),
uploadRoot: text('IMAGE_UPLOAD_ROOT', '/var/lib/image-hook/uploads'),
uploadStatePath: text('IMAGE_UPLOAD_STATE_PATH', '/var/lib/image-hook/upload-state.json'),
};
}