@guayaba/workflow-piece-google-cloud-storage 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.json +33 -0
- package/README.md +5 -0
- package/assets/logo.png +0 -0
- package/package.json +21 -0
- package/src/i18n/de.json +123 -0
- package/src/i18n/es.json +123 -0
- package/src/i18n/fr.json +123 -0
- package/src/i18n/ja.json +123 -0
- package/src/i18n/nl.json +123 -0
- package/src/i18n/pt.json +123 -0
- package/src/i18n/translation.json +123 -0
- package/src/i18n/zh.json +123 -0
- package/src/index.ts +46 -0
- package/src/lib/actions/clone-object.ts +73 -0
- package/src/lib/actions/create-bucket-acl.ts +56 -0
- package/src/lib/actions/create-bucket-default-object-acl.ts +56 -0
- package/src/lib/actions/create-bucket.ts +73 -0
- package/src/lib/actions/create-object-acl.ts +79 -0
- package/src/lib/actions/delete-bucket-acl.ts +50 -0
- package/src/lib/actions/delete-bucket-default-object-acl.ts +50 -0
- package/src/lib/actions/delete-empty-bucket.ts +40 -0
- package/src/lib/actions/delete-object-acl.ts +62 -0
- package/src/lib/actions/delete-object.ts +57 -0
- package/src/lib/actions/search-buckets.ts +90 -0
- package/src/lib/actions/search-objects.ts +99 -0
- package/src/lib/common/auth.ts +14 -0
- package/src/lib/common/client.ts +63 -0
- package/src/lib/common/props.ts +249 -0
- package/src/lib/triggers/new-object-created.ts +171 -0
- package/src/lib/triggers/object-updated.ts +171 -0
- package/tsconfig.json +20 -0
- package/tsconfig.lib.json +13 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { createAction, OAuth2PropertyValue } from '@guayaba/workflows-framework';
|
|
2
|
+
import { googleCloudStorageAuth } from '../common/auth';
|
|
3
|
+
import { gcsCommon } from '../common/client';
|
|
4
|
+
import { bucketDropdown, aclEntityProperty, bucketAclRoleProperty, projectIdProperty } from '../common/props';
|
|
5
|
+
import { HttpMethod } from '@guayaba/workflows-common';
|
|
6
|
+
|
|
7
|
+
export const createBucketAcl = createAction({
|
|
8
|
+
auth: googleCloudStorageAuth,
|
|
9
|
+
name: 'create_bucket_acl',
|
|
10
|
+
displayName: 'Create Bucket ACL',
|
|
11
|
+
description: 'Add an ACL entry at bucket level. Perfect for granting permission to manage the bucket.',
|
|
12
|
+
props: {
|
|
13
|
+
projectId: projectIdProperty,
|
|
14
|
+
bucket: bucketDropdown,
|
|
15
|
+
entity: aclEntityProperty,
|
|
16
|
+
role: bucketAclRoleProperty,
|
|
17
|
+
},
|
|
18
|
+
async run(context) {
|
|
19
|
+
const { bucket, entity, role } = context.propsValue;
|
|
20
|
+
const auth = context.auth as OAuth2PropertyValue;
|
|
21
|
+
|
|
22
|
+
const aclEntry = {
|
|
23
|
+
entity,
|
|
24
|
+
role,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
const response = await gcsCommon.makeRequest(
|
|
29
|
+
HttpMethod.POST,
|
|
30
|
+
`/b/${bucket}/acl`,
|
|
31
|
+
auth.access_token,
|
|
32
|
+
aclEntry
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
success: true,
|
|
37
|
+
bucket,
|
|
38
|
+
acl: response,
|
|
39
|
+
};
|
|
40
|
+
} catch (error: any) {
|
|
41
|
+
if (error.response?.status === 400) {
|
|
42
|
+
throw new Error('Bad request. This bucket may have uniform bucket-level access enabled, which doesn\'t support bucket ACLs. Use IAM policies instead.');
|
|
43
|
+
}
|
|
44
|
+
if (error.response?.status === 403) {
|
|
45
|
+
throw new Error('Access denied. You need storage.buckets.update permission to modify bucket ACLs.');
|
|
46
|
+
}
|
|
47
|
+
if (error.response?.status === 404) {
|
|
48
|
+
throw new Error(`Bucket "${bucket}" not found.`);
|
|
49
|
+
}
|
|
50
|
+
if (error.response?.status === 409) {
|
|
51
|
+
throw new Error(`ACL entry for entity "${entity}" already exists on bucket "${bucket}".`);
|
|
52
|
+
}
|
|
53
|
+
throw new Error(`Failed to create bucket ACL: ${error.message || 'Unknown error'}`);
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
});
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { createAction, OAuth2PropertyValue } from '@guayaba/workflows-framework';
|
|
2
|
+
import { googleCloudStorageAuth } from '../common/auth';
|
|
3
|
+
import { gcsCommon } from '../common/client';
|
|
4
|
+
import { bucketDropdown, aclEntityProperty, objectAclRoleProperty, projectIdProperty } from '../common/props';
|
|
5
|
+
import { HttpMethod } from '@guayaba/workflows-common';
|
|
6
|
+
|
|
7
|
+
export const createBucketDefaultObjectAcl = createAction({
|
|
8
|
+
auth: googleCloudStorageAuth,
|
|
9
|
+
name: 'create_bucket_default_object_acl',
|
|
10
|
+
displayName: 'Create Bucket Default Object ACL',
|
|
11
|
+
description: 'Set default ACLs for new objects added to a bucket. Perfect for automatically assigning permissions to new uploads.',
|
|
12
|
+
props: {
|
|
13
|
+
projectId: projectIdProperty,
|
|
14
|
+
bucket: bucketDropdown,
|
|
15
|
+
entity: aclEntityProperty,
|
|
16
|
+
role: objectAclRoleProperty,
|
|
17
|
+
},
|
|
18
|
+
async run(context) {
|
|
19
|
+
const { bucket, entity, role } = context.propsValue;
|
|
20
|
+
const auth = context.auth as OAuth2PropertyValue;
|
|
21
|
+
|
|
22
|
+
const aclEntry = {
|
|
23
|
+
entity,
|
|
24
|
+
role,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
const response = await gcsCommon.makeRequest(
|
|
29
|
+
HttpMethod.POST,
|
|
30
|
+
`/b/${bucket}/defaultObjectAcl`,
|
|
31
|
+
auth.access_token,
|
|
32
|
+
aclEntry
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
success: true,
|
|
37
|
+
bucket,
|
|
38
|
+
acl: response,
|
|
39
|
+
};
|
|
40
|
+
} catch (error: any) {
|
|
41
|
+
if (error.response?.status === 400) {
|
|
42
|
+
throw new Error('Bad request. This bucket may have uniform bucket-level access enabled, which doesn\'t support default object ACLs. Use IAM policies instead.');
|
|
43
|
+
}
|
|
44
|
+
if (error.response?.status === 403) {
|
|
45
|
+
throw new Error('Access denied. You need storage.buckets.update permission to modify bucket default object ACLs.');
|
|
46
|
+
}
|
|
47
|
+
if (error.response?.status === 404) {
|
|
48
|
+
throw new Error(`Bucket "${bucket}" not found.`);
|
|
49
|
+
}
|
|
50
|
+
if (error.response?.status === 409) {
|
|
51
|
+
throw new Error(`Default object ACL entry for entity "${entity}" already exists on bucket "${bucket}".`);
|
|
52
|
+
}
|
|
53
|
+
throw new Error(`Failed to create bucket default object ACL: ${error.message || 'Unknown error'}`);
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
});
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { createAction, Property, OAuth2PropertyValue } from '@guayaba/workflows-framework';
|
|
2
|
+
import { googleCloudStorageAuth } from '../common/auth';
|
|
3
|
+
import { gcsCommon } from '../common/client';
|
|
4
|
+
import { projectIdProperty, bucketNameProperty, locationProperty, storageClassProperty } from '../common/props';
|
|
5
|
+
import { HttpMethod } from '@guayaba/workflows-common';
|
|
6
|
+
|
|
7
|
+
export const createBucket = createAction({
|
|
8
|
+
auth: googleCloudStorageAuth,
|
|
9
|
+
name: 'create_bucket',
|
|
10
|
+
displayName: 'Create Bucket',
|
|
11
|
+
description: 'Create a new bucket in a specified location/configuration. Perfect for automating storage provisioning for new projects.',
|
|
12
|
+
props: {
|
|
13
|
+
projectId: projectIdProperty,
|
|
14
|
+
name: bucketNameProperty,
|
|
15
|
+
location: locationProperty,
|
|
16
|
+
storageClass: storageClassProperty,
|
|
17
|
+
versioning: Property.Checkbox({
|
|
18
|
+
displayName: 'Enable Versioning',
|
|
19
|
+
required: false,
|
|
20
|
+
}),
|
|
21
|
+
uniformBucketLevelAccess: Property.Checkbox({
|
|
22
|
+
displayName: 'Uniform Bucket Level Access',
|
|
23
|
+
required: false,
|
|
24
|
+
}),
|
|
25
|
+
labels: Property.Object({
|
|
26
|
+
displayName: 'Labels',
|
|
27
|
+
description: 'Key-value pairs for bucket labels',
|
|
28
|
+
required: false,
|
|
29
|
+
}),
|
|
30
|
+
},
|
|
31
|
+
async run(context) {
|
|
32
|
+
const { projectId, name, location, storageClass, versioning, uniformBucketLevelAccess, labels } = context.propsValue;
|
|
33
|
+
const auth = context.auth as OAuth2PropertyValue;
|
|
34
|
+
|
|
35
|
+
const bucketConfig: any = {
|
|
36
|
+
name,
|
|
37
|
+
location: location || 'US',
|
|
38
|
+
storageClass: storageClass || 'STANDARD',
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
if (versioning) {
|
|
42
|
+
bucketConfig.versioning = { enabled: true };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (uniformBucketLevelAccess !== undefined) {
|
|
46
|
+
bucketConfig.iamConfiguration = {
|
|
47
|
+
uniformBucketLevelAccess: {
|
|
48
|
+
enabled: uniformBucketLevelAccess,
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (labels) {
|
|
54
|
+
bucketConfig.labels = labels;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
const response = await gcsCommon.makeRequest(HttpMethod.POST, `/b?project=${projectId}`, auth.access_token, bucketConfig);
|
|
59
|
+
return response;
|
|
60
|
+
} catch (error: any) {
|
|
61
|
+
if (error.response?.status === 409) {
|
|
62
|
+
throw new Error(`Bucket "${name}" already exists. Bucket names must be globally unique.`);
|
|
63
|
+
}
|
|
64
|
+
if (error.response?.status === 403) {
|
|
65
|
+
throw new Error('Access denied. Check your permissions for the selected project.');
|
|
66
|
+
}
|
|
67
|
+
if (error.response?.status === 400) {
|
|
68
|
+
throw new Error('Invalid bucket configuration. Check bucket name format and project settings.');
|
|
69
|
+
}
|
|
70
|
+
throw new Error(`Failed to create bucket: ${error.message || 'Unknown error'}`);
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
});
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createAction,
|
|
3
|
+
Property,
|
|
4
|
+
OAuth2PropertyValue,
|
|
5
|
+
} from '@guayaba/workflows-framework';
|
|
6
|
+
import { googleCloudStorageAuth } from '../common/auth';
|
|
7
|
+
import { gcsCommon } from '../common/client';
|
|
8
|
+
import {
|
|
9
|
+
bucketDropdown,
|
|
10
|
+
objectDropdown,
|
|
11
|
+
aclEntityProperty,
|
|
12
|
+
objectAclRoleProperty,
|
|
13
|
+
projectIdProperty,
|
|
14
|
+
} from '../common/props';
|
|
15
|
+
import { HttpMethod } from '@guayaba/workflows-common';
|
|
16
|
+
|
|
17
|
+
export const createObjectAcl = createAction({
|
|
18
|
+
auth: googleCloudStorageAuth,
|
|
19
|
+
name: 'create_object_acl',
|
|
20
|
+
displayName: 'Create Object ACL',
|
|
21
|
+
description: 'Add an ACL entry to an object (grant a permission). Perfect for granting read/write access to a user or group.',
|
|
22
|
+
props: {
|
|
23
|
+
projectId: projectIdProperty,
|
|
24
|
+
bucket: bucketDropdown,
|
|
25
|
+
object: objectDropdown('bucket'),
|
|
26
|
+
entity: aclEntityProperty,
|
|
27
|
+
role: objectAclRoleProperty,
|
|
28
|
+
generation: Property.Number({
|
|
29
|
+
displayName: 'Generation',
|
|
30
|
+
description: 'Optional generation number for versioned objects',
|
|
31
|
+
required: false,
|
|
32
|
+
}),
|
|
33
|
+
},
|
|
34
|
+
async run(context) {
|
|
35
|
+
const { bucket, object, entity, role, generation } = context.propsValue;
|
|
36
|
+
const auth = context.auth as OAuth2PropertyValue;
|
|
37
|
+
|
|
38
|
+
const aclEntry = {
|
|
39
|
+
entity,
|
|
40
|
+
role,
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
let path = `/b/${bucket}/o/${encodeURIComponent(object as string)}/acl`;
|
|
44
|
+
if (generation) {
|
|
45
|
+
path += `?generation=${generation}`;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
const response = await gcsCommon.makeRequest(
|
|
50
|
+
HttpMethod.POST,
|
|
51
|
+
path,
|
|
52
|
+
auth.access_token,
|
|
53
|
+
aclEntry
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
success: true,
|
|
58
|
+
bucket,
|
|
59
|
+
object,
|
|
60
|
+
generation: generation || 'latest',
|
|
61
|
+
acl: response,
|
|
62
|
+
};
|
|
63
|
+
} catch (error: any) {
|
|
64
|
+
if (error.response?.status === 400) {
|
|
65
|
+
throw new Error('Bad request. This bucket may have uniform bucket-level access enabled, which doesn\'t support object ACLs. Use IAM policies instead.');
|
|
66
|
+
}
|
|
67
|
+
if (error.response?.status === 403) {
|
|
68
|
+
throw new Error('Access denied. You need storage.objects.setIamPolicy permission or OWNER ACL permission on the object.');
|
|
69
|
+
}
|
|
70
|
+
if (error.response?.status === 404) {
|
|
71
|
+
throw new Error(`Object "${object}" not found in bucket "${bucket}".`);
|
|
72
|
+
}
|
|
73
|
+
if (error.response?.status === 409) {
|
|
74
|
+
throw new Error(`ACL entry for entity "${entity}" already exists on this object.`);
|
|
75
|
+
}
|
|
76
|
+
throw new Error(`Failed to create object ACL: ${error.message || 'Unknown error'}`);
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
});
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { createAction, OAuth2PropertyValue } from '@guayaba/workflows-framework';
|
|
2
|
+
import { googleCloudStorageAuth } from '../common/auth';
|
|
3
|
+
import { gcsCommon } from '../common/client';
|
|
4
|
+
import { bucketDropdown, aclEntityProperty, projectIdProperty } from '../common/props';
|
|
5
|
+
import { HttpMethod } from '@guayaba/workflows-common';
|
|
6
|
+
|
|
7
|
+
export const deleteBucketAcl = createAction({
|
|
8
|
+
auth: googleCloudStorageAuth,
|
|
9
|
+
name: 'delete_bucket_acl',
|
|
10
|
+
displayName: 'Delete Bucket ACL',
|
|
11
|
+
description: 'Remove an ACL entry from a bucket. Perfect for revoking access for a user or group.',
|
|
12
|
+
props: {
|
|
13
|
+
projectId: projectIdProperty,
|
|
14
|
+
bucket: bucketDropdown,
|
|
15
|
+
entity: aclEntityProperty,
|
|
16
|
+
},
|
|
17
|
+
async run(context) {
|
|
18
|
+
const { bucket, entity } = context.propsValue;
|
|
19
|
+
const auth = context.auth as OAuth2PropertyValue;
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
await gcsCommon.makeRequest(
|
|
23
|
+
HttpMethod.DELETE,
|
|
24
|
+
`/b/${bucket}/acl/${encodeURIComponent(entity)}`,
|
|
25
|
+
auth.access_token
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
success: true,
|
|
30
|
+
bucket,
|
|
31
|
+
entity,
|
|
32
|
+
message: `ACL entry for entity "${entity}" removed successfully from bucket "${bucket}"`,
|
|
33
|
+
};
|
|
34
|
+
} catch (error: any) {
|
|
35
|
+
if (error.response?.status === 400) {
|
|
36
|
+
throw new Error('Bad request. This bucket may have uniform bucket-level access enabled, which doesn\'t support bucket ACLs. Use IAM policies instead.');
|
|
37
|
+
}
|
|
38
|
+
if (error.response?.status === 403) {
|
|
39
|
+
throw new Error('Access denied. You need storage.buckets.update permission to modify bucket ACLs.');
|
|
40
|
+
}
|
|
41
|
+
if (error.response?.status === 404) {
|
|
42
|
+
if (error.response?.data?.error?.message?.includes('ACL')) {
|
|
43
|
+
throw new Error(`ACL entry for entity "${entity}" not found on bucket "${bucket}".`);
|
|
44
|
+
}
|
|
45
|
+
throw new Error(`Bucket "${bucket}" not found.`);
|
|
46
|
+
}
|
|
47
|
+
throw new Error(`Failed to delete bucket ACL: ${error.message || 'Unknown error'}`);
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
});
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { createAction, OAuth2PropertyValue } from '@guayaba/workflows-framework';
|
|
2
|
+
import { googleCloudStorageAuth } from '../common/auth';
|
|
3
|
+
import { gcsCommon } from '../common/client';
|
|
4
|
+
import { bucketDropdown, aclEntityProperty, projectIdProperty } from '../common/props';
|
|
5
|
+
import { HttpMethod } from '@guayaba/workflows-common';
|
|
6
|
+
|
|
7
|
+
export const deleteBucketDefaultObjectAcl = createAction({
|
|
8
|
+
auth: googleCloudStorageAuth,
|
|
9
|
+
name: 'delete_bucket_default_object_acl',
|
|
10
|
+
displayName: 'Delete Bucket Default Object ACL',
|
|
11
|
+
description: 'Remove default ACL settings from a bucket. Perfect for reverting to default behavior.',
|
|
12
|
+
props: {
|
|
13
|
+
projectId: projectIdProperty,
|
|
14
|
+
bucket: bucketDropdown,
|
|
15
|
+
entity: aclEntityProperty,
|
|
16
|
+
},
|
|
17
|
+
async run(context) {
|
|
18
|
+
const { bucket, entity } = context.propsValue;
|
|
19
|
+
const auth = context.auth as OAuth2PropertyValue;
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
await gcsCommon.makeRequest(
|
|
23
|
+
HttpMethod.DELETE,
|
|
24
|
+
`/b/${bucket}/defaultObjectAcl/${encodeURIComponent(entity)}`,
|
|
25
|
+
auth.access_token
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
success: true,
|
|
30
|
+
bucket,
|
|
31
|
+
entity,
|
|
32
|
+
message: `Default object ACL entry for entity "${entity}" removed successfully from bucket "${bucket}"`,
|
|
33
|
+
};
|
|
34
|
+
} catch (error: any) {
|
|
35
|
+
if (error.response?.status === 400) {
|
|
36
|
+
throw new Error('Bad request. This bucket may have uniform bucket-level access enabled, which doesn\'t support default object ACLs. Use IAM policies instead.');
|
|
37
|
+
}
|
|
38
|
+
if (error.response?.status === 403) {
|
|
39
|
+
throw new Error('Access denied. You need storage.buckets.update permission to modify bucket default object ACLs.');
|
|
40
|
+
}
|
|
41
|
+
if (error.response?.status === 404) {
|
|
42
|
+
if (error.response?.data?.error?.message?.includes('ACL')) {
|
|
43
|
+
throw new Error(`Default object ACL entry for entity "${entity}" not found on bucket "${bucket}".`);
|
|
44
|
+
}
|
|
45
|
+
throw new Error(`Bucket "${bucket}" not found.`);
|
|
46
|
+
}
|
|
47
|
+
throw new Error(`Failed to delete bucket default object ACL: ${error.message || 'Unknown error'}`);
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { createAction, OAuth2PropertyValue } from '@guayaba/workflows-framework';
|
|
2
|
+
import { googleCloudStorageAuth } from '../common/auth';
|
|
3
|
+
import { gcsCommon } from '../common/client';
|
|
4
|
+
import { bucketDropdown, projectIdProperty } from '../common/props';
|
|
5
|
+
import { HttpMethod } from '@guayaba/workflows-common';
|
|
6
|
+
|
|
7
|
+
export const deleteEmptyBucket = createAction({
|
|
8
|
+
auth: googleCloudStorageAuth,
|
|
9
|
+
name: 'delete_empty_bucket',
|
|
10
|
+
displayName: 'Delete Empty Bucket',
|
|
11
|
+
description: 'Clean up unused buckets by deleting them if they contain no live objects.',
|
|
12
|
+
props: {
|
|
13
|
+
projectId: projectIdProperty,
|
|
14
|
+
bucket: bucketDropdown,
|
|
15
|
+
},
|
|
16
|
+
async run(context) {
|
|
17
|
+
const { bucket } = context.propsValue;
|
|
18
|
+
const auth = context.auth as OAuth2PropertyValue;
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
await gcsCommon.makeRequest(HttpMethod.DELETE, `/b/${bucket}`, auth.access_token);
|
|
22
|
+
|
|
23
|
+
return {
|
|
24
|
+
success: true,
|
|
25
|
+
message: `Bucket "${bucket}" deleted successfully`,
|
|
26
|
+
};
|
|
27
|
+
} catch (error: any) {
|
|
28
|
+
if (error.response?.status === 409) {
|
|
29
|
+
throw new Error(`Bucket "${bucket}" contains live or noncurrent objects and cannot be deleted. Remove all objects first.`);
|
|
30
|
+
}
|
|
31
|
+
if (error.response?.status === 403) {
|
|
32
|
+
throw new Error('Access denied. You need storage.buckets.delete permission to delete this bucket.');
|
|
33
|
+
}
|
|
34
|
+
if (error.response?.status === 404) {
|
|
35
|
+
throw new Error(`Bucket "${bucket}" not found. It may have already been deleted.`);
|
|
36
|
+
}
|
|
37
|
+
throw new Error(`Failed to delete bucket: ${error.message || 'Unknown error'}`);
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
});
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { createAction, Property, OAuth2PropertyValue } from '@guayaba/workflows-framework';
|
|
2
|
+
import { googleCloudStorageAuth } from '../common/auth';
|
|
3
|
+
import { gcsCommon } from '../common/client';
|
|
4
|
+
import { bucketDropdown, objectDropdown, aclEntityProperty, projectIdProperty } from '../common/props';
|
|
5
|
+
import { HttpMethod } from '@guayaba/workflows-common';
|
|
6
|
+
|
|
7
|
+
export const deleteObjectAcl = createAction({
|
|
8
|
+
auth: googleCloudStorageAuth,
|
|
9
|
+
name: 'delete_object_acl',
|
|
10
|
+
displayName: 'Delete Object ACL',
|
|
11
|
+
description: 'Remove an ACL entry from an object. Perfect for revoking access for a user.',
|
|
12
|
+
props: {
|
|
13
|
+
projectId: projectIdProperty,
|
|
14
|
+
bucket: bucketDropdown,
|
|
15
|
+
object: objectDropdown('bucket'),
|
|
16
|
+
entity: aclEntityProperty,
|
|
17
|
+
generation: Property.Number({
|
|
18
|
+
displayName: 'Generation',
|
|
19
|
+
description: 'Optional generation number for versioned objects',
|
|
20
|
+
required: false,
|
|
21
|
+
}),
|
|
22
|
+
},
|
|
23
|
+
async run(context) {
|
|
24
|
+
const { bucket, object, entity, generation } = context.propsValue;
|
|
25
|
+
const auth = context.auth as OAuth2PropertyValue;
|
|
26
|
+
|
|
27
|
+
let path = `/b/${bucket}/o/${encodeURIComponent(object as string)}/acl/${encodeURIComponent(entity as string)}`;
|
|
28
|
+
if (generation) {
|
|
29
|
+
path += `?generation=${generation}`;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
await gcsCommon.makeRequest(HttpMethod.DELETE, path, auth.access_token);
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
success: true,
|
|
37
|
+
bucket,
|
|
38
|
+
object,
|
|
39
|
+
entity,
|
|
40
|
+
generation: generation || 'latest',
|
|
41
|
+
message: `ACL entry for entity "${entity}" removed successfully from object "${object}"`,
|
|
42
|
+
};
|
|
43
|
+
} catch (error: any) {
|
|
44
|
+
if (error.response?.status === 400) {
|
|
45
|
+
if (entity.includes('user-') && entity.includes('@')) {
|
|
46
|
+
throw new Error('Cannot remove OWNER access from the object owner. The only way to remove owner access is to delete or replace the object.');
|
|
47
|
+
}
|
|
48
|
+
throw new Error('Bad request. This bucket may have uniform bucket-level access enabled, which doesn\'t support object ACLs. Use IAM policies instead.');
|
|
49
|
+
}
|
|
50
|
+
if (error.response?.status === 403) {
|
|
51
|
+
throw new Error('Access denied. You need storage.objects.setIamPolicy permission or OWNER ACL permission on the object.');
|
|
52
|
+
}
|
|
53
|
+
if (error.response?.status === 404) {
|
|
54
|
+
if (error.response?.data?.error?.message?.includes('ACL')) {
|
|
55
|
+
throw new Error(`ACL entry for entity "${entity}" not found on object "${object}".`);
|
|
56
|
+
}
|
|
57
|
+
throw new Error(`Object "${object}" not found in bucket "${bucket}".`);
|
|
58
|
+
}
|
|
59
|
+
throw new Error(`Failed to delete object ACL: ${error.message || 'Unknown error'}`);
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
});
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { createAction, Property, OAuth2PropertyValue } from '@guayaba/workflows-framework';
|
|
2
|
+
import { googleCloudStorageAuth } from '../common/auth';
|
|
3
|
+
import { gcsCommon } from '../common/client';
|
|
4
|
+
import { bucketDropdown, objectDropdown, projectIdProperty } from '../common/props';
|
|
5
|
+
import { HttpMethod } from '@guayaba/workflows-common';
|
|
6
|
+
|
|
7
|
+
export const deleteObject = createAction({
|
|
8
|
+
auth: googleCloudStorageAuth,
|
|
9
|
+
name: 'delete_object',
|
|
10
|
+
displayName: 'Delete Object',
|
|
11
|
+
description: 'Permanently delete a specific object. Perfect for removing obsolete files.',
|
|
12
|
+
props: {
|
|
13
|
+
projectId: projectIdProperty,
|
|
14
|
+
bucket: bucketDropdown,
|
|
15
|
+
object: objectDropdown('bucket'),
|
|
16
|
+
generation: Property.Number({
|
|
17
|
+
displayName: 'Generation',
|
|
18
|
+
description: 'Optional generation number for versioned objects (permanently deletes a specific revision)',
|
|
19
|
+
required: false,
|
|
20
|
+
}),
|
|
21
|
+
},
|
|
22
|
+
async run(context) {
|
|
23
|
+
const { bucket, object, generation } = context.propsValue;
|
|
24
|
+
const auth = context.auth as OAuth2PropertyValue;
|
|
25
|
+
|
|
26
|
+
let path = `/b/${bucket}/o/${encodeURIComponent(object as string)}`;
|
|
27
|
+
if (generation) {
|
|
28
|
+
path += `?generation=${generation}`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
await gcsCommon.makeRequest(HttpMethod.DELETE, path, auth.access_token);
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
success: true,
|
|
36
|
+
bucket,
|
|
37
|
+
object,
|
|
38
|
+
generation: generation || 'latest',
|
|
39
|
+
message: `Object "${object}" deleted successfully from bucket "${bucket}"`,
|
|
40
|
+
};
|
|
41
|
+
} catch (error: any) {
|
|
42
|
+
if (error.response?.status === 404) {
|
|
43
|
+
throw new Error(`Object "${object}" not found in bucket "${bucket}". It may have already been deleted.`);
|
|
44
|
+
}
|
|
45
|
+
if (error.response?.status === 403) {
|
|
46
|
+
throw new Error('Access denied. You need storage.objects.delete permission to delete this object.');
|
|
47
|
+
}
|
|
48
|
+
if (error.response?.status === 412) {
|
|
49
|
+
throw new Error('Precondition failed. Object may have been modified or deleted by another process.');
|
|
50
|
+
}
|
|
51
|
+
if (error.response?.status === 400) {
|
|
52
|
+
throw new Error('Invalid request. Check object name and generation parameters.');
|
|
53
|
+
}
|
|
54
|
+
throw new Error(`Failed to delete object: ${error.message || 'Unknown error'}`);
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
});
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { createAction, Property, OAuth2PropertyValue } from '@guayaba/workflows-framework';
|
|
2
|
+
import { googleCloudStorageAuth } from '../common/auth';
|
|
3
|
+
import { gcsCommon } from '../common/client';
|
|
4
|
+
import { projectIdProperty } from '../common/props';
|
|
5
|
+
import { HttpMethod } from '@guayaba/workflows-common';
|
|
6
|
+
|
|
7
|
+
export const searchBuckets = createAction({
|
|
8
|
+
auth: googleCloudStorageAuth,
|
|
9
|
+
name: 'search_buckets',
|
|
10
|
+
displayName: 'Search Buckets',
|
|
11
|
+
description: 'Search buckets by name. Perfect for finding buckets in your project.',
|
|
12
|
+
props: {
|
|
13
|
+
projectId: projectIdProperty,
|
|
14
|
+
prefix: Property.ShortText({
|
|
15
|
+
displayName: 'Name Prefix',
|
|
16
|
+
description: 'Filter buckets whose names begin with this prefix',
|
|
17
|
+
required: false,
|
|
18
|
+
}),
|
|
19
|
+
includeSoftDeleted: Property.Checkbox({
|
|
20
|
+
displayName: 'Include Soft-Deleted',
|
|
21
|
+
description: 'Include soft-deleted bucket versions in results',
|
|
22
|
+
required: false,
|
|
23
|
+
}),
|
|
24
|
+
projection: Property.StaticDropdown({
|
|
25
|
+
displayName: 'Projection',
|
|
26
|
+
description: 'Set of properties to return',
|
|
27
|
+
required: false,
|
|
28
|
+
options: {
|
|
29
|
+
options: [
|
|
30
|
+
{ label: 'No ACLs (faster)', value: 'noAcl' },
|
|
31
|
+
{ label: 'Full (includes ACLs)', value: 'full' },
|
|
32
|
+
],
|
|
33
|
+
},
|
|
34
|
+
}),
|
|
35
|
+
pageToken: Property.ShortText({
|
|
36
|
+
displayName: 'Page Token',
|
|
37
|
+
description: 'Token for pagination (from previous response)',
|
|
38
|
+
required: false,
|
|
39
|
+
}),
|
|
40
|
+
maxResults: Property.Number({
|
|
41
|
+
displayName: 'Max Results',
|
|
42
|
+
description: 'Maximum number of buckets to return',
|
|
43
|
+
required: false,
|
|
44
|
+
}),
|
|
45
|
+
},
|
|
46
|
+
async run(context) {
|
|
47
|
+
const {
|
|
48
|
+
projectId,
|
|
49
|
+
prefix,
|
|
50
|
+
includeSoftDeleted,
|
|
51
|
+
projection,
|
|
52
|
+
pageToken,
|
|
53
|
+
maxResults
|
|
54
|
+
} = context.propsValue;
|
|
55
|
+
const auth = context.auth as OAuth2PropertyValue;
|
|
56
|
+
|
|
57
|
+
const params = new URLSearchParams();
|
|
58
|
+
params.append('project', projectId!);
|
|
59
|
+
if (prefix) params.append('prefix', prefix);
|
|
60
|
+
if (includeSoftDeleted) params.append('softDeleted', 'true');
|
|
61
|
+
if (projection) params.append('projection', projection);
|
|
62
|
+
if (pageToken) params.append('pageToken', pageToken);
|
|
63
|
+
if (maxResults) params.append('maxResults', maxResults.toString());
|
|
64
|
+
|
|
65
|
+
const path = `/b?${params.toString()}`;
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
const response = await gcsCommon.makeRequest(HttpMethod.GET, path, auth.access_token);
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
success: true,
|
|
72
|
+
projectId,
|
|
73
|
+
items: response.items || [],
|
|
74
|
+
nextPageToken: response.nextPageToken,
|
|
75
|
+
totalBuckets: response.items?.length || 0,
|
|
76
|
+
};
|
|
77
|
+
} catch (error: any) {
|
|
78
|
+
if (error.response?.status === 403) {
|
|
79
|
+
throw new Error('Access denied. You need storage.buckets.list permission to search buckets in this project.');
|
|
80
|
+
}
|
|
81
|
+
if (error.response?.status === 404) {
|
|
82
|
+
throw new Error(`Project "${projectId}" not found or you don't have access to it.`);
|
|
83
|
+
}
|
|
84
|
+
if (error.response?.status === 400) {
|
|
85
|
+
throw new Error('Invalid search parameters. Check your project ID and other filters.');
|
|
86
|
+
}
|
|
87
|
+
throw new Error(`Failed to search buckets: ${error.message || 'Unknown error'}`);
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
});
|