@aws-amplify/core
Version:
Core category of aws-amplify
330 lines (306 loc) • 9.19 kB
text/typescript
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import { ConsoleLogger } from './Logger';
import { AmplifyError } from './errors';
import {
AuthConfigUserAttributes,
LegacyUserAttributeKey,
OAuthConfig,
OAuthProvider,
} from './singleton/Auth/types';
import { ResourcesConfig } from './singleton/types';
const logger = new ConsoleLogger('parseAWSExports');
const authTypeMapping: Record<any, any> = {
API_KEY: 'apiKey',
AWS_IAM: 'iam',
AMAZON_COGNITO_USER_POOLS: 'userPool',
OPENID_CONNECT: 'oidc',
NONE: 'none',
AWS_LAMBDA: 'lambda',
// `LAMBDA` is an incorrect value that was added during the v6 rewrite.
// Keeping it as a valid value until v7 to prevent breaking customers who might
// be relying on it as a workaround.
// ref: https://github.com/aws-amplify/amplify-js/pull/12922
// TODO: @v7 remove next line
LAMBDA: 'lambda',
};
/**
* Converts the object imported from `aws-exports.js` or `amplifyconfiguration.json` files generated by
* the Amplify CLI into an object that conforms to the {@link ResourcesConfig}.
*
* @param config A configuration object imported from `aws-exports.js` or `amplifyconfiguration.json`.
*
* @returns An object that conforms to the {@link ResourcesConfig} .
*/
export const parseAWSExports = (
config: Record<string, any> = {},
): ResourcesConfig => {
if (!Object.prototype.hasOwnProperty.call(config, 'aws_project_region')) {
throw new AmplifyError({
name: 'InvalidParameterException',
message: 'Invalid config parameter.',
recoverySuggestion:
'Ensure passing the config object imported from `amplifyconfiguration.json`.',
});
}
const {
aws_appsync_apiKey,
aws_appsync_authenticationType,
aws_appsync_graphqlEndpoint,
aws_appsync_region,
aws_bots_config,
aws_cognito_identity_pool_id,
aws_cognito_sign_up_verification_method,
aws_cognito_mfa_configuration,
aws_cognito_mfa_types,
aws_cognito_password_protection_settings,
aws_cognito_verification_mechanisms,
aws_cognito_signup_attributes,
aws_cognito_social_providers,
aws_cognito_username_attributes,
aws_mandatory_sign_in,
aws_mobile_analytics_app_id,
aws_mobile_analytics_app_region,
aws_user_files_s3_bucket,
aws_user_files_s3_bucket_region,
aws_user_files_s3_dangerously_connect_to_http_endpoint_for_testing,
aws_user_pools_id,
aws_user_pools_web_client_id,
geo,
oauth,
predictions,
aws_cloud_logic_custom,
Notifications,
modelIntrospection,
} = config;
const amplifyConfig: ResourcesConfig = {};
// Analytics
if (aws_mobile_analytics_app_id) {
amplifyConfig.Analytics = {
Pinpoint: {
appId: aws_mobile_analytics_app_id,
region: aws_mobile_analytics_app_region,
},
};
}
// Notifications
const { InAppMessaging, Push } = Notifications ?? {};
if (InAppMessaging?.AWSPinpoint || Push?.AWSPinpoint) {
if (InAppMessaging?.AWSPinpoint) {
const { appId, region } = InAppMessaging.AWSPinpoint;
amplifyConfig.Notifications = {
InAppMessaging: {
Pinpoint: {
appId,
region,
},
},
};
}
if (Push?.AWSPinpoint) {
const { appId, region } = Push.AWSPinpoint;
amplifyConfig.Notifications = {
...amplifyConfig.Notifications,
PushNotification: {
Pinpoint: {
appId,
region,
},
},
};
}
}
// Interactions
if (Array.isArray(aws_bots_config)) {
amplifyConfig.Interactions = {
LexV1: Object.fromEntries(aws_bots_config.map(bot => [bot.name, bot])),
};
}
// API
if (aws_appsync_graphqlEndpoint) {
const defaultAuthMode = authTypeMapping[aws_appsync_authenticationType];
if (!defaultAuthMode) {
logger.debug(
`Invalid authentication type ${aws_appsync_authenticationType}. Falling back to IAM.`,
);
}
amplifyConfig.API = {
GraphQL: {
endpoint: aws_appsync_graphqlEndpoint,
apiKey: aws_appsync_apiKey,
region: aws_appsync_region,
defaultAuthMode: defaultAuthMode ?? 'iam',
},
};
if (modelIntrospection) {
amplifyConfig.API.GraphQL!.modelIntrospection = modelIntrospection;
}
}
// Auth
const mfaConfig = aws_cognito_mfa_configuration
? {
status:
aws_cognito_mfa_configuration &&
aws_cognito_mfa_configuration.toLowerCase(),
totpEnabled: aws_cognito_mfa_types?.includes('TOTP') ?? false,
smsEnabled: aws_cognito_mfa_types?.includes('SMS') ?? false,
}
: undefined;
const passwordFormatConfig = aws_cognito_password_protection_settings
? {
minLength:
aws_cognito_password_protection_settings.passwordPolicyMinLength,
requireLowercase:
aws_cognito_password_protection_settings.passwordPolicyCharacters?.includes(
'REQUIRES_LOWERCASE',
) ?? false,
requireUppercase:
aws_cognito_password_protection_settings.passwordPolicyCharacters?.includes(
'REQUIRES_UPPERCASE',
) ?? false,
requireNumbers:
aws_cognito_password_protection_settings.passwordPolicyCharacters?.includes(
'REQUIRES_NUMBERS',
) ?? false,
requireSpecialCharacters:
aws_cognito_password_protection_settings.passwordPolicyCharacters?.includes(
'REQUIRES_SYMBOLS',
) ?? false,
}
: undefined;
const mergedUserAttributes: LegacyUserAttributeKey[] = Array.from(
new Set([
...(aws_cognito_verification_mechanisms ?? []),
...(aws_cognito_signup_attributes ?? []),
]),
);
const userAttributes: AuthConfigUserAttributes = mergedUserAttributes.reduce(
(attributes: AuthConfigUserAttributes, key: LegacyUserAttributeKey) => ({
...attributes,
// All user attributes generated by the CLI are required
[key.toLowerCase()]: { required: true },
}),
{},
);
const loginWithEmailEnabled =
aws_cognito_username_attributes?.includes('EMAIL') ?? false;
const loginWithPhoneEnabled =
aws_cognito_username_attributes?.includes('PHONE_NUMBER') ?? false;
if (aws_cognito_identity_pool_id || aws_user_pools_id) {
amplifyConfig.Auth = {
Cognito: {
identityPoolId: aws_cognito_identity_pool_id,
allowGuestAccess: aws_mandatory_sign_in !== 'enable',
signUpVerificationMethod: aws_cognito_sign_up_verification_method,
userAttributes,
userPoolClientId: aws_user_pools_web_client_id,
userPoolId: aws_user_pools_id,
mfa: mfaConfig,
passwordFormat: passwordFormatConfig,
loginWith: {
username: !(loginWithEmailEnabled || loginWithPhoneEnabled),
email: loginWithEmailEnabled,
phone: loginWithPhoneEnabled,
},
},
};
}
const hasOAuthConfig = oauth ? Object.keys(oauth).length > 0 : false;
const hasSocialProviderConfig = aws_cognito_social_providers
? aws_cognito_social_providers.length > 0
: false;
if (amplifyConfig.Auth && hasOAuthConfig) {
amplifyConfig.Auth.Cognito.loginWith = {
...amplifyConfig.Auth.Cognito.loginWith,
oauth: {
...getOAuthConfig(oauth),
...(hasSocialProviderConfig && {
providers: parseSocialProviders(aws_cognito_social_providers),
}),
},
};
}
// Storage
if (aws_user_files_s3_bucket) {
amplifyConfig.Storage = {
S3: {
bucket: aws_user_files_s3_bucket,
region: aws_user_files_s3_bucket_region,
dangerouslyConnectToHttpEndpointForTesting:
aws_user_files_s3_dangerously_connect_to_http_endpoint_for_testing,
},
};
}
// Geo
if (geo) {
const { amazon_location_service } = geo;
amplifyConfig.Geo = {
LocationService: {
maps: amazon_location_service.maps,
geofenceCollections: amazon_location_service.geofenceCollections,
searchIndices: amazon_location_service.search_indices,
region: amazon_location_service.region,
},
};
}
// REST API
if (aws_cloud_logic_custom) {
amplifyConfig.API = {
...amplifyConfig.API,
REST: (aws_cloud_logic_custom as any[]).reduce(
(acc, api: Record<string, any>) => {
const { name, endpoint, region, service } = api;
return {
...acc,
[name]: {
endpoint,
...(service ? { service } : undefined),
...(region ? { region } : undefined),
},
};
},
{},
),
};
}
// Predictions
if (predictions) {
// map VoiceId from speechGenerator defaults to voiceId
const { VoiceId: voiceId } =
predictions?.convert?.speechGenerator?.defaults ?? {};
amplifyConfig.Predictions = voiceId
? {
...predictions,
convert: {
...predictions.convert,
speechGenerator: {
...predictions.convert.speechGenerator,
defaults: { voiceId },
},
},
}
: predictions;
}
return amplifyConfig;
};
const getRedirectUrl = (redirectStr: string): string[] =>
redirectStr?.split(',') ?? [];
const getOAuthConfig = ({
domain,
scope,
redirectSignIn,
redirectSignOut,
responseType,
}: Record<string, any>): OAuthConfig => ({
domain,
scopes: scope,
redirectSignIn: getRedirectUrl(redirectSignIn),
redirectSignOut: getRedirectUrl(redirectSignOut),
responseType,
});
const parseSocialProviders = (aws_cognito_social_providers: string[]) => {
return aws_cognito_social_providers.map((provider: string) => {
const updatedProvider = provider.toLowerCase();
return updatedProvider.charAt(0).toUpperCase() + updatedProvider.slice(1);
}) as OAuthProvider[];
};