AWS Cognito adminCreateUser from Lambda, created with Amplify CLI - javascript

I created a Lambda function using Amplify CLI, when executing the Lambda function executes without errors but the Cognito User isn't created.
What am I missing here?
I have checked the CloudWatch Logs but not errors that I can pick up either.
I have been following this documentation: https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/CognitoIdentityServiceProvider.html#adminCreateUser-property
/* Amplify Params - DO NOT EDIT
AUTH_XXXXXXXXXXXXXXXXXXXX_USERPOOLID
ENV
REGION
Amplify Params - DO NOT EDIT */
const AWS = require('aws-sdk');
AWS.config.update({ region: process.env.AWS_REGION,accessKeyId: process.env.AWS_ACCESS_KEY_ID, secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY });
const cognitoidentityserviceprovider = new AWS.CognitoIdentityServiceProvider({ apiVersion: '2016-04-18' });
//console.log(process.env);
exports.handler = async (event) => {
let retailerid = event.pathParameters.retailerid;
let params = {
UserPoolId: process.env.AUTH_XXXXXXXXXXXXXXXXXXXX_USERPOOLID, /* required */
Username: 'testtest', /* required */
ClientMetadata: {
},
DesiredDeliveryMediums: [
'EMAIL'
],
ForceAliasCreation: false,
MessageAction: 'SUPPRESS',
TemporaryPassword: 'mynuw000000000TTS',
UserAttributes: [
{
Name: 'custom:app_role', /* required */
Value: 'retail'
},
{
Name: 'email_verified', /* required */
Value: 'true'
},
{
Name: 'email', /* required */
Value: 'usersname#someemail.co.za'
},
{
Name: 'phone_number', /* required */
Value: '27833260000'
},
/* more items */
],
ValidationData: [
/* more items */
]
};
await cognitoidentityserviceprovider.adminCreateUser(params, function (err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log('SUCCESS', data); // successful response
});
// TODO implement
const response = {
statusCode: 200,
// Uncomment below to enable CORS requests
headers: {
"Access-Control-Allow-Origin": "*"
},
body: JSON.stringify(retailerid),
};
return response;
};

Test event
{
"request": {
"userAttributes": {
"custom:name": "Ajay",
"email": "ajay#gmail.com",
"custom:role": "Admin"
}
},
"response": {}
}
Lambda Function
var AWS = require('aws-sdk');
var resp200ok = { statusCode: 200, headers: {'Content-Type': 'application/json'}, body: {} };
var cognitoidentityserviceprovider = new
AWS.CognitoIdentityServiceProvider({apiVersion: '2016-04-18'});
exports.handler = function(event, context, callback){
const attributes = event.request.userAttributes; // read user attributes from event
console.log('User Role : ',attributes['custom:role'])
var params = {
UserPoolId:'*********',
Username: attributes.email,
//TemporaryPassword: 'Password!1',
DesiredDeliveryMediums: ["EMAIL"],
UserAttributes: [
{
Name: "email",
Value: attributes.email
},
{
Name: 'email_verified', /* required */
Value: 'true'
},
{
Name: 'custom:name', /* required */
Value: attributes['custom:name']
},
{
Name: 'custom:role', /* required */
Value: attributes['custom:role']
},
],
};
cognitoidentityserviceprovider.adminCreateUser(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log('SUCCESS', data); // successful response
});
};

I'm not sure that await is working. How about this.
var createUserPromise = cognitoidentityserviceprovider.adminCreateUser(params).promise();
createUserPromise.then(results => {
// TODO implement
const response = {
statusCode: 200,
// Uncomment below to enable CORS requests
headers: {
"Access-Control-Allow-Origin": "*"
},
body: JSON.stringify(retailerid),
};
return response;
})
.catch(err => {
console.log("Error: ", err);
return "err"
});

await cognitoidentityserviceprovider.adminCreateUser(params).promise()
.then((data) => {
console.log('SUCCESS', data);
})
.catch((error) => {
console.log('ERROR', error);
});
This will work

Related

S3 Upload Failing Silently in Production

