mirror of
https://github.com/Dvorinka/Primora.git
synced 2026-10-28 07:41:23 +00:00
feat: Presigned object URLs (s3 driver)
POST /buckets/:id/object-presigns mints SigV4 query-signed GET/PUT URLs so clients move bytes directly against S3 — large transfers skip the backend entirely. - storage.Presigner optional interface; S3Store implements, local driver returns a clear error (no external surface to sign). - TTL 60s–1h (default 15m); download requires read role + existing object row (no key probing); upload requires write role. - S3_PUBLIC_ENDPOINT rewrites the client-facing host for internal S3_ENDPOINTs — signatures bind the host, URLs are valid only where minted. - CLI: primora objects:presign <bucket> <key> [--upload] [--ttl]. Verified live against cloudserver: GET fetched the object with no auth headers; PUT pushed 1 MB direct to S3; unsigned list → 403; untracked-key download presign → 404. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
a84049b8fc
commit
fd36389328
22 files changed
+446
-7
No files matched your search
@@ -108,6 +108,8 @@ export type { OrganizationSummary } from './models/OrganizationSummary';
|
||||
export type { PaginationLimit } from './models/PaginationLimit';
|
||||
export type { PaginationMetadata } from './models/PaginationMetadata';
|
||||
export type { PaginationOffset } from './models/PaginationOffset';
|
||||
export { PresignedURL } from './models/PresignedURL';
|
||||
export { PresignObjectRequest } from './models/PresignObjectRequest';
|
||||
export type { Project } from './models/Project';
|
||||
export type { ProjectID } from './models/ProjectID';
|
||||
export { ProjectMember } from './models/ProjectMember';
|
||||
@@ -258,6 +260,8 @@ export { $OrganizationSummary } from './schemas/$OrganizationSummary';
|
||||
export { $PaginationLimit } from './schemas/$PaginationLimit';
|
||||
export { $PaginationMetadata } from './schemas/$PaginationMetadata';
|
||||
export { $PaginationOffset } from './schemas/$PaginationOffset';
|
||||
export { $PresignedURL } from './schemas/$PresignedURL';
|
||||
export { $PresignObjectRequest } from './schemas/$PresignObjectRequest';
|
||||
export { $Project } from './schemas/$Project';
|
||||
export { $ProjectID } from './schemas/$ProjectID';
|
||||
export { $ProjectMember } from './schemas/$ProjectMember';
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/* generated using openapi-typescript-codegen -- do not edit */
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
export type PresignObjectRequest = {
|
||||
/**
|
||||
* Object key inside the bucket.
|
||||
*/
|
||||
key: string;
|
||||
/**
|
||||
* download → GET URL (object must exist); upload → PUT URL (creates/overwrites).
|
||||
*/
|
||||
op?: PresignObjectRequest.op;
|
||||
ttl_seconds?: number;
|
||||
};
|
||||
export namespace PresignObjectRequest {
|
||||
/**
|
||||
* download → GET URL (object must exist); upload → PUT URL (creates/overwrites).
|
||||
*/
|
||||
export enum op {
|
||||
DOWNLOAD = 'download',
|
||||
UPLOAD = 'upload',
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/* generated using openapi-typescript-codegen -- do not edit */
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
export type PresignedURL = {
|
||||
/**
|
||||
* Fully-signed URL — call it with the returned method, no auth header needed.
|
||||
*/
|
||||
url: string;
|
||||
method: PresignedURL.method;
|
||||
expires_at: string;
|
||||
};
|
||||
export namespace PresignedURL {
|
||||
export enum method {
|
||||
GET = 'GET',
|
||||
PUT = 'PUT',
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
/* generated using openapi-typescript-codegen -- do not edit */
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
export const $PresignObjectRequest = {
|
||||
properties: {
|
||||
key: {
|
||||
type: 'string',
|
||||
description: `Object key inside the bucket.`,
|
||||
isRequired: true,
|
||||
},
|
||||
op: {
|
||||
type: 'Enum',
|
||||
},
|
||||
ttl_seconds: {
|
||||
type: 'number',
|
||||
maximum: 3600,
|
||||
minimum: 60,
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
@@ -0,0 +1,22 @@
|
||||
/* generated using openapi-typescript-codegen -- do not edit */
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
export const $PresignedURL = {
|
||||
properties: {
|
||||
url: {
|
||||
type: 'string',
|
||||
description: `Fully-signed URL — call it with the returned method, no auth header needed.`,
|
||||
isRequired: true,
|
||||
},
|
||||
method: {
|
||||
type: 'Enum',
|
||||
isRequired: true,
|
||||
},
|
||||
expires_at: {
|
||||
type: 'string',
|
||||
isRequired: true,
|
||||
format: 'date-time',
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
@@ -7,6 +7,8 @@ import type { BucketObject } from '../models/BucketObject';
|
||||
import type { BucketObjectListResponse } from '../models/BucketObjectListResponse';
|
||||
import type { CopyBucketObjectRequest } from '../models/CopyBucketObjectRequest';
|
||||
import type { CreateBucketRequest } from '../models/CreateBucketRequest';
|
||||
import type { PresignedURL } from '../models/PresignedURL';
|
||||
import type { PresignObjectRequest } from '../models/PresignObjectRequest';
|
||||
import type { UpdateBucketObjectRequest } from '../models/UpdateBucketObjectRequest';
|
||||
import type { UpdateBucketRequest } from '../models/UpdateBucketRequest';
|
||||
import type { CancelablePromise } from '../core/CancelablePromise';
|
||||
@@ -131,6 +133,31 @@ export class StorageService {
|
||||
mediaType: 'application/json',
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Mint a short-lived URL the client calls against object storage directly — keeps large transfers off the backend. Requires BACKEND_STORAGE_DRIVER=s3; the URL's host comes from S3_PUBLIC_ENDPOINT (or S3_ENDPOINT when unset). Signatures bind the host — a presigned URL is valid only at the endpoint it was minted for.
|
||||
* @returns PresignedURL Presigned URL
|
||||
* @throws ApiError
|
||||
*/
|
||||
public static presignBucketObject({
|
||||
bucketId,
|
||||
requestBody,
|
||||
}: {
|
||||
bucketId: string,
|
||||
requestBody: PresignObjectRequest,
|
||||
}): CancelablePromise<PresignedURL> {
|
||||
return __request(OpenAPI, {
|
||||
method: 'POST',
|
||||
url: '/buckets/{bucketID}/object-presigns',
|
||||
path: {
|
||||
'bucketID': bucketId,
|
||||
},
|
||||
body: requestBody,
|
||||
mediaType: 'application/json',
|
||||
errors: {
|
||||
404: `Bucket or object not found (download)`,
|
||||
},
|
||||
});
|
||||
}
|
||||
/**
|
||||
* @returns void
|
||||
* @throws ApiError
|
||||
|
||||
Reference in new issue
Block a user