From 33426e46a21a771570db71063df5fc1098ddf85a Mon Sep 17 00:00:00 2001 From: Allan Zheng Date: Mon, 1 Jul 2024 23:45:41 -0700 Subject: [PATCH] feat(storage): attempt to remove scope from the types --- .../storage/src/providers/s3/types/options.ts | 15 +- packages/storage/src/storage-browser/types.ts | 133 +++++++++++------- 2 files changed, 93 insertions(+), 55 deletions(-) diff --git a/packages/storage/src/providers/s3/types/options.ts b/packages/storage/src/providers/s3/types/options.ts index 4ed4318c378..016af561009 100644 --- a/packages/storage/src/providers/s3/types/options.ts +++ b/packages/storage/src/providers/s3/types/options.ts @@ -17,17 +17,22 @@ import { export type Permission = 'READ' | 'READWRITE' | 'WRITE'; /** - * @internal + * Whether the bucket path points to a prefix or an object + * If it's 'PREFIX', it points a prefix or folder. For example the list() API's + * bucket path points to prefix or folder + * If it's 'OBJECT', the bucket path points to an object. */ -export type LocationType = 'PREFIX' | 'OBJECT' | 'BUCKET'; +type SubLocationType = 'PREFIX' | 'OBJECT'; /** + * Refer to either prefix a object resources that locates under a given bucket. + * * @internal */ -export interface BucketLocation { +export interface SubLocation { bucket: string; path: string; - type: LocationType; + type: SubLocationType; } /** @@ -35,7 +40,7 @@ export interface BucketLocation { */ export type LocationCredentialsProvider = (options: { forceRefresh?: boolean; - locations: BucketLocation[]; + locations: SubLocation[]; permission: Permission; }) => Promise<{ credentials: AWSCredentials }>; diff --git a/packages/storage/src/storage-browser/types.ts b/packages/storage/src/storage-browser/types.ts index ee08e292347..14b01bf45fd 100644 --- a/packages/storage/src/storage-browser/types.ts +++ b/packages/storage/src/storage-browser/types.ts @@ -4,81 +4,114 @@ import { AWSCredentials } from '@aws-amplify/core/internals/utils'; import { - LocationCredentialsProvider, - LocationType, - Permission, + SubLocation, + LocationCredentialsProvider, + Permission, } from '../providers/s3/types/options'; /** * @internal */ export type CredentialsProvider = (options?: { - forceRefresh?: boolean; + forceRefresh?: boolean; }) => Promise<{ credentials: AWSCredentials }>; +interface BucketLocation { + type: 'BUCKET'; + bucket: string; +} + +type Locations = BucketLocation | SubLocation; + /** * @internal */ -export interface LocationAccess { - /** - * Scope of storage location. For S3 service, it's the S3 path of the data to - * which the access is granted. - * - * @example 's3://MY-BUCKET-NAME/prefix/*' - */ - readonly scope: string; - /** - * The type of access granted to your Storage data. Can be either of READ, - * WRITE or READWRITE - */ - readonly permission: Permission; - /** - * parse location type parsed from scope format: - * * BUCKET: `'s3:///*'` - * * PREFIX: `'s3:///*'` - * * OBJECT: `'s3:////'` - */ - readonly type: LocationType; +export type LocationAccess = Locations & { + /** + * The type of access granted to your Storage data. Can be either of READ, + * WRITE or READWRITE + */ + readonly permission: Permission; } -export interface AccessGrant extends LocationAccess { - /** - * The Amazon Resource Name (ARN) of an AWS IAM Identity Center application - * associated with your Identity Center instance. If the grant includes an - * application ARN, the grantee can only access the S3 data through this - * application. - */ - readonly applicationArn?: string; +export type AccessGrant = LocationAccess & { + /** + * The Amazon Resource Name (ARN) of an AWS IAM Identity Center application + * associated with your Identity Center instance. If the grant includes an + * application ARN, the grantee can only access the S3 data through this + * application. + */ + readonly applicationArn?: string; } /** * @internal */ export interface ListLocationsOutput { - locations: T[]; - nextToken?: string; + locations: T[]; + nextToken?: string; } // Interface for listLocations() handler export type ListLocations = () => Promise>; // Interface for getLocationCredentials() handler. -export type LocationCredentialsHandler = (input: { - scope: string; - permission: Permission; -}) => Promise<{ credentials: AWSCredentials; scope?: string }>; +export type LocationCredentialsHandler = ( + input: LocationAccess, +) => Promise<{ credentials: AWSCredentials }>; export interface LocationCredentialsStore { - /** - * Get location-specific credentials. It uses a cache internally to optimize performance when - * getting credentials for the same location. It will refresh credentials if they expire or - * when forced to. - */ - getProvider(option: LocationAccess): LocationCredentialsProvider; - /** - * Invalidate cached credentials and force subsequent calls to get location-specific - * credentials to throw. It also makes subsequent calls to `getCredentialsProviderForLocation` - * to throw. - */ - destroy(): void; + /** + * Get location-specific credentials. It uses a cache internally to optimize performance when + * getting credentials for the same location. It will refresh credentials if they expire or + * when forced to. + */ + getProvider(option: LocationAccess): LocationCredentialsProvider; + /** + * Invalidate cached credentials and force subsequent calls to get location-specific + * credentials to throw. It also makes subsequent calls to `getCredentialsProviderForLocation` + * to throw. + */ + destroy(): void; } + +const listLocations: ListLocations = async () => ({ + locations: [ + { + permission: 'READ', + bucket: 'bucket', + path: 'path', + type: 'PREFIX', + }, + { + permission: 'READ', + bucket: 'bucket', + path: 'file', + type: 'OBJECT', + }, + ], +}); + +const getLocationCredentials: LocationCredentialsHandler = async input => { + if ( + input.type === 'PREFIX' && + input.bucket === 'bucket' && + input.path === 'path' && + input.permission === 'READ' + ) { + return { + credentials: + 'Temp credentials to read `s3://bucket/path*`' as any as AWSCredentials, + }; + } else if ( + input.type === 'OBJECT' && + input.bucket === 'bucket' && + input.path === 'file' && + input.permission === 'READ' + ) { + return { + credentials: + 'Temp credentials to read `s3://bucket/file`' as any as AWSCredentials, + }; + } else throw new Error(''); +};