I'm struggling to debug a NextJS API that is working in development (via localhost) but is silently failing in production.
Below, the two console.log statements are not returning, so I suspect that the textToSpeech call is not executing correctly, potentially in time?
I'm not sure how to rectify, happy to debug as directed to resolve this!
const faunadb = require('faunadb')
const secret = process.env.FAUNADB_SECRET_KEY
const q = faunadb.query
const client = new faunadb.Client({ secret })
const TextToSpeechV1 = require('ibm-watson/text-to-speech/v1')
const { IamAuthenticator } = require('ibm-watson/auth')
const AWS = require('aws-sdk')
const { randomUUID } = require('crypto')
import { requireAuth } from '#clerk/nextjs/api'
module.exports = requireAuth(async (req, res) => {
try {
const s3 = new AWS.S3({
accessKeyId: process.env.AWS_ACCESS_KEY,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
})
const textToSpeech = new TextToSpeechV1({
authenticator: new IamAuthenticator({
apikey: process.env.IBM_API_KEY
}),
serviceUrl: process.env.IBM_SERVICE_URL
})
const uuid = randomUUID()
const { echoTitle, chapterTitle, chapterText } = req.body
const synthesizeParams = {
text: chapterText,
accept: 'audio/mp3',
voice: 'en-US_KevinV3Voice'
}
textToSpeech
.synthesize(synthesizeParams)
.then(buffer => {
const s3Params = {
Bucket: 'waveforms/audioform',
Key: `${uuid}.mp3`,
Body: buffer.result,
ContentType: 'audio/mp3',
ACL: 'public-read'
}
console.log(buffer.result)
console.log(s3Params)
s3.upload(s3Params, function (s3Err, data) {
if (s3Err) throw s3Err
console.log(`File uploaded successfully at ${data.Location}`)
})
})
.catch(err => {
console.log('error:', err)
})
const dbs = await client.query(
q.Create(q.Collection('audioform'), {
data: {
title: echoTitle,
published: 2022,
leadAuthor: 'winter',
user: req.session.userId,
authors: 1,
playTime: 83,
chapters: 1,
gpt3Description: '',
likes: 20,
image:
'https://waveforms.s3.us-east-2.amazonaws.com/images/Mars.jpeg',
trackURL: `https://waveforms.s3.us-east-2.amazonaws.com/audioform/${uuid}.mp3`,
albumTracks: [
{
title: chapterTitle,
text: chapterText,
trackURL: `https://waveforms.s3.us-east-2.amazonaws.com/audioform/${uuid}.mp3`
}
]
}
})
)
res.status(200).json(dbs.data)
} catch (e) {
res.status(500).json({ error: e.message })
}
})
Replace the async fragments something like this, assuming they are meant to be executed sequentially.
try {
// code removed here for clarity
const buffer = await textToSpeech.synthesize(synthesizeParams);
const s3Params = {
Bucket: 'waveforms/audioform',
Key: `${uuid}.mp3`,
Body: buffer.result,
ContentType: 'audio/mp3',
ACL: 'public-read'
}
await s3.upload(s3Params).promise();
const dbs = await client.query(...);
res.status(200).json(dbs.data);
} catch (e) {
res.status(500).json({ error: e.message });
}

API resolved without sending a response for /api/campaign/dynamicid, this may result in stalled requests. in next js

