Self hosted parse server after-save function - parse-platform

I've configured a self-hosted parse server and I need to use the after-save function. After much researching and testing, I got very confused and have some questions. What I need is to send an email from the parse server (not the app) when a given object is saved.
This is possible with the after-save function, right?
What's the best approach to do that? Where should I add the after-save code?
Parse.Cloud.afterSave("TheObject", function(request) {
//send email!
});
Any help? :) Thanks!

Set up a mail service, like mailgun-js
https://www.npmjs.com/package/mailgun-js
Use cloud code.
var api_key = '[KEY]';
var domain = '[DOMAIN]';
var mailgun = require('mailgun-js')({apiKey: api_key, domain: domain});
Parse.Cloud.afterSave("Event", function(request) {
var data = {
from: 'Excited User <me#samples.mailgun.org>',
to: 'test#test.com',
subject: 'Hello',
text: 'Testing some Mailgun awesomness!'
};
mailgun.messages().send(data, function (error, body) {
});
});

Related

Sending message from Cognito triggers

I want to restrict user sign-ins from Cognito hosted UI. I can see there are triggers in which we can attach lambda, but whenever I change event object inside of lambda, instead of getting my custom message User exceeded limits, I get unrecognizable lambda output error.
Can anyone help me in this or is there any other way to achieve this functionality?
Now,I'm getting this
with this code :
exports.handler = (event, context, callback) => {
if (true) {
var error = new Error("Cannot signin because your signin count is 5");
// Return error to Amazon Cognito
callback(error, event);
}
// Return to Amazon Cognito
callback(null, event);
};
But,I don't want prefix PreAuthentication failed with error,I just want to display my message.
Any help is appreciated.
Currently, there is no way to stop Cognito from adding the prefix because the form is a hosted web UI.
If this is a hard requirement, the workaround is to create your own login form and use the aws-cognito-sdk
Once you make the call to cognitoUser.authenticateUser in the code below the Pre authentication trigger will fire the Lambda function and you will need to handle the error and parse it to remove the unwanted prefix.
Hope this Helps
aws Examples: Using the JavaScript SDK
var authenticationData = {
Username : 'username',
Password : 'password',
};
var authenticationDetails = new AmazonCognitoIdentity.AuthenticationDetails(authenticationData);
var poolData = { UserPoolId : 'us-east-1_TcoKGbf7n',
ClientId : '4pe2usejqcdmhi0a25jp4b5sh3'
};
var userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);
var userData = {
Username : 'username',
Pool : userPool
};
var cognitoUser = new AmazonCognitoIdentity.CognitoUser(userData);
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: function (result) {
var accessToken = result.getAccessToken().getJwtToken();
/* Use the idToken for Logins Map when Federating User Pools with identity pools or when passing through an Authorization Header to an API Gateway Authorizer*/
var idToken = result.idToken.jwtToken;
},
//Your message from the Lambda will return here, you will need to parse the err to remove the unwanted prefix*
onFailure: function(err) {
alert(err);
},
});

How to send message back to device from Lambda function?

Is there any way we can send a message to a device from Lambda function which is invoked by Alexa Skill. The message contains some values collected by Lambda function.
So basically I want to do this:
Device ---> Voice command ---> Alexa Skill --(Trigger)--> Lambda function
Lambda function(collect values) ---- message ---> Device
Is there any example in Java?
Thanks for any pointer/help.
-James
Invoke Alexa device from lambda function is a very similar question, with the answer: "it's not possible YET"
I will elaborate. You can send notifications to all users of a skill such as a new feature, however, you cannot send a notification to a specific user that invokes a function.
To send notifications to all users of an Alexa skill who have notifications enabled, see this design.
Reference this thread for more information on the limitations of sending a notification to a specific user.
What you are asking can be done.
First the voice command does not come from a human from your diagram.
A device talks to Alexa. Alexa invokes or triggers Lambda. Lambda function messages device.
The function inside Lambda is http or https. If your device can handle https or TLS encryption then good. But most of the device are small and have limited computing power, so you will end up using http. As of now 2020, AWS allows http, but a year from now it requires you to use https or TLS 1.3 due to federal regulations. But we don't know until it happens.
Below is a sample of Lambda http post in NodeJS. The trigger data comes in request. So you should know what JSON will come in and extract your data from JSON using the if statement.
NodeJS website has good examples for http.
Now your device is the server. It has to anticipate the Lambda request and process it and reply to Lambda if needed.
Now your device talks and receives information.
const http = require('http');
exports.handler = async (request, context) => {
if (request.directive.header.namespace === 'FromAlexaSkill') {
httpost("This is your data to device", "192.168.1.2");
}
//**********************************************
let httpPost =async (postData, servername) => {
let dataString = '';
const response = await new Promise((resolve, reject) => {
const options = {
hostname: servername,
port: 1777,
path: '/dim',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(postData)
}
};
const req = http.request(options, (res) =>
{
res.setEncoding('utf8');
res.on('data', chunk => {
dataString += chunk;
});
res.on('end', () => {
resolve({
"body":dataString
});
});
});//http.request
req.on('error', (e) => {
console.error("problem with request: "+e.message);
reject({
statusCode: 500,
body: 'Something went wrong!'
});
});
// Write data to request body
req.write(postData);
req.end();
}); //Promise
return response;
};//httpPost
}

