Skip to content

Commit 197cdf0

Browse files
committed
fix: copy command using the new version (#344)
1 parent 525d687 commit 197cdf0

File tree

3 files changed

+83
-42
lines changed

3 files changed

+83
-42
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
create extension if not exists "uuid-ossp";
2+
3+
CREATE TABLE tenants_external_credentials (
4+
"id" uuid NOT NULL DEFAULT uuid_generate_v4(),
5+
name text NOT NULL unique,
6+
tenant_id text NOT NULL references tenants (id),
7+
provider text NOT NULL default 's3',
8+
access_key text NULL,
9+
secret_key text NULL,
10+
role text null,
11+
region text not null,
12+
endpoint text NULL,
13+
force_path_style boolean NOT NULL default false,
14+
PRIMARY KEY (id)
15+
);
16+
17+
create index external_buckets_tenant_id_idx on tenants_external_credentials (tenant_id);
18+
19+
CREATE FUNCTION tenants_external_credentials_update_notify_trigger ()
20+
RETURNS TRIGGER
21+
AS $$
22+
BEGIN
23+
PERFORM
24+
pg_notify('tenants_external_credentials_update', '"' || NEW.id || ':' || NEW.tenant_id || '"');
25+
RETURN NULL;
26+
END;
27+
$$
28+
LANGUAGE plpgsql;
29+
30+
CREATE TRIGGER tenants_external_credentials_notify_trigger
31+
AFTER DELETE ON tenants_external_credentials
32+
FOR EACH ROW
33+
EXECUTE PROCEDURE tenants_external_credentials_update_notify_trigger();
34+
35+
CREATE TRIGGER tenants_external_credentials_notify_trigger
36+
AFTER UPDATE ON tenants_external_credentials
37+
FOR EACH ROW
38+
EXECUTE PROCEDURE tenants_external_credentials_update_notify_trigger();

src/storage/database/knex.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,13 @@ export class StorageKnexDB implements Database {
108108
async createBucket(
109109
data: Pick<
110110
Bucket,
111-
'id' | 'name' | 'public' | 'owner' | 'file_size_limit' | 'allowed_mime_types'
111+
| 'id'
112+
| 'name'
113+
| 'public'
114+
| 'owner'
115+
| 'file_size_limit'
116+
| 'allowed_mime_types'
117+
| 'external_credential_id'
112118
>
113119
) {
114120
const bucketData = {
@@ -118,6 +124,7 @@ export class StorageKnexDB implements Database {
118124
public: data.public,
119125
allowed_mime_types: data.allowed_mime_types,
120126
file_size_limit: data.file_size_limit,
127+
external_credential_id: data.external_credential_id,
121128
}
122129

123130
const bucket = await this.runQuery('CreateBucket', async (knex) => {
@@ -204,13 +211,17 @@ export class StorageKnexDB implements Database {
204211

205212
async updateBucket(
206213
bucketId: string,
207-
fields: Pick<Bucket, 'public' | 'file_size_limit' | 'allowed_mime_types'>
214+
fields: Pick<
215+
Bucket,
216+
'public' | 'file_size_limit' | 'allowed_mime_types' | 'external_credential_id'
217+
>
208218
) {
209219
const bucket = await this.runQuery('UpdateBucket', (knex) => {
210220
return knex.from('buckets').where('id', bucketId).update({
211221
public: fields.public,
212222
file_size_limit: fields.file_size_limit,
213223
allowed_mime_types: fields.allowed_mime_types,
224+
external_credential_id: fields.external_credential_id,
214225
})
215226
})
216227

src/storage/object.ts

Lines changed: 32 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export interface UploadObjectOptions {
2323
version?: string
2424
}
2525

26-
const { urlLengthLimit, globalS3Bucket } = getConfig()
26+
const { urlLengthLimit } = getConfig()
2727

2828
/**
2929
* ObjectStorage
@@ -159,17 +159,15 @@ export class ObjectStorage {
159159
// if successfully deleted, delete from s3 too
160160
// todo: consider moving this to a queue
161161
const prefixesToDelete = data.reduce((all, { name, version }) => {
162-
all.push(withOptionalVersion(`${db.tenantId}/${this.bucketId}/${name}`, version))
162+
all.push(withOptionalVersion(`${this.bucketId}/${name}`, version))
163163

164164
if (version) {
165-
all.push(
166-
withOptionalVersion(`${db.tenantId}/${this.bucketId}/${name}`, version) + '.info'
167-
)
165+
all.push(withOptionalVersion(`${this.bucketId}/${name}`, version) + '.info')
168166
}
169167
return all
170168
}, [] as string[])
171169

172-
await this.backend.deleteObjects(globalS3Bucket, prefixesToDelete)
170+
await this.backend.deleteObjects(prefixesToDelete)
173171

174172
await Promise.allSettled(
175173
data.map((object) =>
@@ -255,38 +253,38 @@ export class ObjectStorage {
255253

256254
const newVersion = randomUUID()
257255
const bucketId = this.bucketId
258-
const s3SourceKey = `${this.db.tenantId}/${bucketId}/${sourceKey}`
259-
const s3DestinationKey = `${this.db.tenantId}/${bucketId}/${destinationKey}`
260-
261-
try {
262-
// We check if the user has permission to copy the object to the destination key
263-
const originObject = await this.db.findObject(
264-
this.bucketId,
265-
sourceKey,
266-
'bucket_id,metadata,version'
267-
)
256+
const s3SourceKey = `${bucketId}/${sourceKey}`
257+
const s3DestinationKey = `${bucketId}/${destinationKey}`
258+
259+
// We check if the user has permission to copy the object to the destination key
260+
const originObject = await this.db.findObject(
261+
this.bucketId,
262+
sourceKey,
263+
'bucket_id,metadata,version'
264+
)
268265

269-
await this.uploader.canUpload({
270-
bucketId: this.bucketId,
271-
objectName: destinationKey,
272-
isUpsert: false,
273-
})
266+
await this.uploader.canUpload({
267+
bucketId: this.bucketId,
268+
objectName: destinationKey,
269+
isUpsert: false,
270+
})
274271

272+
try {
275273
const copyResult = await this.backend.copyObject(
276-
globalS3Bucket,
277274
s3SourceKey,
278275
originObject.version,
279276
s3DestinationKey,
280277
newVersion
281278
)
282279

283-
const metadata = await this.backend.headObject(globalS3Bucket, s3DestinationKey, newVersion)
280+
const metadata = await this.backend.headObject(s3DestinationKey, newVersion)
284281

285282
const destObject = await this.db.createObject({
286283
...originObject,
287284
name: destinationKey,
288285
owner,
289286
metadata,
287+
version: newVersion,
290288
})
291289

292290
await ObjectCreatedCopyEvent.sendWebhook({
@@ -325,8 +323,8 @@ export class ObjectStorage {
325323
}
326324

327325
const newVersion = randomUUID()
328-
const s3SourceKey = `${this.db.tenantId}/${this.bucketId}/${sourceObjectName}`
329-
const s3DestinationKey = `${this.db.tenantId}/${this.bucketId}/${destinationObjectName}`
326+
const s3SourceKey = `${this.bucketId}/${sourceObjectName}`
327+
const s3DestinationKey = `${this.bucketId}/${destinationObjectName}`
330328

331329
await this.db.testPermission((db) => {
332330
return Promise.all([
@@ -352,15 +350,9 @@ export class ObjectStorage {
352350
.findObject(this.bucketId, sourceObjectName, 'id, version')
353351

354352
try {
355-
await this.backend.copyObject(
356-
globalS3Bucket,
357-
s3SourceKey,
358-
sourceObj.version,
359-
s3DestinationKey,
360-
newVersion
361-
)
353+
await this.backend.copyObject(s3SourceKey, sourceObj.version, s3DestinationKey, newVersion)
362354

363-
const metadata = await this.backend.headObject(globalS3Bucket, s3DestinationKey, newVersion)
355+
const metadata = await this.backend.headObject(s3DestinationKey, newVersion)
364356

365357
await this.db.asSuperUser().withTransaction(async (db) => {
366358
await db.createObject({
@@ -372,14 +364,14 @@ export class ObjectStorage {
372364
})
373365

374366
await db.deleteObject(this.bucketId, sourceObjectName, sourceObj.version)
367+
await ObjectAdminDelete.send({
368+
name: sourceObjectName,
369+
bucketId: this.bucketId,
370+
tenant: this.db.tenant(),
371+
version: sourceObj.version,
372+
})
375373

376-
await Promise.all([
377-
ObjectAdminDelete.send({
378-
name: sourceObjectName,
379-
bucketId: this.bucketId,
380-
tenant: this.db.tenant(),
381-
version: sourceObj.version,
382-
}),
374+
await Promise.allSettled([
383375
ObjectRemovedMove.sendWebhook({
384376
tenant: this.db.tenant(),
385377
name: sourceObjectName,

0 commit comments

Comments
 (0)