Skip to content

Commit

Permalink
feat!: Update storage APIs to accept StoragePath (#4549)
Browse files Browse the repository at this point in the history
* chore: add `StoragePath`

* chore: add `S3PathResolver`

* chore: update `getUrl` and `getProperties` API

* chore: update S3UploadTask

* chore: fix tests

* chore: validate storage path

* chore: add tests for S3PathResolver

* feat: Gen 2 Upload APIs (#4542)

* feat: add path parameter and made key optional

Co-Authored-By: Jordan Nelson <[email protected]>

* chore: added/modified unit tests and added a missing deprecation tag

Co-Authored-By: Jordan Nelson <[email protected]>

* chore: added extra assert statement to make sure users don't put in both path and key into upload method

Co-Authored-By: Jordan Nelson <[email protected]>

* chore: add ignore statements to ignore key deprecated warnings

* chore: add ignore statements for deprecated members

---------

Co-authored-by: Jordan Nelson <[email protected]>

* chore: refactor StoragePath (#4544)

* chore: remove `key` from public APIs

* chore: update tests to adjust for using path

* chore: fix lint issues

* chore: fix formatting

* chore: fix test

* chore: remove lint ignored

* chore: update comment

* chore: remove unused method

* chore: skip tests other than main

* chore: update generated code

* chore: add leading `/`

* feat(storage): copy and move APIs (#4569)

* chore: update copy api

* chore: update integ tests for copy

* chore: removed unused code

* chore: add back test

* chore: update download apis to use path (#4561)

* chore: add `StoragePath`

* chore: add `S3PathResolver`

* chore: update `getUrl` and `getProperties` API

* chore: update S3UploadTask

* chore: fix tests

* chore: validate storage path

* chore: add tests for S3PathResolver

* feat: Gen 2 Upload APIs (#4542)

* feat: add path parameter and made key optional

Co-Authored-By: Jordan Nelson <[email protected]>

* chore: added/modified unit tests and added a missing deprecation tag

Co-Authored-By: Jordan Nelson <[email protected]>

* chore: added extra assert statement to make sure users don't put in both path and key into upload method

Co-Authored-By: Jordan Nelson <[email protected]>

* chore: add ignore statements to ignore key deprecated warnings

* chore: add ignore statements for deprecated members

---------

Co-authored-by: Jordan Nelson <[email protected]>

* chore: refactor StoragePath (#4544)

* chore: remove `key` from public APIs

* chore: update tests to adjust for using path

* chore: fix lint issues

* chore: fix formatting

* chore: fix test

* chore: remove lint ignored

* chore: update comment

* chore: remove unused method

* chore: update download apis to use path

* chore: skip tests other than main

* chore: run dart format on both files that are receiving analyze warnings

* chore: used dart fix to add trailing commas

* chore: fixed formatting

* chore: run format on test files

* chore: fix formatting in integration tests

* chore: update generated code

* chore: add leading `/`

* chore: remove access level from e2e test

* fix(auth): device metadata migration (#4503)

* merge main

* chore: added a bracket and removed new keywords

* chore: changed signature of deleteLegacyDeviceSecrets and regenerated pigeons. Changed legacysecrethandler.kt file to .txt to "comment" it out

* chore: run dart format on generated file

* chore: migrateLegacyDeviceSecrets now gets called before deleteLegacyCredentials. Cognito_device_secrets return type fixed

* chore: add delete and fetch methods to the cognito swift file

* fix: various issues with implementation

* chore: fix lint issues

* test: update test to include mfa and token refresh

* chore: use coroutines, add plugin

* chore: remove generate code in iOS

* chore: fetch asf deviceId from shared prefs directly

* chore: update error name

* chore: remove native auth plugin

* chore: remove old legacy handler

* chore: remove check for null device metadata

* chore: flatten nested if statements

* chore: remove unused type

---------

Co-authored-by: Kha Truong <[email protected]>

* fix(auth): Allow retries with verifyTotpSetup() (#4532)

* chore(version): cherry pick Bump version (#4545)

* fix(auth): verifyTotp throw EnableSoftwareTokenMfaException (#4558)

* chore(version): cherry pick Bump version (#4560)

* chore: Update BUG-REPORT.yaml (#4568)

* fix: correct `package_info_plus` version constraint (#4583)

chore: fix version constraint

* feat(storage): copy and move APIs (#4569)

* chore: update copy api

* chore: update integ tests for copy

* chore: removed unused code

* chore: add back test

* chore: update download apis to use path

* chore: remove duplicate code from rebase

* chore: removed random text file

* chore: remove commented code

* chore: fix failing tests

* chore: update options, tests

* chore: update options classes

* chore: add back temp dir

* chore: fix integ test

* chore: add skip back to io specific test

* chore: skip test set up in configs other than main

---------

Co-authored-by: Jordan Nelson <[email protected]>
Co-authored-by: Jordan Nelson <[email protected]>
Co-authored-by: Jordan Nelson <[email protected]>
Co-authored-by: Elijah Quartey <[email protected]>

* feat(storage): update `remove` and `removeMany` APIs (#4593)

* chore: update removeMany API

* chore: update remove api, tests

* chore: handle leading slash

* test: update e2e tests

* chore: update sample app

* chore: fix comment

* chore: add doc comment

* chore: update path validation logic

* chore: remove leading `/` from tests

* chore: add `/` back to `StoragePathValidationException` test

* chore: update tests

* chore: remove leading `/`

* chore: update tests

* chore: remove unused types and constructors, use consistent naming  (#4603)

* chore: remove unused types and properties

* fix: set path of S3Item in download file

* chore: use consistent naming when resolving path

* chore: update path resolution in tests

* fix: update where leading `/` is added for getUrl

* feat: update list API (#4600)

* feat: list API init commit

* chore: removed / from beginning of paths

* chore: fix formatting

* chore: fix formatting and tests

* chore: fix formatting in storage_s3_service_test.dart

* chore: remove commented code and and / before paths

* Apply suggestions from code review

Co-authored-by: Jordan Nelson <[email protected]>

* chore: remove accessLevel from StorageListOptions

* chore: removed prefix formatter and fixed formatting

* chore: removed unused field

* chore: remove prefix resolver and fix classes

* chore: change variable name

Co-Authored-By: Jordan Nelson <[email protected]>

* chore: fix formatting

* chore: add deleted documentation back in

* chore: fixed comment placement

---------

Co-authored-by: Jordan Nelson <[email protected]>
Co-authored-by: Jordan Nelson <[email protected]>

* chore(storage): cleanup and enable tests (#4617)

* chore: update canary tests

* chore: remove `StorageOperationOptions`

* chore: remove access level from examples

* chore: update doc comment

* chore: enable transfer acceleration tests

* chore: update not found message

* chore: update `S3PathResolver` doc comments

* fix: copy impl

* chore: remove skips from tests

* chore: add back other env to integ tests

* chore: remove targetIdentityId from `S3ListOptions`

* chore: remove try/catch from test

* chore: update formatting

* chore: update copy test

* Update packages/storage/amplify_storage_s3/example/integration_test/use_case_test.dart

* chore: add space back to test path

* chore: update path in test

* chore: clean up example app

* chore: rename `withIdentityId` to `fromIdentityId`

* chore: add validation for empty path

* chore: add tests for path resolver

* chore: remove reference to CLI in doc comment

* chore: add comment to `StoragePathFromIdentityId`

* chore: revert public API changes in s3 list result

* chore: use `resolvePaths` in copy API

* chore: update error handling for identityId

* chore: undo changes to type cast in html download file

* chore: fix failing copy tests

* chore: update doc comment

Co-authored-by: NikaHsn <[email protected]>

* chore: update doc comments

Co-authored-by: NikaHsn <[email protected]>

---------

Co-authored-by: Jordan Nelson <[email protected]>
Co-authored-by: Jordan Nelson <[email protected]>
Co-authored-by: Jordan Nelson <[email protected]>
Co-authored-by: Elijah Quartey <[email protected]>
Co-authored-by: NikaHsn <[email protected]>
  • Loading branch information
6 people authored Apr 12, 2024
1 parent 17fc13c commit c20e0d2
Show file tree
Hide file tree
Showing 84 changed files with 1,204 additions and 2,734 deletions.
14 changes: 5 additions & 9 deletions canaries/integration_test/main_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@ void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();

const data = 'hello, world';
const dataKey = 'hello';
const path = StoragePath.fromString('public/hello');
final event = AnalyticsEvent('hello');

Future<void> performUnauthenticatedActions() async {
// Upload data to Storage
await Amplify.Storage.uploadData(
data: HttpPayload.string(data),
key: dataKey,
path: path,
).result;

// Record Analytics event
Expand All @@ -63,19 +63,15 @@ void main() {
Future<void> performAuthenticatedActions() async {
// Retrieve guest data
final guestData = await Amplify.Storage.downloadData(
key: dataKey,
options: const StorageDownloadDataOptions(
accessLevel: StorageAccessLevel.guest,
),
path: path,
).result;
expect(utf8.decode(guestData.bytes), data);

// Upload data to Storage
await Amplify.Storage.uploadData(
data: HttpPayload.string(data),
key: dataKey,
options: const StorageUploadDataOptions(
accessLevel: StorageAccessLevel.private,
path: StoragePath.fromIdentityId(
(String identityId) => 'private/$identityId/hello',
),
).result;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ part of 'amplify_categories.dart';
///
/// It comes with default, built-in support for Amazon S3 service
/// leveraging Amplify Auth Category for authorization.
///
/// The Amplify CLI helps you to create and configure the storage category
/// and auth category.
/// {@endtemplate}
class StorageCategory extends AmplifyCategory<StoragePluginInterface> {
@override
Expand All @@ -37,7 +34,7 @@ class StorageCategory extends AmplifyCategory<StoragePluginInterface> {
/// returns a [StorageListOperation].
/// {@endtemplate}
StorageListOperation list({
String? path,
required StoragePath path,
StorageListOptions? options,
}) {
return identifyCall(
Expand All @@ -50,84 +47,84 @@ class StorageCategory extends AmplifyCategory<StoragePluginInterface> {
}

/// {@template amplify_core.amplify_storage_category.get_properties}
/// Retrieves properties of the object specified by [key] with optional
/// Retrieves properties of the object specified by [path] with optional
/// [StorageGetPropertiesOptions]. And returns a
/// [StorageGetPropertiesOperation].
///
/// The result may include the metadata (if any) specified when the object
/// was uploaded.
/// {@endtemplate}
StorageGetPropertiesOperation getProperties({
required String key,
required StoragePath path,
StorageGetPropertiesOptions? options,
}) {
return identifyCall(
StorageCategoryMethod.getProperties,
() => defaultPlugin.getProperties(
key: key,
path: path,
options: options,
),
);
}

/// {@template amplify_core.amplify_storage_category.get_url}
/// Generates a downloadable url for the object specified by [key] with
/// Generates a downloadable url for the object specified by [path] with
/// [StorageGetUrlOptions], and returns a [StorageGetUrlOperation].
///
/// The url is presigned by the aws_signature_v4, and is enforced with scheme
/// `https`.
/// {@endtemplate}
StorageGetUrlOperation getUrl({
required String key,
required StoragePath path,
StorageGetUrlOptions? options,
}) {
return identifyCall(
StorageCategoryMethod.getUrl,
() => defaultPlugin.getUrl(
key: key,
path: path,
options: options,
),
);
}

/// {@template amplify_core.amplify_storage_category.download_data}
/// Downloads bytes of object specified by [key] into memory with optional
/// Downloads bytes of object specified by [path] into memory with optional
/// [onProgress] and [StorageDownloadDataOptions], and returns a
/// [StorageDownloadDataOperation].
///
/// Ensure you are managing the data in memory properly to avoid unexpected
/// memory leaks.
/// {@endtemplate}
StorageDownloadDataOperation downloadData({
required String key,
required StoragePath path,
void Function(StorageTransferProgress)? onProgress,
StorageDownloadDataOptions? options,
}) {
return identifyCall(
StorageCategoryMethod.downloadData,
() => defaultPlugin.downloadData(
key: key,
path: path,
onProgress: onProgress,
options: options,
),
);
}

/// {@template amplify_core.amplify_storage_category.download_file}
/// Downloads the object specified by [key] to [localFile] with optional
/// Downloads the object specified by [path] to [localFile] with optional
/// [onProgress] and [StorageDownloadFileOptions], and returns a
/// [StorageDownloadFileOperation].
/// {@endtemplate}
StorageDownloadFileOperation downloadFile({
required String key,
required StoragePath path,
required AWSFile localFile,
void Function(StorageTransferProgress)? onProgress,
StorageDownloadFileOptions? options,
}) {
return identifyCall(
StorageCategoryMethod.downloadFile,
() => defaultPlugin.downloadFile(
key: key,
path: path,
localFile: localFile,
onProgress: onProgress,
options: options,
Expand All @@ -137,21 +134,21 @@ class StorageCategory extends AmplifyCategory<StoragePluginInterface> {

/// {@template amplify_core.amplify_storage_category.upload_data}
/// Uploads [data] as a [StorageDataPayload] with optional
/// [onProgress] and [StorageUploadDataOptions] to object specified by [key],
/// [onProgress] and [StorageUploadDataOptions] to object specified by [path],
/// and returns a [StorageUploadDataOperation].
///
/// See [StorageDataPayload] for supported data formats.
/// {@endtemplate}
StorageUploadDataOperation uploadData({
required StorageDataPayload data,
required String key,
required StoragePath path,
void Function(StorageTransferProgress)? onProgress,
StorageUploadDataOptions? options,
}) {
return identifyCall(
StorageCategoryMethod.uploadData,
() => defaultPlugin.uploadData(
key: key,
path: path,
data: data,
onProgress: onProgress,
options: options,
Expand All @@ -161,22 +158,22 @@ class StorageCategory extends AmplifyCategory<StoragePluginInterface> {

/// {@template amplify_core.amplify_storage_category.upload_file}
/// Uploads data from [localFile] with optional [onProgress] and
/// [StorageUploadFileOptions] to object specified by [key], and returns a
/// [StorageUploadFileOptions] to object specified by [path], and returns a
/// [StorageUploadFileOperation].
///
/// [AWSFile] provides various adapters to read file content from file
/// abstractions, such as `XFile`, `PlatformFile`, `io.File` or `html.File`.
/// {@endtemplate}
StorageUploadFileOperation uploadFile({
required AWSFile localFile,
required String key,
required StoragePath path,
void Function(StorageTransferProgress)? onProgress,
StorageUploadFileOptions? options,
}) {
return identifyCall(
StorageCategoryMethod.uploadFile,
() => defaultPlugin.uploadFile(
key: key,
path: path,
localFile: localFile,
onProgress: onProgress,
options: options,
Expand All @@ -190,12 +187,11 @@ class StorageCategory extends AmplifyCategory<StoragePluginInterface> {
/// {@endtemplate}
///
/// {@template amplify_core.amplify_storage_category.copy_source}
/// The `source` should be readable to the API call originator following
/// corresponding [StorageAccessLevel].
/// The `source` should be readable to the API call originator.
/// {@endtemplate}
StorageCopyOperation copy({
required StorageItemWithAccessLevel<StorageItem> source,
required StorageItemWithAccessLevel<StorageItem> destination,
required StoragePath source,
required StoragePath destination,
StorageCopyOptions? options,
}) {
return identifyCall(
Expand All @@ -208,65 +204,32 @@ class StorageCategory extends AmplifyCategory<StoragePluginInterface> {
);
}

/// {@template amplify_core.amplify_storage_category.move}
/// Moves [source] to [destination] with optional [StorageMoveOptions],
/// and returns a [StorageMoveOperation].
///
/// This API performs two consecutive S3 service calls:
/// 1. copy the source object to destination objection
/// 2. delete the source object
///
/// {@macro amplify_core.amplify_storage_category.copy_source}
/// {@endtemplate}
@Deprecated(
'This API will be removed in the next major version. '
'This API calls Amplify.Storage.copy() to create a copy of the file in the '
'destination directory and then calls Amplify.Storage.remove() to remove '
'the source file. '
'Please use Amplify.Storage.copy() and Amplify.Storage.remove() directly '
'instead.',
)
StorageMoveOperation move({
required StorageItemWithAccessLevel<StorageItem> source,
required StorageItemWithAccessLevel<StorageItem> destination,
StorageMoveOptions? options,
}) {
return identifyCall(
StorageCategoryMethod.move,
() => defaultPlugin.move(
source: source,
destination: destination,
options: options,
),
);
}

/// {@template amplify_core.amplify_storage_category.remove}
/// Removes an object specified by [key] with optional [StorageRemoveOptions],
/// Removes an object specified by [path] with optional [StorageRemoveOptions],
/// and returns a [StorageRemoveOperation].
/// {@endtemplate}
StorageRemoveOperation remove({
required String key,
required StoragePath path,
StorageRemoveOptions? options,
}) {
return identifyCall(
StorageCategoryMethod.remove,
() => defaultPlugin.remove(key: key, options: options),
() => defaultPlugin.remove(path: path, options: options),
);
}

/// {@template amplify_core.amplify_storage_category.remove_many}
/// Removes multiple objects specified by [keys] with optional
/// Removes multiple objects specified by [paths] with optional
/// [StorageRemoveManyOptions], and returns a [StorageRemoveManyOperation].
/// {@endtemplate}
StorageRemoveManyOperation removeMany({
required List<String> keys,
required List<StoragePath> paths,
StorageRemoveManyOptions? options,
}) {
return identifyCall(
StorageCategoryMethod.removeMany,
() => defaultPlugin.removeMany(
keys: keys,
paths: paths,
options: options,
),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,31 +16,31 @@ abstract class StoragePluginInterface extends AmplifyPluginInterface {

/// {@macro amplify_core.amplify_storage_category.list}
StorageListOperation list({
String? path,
required StoragePath path,
StorageListOptions? options,
}) {
throw UnimplementedError('list() has not been implemented.');
}

/// {@macro amplify_core.amplify_storage_category.get_properties}
StorageGetPropertiesOperation getProperties({
required String key,
required StoragePath path,
StorageGetPropertiesOptions? options,
}) {
throw UnimplementedError('getProperties() has not been implemented.');
}

/// {@macro amplify_core.amplify_storage_category.get_url}
StorageGetUrlOperation getUrl({
required String key,
required StoragePath path,
StorageGetUrlOptions? options,
}) {
throw UnimplementedError('getUrl() has not been implemented.');
}

/// {@macro amplify_core.amplify_storage_category.download_data}
StorageDownloadDataOperation downloadData({
required String key,
required StoragePath path,
void Function(StorageTransferProgress)? onProgress,
StorageDownloadDataOptions? options,
}) {
Expand All @@ -49,7 +49,7 @@ abstract class StoragePluginInterface extends AmplifyPluginInterface {

/// {@macro amplify_core.amplify_storage_category.download_file}
StorageDownloadFileOperation downloadFile({
required String key,
required StoragePath path,
required AWSFile localFile,
void Function(StorageTransferProgress)? onProgress,
StorageDownloadFileOptions? options,
Expand All @@ -59,7 +59,7 @@ abstract class StoragePluginInterface extends AmplifyPluginInterface {

/// {@macro amplify_core.amplify_storage_category.upload_data}
StorageUploadDataOperation uploadData({
required String key,
required StoragePath path,
required StorageDataPayload data,
void Function(StorageTransferProgress)? onProgress,
StorageUploadDataOptions? options,
Expand All @@ -69,7 +69,7 @@ abstract class StoragePluginInterface extends AmplifyPluginInterface {

/// {@macro amplify_core.amplify_storage_category.upload_file}
StorageUploadFileOperation uploadFile({
required String key,
required StoragePath path,
required AWSFile localFile,
void Function(StorageTransferProgress)? onProgress,
StorageUploadFileOptions? options,
Expand All @@ -79,33 +79,24 @@ abstract class StoragePluginInterface extends AmplifyPluginInterface {

/// {@macro amplify_core.amplify_storage_category.copy}
StorageCopyOperation copy({
required StorageItemWithAccessLevel<StorageItem> source,
required StorageItemWithAccessLevel<StorageItem> destination,
required StoragePath source,
required StoragePath destination,
StorageCopyOptions? options,
}) {
throw UnimplementedError('copy() has not been implemented.');
}

/// {@macro amplify_core.amplify_storage_category.move}
StorageMoveOperation move({
required StorageItemWithAccessLevel<StorageItem> source,
required StorageItemWithAccessLevel<StorageItem> destination,
StorageMoveOptions? options,
}) {
throw UnimplementedError('move() has not been implemented.');
}

/// {@macro amplify_core.amplify_storage_category.remove}
StorageRemoveOperation remove({
required String key,
required StoragePath path,
StorageRemoveOptions? options,
}) {
throw UnimplementedError('remove() has not been implemented.');
}

/// {@macro amplify_core.amplify_storage_category.remove_many}
StorageRemoveManyOperation removeMany({
required List<String> keys,
required List<StoragePath> paths,
StorageRemoveManyOptions? options,
}) {
throw UnimplementedError('removeMany() has not been implemented.');
Expand Down
Loading

0 comments on commit c20e0d2

Please sign in to comment.