I'm trying to access user attributes in lambda function. Basically I need email of listUsersRes.Users. I'm trying through listUsersRes.Users[0].Email but it is returning undefined.
const aws = require("aws-sdk");
exports.handler = async (event, context, callback) => {
const cognitoProvider = new aws.CognitoIdentityServiceProvider({apiVersion: "2016-04-18"});
if (event.triggerSource == "PreSignUp_SignUp" ||event.triggerSource == "PreSignUp_AdminCreateUser" || event.triggerSource=="PreSignUp_ExternalProvider") {
try {
const listUserParams={UserPoolId: event.userPoolId,AttributesToGet: ["email"],Filter: `cognito:user_status= \"${"UNCONFIRMED"}\"`, Limit: 10 };
const listUsersRes = await cognitoProvider.listUsers(listUserParams).promise();
if (listUsersRes.Users.length >= 0) {
var params = {
Username: listUsersRes.Users[0].Username,
UserPoolId: event.userPoolId};
await cognitoProvider.adminGetUser(params, function(err,data){
if(err) callback(new Error(err), event);
else {
callback(new Error(data), event);
}
});
// callback(new Error(listUsersRes.Users[0].Username),event);
}else {callback(new Error("Something went wrong!"), event);}
}
catch (error) {return callback(new Error("catch error"), event);}
}
else {callback(new Error("This provider is not supported"), event);}
};
I need email of listUsers am I doing right?
Related
Consider the code :
const AWS = require('aws-sdk');
const dynamoDB = new AWS.DynamoDB({
region : 'us-east-2' ,
apiVersion: '2012-08-10'
});
exports.handler = async (event , context , callback) => {
const type = event.type;
if (type === 'all') {
// Which table we want to scan
const params = {
TableName : 'compare-yourself'
};
await dynamoDB.scan(params ,(err , data) => {
if (err) {
callback(err);
}
else{
callback(null , data);
}
});
// callback(null , "All Data");
}
else if (type === 'single') {
callback(null , "Single data");
}
else{
callback(null , "Everything else...");
}
};
When I test this piece of code on AWS Lambda with the value :
The result is always "Response: null" , even through there is data in the DynamoDB table compare-yourself.
What might be the problem here ?
Promise will solve the issue. I prefer documentclient.
const AWS = require('aws-sdk');
const documentClient = new AWS.DynamoDB.DocumentClient();
exports.handler = async (event, context, callback) => {
const type = event.type;
if (type === 'all') {
const params = {
TableName: 'compare-yourself'
};
let data = await documentClient.scan(params).promise();
callback(null, data);
} else if (type === 'single') {
callback(null, "Single data");
} else {
callback(null, "Everything else...");
}
};
The data will be an object with table values in the Items,
{
Items: [],
Count:
ScannedCount:
.....
}
try use DocumentClient();
var documentClient = new AWS.DynamoDB.DocumentClient();
const params = {
TableName : 'compare-yourself'
};
documentClient.scan(params, function(err, data) {
if (err) console.log(err);
else console.log(data);
});
Mistake:
The problem is you are doing both callback and await at the same.
Fix:
So you could put the scan function in a try block, so on error
we do callback error in the catch block and stop the function without proceeding further (return) else you will send the data.
Code:
const AWS = require('aws-sdk');
const dynamoDB = new AWS.DynamoDB({
region : 'us-east-2' ,
apiVersion: '2012-08-10'
});
exports.handler = async (event , context , callback) => {
const type = event.type;
if (type === 'all') {
// Which table we want to scan
const params = {
TableName : 'compare-yourself'
};
try {
await dynamoDB.scan(params).promise();
} catch (e) {
callback(e);
return;
}
callback(null , data);
}
else if (type === 'single') {
callback(null , "Single data");
}
else{
callback(null , "Everything else...");
}
};
Note:
Just wanted to add this, when performing scan be aware of the limits, if the limit exceeds you won't get the entire entries in the table.
I am using Nodejs + redis to Set and Get key:value pairs. I have written a sample code to set a key:value pair and then fetch it using the default readme from npm redis plugin.
My goal here is to get value from the redis server using any given key. I have followed the steps as given by npm redis plugin. I am able to log it, but since the plugin is async cant figure out a way to get a synchronous client.get request.
My code is
var redis = require("redis"),
client = redis.createClient();
const bluebird = require("bluebird");
bluebird.promisifyAll(redis.RedisClient.prototype);
bluebird.promisifyAll(redis.Multi.prototype);
const redisKey = "redis-set-key";
const redisValue = "hello-world";
client.set(redisKey, redisValue);
function getData(key) {
return client.get(key, function(err, result) {
console.log("1. Get key from redis - ", result.toString());
return result.toString();
});
}
const getRedisdata = getData(redisKey);
console.log("2. getRedisdata", getRedisdata);
Result
2. getRedisdata false
1. Get key from redis - hello-world
My goal is to get the result like this
1. Get key from redis - hello-world
2. getRedisdata hello-world
Please help me resolve this.
Found a solution, here is my resolved code
const redis = require("redis");
const client = redis.createClient();
const bluebird = require("bluebird");
bluebird.promisifyAll(redis.RedisClient.prototype);
bluebird.promisifyAll(redis.Multi.prototype);
const redisKey = "redis-set-key";
const redisValue = "hello-world";
client.set(redisKey, redisValue);
async function setKey(key, value, expire = "EX", time = 300) {
return new Promise((resolve, reject) => {
return client.set(key, value, function(err, result) {
if (result === null) {
reject("set key fail promise");
} else {
resolve(result);
}
});
});
}
async function getKey(key) {
return new Promise((resolve, reject) => {
return client.getAsync(key).then(function(res) {
if (res == null) {
reject("fail promise");
} else {
resolve(res);
}
});
});
}
async function hashGetKey(hashKey, hashvalue) {
return new Promise((resolve, reject) => {
return client.hget(hashKey, hashvalue, function(err, res) {
if (res == null) {
reject("hash key fail promise");
} else {
resolve(res.toString());
}
});
});
}
async function hashGetAllKey(hashKey) {
return new Promise((resolve, reject) => {
return client.hgetall(hashKey, function(err, res) {
if (res == null) {
reject("hash key all fail promise");
} else {
resolve(res);
}
});
});
}
async function delKey(key) {
return new Promise((resolve, reject) => {
return client.del(key, function(err, result) {
if (result === null) {
reject("delete fail promise");
} else {
resolve(result);
}
});
});
}
(async () => {
// get single key value
try {
const keyData = await getKey("string key");
console.log("Single key data:-", keyData);
} catch (error) {
console.log("Single key data error:-", error);
}
// get single hash key value
try {
const hashKeyData = await hashGetKey("hashkey", "hashtest 1");
console.log("Single hash key data:-", hashKeyData);
} catch (error) {
console.log("Single hash key data error:-", error);
}
// get all hash key values
try {
const allHashKeyData = await hashGetAllKey("hashkey");
console.log("All hash key data:-", allHashKeyData);
} catch (error) {
console.log("All hash key data error:-", error);
}
// delte single key
try {
const checkDel = await delKey("XXYYZZ!!!!");
console.log("Check key delete:-", checkDel);
} catch (error) {
console.log("Check key delete error:-", error);
}
// set single key
try {
const checkSet = await setKey("XXYYZZ", "AABBCC");
console.log("Check data setkey", checkSet);
} catch (error) {
console.log("Check data setkey error", error);
}
})();
// hget hashkey "hashtest 1"
client.hset("hashkey", "hashtest 1", "some value", redis.print);
client.hset(["hashkey", "hashtest 2", "some other value"], redis.print);
Haven't you read the Redis module's readme, it provides another way to use async/await way to make the async redis get process as sync.
const { promisify } = require("util");
const getAsync = promisify(client.get).bind(client);
getAsync.then(console.log).catch(console.error);
I'm trying to use AWS Secrets Manager to fetch my RDS credentials,
The Secrets Manager SDK is able to get the Secret properly,
But I am unable to export it back to my calling file.
I have 2 files -
1. index.js -
var mysql = require('mysql');
var secretsManager = require('./secrets-manager');
exports.handler = (event, context, callback) => {
secretsManager.getDbCredentialFromSecretsManager(function(err,creds) {
if (err) {
console.log(err);
callback(err, null);
}
else{
console.log("Creds ", creds);
var connection = mysql.createConnection(creds);
connection.connect(function(err) {
if (err) {
console.error(err.stack);
callback(err,null);
}
else{
callback(null,connection);
}
});
}
});
}
2. secrets-manager.js -
var AWS = require('aws-sdk');
var constants = require('/opt/nodejs/utils/constants');
module.exports = {
getRDSCredsFromSM
};
function getRDSCredsFromSM (callback) {
var response = {};
let secretName = "secretId";
var client = new AWS.SecretsManager({
region: constants.aws.region
});
client.getSecretValue({SecretId: secretName}, function(err, data) {
if (err) {
console.log(err);
callback(err, null);
}
else {
if ('SecretString' in data) {
let secret = data.SecretString;
secret = JSON.parse(secret);
console.log("secret",secret);
callback(null, secret);
} else {
let buff = new Buffer(data.SecretBinary, 'base64');
let decodedBinarySecret = buff.toString('ascii');
callback(null, decodedBinarySecret);
}
}
});
}
I feel there's some mistake from me on Node side,
Which is why the callback isn't working properly,
The Lambda Timesout,
And the logs show nothing in creds variable -
console.log("Creds ", creds);
Working code -
let async = require('async');
let AWS = require('aws-sdk');
module.exports = {
getDbCredentialFromSecretsManager
};
const TAG = '[SECRETS-MANAGER-UTIL->';
function getDbCredentialFromSecretsManager (constants, callback) {
let response = {};
const METHOD_TAG = TAG + 'getDbCredentialFromSecretsManager->';
async.waterfall([
function(callback) {
let client = new AWS.SecretsManager({
region: constants.aws.region
});
client.getSecretValue({SecretId: constants.aws.sm}, function(err, data) {
if (err) {
console.log(METHOD_TAG,err);
callback(err, null);
}
else {
console.log(METHOD_TAG, 'Secrets Manager call successful');
if ('SecretString' in data) {
let secret = data.SecretString;
secret = JSON.parse(secret);
response.user = secret.username;
response.password = secret.password;
response.host = secret.host;
response.database = constants.db.database;
callback(null, response);
} else {
let buff = new Buffer(data.SecretBinary, 'base64');
let decodedBinarySecret = buff.toString('ascii');
callback(null, decodedBinarySecret);
}
}
});
}
],
function(err, response) {
if (err) {
console.log(METHOD_TAG, err);
callback(err, response);
}
else {
callback(null, response);
}
});
}
I've been working on a function to verify purchase in server side. Everything works well.
Only one issue, when the purchase is valid (the response.status === 200) the console shows (success) but the document hasn't been updated.
Here is my code. Did i miss something ?
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const {google} = require('googleapis');
const publisher = google.androidpublisher('v2');
const authClient = new google.auth.JWT({
email: 'my_email',
key: 'my_key',
scopes: ['https://www.googleapis.com/auth/androidpublisher']
});
admin.initializeApp();
admin.firestore().settings({timestampsInSnapshots: true});
exports.validatePurchases = functions.firestore
.document('purchases/{channel}')
.onCreate((docSnapshot, context) => {
const purchase = docSnapshot.data();
const order_id = purchase.orderId;
const package_name = purchase.packageName;
const sku = purchase.sku;
const purchase_token = purchase.purchaseToken;
const user_id = purchase.userId;
authClient.authorize((err, result) => {
if (err) {
console.log(err);
}
publisher.purchases.subscriptions.get({
auth: authClient,
packageName: package_name,
subscriptionId: sku,
token: purchase_token
}, (err, response) => {
if (err) {
console.log(err);
}
// Result Status must be equals to 200 so that the purchase is valid
if (response.status === 200) {
console.log('success');
return admin.firestore().collection('users').doc(user_id).update({
purchaseToken: purchase_token,
isPremiumS: 'true'
});
} else {
console.log('fail');
return admin.firestore().collection('users').doc(user_id).update({
purchaseToken: purchase_token,
isPremiumS: 'false'
});
}
});
});
return null;
});
Instead of returning null, your function should return the Promise from your Firestore update() calls.
Add return in two places:
return authClient.authorize((err, result) => {...
return publisher.purchases.subscriptions.get({...
Delete return null; at the end of the function
I have been trying to use Cloud Messaging with my Lambda Function to send push notifications.
At first I tried to use SNS linked to Firebase. But calling SNS.publish does nothing... no errors, no timeouts just seems to ignore the call. Here is a snippet of where it goes wrong:
const intentName = event.request.intent.name;
// Dispatch to your skill's intent handlers
if (intentName === 'Temperature') {
getPatientTemperature(intent, context,
function (internalcontext, speechOutput) {
//sns
//var outmessage = {Display: speechOutput};
var sns = new AWS.SNS({region:'us-east-1'});
//console.log(sns);
console.log('sending push');
sns.publish({
Message: speechOutput,
TopicArn: "arn:aws:sns:us-east-1:*************:MedicalAssistantDisplayUpdates",
Subject: "TestSNS"
}, function(err, data) {
//context.callbackWaitsForEmptyEventLoop = false;
console.log("SNS here 2");
if (err) {
console.log(err.stack);
return;
}
console.log('push sent');
console.log(data);
console.log("SNS here 3");
});
context.succeed( buildResponse({}, buildSpeechletResponse("Sent",speechOutput, "no text", true)));
console.log("That's all folks");
});
} else {
throw new Error('Invalid intent');
}
It's full code:
/* eslint-disable func-names */
/* eslint-disable no-console */
//const Alexa = require('ask-sdk-core');
var mysql = require('mysql');
var AWS = require("aws-sdk");
var connection = mysql.createConnection({
host: "********************",
port: "****",
user: "*******",
password: "*****",
database: "**************"
});
//=========================================================================================================================================
//TODO: The items below this comment need your attention.
//=========================================================================================================================================
const SKILL_NAME = 'Medical Assistant';
const GET_TEMPERATURE_MESSAGE = '\'s temperature is ';
const HELP_MESSAGE = 'You can say tell me the latest tempearture of patient patient ID, or, you can say exit... What can I help you with?';
const HELP_REPROMPT = 'What can I help you with?';
const FALLBACK_MESSAGE = 'The Medical Assistant can\'t help you with that. It can help you retrieve a patient\'s tempearture. What can I help you with?';
const FALLBACK_REPROMPT = 'What can I help you with?';
const STOP_MESSAGE = 'Goodbye!';
// --------------- Helpers that build all of the responses -----------------------
function buildSpeechletResponse(title, output, repromptText, shouldEndSession) {
return {
outputSpeech: {
type: 'PlainText',
text: output,
},
card: {
type: 'Simple',
title: `${title}`,
content: `${output}`,
},
reprompt: {
outputSpeech: {
type: 'PlainText',
text: repromptText,
},
},
shouldEndSession,
};
}
function buildResponse(sessionAttributes, speechletResponse) {
return {
version: '1.0',
sessionAttributes,
response: speechletResponse,
};
}
function getPatientTemperature(intent, context, callback) {
const cardTitle = intent.name;
const PatientID = intent.slots.PatientID.value;
console.log(PatientID);
let repromptText = '';
let sessionAttributes = {};
const shouldEndSession = false;
let speechOutput = '';
console.log('Then run MySQL code:');
//connection.connect(function(err) {
console.log('Inside connection.connect() callback');
//context.callbackWaitsForEmptyEventLoop = false;
//if (!err) {
console.log("Database is connected ... ");
connection.query("SELECT Temperature, Patient_Name FROM (SELECT * FROM (SELECT c.Temperature, p.Patient_Name, c.Recorded_Time FROM ConsultationRecords c, Patients p WHERE (c.Patient_ID = p.Patient_ID) AND c.Patient_ID = '"+ PatientID +"' AND c.Temperature IS NOT NULL)AS Alias ORDER BY Recorded_Time DESC LIMIT 1) AS RequiredTemp",
function(err, result) {
//connection.end();
console.log("Inside connection.query() callback")
if (!err) {
console.log("Query Successful! Ending Connection.");
//connection.end();
if (result.length > 0) {
if(result[0].Temperature == 'null'){
}
else{
speechOutput = result[0].Patient_Name+"'s temperature is "+result[0].Temperature;
console.log("Returning Response");
}
}
else{
speechOutput = "Patient ID not found in records";
console.log("Returning invalid ID Response");
}
callback(context, speechOutput);
} else {
console.log("Query error!");
}
});
// } else {
// console.log("Error connecting database ..." + err.message);
// connection.end();
// }
console.log("here end");
// });
}
function getWelcomeResponse(context) {
// If we wanted to initialize the session to have some attributes we could add those here.
const sessionAttributes = {};
const cardTitle = 'Welcome';
const speechOutput = 'Welcome to Medical Assistant. ' +
'You can ask for Patient information like Temperature';
// If the user either does not reply to the welcome message or says something that is not
// understood, they will be prompted again with this text.
const repromptText = 'For example, say: what is the latest temparature of patient 1.';
const shouldEndSession = false;
console.log(`Send Welcome Response`);
context.succeed(buildSpeechletResponse(cardTitle, speechOutput, repromptText, shouldEndSession));
}
exports.handler = (event, context) => {
try {
if (event.session.new) {
// New Session
console.log("NEW SESSION");
}
// Fix for hardcoded context from simulator
//if(event.context && event.context.System.application.applicationId == 'applicationId'){
// event.context.System.application.applicationId = event.session.application.applicationId;
//}
switch (event.request.type) {
case "LaunchRequest":
console.log(`Launch Request`);
getWelcomeResponse(context);
console.log(`End Launch`);
break;
case "IntentRequest":
// Intent Request
console.log(`Intent Request`);
const intent = event.request.intent;
const intentName = event.request.intent.name;
// Dispatch to your skill's intent handlers
if (intentName === 'Temperature') {
getPatientTemperature(intent, context,
function (internalcontext, speechOutput) {
//sns
//var outmessage = {Display: speechOutput};
var sns = new AWS.SNS({region:'us-east-1'});
//console.log(sns);
console.log('sending push');
sns.publish({
Message: speechOutput,
TopicArn: "arn:aws:sns:us-east-1:**********:MedicalAssistantDisplayUpdates",
Subject: "TestSNS"
}, function(err, data) {
//context.callbackWaitsForEmptyEventLoop = false;
console.log("SNS here 2");
if (err) {
console.log(err.stack);
return;
}
console.log('push sent');
console.log(data);
console.log("SNS here 3");
});
context.succeed( buildResponse({}, buildSpeechletResponse("Sent",speechOutput, "no text", true)));
console.log("That's all folks");
});
} else {
throw new Error('Invalid intent');
}
break;
case "SessionEndedRequest":
// Session Ended Request
console.log(`SESSION ENDED REQUEST`);
break;
default:
context.fail(`INVALID REQUEST TYPE: ${event.request.type}`);
}
} catch (error) {
context.fail(`Exceptiodn: ${error}`)
}
};
After console.log('sending push'); it correctly runs context.succeed and the final console.log.
For my second attempt I tried to use the Firebase Admin SDK to update the firebase database (figuring I can store my messages there and then trigger a push notification from firebase when an insertion is made). I created a whole new Lambda function to test that and again.. just seems to ignore usersRef.set call. Here is the full code for that function:
var admin = require("firebase-admin");
var serviceAccount = require("medicalassistantviewer-firebase-adminsdk-7xw02-266915e453.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://****************.firebaseio.com"
});
// As an admin, the app has access to read and write all data, regardless of Security Rules
var db = admin.database();
var ref = db.ref();
var usersRef = ref.child("Messages");
exports.handler = (event, context) => {
console.log("Let's start");
context.succeed(usersRef.set({
message2: {
Message: "testing again",
Token: "200"
},
message3: {
Message: "and again",
Token: "300"
}
}, function(err, data) {
//context.callbackWaitsForEmptyEventLoop = false;
console.log("messages not sent");
if (err) {
console.log(err.stack);
return;
}
console.log('messages sent');
console.log(data);
console.log("here");
}));
};