Push Notification Using Amazon SNS (Node) - javascript

I am trying to implement push notification using Amazon SNS in Node. I have created a topic and published a message using below code
Create Topic
var createTopicPromise = new AWS.SNS({apiVersion: '2010-03-31'}).createTopic({Name: "TOPIC_NAME"}).promise();
// Handle promise's fulfilled/rejected states
createTopicPromise.then(
function(data) {
console.log("Topic ARN is " + data.TopicArn);
}).catch(
function(err) {
console.error(err, err.stack);
});
I got a TopicArn something like this arn:aws:sns:us-east-1:xxxxxxxxxx:TOPIC_NAME
Publish
// Load the AWS SDK for Node.js
var AWS = require('aws-sdk');
// Set region
AWS.config.update({region: 'REGION'});
// Create publish parameters
var params = {
Message: 'You Got Message!! Hello....', /* required */
TopicArn: 'arn:aws:sns:us-east-1:xxxxxxxxxx:TOPIC_NAME'
};
// Create promise and SNS service object
var publishTextPromise = new AWS.SNS({apiVersion: '2010-03-31'}).publish(params).promise();
// Handle promise's fulfilled/rejected states
publishTextPromise.then(
function(data) {
console.log("Message ${params.Message} send sent to the topic ${params.TopicArn}");
console.log("MessageID is " + data.MessageId);
}).catch(
function(err) {
console.error(err, err.stack);
});
Now the message have been published now I need to see this on my mobile. So I used subscribe code like this
var params = {
Protocol: 'application', /* required */
TopicArn: 'arn:aws:sns:us-east-1:xxxxxxxxxx:TOPIC_NAME', /* required */
Endpoint: 'MOBILE_ENDPOINT_ARN'
};
// Create promise and SNS service object
var subscribePromise = new AWS.SNS({ apiVersion: '2010-03-31' }).subscribe(params).promise();
req;
res;
// Handle promise's fulfilled/rejected states
subscribePromise.then(
function (data) {
console.log("Subscription ARN is " + data.SubscriptionArn);
}).catch(
function (err) {
console.error(err, err.stack);
});
}
My question is what is Endpoint in Subscribe params. Where should I get this? and So far Am I right ? Please help me out.

Endpoint here is the ARN of your mobile application that you need to register with AWS. Here is the snippet from the official documentation
For Amazon SNS to send notification messages to mobile endpoints,
whether it is direct or with subscriptions to a topic, you first need
to register the app with AWS.
Source : https://docs.aws.amazon.com/sns/latest/dg/mobile-push-send-register.html

Related

Permission Issue when trying to verify Google Play Subscription with NodeJS google-play-billing-validator

I am trying to verify Subscription Purchase from Android App ( Google Play ) on my server side using node and google-play-billing-validator package. I have followed the instruction and added services account along with accounts permission ( tried both only account and admin ) but its still returns me with insufficient permissions . I don't know why its doing that and whats wrong .
var Verifier = require('google-play-billing-validator');
var options = {
"email": '###########################',
"key": "PRIVATE",
};
try {
var verifier = new Verifier(options);
let receipt = {
packageName: "com.tech.ichat",
productId:
"mychat_bms1",
purchaseToken: "hajlffdcmmkdijnilkogpih.AO-J1OwYTQjVf57Exl8eJBRVNo4VLfwlWIOJykDfyASPLx9YbxvWwP0qDqls14Llcyt8cyslTCT4fN-Xy-0Vg-9BETVnTrxpPQ"
};
let promiseData = verifier.verifySub(receipt)
promiseData.then(function (response) {
// Yay! Subscription is valid
// See response structure below
console.log('API SUCCESS RESPONSE', error);
})
.then(function (response) {
// Here for example you can chain your work if subscription is valid
// eg. add coins to the user profile, etc
// If you are new to promises API
// Awesome docs: https://developers.google.com/web/fundamentals/primers/promises
})
.catch(function (error) {
// Subscription is not valid or API error
// See possible error messages below
console.error(error);
});
} catch (error) {
console.error('Exception Handled', error);
}
response I got .
{
isSuccessful: false,
errorCode: 401,
errorMessage: 'The current user has insufficient permissions to perform the requested operation.'
}

How to create a lambda function to update a new record on amplify?