I am getting an error while running amazon ses code in next js. don't know where am wrong, please try to fix my error. If you have any question please free feel to ask.
sendmail.js
This is the sendmail.js file where i got error. here I am using amazon ses for sending mail.
var AWS = require('aws-sdk');
AWS.config.update({ region: process.env.AWS_REGION });
// var mail = '';
function sendMail(Email) {
var result;
// Create sendEmail params
var params = {
Destination: { /* required */
CcAddresses: [
Email,
/* more items */
],
ToAddresses: [
Email,
/* more items */
]
},
Message: { /* required */
Body: { /* required */
Html: {
Charset: "UTF-8",
Data: "HTML_FORMAT_BODY"
},
Text: {
Charset: "UTF-8",
Data: "TEXT_FORMAT_BODY"
}
},
Subject: {
Charset: 'UTF-8',
Data: 'Test email'
}
},
Source: 'abc#gmail.com', /* required */
ReplyToAddresses: [
'abc12#gmail.com',
/* more items */
],
};
// Create the promise and SES service object
var sendPromise = new AWS.SES({ apiVersion: '2010-12-01' }).sendEmail(params).promise();
// Handle promise's fulfilled/rejected states
sendPromise.then(
function (data) {
result = 'Success';
}).catch(
function (err) {
result = 'Failed';
});
}
export default sendMail;
dynamicid.js
This is the dynamic id .js file where i wrote my endpoint code
import { getDataFromSheets } from '../../../libs/sheets';
import sendmail from '../../../libs/ses/sendmail';
export default function handler(req, res) {
var data;
getDataFromSheets()
.then(sheet => {
data = sheet.length
for (var i = 1; i < data; i++) {
sendmail(sheet[i].Email)
}
})
.catch(err => console.log(err))
}
Each endpoint function must end the request-response cycle by sending a response ( res.send(), res.json(), res.end(), etc). So the solution would be:
export default function handler(req, res) {
var data;
getDataFromSheets()
.then(sheet => {
data = sheet.length
for (var i = 1; i < data; i++) {
sendmail(sheet[i].Email)
}
res.json({status: 'success', message: 'email has been sent'})
})
.catch(err => {
console.log(err)
res.json({status: 'fail', error: err})
})
}

Is there a correct way to handle promisified stream error in Nodejs

I am trying to catch an error in the controller and send status(500) to the front-end to let the user know that there is a streaming error. But for some reason the error is not caught and I am sending status(200) to the user. Let me know if i am doing something wrong.
file - utils.js
import WebSocket from 'ws';
import Twitter from 'twitter-lite';
import ck from 'ckey';
export const stream = (term, clients, twitterStream) => {
try {
const twitter = new Twitter({
// subdomain: 'api', // "api" is the default (change for other subdomains)
// version: '1.1', // version "1.1" is the default (change for other subdomains)
version: '2', // version "1.1" is the default (change for v2)
extension: false, // true is the default (this must be set to false for v2 endpoints)
consumer_key: ck.TWITTER_CONSUMER_KEY,
consumer_secret: ck.TWITTER_CONSUMER_SECRET,
access_token_key: ck.TWITTER_ACCESS_TOKEN_KEY,
access_token_secret: ck.TWITTER_ACCESS_TOKEN_SECRET,
});
let stream = twitter.stream('statuses/filter', { track: term });
new Promise(function (resolve, reject) {
stream.on('data', function (tweet) {
console.log('tweet');
resolve(broadcast(clients, JSON.stringify(tweet)));
});
stream.on('error', function (error) {
reject(error);
});
}).catch(function (e) {
console.log('stream error catch: ', e);
// throw e;
});
twitterStream = stream;
return twitterStream;
} catch (error) {
console.log('error from util', error);
// throw error;
}
};
const broadcast = (clients, message) => {
clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
client.send(message);
}
});
};
controller
import { stream } from './utils.js';
let twitterStream;
// Sets search term for twitter stream.
export const setSearchTerm = (req, res) => {
try {
const { term } = req.params;
console.log('setSearchTerm');
console.log('term: ', term);
if (twitterStream) {
console.log('getTweetPause');
twitterStream.destroy();
}
twitterStream = stream(term, req.app.locals.clients, twitterStream);
res.status(200).json({ message: 'Successful search request' });
} catch (error) {
res.status(500).json({ message: error });
}
};
file - utils.js
import WebSocket from 'ws';
import Twitter from 'twitter-lite';
import ck from 'ckey';
export const stream = (term) => {
const twitter = new Twitter({
// subdomain: 'api', // "api" is the default (change for other subdomains)
// version: '1.1', // version "1.1" is the default (change for other subdomains)
version: '2', // version "1.1" is the default (change for v2)
extension: false, // true is the default (this must be set to false for v2 endpoints)
consumer_key: ck.TWITTER_CONSUMER_KEY,
consumer_secret: ck.TWITTER_CONSUMER_SECRET,
access_token_key: ck.TWITTER_ACCESS_TOKEN_KEY,
access_token_secret: ck.TWITTER_ACCESS_TOKEN_SECRET,
});
let stream = twitter.stream('statuses/filter', { track: term });
return stream;
};
export const broadcast = (clients, message) => {
clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
client.send(message);
}
});
};
controller
import { stream, broadcast } from './utils.js';
let twitterStream;
// Sets search term for twitter stream.
export const setSearchTerm = async (req, res) => {
try {
const { term } = req.params;
console.log('setSearchTerm');
console.log('term: ', term);
if (twitterStream) {
console.log('getTweetPause');
twitterStream.destroy();
}
const currentStream = stream(term);
twitterStream = currentStream;
await new Promise((resolve, reject) => {
currentStream.on('data', function (tweet) {
console.log('tweets: ');
broadcast(req.app.locals.clients, JSON.stringify(tweet));
resolve(tweet);
});
currentStream.on('error', function (error) {
reject(error);
});
});
res.status(200).json({ message: 'Successful HTTP request' });
} catch (error) {
console.log('error catch: ');
res.status(500).json({ message: error });
}
};

