Files
boss/src/lib/boss-storage-config.ts
2026-03-29 16:05:25 +08:00

101 lines
3.2 KiB
TypeScript

import type { UserAttachmentStorageConfig } from "@/lib/boss-data";
import { encryptStorageSecret } from "@/lib/boss-storage-secrets";
export interface AttachmentStorageConfigPatch {
mode?: UserAttachmentStorageConfig["mode"];
ossProvider?: UserAttachmentStorageConfig["ossProvider"];
aliyunOss?: {
enabled?: boolean;
accessKeyId?: string;
accessKeySecret?: string;
bucket?: string;
endpoint?: string;
region?: string;
prefix?: string;
};
}
function trimText(value: string | undefined) {
return value?.trim() ?? "";
}
function normalizePrefix(prefix: string | undefined, fallback?: string) {
const candidate = prefix?.trim() || fallback?.trim() || "boss/";
return candidate || "boss/";
}
function buildAliyunOssBaseConfig(existing?: UserAttachmentStorageConfig["aliyunOss"]) {
return {
enabled: existing?.enabled ?? false,
accessKeyId: existing?.accessKeyId ?? "",
accessKeySecretEncrypted: existing?.accessKeySecretEncrypted ?? "",
bucket: existing?.bucket ?? "",
endpoint: existing?.endpoint ?? "",
region: existing?.region ?? "",
prefix: existing?.prefix ?? "boss/",
};
}
export async function applyAttachmentStorageConfigPatch(
existing: UserAttachmentStorageConfig,
patch: AttachmentStorageConfigPatch,
): Promise<UserAttachmentStorageConfig> {
const mode = patch.mode ?? existing.mode;
const effectiveOssProvider =
mode === "oss" ? patch.ossProvider ?? existing.ossProvider ?? "aliyun_oss" : existing.ossProvider;
const nextAliyun = buildAliyunOssBaseConfig(existing.aliyunOss);
if (patch.aliyunOss) {
if (patch.aliyunOss.enabled !== undefined) {
nextAliyun.enabled = patch.aliyunOss.enabled;
}
if (patch.aliyunOss.accessKeyId !== undefined) {
nextAliyun.accessKeyId = trimText(patch.aliyunOss.accessKeyId);
}
if (patch.aliyunOss.bucket !== undefined) {
nextAliyun.bucket = trimText(patch.aliyunOss.bucket);
}
if (patch.aliyunOss.endpoint !== undefined) {
nextAliyun.endpoint = trimText(patch.aliyunOss.endpoint);
}
if (patch.aliyunOss.region !== undefined) {
nextAliyun.region = trimText(patch.aliyunOss.region);
}
if (patch.aliyunOss.prefix !== undefined) {
nextAliyun.prefix = normalizePrefix(patch.aliyunOss.prefix, nextAliyun.prefix);
}
if (patch.aliyunOss.accessKeySecret !== undefined) {
nextAliyun.accessKeySecretEncrypted = await encryptStorageSecret(
patch.aliyunOss.accessKeySecret,
);
}
}
if (mode === "oss") {
if (effectiveOssProvider !== "aliyun_oss") {
throw new Error("ALIYUN_OSS_PROVIDER_REQUIRED");
}
if (
!nextAliyun.accessKeyId ||
!nextAliyun.accessKeySecretEncrypted ||
!nextAliyun.bucket ||
!nextAliyun.endpoint ||
!nextAliyun.region
) {
throw new Error("ALIYUN_OSS_CONFIG_INCOMPLETE");
}
nextAliyun.enabled = true;
}
return {
account: existing.account,
mode,
ossProvider: effectiveOssProvider,
aliyunOss: nextAliyun,
updatedAt: new Date().toISOString(),
validatedAt: patch.mode !== undefined || patch.ossProvider !== undefined || patch.aliyunOss
? undefined
: existing.validatedAt,
};
}