Welcome Back Friends !! Hope you all have been following the blog series.
To recap briefly, we have implemented the Firebase features like Firebase Authentication, Firebase Database and Firebase hosting in previous blogs. In this blog post, we will explore another Firebase feature – Firebase Cloud Functions.
Firebase Cloud Functions uses Google Cloud Functions which is very similar to AWS Lambda.
Check out official documentation to understand basics of Firebase Cloud Functions.
USE CASE
Application should send an email to user once his/her request has been approved by admin.SOLUTION
Firebase does not provide any in-built solution to fulfil our use case however it does provide Cloud Function API where we can write our own backend logic. Our backend logic would be –- Listen to any changes for request object.
- If status changed to “approved”, then send an email to user.
- Else ignore changes.
CLOUD FUNCTIONS
Install Firebase tools
sudo npm install -g firebase-tools
firebase init functions
=== Functions Setup A functions directory will be created in your project with a Node.js package pre-configured. Functions can be deployed with firebase deploy. <img draggable="false" data-mce-resize="false" data-mce-placeholder="1" data-wp-emoji="1" class="emoji" alt="<img draggable="false" role="img" class="emoji" alt="✔" src="https://s.w.org/images/core/emoji/13.0.1/svg/2714.svg">" src="https://s.w.org/images/core/emoji/72x72/2714.png"> Wrote functions/package.json <img draggable="false" data-mce-resize="false" data-mce-placeholder="1" data-wp-emoji="1" class="emoji" alt="<img draggable="false" role="img" class="emoji" alt="✔" src="https://s.w.org/images/core/emoji/13.0.1/svg/2714.svg">" src="https://s.w.org/images/core/emoji/72x72/2714.png"> Wrote functions/index.js ? Do you want to install dependencies with npm now? Yes
This will create another directory in inventory-app root directory named ‘functions’.
Go inside the functions directory and install node package for mailgun
npm install mailgun-js --save
INDEX.JS
We have to write all our Cloud Functions code in index.js
const functions = require('firebase-functions'); const apiKey = 'key-mailgun-account-key'; const domain = 'sandboxab1173eb6ab04b16b240e6982f1ff69f.mailgun.org'; const mailgun = require('mailgun-js')({apiKey, domain}) exports.sendApprovalEmail = functions.database.ref('requests/{key}').onWrite(event => { if (!event.data.exists() || event.data.val().status != "approved") { return; } var request = event.data.val(); var data = { subject: 'Request Approved', html: `<p>Request Approved for ${request.itemId}</p>`, to: request.email }; mailgun.messages().send(data, function (error, body) { console.log(body) }) })
Let’s try to understand above code,
– exports.sendApprovalEmail is name of our function.
– functions.database.ref(‘requests/{key}’).onWrite – This means whenever there is write on requests/{key} node, sendApprovalEmail function will be invoked.
– event.data is snapshot of written object
– We can extract requestId and email from request object (event.data.val()) to send an email.
After code development, we need to deploy function to Firebase Cloud
Go to root directory of inventory-app and run
firebase deploy --only functions
TESTING
Open your app in browser.
Approve any item request.
Requester should get an approval email.
You can check Cloud Function logs in Firebase as well
Firebase Console -> Your App -> Functions -> Logs
BILLING ERROR
If you get below error –
Billing account not configured. External network is not accessible and quotas are severely limited. Configure billing account to remove these restrictions.
Then you need to enable billing for Google Compute Platform.
Enable the billing and run your tests.
Great work, we have pushed our Cloud Function and it is running perfectly fine.
FIREBASE-ADMIN
We would like to add more meta information like Item Name in approval email. In this case, we have to join request data with item data. Cloud Function provides firebase admin sdk, which have full control over Firebase Database.
New sendApprovalEmail function would be –
// The Firebase Admin SDK to access the Firebase Realtime Database. const admin = require('firebase-admin'); admin.initializeApp(functions.config().firebase); const apiKey = 'key-mailgun-account-key'; const domain = 'sandboxab1173eb6ab04b16b240e6982f1ff69f.mailgun.org'; const mailgun = require('mailgun-js')({apiKey, domain}) exports.sendApprovalEmail = functions.database.ref('requests/{key}').onWrite(event => { if (!event.data.exists() || event.data.val().status != "approved") { return; } var request = event.data.val(); var itemRef = admin.database().ref('items/' + request.itemId); itemRef.once('value').then(function(snapshot) { var data = { subject: 'Request Approved', html: `<p>Request Approved for ${snapshot.val().name} , Request ID - ${request.itemId}</p>`, to: request.email }; mailgun.messages().send(data, function (error, body) { console.log(body) }); }); })
Deploy this new function on Firebase Cloud.
User should now receive an approval email with item name.
Cloud Function is easy, isn’t it? You can do a lot more with it.
Check out this link for other use cases.
In the next blog post, we will implement another useful Firebase Service “Firebase Storage.”
Keep checking this space for the next blog.
Cheers..!!!