How to create a lambda function to update a new record on amplify project using GraphQL ?
I have an amplify project using api GraphQL as api (also dynamoDB).
My app is a simple todo list, just to study, so I'm saving todos on my dynamoDB, that's my schema:
type Todo #model #auth(rules: [{ allow: owner }]) {
id: ID!
title: String!
status: String
}
When I create a new Todo I only set the title, not the status, I want to update the status with a default value using a lambda trigger function (I know I don't have to do that way, but I'm trying that to learn more lambda functions on amplify).
So I followed the steps from amplify docs, but now I can't figure it out what's the next step (I'm not familiar with aws lambda functions).
What I want to do something like:
for each new record
newRecord.status = 'To do'
newRecord.update()
When you first create the Todo item, it is stored as an item in a DynamodDB table. To update the todo item, you need to update the item in the DynamoDB table.
When you're updating an item in DynamoDB you need to use an AWS SDK to handle this. The simplest sdk to use is to use the AWS DynamoDB Document Client if you are using nodejs in the lambda function.
// Load the AWS SDK for Node.js
var AWS = require('aws-sdk');
// Set the region
AWS.config.update({region: 'REGION'}); //replace Region with the region you are using ('EU-WEST-1')
// Create DynamoDB document client
var docClient = new AWS.DynamoDB.DocumentClient({apiVersion: '2012-08-10'});
// put the the following code in the exports.handler in your lambda function
var params = {
TableName: 'Todo-SOMERANDOMSTRING-ENV',//The name of your dynamodb table
Key: {
'id' : 'asasd123-asdsa1-12sdasads-12', // the id of your todo item
},
UpdateExpression: 'set status = :s',
ExpressionAttributeValues: {
':s' : 'To do' // what the new status should be
}
};
// and run the update function
docClient.update(params, function(err, data) {
if (err) {
console.log("Error", err);
} else {
console.log("Success", data);
}
});
Edit
Based on your comment I think you might be on the DynamoDB Lambda Triggers section (?) and your boilerplate lambda function might looks like this:
exports.handler = function (event, context) {
console.log(JSON.stringify(event, null, 2));
event.Records.forEach((record) => {
console.log(record.eventID);
console.log(record.eventName);
console.log('DynamoDB Record: %j', record.dynamodb);
});
context.done(null, 'Successfully processed DynamoDB record');
};
I haven't done this type of trigger myself before so I'm not completely sure how data in record is structured, but I think it might will be accessible like this:
record.data.id
//or
record.Item.id
You can find this out by going to the lambda console, find and open your lambda function, go to "monitoring" and then open "View logs in CloudWatch" in AWS and check the CloudWatch logs after you have created an item.
Assuming it is record.Item.id your lambda code could look like this (untested):
var AWS = require('aws-sdk');
AWS.config.update({region: 'REGION'});
var docClient = new AWS.DynamoDB.DocumentClient({apiVersion: '2012-08-10'});
exports.handler = function (event, context) {
console.log(JSON.stringify(event, null, 2));
event.Records.forEach((record) => {
var params = {
TableName: 'YOUR-DB-TABLE-NAME',
Key: {
'id' : record.Item.id,
},
UpdateExpression: 'set status = :status',
ExpressionAttributeValues: {
':status' : 'To do' // what the new status should be
}
};
docClient.update(params, function(err, data) {
if (err) {
console.log("Error", err);
} else {
console.log("Success", data);
}
});
});
context.done(null, 'Successfully processed DynamoDB record');
};
I don't think this code is entirely complete, and you might have to change how/when the "context.done" function works (because I think it will run before the code finishes updating the item), but it might get you somewhat in the right direction.

Lambda function does not publish to SNS or update dynamodb

I am trying to update dynamodb and send SNS notification from Lambda function using the following code. Even though function execute successfully SNS notification does not happen. SNS log does not show any entry either. SNS from console to the same ARN works. Checked to update dynamodb that does not work either. Required IAM role policies for Dynamodb and SNS publish are created. Any pointers or way to debug will help.
'use strict';
console.log('Loading function');
var AWS = require("aws-sdk");
var sns = new AWS.SNS();
AWS.config.update({
region: "us-east-1"
});
var docClient = new AWS.DynamoDB.DocumentClient();
exports.handler = (event, context, callback) => {
context.callbackWaitsForEmptyEventLoop = false;
console.log('Received event: ', JSON.stringify(event, null, 2));
console.log('Received context: ', JSON.stringify(context, null, 2));
// console.log('Cognito id: ', context.identity.cognitoIdentityId);
+console.log("Start .................." + new Date().toString());+
console.log("Notifying....:");
sns.publish({
TargetArn: "arn:aws:sns:us-east-1:796915632304:endpoint/GCM/JaybMe/b65794ea-d30d-38a8-8450-e0ff3b877bfc",
Message: "Simple notification message "
}, function(err, data) {
if(err) {
console.error('error publishing to SNS');
context.callbackWaitsForEmptyEventLoop = false;
callback(err);
//context.fail(err);
} else {
console.info('Message published to SNS');
context.callbackWaitsForEmptyEventLoop = false;
callback(null, "SUCCESS");
}
});
console.log('Finished function');
context.callbackWaitsForEmptyEventLoop = false;
callback(null, "SUCCESS");
}
Tested with run time 4.3 and 6.10 but same behaviour
thanks
Sajeev
It reminds me of two possible cases;
First, maybe lambda function terminates itself just before sns client finishes sending the message. you better use await or promise() properties of javascript.
Second, maybe you have put your lambda in a VPC. look at a similar case here.

How to setup Twilio.Device with new token?

By default all tokens generated with the Twilio helper libraries expire after one hour. But you should configure this expiration to be as short as possible for your application.
I am trying to generate a new token each time a user attempts a new connection and try to setup Twilio device. But it creates new device each time. So all Twilio device get incoming call and i can see multiple notification for that. Multiple connections created an dmultiple dtmf sent. I want only one twilio device with fresh token.
Twilio.Device.destroy() method is there but it is not working. What are other option do I have?
How to release/destroy/stop/delete Twilio.Device?
After saving credentials globalTwilioSagaSetup() called and after 58min of that again token is generated and Twilio.Device setup is done.
function globalTwilioSagaSetup()
{
// Get Twilio credentials
// Get Twilio Token
// Setup Twilio Device
// For token re-generation before expire. 58min
setInterval(function(){globalTwilioSagaSetup();},3480000);
}
I've had similar issue although in current version of twilio lib (i.e. 1.2). The thing is that once setup is called ready event is fired but only after first call to the setup method. It means that even if one will initialize device with new token there will be problems with establishing new connection. Therefore calling Twilio.Device.destroy() then setup and then connect (via ready event) solved that issue for me. Here is an example:
srv.connectToTwilio = () => $q((resolve, reject) => {
var connection;
try {
connection = Twilio.Device.connect();
} catch (err) {
$log.debug('Device.connect(): throw', err);
}
if (connection) {
try {
connection.accept(() => {
$log.debug(`Twilio connection.accept.`);
resolve();
});
} catch (err) {
$log.debug('connection.accept(): throw', err);
}
} else {
reject(`Device.connect() did not return connection`);
}
});
srv.connect = (token) => {
return srv.setToken(token).then(() => srv.connectToTwilio());
};
srv.disconnect = () => {
shouldBeConnected = false;
try {
Twilio.Device.activeConnection().disconnect();
} catch (error) {
$log.debug(error);
} finally {
Twilio.Device.destroy();
}
$log.debug(`Twilio disconnect.`);
};

Azure Mobile Services - Getting more user information

I inherited a Windows 8 application that is written with XAML. So in C# when I make this call
user = await MobileServices.MobileService
.LoginAsync(MobileServiceAuthenticationProvider.MicrosoftAccount);
(This is for Azure Mobile Services)
The user object is ONLY giving me the Token and the MicrosoftAccount:..............
In order to get to authenticate people, I need to be able to see WHO is requesting access...
I looking at articles like below, but I seem to be missing something? Is this javascript in the article something I would have to write in Node.js?
Example article:
http://blogs.msdn.com/b/carlosfigueira/archive/2013/12/12/expanded-login-scopes-in-azure-mobile-services.aspx
Currently to be able to get more information about the logged in user, you need to make a second call to the service to retrieve the user info. You don't really need to ask for additional login scopes (the topic of the post you mentioned) to retrieve the user name, since that is given by default for all the providers.
This post should have the code you need to write in the server side (node.js) to get more information about the logged in user. The TL;DR version is given below:
On the server side: add this custom API (I'll call it "userInfo"; set the permission of GET to "user", and all others to admin):
exports.get = function(request, response) {
var user = request.user;
user.getIdentities({
success: function(identities) {
var accessToken = identities.microsoft.accessToken;
var url = 'https://apis.live.net/v5.0/me/?method=GET&access_token=' + accessToken;
var requestCallback = function (err, resp, body) {
if (err || resp.statusCode !== 200) {
console.error('Error sending data to the provider: ', err);
response.send(statusCodes.INTERNAL_SERVER_ERROR, body);
} else {
try {
var userData = JSON.parse(body);
response.send(200, userData);
} catch (ex) {
console.error('Error parsing response from the provider API: ', ex);
response.send(statusCodes.INTERNAL_SERVER_ERROR, ex);
}
}
}
var req = require('request');
var reqOptions = {
uri: url,
headers: { Accept: "application/json" }
};
req(reqOptions, requestCallback);
}
});
}
On the client side, after a successful login, call that API:
user = await MobileServices.MobileService
.LoginAsync(MobileServiceAuthenticationProvider.MicrosoftAccount);
var userInfo = await MobileServices.MobileService.InvokeApiAsync(
"userInfo", HttpMethod.Get, null);
userInfo will contain a JObject with the user information. There is an open feature request to make this better at http://feedback.azure.com/forums/216254-mobile-services/suggestions/5211616-ability-to-intercept-the-login-response.

Categories