Skip to content

Commit

Permalink
chore: update download apis to use path (#4561)
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 <20613561+Jordan-Nelson@users.noreply.github.com>

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

Co-Authored-By: Jordan Nelson <20613561+Jordan-Nelson@users.noreply.github.com>

* 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 <20613561+Jordan-Nelson@users.noreply.github.com>

* chore: add ignore statements to ignore key deprecated warnings

* chore: add ignore statements for deprecated members

---------

Co-authored-by: Jordan Nelson <20613561+Jordan-Nelson@users.noreply.github.com>

* 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 <64438356+khatruong2009@users.noreply.github.com>

* 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 <Jordanryannelson@gmail.com>
Co-authored-by: Jordan Nelson <20613561+Jordan-Nelson@users.noreply.github.com>
Co-authored-by: Jordan Nelson <nejrd@amazon.com>
Co-authored-by: Elijah Quartey <Equartey@users.noreply.github.com>
  • Loading branch information
5 people committed Apr 9, 2024
1 parent fe28a87 commit cf1cd4a
Show file tree
Hide file tree
Showing 23 changed files with 193 additions and 522 deletions.
Expand Up @@ -91,43 +91,43 @@ class StorageCategory extends AmplifyCategory<StoragePluginInterface> {
}

/// {@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 Down
Expand Up @@ -40,7 +40,7 @@ abstract class StoragePluginInterface extends AmplifyPluginInterface {

/// {@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 Down
Expand Up @@ -9,12 +9,12 @@ import 'package:amplify_core/amplify_core.dart';
class StorageDownloadDataRequest {
/// {@macro amplify_core.storage.download_data_request}
const StorageDownloadDataRequest({
required this.key,
required this.path,
this.options,
});

/// Key of the object to download.
final String key;
/// Path of the object to download.
final StoragePath path;

/// Configurable options of the [StorageDownloadDataRequest].
final StorageDownloadDataOptions? options;
Expand Down
Expand Up @@ -14,22 +14,20 @@ class StorageDownloadFileOptions extends StorageOperationOptions
AWSDebuggable {
/// {@macro amplify_core.storage.download_file_options}
const StorageDownloadFileOptions({
super.accessLevel,
this.pluginOptions,
});

/// {@macro amplify_core.storage.download_file_plugin_options}
final StorageDownloadFilePluginOptions? pluginOptions;

@override
List<Object?> get props => [accessLevel, pluginOptions];
List<Object?> get props => [pluginOptions];

@override
String get runtimeTypeName => 'StorageDownloadFileOptions';

@override
Map<String, Object?> toJson() => {
'accessLevel': accessLevel?.name,
'pluginOptions': pluginOptions?.toJson(),
};
}
Expand Down
Expand Up @@ -9,13 +9,13 @@ import 'package:amplify_core/amplify_core.dart';
class StorageDownloadFileRequest {
/// {@macro amplify_core.storage.download_file_request}
const StorageDownloadFileRequest({
required this.key,
required this.path,
required this.localFile,
this.options,
});

/// Key of the object to download.
final String key;
/// Path of the object to download.
final StoragePath path;

/// Reference to the local file that download the object to.
final AWSFile localFile;
Expand Down
Expand Up @@ -72,10 +72,11 @@ void testTransferAcceleration({
test('S3DataPayload ${entry.key}', () async {
final dataPayload = entry.value;
final result = await Amplify.Storage.downloadData(
key: dataPayload.targetKey,
options: StorageDownloadDataOptions(
accessLevel: dataPayload.targetAccessLevel,
pluginOptions: const S3DownloadDataPluginOptions(
path: StoragePath.fromString(
'/${dataPayload.targetAccessLevel}/${dataPayload.targetKey}',
),
options: const StorageDownloadDataOptions(
pluginOptions: S3DownloadDataPluginOptions(
useAccelerateEndpoint: true,
),
),
Expand Down Expand Up @@ -156,9 +157,10 @@ void testTransferAcceleration({
const end = 5 * 1024 + 12;
final awsFile = entry.value;
final result = await Amplify.Storage.downloadData(
key: awsFile.targetKey,
path: StoragePath.fromString(
'${awsFile.targetAccessLevel}/${awsFile.targetKey}',
),
options: StorageDownloadDataOptions(
accessLevel: awsFile.targetAccessLevel,
pluginOptions: S3DownloadDataPluginOptions(
useAccelerateEndpoint: true,
bytesRange: S3DataBytesRange(start: start, end: end),
Expand Down
Expand Up @@ -64,11 +64,10 @@ void main() {
const testObjectFileName2 = 'user1Protected.jpg';
const testObjectFileName3 = 'user1Private.large';

for (final entry in amplifyEnvironments.entries) {
group(
// TODO(Jordan-Nelson): enable dots-in-name, remove custom-prefix
skip: entry.key != 'main',
'[Environment ${entry.key}]', () {
// TODO(Jordan-Nelson): enable dots-in-name, remove custom-prefix
for (final entry in amplifyEnvironments.entries
.where((element) => element.key == 'main')) {
group('[Environment ${entry.key}]', () {
S3PrefixResolver? prefixResolver;
late String user1IdentityId;
late String object1Etag;
Expand Down Expand Up @@ -320,13 +319,13 @@ void main() {
});

testWidgets(
skip: true,
'download object as bytes data in memory with access level private'
' for the currently signed in user', (WidgetTester tester) async {
final result = await Amplify.Storage.downloadData(
key: testObjectKey3,
path: StoragePath.withIdentityId(
(identityId) => '/private/$identityId/$testObjectKey3',
),
options: const StorageDownloadDataOptions(
accessLevel: StorageAccessLevel.private,
pluginOptions: S3DownloadDataPluginOptions(
getProperties: true,
),
Expand All @@ -338,15 +337,15 @@ void main() {
});

testWidgets(
skip: true,
'download a range of bytes of an object with access level private'
' for the currently signed in user', (WidgetTester tester) async {
const start = 5 * 1024;
const end = 5 * 1024 + 12;
final result = await Amplify.Storage.downloadData(
key: testObjectKey3,
path: StoragePath.withIdentityId(
(identityId) => '/private/$identityId/$testObjectKey3',
),
options: StorageDownloadDataOptions(
accessLevel: StorageAccessLevel.private,
pluginOptions: S3DownloadDataPluginOptions(
getProperties: true,
bytesRange: S3DataBytesRange(
Expand All @@ -366,7 +365,6 @@ void main() {
});

testWidgets(
skip: true,
'download file with access level private for the currently signed in user',
(WidgetTester tester) async {
final s3Plugin =
Expand All @@ -377,10 +375,11 @@ void main() {

final result = await s3Plugin
.downloadFile(
key: testObjectKey3,
path: StoragePath.withIdentityId(
(identityId) => '/private/$identityId/$testObjectKey3',
),
localFile: localFile,
options: const StorageDownloadFileOptions(
accessLevel: StorageAccessLevel.private,
pluginOptions: S3DownloadFilePluginOptions(
getProperties: true,
),
Expand All @@ -396,8 +395,7 @@ void main() {
},
// Web download relies on getUrl which has been covered in the getUrl
// integration test run.
// TODO(khatruong2009): Re-enable this test after download apis completed.
// skip: zIsWeb,
skip: zIsWeb,
);

testWidgets(
Expand Down Expand Up @@ -618,16 +616,15 @@ void main() {
});

testWidgets(
skip: true,
'download data of object with access level protected and a target'
' identity id for the currently signed user',
(WidgetTester tester) async {
final result = await Amplify.Storage.downloadData(
key: testObjectKey2,
options: StorageDownloadDataOptions(
accessLevel: StorageAccessLevel.protected,
pluginOptions: S3DownloadDataPluginOptions.forIdentity(
user1IdentityId,
path: StoragePath.fromString(
'/protected/$user1IdentityId/$testObjectKey2',
),
options: const StorageDownloadDataOptions(
pluginOptions: S3DownloadDataPluginOptions(
getProperties: true,
),
),
Expand All @@ -637,14 +634,14 @@ void main() {
});

testWidgets(
skip: true,
'download data of object (belongs to other user) with access level'
' private for the currently signed user',
(WidgetTester tester) async {
final operation = Amplify.Storage.downloadData(
key: testObjectKey3,
path: StoragePath.withIdentityId(
(identityId) => '/private/$identityId/$testObjectKey3',
),
options: const StorageDownloadDataOptions(
accessLevel: StorageAccessLevel.private,
pluginOptions: S3DownloadDataPluginOptions(
getProperties: true,
),
Expand Down
4 changes: 2 additions & 2 deletions packages/storage/amplify_storage_s3/example/lib/main.dart
Expand Up @@ -181,7 +181,7 @@ class _HomeScreenState extends State<HomeScreen> {
final filepath = '${documentsDir.path}/$key';
try {
await Amplify.Storage.downloadFile(
key: key,
path: StoragePath.fromString(key),
localFile: AWSFile.fromPath(filepath),
onProgress: (p0) => _logger
.debug('Progress: ${(p0.transferredBytes / p0.totalBytes) * 100}%'),
Expand All @@ -196,7 +196,7 @@ class _HomeScreenState extends State<HomeScreen> {
Future<void> downloadFileWeb(String key) async {
try {
await Amplify.Storage.downloadFile(
key: key,
path: StoragePath.fromString(key),
localFile: AWSFile.fromPath(key),
onProgress: (p0) => _logger
.debug('Progress: ${(p0.transferredBytes / p0.totalBytes) * 100}%'),
Expand Down
Expand Up @@ -207,7 +207,7 @@ Future<void> downloadDataOperation() async {

final s3Plugin = Amplify.Storage.getPlugin(AmplifyStorageS3Dart.pluginKey);
final downloadDataOperation = s3Plugin.downloadData(
key: key,
path: StoragePath.fromString(key),
options: StorageDownloadDataOptions(
accessLevel: accessLevel,
pluginOptions: const S3DownloadDataPluginOptions(
Expand Down Expand Up @@ -239,9 +239,6 @@ Future<void> downloadDataOperation() async {

Future<void> downloadFileOperation() async {
final key = prompt('Enter the key of the object to download: ');
final accessLevel = promptStorageAccessLevel(
'Choose the storage access level associated with the object: ',
);
final destinationPath = prompt(
'Enter the destination file path (ensure the file path is writable): ',
);
Expand All @@ -251,10 +248,9 @@ Future<void> downloadFileOperation() async {

final s3Plugin = Amplify.Storage.getPlugin(AmplifyStorageS3Dart.pluginKey);
final downloadFileOperation = s3Plugin.downloadFile(
key: key,
path: StoragePath.fromString(key),
localFile: localFile,
options: StorageDownloadFileOptions(
accessLevel: accessLevel,
pluginOptions: S3DownloadFilePluginOptions(
getProperties: true,
useAccelerateEndpoint: useAccelerateEndpoint,
Expand Down
Expand Up @@ -222,7 +222,7 @@ class AmplifyStorageS3Dart extends StoragePluginInterface

@override
S3DownloadDataOperation downloadData({
required String key,
required StoragePath path,
StorageDownloadDataOptions? options,
void Function(S3TransferProgress)? onProgress,
}) {
Expand All @@ -232,21 +232,20 @@ class AmplifyStorageS3Dart extends StoragePluginInterface
);

final s3Options = StorageDownloadDataOptions(
accessLevel: options?.accessLevel,
pluginOptions: s3PluginOptions,
);

final bytes = BytesBuilder();
final downloadTask = storageS3Service.downloadData(
key: key,
path: path,
options: s3Options,
onProgress: onProgress,
onData: bytes.add,
);

return S3DownloadDataOperation(
request: StorageDownloadDataRequest(
key: key,
path: path,
options: options,
),
result: downloadTask.result.then(
Expand All @@ -263,7 +262,7 @@ class AmplifyStorageS3Dart extends StoragePluginInterface

@override
S3DownloadFileOperation downloadFile({
required String key,
required StoragePath path,
required AWSFile localFile,
void Function(S3TransferProgress)? onProgress,
StorageDownloadFileOptions? options,
Expand All @@ -273,11 +272,10 @@ class AmplifyStorageS3Dart extends StoragePluginInterface
defaultPluginOptions: const S3DownloadFilePluginOptions(),
);
options = StorageDownloadFileOptions(
accessLevel: options?.accessLevel,
pluginOptions: s3PluginOptions,
);
return download_file_impl.downloadFile(
key: key,
path: path,
localFile: localFile,
options: options,
s3pluginConfig: s3pluginConfig,
Expand Down

0 comments on commit cf1cd4a

Please sign in to comment.