From e8243c61c0885c7ca80f00e0a4da546ad5ed6385 Mon Sep 17 00:00:00 2001 From: Tim Holm Date: Mon, 18 Mar 2024 09:53:38 +1100 Subject: [PATCH] fix: Make permission names and methods consistent (#224) --- src/resources/bucket.ts | 54 +++++++++++++++++++++++++++++++++----- src/resources/keyvalue.ts | 55 ++++++++++++++++++++++++++++++++++----- src/resources/queue.ts | 9 +++++++ src/resources/secret.ts | 38 +++++++++++++++++++++++---- src/resources/topic.ts | 33 +++++++++++++++++++---- 5 files changed, 167 insertions(+), 22 deletions(-) diff --git a/src/resources/bucket.ts b/src/resources/bucket.ts index e1c4620..452ef07 100644 --- a/src/resources/bucket.ts +++ b/src/resources/bucket.ts @@ -47,9 +47,11 @@ import { import { BlobEventContext, BucketEventContext } from '../context/bucket'; import { fromGrpcError } from '../api/errors'; -type BucketPermission = 'reading' | 'writing' | 'deleting'; +type BucketPermissionLegacy = 'reading' | 'writing' | 'deleting'; -const everything: BucketPermission[] = ['reading', 'writing', 'deleting']; +type BucketPermission = 'read' | 'write' | 'delete'; + +const everything: BucketPermission[] = ['read', 'write', 'delete']; export type BucketNotificationType = 'write' | 'delete'; @@ -266,11 +268,11 @@ export class BucketResource extends SecureResource { protected permsToActions(...perms: BucketPermission[]): ActionsList { return perms.reduce((actions, perm) => { switch (perm) { - case 'reading': + case 'read': return [...actions, Action.BUCKETFILEGET, Action.BUCKETFILELIST]; - case 'writing': + case 'write': return [...actions, Action.BUCKETFILEPUT]; - case 'deleting': + case 'delete': return [...actions, Action.BUCKETFILEDELETE]; default: throw new Error( @@ -286,6 +288,46 @@ export class BucketResource extends SecureResource { return ResourceType.BUCKET; } + /** + * Return a bucket reference and register the permissions required by the currently scoped function for this resource. + * + * e.g. const imgs = resources.bucket('image').for('writing') + * + * @deprecated use allow instead + * + * @param perm the required permission set + * @param perms additional required permissions set + * @returns a usable bucket reference + */ + public for( + perm: BucketPermissionLegacy, + ...perms: BucketPermissionLegacy[] + ): Bucket { + console.warn("The 'for' method is deprecated, please use 'allow' instead."); + + // Translate to new permissions + const allPerms = [perm, ...perms].map((p) => { + switch (p) { + case 'reading': + return 'read'; + case 'writing': + return 'write'; + case 'deleting': + return 'delete'; + default: + throw new Error( + `unknown bucket permission ${p}, supported permissions are ${everything.join( + ', ' + )}` + ); + } + }); + + this.registerPolicy(...allPerms); + + return storage().bucket(this.name); + } + /** * Return a bucket reference and register the permissions required by the currently scoped function for this resource. * @@ -295,7 +337,7 @@ export class BucketResource extends SecureResource { * @param perms additional required permissions set * @returns a usable bucket reference */ - public for(perm: BucketPermission, ...perms: BucketPermission[]): Bucket { + public allow(perm: BucketPermission, ...perms: BucketPermission[]): Bucket { this.registerPolicy(perm, ...perms); return storage().bucket(this.name); diff --git a/src/resources/keyvalue.ts b/src/resources/keyvalue.ts index 0380c5b..de7911d 100644 --- a/src/resources/keyvalue.ts +++ b/src/resources/keyvalue.ts @@ -27,8 +27,10 @@ import { make, SecureResource } from './common'; import { fromGrpcError } from '../api/errors'; import { StoreRef } from '../api/keyvalue/v1/store'; -type StorePermission = 'getting' | 'setting' | 'deleting'; -const everything: StorePermission[] = ['getting', 'setting', 'deleting']; +type StorePermissionLegacy = 'getting' | 'setting' | 'deleting'; + +type StorePermission = 'get' | 'set' | 'delete'; +const everything: StorePermission[] = ['get', 'set', 'delete']; /** * A key/value store resource. @@ -70,11 +72,11 @@ export class KeyValueStoreResource< ): ActionMap[keyof ActionMap][] { const actions = perms.reduce((actions, perm) => { switch (perm) { - case 'getting': + case 'get': return [...actions, Action.KEYVALUESTOREREAD]; - case 'setting': + case 'set': return [...actions, Action.KEYVALUESTOREWRITE]; - case 'deleting': + case 'delete': return [...actions, Action.KEYVALUESTOREDELETE]; default: throw new Error( @@ -92,6 +94,44 @@ export class KeyValueStoreResource< return ResourceType.KEYVALUESTORE; } + /** + * Return a key/value store reference and register the permissions required by the currently scoped service for this resource. + * + * e.g. const customers = resources.kv('customers').for('getting', 'setting') + * + * @deprecated use allow instead + * @param perm the required permission set + * @param perms additional required permissions set + * @returns a usable key/value store reference + */ + public for( + perm: StorePermissionLegacy, + ...perms: StorePermissionLegacy[] + ): StoreRef { + console.warn("The 'for' method is deprecated, please use 'allow' instead."); + + const allPerms = [perm, ...perms].map((p) => { + switch (p) { + case 'getting': + return 'get'; + case 'setting': + return 'set'; + case 'deleting': + return 'delete'; + default: + throw new Error( + `unknown key/value store permission ${p}, supported permissions are ${everything.join( + ', ' + )}` + ); + } + }); + + this.registerPolicy(...allPerms); + + return keyvalue().store(this.name); + } + /** * Return a key/value store reference and register the permissions required by the currently scoped service for this resource. * @@ -101,7 +141,10 @@ export class KeyValueStoreResource< * @param perms additional required permissions set * @returns a usable key/value store reference */ - public for(perm: StorePermission, ...perms: StorePermission[]): StoreRef { + public allow( + perm: StorePermission, + ...perms: StorePermission[] + ): StoreRef { this.registerPolicy(perm, ...perms); return keyvalue().store(this.name); diff --git a/src/resources/queue.ts b/src/resources/queue.ts index 19295bc..6da2ac9 100644 --- a/src/resources/queue.ts +++ b/src/resources/queue.ts @@ -90,11 +90,20 @@ export class QueueResource< * * e.g. const taskQueue = resources.queue('work').for('enqueue') * + * @deprecated use allow instead * @param perm - the access that the currently scoped function is requesting to this resource. * @param perms - the access that the currently scoped function is requesting to this resource. * @returns a useable queue. */ public for(perm: QueuePermission, ...perms: QueuePermission[]): Queue { + console.warn("The 'for' method is deprecated, please use 'allow' instead"); + + this.registerPolicy(perm, ...perms); + + return queues().queue(this.name); + } + + public allow(perm: QueuePermission, ...perms: QueuePermission[]): Queue { this.registerPolicy(perm, ...perms); return queues().queue(this.name); diff --git a/src/resources/secret.ts b/src/resources/secret.ts index 8f0592f..f90933a 100644 --- a/src/resources/secret.ts +++ b/src/resources/secret.ts @@ -25,9 +25,11 @@ import { secrets, Secret } from '../api/secrets'; import { ActionsList, make, SecureResource } from './common'; import { fromGrpcError } from '../api/errors'; -type SecretPermission = 'putting' | 'accessing'; +type SecretPermission = 'put' | 'access'; -const everything: SecretPermission[] = ['putting', 'accessing']; +type SecretPermissionLegacy = 'putting' | 'accessing'; + +const everything: SecretPermission[] = ['put', 'access']; /** * Cloud secret resource for secret storage @@ -59,9 +61,9 @@ export class SecretResource extends SecureResource { protected permsToActions(...perms: SecretPermission[]): ActionsList { return perms.reduce((actions, perm) => { switch (perm) { - case 'putting': + case 'put': return [...actions, Action.SECRETPUT]; - case 'accessing': + case 'access': return [...actions, Action.SECRETACCESS]; default: throw new Error( @@ -77,7 +79,33 @@ export class SecretResource extends SecureResource { return ResourceType.SECRET; } - public for(perm: SecretPermission, ...perms: SecretPermission[]): Secret { + public for( + perm: SecretPermissionLegacy, + ...perms: SecretPermissionLegacy[] + ): Secret { + console.warn("The 'for' method is deprecated, please use 'allow' instead"); + + const allPerms = [perm, ...perms].map((p) => { + switch (p) { + case 'putting': + return 'put'; + case 'accessing': + return 'access'; + default: + throw new Error( + `unknown secret permission ${p}, supported permissions are ${everything.join( + ', ' + )}` + ); + } + }); + + this.registerPolicy(...allPerms); + + return secrets().secret(this.name); + } + + public allow(perm: SecretPermission, ...perms: SecretPermission[]): Secret { this.registerPolicy(perm, ...perms); return secrets().secret(this.name); diff --git a/src/resources/topic.ts b/src/resources/topic.ts index 3f11dd2..1d45886 100644 --- a/src/resources/topic.ts +++ b/src/resources/topic.ts @@ -42,7 +42,9 @@ import { MessageContext } from '../context/message'; import { MessageMiddleware, createHandler } from '../handlers/handler'; import { fromGrpcError } from '../api/errors'; -type TopicPermission = 'publishing'; +type TopicPermission = 'publish'; + +type TopicPermissionLegacy = 'publishing'; export class SubscriptionWorkerOptions { public readonly topic: string; @@ -159,12 +161,11 @@ export class TopicResource< protected permsToActions(...perms: TopicPermission[]): ActionsList { return perms.reduce((actions, p) => { switch (p) { - case 'publishing': + case 'publish': return [...actions, Action.TOPICPUBLISH]; default: throw new Error( - `unknown permission ${p}, supported permissions is publishing.} - )}` + `unknown permission ${p}, supported permission is publish` ); } }, []); @@ -190,11 +191,33 @@ export class TopicResource< * * e.g. const updates = resources.topic('updates').for('publishing') * + * @deprecated use allow instead * @param perm the required permission set * @param perms additional required permissions set * @returns a usable topic reference */ - public for(perm: TopicPermission, ...perms: TopicPermission[]): Topic { + public for( + perm: TopicPermissionLegacy, + ...perms: TopicPermissionLegacy[] + ): Topic { + console.warn("The 'for' method is deprecated, please use 'allow' instead"); + + const allPerms = [perm, ...perms].map((p) => { + switch (p) { + case 'publishing': + return 'publish'; + default: + throw new Error( + `unknown topic permission ${p}, supported permission is publishing` + ); + } + }) as TopicPermission[]; + + this.registerPolicy(...allPerms); + return topics().topic(this.name); + } + + public allow(perm: TopicPermission, ...perms: TopicPermission[]): Topic { this.registerPolicy(perm, ...perms); return topics().topic(this.name); }