Redirect link to distribution slack app

I'm trying to redirect URL to distribute (OAuth 2.0)my slack app with API gateway and lambda function (AWS) but I can't realize how to get the code.
the event that returns is null.
My lambda code :
// Lambda handler
exports.handler = (event, context, callback) => {
var messageTest = {
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
code: event.code
};
var queryTest = qs.stringify(messageTest);
https.get(`https://slack.com/api/oauth.access?${queryTest}`, (res, err) => {
console.log("statusCode: ", res.statusCode);
console.log("headers: ", res.headers);
var data = [];
res.on('data', function(chunk) {
data.push(chunk);
});
res.on('end', function() {
var result = JSON.parse(data.join(''))
console.log(result);
});
});
callback(null);
};
My redirect URL is the lambda URL.
The event that i get is null.
How can i get the "code" from the oAuth 2.0?
Assuming you are using Lambda Proxy integration (and therefore you don't use a Body Mapping Template), the JSON payload that you send to your API Gateway will be received by your Lambda as a stringified JSON in event.body.
So, you'll need to parse that first and you can get your code.
const body = JSON.parse(event.body)
const code = body.code
Reference: Input Format of a Lambda Function for Proxy Integration

Stripe Payments with parse server cloud code

I have this code included in my main.js:
var stripe = require("/cloud/stripe.js")("sk_test_*********");
//create customer
Parse.Cloud.define('createCustomer', function (req, res) {
stripe.customers.create({
description: req.params.fullName,
source: req.params.token
//email: req.params.email
}, function (err, customer) {
// asynchronously called
res.error("someting went wrong with creating a customer");
});
});
After pushing this code to my Heroku server the logs indicate that: Error: Cannot find module '/cloud/stripe.js'
I have also tried var stripe = require("stripe")("sk_test_*********"); but this returns the same error. Whenever I try add this new module to my server the whole server becomes dysfunctional. What workarounds are there to this? Thanks
Have you added Stripe to the requirements of your package.json file for your node project? If so, you should be able to reference it using the term require('stripe') as opposed to what you're doing.
I'll tell you what worked for me, I racked my brain on this for a day. Instead of using Cloud Code to make a charge, create a route on index.js. Something like this in index.js
var stripe = require('stripe')('sk_test_****');
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({
extended: false
}));
app.post('/charge', function(req, res){
var token = req.body.token;
var amount = req.body.amount;
stripe.charges.create({
amount: amount,
currency: 'usd',
source: token,
}, function(err, charge){
if(err)
// Error check
else
res.send('Payment successful!');
}
});
I call this using jQuery post but you could also use a form.

How can I read a local file in Cloud Code as a string?

I'm using Parse Cloud Code.
My system has a welcome message. I use MailGun to send it.
The problem I have is that the message now is an HTML file, so I would like to let the HTML file in my server, read it using Cloud Code and pass that info to MailGun.
Can I read a local text file using Cloud Code and have it in my program as a string?
Should I save that file in my public folder or in the same folder than my cloudcode program?
I'm not confident with MailGun, but I believe it should work like MailChimp or Mandrill. If so, you should be able to store on MailGun your whole HTML template and just have some template_vars to complete.
This is a sample code of our own way to send mail with HTML thanks to the Mandrill system
Parse.Cloud.define("sendMailTemplate", function(request, response) {
var emails = request.params.emails;
var template_name = request.params.template_name;
var template_merge_content = request.params.template_merge_content;
var subject = request.params.subject;
var Mandrill = require('cloud/mandrillTemplateSend.js');
if (subject === undefined) {
subject = 'Mail sent by Mandrill';
body = subject;
}
Parse.Config.get().then(function(config) {
Mandrill.initialize(config.get('Mandrill_key'));
}).then(function() {
_.each(emails, function(email) {
Mandrill.sendTemplate({
template_name: template_name,
template_content: [{
name: template_merge_content.username,
content: ''
}],
message: {
text: '',
subject: subject,
from_email: 'contact#yourdomain.com',
to: [{
email: email,
name: template_merge_content.username
}],
merge_vars: [{
rcpt: email,
vars: template_merge_content
}],
},
async: false
});
});
}).then(function() {
response.success('Success');
}, function(error) {
response.error(error);
});
});
This object template_merge_content is quiet important. It's an object where is saved all the dynamic vars which are send to complete your HTML mail.
According to http://blog.mailgun.com/transactional-html-email-templates/ it seems you have same kind of method to send your mail.
So final advice would be to NOT store your HTML template within any Parse's class, or to save it within https://parse.com/docs/js/api/symbols/Parse.Config.html

Resources