Posted on by

Welcome back !!

In this blog, we are going to dig deeper into back-end of Firebase.

When we write custom back-end service for any app, that involves API service and data store. API service could be Spring Boot or Play Framework, which handles user authentication, user authorization, data validation and performing business logic. Data store such as MySQL or MongoDB provides data structure, indexing mechanism, aggregation functions and data import/export tools.

Firebase handles all above tasks through different services.

User Authentication – handled by Firebase Authentication Service.

Business Logic – We need to write in typescript code.

Import/Export – Firebase has tools for importing and exporting data.

Aggregate Function – Firebase does not have native support for this.

User Authorization – Handled by Firebase Security Rules.

Data Validation – Handled by Firebase Security Rules.

Indexing – Handled by Firebase Security Rules.

In this blog post, we will cover Firebase security rules.

There is a very informative blog on basics of Firebase security rules available at following link

https://code.tutsplus.com/articles/quick-tip-firebase-database-security-rules–cms-27926

I recommend you to read this blog to get good understanding of Firebase security rules.

Security Rules

Let’s define security rules for Inventory App.

There will be two type of users – Admin & Simple User All authorized users can access inventory items Only Admin can add new item in inventory list Item cost can only be numeric All authorized users can see inventory requests Simple user can request for inventory item Only admin can approve or decline user request

First Rule

“There will be two type of users – Admin & Simple User”

First remove read and write access from all users.

{ "rules": { ".read": false, ".write": false } }

Open the Inventory App in browser.

If you click in any of component link, you will see permission denied error in browser console.



To distinguish admin and simple user, I have created another data node $ref named “roles” which contains {“auth.id” : “role”}

Example data:

"roles" : { "slJH9Jl9rvuTjKnYMFZ54WiYeA3" : "admin" }

So we have implemented first rule.

Second Rule

“All authorized users can access inventory items”

{ "rules": { ".read": false, ".write": false, "items": { ".read": "auth != null", /*Only Authorized users*/ } } }

Click on Manage page, it should display inventory items.

Third Rule

“Only Admin can add new item in inventory list”

{ "rules": { ".read": false, ".write": false, "items": { ".read": "auth != null", /*Only Authorized users*/ ".write": "root.child('roles').child(auth.uid).val() === 'admin'", /*Only Admin users*/ } } }

Fourth Rule

“Item cost can only be numeric”

{ "rules": { ".read": false, ".write": false, "items": { ".read": "auth != null", /*Only Authorized users*/ ".write": "root.child('roles').child(auth.uid).val() === 'admin'", /*Only Admin users*/ "$iId": { "cost": { ".validate": "newData.isNumber()" } } } } }

Fifth Rule

“All authorized users can see inventory requests”

{ "rules": { ".read": false, ".write": false, "items": { ".read": "auth != null", /*Only Authorized users*/ ".write": "root.child('roles').child(auth.uid).val() === 'admin'", /*Only Admin users*/ "$iId": { "cost": { ".validate": "newData.isNumber()" } } }, "requests": { ".read": "auth != null", /*Only Authorized users*/ ".indexOn": "status", } } }

Sixth Rule

“Simple user can request for inventory item”

{ "rules": { ".read": false, ".write": false, "items": { ".read": "auth != null", /*Only Authorized users*/ ".write": "root.child('roles').child(auth.uid).val() === 'admin'", /*Only Admin users*/ "$iId": { "cost": { ".validate": "newData.isNumber()" } } }, "requests": { ".read": "auth != null", /*Only Authorized users*/ ".indexOn": "status", "$rId": { ".write": "(auth != null && !data.exists() && newData.child('status').val() === 'new')" } } } }

Simple user can only create request means he/she cannot update existing data.

!data.exists() – this method will check if data is insert or update and also simple user can submit

newData.child(‘status’).val() === ‘new’ – All user to add only new request.

Seventh Rule

“Only admin can approve or decline user request”

{ "rules": { ".read": false, ".write": false, "items": { ".read": "auth != null", /*Only Authorized users*/ ".write": "root.child('roles').child(auth.uid).val() === 'admin'", /*Only Admin users*/ "$iId": { "cost": { ".validate": "newData.isNumber()" } } }, "requests": { ".read": "auth != null", /*Only Authorized users*/ ".indexOn": "status", "$rId": { ".write": "(auth != null && !data.exists() && newData.child('status').val() === 'new') || root.child('roles').child(auth.uid).val() === 'admin'" /*Only Admins can update request*/ } } } }

With above rule json, we have satisfied all our prerequisites.

Our MVP is ready. You can access full source code at git

In next blog, we will deploy our inventory app code on Firebase hosting.Till then you can visit and practice on my inventory app hosted on Firebase.

Click on the following link-

https://inventory-app-726af.firebaseapp.com/

Keep looking to this space for next blog.

Cheers..!!!