fix: make direct upload cors script standalone
This commit is contained in:
parent
e1e53713b5
commit
9c450a3d07
@ -3,13 +3,21 @@ import "dotenv/config";
|
||||
import {
|
||||
GetBucketCorsCommand,
|
||||
PutBucketCorsCommand,
|
||||
S3Client,
|
||||
type CORSRule,
|
||||
} from "@aws-sdk/client-s3";
|
||||
import { and, eq } from "drizzle-orm";
|
||||
|
||||
import {
|
||||
createS3Client,
|
||||
resolveS3UploadTarget,
|
||||
} from "@/lib/storage/service";
|
||||
import { db } from "@/lib/db";
|
||||
import { storageConfig } from "@/lib/db/schema";
|
||||
|
||||
type S3UploadConfig = {
|
||||
endpoint: string;
|
||||
region: string;
|
||||
bucket: string;
|
||||
accessKeyId: string;
|
||||
secretAccessKey: string;
|
||||
};
|
||||
|
||||
const DEFAULT_ORIGINS = [
|
||||
"https://ai.yydd.ai",
|
||||
@ -20,6 +28,103 @@ const DEFAULT_ORIGINS = [
|
||||
"http://localhost:3001",
|
||||
];
|
||||
|
||||
function normalizeEndpoint(endpoint: string): string {
|
||||
const trimmed = endpoint.trim().replace(/\/+$/, "");
|
||||
if (!trimmed) return "";
|
||||
|
||||
if (/aliyuncs\.com/i.test(trimmed)) {
|
||||
const withoutProtocol = trimmed.replace(/^https?:\/\//i, "");
|
||||
return `https://${withoutProtocol}`;
|
||||
}
|
||||
|
||||
return trimmed;
|
||||
}
|
||||
|
||||
function createS3Client(config: S3UploadConfig) {
|
||||
const normalizedEndpoint = normalizeEndpoint(config.endpoint);
|
||||
const lowerEndpoint = normalizedEndpoint.toLowerCase();
|
||||
const isCloudS3 =
|
||||
lowerEndpoint.includes("aliyuncs.com") ||
|
||||
lowerEndpoint.includes("amazonaws.com");
|
||||
|
||||
return new S3Client({
|
||||
endpoint: normalizedEndpoint,
|
||||
region: config.region || "auto",
|
||||
credentials: {
|
||||
accessKeyId: config.accessKeyId,
|
||||
secretAccessKey: config.secretAccessKey,
|
||||
},
|
||||
forcePathStyle: !isCloudS3,
|
||||
});
|
||||
}
|
||||
|
||||
function toS3Config(value: unknown): S3UploadConfig | null {
|
||||
const raw = value as Record<string, unknown> | null | undefined;
|
||||
const endpoint = raw?.endpoint ? normalizeEndpoint(String(raw.endpoint)) : "";
|
||||
const bucket = raw?.bucket ? String(raw.bucket).trim() : "";
|
||||
const accessKeyId = raw?.accessKeyId ? String(raw.accessKeyId).trim() : "";
|
||||
const secretAccessKey = raw?.secretAccessKey
|
||||
? String(raw.secretAccessKey).trim()
|
||||
: "";
|
||||
|
||||
if (
|
||||
!raw ||
|
||||
raw.type !== "s3" ||
|
||||
raw.isEnabled !== true ||
|
||||
!endpoint ||
|
||||
!bucket ||
|
||||
!accessKeyId ||
|
||||
!secretAccessKey
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
endpoint,
|
||||
region: String(raw.region || "auto").trim() || "auto",
|
||||
bucket,
|
||||
accessKeyId,
|
||||
secretAccessKey,
|
||||
};
|
||||
}
|
||||
|
||||
function readEnvS3Config(): S3UploadConfig | null {
|
||||
const endpoint = process.env.S3_ENDPOINT
|
||||
? normalizeEndpoint(process.env.S3_ENDPOINT)
|
||||
: "";
|
||||
const bucket = process.env.S3_BUCKET?.trim() || "";
|
||||
const accessKeyId = process.env.S3_ACCESS_KEY_ID?.trim() || "";
|
||||
const secretAccessKey = process.env.S3_SECRET_ACCESS_KEY?.trim() || "";
|
||||
|
||||
if (!endpoint || !bucket || !accessKeyId || !secretAccessKey) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
endpoint,
|
||||
region: process.env.S3_REGION?.trim() || "auto",
|
||||
bucket,
|
||||
accessKeyId,
|
||||
secretAccessKey,
|
||||
};
|
||||
}
|
||||
|
||||
async function resolveS3Config() {
|
||||
const [defaultConfig] = await db
|
||||
.select()
|
||||
.from(storageConfig)
|
||||
.where(
|
||||
and(
|
||||
eq(storageConfig.type, "s3"),
|
||||
eq(storageConfig.isDefault, true),
|
||||
eq(storageConfig.isEnabled, true)
|
||||
)
|
||||
)
|
||||
.limit(1);
|
||||
|
||||
return toS3Config(defaultConfig) || readEnvS3Config();
|
||||
}
|
||||
|
||||
function readOrigins() {
|
||||
const raw = process.env.DIRECT_UPLOAD_CORS_ORIGINS || "";
|
||||
const origins = raw
|
||||
@ -51,15 +156,14 @@ function isDirectUploadRule(rule: CORSRule, origins: string[]) {
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const target = await resolveS3UploadTarget();
|
||||
if (!target) {
|
||||
const config = await resolveS3Config();
|
||||
if (!config) {
|
||||
console.log("[direct-upload-cors] skip: no S3-compatible upload target");
|
||||
return;
|
||||
}
|
||||
|
||||
const origins = readOrigins();
|
||||
const client = createS3Client(target.config);
|
||||
const bucket = target.config.bucket;
|
||||
const client = createS3Client(config);
|
||||
const directRule: CORSRule = {
|
||||
AllowedOrigins: origins,
|
||||
AllowedMethods: ["GET", "PUT", "POST", "HEAD"],
|
||||
@ -70,7 +174,9 @@ async function main() {
|
||||
|
||||
let existingRules: CORSRule[] = [];
|
||||
try {
|
||||
const current = await client.send(new GetBucketCorsCommand({ Bucket: bucket }));
|
||||
const current = await client.send(
|
||||
new GetBucketCorsCommand({ Bucket: config.bucket })
|
||||
);
|
||||
existingRules = current.CORSRules || [];
|
||||
} catch (error) {
|
||||
console.warn(
|
||||
@ -88,7 +194,7 @@ async function main() {
|
||||
|
||||
await client.send(
|
||||
new PutBucketCorsCommand({
|
||||
Bucket: bucket,
|
||||
Bucket: config.bucket,
|
||||
CORSConfiguration: {
|
||||
CORSRules: mergedRules,
|
||||
},
|
||||
@ -96,7 +202,7 @@ async function main() {
|
||||
);
|
||||
|
||||
console.log("[direct-upload-cors] configured", {
|
||||
bucket,
|
||||
bucket: config.bucket,
|
||||
origins,
|
||||
ruleCount: mergedRules.length,
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user