Firebase Notifications to iOS topic via HTTP POST request - ios

So we are using Firebase to send notifications to our users on our iOS app. It works great in the console, but now we are looking to allow a few more people to send notifications, and we don't really want them signing into Firebase to do that. One solution we came up with is to put a form on our website and let them sign in and send notifications from there, but we can't get it to work. The code below is a stripped down version of what we have right now. It uses the cloud messaging API to send an HTTP POST request to a specific topic and Firebase responds with a message_id, however no message is delivered on any of the devices.
<!DOCTYPE html>
<html>
<body>
<input id="title"></input>
<input id="message"></input>
<button>Submit</button>
</body>
<script src="https://code.jquery.com/jquery-1.12.2.min.js" integrity="sha256-lZFHibXzMHo3GGeehn1hudTAP3Sc0uKXBXAzHX1sjtk=" crossorigin="anonymous"></script>
<script>
$("button").click(function () {
var title = $("#title").val();
var message = $("#message").val();
var param = {
"to" : "/topics/myTopic",
"content_available" : true,
"notification" : {
"title" : title,
"body" : message
}
};
$.ajax({
url: 'https://fcm.googleapis.com/fcm/send',
type: "POST",
headers: { 'Authorization': 'key=<myKey>', 'Content-Type': 'application/json' },
data: JSON.stringify(param),
success: function () {
alert("success");
},
error: function(error) {
alert("error: "+error);
}
});
});
</script>
</html>
Solution:
After we played around with it a bit more, we found that content_available should really be false in order to actually display a notification in our app. We also made sure to implement jQuery variables correctly. You can see our improved script for handling everything below.
$("button").click(function () {
// Grab the input values
$title = $("#title").val();
$message = $("#message").val();
// Verify that the message is not left empty
if ( $message.length < 2 ){
// Message is empty
return;
}
// Create the JSON object
var paramaters = {
"to" : "/topics/test",
"content_available" : false,
"notification" : {
"title" : $title,
"body" : $message
}
};
// Send request
$.ajax({
url: 'https://fcm.googleapis.com/fcm/send',
type: "POST",
headers: { 'Authorization': 'key=$key', 'Content-Type': 'application/json' },
data: JSON.stringify(paramaters),
success: function (e) {
// Process succeeded
console.log(e);
},
error: function(error) {
// Display error message
}
});
});
We also made sure that our server keys were not included directly in our code as Frank mentioned in his comment. Everything now works and we are successfully receiving notifications.

Related

How to send 400KB video back to server on "onpagehide" call

Issue
I have a MediaRecorder video of up to 400 KB that I need to send to the server.
I want to be able to also send the video when someone exits the page.
My code looks kind of like this:
window.onpagehide = (e) => {
e.preventDefault();
var blob = new Blob(this.data, {type: "video/mp4"});
var file = new File([blob], "recording");
var formData = new FormData();
formData.append("recording", file);
axios.post('my-site-url', formData)
.then(function (response) {
if(response.data.result) {
console.log("email has been sent")
} else {
console.log("failed to send email")
}
})
.catch(({response}) => {
console.log("an error occured during email call");
console.error(response);
})
return null;
}
However window.onpagehide doesn't allow async functions so axios.post isn't running at all.
NB: this issue is tested only on IOS Safari.
For Chrome and Edge I am using onbeforeunload and it works fine
Question
What synchronous axios.post alternative can I use for this scenario?
What I tried
navigator.sendBeacon
It looked pretty promising, but it has a limit of 64KB, so I couldn't rely on it.
fetch
fetch('my-site-url', {
method: 'POST',
body: formData
});
error message:
Fetch API cannot load my-site-url due to access control checks.
ajax
$.ajax({
type: 'POST',
async: false,
url: "my-site-url",
data: formData,
processData: false,
timeout: 5000,
});
error message:
XMLHttpRequest cannot load my-site-url due to access control checks.
XMLHttpRequest
var request = new XMLHttpRequest();
request.open('POST', 'my-site-url', false);
request.send(formData);
if (request.status === 200) {
console.log("success!");
}
error message:
XMLHttpRequest cannot load my-site-url due to access control checks.
But these are not CORS related issues, as they only happen when inside onpagehide on Safari.

Office 365 api draft flag

I have an Office 365 extension that provides its own "Send" button which does some custom processing of the "draft" email and sends it through other means (ie not Office 365 Web). Since the email isn't sent by Outlook it never makes it to the sent folder (which makes sense). I would like to take that draft email and move it to the sent folder and remove the draft flag so it looks like it was sent by Outlook 365 Web.
var getMessageUrl = Office.context.mailbox.restUrl + '/v2.0/me/messages/' + itemId;
var data = JSON.stringify({ 'ToRecipients': [{ 'EmailAddress': { 'Address': 'sheprts#cox.net', 'Name': 'Katie Jordan' } }], 'IsRead': true, 'IsDraft': false });
$.ajax({
url: getMessageUrl,
type: 'PATCH',
dataType: 'json',
headers: { 'Authorization': 'Bearer ' + accessToken, 'Content-Type': 'application/json' },
data: data
})
})
.done(function (item) {
})
.fail(function (error) {
var err = ""
});
The request above works fine except the changing of the draft flag. If this isn't the solution what else can I do? I need to get a draft email into the sent folder as "Not" a draft.
Unfortunately you cannot create non-draft messages using the API.
Change your "other means" and set the "SaveInSentFolder" flag; or change to SMTP for your "other means".

