Merge branch 'master' into improve-error-handling

This commit is contained in:
Mariusz Nowak 2019-08-06 14:17:14 +02:00
commit 6c54275b02
No known key found for this signature in database
GPG Key ID: B1FBDA8A182B03F2
13 changed files with 547 additions and 74 deletions

View File

@ -78,6 +78,8 @@ functions:
Sometimes you might want to attach Lambda functions to existing Cognito User Pools. In that case you just need to set the `existing` event configuration property to `true`. All the other config parameters can also be used on existing user pools:
**IMPORTANT:** You can only attach 1 existing Cognito User Pool per function.
**NOTE:** Using the `existing` config will add an additional Lambda function and IAM Role to your stack. The Lambda function backs-up the Custom Cognito User Pool Resource which is used to support existing user pools.
```yaml

View File

@ -16,7 +16,7 @@ function handler(event, context) {
}
function create(event, context) {
const { FunctionName, UserPoolName, UserPoolConfig } = event.ResourceProperties;
const { FunctionName, UserPoolName, UserPoolConfigs } = event.ResourceProperties;
const { Region, AccountId } = getEnvironment(context);
const lambdaArn = getLambdaArn(Region, AccountId, FunctionName);
@ -32,7 +32,7 @@ function create(event, context) {
updateConfiguration({
lambdaArn,
userPoolName: UserPoolName,
userPoolConfig: UserPoolConfig,
userPoolConfigs: UserPoolConfigs,
region: Region,
})
)
@ -41,14 +41,14 @@ function create(event, context) {
function update(event, context) {
const { Region, AccountId } = getEnvironment(context);
const { FunctionName, UserPoolName, UserPoolConfig } = event.ResourceProperties;
const { FunctionName, UserPoolName, UserPoolConfigs } = event.ResourceProperties;
const lambdaArn = getLambdaArn(Region, AccountId, FunctionName);
return updateConfiguration({
lambdaArn,
userPoolName: UserPoolName,
userPoolConfig: UserPoolConfig,
userPoolConfigs: UserPoolConfigs,
region: Region,
});
}

View File

@ -42,7 +42,7 @@ function getConfiguration(config) {
}
function updateConfiguration(config) {
const { lambdaArn, userPoolConfig, region } = config;
const { lambdaArn, userPoolConfigs, region } = config;
const cognito = new CognitoIdentityServiceProvider({ region });
return getConfiguration(config).then(res => {
@ -54,7 +54,9 @@ function updateConfiguration(config) {
return accum;
}, LambdaConfig);
LambdaConfig[userPoolConfig.Trigger] = lambdaArn;
userPoolConfigs.forEach(poolConfig => {
LambdaConfig[poolConfig.Trigger] = lambdaArn;
});
return cognito.updateUserPool({ UserPoolId, LambdaConfig }).promise();
});

View File

@ -485,8 +485,12 @@ module.exports = {
)}`
);
},
getCustomResourceCognitoUserPoolResourceLogicalId(functionName, idx) {
return `${this.getNormalizedFunctionName(functionName)}CustomCognitoUserPool${idx}`;
getCustomResourceCognitoUserPoolResourceLogicalId(functionName) {
// NOTE: we have to keep the 1 at the end to ensure backwards compatibility
// previously we've used an index to allow the creation of multiple custom
// Cognito User Pool resources
// we're now using one resource to handle multiple Cognito User Pool event definitions
return `${this.getNormalizedFunctionName(functionName)}CustomCognitoUserPool1`;
},
// Event Bridge
getCustomResourceEventBridgeHandlerFunctionName() {

View File

@ -780,10 +780,9 @@ describe('#naming()', () => {
describe('#getCustomResourceCognitoUserPoolResourceLogicalId()', () => {
it('should return the logical id of the Cognito User Pool custom resouce', () => {
const functionName = 'my-function';
const index = 1;
expect(
sdk.naming.getCustomResourceCognitoUserPoolResourceLogicalId(functionName, index)
).to.equal('MyDashfunctionCustomCognitoUserPool1');
expect(sdk.naming.getCustomResourceCognitoUserPoolResourceLogicalId(functionName)).to.equal(
'MyDashfunctionCustomCognitoUserPool1'
);
});
});

View File

@ -108,56 +108,90 @@ class AwsCompileCognitoUserPoolEvents {
const { service } = this.serverless;
const { provider } = service;
const { compiledCloudFormationTemplate } = provider;
const { Resources } = compiledCloudFormationTemplate;
const iamRoleStatements = [];
// used to keep track of the custom resources created for each Cognito User Pool
const poolResources = {};
service.getAllFunctions().forEach(functionName => {
let numEventsForFunc = 0;
let currentPoolName = null;
let funcUsesExistingCognitoUserPool = false;
const functionObj = service.getFunction(functionName);
const FunctionName = functionObj.name;
if (functionObj.events) {
functionObj.events.forEach((event, idx) => {
functionObj.events.forEach(event => {
if (event.cognitoUserPool && event.cognitoUserPool.existing) {
idx++;
numEventsForFunc++;
const { pool, trigger } = event.cognitoUserPool;
funcUsesExistingCognitoUserPool = true;
if (!currentPoolName) {
currentPoolName = pool;
}
if (pool !== currentPoolName) {
const errorMessage = [
'Only one Cognito User Pool can be configured per function.',
` In "${FunctionName}" you're attempting to configure "${currentPoolName}" and "${pool}" at the same time.`,
].join('');
throw new this.serverless.classes.Error(errorMessage);
}
const eventFunctionLogicalId = this.provider.naming.getLambdaLogicalId(functionName);
const customResourceFunctionLogicalId = this.provider.naming.getCustomResourceCognitoUserPoolHandlerFunctionLogicalId();
const customCognitoUserPoolResourceLogicalId = this.provider.naming.getCustomResourceCognitoUserPoolResourceLogicalId(
functionName,
idx
const customPoolResourceLogicalId = this.provider.naming.getCustomResourceCognitoUserPoolResourceLogicalId(
functionName
);
const customCognitoUserPool = {
[customCognitoUserPoolResourceLogicalId]: {
Type: 'Custom::CognitoUserPool',
Version: 1.0,
DependsOn: [eventFunctionLogicalId, customResourceFunctionLogicalId],
Properties: {
ServiceToken: {
'Fn::GetAtt': [customResourceFunctionLogicalId, 'Arn'],
},
FunctionName,
UserPoolName: pool,
UserPoolConfig: {
Trigger: trigger,
// store how often the custom Cognito User Pool resource is used
if (poolResources[pool]) {
poolResources[pool] = _.union(poolResources[pool], [customPoolResourceLogicalId]);
} else {
Object.assign(poolResources, {
[pool]: [customPoolResourceLogicalId],
});
}
let customCognitoUserPoolResource;
if (numEventsForFunc === 1) {
customCognitoUserPoolResource = {
[customPoolResourceLogicalId]: {
Type: 'Custom::CognitoUserPool',
Version: 1.0,
DependsOn: [eventFunctionLogicalId, customResourceFunctionLogicalId],
Properties: {
ServiceToken: {
'Fn::GetAtt': [customResourceFunctionLogicalId, 'Arn'],
},
FunctionName,
UserPoolName: pool,
UserPoolConfigs: [
{
Trigger: trigger,
},
],
},
},
},
};
};
_.merge(compiledCloudFormationTemplate.Resources, customCognitoUserPool);
iamRoleStatements.push({
Effect: 'Allow',
Resource: '*',
Action: [
'cognito-idp:ListUserPools',
'cognito-idp:DescribeUserPool',
'cognito-idp:UpdateUserPool',
],
});
} else {
Resources[customPoolResourceLogicalId].Properties.UserPoolConfigs.push({
Trigger: trigger,
});
}
iamRoleStatements.push({
Effect: 'Allow',
Resource: '*',
Action: [
'cognito-idp:ListUserPools',
'cognito-idp:DescribeUserPool',
'cognito-idp:UpdateUserPool',
],
});
_.merge(Resources, customCognitoUserPoolResource);
}
});
}
@ -171,6 +205,22 @@ class AwsCompileCognitoUserPoolEvents {
}
});
// check if we need to add DependsOn clauses in case more than 1
// custom resources are created for one Cognito User Pool (to avoid race conditions)
if (Object.keys(poolResources).length > 0) {
Object.keys(poolResources).forEach(pool => {
const resources = poolResources[pool];
if (resources.length > 1) {
resources.forEach((currResourceLogicalId, idx) => {
if (idx > 0) {
const prevResourceLogicalId = resources[idx - 1];
Resources[currResourceLogicalId].DependsOn.push(prevResourceLogicalId);
}
});
}
});
}
if (iamRoleStatements.length) {
return addCustomResourceToService.call(this, 'cognitoUserPool', iamRoleStatements);
}

View File

@ -368,6 +368,22 @@ describe('AwsCompileCognitoUserPoolEvents', () => {
expect(addCustomResourceToServiceStub).to.have.been.calledOnce;
expect(addCustomResourceToServiceStub.args[0][1]).to.equal('cognitoUserPool');
expect(addCustomResourceToServiceStub.args[0][2]).to.deep.equal([
{
Action: [
'cognito-idp:ListUserPools',
'cognito-idp:DescribeUserPool',
'cognito-idp:UpdateUserPool',
],
Effect: 'Allow',
Resource: '*',
},
{
Action: ['lambda:AddPermission', 'lambda:RemovePermission'],
Effect: 'Allow',
Resource: 'arn:aws:lambda:*:*:function:first',
},
]);
expect(Resources.FirstCustomCognitoUserPool1).to.deep.equal({
Type: 'Custom::CognitoUserPool',
Version: 1,
@ -378,13 +394,273 @@ describe('AwsCompileCognitoUserPoolEvents', () => {
},
FunctionName: 'first',
UserPoolName: 'existing-cognito-user-pool',
UserPoolConfig: {
Trigger: 'CustomMessage',
},
UserPoolConfigs: [
{
Trigger: 'CustomMessage',
},
],
},
});
});
});
it('should create the necessary resources for a service using multiple event definitions', () => {
awsCompileCognitoUserPoolEvents.serverless.service.functions = {
first: {
name: 'first',
events: [
{
cognitoUserPool: {
pool: 'existing-cognito-user-pool',
trigger: 'CustomMessage',
existing: true,
},
},
{
cognitoUserPool: {
pool: 'existing-cognito-user-pool',
trigger: 'PreSignUp',
existing: true,
},
},
{
cognitoUserPool: {
pool: 'existing-cognito-user-pool',
trigger: 'DefineAuthChallenge',
existing: true,
},
},
],
},
};
return expect(
awsCompileCognitoUserPoolEvents.existingCognitoUserPools()
).to.be.fulfilled.then(() => {
const {
Resources,
} = awsCompileCognitoUserPoolEvents.serverless.service.provider.compiledCloudFormationTemplate;
expect(addCustomResourceToServiceStub).to.have.been.calledOnce;
expect(addCustomResourceToServiceStub.args[0][1]).to.equal('cognitoUserPool');
expect(addCustomResourceToServiceStub.args[0][2]).to.deep.equal([
{
Action: [
'cognito-idp:ListUserPools',
'cognito-idp:DescribeUserPool',
'cognito-idp:UpdateUserPool',
],
Effect: 'Allow',
Resource: '*',
},
{
Action: ['lambda:AddPermission', 'lambda:RemovePermission'],
Effect: 'Allow',
Resource: 'arn:aws:lambda:*:*:function:first',
},
]);
expect(Resources.FirstCustomCognitoUserPool1).to.deep.equal({
Type: 'Custom::CognitoUserPool',
Version: 1,
DependsOn: ['FirstLambdaFunction', 'CustomDashresourceDashexistingDashcupLambdaFunction'],
Properties: {
ServiceToken: {
'Fn::GetAtt': ['CustomDashresourceDashexistingDashcupLambdaFunction', 'Arn'],
},
FunctionName: 'first',
UserPoolName: 'existing-cognito-user-pool',
UserPoolConfigs: [
{
Trigger: 'CustomMessage',
},
{
Trigger: 'PreSignUp',
},
{
Trigger: 'DefineAuthChallenge',
},
],
},
});
});
});
it('should create DependsOn clauses when one cognito user pool is used in more than 1 custom resources', () => {
awsCompileCognitoUserPoolEvents.serverless.service.functions = {
first: {
name: 'first',
events: [
{
cognitoUserPool: {
pool: 'existing-cognito-user-pool',
trigger: 'CustomMessage',
existing: true,
},
},
{
cognitoUserPool: {
pool: 'existing-cognito-user-pool',
trigger: 'PreSignUp',
existing: true,
},
},
{
cognitoUserPool: {
pool: 'existing-cognito-user-pool',
trigger: 'DefineAuthChallenge',
existing: true,
},
},
],
},
second: {
name: 'second',
events: [
{
cognitoUserPool: {
pool: 'existing-cognito-user-pool',
trigger: 'PostConfirmation',
existing: true,
},
},
{
cognitoUserPool: {
pool: 'existing-cognito-user-pool',
trigger: 'PreAuthentication',
existing: true,
},
},
{
cognitoUserPool: {
pool: 'existing-cognito-user-pool',
trigger: 'PostAuthentication',
existing: true,
},
},
],
},
};
return expect(
awsCompileCognitoUserPoolEvents.existingCognitoUserPools()
).to.be.fulfilled.then(() => {
const {
Resources,
} = awsCompileCognitoUserPoolEvents.serverless.service.provider.compiledCloudFormationTemplate;
expect(addCustomResourceToServiceStub).to.have.been.calledOnce;
expect(addCustomResourceToServiceStub.args[0][1]).to.equal('cognitoUserPool');
expect(addCustomResourceToServiceStub.args[0][2]).to.deep.equal([
{
Action: [
'cognito-idp:ListUserPools',
'cognito-idp:DescribeUserPool',
'cognito-idp:UpdateUserPool',
],
Effect: 'Allow',
Resource: '*',
},
{
Action: ['lambda:AddPermission', 'lambda:RemovePermission'],
Effect: 'Allow',
Resource: 'arn:aws:lambda:*:*:function:first',
},
{
Action: [
'cognito-idp:ListUserPools',
'cognito-idp:DescribeUserPool',
'cognito-idp:UpdateUserPool',
],
Effect: 'Allow',
Resource: '*',
},
{
Action: ['lambda:AddPermission', 'lambda:RemovePermission'],
Effect: 'Allow',
Resource: 'arn:aws:lambda:*:*:function:second',
},
]);
expect(Object.keys(Resources)).to.have.length(2);
expect(Resources.FirstCustomCognitoUserPool1).to.deep.equal({
Type: 'Custom::CognitoUserPool',
Version: 1,
DependsOn: ['FirstLambdaFunction', 'CustomDashresourceDashexistingDashcupLambdaFunction'],
Properties: {
ServiceToken: {
'Fn::GetAtt': ['CustomDashresourceDashexistingDashcupLambdaFunction', 'Arn'],
},
FunctionName: 'first',
UserPoolName: 'existing-cognito-user-pool',
UserPoolConfigs: [
{
Trigger: 'CustomMessage',
},
{
Trigger: 'PreSignUp',
},
{
Trigger: 'DefineAuthChallenge',
},
],
},
});
expect(Resources.SecondCustomCognitoUserPool1).to.deep.equal({
Type: 'Custom::CognitoUserPool',
Version: 1,
DependsOn: [
'SecondLambdaFunction',
'CustomDashresourceDashexistingDashcupLambdaFunction',
'FirstCustomCognitoUserPool1',
],
Properties: {
ServiceToken: {
'Fn::GetAtt': ['CustomDashresourceDashexistingDashcupLambdaFunction', 'Arn'],
},
FunctionName: 'second',
UserPoolName: 'existing-cognito-user-pool',
UserPoolConfigs: [
{
Trigger: 'PostConfirmation',
},
{
Trigger: 'PreAuthentication',
},
{
Trigger: 'PostAuthentication',
},
],
},
});
});
});
it('should throw if more than 1 Cognito User Pool is configured per function', () => {
awsCompileCognitoUserPoolEvents.serverless.service.functions = {
first: {
name: 'first',
events: [
{
cognitoUserPool: {
pool: 'existing-cognito-user-pool',
trigger: 'CustomMessage',
existing: true,
},
},
{
cognitoUserPool: {
pool: 'existing-cognito-user-pool-2',
trigger: 'PreSignUp',
existing: true,
},
},
],
},
};
return expect(() => awsCompileCognitoUserPoolEvents.existingCognitoUserPools()).to.throw(
'Only one Cognito User Pool'
);
});
});
describe('#mergeWithCustomResources()', () => {

View File

@ -208,6 +208,7 @@ class AwsCompileS3Events {
service.getAllFunctions().forEach(functionName => {
let numEventsForFunc = 0;
let currentBucketName = null;
let funcUsesExistingS3Bucket = false;
const functionObj = service.getFunction(functionName);
const FunctionName = functionObj.name;
@ -221,6 +222,17 @@ class AwsCompileS3Events {
const notificationEvent = event.s3.event || 's3:ObjectCreated:*';
funcUsesExistingS3Bucket = true;
if (!currentBucketName) {
currentBucketName = bucket;
}
if (bucket !== currentBucketName) {
const errorMessage = [
'Only one S3 Bucket can be configured per function.',
` In "${FunctionName}" you're attempting to configure "${currentBucketName}" and "${bucket}" at the same time.`,
].join('');
throw new this.serverless.classes.Error(errorMessage);
}
rules = _.map(event.s3.rules, rule => {
const key = Object.keys(rule)[0];
const value = rule[key];

View File

@ -741,5 +741,29 @@ describe('AwsCompileS3Events', () => {
});
});
});
it('should throw if more than 1 S3 bucket is configured per function', () => {
awsCompileS3Events.serverless.service.functions = {
first: {
name: 'second',
events: [
{
s3: {
bucket: 'existing-s3-bucket',
existing: true,
},
},
{
s3: {
bucket: 'existing-s3-bucket-2',
existing: true,
},
},
],
},
};
return expect(() => awsCompileS3Events.existingS3Buckets()).to.throw('Only one S3 Bucket');
});
});
});

View File

@ -13,8 +13,8 @@ function basic(event, context, callback) {
return callback(null, nextEvent);
}
function existing(event, context, callback) {
const functionName = 'existing';
function existingSimple(event, context, callback) {
const functionName = 'existingSimple';
const nextEvent = Object.assign({}, event);
nextEvent.response.autoConfirmUser = true;
@ -22,4 +22,11 @@ function existing(event, context, callback) {
return callback(null, nextEvent);
}
module.exports = { basic, existing };
function existingMulti(event, context, callback) {
const functionName = 'existingMulti';
log(functionName, JSON.stringify(event));
return callback(null, event);
}
module.exports = { basic, existingSimple, existingMulti };

View File

@ -12,10 +12,22 @@ functions:
- cognitoUserPool:
pool: CHANGE_TO_UNIQUE_PER_RUN
trigger: PreSignUp
existing:
handler: core.existing
existingSimple:
handler: core.existingSimple
events:
- cognitoUserPool:
pool: CHANGE_TO_UNIQUE_PER_RUN
trigger: PreSignUp
existing: true
# testing if two functions share one cognito user pool with multiple configs
existingMulti:
handler: core.existingMulti
events:
- cognitoUserPool:
pool: CHANGE_TO_UNIQUE_PER_RUN
trigger: PreSignUp
existing: true
- cognitoUserPool:
pool: CHANGE_TO_UNIQUE_PER_RUN
trigger: PreAuthentication
existing: true

View File

@ -1,6 +1,7 @@
'use strict';
const path = require('path');
const BbPromise = require('bluebird');
const { expect } = require('chai');
const { getTmpDirPath } = require('../../utils/fs');
@ -9,6 +10,9 @@ const {
deleteUserPool,
findUserPoolByName,
createUser,
createUserPoolClient,
setUserPassword,
initiateAuth,
} = require('../../utils/cognito');
const {
createTestService,
@ -23,7 +27,8 @@ describe('AWS - Cognito User Pool Integration Test', () => {
let stackName;
let tmpDirPath;
let poolBasicSetup;
let poolExistingSetup;
let poolExistingSimpleSetup;
let poolExistingMultiSetup;
const stage = 'dev';
beforeAll(() => {
@ -36,17 +41,23 @@ describe('AWS - Cognito User Pool Integration Test', () => {
// Ensure unique user pool names for each test (to avoid collision among concurrent CI runs)
config => {
poolBasicSetup = `${config.service} CUP Basic`;
poolExistingSetup = `${config.service} CUP Existing`;
poolExistingSimpleSetup = `${config.service} CUP Existing Simple`;
poolExistingMultiSetup = `${config.service} CUP Existing Multi`;
config.functions.basic.events[0].cognitoUserPool.pool = poolBasicSetup;
config.functions.existing.events[0].cognitoUserPool.pool = poolExistingSetup;
config.functions.existingSimple.events[0].cognitoUserPool.pool = poolExistingSimpleSetup;
config.functions.existingMulti.events[0].cognitoUserPool.pool = poolExistingMultiSetup;
config.functions.existingMulti.events[1].cognitoUserPool.pool = poolExistingMultiSetup;
},
});
serviceName = serverlessConfig.service;
stackName = `${serviceName}-${stage}`;
// create an external Cognito User Pool
// NOTE: deployment can only be done once the Cognito User Pool is created
console.info(`Creating Cognito User Pool "${poolExistingSetup}"...`);
return createUserPool(poolExistingSetup).then(() => {
// create external Cognito User Pools
// NOTE: deployment can only be done once the Cognito User Pools are created
console.info('Creating Cognito User Pools');
return BbPromise.all([
createUserPool(poolExistingSimpleSetup),
createUserPool(poolExistingMultiSetup),
]).then(() => {
console.info(`Deploying "${stackName}" service...`);
deployService();
});
@ -55,8 +66,11 @@ describe('AWS - Cognito User Pool Integration Test', () => {
afterAll(() => {
console.info('Removing service...');
removeService();
console.info(`Deleting Cognito User Pool "${poolExistingSetup}"...`);
return deleteUserPool(poolExistingSetup);
console.info('Deleting Cognito User Pools');
return BbPromise.all([
deleteUserPool(poolExistingSimpleSetup),
deleteUserPool(poolExistingMultiSetup),
]);
});
describe('Basic Setup', () => {
@ -80,22 +94,53 @@ describe('AWS - Cognito User Pool Integration Test', () => {
});
describe('Existing Setup', () => {
it('should invoke function when a user is created', () => {
let userPoolId;
const functionName = 'existing';
const markers = getMarkers(functionName);
describe('single function / single pool setup', () => {
it('should invoke function when a user is created', () => {
let userPoolId;
const functionName = 'existingSimple';
const markers = getMarkers(functionName);
return findUserPoolByName(poolExistingSetup)
.then(pool => {
userPoolId = pool.Id;
return createUser(userPoolId, 'janedoe', '!!!wAsD123456wAsD!!!');
})
.then(() => waitForFunctionLogs(functionName, markers.start, markers.end))
.then(logs => {
expect(logs).to.include(`"userPoolId":"${userPoolId}"`);
expect(logs).to.include('"userName":"janedoe"');
expect(logs).to.include('"triggerSource":"PreSignUp_AdminCreateUser"');
});
return findUserPoolByName(poolExistingSimpleSetup)
.then(pool => {
userPoolId = pool.Id;
return createUser(userPoolId, 'janedoe', '!!!wAsD123456wAsD!!!');
})
.then(() => waitForFunctionLogs(functionName, markers.start, markers.end))
.then(logs => {
expect(logs).to.include(`"userPoolId":"${userPoolId}"`);
expect(logs).to.include('"userName":"janedoe"');
expect(logs).to.include('"triggerSource":"PreSignUp_AdminCreateUser"');
});
});
});
describe('single function / multi pool setup', () => {
it('should invoke function when a user inits auth after being created', () => {
let userPoolId;
let clientId;
const functionName = 'existingMulti';
const markers = getMarkers(functionName);
const username = 'janedoe';
const password = '!!!wAsD123456wAsD!!!';
return findUserPoolByName(poolExistingMultiSetup)
.then(pool => {
userPoolId = pool.Id;
return createUserPoolClient('myClient', userPoolId).then(client => {
clientId = client.UserPoolClient.ClientId;
return createUser(userPoolId, username, password)
.then(() => setUserPassword(userPoolId, username, password))
.then(() => initiateAuth(clientId, username, password));
});
})
.then(() => waitForFunctionLogs(functionName, markers.start, markers.end))
.then(logs => {
expect(logs).to.include(`"userPoolId":"${userPoolId}"`);
expect(logs).to.include(`"userName":"${username}"`);
expect(logs).to.include('"triggerSource":"PreSignUp_AdminCreateUser"');
expect(logs).to.include('"triggerSource":"PreAuthentication_Authentication"');
});
});
});
});
});

View File

@ -9,6 +9,17 @@ function createUserPool(name) {
return cognito.createUserPool({ PoolName: name }).promise();
}
function createUserPoolClient(name, userPoolId) {
const cognito = new AWS.CognitoIdentityServiceProvider({ region });
const params = {
ClientName: name,
UserPoolId: userPoolId,
ExplicitAuthFlows: ['USER_PASSWORD_AUTH'],
};
return cognito.createUserPoolClient(params).promise();
}
function deleteUserPool(name) {
const cognito = new AWS.CognitoIdentityServiceProvider({ region });
@ -53,9 +64,38 @@ function createUser(userPoolId, username, password) {
return cognito.adminCreateUser(params).promise();
}
function setUserPassword(userPoolId, username, password) {
const cognito = new AWS.CognitoIdentityServiceProvider({ region });
const params = {
UserPoolId: userPoolId,
Username: username,
Password: password,
Permanent: true,
};
return cognito.adminSetUserPassword(params).promise();
}
function initiateAuth(clientId, username, password) {
const cognito = new AWS.CognitoIdentityServiceProvider({ region });
const params = {
ClientId: clientId,
AuthFlow: 'USER_PASSWORD_AUTH',
AuthParameters: {
USERNAME: username,
PASSWORD: password,
},
};
return cognito.initiateAuth(params).promise();
}
module.exports = {
createUserPool: persistentRequest.bind(this, createUserPool),
deleteUserPool: persistentRequest.bind(this, deleteUserPool),
findUserPoolByName: persistentRequest.bind(this, findUserPoolByName),
createUserPoolClient: persistentRequest.bind(this, createUserPoolClient),
createUser: persistentRequest.bind(this, createUser),
setUserPassword: persistentRequest.bind(this, setUserPassword),
initiateAuth: persistentRequest.bind(this, initiateAuth),
};