Expectations Error while unit testing Got Client

I need your help with this issue that I am having while unit testing a Got client hook
where I do logging of HTTP requests. I am using Jest.
I am getting an expectations error that is seeing the argument to .toBeCalledWith as object whereas it is a string when I console log it. Maybe I am doing something wrong here. Please let me know.
got-client.js below
const http = require('http');
const https = require('https');
const got = require('got');
const _ = require('lodash');
const { name: packageName, version: packageVersion } = require('../../package.json');
const keepAliveOptions = { keepAlive: true, keepAliveMsecs: 20000 };
let clients = {};
const allowedHeaders = ['user-agent', 'x-forwarded-for', 'referer', 'content-length'];
const filterHeaders = headers => _.pick(headers, allowedHeaders);
const gotLoggingHooks = (name, logger) => ({
hooks: {
beforeRequest: [
options => {
const { url, method, headers } = options;
logger.debug({
message: `${name} request ${options.method} ${options.url}`,
http_request: {
method,
target: url,
direction: 'OUT',
headers: filterHeaders(headers)
},
request: _.pick(options, ['url', 'method', 'headers', 'body', 'json'])
});
}
],
beforeRetry: [
(options, error, retryCount) => {
const {
response: { statusCode, ip } = {},
request: { options: { method, headers = {} } = {}, requestUrl: url } = {},
timings: {
// eslint-disable-next-line camelcase
phases: { total: duration_ms } = {}
} = {}
} = error;
logger.warn({
message: `${name} will retry request, attempt ${retryCount}/${options.retry.limit} ${method} ${url} (${error.code} ${error.message})`,
err: error,
http_request: {
method,
target: url,
status: statusCode,
server_ip: ip,
duration_ms,
direction: 'OUT',
protocol: headers.via,
headers: filterHeaders(headers)
}
});
}
],
beforeError: [
error => {
const {
response: { statusCode, ip } = {},
request: { options: { method, headers } = {}, requestUrl: url } = {},
timings: {
// eslint-disable-next-line camelcase
phases: { total: duration_ms } = {}
} = {}
} = error;
if (!statusCode) {
logger.error({
message: `${name} request error ${method} ${url} (${error.code} ${error.message})`,
err: error,
http_request: {
method,
target: url,
status: statusCode,
server_ip: ip,
duration_ms,
direction: 'OUT',
protocol: headers.via,
headers: filterHeaders(headers)
}
});
}
// eslint-disable-next-line no-param-reassign
error.serviceName = name;
return error;
}
],
afterResponse: [
response => {
const {
statusCode,
body,
url,
ip,
headers = {},
request: { options: { method } = {} } = {},
timings: {
// eslint-disable-next-line camelcase
phases: { total: duration_ms } = {}
} = {},
retryCount
} = response;
logger.debug({
message: `${name} response ${method} ${url}`,
response: { body, retryCount, headers },
http_request: {
method,
target: url,
status: statusCode,
server_ip: ip,
duration_ms,
direction: 'OUT',
protocol: headers.via,
headers: filterHeaders(_.get(response, 'request.options.headers'))
}
});
return response;
}
]
}
});
const gotClient = ({ name, logger, keepAlive = true, gotOptions = {} }) => {
if (!clients[name]) {
clients[name] = got
.extend({
headers: {
'user-agent': `${packageName} ${packageVersion}`
},
...(keepAlive && {
agent: {
http: new http.Agent(keepAliveOptions),
https: new https.Agent(keepAliveOptions)
}
}),
responseType: 'json',
timeout: 5000
})
.extend(gotLoggingHooks(name, logger))
.extend(gotOptions);
}
return clients[name];
};
gotClient.clearAll = () => {
clients = {};
};
module.exports = gotClient;
got-client.spec.js below
const nock = require('nock');
const { name: packageName, version: packageVersion } = require('../../../package.json');
const gotClient = require('../../../src/lib/got-client');
const BASE_URL = 'https://subdomain.domain.com/';
const BASE_ENDPOINT = 'path';
const logger = {
error: jest.fn(),
debug: jest.fn(),
info: jest.fn(),
log: jest.fn(),
warn: jest.fn(),
};
describe('got client', () => {
afterEach(gotClient.clearAll);
test('should log requests', async () => {
const client = gotClient({
name: 'test',
logger,
gotOptions: {
prefixUrl: BASE_URL,
},
});
nock(BASE_URL).get(`/${BASE_ENDPOINT}`).reply(200, { success: true });
await client.get(BASE_ENDPOINT);
// console.log('mock call 0', logger.debug.mock.calls[0][0]);
// TODO: match message
expect(logger.debug).toBeCalled();
expect(logger.debug).toBeCalledWith(
expect.objectContaining({
message: expect.stringContaining(`request GET ${BASE_URL}${BASE_ENDPOINT}`),
})
);
expect(logger.debug).toBeCalledWith(
expect.objectContaining({
message: expect.stringContaining(`response GET ${BASE_URL}${BASE_ENDPOINT}`),
})
);
nock(BASE_URL).get(`/${BASE_ENDPOINT}/error`).reply(500, { success: false });
try {
await client.get(`${BASE_ENDPOINT}/error`, { retry: 0 });
} catch (e) {}
expect(logger.error).toBeCalledWith(
expect.objectContaining({
message: expect.stringContaining(`request error GET ${BASE_URL}${BASE_ENDPOINT}/error`),
})
);
});
});
Failing Test Error below
Error: expect(jest.fn()).toBeCalledWith(...expected)
Expected: ObjectContaining {"message": StringContaining "request error GET https://subdomain.domain.com/path/error"}
Number of calls: 0
at Object.<anonymous> (/Users/user/Documents/company/teams/team/project/test/unit/lib/got-clients.spec.js:62:26)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
I will really appreciate help with this. Thank you very much in advance.
Working got-client.spec.js
const nock = require('nock');
const { name: packageName, version: packageVersion } = require('../../../package.json');
const gotClient = require('../../../src/lib/got-client');
const BASE_URL = 'https://subdomain.domain.com/';
const BASE_ENDPOINT = 'path';
const logger = {
error: jest.fn(),
debug: jest.fn(),
info: jest.fn(),
log: jest.fn(),
warn: jest.fn(),
};
const defaultClient = gotClient({
name: 'test',
logger,
gotOptions: {
prefixUrl: BASE_URL,
},
});
describe('got client', () => {
afterEach(gotClient.clearAll);
test('should log requests', async () => {
nock(BASE_URL).get(`/${BASE_ENDPOINT}`).reply(200, { success: true });
await defaultClient.get(BASE_ENDPOINT);
expect(logger.debug).toBeCalledWith(
expect.objectContaining({
message: expect.stringContaining(`request GET ${BASE_URL}${BASE_ENDPOINT}`),
})
);
});
test('should log responses', async () => {
nock(BASE_URL).get(`/${BASE_ENDPOINT}`).reply(200, { success: true });
await defaultClient.get(BASE_ENDPOINT);
expect(logger.debug).toBeCalledWith(
expect.objectContaining({
message: expect.stringContaining(`response GET ${BASE_URL}${BASE_ENDPOINT}`),
})
);
});
test('should log errors', async () => {
const endpoint = `${BASE_ENDPOINT}/error`;
nock(BASE_URL).get(`/${endpoint}`).replyWithError({
message: 'something awful happened',
code: 'ECONNRESET',
});
try {
await defaultClient.get(endpoint, { retry: 0 });
} catch (e) {}
expect(logger.error).toBeCalledWith(
expect.objectContaining({
message: expect.stringContaining(`request error GET ${BASE_URL}${endpoint}`),
})
);
});
test('should log retries', async () => {
nock(BASE_URL)
.get(`/${BASE_ENDPOINT}`)
.replyWithError({
message: 'something awful happened',
code: 'ECONNRESET',
})
.get(`/${BASE_ENDPOINT}`)
.reply(500, { success: false })
.get(`/${BASE_ENDPOINT}`)
.reply(500, { success: false })
.get(`/${BASE_ENDPOINT}`)
.reply(200, { success: true });
await defaultClient.get(BASE_ENDPOINT, { retry: { limit: 3, calculateDelay: () => 1 } });
expect(logger.warn).toBeCalledTimes(3);
expect(logger.warn).toBeCalledWith(
expect.objectContaining({
message: expect.stringContaining(`will retry request`),
})
);
});
});

