I have an android app in which I send push notification using firebase admin sdk with nodejs.
I was able to send notification from the nodejs raw script when I ran the script.
However, I just built an admin dashboard for sending notification to the app with angular 6 but don't know how to integrate the nodejs script with the new angular app so that I can send notification from the angular app by just a click.
I'd also encourage new ideas on how best to to this.
attached is a screenshot from the nodejs admin script
Setup your node to behave as API server, using Express for example.
Wrap your script as Express module (named send-message.js), basically just make that a function that you export:
const sendMessage = (...params) => {
//your send message logic, I would do copy paste of your code here however it is an image
}
module.exports = sendMessage;
Well and then setup API route that calls the script:
var express = require('express')
var sendMessage = require('./send-message')
var app = express()
app.get('/send-message', function (req, res) {
sendMessage(....);
res.status(200).end();
})
app.listen(3000)
And finally in Angular use HttpClient to call the API.
I finally solved the problem by using firebase cloud functions.
First I set up cloud functions on firebase with this guide
Then I created a cloud function named sendNotification() which is triggered each time new objects are inserted to the firebase realtime database.
Then I placed my existing notification code inside sendNotification() function
Deployed the function to my firebase console
Then hurray, the notification was sent to my device after some db triggers
`
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
//This functions listens to the node '/Food menu/date/Food' for new insert and sends notification to a client
exports.sendNotification = functions.database.ref('/Food menu/date/Food')
.onCreate((snapshot, context) => {
//place your client app registration token here, this is created when a user first opens the app and it is stored in the db.
//You could also retrieve the token from the db but in this case it is hard coded
var registrationToken = "{my-registration-token}";
//This is the payload for notification
var payload = {
data: {
'title': 'Tomorrow\'s Menu',
'message': 'Hello, kindly check the menu available for today',
'is_background': 'true',
'image': 'http://www.allwhitebackground.com/images/3/3430.jpg',
'timestamp': '234'
}
};
// Send a message to the device corresponding to the provided
// registration token.
admin.messaging().sendToDevice(registrationToken, payload)
.then((response) => {
// Response is a message ID string.
console.log('Successfully sent message:', response);
//return a promise here since this function is asynchronous
return "Yes";
})
.catch((error) => {
console.log('Error sending message:', error);
});
//return snapshot.ref.parent.child('uppercaseFood').set(uppercase);
});
`
After this, you run firebase deploy --only functionsto deploy the cloud function
Read this guide for more info on cloud functions
Related
I want to implement firebase cloud messaging via firebase cloud function so that I can send message to every users which have installed my android application. The message would be a value of a key of json object from this url <[https://coronavirus-19-api.herokuapp.com/countries/bangladesh]>.
Click the text below to see the image of json object
json object
In my case, I want to send the value of the key "todayDeaths" through firebase cloud message. When I try to call the json by api method and fetch the data of it and set this in message in index.js file, it showed no error and deploy created. But when I try to check the status of my function ,it shows error.
Click the text below to see the image of error showed in Logs of firebase cloud function.
firebase cloud function Logs.
I will add the index.js code below:
const functions = require("firebase-functions");
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.scheduledFunction = functions.pubsub.schedule('every 2 minutes').onRun(async (context)
=> {
const response=await axios.get(
'https://coronavirus-19-api.herokuapp.com/countries/bangladesh'
);
console.log(response.data);
const body=response.todayDeaths;
const message = {
notification: {
'title': 'Today death',
'body': body,
},
topic:'allUser'
};
admin.messaging().send(message)
.then(response=>{
console.log("Successfully sent",response);
}).catch(error=>{
console.log("failed",response);
});
console.log('This will be run every 2 minutes!');
return null;
});
How can I solve the problem so that the firebase cloud messaging successfully send the message to all of the users of the project?
It looks like you just forgot to import axios.
Add this to the top:
const axios= require('axios');
I am using Firebase Cloud Functions with Express and Firebase Hosting to serve my multi-page site. I have successfully implemented server-side cookies as explained here and as implemented below:
function verifyLogin(request, response, next) {
const sessionCookie = request.cookies.__session || '';
firebase.auth().verifySessionCookie(sessionCookie, true /** checkRevoked */ )
.then((decodedClaims) => {
//serve content for user
return next();
}).catch(error => {
// Session cookie is unavailable or invalid. Force user to log in.
console.log(error);
response.redirect('/login');
return;
});
}
app.get('/', verifyLogin, (request, response) => {
var page_title = "Home";
response.render('index', {
page_title,
});
});
I am using the Firebase Web SDK (JavaScript) to access the Firebase Cloud Firestore. In order to do this, I need to get the idToken on the client side for the currently-logged-in user, like so:
firebase.auth().onAuthStateChanged(firebaseUser => {
if (firebaseUser) {
firebase.auth().currentUser.getIdTokenResult()
.then((idTokenResult) => {
// Access the Firebase Cloud Firestore here
});
}
});
This seems redundant to me, since I already know which user is signed in via my server cookie, but how else can I get the idToken without another call to Firebase Auth?
Is there a way to extrapolate it from my session cookie somehow and pass it to my client from my cloud function as a variable?
Or is there another way to look at this philosophically that I am overlooking?
In the same way you can listen to user sign-in state changes using onAuthStateChanged(), you can also listen to user ID token changes using onIdTokenChanged(). You will only need to use a new token when the observer you attach shows that a new one appears (for example, when it's refreshed every hour by the SDK).
I'm using only the Real-Time Database part of Firebase.
I have a Python Firebase admin on the server, a Javascript Firebase on the web client. No Android or iOS. My web Javascript client receives a token from the Python server for its authentication.
Only the Python server writes to Firebase, the Javascript client never does. But the client registers a "child_added" listener with Firebase to receive database changes in data.
Everything works except for this event listener.
The Firebase docs say:
The Python Admin SDK currently only supports blocking reads. It cannot
be used to add event listeners that receive realtime update
notifications.
But as I understand it, that applies to my server, not the client. Or does getting a custom token from a Python Admin disqualify the Javascript client for these events?
Maybe it's a problem that the server initializes itself with service account credentials, while the client does so with an api key? If so, why doesn't Firebase issue an error?
Here's the relevant Python code (views.py):
import firebase_admin
from firebase_admin import credentials, auth, db
def getFirebaseInstance():
try:
# using fresh download of key from service account for this app
cred = credentials.Certificate('myapp/static/myap/firebase/firebase-adminsdk-4mcup-144fd3c404.json')
firebase = firebase_admin.initialize_app(cred,{'databaseURL': 'https://my-db-url'})
except:
raise
#login_required()
def firebaseClientToken(request):
try:
global __firebase
if __firebase is None:
__firebase = getFirebaseInstance()
token = firebase_admin.auth.create_custom_token('1')
return HttpResponse(token)
except Exception as err:
return HttpResponse("System error:" + str(err), status=406)
def sendToFirebase(request, data):
try:
global __firebase
if not __firebase:
__firebase = getFirebaseInstance()
db = firebase_admin.db
ref = db.reference("messages/")
ref.push(json.dumps(data))
except Exception:
raise
All that works fine as far as the server being able to write to firebase and for generating a custom Token.
The javascript web client receives a token from the Python server (not shown), and registers the event listener with:
(
function authClient2Firebase() {
var waiting;
$.ajax({
url: "firebaseClientToken/",
method: "POST",
success: function(response) { step2(response); },
error: function(xhr) { alert(xhr.responseText); }
});
function step2(customToken) {
try {
firebase.auth().signInWithCustomToken(customToken).catch(function(error) {
var errorCode = error.code;
var errorMessage = error.message;
alert(errorMessage + ' code:' + errorCode);
});
var db = firebase.database();
var fbRef = db.ref("myapp");
fbRef.startAt(loadTransaction.time).on ( "child_added",
function(snapshot) { alert(snapshot.val()); });
}
}
}
)();
It doesn't have to do with tokens or authentication at all, but with a difference between the push(data) command in the Firebase Python and Javascript SDK vs. their documentation.
See the accepted answer at:
Why does Firebase event return empty object on second and subsequent events?
I am using the Node.js Admin SDK within a Cloud Function for Firebase and I want to call the admin.auth().getUserByEmail() method.
Since I'm using a Cloud Function I read here that I only need to call admin.initializeApp(functions.config().firebase); which you can see below I've done.
However, when I call the getUserByEmail() (only tested locally) I get the following error:
'No Firebase project was found for the provided credential.'
Here's my index.js
'use strict';
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.hello = functions.https.onRequest(function (req, resp) {
var from = req.body.sender;
admin.auth().getUserByEmail(from)
.then(function (userRecord) {
// See the UserRecord reference doc for the contents of userRecord.
console.log("Successfully fetched user data:", userRecord.toJSON());
})
.catch(function (error) {
console.log("Error fetching user data:", error);
})
});
Has anyone got any experience of this and can tell me what I'm doing wrong?
The admin sdk won't get proper config json if you are using localy(in google cloud functions emulator). You have to use your service account json obtained from firebase console.
But if you have deployed it, your method will work just fine.
I just configured my first Cloud Functions for Firebase and after deploying the index.js file and upload all the changes to my server. I'm trying to use one of my functions which is a simple HTTP request to create a field on a table in my Firebase Database:
const functions = require('firebase-functions');
exports.addMessage = functions.https.onRequest((req, res) => {
// Grab the text parameter.
const original = req.query.text;
// Push it into the Realtime Database then send a response
admin.database().ref('/messages').push({ original: original }).then(snapshot => {
// Redirect with 303 SEE OTHER to the URL of the pushed object in the Firebase console.
res.redirect(303, snapshot.ref);
});
});
But when I'm calling to my request on my browser I'm receiving an error on my Functions console which says admin is not defined:
What might be causing this error?
You need to import the Admin SDK module just like you are importing the Cloud Functions SDK:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
Example code can be found here. This is also covered in the "get started" guide.