sending notification using firebase admin sdk not working

I am trying to send notification from Node.js server to an ios application. It seems working if I send notification from Firebase console, but isn't working if try from my node.js server using firebase-admin sdk.
I followed tutorial from https://firebase.google.com/docs/cloud-messaging/admin/send-messages.
One thing I do not understand is the response after sending notification seems working. I get below response.
{
"results": [
{
"messageId": "0:1511109840587284%a63b4c28f9fd7ecd"
}
],
"canonicalRegistrationTokenCount": 0,
"failureCount": 0,
"successCount": 1,
"multicastId": 7436388871122493000
}
Does anyone know what I am doing wrong?
-- Edit
Here is the code that sends the notification. admin is the firebase-admin instance.
router.post('/notify', (req, res) => {
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "<database>.firebaseio.com"
});
var registrationTokens = [
'tokenFromIosApp'
];
var payload = {
data : {
body : 'TEST'
}
};
admin.messaging().sendToDevice(registrationTokens, payload)
.then((response) => {
console.log('Sent successfully.\n');
console.log(response);
res.status(statusCodes.Ok);
res.json(response);
})
.catch((error) => {
console.log('Sent failed.\n');
console.log(error);
res.status(statusCodes.InternalServerError);
res.json(error);
});
});
To send a notification, the payload must use the notification key:
var payload = {
notification: {
title: 'My Title',
body : 'TEST'
}
};

auth0 invalid token toward Rails API

I'm trying to set up authentication using the Auth0 lock along with a React single page app and a Ruby on Rails API.
import React from 'react';
import Auth0Lock from 'auth0-lock';
var Login = React.createClass({
componentWillMount: function() {
this.lock = new Auth0Lock('*************', '****.eu.auth0.com', {
allowedConnections: ['facebook']
});
this.lock.on('authenticated', this._doAuthentication.bind(this));
},
showLock: function() {
this.lock.show();
},
_doAuthentication(authResult) {
console.log('Bearer '+authResult.idToken);
var request = require("request");
var options = { method: 'POST',
url: 'http://localhost:3000/authenticate',
headers: { authorization: 'Bearer '+authResult.idToken } };
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
console.log(authResult);
this.setToken(authResult.idToken)
},
login() {
this.lock.show()
},
loggedIn() {
return !!this.getToken()
},
setToken(idToken) {
localStorage.setItem('id_token', idToken)
},
getToken() {
return localStorage.getItem('id_token')
},
logout() {
localStorage.removeItem('id_token');
},
render: function() {
return (
<div className="login-box">
<button className="btn btn-success" onClick={this.showLock}>Sign In</button>
</div>);
}
});
export default Login;
This code comes from the Auth0 documentation. I also configured knock on the Rails API. Still, whenever I click on the "Connect via Facebook" button, I get the following:
- my token is generated (It's a valid token)
- Request is sent, with the correct authorization header
- Rails returns a 401
I made sure Rails receives the header as "Bearer [MY TOKEN]", still getting a 401.
Did I miss something ? Is anything else required ?
Ok, finally found out: my secret was not 64base encoded, which means the JWT.base64url_decode in my knock.rb was not necessary. I removed it, and voila.

Mailgun: Sending image using parse cloud code

I have a code defined as
Parse.Cloud.define("mailgunSendMail", function(request, response) {
var Mailgun = require('mailgun');
Mailgun.initialize('photoshare.com', 'APPKey');
Mailgun.sendEmail({
to: "toTestUser#mail.com",
from: "fromTestUser#mail.com",
subject: "Hello from Cloud Code!",
text: "Using Parse and Mailgun is great!",
attachment:"ZXhhbXBsZSBmaWxl"
}, {
success: function(httpResponse) {
console.log(httpResponse);
response.success("Email sent!");
},
error: function(httpResponse) {
console.error(httpResponse);
response.error("Uh oh, something went wrong");
}
});
});
Mail was sent successfully and recipient got the mail but the attachment is missing. How can i send attachment in the form of data?
According to parse, at this point there is no way to send attachments in an email. Check this link
However, if you can include your image file in your HTML code like this if this serves your needs.
html: '<html><body style="text-align:center;"><img border="0" src="http://files.parse.com/6ffa6b80-d0eb-401f-b663-22d4a16df004/bfed9ac4-058c-41fc-a0f1-fb6155572c12-ad77a082-453f-42f7-94ef-40c3f3e885e6.png" alt="Pulpit rock" width="300" height="150"></body></html>'
Subash answer is right. I just edited to my question:
Parse.Cloud.define("mailgunSendMail", function(request, response) {
var Mailgun = require('mailgun');
Mailgun.initialize('photoshare.com', 'AppKey');
Mailgun.sendEmail({
to: "toTestuser#mail.com",
from: "fromTestUser#mail.com",
subject: "Hello from Cloud Code!",
text: "Using Parse and Mailgun is great!",
html: '<html><body><img src="' + request.params.imageUrlKey + '"></body></html>' }, {
success: function(httpResponse) {
console.log(httpResponse);
response.success("Email sent!");
},
error: function(httpResponse) {
console.error(httpResponse);
response.error("Uh oh, something went wrong");
}
});
});
Where imageUrlKey is a parameter key which contains image url.

Resources