ConfigError: Missing region in config when i am using amazon ses with Node.js

I have used an env file and i used the structure like this and getting this error how to resolve that
"AWS_SES_REGION":"us-east-1" and i have put us-west-2 also but still getting the same error
"AWS_ACCESS_KEY_ID":"value"
"AWS_SECRET_KEY":"value"
and here is the code which i am using to send the email can anyone suggest me how to solve this problem
require('dotenv').config();
const AWS = require('aws-sdk');
const SESConfig = {
apiVersion:"2010-12-01",
accessKeyId:process.env.AWS_SECRET_KEY,
accessSecretKey:process.env.AWS_SECRET_KEY,
region:process.env.AWS_SES_REGION
}
// AWS.SESConfig.update({region: 'eu-central-1'});
var params = {
Source: 'xyz045#gmail.com',
Destination: {
ToAddresses: [
'yyy45#gmail.com'
]
},
ReplyToAddresses: [
'xyz05#gmail.com',
],
Message: {
Body: {
Html: {
Charset: "UTF-8",
Data: 'IT IS <strong>WORKING</strong>!'
}
},
Subject: {
Charset: 'UTF-8',
Data: 'Node + SES Example'
}
}
};
new AWS.SES(SESConfig).sendEmail(params).promise().then((res) => {
console.log(res);
}).catch(error => {
console.log(error)
});
Try to load the config using the AWS.Config class.
Example:
require('dotenv').config();
const AWS = require('aws-sdk');
const SESConfig = {
apiVersion: "2010-12-01",
accessKeyId: process.env.AWS_SECRET_KEY,
accessSecretKey: process.env.AWS_SECRET_KEY,
region: process.env.AWS_SES_REGION
}
let config = new AWS.Config(SESConfig); // Load the configuration like this.
/*
Or you could update the config like this.
AWS.config.update(SESConfig);
*/
var params = {
Source: 'xyz045#gmail.com',
Destination: {
ToAddresses: [
'yyy45#gmail.com'
]
},
ReplyToAddresses: [
'xyz05#gmail.com',
],
Message: {
Body: {
Html: {
Charset: "UTF-8",
Data: 'IT IS <strong>WORKING</strong>!'
}
},
Subject: {
Charset: 'UTF-8',
Data: 'Node + SES Example'
}
}
};
new AWS.SES().sendEmail(params).promise().then((res) => {
console.log(res);
}).catch(error => {
console.log(error)
});

Categories

Resources