Skip to content
This repository was archived by the owner on Mar 24, 2020. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,17 @@ Each entry in the `amplify` section must consist of two parts, with two optional
* `schema.json` (the AWS AppSync schema in JSON format),
* `graphql` (a sample GraphQL operations file for codegen),
* `appsync` (generated code for AppSync - the format is based on the extension)
* `appClient` is the name of the Amazon Cognito user pool app client configured within the `resources` section of the `serverless.yml` file. It is optional.
* `appClient` is the name of the Amazon Cognito user pool app client configured within the `resources` section of the `serverless.yml` file. Define the individual properties for resources on a different stack. It is optional.
* `UserPoolId` (reference to a UserPool in another stack)
* `ClientId` (the ClientId of a UserPoolClient in another stack)
* `ClientSecret` (optional ClientSecret. **Must be entered manually.** CF doesn't support the export of this value.)
* `identityPool` (optional reference to an IdentityPool in another stack)
* `s3bucket` is the name of the S3 Bucket used for the S3 transfer utility. It is optional. If `disabled`, no S3 bucket information is written to the configuration file. If not included, the first non-deployed S3 bucket will be used.

For the `appsync` type, the extension of the file is checked. Supported formats include `flow`, `ts` (for TypeScript), `scala`, and `swift`.

Cross stack `appClient` / `identityPool` configuration only supports `Amazon Cognito User Pools`. Other providers like Google are not tested or implemented yet.

See the `example` directory for a complete sample of an AWS AppSync client deployment with Amazon Cognito user pools.

### Another Example
Expand Down
91 changes: 85 additions & 6 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,14 @@ class ServerlessAmplifyPlugin {
};

if (fileDetails.hasOwnProperty('appClient')) {
const appClient = resources.find(r => r.ResourceType === 'AWS::Cognito::UserPoolClient' && r.LogicalResourceId === fileDetails.appClient);
// Look for manually defined appClient configuration
// when none is available in the resources because
// it is defined in a different stack.
let appClient = resources.find(
r => r.ResourceType === 'AWS::Cognito::UserPoolClient'
&& r.LogicalResourceId === fileDetails.appClient
) || this.getManuallyDefinedAppClientConfiguration(fileDetails);

if (typeof appClient !== 'undefined') {
config.CognitoUserPool = {
Default: {
Expand All @@ -271,7 +278,9 @@ class ServerlessAmplifyPlugin {
r.metadata.CognitoIdentityProviders.some(({ClientId}) => ClientId === config.CognitoUserPool.Default.AppClientId)
)
: undefined;
const identityPool = identityPoolForUserPool || identityPools[0];

const identityPool = identityPoolForUserPool || identityPools[0] || this.getManuallyDefinedIdentityPoolConfiguration(fileDetails);

if (typeof identityPool !== 'undefined') {
config.CredentialsProvider = {
CognitoIdentity: {
Expand All @@ -282,7 +291,7 @@ class ServerlessAmplifyPlugin {
}
};

if (typeof identityPool.metadata.SupportedLoginProviders == 'object') {
if (identityPool.metadata.SupportedLoginProviders !== null && typeof identityPool.metadata.SupportedLoginProviders == 'object') {
const providers = identityPool.metadata.SupportedLoginProviders;

// Each authentication provider that is supported for federation has an entry in
Expand Down Expand Up @@ -362,7 +371,14 @@ class ServerlessAmplifyPlugin {
config.aws_project_region = this.provider.getRegion();

if (fileDetails.hasOwnProperty('appClient')) {
const appClient = resources.find(r => r.ResourceType === 'AWS::Cognito::UserPoolClient' && r.LogicalResourceId === fileDetails.appClient);
// Look for manually defined appClient configuration
// when none is available in the resources because
// it is defined in a different stack.
let appClient = resources.find(
r => r.ResourceType === 'AWS::Cognito::UserPoolClient'
&& r.LogicalResourceId === fileDetails.appClient
) || this.getManuallyDefinedAppClientConfiguration(fileDetails);

if (typeof appClient !== 'undefined') {
config.aws_cognito_region = appClient.metadata.UserPoolClient.UserPoolId.split('_')[0];
config.aws_user_pools_id = appClient.metadata.UserPoolClient.UserPoolId;
Expand All @@ -382,14 +398,16 @@ class ServerlessAmplifyPlugin {
r.metadata.CognitoIdentityProviders.some(({ClientId}) => ClientId === config.aws_user_pools_web_client_id)
)
: undefined;
const identityPool = identityPoolForUserPool || identityPools[0];

const identityPool = identityPoolForUserPool || identityPools[0] || this.getManuallyDefinedIdentityPoolConfiguration(fileDetails);

if (typeof identityPool !== 'undefined') {
if (!config.hasOwnProperty("aws_cognito_region")) {
config.aws_cognito_region = identityPool.PhysicalResourceId.split(':')[0];
}
config.aws_cognito_identity_pool_id = identityPool.PhysicalResourceId;

if (typeof identityPool.metadata.SupportedLoginProviders == 'object') {
if (identityPool.metadata.SupportedLoginProviders !== null && typeof identityPool.metadata.SupportedLoginProviders == 'object') {
const providers = identityPool.metadata.SupportedLoginProviders;
const federated = {};
let hasFederated = false;
Expand Down Expand Up @@ -586,6 +604,67 @@ class ServerlessAmplifyPlugin {
}
});
}

/**
* Checks for and returns a manually defined AppClient cofiguration
*
* If the appClient information is defined in a different stack,
* we need to be able to define the UserPoolId and ClientId
* manually, using available cross stack variable references.
*
* @param {FileDetails} fileDetails the file details
*/
getManuallyDefinedAppClientConfiguration(fileDetails) {
let appClient;

try {
if (
fileDetails.appClient.UserPoolId
&& fileDetails.appClient.ClientId
) {
appClient = {
metadata: {
UserPoolClient: fileDetails.appClient
}
};
}
} catch (e) {
console.log('No manual appClient configuration available.');
}

return appClient;
}

/**
* Checks for and returns a manually defined IdentityPool cofiguration
*
* If the IdentityPool information is defined in a different stack,
* we need to be able to define the IdentityPoolId manually,
* using available cross stack variable references.
*
* @param {FileDetails} fileDetails the file details
*/
getManuallyDefinedIdentityPoolConfiguration(fileDetails) {
let identityPool;

try {
if (fileDetails.identityPool) {
identityPool = {
PhysicalResourceId: fileDetails.identityPool,
metadata: {
// This is not yet supported for manual
// specification of identityPool config.
// Please add.
SupportedLoginProviders: null
}
};
}
} catch (e) {
console.log('No manual identityPool configuration available.');
}

return identityPool;
}
}

module.exports = ServerlessAmplifyPlugin;
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "aws-amplify-serverless-plugin",
"version": "1.4.0",
"version": "1.4.2",
"description": "A plugin for the Serverless Framework that outputs AWS Amplify artifacts based on the deployed resources.",
"keywords": [
"serverless",
Expand Down