From b60fb0a1bdf0aca742b244a55a6ea36c61cbaf9a Mon Sep 17 00:00:00 2001 From: Nika Hassani Date: Tue, 11 Jun 2024 15:41:26 -0700 Subject: [PATCH 1/6] chore: update configure apis to use AmplifyOutputs instead of AmplifyConfig --- .../amplify_core/lib/src/amplify_class.dart | 40 +++-- .../lib/src/config/auth/cognito/oauth.dart | 42 +++++ .../src/config/auth/cognito/user_pool.dart | 25 +++ .../src/plugin/amplify_plugin_interface.dart | 2 +- .../push/service_provider_client.dart | 3 +- .../amplify_core/test/amplify_class_test.dart | 8 +- .../test/plugin/auth_providers_test.dart | 6 +- .../amplify_datastore/android/build.gradle | 8 +- .../lib/amplify_datastore.dart | 10 +- .../lib/src/analytics_plugin_impl.dart | 14 +- .../test/analytics_plugin_config_test.dart | 77 ++++---- .../lib/src/api_plugin_impl.dart | 164 ++++++++++++++---- .../test/plugin_configuration_test.dart | 16 +- .../test/rest_methods_test.dart | 4 +- .../lib/src/auth_plugin_impl.dart | 2 +- .../lib/src/auth_plugin_impl.dart | 2 +- .../lib/src/model/auth_configuration.dart | 50 ++++++ .../src/state/event/configuration_event.dart | 8 +- .../machines/configuration_state_machine.dart | 11 +- .../src/state/state/configuration_state.dart | 4 +- .../lib/common/mock_config.dart | 22 ++- .../test/plugin/delete_user_test.dart | 2 +- .../test/plugin/reset_password_test.dart | 2 +- .../configuration_state_machine_test.dart | 4 +- ...fetch_auth_session_state_machine_test.dart | 4 +- .../android/build.gradle | 2 +- .../src/amplify_push_notifications_impl.dart | 4 +- .../amplify_push_notifications_impl_test.dart | 6 +- ...fy_push_notifications_impl_test.mocks.dart | 42 ++++- .../lib/src/pinpoint_provider.dart | 8 +- .../test/pinpoint_provider_test.dart | 9 +- .../lib/src/amplify_storage_s3_impl.dart | 2 +- .../test/amplify_storage_s3_impl_test.dart | 5 +- .../lib/src/amplify_storage_s3_dart_impl.dart | 18 +- .../download_file/download_file_html.dart | 8 +- .../download_file/download_file_io.dart | 4 +- .../download_file/download_file_stub.dart | 4 +- .../service/storage_s3_service_impl.dart | 50 +++--- .../test/amplify_storage_s3_dart_test.dart | 5 +- .../download_file_html_test.dart | 11 +- .../platform_impl/download_file_io_test.dart | 15 +- .../storage_s3_service_test.dart | 23 +-- .../lib/src/stubs/amplify_stub.dart | 5 +- 43 files changed, 518 insertions(+), 233 deletions(-) diff --git a/packages/amplify_core/lib/src/amplify_class.dart b/packages/amplify_core/lib/src/amplify_class.dart index b9dd470187..ca8243fbb0 100644 --- a/packages/amplify_core/lib/src/amplify_class.dart +++ b/packages/amplify_core/lib/src/amplify_class.dart @@ -111,24 +111,44 @@ abstract class AmplifyClass { 'Check if Amplify is already configured using Amplify.isConfigured.', ); } - - late AmplifyConfig amplifyConfig; + late final AmplifyOutputs amplifyOutputs; try { + final Map json; + late final AmplifyConfig amplifyConfig; try { - final json = jsonDecode(configuration) as Map; - amplifyConfig = AmplifyConfig.fromJson(json.cast()); + json = jsonDecode(configuration) as Map; } on Object catch (e) { throw ConfigurationError( 'The provided configuration is not a valid json. ' 'Check underlyingException.', recoverySuggestion: - 'Inspect your amplifyconfiguration.dart and ensure that ' - 'the string is proper json', + 'Inspect your amplify_output.dart or amplifyconfiguration.dart ' + 'and ensure that the string is proper json', underlyingException: e, ); } - await _configurePlugins(amplifyConfig); - _configCompleter.complete(amplifyConfig.toAmplifyOutputs()); + try { + amplifyOutputs = AmplifyOutputs.fromJson(json); + } on Object { + try { + amplifyConfig = AmplifyConfig.fromJson(json); + amplifyOutputs = amplifyConfig.toAmplifyOutputs(); + } on Object catch (e) { + throw ConfigurationError( + 'The provided configuration can not be decoded to AmplifyOutputs ' + 'or AmplifyConfig. ' + 'Check underlyingException.', + recoverySuggestion: + 'If using Amplify Gen 2 ensure that the json string ' + 'can be decoded to AmplifyOutputs type. ' + 'If using Amplify Gen 1 ensure that the json ' + 'string can be decoded to AmplifyConfig type.', + underlyingException: e, + ); + } + } + await _configurePlugins(amplifyOutputs); + _configCompleter.complete(amplifyOutputs); } on ConfigurationError catch (e, st) { // Complete with the configuration error and reset the completer so // that 1) `configure` can be called again and 2) listeners registered @@ -146,14 +166,14 @@ abstract class AmplifyClass { // handled by the developer, but since they are unrelated to // configuration, listeners to `Amplify.asyncConfig` should be allowed to // proceed with the validated configuration. - _configCompleter.complete(amplifyConfig.toAmplifyOutputs()); + _configCompleter.complete(amplifyOutputs); _configCompleter = Completer(); rethrow; } } /// Configures all plugins in topologically-sorted order. - Future _configurePlugins(AmplifyConfig config) async { + Future _configurePlugins(AmplifyOutputs config) async { await Future.wait(_addPluginFutures); _addPluginFutures.clear(); final categories = { diff --git a/packages/amplify_core/lib/src/config/auth/cognito/oauth.dart b/packages/amplify_core/lib/src/config/auth/cognito/oauth.dart index 6dc3799846..6f9863b507 100644 --- a/packages/amplify_core/lib/src/config/auth/cognito/oauth.dart +++ b/packages/amplify_core/lib/src/config/auth/cognito/oauth.dart @@ -2,7 +2,9 @@ // SPDX-License-Identifier: Apache-2.0 import 'package:amplify_core/amplify_core.dart'; +import 'package:amplify_core/src/config/amplify_outputs/auth/auth_outputs.dart'; import 'package:json_annotation/json_annotation.dart'; +import 'package:meta/meta.dart'; part 'oauth.g.dart'; @@ -27,6 +29,46 @@ class CognitoOAuthConfig this.tokenUriQueryParameters, }); + @internal + factory CognitoOAuthConfig.fromAuthOutputs(AuthOutputs authOutputs) { + if (authOutputs.userPoolClientId == null) { + throw ConfigurationError('Invalid config: no User Pool Client Id found.'); + } + if (authOutputs.oauth == null) { + throw ConfigurationError('Invalid config: no oAuth configuration found.'); + } + + final appClientId = authOutputs.userPoolClientId!; + final appClientSecret = authOutputs.appClientSecret; + final scopes = authOutputs.oauth!.scopes; + final signInUri = authOutputs.oauth!.signInUri; + final signOutUri = authOutputs.oauth!.signOutUri; + final signInUriQueryParameters = + authOutputs.oauth!.signInUriQueryParameters; + final signOutUriQueryParameters = + authOutputs.oauth!.signOutUriQueryParameters; + final signInRedirectUri = authOutputs.oauth!.redirectSignInUri.join(','); + final signOutRedirectUri = authOutputs.oauth!.redirectSignOutUri.join(','); + final webDomain = authOutputs.oauth!.domain; + final tokenUri = authOutputs.oauth!.tokenUri; + final tokenUriQueryParameters = authOutputs.oauth!.tokenUriQueryParameters; + + return CognitoOAuthConfig( + appClientId: appClientId, + appClientSecret: appClientSecret, + scopes: scopes, + signInUri: signInUri, + signOutUri: signOutUri, + signInRedirectUri: signInRedirectUri, + signOutRedirectUri: signOutRedirectUri, + webDomain: webDomain, + signInUriQueryParameters: signInUriQueryParameters, + signOutUriQueryParameters: signOutUriQueryParameters, + tokenUri: tokenUri, + tokenUriQueryParameters: tokenUriQueryParameters, + ); + } + factory CognitoOAuthConfig.fromJson(Map json) => _$CognitoOAuthConfigFromJson(json); diff --git a/packages/amplify_core/lib/src/config/auth/cognito/user_pool.dart b/packages/amplify_core/lib/src/config/auth/cognito/user_pool.dart index a5b58bb587..9a6e8a8d02 100644 --- a/packages/amplify_core/lib/src/config/auth/cognito/user_pool.dart +++ b/packages/amplify_core/lib/src/config/auth/cognito/user_pool.dart @@ -2,6 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 import 'package:amplify_core/amplify_core.dart'; +import 'package:amplify_core/src/config/amplify_outputs/auth/auth_outputs.dart'; +import 'package:meta/meta.dart'; part 'user_pool.g.dart'; @@ -17,6 +19,29 @@ class CognitoUserPoolConfig this.endpoint, }); + @internal + factory CognitoUserPoolConfig.fromAuthOutputs(AuthOutputs authOutputs) { + if (authOutputs.userPoolId == null) { + throw ConfigurationError( + 'Invalid Cognito User Pool config: No User Pool Id found', + ); + } + if (authOutputs.userPoolClientId == null) { + throw ConfigurationError( + 'Invalid Cognito User Pool config: No User Pool Client Id found', + ); + } + return CognitoUserPoolConfig( + poolId: authOutputs.userPoolId!, + appClientId: authOutputs.userPoolClientId!, + appClientSecret: authOutputs.appClientSecret, + region: authOutputs.awsRegion, + hostedUI: authOutputs.oauth == null + ? null + : CognitoOAuthConfig.fromAuthOutputs(authOutputs), + ); + } + factory CognitoUserPoolConfig.fromJson(Map json) => _$CognitoUserPoolConfigFromJson(json); final String poolId; diff --git a/packages/amplify_core/lib/src/plugin/amplify_plugin_interface.dart b/packages/amplify_core/lib/src/plugin/amplify_plugin_interface.dart index 4898c1ff2e..587d1e2a1b 100644 --- a/packages/amplify_core/lib/src/plugin/amplify_plugin_interface.dart +++ b/packages/amplify_core/lib/src/plugin/amplify_plugin_interface.dart @@ -27,7 +27,7 @@ abstract /* base */ class AmplifyPluginInterface { /// Configures the plugin using the registered [config]. Future configure({ - AmplifyConfig? config, + AmplifyOutputs? config, required AmplifyAuthProviderRepository authProviderRepo, }) async {} diff --git a/packages/amplify_core/lib/src/types/notifications/push/service_provider_client.dart b/packages/amplify_core/lib/src/types/notifications/push/service_provider_client.dart index 62fbcf3ded..2c6454f7ca 100644 --- a/packages/amplify_core/lib/src/types/notifications/push/service_provider_client.dart +++ b/packages/amplify_core/lib/src/types/notifications/push/service_provider_client.dart @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import 'package:amplify_core/amplify_core.dart'; +import 'package:amplify_core/src/config/amplify_outputs/notifications/notifications_outputs.dart'; /// {@template amplify_core.push.service_provider_client} /// A base class for new service providers to implement and add functionality @@ -11,7 +12,7 @@ import 'package:amplify_core/amplify_core.dart'; abstract class ServiceProviderClient { /// Initialize this client, used by the plugin during configuration. Future init({ - required NotificationsPinpointPluginConfig config, + required NotificationsOutputs config, required AmplifyAuthProviderRepository authProviderRepo, }); diff --git a/packages/amplify_core/test/amplify_class_test.dart b/packages/amplify_core/test/amplify_class_test.dart index de24500a06..d1228f8268 100644 --- a/packages/amplify_core/test/amplify_class_test.dart +++ b/packages/amplify_core/test/amplify_class_test.dart @@ -72,7 +72,7 @@ void main() { class ConfigErrorPlugin extends AnalyticsPluginInterface { @override Future configure({ - AmplifyConfig? config, + AmplifyOutputs? config, required AmplifyAuthProviderRepository authProviderRepo, }) { throw ConfigurationError('Could not configure'); @@ -82,7 +82,7 @@ class ConfigErrorPlugin extends AnalyticsPluginInterface { class NonConfigErrorPlugin extends AnalyticsPluginInterface { @override Future configure({ - AmplifyConfig? config, + AmplifyOutputs? config, required AmplifyAuthProviderRepository authProviderRepo, }) { throw const UnknownException('Could not configure'); @@ -92,7 +92,7 @@ class NonConfigErrorPlugin extends AnalyticsPluginInterface { class SuccessPlugin extends AnalyticsPluginInterface { @override Future configure({ - AmplifyConfig? config, + AmplifyOutputs? config, required AmplifyAuthProviderRepository authProviderRepo, }) async { return; @@ -107,7 +107,7 @@ class AsyncAddPlugin extends AnalyticsPluginInterface { @override Future configure({ - AmplifyConfig? config, + AmplifyOutputs? config, required AmplifyAuthProviderRepository authProviderRepo, }) async { _configureCompleter.complete(); diff --git a/packages/amplify_core/test/plugin/auth_providers_test.dart b/packages/amplify_core/test/plugin/auth_providers_test.dart index 160576d77b..1856d9532d 100644 --- a/packages/amplify_core/test/plugin/auth_providers_test.dart +++ b/packages/amplify_core/test/plugin/auth_providers_test.dart @@ -42,7 +42,7 @@ class AuthPlugin extends Fake implements AuthPluginInterface { @override Future configure({ - AmplifyConfig? config, + AmplifyOutputs? config, required AmplifyAuthProviderRepository authProviderRepo, }) async { _authProvider = authProviderRepo.getAuthProvider( @@ -72,7 +72,7 @@ class ApiPlugin extends Fake implements APIPluginInterface { @override Future configure({ - AmplifyConfig? config, + AmplifyOutputs? config, required AmplifyAuthProviderRepository authProviderRepo, }) async { _authProvider = authProviderRepo.getAuthProvider( @@ -83,7 +83,7 @@ class ApiPlugin extends Fake implements APIPluginInterface { void main() { group('AuthProviderRepository', () { - test('allows plugin interdependenices', () async { + test('allows plugin interdependencies', () async { final apiPlugin = ApiPlugin(); final authPlugin = AuthPlugin(); diff --git a/packages/amplify_datastore/android/build.gradle b/packages/amplify_datastore/android/build.gradle index 9a01bcbea2..fe75374265 100644 --- a/packages/amplify_datastore/android/build.gradle +++ b/packages/amplify_datastore/android/build.gradle @@ -73,10 +73,10 @@ android { } dependencies { - implementation 'com.amplifyframework:aws-auth-cognito:2.15.0' - implementation "com.amplifyframework:aws-api:2.15.0" - implementation "com.amplifyframework:aws-datastore:2.15.0" - implementation "com.amplifyframework:aws-api-appsync:2.15.0" + implementation 'com.amplifyframework:aws-auth-cognito:2.19.0' + implementation "com.amplifyframework:aws-api:2.19.0" + implementation "com.amplifyframework:aws-datastore:2.19.0" + implementation "com.amplifyframework:aws-api-appsync:2.19.0" implementation 'com.google.code.gson:gson:2.10.1' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.1' diff --git a/packages/amplify_datastore/lib/amplify_datastore.dart b/packages/amplify_datastore/lib/amplify_datastore.dart index 35a949c4d9..bf3f424961 100644 --- a/packages/amplify_datastore/lib/amplify_datastore.dart +++ b/packages/amplify_datastore/lib/amplify_datastore.dart @@ -50,7 +50,7 @@ class AmplifyDataStore extends DataStorePluginInterface @override Future configure({ - AmplifyConfig? config, + AmplifyOutputs? config, required AmplifyAuthProviderRepository authProviderRepo, }) async { if (config == null) { @@ -100,15 +100,13 @@ class AmplifyDataStore extends DataStorePluginInterface } final apiPlugin = Amplify.API.plugins.firstOrNull; - final gqlConfig = config.api?.awsPlugin?.all.values.firstWhereOrNull( - (config) => config.endpointType == EndpointType.graphQL, - ); + final gqlConfig = config.data; if (apiPlugin != null && gqlConfig != null) { // ignore: invalid_use_of_protected_member final authProviders = apiPlugin.authProviders; Map endpoints = {}; - config.api?.awsPlugin?.all.entries.forEach((e) { - endpoints[e.key] = e.value.authorizationType.name; + gqlConfig.entries.forEach((e) { + endpoints[e.key] = e.value.defaultAuthorizationType.name; }); final nativePlugin = NativeAmplifyApi(authProviders); NativeApiPlugin.setup(nativePlugin); diff --git a/packages/analytics/amplify_analytics_pinpoint_dart/lib/src/analytics_plugin_impl.dart b/packages/analytics/amplify_analytics_pinpoint_dart/lib/src/analytics_plugin_impl.dart index 2ecc795bad..f981412729 100644 --- a/packages/analytics/amplify_analytics_pinpoint_dart/lib/src/analytics_plugin_impl.dart +++ b/packages/analytics/amplify_analytics_pinpoint_dart/lib/src/analytics_plugin_impl.dart @@ -83,19 +83,17 @@ class AmplifyAnalyticsPinpointDart extends AnalyticsPluginInterface { @override Future configure({ - AmplifyConfig? config, + AmplifyOutputs? config, required AmplifyAuthProviderRepository authProviderRepo, }) async { // Parse config values from amplifyconfiguration.json - if (config == null || - config.analytics == null || - config.analytics?.awsPlugin == null) { - throw ConfigurationError('No Pinpoint plugin config available.'); + if (config?.analytics?.amazonPinpoint == null) { + throw ConfigurationError('No analytics config available.'); } - final pinpointConfig = config.analytics!.awsPlugin!; - final pinpointAppId = pinpointConfig.pinpointAnalytics.appId; - final region = pinpointConfig.pinpointAnalytics.region; + final pinpointConfig = config!.analytics!.amazonPinpoint!; + final pinpointAppId = pinpointConfig.appId; + final region = pinpointConfig.awsRegion; // Prepare PinpointClient final authProvider = authProviderRepo diff --git a/packages/analytics/amplify_analytics_pinpoint_dart/test/analytics_plugin_config_test.dart b/packages/analytics/amplify_analytics_pinpoint_dart/test/analytics_plugin_config_test.dart index 62863fdde8..2af9db5f22 100644 --- a/packages/analytics/amplify_analytics_pinpoint_dart/test/analytics_plugin_config_test.dart +++ b/packages/analytics/amplify_analytics_pinpoint_dart/test/analytics_plugin_config_test.dart @@ -7,6 +7,8 @@ import 'package:amplify_analytics_pinpoint_dart/src/impl/analytics_client/event_ import 'package:amplify_analytics_pinpoint_dart/src/impl/flutter_provider_interfaces/cached_events_path_provider.dart'; import 'package:amplify_analytics_pinpoint_dart/src/sdk/src/pinpoint/model/session.dart'; import 'package:amplify_core/amplify_core.dart'; +import 'package:amplify_core/src/config/amplify_outputs/analytics/amazon_pinpoint_outputs.dart'; +import 'package:amplify_core/src/config/amplify_outputs/analytics/analytics_outputs.dart'; import 'package:mocktail/mocktail.dart'; import 'package:test/test.dart'; @@ -65,6 +67,13 @@ void main() { const appId = 'appId'; const region = 'region'; + // ignore: invalid_use_of_internal_member + const config = AmplifyOutputs( + version: '1', + analytics: AnalyticsOutputs( + amazonPinpoint: AmazonPinpointOutputs(awsRegion: region, appId: appId), + ), + ); setUpAll(() async { mockPathProvider = MockPathProvider(); @@ -80,6 +89,25 @@ void main() { Amplify.dependencies.addInstance(MockAnalyticsClient()); }); + test('throws ConfigurationError when no analytics config is provided', + () async { + final plugin = AmplifyAnalyticsPinpointDart( + secureStorageFactory: (_) => MockSecureStorage(), + ); + + await expectLater( + plugin.configure( + // ignore: invalid_use_of_internal_member + config: const AmplifyOutputs(version: '1'), + authProviderRepo: AmplifyAuthProviderRepository() + ..registerAuthProvider( + APIAuthorizationType.iam.authProviderToken, + mockAuthProvider, + ), + ), + throwsA(isA()), + ); + }); test('throws ConfigurationError when negative', () async { final plugin = AmplifyAnalyticsPinpointDart( pathProvider: mockPathProvider, @@ -91,21 +119,8 @@ void main() { await expectLater( plugin.configure( - config: const AmplifyConfig( - analytics: AnalyticsConfig( - plugins: { - PinpointPluginConfig.pluginKey: PinpointPluginConfig( - pinpointAnalytics: PinpointAnalytics( - appId: appId, - region: region, - ), - pinpointTargeting: PinpointTargeting( - region: region, - ), - ), - }, - ), - ), + // ignore: invalid_use_of_internal_member + config: config, authProviderRepo: AmplifyAuthProviderRepository() ..registerAuthProvider( APIAuthorizationType.iam.authProviderToken, @@ -126,21 +141,7 @@ void main() { ); await plugin.configure( - config: const AmplifyConfig( - analytics: AnalyticsConfig( - plugins: { - PinpointPluginConfig.pluginKey: PinpointPluginConfig( - pinpointAnalytics: PinpointAnalytics( - appId: appId, - region: region, - ), - pinpointTargeting: PinpointTargeting( - region: region, - ), - ), - }, - ), - ), + config: config, authProviderRepo: AmplifyAuthProviderRepository() ..registerAuthProvider( APIAuthorizationType.iam.authProviderToken, @@ -163,21 +164,7 @@ void main() { ); await plugin.configure( - config: const AmplifyConfig( - analytics: AnalyticsConfig( - plugins: { - PinpointPluginConfig.pluginKey: PinpointPluginConfig( - pinpointAnalytics: PinpointAnalytics( - appId: appId, - region: region, - ), - pinpointTargeting: PinpointTargeting( - region: region, - ), - ), - }, - ), - ), + config: config, authProviderRepo: AmplifyAuthProviderRepository() ..registerAuthProvider( APIAuthorizationType.iam.authProviderToken, diff --git a/packages/api/amplify_api_dart/lib/src/api_plugin_impl.dart b/packages/api/amplify_api_dart/lib/src/api_plugin_impl.dart index e3b1b9b530..8cf128dede 100644 --- a/packages/api/amplify_api_dart/lib/src/api_plugin_impl.dart +++ b/packages/api/amplify_api_dart/lib/src/api_plugin_impl.dart @@ -14,6 +14,10 @@ import 'package:amplify_api_dart/src/graphql/web_socket/types/connectivity_platf import 'package:amplify_api_dart/src/util/amplify_api_config.dart'; import 'package:amplify_api_dart/src/util/amplify_authorization_rest_client.dart'; import 'package:amplify_core/amplify_core.dart'; +// ignore: implementation_imports +import 'package:amplify_core/src/config/amplify_outputs/data/data_outputs.dart'; +// ignore: implementation_imports +import 'package:amplify_core/src/config/amplify_outputs/rest_api/rest_api_outputs.dart'; import 'package:meta/meta.dart'; /// {@template amplify_api_dart.amplify_api_dart} @@ -30,7 +34,8 @@ class AmplifyAPIDart extends APIPluginInterface with AWSDebuggable { } final APIPluginOptions _options; - late final AWSApiPluginConfig _apiConfig; + late final Map? _dataConfig; + late final Map? _restConfig; late final AmplifyAuthProviderRepository _authProviderRepo; /// Creates a stream representing network connectivity at the hardware level. @@ -63,30 +68,49 @@ class AmplifyAPIDart extends APIPluginInterface with AWSDebuggable { @override Future configure({ - AmplifyConfig? config, + AmplifyOutputs? config, required AmplifyAuthProviderRepository authProviderRepo, }) async { - final apiConfig = config?.api?.awsPlugin; - if (apiConfig == null) { + final dataConfig = config?.data; + // ignore: invalid_use_of_internal_member + final restApiConfig = config?.restApi; + _validateConfig(dataConfig, restApiConfig); + _dataConfig = dataConfig; + _restConfig = restApiConfig; + _authProviderRepo = authProviderRepo; + _registerApiPluginAuthProviders(); + Amplify.Hub.addChannel(HubChannel.Api, _hubEventController.stream); + } + + void _validateConfig( + Map? dataConfig, + Map? restApiConfig, + ) { + if (dataConfig == null && restApiConfig == null) { throw ConfigurationError( - 'No AWS API config found', - recoverySuggestion: 'Add API from the Amplify CLI. See ' + 'No API config found', + recoverySuggestion: 'Add API configuration to use API plugin. See ' 'https://docs.amplify.aws/lib/graphqlapi/getting-started/q/platform/flutter/#configure-api', ); } - for (final entry in apiConfig.endpoints.entries) { - if (!entry.value.endpoint.startsWith('https')) { + dataConfig?.forEach((key, value) { + if (!value.url.startsWith('https')) { throw ConfigurationError( - 'Non-HTTPS endpoint found for ${entry.key} which is not supported.', + 'Non-HTTPS url found for $key which is not supported.', recoverySuggestion: - 'Ensure the configured endpoint for ${entry.key} utilizes https.', + 'Ensure the configured url for $key utilizes https.', ); } - } - _apiConfig = apiConfig; - _authProviderRepo = authProviderRepo; - _registerApiPluginAuthProviders(); - Amplify.Hub.addChannel(HubChannel.Api, _hubEventController.stream); + }); + restApiConfig?.forEach((key, value) { + if (!value.url.startsWith('https')) { + throw ConfigurationError( + 'Non-HTTPS url found for $key which is not supported.', + recoverySuggestion: + 'Ensure the configured url for $key utilizes https.', + ); + } + }); } /// Register AmplifyAuthProviders that are specific to API category (API key, @@ -96,10 +120,13 @@ class AmplifyAPIDart extends APIPluginInterface with AWSDebuggable { /// /// Register OIDC/Lambda set to _authProviders in constructor. void _registerApiPluginAuthProviders() { - _apiConfig.endpoints.forEach((key, value) { + _dataConfig?.forEach((key, value) { // Check the presence of apiKey (not auth type) because other modes might // have a key if not the primary auth mode. - if (value.apiKey != null) { + if (value.apiKey != null || + value.defaultAuthorizationType == APIAuthorizationType.apiKey || + value.authorizationTypes + .any((element) => element == APIAuthorizationType.apiKey)) { _authProviderRepo.registerAuthProvider( APIAuthorizationType.apiKey.authProviderToken, AppSyncApiKeyAuthProvider(), @@ -140,10 +167,7 @@ class AmplifyAPIDart extends APIPluginInterface with AWSDebuggable { String? apiName, APIAuthorizationType? authorizationMode, }) { - final endpoint = _apiConfig.getEndpoint( - type: type, - apiName: apiName, - ); + final endpoint = _getEndpointConfig(type, apiName); final authModeForClientKey = authorizationMode ?? endpoint.config.authorizationType; final clientPoolKey = '${endpoint.name}.${authModeForClientKey.name}'; @@ -158,10 +182,90 @@ class AmplifyAPIDart extends APIPluginInterface with AWSDebuggable { ); } + EndpointConfig _getEndpointConfig(EndpointType type, String? apiName) { + if (type == EndpointType.graphQL) { + if (_dataConfig == null) { + throw ConfigurationError( + 'No GraphQL API endpoint found.', + ); + } + DataOutputs config; + if (apiName != null) { + config = _dataConfig.entries + .firstWhere( + (config) => config.key == apiName, + orElse: () => throw ConfigurationError( + 'No GraphQL API endpoint found matching apiName $apiName.', + ), + ) + .value; + } else { + if (_dataConfig.length > 1) { + throw ConfigurationError( + 'Multiple GraphQL API endpoints defined. Pass apiName parameter to specify ' + 'which one to use.', + ); + } + config = _dataConfig.values.first; + apiName = _dataConfig.keys.first; + } + return EndpointConfig( + apiName, + AWSApiConfig( + region: config.awsRegion, + endpoint: config.url, + endpointType: EndpointType.graphQL, + authorizationType: config.defaultAuthorizationType, + apiKey: config.apiKey, + ), + ); + } + if (type == EndpointType.rest) { + if (_restConfig == null) { + throw ConfigurationError( + 'No REST API endpoint found.', + ); + } + RestApiOutputs config; + if (apiName != null) { + config = _restConfig.entries + .firstWhere( + (config) => config.key == apiName, + orElse: () => throw ConfigurationError( + 'No REST API endpoint found matching apiName $apiName.', + ), + ) + .value; + } else { + if (_restConfig.length > 1) { + throw ConfigurationError( + 'Multiple REST API endpoints defined. Pass apiName parameter to specify ' + 'which one to use.', + ); + } + config = _restConfig.values.first; + apiName = _restConfig.keys.first; + } + return EndpointConfig( + apiName, + AWSApiConfig( + region: config.awsRegion, + endpoint: config.url, + endpointType: EndpointType.rest, + authorizationType: config.authorizationType, + apiKey: config.apiKey, + ), + ); + } + throw ConfigurationError( + 'Endpoint type $type is not supported.', + ); + } + WebSocketBloc _webSocketBloc({String? apiName}) { - final endpoint = _apiConfig.getEndpoint( - type: EndpointType.graphQL, - apiName: apiName, + final endpoint = _getEndpointConfig( + EndpointType.graphQL, + apiName, ); return _webSocketBlocPool[endpoint.name] ??= createWebSocketBloc(endpoint) @@ -188,9 +292,9 @@ class AmplifyAPIDart extends APIPluginInterface with AWSDebuggable { } Uri _getGraphQLUri(String? apiName) { - final endpoint = _apiConfig.getEndpoint( - type: EndpointType.graphQL, - apiName: apiName, + final endpoint = _getEndpointConfig( + EndpointType.graphQL, + apiName, ); return endpoint.getUri(); } @@ -200,9 +304,9 @@ class AmplifyAPIDart extends APIPluginInterface with AWSDebuggable { String? apiName, Map? queryParameters, ) { - final endpoint = _apiConfig.getEndpoint( - type: EndpointType.rest, - apiName: apiName, + final endpoint = _getEndpointConfig( + EndpointType.rest, + apiName, ); return endpoint.getUri(path: path, queryParameters: queryParameters); } diff --git a/packages/api/amplify_api_dart/test/plugin_configuration_test.dart b/packages/api/amplify_api_dart/test/plugin_configuration_test.dart index d1c37016e8..97c623eec0 100644 --- a/packages/api/amplify_api_dart/test/plugin_configuration_test.dart +++ b/packages/api/amplify_api_dart/test/plugin_configuration_test.dart @@ -64,9 +64,13 @@ void main() { final config = AmplifyConfig.fromJson( jsonDecode(amplifyconfig) as Map, ); + // ignore: invalid_use_of_internal_member + final amplifyOutputs = config.toAmplifyOutputs(); final configIamWithApiKey = AmplifyConfig.fromJson( jsonDecode(amplifyconfigwithapikey) as Map, ); + // ignore: invalid_use_of_internal_member + final amplifyOutputsIamWithApiKey = configIamWithApiKey.toAmplifyOutputs(); group('AmplifyAPI plugin configuration', () { test( @@ -75,7 +79,7 @@ void main() { final plugin = AmplifyAPIDart(); await plugin.configure( authProviderRepo: authProviderRepo, - config: config, + config: amplifyOutputs, ); final apiKeyAuthProvider = authProviderRepo.getAuthProvider( APIAuthorizationType.apiKey.authProviderToken, @@ -89,7 +93,7 @@ void main() { final plugin = AmplifyAPIDart(); await plugin.configure( authProviderRepo: authProviderRepo, - config: configIamWithApiKey, + config: amplifyOutputsIamWithApiKey, ); final apiKeyAuthProvider = authProviderRepo.getAuthProvider( APIAuthorizationType.apiKey.authProviderToken, @@ -104,7 +108,7 @@ void main() { ); await plugin.configure( authProviderRepo: authProviderRepo, - config: config, + config: amplifyOutputs, ); final oidcAuthProvider = authProviderRepo .getAuthProvider(APIAuthorizationType.oidc.authProviderToken); @@ -124,7 +128,7 @@ void main() { ); await plugin.configure( authProviderRepo: authProviderRepo, - config: config, + config: amplifyOutputs, ); final functionAuthProvider = authProviderRepo .getAuthProvider(APIAuthorizationType.function.authProviderToken); @@ -143,7 +147,7 @@ void main() { ); await plugin.configure( authProviderRepo: authProviderRepo, - config: config, + config: amplifyOutputs, ); const graphQLDocument = '''query TestQuery { @@ -169,7 +173,7 @@ void main() { ); await plugin.configure( authProviderRepo: authProviderRepo, - config: config, + config: amplifyOutputs, ); await plugin.get('/items').response; diff --git a/packages/api/amplify_api_dart/test/rest_methods_test.dart b/packages/api/amplify_api_dart/test/rest_methods_test.dart index 82728ce9fe..44195ce6d1 100644 --- a/packages/api/amplify_api_dart/test/rest_methods_test.dart +++ b/packages/api/amplify_api_dart/test/rest_methods_test.dart @@ -43,8 +43,10 @@ void main() { final config = AmplifyConfig.fromJson( jsonDecode(amplifyconfig) as Map, ); + // ignore: invalid_use_of_internal_member + final amplifyOutputs = config.toAmplifyOutputs(); await apiPlugin.configure( - config: config, + config: amplifyOutputs, authProviderRepo: authProviderRepo, ); diff --git a/packages/auth/amplify_auth_cognito/lib/src/auth_plugin_impl.dart b/packages/auth/amplify_auth_cognito/lib/src/auth_plugin_impl.dart index c303fe10cb..7b9889f309 100644 --- a/packages/auth/amplify_auth_cognito/lib/src/auth_plugin_impl.dart +++ b/packages/auth/amplify_auth_cognito/lib/src/auth_plugin_impl.dart @@ -77,7 +77,7 @@ class AmplifyAuthCognito extends AmplifyAuthCognitoDart with AWSDebuggable { @override Future configure({ - AmplifyConfig? config, + AmplifyOutputs? config, required AmplifyAuthProviderRepository authProviderRepo, }) async { // Dependencies for AnalyticsMetadataType diff --git a/packages/auth/amplify_auth_cognito_dart/lib/src/auth_plugin_impl.dart b/packages/auth/amplify_auth_cognito_dart/lib/src/auth_plugin_impl.dart index 608fd09bf0..0ebc16cec8 100644 --- a/packages/auth/amplify_auth_cognito_dart/lib/src/auth_plugin_impl.dart +++ b/packages/auth/amplify_auth_cognito_dart/lib/src/auth_plugin_impl.dart @@ -212,7 +212,7 @@ class AmplifyAuthCognitoDart extends AuthPluginInterface @override Future configure({ - AmplifyConfig? config, + AmplifyOutputs? config, required AmplifyAuthProviderRepository authProviderRepo, }) async { if (config == null) { diff --git a/packages/auth/amplify_auth_cognito_dart/lib/src/model/auth_configuration.dart b/packages/auth/amplify_auth_cognito_dart/lib/src/model/auth_configuration.dart index 74bdd1831a..1b0b14e291 100644 --- a/packages/auth/amplify_auth_cognito_dart/lib/src/model/auth_configuration.dart +++ b/packages/auth/amplify_auth_cognito_dart/lib/src/model/auth_configuration.dart @@ -18,6 +18,56 @@ class AuthConfiguration with AWSEquatable { this.pinpointConfig, }); + /// Parses [amplifyOutputs] into the appropriate [AuthConfiguration] type. + /// + /// {@macro amplify_auth_cognito.auth_configuration} + factory AuthConfiguration.fromAmplifyOutputs(AmplifyOutputs amplifyOutputs) { + final authOutputs = amplifyOutputs.auth; + if (authOutputs == null) { + throw ConfigurationError( + 'Invalid config: No Auth config found', + ); + } + CognitoUserPoolConfig? userPoolConfig; + if (authOutputs.userPoolId != null && + authOutputs.userPoolClientId != null) { + // ignore: invalid_use_of_internal_member + userPoolConfig = CognitoUserPoolConfig.fromAuthOutputs(authOutputs); + } + CognitoIdentityCredentialsProvider? identityPoolConfig; + if (authOutputs.identityPoolId != null) { + identityPoolConfig = CognitoIdentityCredentialsProvider( + poolId: authOutputs.identityPoolId!, + region: authOutputs.awsRegion, + ); + } + CognitoOAuthConfig? hostedUiConfig; + if (authOutputs.userPoolClientId != null && authOutputs.oauth != null) { + // ignore: invalid_use_of_internal_member + hostedUiConfig = CognitoOAuthConfig.fromAuthOutputs(authOutputs); + } + if (userPoolConfig == null && + identityPoolConfig == null && + hostedUiConfig == null) { + throw ConfigurationError( + 'Invalid config: No user pool or identity pool found', + ); + } + CognitoPinpointAnalyticsConfig? pinpointConfig; + if (amplifyOutputs.analytics?.amazonPinpoint != null) { + pinpointConfig = CognitoPinpointAnalyticsConfig( + appId: amplifyOutputs.analytics!.amazonPinpoint!.appId, + region: amplifyOutputs.analytics!.amazonPinpoint!.awsRegion, + ); + } + return AuthConfiguration._( + userPoolConfig: userPoolConfig, + identityPoolConfig: identityPoolConfig, + hostedUiConfig: hostedUiConfig, + pinpointConfig: pinpointConfig, + ); + } + /// Parses [config] into the appropriate [AuthConfiguration] type. /// /// {@macro amplify_auth_cognito.auth_configuration} diff --git a/packages/auth/amplify_auth_cognito_dart/lib/src/state/event/configuration_event.dart b/packages/auth/amplify_auth_cognito_dart/lib/src/state/event/configuration_event.dart index a576c1f790..d12d0fe724 100644 --- a/packages/auth/amplify_auth_cognito_dart/lib/src/state/event/configuration_event.dart +++ b/packages/auth/amplify_auth_cognito_dart/lib/src/state/event/configuration_event.dart @@ -22,11 +22,11 @@ sealed class ConfigurationEvent const ConfigurationEvent._(); /// {@macro amplify_auth_cognito.configuration_event.configure} - const factory ConfigurationEvent.configure(AmplifyConfig config) = Configure; + const factory ConfigurationEvent.configure(AmplifyOutputs config) = Configure; /// {@macro amplify_auth_cognito.configuration_event.configure_succeeded} const factory ConfigurationEvent.configureSucceeded( - CognitoPluginConfig config, + AmplifyOutputs config, ) = ConfigureSucceeded; @override @@ -45,7 +45,7 @@ final class Configure extends ConfigurationEvent { const Configure(this.config) : super._(); /// The user's Amplify configuration. - final AmplifyConfig config; + final AmplifyOutputs config; @override ConfigurationEventType get type => ConfigurationEventType.configure; @@ -79,7 +79,7 @@ final class ConfigureSucceeded extends ConfigurationEvent { const ConfigureSucceeded(this.config) : super._(); /// The Cognito plugin configuration. - final CognitoPluginConfig config; + final AmplifyOutputs config; @override ConfigurationEventType get type => ConfigurationEventType.configureSucceeded; diff --git a/packages/auth/amplify_auth_cognito_dart/lib/src/state/machines/configuration_state_machine.dart b/packages/auth/amplify_auth_cognito_dart/lib/src/state/machines/configuration_state_machine.dart index 80632a62e9..1ae2e5e298 100644 --- a/packages/auth/amplify_auth_cognito_dart/lib/src/state/machines/configuration_state_machine.dart +++ b/packages/auth/amplify_auth_cognito_dart/lib/src/state/machines/configuration_state_machine.dart @@ -64,12 +64,11 @@ final class ConfigurationStateMachine /// State machine callback for the [Configure] event. Future onConfigure(Configure event) async { - final cognitoConfig = event.config.auth?.awsPlugin; - if (cognitoConfig == null) { + if (event.config.auth == null) { throw ConfigurationError('No Cognito plugin config available'); } - addInstance(cognitoConfig); - final config = AuthConfiguration.fromConfig(cognitoConfig); + addInstance(event.config.auth!); + final config = AuthConfiguration.fromAmplifyOutputs(event.config); addInstance(config); final waiters = >[]; @@ -107,14 +106,14 @@ final class ConfigurationStateMachine waiters.add(manager.loadCredentials()); - await _waitForConfiguration(cognitoConfig, waiters); + await _waitForConfiguration(event.config, waiters); // Setup AnalyticsMetadataType await _registerAnalyticsMetadata(config); } Future _waitForConfiguration( - CognitoPluginConfig config, + AmplifyOutputs config, List> futures, ) async { await Future.wait(futures, eagerError: true); diff --git a/packages/auth/amplify_auth_cognito_dart/lib/src/state/state/configuration_state.dart b/packages/auth/amplify_auth_cognito_dart/lib/src/state/state/configuration_state.dart index ade718ee38..7a1a074ebf 100644 --- a/packages/auth/amplify_auth_cognito_dart/lib/src/state/state/configuration_state.dart +++ b/packages/auth/amplify_auth_cognito_dart/lib/src/state/state/configuration_state.dart @@ -34,7 +34,7 @@ sealed class ConfigurationState extends AuthState { const factory ConfigurationState.configuring() = Configuring; /// {@macro amplify_auth_cognito.configuration_state.configured} - const factory ConfigurationState.configured(CognitoPluginConfig config) = + const factory ConfigurationState.configured(AmplifyOutputs config) = Configured; /// {@macro amplify_auth_cognito.configuration_state.configure_failure} @@ -83,7 +83,7 @@ final class Configured extends ConfigurationState with SuccessState { const Configured(this.config); /// The configured plugin config. - final CognitoPluginConfig config; + final AmplifyOutputs config; @override ConfigurationStateType get type => ConfigurationStateType.configured; diff --git a/packages/auth/amplify_auth_cognito_test/lib/common/mock_config.dart b/packages/auth/amplify_auth_cognito_test/lib/common/mock_config.dart index 41871af7f5..249c56efb5 100644 --- a/packages/auth/amplify_auth_cognito_test/lib/common/mock_config.dart +++ b/packages/auth/amplify_auth_cognito_test/lib/common/mock_config.dart @@ -34,7 +34,8 @@ final userPoolOnlyConfig = AmplifyConfig( region: testRegion, ), ), -); +).toAmplifyOutputs(); + final mockConfig = AmplifyConfig( auth: AuthConfig.cognito( userPoolConfig: const CognitoUserPoolConfig( @@ -48,7 +49,7 @@ final mockConfig = AmplifyConfig( ), hostedUiConfig: hostedUiConfig, ), -); +).toAmplifyOutputs(); final mockConfigWithPinpoint = AmplifyConfig( auth: AuthConfig.cognito( @@ -57,12 +58,17 @@ final mockConfigWithPinpoint = AmplifyConfig( appClientId: testAppClientId, region: testRegion, ), - pinpointAnalyticsConfig: const CognitoPinpointAnalyticsConfig( - appId: testPinpointAppId, - region: testRegion, - ), ), -); + analytics: const AnalyticsConfig( + plugins: { + 'awsPinpointAnalyticsPlugin': PinpointPluginConfig( + pinpointAnalytics: + PinpointAnalytics(appId: testPinpointAppId, region: testRegion), + pinpointTargeting: PinpointTargeting(region: testRegion), + ), + }, + ), +).toAmplifyOutputs(); final accessToken = JsonWebToken( header: const JsonWebHeader(algorithm: Algorithm.hmacSha256), @@ -98,7 +104,7 @@ const deviceKey = 'deviceKey'; const deviceGroupKey = 'deviceGroupKey'; const devicePassword = 'devicePassword'; -final authConfig = AuthConfiguration.fromConfig(mockConfig.auth!.awsPlugin!); +final authConfig = AuthConfiguration.fromAmplifyOutputs(mockConfig); final userPoolConfig = authConfig.userPoolConfig!; final identityPoolConfig = authConfig.identityPoolConfig!; final userPoolKeys = CognitoUserPoolKeys(userPoolConfig); diff --git a/packages/auth/amplify_auth_cognito_test/test/plugin/delete_user_test.dart b/packages/auth/amplify_auth_cognito_test/test/plugin/delete_user_test.dart index 6cafea2ffc..4fb4fdf006 100644 --- a/packages/auth/amplify_auth_cognito_test/test/plugin/delete_user_test.dart +++ b/packages/auth/amplify_auth_cognito_test/test/plugin/delete_user_test.dart @@ -20,7 +20,7 @@ import 'package:amplify_secure_storage_dart/amplify_secure_storage_dart.dart'; import 'package:test/test.dart'; void main() { - final authConfig = AuthConfiguration.fromConfig(mockConfig.auth!.awsPlugin!); + final authConfig = AuthConfiguration.fromAmplifyOutputs(mockConfig); final userPoolConfig = authConfig.userPoolConfig!; final identityPoolConfig = authConfig.identityPoolConfig!; final userPoolKeys = CognitoUserPoolKeys(userPoolConfig); diff --git a/packages/auth/amplify_auth_cognito_test/test/plugin/reset_password_test.dart b/packages/auth/amplify_auth_cognito_test/test/plugin/reset_password_test.dart index 48e543f073..d1d4ebe6e1 100644 --- a/packages/auth/amplify_auth_cognito_test/test/plugin/reset_password_test.dart +++ b/packages/auth/amplify_auth_cognito_test/test/plugin/reset_password_test.dart @@ -17,7 +17,7 @@ import 'package:test/test.dart'; // Follows resetPassword test cases: // https://github.com/aws-amplify/amplify-android/tree/main/aws-auth-cognito/src/test/resources/feature-test/testsuites/resetPassword void main() { - final authConfig = AuthConfiguration.fromConfig(mockConfig.auth!.awsPlugin!); + final authConfig = AuthConfiguration.fromAmplifyOutputs(mockConfig); final userPoolConfig = authConfig.userPoolConfig!; final identityPoolConfig = authConfig.identityPoolConfig!; final userPoolKeys = CognitoUserPoolKeys(userPoolConfig); diff --git a/packages/auth/amplify_auth_cognito_test/test/state/configuration_state_machine_test.dart b/packages/auth/amplify_auth_cognito_test/test/state/configuration_state_machine_test.dart index f707d9a2dc..b44f655525 100644 --- a/packages/auth/amplify_auth_cognito_test/test/state/configuration_state_machine_test.dart +++ b/packages/auth/amplify_auth_cognito_test/test/state/configuration_state_machine_test.dart @@ -13,7 +13,7 @@ import 'package:amplify_secure_storage_dart/amplify_secure_storage_dart.dart'; import 'package:stream_transform/stream_transform.dart'; import 'package:test/test.dart'; -const badConfig = AmplifyConfig(); +final badConfig = const AmplifyConfig().toAmplifyOutputs(); void main() { late CognitoAuthStateMachine stateMachine; @@ -50,7 +50,7 @@ void main() { expect( stateMachine - .dispatch(const ConfigurationEvent.configure(badConfig)) + .dispatch(ConfigurationEvent.configure(badConfig)) .completed, throwsA(isA()), ); diff --git a/packages/auth/amplify_auth_cognito_test/test/state/fetch_auth_session_state_machine_test.dart b/packages/auth/amplify_auth_cognito_test/test/state/fetch_auth_session_state_machine_test.dart index 896aa0c0e4..93acde47d4 100644 --- a/packages/auth/amplify_auth_cognito_test/test/state/fetch_auth_session_state_machine_test.dart +++ b/packages/auth/amplify_auth_cognito_test/test/state/fetch_auth_session_state_machine_test.dart @@ -20,7 +20,7 @@ void main() { group('FetchAuthSessionStateMachine', () { late CognitoAuthStateMachine stateMachine; late SecureStorageInterface secureStorage; - late AmplifyConfig config; + late AmplifyOutputs config; late CognitoAuthSession session; final newAccessToken = createJwt( @@ -46,7 +46,7 @@ void main() { const newAccessKeyId = 'newAccessKeyId'; const newSecretAccessKey = 'newSecretAccessKey'; - Future configureAmplify(AmplifyConfig config) async { + Future configureAmplify(AmplifyOutputs config) async { stateMachine.dispatch(ConfigurationEvent.configure(config)).ignore(); await stateMachine.stream.whereType().first; } diff --git a/packages/notifications/push/amplify_push_notifications/android/build.gradle b/packages/notifications/push/amplify_push_notifications/android/build.gradle index 7b2d5bb67e..8b583ff9d3 100644 --- a/packages/notifications/push/amplify_push_notifications/android/build.gradle +++ b/packages/notifications/push/amplify_push_notifications/android/build.gradle @@ -65,7 +65,7 @@ android { dependencies { api "com.google.firebase:firebase-messaging:23.2.0" // Import support library for Amplify push utils - implementation 'com.amplifyframework:aws-push-notifications-pinpoint-common:2.15.0' + implementation 'com.amplifyframework:aws-push-notifications-pinpoint-common:2.19.0' implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1" implementation project(path: ':flutter_plugin_android_lifecycle') implementation 'androidx.test:core-ktx:1.5.0' diff --git a/packages/notifications/push/amplify_push_notifications/lib/src/amplify_push_notifications_impl.dart b/packages/notifications/push/amplify_push_notifications/lib/src/amplify_push_notifications_impl.dart index eaf8faba52..9105e011f9 100644 --- a/packages/notifications/push/amplify_push_notifications/lib/src/amplify_push_notifications_impl.dart +++ b/packages/notifications/push/amplify_push_notifications/lib/src/amplify_push_notifications_impl.dart @@ -205,10 +205,10 @@ abstract class AmplifyPushNotifications @override Future configure({ - AmplifyConfig? config, + AmplifyOutputs? config, required AmplifyAuthProviderRepository authProviderRepo, }) async { - final notificationsConfig = config?.notifications?.awsPlugin; + final notificationsConfig = config?.notifications; if (notificationsConfig == null) { throw const PushNotificationException( 'No Pinpoint plugin config available', diff --git a/packages/notifications/push/amplify_push_notifications/test/amplify_push_notifications_impl_test.dart b/packages/notifications/push/amplify_push_notifications/test/amplify_push_notifications_impl_test.dart index 4982136ffa..49323b92fc 100644 --- a/packages/notifications/push/amplify_push_notifications/test/amplify_push_notifications_impl_test.dart +++ b/packages/notifications/push/amplify_push_notifications/test/amplify_push_notifications_impl_test.dart @@ -56,7 +56,8 @@ void main() { final config = AmplifyConfig.fromJson( jsonDecode(amplifyconfig) as Map, - ); + // ignore: invalid_use_of_internal_member + ).toAmplifyOutputs(); setUp(() { plugin = TestAmplifyPushNotifications( @@ -204,7 +205,8 @@ void main() { () async { final config = AmplifyConfig.fromJson( jsonDecode(noPushAppIdAmplifyConfig) as Map, - ); + // ignore: invalid_use_of_internal_member + ).toAmplifyOutputs(); expect( () async => plugin.configure( authProviderRepo: authProviderRepo, diff --git a/packages/notifications/push/amplify_push_notifications/test/amplify_push_notifications_impl_test.mocks.dart b/packages/notifications/push/amplify_push_notifications/test/amplify_push_notifications_impl_test.mocks.dart index 7b11a92877..a484147ca5 100644 --- a/packages/notifications/push/amplify_push_notifications/test/amplify_push_notifications_impl_test.mocks.dart +++ b/packages/notifications/push/amplify_push_notifications/test/amplify_push_notifications_impl_test.mocks.dart @@ -1,4 +1,4 @@ -// Mocks generated by Mockito 5.4.2 from annotations +// Mocks generated by Mockito 5.4.4 from annotations // in amplify_push_notifications/test/amplify_push_notifications_impl_test.dart. // Do not manually edit this file. @@ -6,20 +6,25 @@ import 'dart:async' as _i5; import 'package:amplify_core/amplify_core.dart' as _i4; +import 'package:amplify_core/src/config/amplify_outputs/notifications/notifications_outputs.dart' + as _i6; import 'package:amplify_push_notifications/src/native_push_notifications_plugin.g.dart' as _i2; import 'package:amplify_push_notifications/src/push_notifications_flutter_api.dart' - as _i7; + as _i9; import 'package:amplify_secure_storage/src/amplify_secure_storage.vm.dart' - as _i6; + as _i7; import 'package:amplify_secure_storage_dart/amplify_secure_storage_dart.dart' as _i3; import 'package:mockito/mockito.dart' as _i1; +import 'package:mockito/src/dummies.dart' as _i8; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values // ignore_for_file: avoid_setters_without_getters // ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package // ignore_for_file: implementation_imports // ignore_for_file: invalid_use_of_visible_for_testing_member // ignore_for_file: prefer_const_constructors @@ -77,6 +82,7 @@ class MockPushNotificationsHostApi extends _i1.Mock returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); + @override _i5.Future<_i2.GetPermissionStatusResult> getPermissionStatus() => (super.noSuchMethod( @@ -93,6 +99,7 @@ class MockPushNotificationsHostApi extends _i1.Mock ), )), ) as _i5.Future<_i2.GetPermissionStatusResult>); + @override _i5.Future requestPermissions( _i2.PermissionsOptions? arg_withPermissionOptions) => @@ -103,6 +110,7 @@ class MockPushNotificationsHostApi extends _i1.Mock ), returnValue: _i5.Future.value(false), ) as _i5.Future); + @override _i5.Future?> getLaunchNotification() => (super.noSuchMethod( @@ -112,6 +120,7 @@ class MockPushNotificationsHostApi extends _i1.Mock ), returnValue: _i5.Future?>.value(), ) as _i5.Future?>); + @override _i5.Future getBadgeCount() => (super.noSuchMethod( Invocation.method( @@ -120,6 +129,7 @@ class MockPushNotificationsHostApi extends _i1.Mock ), returnValue: _i5.Future.value(0), ) as _i5.Future); + @override _i5.Future setBadgeCount(int? arg_withBadgeCount) => (super.noSuchMethod( @@ -130,6 +140,7 @@ class MockPushNotificationsHostApi extends _i1.Mock returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); + @override _i5.Future registerCallbackFunction(int? arg_callbackHandle) => (super.noSuchMethod( @@ -153,7 +164,7 @@ class MockServiceProviderClient extends _i1.Mock @override _i5.Future init({ - required _i4.NotificationsPinpointPluginConfig? config, + required _i6.NotificationsOutputs? config, required _i4.AmplifyAuthProviderRepository? authProviderRepo, }) => (super.noSuchMethod( @@ -168,6 +179,7 @@ class MockServiceProviderClient extends _i1.Mock returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); + @override _i5.Future registerDevice(String? deviceToken) => (super.noSuchMethod( Invocation.method( @@ -177,6 +189,7 @@ class MockServiceProviderClient extends _i1.Mock returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); + @override _i5.Future recordNotificationEvent({ required _i4.PinpointEventType? eventType, @@ -194,6 +207,7 @@ class MockServiceProviderClient extends _i1.Mock returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); + @override _i5.Future identifyUser({ required String? userId, @@ -217,7 +231,7 @@ class MockServiceProviderClient extends _i1.Mock /// /// See the documentation for Mockito's code generation for more information. class MockAmplifySecureStorage extends _i1.Mock - implements _i6.AmplifySecureStorage { + implements _i7.AmplifySecureStorage { MockAmplifySecureStorage() { _i1.throwOnMissingStub(this); } @@ -230,11 +244,16 @@ class MockAmplifySecureStorage extends _i1.Mock Invocation.getter(#config), ), ) as _i3.AmplifySecureStorageConfig); + @override String get runtimeTypeName => (super.noSuchMethod( Invocation.getter(#runtimeTypeName), - returnValue: '', + returnValue: _i8.dummyValue( + this, + Invocation.getter(#runtimeTypeName), + ), ) as String); + @override _i4.AWSLogger get logger => (super.noSuchMethod( Invocation.getter(#logger), @@ -243,6 +262,7 @@ class MockAmplifySecureStorage extends _i1.Mock Invocation.getter(#logger), ), ) as _i4.AWSLogger); + @override _i5.Future delete({required String? key}) => (super.noSuchMethod( Invocation.method( @@ -253,6 +273,7 @@ class MockAmplifySecureStorage extends _i1.Mock returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); + @override _i5.Future read({required String? key}) => (super.noSuchMethod( Invocation.method( @@ -262,6 +283,7 @@ class MockAmplifySecureStorage extends _i1.Mock ), returnValue: _i5.Future.value(), ) as _i5.Future); + @override _i5.Future write({ required String? key, @@ -279,6 +301,7 @@ class MockAmplifySecureStorage extends _i1.Mock returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); + @override _i5.Future removeAll() => (super.noSuchMethod( Invocation.method( @@ -294,7 +317,7 @@ class MockAmplifySecureStorage extends _i1.Mock /// /// See the documentation for Mockito's code generation for more information. class MockAmplifyPushNotificationsFlutterApi extends _i1.Mock - implements _i7.AmplifyPushNotificationsFlutterApi { + implements _i9.AmplifyPushNotificationsFlutterApi { MockAmplifyPushNotificationsFlutterApi() { _i1.throwOnMissingStub(this); } @@ -304,6 +327,7 @@ class MockAmplifyPushNotificationsFlutterApi extends _i1.Mock Invocation.getter(#eventQueue), returnValue: <_i4.PushNotificationMessage>[], ) as List<_i4.PushNotificationMessage>); + @override set onNullifyLaunchNotificationCallback(void Function()? callback) => super.noSuchMethod( @@ -313,6 +337,7 @@ class MockAmplifyPushNotificationsFlutterApi extends _i1.Mock ), returnValueForMissingStub: null, ); + @override set serviceProviderClient(_i4.ServiceProviderClient? serviceProviderClient) => super.noSuchMethod( @@ -322,6 +347,7 @@ class MockAmplifyPushNotificationsFlutterApi extends _i1.Mock ), returnValueForMissingStub: null, ); + @override void registerOnReceivedInBackgroundCallback( _i4.OnRemoteMessageCallback? callback) => @@ -332,6 +358,7 @@ class MockAmplifyPushNotificationsFlutterApi extends _i1.Mock ), returnValueForMissingStub: null, ); + @override _i5.Future onNotificationReceivedInBackground( Map? payload) => @@ -343,6 +370,7 @@ class MockAmplifyPushNotificationsFlutterApi extends _i1.Mock returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); + @override void nullifyLaunchNotification() => super.noSuchMethod( Invocation.method( diff --git a/packages/notifications/push/amplify_push_notifications_pinpoint/lib/src/pinpoint_provider.dart b/packages/notifications/push/amplify_push_notifications_pinpoint/lib/src/pinpoint_provider.dart index 16cf585409..9ed9639d94 100644 --- a/packages/notifications/push/amplify_push_notifications_pinpoint/lib/src/pinpoint_provider.dart +++ b/packages/notifications/push/amplify_push_notifications_pinpoint/lib/src/pinpoint_provider.dart @@ -12,6 +12,8 @@ import 'package:amplify_analytics_pinpoint_dart/src/impl/analytics_client/analyt // ignore: implementation_imports import 'package:amplify_analytics_pinpoint_dart/src/sdk/src/pinpoint/model/channel_type.dart'; import 'package:amplify_core/amplify_core.dart'; +// ignore: implementation_imports +import 'package:amplify_core/src/config/amplify_outputs/notifications/notifications_outputs.dart'; import 'package:amplify_push_notifications_pinpoint/src/event_info_type.dart'; import 'package:amplify_secure_storage/amplify_secure_storage.dart'; import 'package:flutter/widgets.dart'; @@ -54,7 +56,7 @@ class PinpointProvider implements ServiceProviderClient { @override Future init({ - required NotificationsPinpointPluginConfig config, + required NotificationsOutputs config, required AmplifyAuthProviderRepository authProviderRepo, @visibleForTesting AnalyticsClient? analyticsClient, }) async { @@ -68,8 +70,8 @@ class PinpointProvider implements ServiceProviderClient { 'No AWSIamAmplifyAuthProvider available. Is Auth category added and configured?', ); } - final region = config.region; - final appId = config.appId; + final region = config.awsRegion; + final appId = config.amazonPinpointAppId; final secureStorageFactory = AmplifySecureStorage.factoryFrom(); diff --git a/packages/notifications/push/amplify_push_notifications_pinpoint/test/pinpoint_provider_test.dart b/packages/notifications/push/amplify_push_notifications_pinpoint/test/pinpoint_provider_test.dart index 047d94217a..1baaa9ccc7 100644 --- a/packages/notifications/push/amplify_push_notifications_pinpoint/test/pinpoint_provider_test.dart +++ b/packages/notifications/push/amplify_push_notifications_pinpoint/test/pinpoint_provider_test.dart @@ -5,6 +5,8 @@ import 'package:amplify_analytics_pinpoint_dart/src/impl/analytics_client/analytics_client.dart'; import 'package:amplify_analytics_pinpoint_dart/src/impl/analytics_client/endpoint_client/endpoint_client.dart'; import 'package:amplify_analytics_pinpoint_dart/src/impl/analytics_client/event_client/event_client.dart'; +import 'package:amplify_core/src/config/amplify_outputs/notifications/amazon_pinpoint_channel.dart'; +import 'package:amplify_core/src/config/amplify_outputs/notifications/notifications_outputs.dart'; import 'package:amplify_flutter/amplify_flutter.dart'; import 'package:amplify_push_notifications_pinpoint/src/pinpoint_provider.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -30,9 +32,10 @@ void main() { TestWidgetsFlutterBinding.ensureInitialized(); final pinpointProvider = PinpointProvider(); final mockAmplifyAuthProviderRepository = MockAmplifyAuthProviderRepository(); - const notificationsPinpointConfig = NotificationsPinpointPluginConfig( - appId: 'APP_ID', - region: 'REGION', + const notificationsPinpointConfig = NotificationsOutputs( + amazonPinpointAppId: 'APP_ID', + awsRegion: 'REGION', + channels: [AmazonPinpointChannel.fcm, AmazonPinpointChannel.apns], ); final awsIamAmplifyAuthProvider = MockAWSIamAmplifyAuthProvider(); final mockAnalyticsClient = MockAnalyticsClient(); diff --git a/packages/storage/amplify_storage_s3/lib/src/amplify_storage_s3_impl.dart b/packages/storage/amplify_storage_s3/lib/src/amplify_storage_s3_impl.dart index a3a693fcd7..57ac298d87 100644 --- a/packages/storage/amplify_storage_s3/lib/src/amplify_storage_s3_impl.dart +++ b/packages/storage/amplify_storage_s3/lib/src/amplify_storage_s3_impl.dart @@ -21,7 +21,7 @@ class AmplifyStorageS3 extends AmplifyStorageS3Dart { @override Future configure({ - AmplifyConfig? config, + AmplifyOutputs? config, required AmplifyAuthProviderRepository authProviderRepo, }) async { await super.configure(config: config, authProviderRepo: authProviderRepo); diff --git a/packages/storage/amplify_storage_s3/test/amplify_storage_s3_impl_test.dart b/packages/storage/amplify_storage_s3/test/amplify_storage_s3_impl_test.dart index 4612eb6b5a..418bd4dbdb 100644 --- a/packages/storage/amplify_storage_s3/test/amplify_storage_s3_impl_test.dart +++ b/packages/storage/amplify_storage_s3/test/amplify_storage_s3_impl_test.dart @@ -12,7 +12,7 @@ import 'test_utils/test_token_provider.dart'; void main() { group('AmplifyStorageS3', () { - const testConfig = AmplifyConfig( + final testConfig = const AmplifyConfig( storage: StorageConfig( plugins: { S3PluginConfig.pluginKey: S3PluginConfig( @@ -21,7 +21,8 @@ void main() { ), }, ), - ); + // ignore: invalid_use_of_internal_member + ).toAmplifyOutputs(); final testAuthProviderRepo = AmplifyAuthProviderRepository() ..registerAuthProvider( APIAuthorizationType.userPools.authProviderToken, diff --git a/packages/storage/amplify_storage_s3_dart/lib/src/amplify_storage_s3_dart_impl.dart b/packages/storage/amplify_storage_s3_dart/lib/src/amplify_storage_s3_dart_impl.dart index ea432433f1..cc709c5802 100644 --- a/packages/storage/amplify_storage_s3_dart/lib/src/amplify_storage_s3_dart_impl.dart +++ b/packages/storage/amplify_storage_s3_dart/lib/src/amplify_storage_s3_dart_impl.dart @@ -5,6 +5,8 @@ import 'dart:async'; import 'dart:typed_data'; import 'package:amplify_core/amplify_core.dart'; +// ignore: implementation_imports +import 'package:amplify_core/src/config/amplify_outputs/storage/storage_outputs.dart'; import 'package:amplify_db_common_dart/amplify_db_common_dart.dart' as db_common; import 'package:amplify_storage_s3_dart/amplify_storage_s3_dart.dart'; @@ -46,9 +48,9 @@ class AmplifyStorageS3Dart extends StoragePluginInterface DependencyManager get dependencies => _dependencyManagerOverride ?? super.dependencies; - /// The [S3PluginConfig] of the [AmplifyStorageS3Dart] plugin. + /// The [StorageOutputs] of the [AmplifyStorageS3Dart] plugin. @protected - late final S3PluginConfig s3pluginConfig; + late final StorageOutputs storageOutputs; late S3PathResolver _pathResolver; @@ -60,15 +62,13 @@ class AmplifyStorageS3Dart extends StoragePluginInterface @override Future configure({ - AmplifyConfig? config, + AmplifyOutputs? config, required AmplifyAuthProviderRepository authProviderRepo, }) async { - final s3PluginConfig = config?.storage?.awsPlugin; - - if (s3PluginConfig == null) { + if (config?.storage == null) { throw ConfigurationError('No Storage S3 plugin config detected.'); } - s3pluginConfig = s3PluginConfig; + storageOutputs = config!.storage!; final identityProvider = authProviderRepo .getAuthProvider(APIAuthorizationType.userPools.authProviderToken); @@ -107,7 +107,7 @@ class AmplifyStorageS3Dart extends StoragePluginInterface ..addInstance( StorageS3Service( credentialsProvider: credentialsProvider, - s3PluginConfig: s3PluginConfig, + storageOutputs: storageOutputs, pathResolver: _pathResolver, logger: logger, dependencyManager: dependencies, @@ -261,7 +261,7 @@ class AmplifyStorageS3Dart extends StoragePluginInterface path: path, localFile: localFile, options: options, - s3pluginConfig: s3pluginConfig, + storageOutputs: storageOutputs, storageS3Service: storageS3Service, appPathProvider: _appPathProvider, onProgress: onProgress, diff --git a/packages/storage/amplify_storage_s3_dart/lib/src/platform_impl/download_file/download_file_html.dart b/packages/storage/amplify_storage_s3_dart/lib/src/platform_impl/download_file/download_file_html.dart index 3d2b750855..32f79a9d38 100644 --- a/packages/storage/amplify_storage_s3_dart/lib/src/platform_impl/download_file/download_file_html.dart +++ b/packages/storage/amplify_storage_s3_dart/lib/src/platform_impl/download_file/download_file_html.dart @@ -2,6 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 import 'package:amplify_core/amplify_core.dart'; +// ignore: implementation_imports +import 'package:amplify_core/src/config/amplify_outputs/storage/storage_outputs.dart'; import 'package:amplify_storage_s3_dart/amplify_storage_s3_dart.dart'; import 'package:amplify_storage_s3_dart/src/platform_impl/download_file/dom_helper.dart'; import 'package:amplify_storage_s3_dart/src/storage_s3_service/storage_s3_service.dart'; @@ -11,7 +13,7 @@ S3DownloadFileOperation downloadFile({ required StoragePath path, required AWSFile localFile, required StorageDownloadFileOptions options, - required S3PluginConfig s3pluginConfig, + required StorageOutputs storageOutputs, required StorageS3Service storageS3Service, required AppPathProvider appPathProvider, void Function(S3TransferProgress)? onProgress, @@ -28,7 +30,7 @@ S3DownloadFileOperation downloadFile({ path: path, localFile: localFile, options: options, - s3pluginConfig: s3pluginConfig, + storageOutputs: storageOutputs, storageS3Service: storageS3Service, ), // In Web the download process is managed by the browser so the operation @@ -43,7 +45,7 @@ Future _downloadFromUrl({ required StoragePath path, required AWSFile localFile, required StorageDownloadFileOptions options, - required S3PluginConfig s3pluginConfig, + required StorageOutputs storageOutputs, required StorageS3Service storageS3Service, }) async { final s3PluginOptions = options.pluginOptions as S3DownloadFilePluginOptions; diff --git a/packages/storage/amplify_storage_s3_dart/lib/src/platform_impl/download_file/download_file_io.dart b/packages/storage/amplify_storage_s3_dart/lib/src/platform_impl/download_file/download_file_io.dart index 6e7558c042..5651870acd 100644 --- a/packages/storage/amplify_storage_s3_dart/lib/src/platform_impl/download_file/download_file_io.dart +++ b/packages/storage/amplify_storage_s3_dart/lib/src/platform_impl/download_file/download_file_io.dart @@ -4,6 +4,8 @@ import 'dart:io'; import 'package:amplify_core/amplify_core.dart'; +// ignore: implementation_imports +import 'package:amplify_core/src/config/amplify_outputs/storage/storage_outputs.dart'; import 'package:amplify_storage_s3_dart/amplify_storage_s3_dart.dart'; import 'package:amplify_storage_s3_dart/src/storage_s3_service/storage_s3_service.dart'; import 'package:meta/meta.dart'; @@ -15,7 +17,7 @@ S3DownloadFileOperation downloadFile({ required StoragePath path, required AWSFile localFile, required StorageDownloadFileOptions options, - required S3PluginConfig s3pluginConfig, + required StorageOutputs storageOutputs, required StorageS3Service storageS3Service, required AppPathProvider appPathProvider, void Function(S3TransferProgress)? onProgress, diff --git a/packages/storage/amplify_storage_s3_dart/lib/src/platform_impl/download_file/download_file_stub.dart b/packages/storage/amplify_storage_s3_dart/lib/src/platform_impl/download_file/download_file_stub.dart index 94eb03c0e9..066fdc5160 100644 --- a/packages/storage/amplify_storage_s3_dart/lib/src/platform_impl/download_file/download_file_stub.dart +++ b/packages/storage/amplify_storage_s3_dart/lib/src/platform_impl/download_file/download_file_stub.dart @@ -2,6 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 import 'package:amplify_core/amplify_core.dart'; +// ignore: implementation_imports +import 'package:amplify_core/src/config/amplify_outputs/storage/storage_outputs.dart'; import 'package:amplify_storage_s3_dart/amplify_storage_s3_dart.dart'; import 'package:amplify_storage_s3_dart/src/storage_s3_service/storage_s3_service.dart'; @@ -10,7 +12,7 @@ S3DownloadFileOperation downloadFile({ required StoragePath path, required AWSFile localFile, required StorageDownloadFileOptions options, - required S3PluginConfig s3pluginConfig, + required StorageOutputs storageOutputs, required StorageS3Service storageS3Service, required AppPathProvider appPathProvider, void Function(S3TransferProgress)? onProgress, diff --git a/packages/storage/amplify_storage_s3_dart/lib/src/storage_s3_service/service/storage_s3_service_impl.dart b/packages/storage/amplify_storage_s3_dart/lib/src/storage_s3_service/service/storage_s3_service_impl.dart index 26e56cd1d7..f8ed6eab3e 100644 --- a/packages/storage/amplify_storage_s3_dart/lib/src/storage_s3_service/service/storage_s3_service_impl.dart +++ b/packages/storage/amplify_storage_s3_dart/lib/src/storage_s3_service/service/storage_s3_service_impl.dart @@ -5,6 +5,8 @@ import 'dart:async'; import 'dart:math'; import 'package:amplify_core/amplify_core.dart' hide PaginatedResult; +// ignore: implementation_imports +import 'package:amplify_core/src/config/amplify_outputs/storage/storage_outputs.dart'; import 'package:amplify_storage_s3_dart/amplify_storage_s3_dart.dart'; import 'package:amplify_storage_s3_dart/src/exception/s3_storage_exception.dart' as s3_exception; @@ -31,13 +33,13 @@ const testDateTimeNowOverride = #_testDateTimeNowOverride; class StorageS3Service { /// {@macro amplify_storage_s3.storage_s3_service} factory StorageS3Service({ - required S3PluginConfig s3PluginConfig, + required StorageOutputs storageOutputs, required S3PathResolver pathResolver, required AWSIamAmplifyAuthProvider credentialsProvider, required AWSLogger logger, required DependencyManager dependencyManager, }) { - final usePathStyle = s3PluginConfig.bucket.contains('.'); + final usePathStyle = storageOutputs.bucketName.contains('.'); if (usePathStyle) { logger.warn( @@ -54,7 +56,7 @@ class StorageS3Service { ); return StorageS3Service._( - s3PluginConfig: s3PluginConfig, + storageOutputs: storageOutputs, s3ClientConfig: s3ClientConfig, pathResolver: pathResolver, credentialsProvider: credentialsProvider, @@ -64,18 +66,18 @@ class StorageS3Service { } StorageS3Service._({ - required S3PluginConfig s3PluginConfig, + required StorageOutputs storageOutputs, required smithy_aws.S3ClientConfig s3ClientConfig, required S3PathResolver pathResolver, required AWSIamAmplifyAuthProvider credentialsProvider, required AWSLogger logger, required DependencyManager dependencyManager, - }) : _s3PluginConfig = s3PluginConfig, + }) : _storageOutptus = storageOutputs, _defaultS3ClientConfig = s3ClientConfig, // dependencyManager.get() => S3Client is used for unit tests _defaultS3Client = dependencyManager.get() ?? s3.S3Client( - region: s3PluginConfig.region, + region: storageOutputs.awsRegion, credentialsProvider: credentialsProvider, s3ClientConfig: s3ClientConfig, client: AmplifyHttpClient(dependencyManager) @@ -94,7 +96,7 @@ class StorageS3Service { static final _defaultS3SignerConfiguration = sigv4.S3ServiceConfiguration(signPayload: false); - final S3PluginConfig _s3PluginConfig; + final StorageOutputs _storageOutptus; final smithy_aws.S3ClientConfig _defaultS3ClientConfig; final s3.S3Client _defaultS3Client; final S3PathResolver _pathResolver; @@ -104,7 +106,7 @@ class StorageS3Service { final DateTime _serviceStartingTime; sigv4.AWSCredentialScope get _signerScope => sigv4.AWSCredentialScope( - region: _s3PluginConfig.region, + region: _storageOutptus.awsRegion, service: AWSService.s3, ); @@ -132,7 +134,7 @@ class StorageS3Service { if (!s3PluginOptions.listAll) { final request = s3.ListObjectsV2Request.build((builder) { builder - ..bucket = _s3PluginConfig.bucket + ..bucket = _storageOutptus.bucketName ..prefix = resolvedPath ..maxKeys = options.pageSize ..continuationToken = options.nextToken @@ -159,7 +161,7 @@ class StorageS3Service { try { final request = s3.ListObjectsV2Request.build((builder) { builder - ..bucket = _s3PluginConfig.bucket + ..bucket = _storageOutptus.bucketName ..prefix = resolvedPath ..delimiter = s3PluginOptions.excludeSubPaths ? s3PluginOptions.delimiter @@ -205,7 +207,7 @@ class StorageS3Service { storageItem: S3Item.fromHeadObjectOutput( await headObject( s3client: _defaultS3Client, - bucket: _s3PluginConfig.bucket, + bucket: _storageOutptus.bucketName, key: resolvedPath, ), path: resolvedPath, @@ -242,14 +244,14 @@ class StorageS3Service { var resolvedPath = await _pathResolver.resolvePath(path: path); var host = - '${_s3PluginConfig.bucket}.${_getS3EndpointHost(region: _s3PluginConfig.region)}'; + '${_storageOutptus.bucketName}.${_getS3EndpointHost(region: _storageOutptus.awsRegion)}'; if (_defaultS3ClientConfig.usePathStyle) { - host = host.replaceFirst('${_s3PluginConfig.bucket}.', ''); - resolvedPath = '${_s3PluginConfig.bucket}/$resolvedPath'; + host = host.replaceFirst('${_storageOutptus.bucketName}.', ''); + resolvedPath = '${_storageOutptus.bucketName}/$resolvedPath'; } else if (s3PluginOptions.useAccelerateEndpoint) { // https: //docs.aws.amazon.com/AmazonS3/latest/userguide/transfer-acceleration-getting-started.html host = host - .replaceFirst(RegExp('${_s3PluginConfig.region}\\.'), '') + .replaceFirst(RegExp('${_storageOutptus.awsRegion}\\.'), '') .replaceFirst(RegExp(r'\.s3\.'), '.s3-accelerate.'); } @@ -295,7 +297,7 @@ class StorageS3Service { final downloadDataTask = S3DownloadTask( s3Client: _defaultS3Client, defaultS3ClientConfig: _defaultS3ClientConfig, - bucket: _s3PluginConfig.bucket, + bucket: _storageOutptus.bucketName, path: path, options: options, pathResolver: _pathResolver, @@ -326,7 +328,7 @@ class StorageS3Service { dataPayload, s3Client: _defaultS3Client, defaultS3ClientConfig: _defaultS3ClientConfig, - bucket: _s3PluginConfig.bucket, + bucket: _storageOutptus.bucketName, path: path, options: options, pathResolver: _pathResolver, @@ -365,7 +367,7 @@ class StorageS3Service { localFile, s3Client: _defaultS3Client, defaultS3ClientConfig: _defaultS3ClientConfig, - bucket: _s3PluginConfig.bucket, + bucket: _storageOutptus.bucketName, path: path, options: uploadDataOptions, pathResolver: _pathResolver, @@ -405,8 +407,8 @@ class StorageS3Service { final copyRequest = s3.CopyObjectRequest.build((builder) { builder - ..bucket = _s3PluginConfig.bucket - ..copySource = '${_s3PluginConfig.bucket}/$sourcePath' + ..bucket = _storageOutptus.bucketName + ..copySource = '${_storageOutptus.bucketName}/$sourcePath' ..key = destinationPath ..metadataDirective = s3.MetadataDirective.copy; }); @@ -425,7 +427,7 @@ class StorageS3Service { ? S3Item.fromHeadObjectOutput( await headObject( s3client: _defaultS3Client, - bucket: _s3PluginConfig.bucket, + bucket: _storageOutptus.bucketName, key: destinationPath, ), path: destinationPath, @@ -449,7 +451,7 @@ class StorageS3Service { await _deleteObject( s3client: _defaultS3Client, - bucket: _s3PluginConfig.bucket, + bucket: _storageOutptus.bucketName, key: resolvedPath, ); @@ -489,7 +491,7 @@ class StorageS3Service { ); final request = s3.DeleteObjectsRequest.build((builder) { builder - ..bucket = _s3PluginConfig.bucket + ..bucket = _storageOutptus.bucketName // force to use sha256 instead of md5 ..checksumAlgorithm = s3.ChecksumAlgorithm.sha256 ..delete = s3.Delete.build((builder) { @@ -596,7 +598,7 @@ class StorageS3Service { for (final record in records) { final request = s3.AbortMultipartUploadRequest.build((builder) { builder - ..bucket = _s3PluginConfig.bucket + ..bucket = _storageOutptus.bucketName ..key = record.objectKey ..uploadId = record.uploadId; }); diff --git a/packages/storage/amplify_storage_s3_dart/test/amplify_storage_s3_dart_test.dart b/packages/storage/amplify_storage_s3_dart/test/amplify_storage_s3_dart_test.dart index e2847a0efd..17015eb5f7 100644 --- a/packages/storage/amplify_storage_s3_dart/test/amplify_storage_s3_dart_test.dart +++ b/packages/storage/amplify_storage_s3_dart/test/amplify_storage_s3_dart_test.dart @@ -15,7 +15,7 @@ import 'test_utils/test_token_provider.dart'; const testPath = StoragePath.fromString('some/path.txt'); void main() { - const testConfig = AmplifyConfig( + final testConfig = const AmplifyConfig( storage: StorageConfig( plugins: { S3PluginConfig.pluginKey: S3PluginConfig( @@ -24,7 +24,8 @@ void main() { ), }, ), - ); + // ignore: invalid_use_of_internal_member + ).toAmplifyOutputs(); final testAuthProviderRepo = AmplifyAuthProviderRepository() ..registerAuthProvider( diff --git a/packages/storage/amplify_storage_s3_dart/test/platform_impl/download_file_html_test.dart b/packages/storage/amplify_storage_s3_dart/test/platform_impl/download_file_html_test.dart index 736e8a184c..50f205d91d 100644 --- a/packages/storage/amplify_storage_s3_dart/test/platform_impl/download_file_html_test.dart +++ b/packages/storage/amplify_storage_s3_dart/test/platform_impl/download_file_html_test.dart @@ -4,6 +4,7 @@ @TestOn('chrome') import 'package:amplify_core/amplify_core.dart'; +import 'package:amplify_core/src/config/amplify_outputs/storage/storage_outputs.dart'; import 'package:amplify_storage_s3_dart/amplify_storage_s3_dart.dart'; import 'package:amplify_storage_s3_dart/src/platform_impl/download_file/download_file.dart'; import 'package:amplify_storage_s3_dart/src/storage_s3_service/storage_s3_service.dart'; @@ -30,9 +31,9 @@ void main() { group('downloadFile() html implementation', () { late StorageS3Service storageS3Service; const testKey = 'upload-key.text'; - const testS3pluginConfig = S3PluginConfig( - bucket: 'fake-bucket', - region: 'west-2', + const testStorageOutputs = StorageOutputs( + bucketName: 'fake-bucket', + awsRegion: 'west-2', ); final testItem = S3Item( path: testKey, @@ -90,7 +91,7 @@ void main() { path: const StoragePath.fromString('public/$testKey'), localFile: AWSFile.fromPath('file_name.jpg'), options: const StorageDownloadFileOptions(), - s3pluginConfig: testS3pluginConfig, + storageOutputs: testStorageOutputs, storageS3Service: storageS3Service, appPathProvider: const DummyPathProvider(), ); @@ -129,7 +130,7 @@ void main() { ), localFile: AWSFile.fromPath('download.jpg'), options: options, - s3pluginConfig: testS3pluginConfig, + storageOutputs: testStorageOutputs, storageS3Service: storageS3Service, appPathProvider: const DummyPathProvider(), ).result; diff --git a/packages/storage/amplify_storage_s3_dart/test/platform_impl/download_file_io_test.dart b/packages/storage/amplify_storage_s3_dart/test/platform_impl/download_file_io_test.dart index ea43d59e18..423f65ed96 100644 --- a/packages/storage/amplify_storage_s3_dart/test/platform_impl/download_file_io_test.dart +++ b/packages/storage/amplify_storage_s3_dart/test/platform_impl/download_file_io_test.dart @@ -8,6 +8,7 @@ import 'dart:convert'; import 'dart:io'; import 'package:amplify_core/amplify_core.dart'; +import 'package:amplify_core/src/config/amplify_outputs/storage/storage_outputs.dart'; import 'package:amplify_core/src/types/storage/storage_path_from_identity_id.dart'; import 'package:amplify_storage_s3_dart/amplify_storage_s3_dart.dart'; import 'package:amplify_storage_s3_dart/src/platform_impl/download_file/download_file.dart'; @@ -29,9 +30,9 @@ void main() { late FutureOr Function() onDone; const appPathProvider = S3DartAppPathProvider(); final testDestinationPath = path.join(Directory.current.path, 'test.txt'); - const testS3pluginConfig = S3PluginConfig( - bucket: 'fake-bucket', - region: 'west-2', + const testStorageOutputs = StorageOutputs( + bucketName: 'fake-bucket', + awsRegion: 'west-2', ); const testKey = 'upload-key.text'; const testFileContent = 'Hello world!'; @@ -83,7 +84,7 @@ void main() { ), localFile: AWSFile.fromPath(testDestinationPath), options: options, - s3pluginConfig: testS3pluginConfig, + storageOutputs: testStorageOutputs, storageS3Service: storageS3Service, appPathProvider: appPathProvider, onProgress: (progress) { @@ -167,7 +168,7 @@ void main() { options: const StorageDownloadFileOptions( pluginOptions: S3DownloadFilePluginOptions(), ), - s3pluginConfig: testS3pluginConfig, + storageOutputs: testStorageOutputs, storageS3Service: storageS3Service, appPathProvider: appPathProvider, onProgress: (progress) { @@ -199,7 +200,7 @@ void main() { options: const StorageDownloadFileOptions( pluginOptions: S3DownloadFilePluginOptions(), ), - s3pluginConfig: testS3pluginConfig, + storageOutputs: testStorageOutputs, storageS3Service: storageS3Service, appPathProvider: appPathProvider, onProgress: (progress) { @@ -237,7 +238,7 @@ void main() { options: const StorageDownloadFileOptions( pluginOptions: S3DownloadFilePluginOptions(), ), - s3pluginConfig: testS3pluginConfig, + storageOutputs: testStorageOutputs, storageS3Service: storageS3Service, appPathProvider: appPathProvider, onProgress: (progress) { diff --git a/packages/storage/amplify_storage_s3_dart/test/storage_s3_service/storage_s3_service_test.dart b/packages/storage/amplify_storage_s3_dart/test/storage_s3_service/storage_s3_service_test.dart index 7b553bba62..aec65db336 100644 --- a/packages/storage/amplify_storage_s3_dart/test/storage_s3_service/storage_s3_service_test.dart +++ b/packages/storage/amplify_storage_s3_dart/test/storage_s3_service/storage_s3_service_test.dart @@ -4,6 +4,7 @@ import 'dart:async'; import 'package:amplify_core/amplify_core.dart' hide PaginatedResult; +import 'package:amplify_core/src/config/amplify_outputs/storage/storage_outputs.dart'; import 'package:amplify_storage_s3_dart/amplify_storage_s3_dart.dart'; import 'package:amplify_storage_s3_dart/src/exception/s3_storage_exception.dart'; import 'package:amplify_storage_s3_dart/src/sdk/s3.dart'; @@ -25,8 +26,8 @@ void main() { group('StorageS3Service', () { const testBucket = 'bucket1'; const testRegion = 'west-2'; - const s3PluginConfig = - S3PluginConfig(bucket: testBucket, region: testRegion); + const storageOutputs = + StorageOutputs(bucketName: testBucket, awsRegion: testRegion); final pathResolver = TestPathResolver(); late DependencyManager dependencyManager; @@ -43,7 +44,7 @@ void main() { ..addInstance(s3Client) ..addInstance(awsSigV4Signer); storageS3Service = StorageS3Service( - s3PluginConfig: s3PluginConfig, + storageOutputs: storageOutputs, pathResolver: pathResolver, credentialsProvider: TestIamAuthProvider(), logger: logger, @@ -53,9 +54,9 @@ void main() { test('log a warning when should use path style URLs', () { StorageS3Service( - s3PluginConfig: const S3PluginConfig( - bucket: 'bucket.name.has.dots.com', - region: 'us-west-2', + storageOutputs: const StorageOutputs( + bucketName: 'bucket.name.has.dots.com', + awsRegion: 'us-west-2', ), pathResolver: pathResolver, credentialsProvider: TestIamAuthProvider(), @@ -770,8 +771,10 @@ void main() { late StorageS3Service pathStyleStorageS3Service; const pathStyleBucket = 'bucket.name.has.dots.com'; const pathStyleRegion = 'west-2'; - const pathStyleS3PluginConfig = - S3PluginConfig(bucket: pathStyleBucket, region: pathStyleRegion); + const pathStyleStorageOutputs = StorageOutputs( + bucketName: pathStyleBucket, + awsRegion: pathStyleRegion, + ); final pathStyleURL = Uri( host: 's3.amazonaws.com', path: '/bucket.name.has.dots.com/album/1.jpg', @@ -784,7 +787,7 @@ void main() { ..addInstance(MockS3Client()) ..addInstance(pathStyleAwsSigV4Signer); pathStyleStorageS3Service = StorageS3Service( - s3PluginConfig: pathStyleS3PluginConfig, + storageOutputs: pathStyleStorageOutputs, pathResolver: pathResolver, credentialsProvider: TestIamAuthProvider(), logger: MockAWSLogger(), @@ -828,7 +831,7 @@ void main() { .having( (o) => o.host, 'host', - 's3.${pathStyleS3PluginConfig.region}.amazonaws.com', + 's3.${pathStyleStorageOutputs.awsRegion}.amazonaws.com', ) .having( (o) => o.path, diff --git a/packages/test/amplify_integration_test/lib/src/stubs/amplify_stub.dart b/packages/test/amplify_integration_test/lib/src/stubs/amplify_stub.dart index cfbfde6e58..55f880ee25 100644 --- a/packages/test/amplify_integration_test/lib/src/stubs/amplify_stub.dart +++ b/packages/test/amplify_integration_test/lib/src/stubs/amplify_stub.dart @@ -80,9 +80,8 @@ class AmplifyStub extends AmplifyClass { jsonDecode(configuration) as Map, ); } on Exception { - return const AmplifyOutputs( - version: '1', - ); + // ignore: invalid_use_of_internal_member + return const AmplifyOutputs(version: '1'); } } } From 9dc9c24c15d40099af28ba80db54a52d50da58fb Mon Sep 17 00:00:00 2001 From: Nika Hassani Date: Thu, 20 Jun 2024 15:12:34 -0700 Subject: [PATCH 2/6] fix the AmplifyOutputs.toJson for data and rest_api --- .../lib/src/config/amplify_outputs/amplify_outputs.dart | 3 ++- .../lib/src/config/amplify_outputs/amplify_outputs.g.dart | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/amplify_core/lib/src/config/amplify_outputs/amplify_outputs.dart b/packages/amplify_core/lib/src/config/amplify_outputs/amplify_outputs.dart index 72da987de2..28105b039b 100644 --- a/packages/amplify_core/lib/src/config/amplify_outputs/amplify_outputs.dart +++ b/packages/amplify_core/lib/src/config/amplify_outputs/amplify_outputs.dart @@ -55,6 +55,7 @@ class AmplifyOutputs /// {@macro amplify_core.amplify_outputs.rest_api_outputs} @internal + @JsonKey(includeToJson: false) final Map? restApi; /// {@macro amplify_core.amplify_outputs.notifications_outputs} @@ -119,6 +120,6 @@ Object? _dataToJson(Map? outputs) { ' Amplify Outputs does not support multiple GraphQL endpoints.', ); } - final data = outputs[_dataPluginName]; + final data = outputs.values.firstOrNull; return data?.toJson(); } diff --git a/packages/amplify_core/lib/src/config/amplify_outputs/amplify_outputs.g.dart b/packages/amplify_core/lib/src/config/amplify_outputs/amplify_outputs.g.dart index 2688583d6d..6158588c2b 100644 --- a/packages/amplify_core/lib/src/config/amplify_outputs/amplify_outputs.g.dart +++ b/packages/amplify_core/lib/src/config/amplify_outputs/amplify_outputs.g.dart @@ -48,8 +48,6 @@ Map _$AmplifyOutputsToJson(AmplifyOutputs instance) { writeNotNull('analytics', instance.analytics?.toJson()); writeNotNull('auth', instance.auth?.toJson()); writeNotNull('data', _dataToJson(instance.data)); - writeNotNull( - 'rest_api', instance.restApi?.map((k, e) => MapEntry(k, e.toJson()))); writeNotNull('notifications', instance.notifications?.toJson()); writeNotNull('storage', instance.storage?.toJson()); writeNotNull('custom', instance.custom); From a9cb8f8587de988504e5ac26ea313127479d4aa6 Mon Sep 17 00:00:00 2001 From: Nika Hassani Date: Fri, 21 Jun 2024 11:33:34 -0700 Subject: [PATCH 3/6] update native plugins to pass Gen 2 config to Amplify.configure() --- packages/amplify_datastore/android/build.gradle | 8 ++++---- .../amplify_datastore/AmplifyDataStorePlugin.kt | 10 +++++----- .../ios/Classes/SwiftAmplifyDataStorePlugin.swift | 4 +--- .../amplify_push_notifications/android/build.gradle | 2 +- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/packages/amplify_datastore/android/build.gradle b/packages/amplify_datastore/android/build.gradle index fe75374265..e52ed5e0ef 100644 --- a/packages/amplify_datastore/android/build.gradle +++ b/packages/amplify_datastore/android/build.gradle @@ -73,10 +73,10 @@ android { } dependencies { - implementation 'com.amplifyframework:aws-auth-cognito:2.19.0' - implementation "com.amplifyframework:aws-api:2.19.0" - implementation "com.amplifyframework:aws-datastore:2.19.0" - implementation "com.amplifyframework:aws-api-appsync:2.19.0" + implementation 'com.amplifyframework:aws-auth-cognito:2.19.1' + implementation "com.amplifyframework:aws-api:2.19.1" + implementation "com.amplifyframework:aws-datastore:2.19.1" + implementation "com.amplifyframework:aws-api-appsync:2.19.1" implementation 'com.google.code.gson:gson:2.10.1' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.1' diff --git a/packages/amplify_datastore/android/src/main/kotlin/com/amazonaws/amplify/amplify_datastore/AmplifyDataStorePlugin.kt b/packages/amplify_datastore/android/src/main/kotlin/com/amazonaws/amplify/amplify_datastore/AmplifyDataStorePlugin.kt index c1c7ece49e..803a4f764c 100644 --- a/packages/amplify_datastore/android/src/main/kotlin/com/amazonaws/amplify/amplify_datastore/AmplifyDataStorePlugin.kt +++ b/packages/amplify_datastore/android/src/main/kotlin/com/amazonaws/amplify/amplify_datastore/AmplifyDataStorePlugin.kt @@ -31,6 +31,7 @@ import com.amazonaws.amplify.amplify_datastore.util.cast import com.amazonaws.amplify.amplify_datastore.util.safeCastToList import com.amazonaws.amplify.amplify_datastore.util.safeCastToMap import com.amplifyframework.AmplifyException +import com.amplifyframework.annotations.AmplifyFlutterApi import com.amplifyframework.api.aws.AWSApiPlugin import com.amplifyframework.api.aws.AuthModeStrategyType import com.amplifyframework.api.aws.AuthorizationType @@ -38,6 +39,7 @@ import com.amplifyframework.auth.AuthUser import com.amplifyframework.core.Amplify import com.amplifyframework.core.AmplifyConfiguration import com.amplifyframework.core.async.Cancelable +import com.amplifyframework.core.configuration.AmplifyOutputs import com.amplifyframework.core.model.CustomTypeSchema import com.amplifyframework.core.model.Model import com.amplifyframework.core.model.ModelSchema @@ -937,11 +939,9 @@ class AmplifyDataStorePlugin : ) { coroutineScope.launch(dispatcher) { try { - val configuration = AmplifyConfiguration.builder(JSONObject(config)) - .addPlatform(UserAgent.Platform.FLUTTER, "$version /datastore") - .devMenuEnabled(false) - .build() - Amplify.configure(configuration, context) + @OptIn(AmplifyFlutterApi::class) + Amplify.addUserAgentPlatform(UserAgent.Platform.FLUTTER, "$version /datastore") + Amplify.configure(AmplifyOutputs(config), context) withContext(Dispatchers.Main) { callback(kotlin.Result.success(Unit)) } diff --git a/packages/amplify_datastore/ios/Classes/SwiftAmplifyDataStorePlugin.swift b/packages/amplify_datastore/ios/Classes/SwiftAmplifyDataStorePlugin.swift index 681c679068..7e780985df 100644 --- a/packages/amplify_datastore/ios/Classes/SwiftAmplifyDataStorePlugin.swift +++ b/packages/amplify_datastore/ios/Classes/SwiftAmplifyDataStorePlugin.swift @@ -145,11 +145,9 @@ public class SwiftAmplifyDataStorePlugin: NSObject, FlutterPlugin, NativeAmplify nil ) } - let amplifyConfiguration = try JSONDecoder().decode(AmplifyConfiguration.self, - from: data) // TODO: Migrate to Async Swift v2 // AmplifyAWSServiceConfiguration.addUserAgentPlatform(.flutter, version: "\(version) /datastore") - try Amplify.configure(amplifyConfiguration) + try Amplify.configure(with : .data(data)) return completion(.success(())) } catch let error as ConfigurationError { switch error { diff --git a/packages/notifications/push/amplify_push_notifications/android/build.gradle b/packages/notifications/push/amplify_push_notifications/android/build.gradle index 8b583ff9d3..5ddf57a8e6 100644 --- a/packages/notifications/push/amplify_push_notifications/android/build.gradle +++ b/packages/notifications/push/amplify_push_notifications/android/build.gradle @@ -65,7 +65,7 @@ android { dependencies { api "com.google.firebase:firebase-messaging:23.2.0" // Import support library for Amplify push utils - implementation 'com.amplifyframework:aws-push-notifications-pinpoint-common:2.19.0' + implementation 'com.amplifyframework:aws-push-notifications-pinpoint-common:2.19.1' implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1" implementation project(path: ':flutter_plugin_android_lifecycle') implementation 'androidx.test:core-ktx:1.5.0' From 835ebfd36b89a51daa5ec1742528141619f160a7 Mon Sep 17 00:00:00 2001 From: Nika Hassani Date: Mon, 24 Jun 2024 14:34:46 -0700 Subject: [PATCH 4/6] address comments --- .../amplify_core/lib/src/amplify_class.dart | 74 ++++++++++--------- .../lib/src/util/amplify_api_config.dart | 31 -------- .../machines/configuration_state_machine.dart | 5 +- .../configuration_state_machine_test.dart | 4 +- .../service/storage_s3_service_impl.dart | 38 +++++----- 5 files changed, 64 insertions(+), 88 deletions(-) diff --git a/packages/amplify_core/lib/src/amplify_class.dart b/packages/amplify_core/lib/src/amplify_class.dart index ca8243fbb0..83b5d30c93 100644 --- a/packages/amplify_core/lib/src/amplify_class.dart +++ b/packages/amplify_core/lib/src/amplify_class.dart @@ -113,40 +113,8 @@ abstract class AmplifyClass { } late final AmplifyOutputs amplifyOutputs; try { - final Map json; - late final AmplifyConfig amplifyConfig; - try { - json = jsonDecode(configuration) as Map; - } on Object catch (e) { - throw ConfigurationError( - 'The provided configuration is not a valid json. ' - 'Check underlyingException.', - recoverySuggestion: - 'Inspect your amplify_output.dart or amplifyconfiguration.dart ' - 'and ensure that the string is proper json', - underlyingException: e, - ); - } - try { - amplifyOutputs = AmplifyOutputs.fromJson(json); - } on Object { - try { - amplifyConfig = AmplifyConfig.fromJson(json); - amplifyOutputs = amplifyConfig.toAmplifyOutputs(); - } on Object catch (e) { - throw ConfigurationError( - 'The provided configuration can not be decoded to AmplifyOutputs ' - 'or AmplifyConfig. ' - 'Check underlyingException.', - recoverySuggestion: - 'If using Amplify Gen 2 ensure that the json string ' - 'can be decoded to AmplifyOutputs type. ' - 'If using Amplify Gen 1 ensure that the json ' - 'string can be decoded to AmplifyConfig type.', - underlyingException: e, - ); - } - } + final json = _decodeJson(configuration); + amplifyOutputs = _parseJsonConfig(json); await _configurePlugins(amplifyOutputs); _configCompleter.complete(amplifyOutputs); } on ConfigurationError catch (e, st) { @@ -172,6 +140,44 @@ abstract class AmplifyClass { } } + AmplifyOutputs _parseJsonConfig(Map json) { + try { + return AmplifyOutputs.fromJson(json); + } on Object { + try { + final amplifyConfig = AmplifyConfig.fromJson(json); + return amplifyConfig.toAmplifyOutputs(); + } on Object catch (e) { + throw ConfigurationError( + 'The provided configuration can not be decoded to AmplifyOutputs ' + 'or AmplifyConfig. ' + 'Check underlyingException.', + recoverySuggestion: + 'If using Amplify Gen 2 ensure that the json string ' + 'can be decoded to AmplifyOutputs type. ' + 'If using Amplify Gen 1 ensure that the json ' + 'string can be decoded to AmplifyConfig type.', + underlyingException: e, + ); + } + } + } + + Map _decodeJson(String configuration) { + try { + return jsonDecode(configuration) as Map; + } on Object catch (e) { + throw ConfigurationError( + 'The provided configuration is not a valid json. ' + 'Check underlyingException.', + recoverySuggestion: + 'Inspect your amplify_outputs.dart or amplifyconfiguration.dart ' + 'and ensure that the string is proper json', + underlyingException: e, + ); + } + } + /// Configures all plugins in topologically-sorted order. Future _configurePlugins(AmplifyOutputs config) async { await Future.wait(_addPluginFutures); diff --git a/packages/api/amplify_api_dart/lib/src/util/amplify_api_config.dart b/packages/api/amplify_api_dart/lib/src/util/amplify_api_config.dart index d36119064e..917cfcd695 100644 --- a/packages/api/amplify_api_dart/lib/src/util/amplify_api_config.dart +++ b/packages/api/amplify_api_dart/lib/src/util/amplify_api_config.dart @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 import 'package:amplify_core/amplify_core.dart'; -import 'package:collection/collection.dart'; import 'package:meta/meta.dart'; const _slash = '/'; @@ -46,33 +45,3 @@ class EndpointConfig with AWSEquatable { return path.split(_slash); } } - -/// Allows getting desired endpoint more easily. -@internal -extension AWSApiPluginConfigHelpers on AWSApiPluginConfig { - /// Finds the first endpoint matching the type and apiName. - EndpointConfig getEndpoint({ - required EndpointType type, - String? apiName, - }) { - final typeConfigs = - entries.where((config) => config.value.endpointType == type); - if (apiName != null) { - final config = typeConfigs.firstWhere( - (config) => config.key == apiName, - orElse: () => throw ConfigurationError( - 'No API endpoint found matching apiName $apiName.', - ), - ); - return EndpointConfig(config.key, config.value); - } - final onlyConfig = typeConfigs.singleOrNull; - if (onlyConfig == null) { - throw ConfigurationError( - 'Multiple API endpoints defined. Pass apiName parameter to specify ' - 'which one to use.', - ); - } - return EndpointConfig(onlyConfig.key, onlyConfig.value); - } -} diff --git a/packages/auth/amplify_auth_cognito_dart/lib/src/state/machines/configuration_state_machine.dart b/packages/auth/amplify_auth_cognito_dart/lib/src/state/machines/configuration_state_machine.dart index 1ae2e5e298..af8eaabb55 100644 --- a/packages/auth/amplify_auth_cognito_dart/lib/src/state/machines/configuration_state_machine.dart +++ b/packages/auth/amplify_auth_cognito_dart/lib/src/state/machines/configuration_state_machine.dart @@ -64,10 +64,11 @@ final class ConfigurationStateMachine /// State machine callback for the [Configure] event. Future onConfigure(Configure event) async { - if (event.config.auth == null) { + final authOutputs = event.config.auth; + if (authOutputs == null) { throw ConfigurationError('No Cognito plugin config available'); } - addInstance(event.config.auth!); + addInstance(authOutputs); final config = AuthConfiguration.fromAmplifyOutputs(event.config); addInstance(config); diff --git a/packages/auth/amplify_auth_cognito_test/test/state/configuration_state_machine_test.dart b/packages/auth/amplify_auth_cognito_test/test/state/configuration_state_machine_test.dart index b44f655525..83725d0003 100644 --- a/packages/auth/amplify_auth_cognito_test/test/state/configuration_state_machine_test.dart +++ b/packages/auth/amplify_auth_cognito_test/test/state/configuration_state_machine_test.dart @@ -13,7 +13,7 @@ import 'package:amplify_secure_storage_dart/amplify_secure_storage_dart.dart'; import 'package:stream_transform/stream_transform.dart'; import 'package:test/test.dart'; -final badConfig = const AmplifyConfig().toAmplifyOutputs(); +const badConfig = AmplifyOutputs(version: '1'); void main() { late CognitoAuthStateMachine stateMachine; @@ -50,7 +50,7 @@ void main() { expect( stateMachine - .dispatch(ConfigurationEvent.configure(badConfig)) + .dispatch(const ConfigurationEvent.configure(badConfig)) .completed, throwsA(isA()), ); diff --git a/packages/storage/amplify_storage_s3_dart/lib/src/storage_s3_service/service/storage_s3_service_impl.dart b/packages/storage/amplify_storage_s3_dart/lib/src/storage_s3_service/service/storage_s3_service_impl.dart index f8ed6eab3e..f749de67f3 100644 --- a/packages/storage/amplify_storage_s3_dart/lib/src/storage_s3_service/service/storage_s3_service_impl.dart +++ b/packages/storage/amplify_storage_s3_dart/lib/src/storage_s3_service/service/storage_s3_service_impl.dart @@ -72,7 +72,7 @@ class StorageS3Service { required AWSIamAmplifyAuthProvider credentialsProvider, required AWSLogger logger, required DependencyManager dependencyManager, - }) : _storageOutptus = storageOutputs, + }) : _storageOutputs = storageOutputs, _defaultS3ClientConfig = s3ClientConfig, // dependencyManager.get() => S3Client is used for unit tests _defaultS3Client = dependencyManager.get() ?? @@ -96,7 +96,7 @@ class StorageS3Service { static final _defaultS3SignerConfiguration = sigv4.S3ServiceConfiguration(signPayload: false); - final StorageOutputs _storageOutptus; + final StorageOutputs _storageOutputs; final smithy_aws.S3ClientConfig _defaultS3ClientConfig; final s3.S3Client _defaultS3Client; final S3PathResolver _pathResolver; @@ -106,7 +106,7 @@ class StorageS3Service { final DateTime _serviceStartingTime; sigv4.AWSCredentialScope get _signerScope => sigv4.AWSCredentialScope( - region: _storageOutptus.awsRegion, + region: _storageOutputs.awsRegion, service: AWSService.s3, ); @@ -134,7 +134,7 @@ class StorageS3Service { if (!s3PluginOptions.listAll) { final request = s3.ListObjectsV2Request.build((builder) { builder - ..bucket = _storageOutptus.bucketName + ..bucket = _storageOutputs.bucketName ..prefix = resolvedPath ..maxKeys = options.pageSize ..continuationToken = options.nextToken @@ -161,7 +161,7 @@ class StorageS3Service { try { final request = s3.ListObjectsV2Request.build((builder) { builder - ..bucket = _storageOutptus.bucketName + ..bucket = _storageOutputs.bucketName ..prefix = resolvedPath ..delimiter = s3PluginOptions.excludeSubPaths ? s3PluginOptions.delimiter @@ -207,7 +207,7 @@ class StorageS3Service { storageItem: S3Item.fromHeadObjectOutput( await headObject( s3client: _defaultS3Client, - bucket: _storageOutptus.bucketName, + bucket: _storageOutputs.bucketName, key: resolvedPath, ), path: resolvedPath, @@ -244,14 +244,14 @@ class StorageS3Service { var resolvedPath = await _pathResolver.resolvePath(path: path); var host = - '${_storageOutptus.bucketName}.${_getS3EndpointHost(region: _storageOutptus.awsRegion)}'; + '${_storageOutputs.bucketName}.${_getS3EndpointHost(region: _storageOutputs.awsRegion)}'; if (_defaultS3ClientConfig.usePathStyle) { - host = host.replaceFirst('${_storageOutptus.bucketName}.', ''); - resolvedPath = '${_storageOutptus.bucketName}/$resolvedPath'; + host = host.replaceFirst('${_storageOutputs.bucketName}.', ''); + resolvedPath = '${_storageOutputs.bucketName}/$resolvedPath'; } else if (s3PluginOptions.useAccelerateEndpoint) { // https: //docs.aws.amazon.com/AmazonS3/latest/userguide/transfer-acceleration-getting-started.html host = host - .replaceFirst(RegExp('${_storageOutptus.awsRegion}\\.'), '') + .replaceFirst(RegExp('${_storageOutputs.awsRegion}\\.'), '') .replaceFirst(RegExp(r'\.s3\.'), '.s3-accelerate.'); } @@ -297,7 +297,7 @@ class StorageS3Service { final downloadDataTask = S3DownloadTask( s3Client: _defaultS3Client, defaultS3ClientConfig: _defaultS3ClientConfig, - bucket: _storageOutptus.bucketName, + bucket: _storageOutputs.bucketName, path: path, options: options, pathResolver: _pathResolver, @@ -328,7 +328,7 @@ class StorageS3Service { dataPayload, s3Client: _defaultS3Client, defaultS3ClientConfig: _defaultS3ClientConfig, - bucket: _storageOutptus.bucketName, + bucket: _storageOutputs.bucketName, path: path, options: options, pathResolver: _pathResolver, @@ -367,7 +367,7 @@ class StorageS3Service { localFile, s3Client: _defaultS3Client, defaultS3ClientConfig: _defaultS3ClientConfig, - bucket: _storageOutptus.bucketName, + bucket: _storageOutputs.bucketName, path: path, options: uploadDataOptions, pathResolver: _pathResolver, @@ -407,8 +407,8 @@ class StorageS3Service { final copyRequest = s3.CopyObjectRequest.build((builder) { builder - ..bucket = _storageOutptus.bucketName - ..copySource = '${_storageOutptus.bucketName}/$sourcePath' + ..bucket = _storageOutputs.bucketName + ..copySource = '${_storageOutputs.bucketName}/$sourcePath' ..key = destinationPath ..metadataDirective = s3.MetadataDirective.copy; }); @@ -427,7 +427,7 @@ class StorageS3Service { ? S3Item.fromHeadObjectOutput( await headObject( s3client: _defaultS3Client, - bucket: _storageOutptus.bucketName, + bucket: _storageOutputs.bucketName, key: destinationPath, ), path: destinationPath, @@ -451,7 +451,7 @@ class StorageS3Service { await _deleteObject( s3client: _defaultS3Client, - bucket: _storageOutptus.bucketName, + bucket: _storageOutputs.bucketName, key: resolvedPath, ); @@ -491,7 +491,7 @@ class StorageS3Service { ); final request = s3.DeleteObjectsRequest.build((builder) { builder - ..bucket = _storageOutptus.bucketName + ..bucket = _storageOutputs.bucketName // force to use sha256 instead of md5 ..checksumAlgorithm = s3.ChecksumAlgorithm.sha256 ..delete = s3.Delete.build((builder) { @@ -598,7 +598,7 @@ class StorageS3Service { for (final record in records) { final request = s3.AbortMultipartUploadRequest.build((builder) { builder - ..bucket = _storageOutptus.bucketName + ..bucket = _storageOutputs.bucketName ..key = record.objectKey ..uploadId = record.uploadId; }); From fb3c59c3169e96050bd6fa42d09e9123e7ffdd78 Mon Sep 17 00:00:00 2001 From: Nika Hassani Date: Tue, 25 Jun 2024 11:34:52 -0700 Subject: [PATCH 5/6] add todo to use AmplifyOutputs config for the unit tests --- .../lib/src/api_plugin_impl.dart | 3 +-- .../test/plugin_configuration_test.dart | 1 + .../test/rest_methods_test.dart | 1 + .../lib/common/mock_config.dart | 2 +- .../amplify_push_notifications_impl_test.dart | 2 ++ .../test/amplify_storage_s3_impl_test.dart | 18 +++++++----------- 6 files changed, 13 insertions(+), 14 deletions(-) diff --git a/packages/api/amplify_api_dart/lib/src/api_plugin_impl.dart b/packages/api/amplify_api_dart/lib/src/api_plugin_impl.dart index 8cf128dede..36f83e993f 100644 --- a/packages/api/amplify_api_dart/lib/src/api_plugin_impl.dart +++ b/packages/api/amplify_api_dart/lib/src/api_plugin_impl.dart @@ -123,8 +123,7 @@ class AmplifyAPIDart extends APIPluginInterface with AWSDebuggable { _dataConfig?.forEach((key, value) { // Check the presence of apiKey (not auth type) because other modes might // have a key if not the primary auth mode. - if (value.apiKey != null || - value.defaultAuthorizationType == APIAuthorizationType.apiKey || + if (value.defaultAuthorizationType == APIAuthorizationType.apiKey || value.authorizationTypes .any((element) => element == APIAuthorizationType.apiKey)) { _authProviderRepo.registerAuthProvider( diff --git a/packages/api/amplify_api_dart/test/plugin_configuration_test.dart b/packages/api/amplify_api_dart/test/plugin_configuration_test.dart index 97c623eec0..dae096aabe 100644 --- a/packages/api/amplify_api_dart/test/plugin_configuration_test.dart +++ b/packages/api/amplify_api_dart/test/plugin_configuration_test.dart @@ -61,6 +61,7 @@ void main() { APIAuthorizationType.iam.authProviderToken, TestIamAuthProvider(), ); + // TODO(nikahsn): update to use AmplifyOutputs config final config = AmplifyConfig.fromJson( jsonDecode(amplifyconfig) as Map, ); diff --git a/packages/api/amplify_api_dart/test/rest_methods_test.dart b/packages/api/amplify_api_dart/test/rest_methods_test.dart index 44195ce6d1..3d3bad58fd 100644 --- a/packages/api/amplify_api_dart/test/rest_methods_test.dart +++ b/packages/api/amplify_api_dart/test/rest_methods_test.dart @@ -40,6 +40,7 @@ void main() { APIAuthorizationType.iam.authProviderToken, TestIamAuthProvider(), ); + // TODO(nikahsn): update to use AmplifyOutputs config final config = AmplifyConfig.fromJson( jsonDecode(amplifyconfig) as Map, ); diff --git a/packages/auth/amplify_auth_cognito_test/lib/common/mock_config.dart b/packages/auth/amplify_auth_cognito_test/lib/common/mock_config.dart index 249c56efb5..e0ebba2771 100644 --- a/packages/auth/amplify_auth_cognito_test/lib/common/mock_config.dart +++ b/packages/auth/amplify_auth_cognito_test/lib/common/mock_config.dart @@ -25,7 +25,7 @@ const hostedUiConfig = CognitoOAuthConfig( signOutRedirectUri: redirectUri, webDomain: webDomain, ); - +// TODO(nikahsn): update to use AmplifyOutputs config final userPoolOnlyConfig = AmplifyConfig( auth: AuthConfig.cognito( userPoolConfig: const CognitoUserPoolConfig( diff --git a/packages/notifications/push/amplify_push_notifications/test/amplify_push_notifications_impl_test.dart b/packages/notifications/push/amplify_push_notifications/test/amplify_push_notifications_impl_test.dart index 49323b92fc..a170e8e03f 100644 --- a/packages/notifications/push/amplify_push_notifications/test/amplify_push_notifications_impl_test.dart +++ b/packages/notifications/push/amplify_push_notifications/test/amplify_push_notifications_impl_test.dart @@ -54,6 +54,7 @@ void main() { ..addInstance(mockPushNotificationsHostApi) ..addInstance(mockAmplifySecureStorage); + // TODO(nikahsn): update to use AmplifyOutputs config final config = AmplifyConfig.fromJson( jsonDecode(amplifyconfig) as Map, // ignore: invalid_use_of_internal_member @@ -203,6 +204,7 @@ void main() { group('Config failure cases', () { test('should throw exception when configuring if there is no appId present', () async { + // TODO(nikahsn): update to use AmplifyOutputs config final config = AmplifyConfig.fromJson( jsonDecode(noPushAppIdAmplifyConfig) as Map, // ignore: invalid_use_of_internal_member diff --git a/packages/storage/amplify_storage_s3/test/amplify_storage_s3_impl_test.dart b/packages/storage/amplify_storage_s3/test/amplify_storage_s3_impl_test.dart index 418bd4dbdb..8eb798aa9a 100644 --- a/packages/storage/amplify_storage_s3/test/amplify_storage_s3_impl_test.dart +++ b/packages/storage/amplify_storage_s3/test/amplify_storage_s3_impl_test.dart @@ -4,6 +4,7 @@ import 'dart:async'; import 'package:amplify_core/amplify_core.dart'; +import 'package:amplify_core/src/config/amplify_outputs/storage/storage_outputs.dart'; import 'package:amplify_storage_s3/amplify_storage_s3.dart'; import 'package:amplify_storage_s3/src/utils/app_path_provider/app_path_provider.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -12,17 +13,12 @@ import 'test_utils/test_token_provider.dart'; void main() { group('AmplifyStorageS3', () { - final testConfig = const AmplifyConfig( - storage: StorageConfig( - plugins: { - S3PluginConfig.pluginKey: S3PluginConfig( - bucket: '123', - region: 'west-2', - ), - }, - ), - // ignore: invalid_use_of_internal_member - ).toAmplifyOutputs(); + // ignore: invalid_use_of_internal_member + const testConfig = AmplifyOutputs( + version: '1', + storage: StorageOutputs(bucketName: '123', awsRegion: 'west-2'), + ); + // ignore: invalid_use_of_internal_member final testAuthProviderRepo = AmplifyAuthProviderRepository() ..registerAuthProvider( APIAuthorizationType.userPools.authProviderToken, From 7f458e701f218edec72ca40c904f3f27e2a9441a Mon Sep 17 00:00:00 2001 From: Nika Hassani Date: Tue, 25 Jun 2024 12:41:00 -0700 Subject: [PATCH 6/6] add todo for AuthConfiguration and EndpointConfig to not use types shared with AmplifyConfig --- .../api/amplify_api_dart/lib/src/util/amplify_api_config.dart | 2 ++ .../lib/src/model/auth_configuration.dart | 2 ++ 2 files changed, 4 insertions(+) diff --git a/packages/api/amplify_api_dart/lib/src/util/amplify_api_config.dart b/packages/api/amplify_api_dart/lib/src/util/amplify_api_config.dart index 917cfcd695..0ad17e1473 100644 --- a/packages/api/amplify_api_dart/lib/src/util/amplify_api_config.dart +++ b/packages/api/amplify_api_dart/lib/src/util/amplify_api_config.dart @@ -8,6 +8,8 @@ const _slash = '/'; /// Allows formatting the URL from the config with new paths/query params. @internal + +// TODO(nikahsn): refactor EndpointConfig to not use AWSApiConfig type class EndpointConfig with AWSEquatable { // ignore: public_member_api_docs const EndpointConfig(this.name, this.config); diff --git a/packages/auth/amplify_auth_cognito_dart/lib/src/model/auth_configuration.dart b/packages/auth/amplify_auth_cognito_dart/lib/src/model/auth_configuration.dart index 1b0b14e291..ca3d3f52bb 100644 --- a/packages/auth/amplify_auth_cognito_dart/lib/src/model/auth_configuration.dart +++ b/packages/auth/amplify_auth_cognito_dart/lib/src/model/auth_configuration.dart @@ -10,6 +10,8 @@ import 'package:meta/meta.dart'; /// {@template amplify_auth_cognito.auth_configuration} /// Union class for auth configurations of the different types. /// {@endtemplate} + +// TODO(nikahsn): refactor AuthConfiguration to not use AmplifyConfig types class AuthConfiguration with AWSEquatable { const AuthConfiguration._({ this.userPoolConfig,