Skip to content

Commit eea70d2

Browse files
committed
fix: wire per-database allowed_origins into lazy bucket provisioner
The lazy provisioner now follows the same CORS resolution as the bucket provisioner plugin: 1. Per-database allowed_origins from storage_module table 2. Global fallback from SERVER_ORIGIN env var Changes: - Add allowedOrigins to StorageModuleConfig type + SQL query - Add allowedOrigins param to EnsureBucketProvisioned callback - Pass storageConfig.allowedOrigins through ensureS3BucketExists - In createEnsureBucketProvisioned, use per-database origins when available, fall back to getAllowedOrigins() (SERVER_ORIGIN env)
1 parent d13d08c commit eea70d2

4 files changed

Lines changed: 18 additions & 3 deletions

File tree

graphile/graphile-presigned-url-plugin/src/plugin.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,12 +127,13 @@ async function ensureS3BucketExists(
127127
s3BucketName: string,
128128
bucket: BucketConfig,
129129
databaseId: string,
130+
allowedOrigins: string[] | null,
130131
): Promise<void> {
131132
if (!options.ensureBucketProvisioned) return;
132133
if (isS3BucketProvisioned(s3BucketName)) return;
133134

134135
log.info(`Lazy-provisioning S3 bucket "${s3BucketName}" for database ${databaseId}`);
135-
await options.ensureBucketProvisioned(s3BucketName, bucket.type, databaseId);
136+
await options.ensureBucketProvisioned(s3BucketName, bucket.type, databaseId, allowedOrigins);
136137
markS3BucketProvisioned(s3BucketName);
137138
log.info(`Lazy-provisioned S3 bucket "${s3BucketName}" successfully`);
138139
}
@@ -341,7 +342,7 @@ export function createPresignedUrlPlugin(
341342

342343
// --- Ensure the S3 bucket exists (lazy provisioning) ---
343344
const s3ForDb = resolveS3ForDatabase(options, storageConfig, databaseId);
344-
await ensureS3BucketExists(options, s3ForDb.bucket, bucket, databaseId);
345+
await ensureS3BucketExists(options, s3ForDb.bucket, bucket, databaseId, storageConfig.allowedOrigins);
345346

346347
// --- Generate presigned PUT URL (per-database bucket) ---
347348
const uploadUrl = await generatePresignedPutUrl(

graphile/graphile-presigned-url-plugin/src/storage-module-cache.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ const STORAGE_MODULE_QUERY = `
4747
sm.endpoint,
4848
sm.public_url_prefix,
4949
sm.provider,
50+
sm.allowed_origins,
5051
sm.upload_url_expiry_seconds,
5152
sm.download_url_expiry_seconds,
5253
sm.default_max_file_size,
@@ -74,6 +75,7 @@ interface StorageModuleRow {
7475
endpoint: string | null;
7576
public_url_prefix: string | null;
7677
provider: string | null;
78+
allowed_origins: string[] | null;
7779
upload_url_expiry_seconds: number | null;
7880
download_url_expiry_seconds: number | null;
7981
default_max_file_size: number | null;
@@ -121,6 +123,7 @@ export async function getStorageModuleConfig(
121123
endpoint: row.endpoint,
122124
publicUrlPrefix: row.public_url_prefix,
123125
provider: row.provider,
126+
allowedOrigins: row.allowed_origins,
124127
uploadUrlExpirySeconds: row.upload_url_expiry_seconds ?? DEFAULT_UPLOAD_URL_EXPIRY_SECONDS,
125128
downloadUrlExpirySeconds: row.download_url_expiry_seconds ?? DEFAULT_DOWNLOAD_URL_EXPIRY_SECONDS,
126129
defaultMaxFileSize: row.default_max_file_size ?? DEFAULT_MAX_FILE_SIZE,

graphile/graphile-presigned-url-plugin/src/types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ export interface StorageModuleConfig {
4242
publicUrlPrefix: string | null;
4343
/** Storage provider type: 'minio', 's3', 'gcs', etc. (per-database override) */
4444
provider: string | null;
45+
/** CORS allowed origins (per-database override, NULL = use global fallback) */
46+
allowedOrigins: string[] | null;
4547

4648
// --- Per-database configurable settings ---
4749

@@ -159,11 +161,13 @@ export type BucketNameResolver = (databaseId: string) => string;
159161
* @param bucketName - The S3 bucket name to provision
160162
* @param accessType - The logical bucket type ('public', 'private', 'temp')
161163
* @param databaseId - The metaschema database UUID
164+
* @param allowedOrigins - Per-database CORS origins (from storage_module), or null to use global fallback
162165
*/
163166
export type EnsureBucketProvisioned = (
164167
bucketName: string,
165168
accessType: 'public' | 'private' | 'temp',
166169
databaseId: string,
170+
allowedOrigins: string[] | null,
167171
) => Promise<void>;
168172

169173
/**

graphile/graphile-settings/src/presigned-url-resolver.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,17 @@ export function createEnsureBucketProvisioned(): EnsureBucketProvisioned {
115115
bucketName: string,
116116
accessType: 'public' | 'private' | 'temp',
117117
databaseId: string,
118+
allowedOrigins: string[] | null,
118119
): Promise<void> => {
120+
// Per-database origins from storage_module, falling back to global SERVER_ORIGIN
121+
const effectiveOrigins = (allowedOrigins && allowedOrigins.length > 0)
122+
? allowedOrigins
123+
: getAllowedOrigins();
124+
119125
if (!provisioner) {
120126
provisioner = new BucketProvisioner({
121127
connection: getBucketProvisionerConnection(),
122-
allowedOrigins: getAllowedOrigins(),
128+
allowedOrigins: effectiveOrigins,
123129
});
124130
}
125131

@@ -132,6 +138,7 @@ export function createEnsureBucketProvisioned(): EnsureBucketProvisioned {
132138
bucketName,
133139
accessType,
134140
versioning: false,
141+
allowedOrigins: effectiveOrigins,
135142
});
136143

137144
log.info(`[lazy-provision] S3 bucket "${bucketName}" provisioned successfully`);

0 commit comments

Comments
 (0)