Building an enterprise mobile app using React Native and Realtime - Part 1/3

  • Nov 17, 2015
  • React Native, Code Hosting, Cloud Storage

Summary

Do you want to ensure that your employees, partners and customers can access your enterprise content using their mobile phones? Do you want to notify them with a push notification when you publish new content?

If you do, this tutorial is for you and we're happy to give you the complete source code using the React Native framework. Feel free to fork it and publish your own enterprise mobile content app to the Apple and Google stores: https://github.com/realtime-framework/RCTRealtimeNews

In the Realtime News React Native app, content is stored in Realtime Cloud Storage. Using the new Realtime Code Hosting features we were able to authenticate the users through a RESTful API for increased security and leverage the brand new Cloud Storage triggers to send custom push notifications whenever new content is published.

Currently the Realtime Code Hosting is public preview but we want you to join the party, so just register here to activate your free access. If you want to know more about this new feature checkout the preview guide.

Let’s get started with the Realtime Cloud Storage configuration, the cloud database for our app.


Storage configuration

We are assuming you already signed-up for a Realtime developer account at https://accounts.realtime.co/signup and have a Realtime Cloud Storage subscription. If you haven’t please take a few minutes to go through the subscription process, it’s free and you don’t need to enter any credit card.

As soon as you have your Cloud Storage subscription ready let’s enable the authentication so we can keep our content secure and only accessible to valid users.

Enable authentication

Security is a key feature in any enterprise-grade storage solution and Realtime Cloud Storage gives you the right tools to secure your data. The first thing you must guarantee is that your Cloud Storage application key has the authentication feature turned on. You can turn it on using the Realtime Web Console.

Go to your subscriptions page and click the details link on the Realtime Cloud Storage subscription for which you want to activate authentication.

Enable authentication

Here you can find more information about Realtime Cloud Storage Security

Enable push notifications

In our app we want to send users a push notification whenever we publish a new content. To achieve this goal we’ll use the Realtime Mobile Push Notifications feature of the Realtime Platform.

Realtime Mobile Push Notifications are a great way to keep your mobile users engaged and informed about your app. It'll allow you to send notifications about content and other updates to users when they are not using your app. You can use the Mobile Push Notifications feature on the React Native app. For the iOS apps we’ll use the Apple Notification Service (APNS) and for Android apps we’ll use Google Cloud Messaging (GCM).

To turn this option on just edit your Realtime Messaging Subscription (it was automatically created for you when you subscribed to Realtime Storage) and enter the required data.

Enable push notifications

You can follow this guide for a complete step by step configuration for iOS and Android.


Storage tables structure

As mentioned before our contents will be saved in Realtime Cloud Storage so we need to create a few database tables to keep our data. To create the tables you’ll only need to enter the primary key (and secondary key when applicable), the other fields will be created by the CMS backoffice when new contents are saved.

Here’s the complete table description:

Table Users

This table stores the user authentication credentials. This data is used to perform the login in the app as well as in the backoffice (a simple bootstrap based CMS to help you manage your app’s content).

  • UserName
    - Primary key, String: User name for login in the application
  • Password
    - Password used for authentication

Table Tags

You’ll be able to tag your contents and the TAGS table will keep your available tags. This will be used to provide data filtering as shown in the app section below.

  • Tag
    - Primary key, String: Name of the tag
  • Type
    - Content type, in this app we’ll use "Blog" and "White papers"

Table Contents

This table is used to store the actual contents displayed in the app.

  • MonthYear
    - Primary key, String: the concatenation of the month and year. It’s used to distribute the contents into shards for better scalability
  • Timestamp
    - Secondary key, String: the content creation timestamp
  • Type
    - Content type used for data filtering
  • Body
    - Body will store html/text content if you don’t want to use an external URL (optional)
  • Description
    - The description of the content
  • IMG
    - The image url for the content thumbnail
  • Tag
    - Content tag for data filtering
  • Title
    - The content title
  • URL
    - The external url for the content body (optional)


Here you can find more details about table management.


Create authentication roles

We want to keep our data secure so we need to define the authentication roles so we can give the right permissons to the CMS backoffice and to the app users.

When you define a role you are defining a set of permissions known as policies. Policies are divided into three groups:

  • Database policies: refer to general database operations like create a table or list the existing tables;
  • Table policies: refer to specific tables on your database;
  • Item policies: refer to specific items of specific tables in your database.

For this app we’ve created two distinct authentication roles:

  • BackofficeApp role: Gives permission to the backoffice application to CRUD (create, read, update and delete) the data in the Contents, Tags and Users tables. This provides access to the backoffice app to manage the contents displayed in the mobile apps
  • iOSApp role: Provides read-only access to the Contents and Tags tables

BackofficeApp role

{
	"role": "BackofficeApp",
	"policies": {
		"tables": {
			"Contents": {
				"allow": "CRUD"
			},
			"Tags": {
				"allow": "CRUD"
			},										
			"Users": {
				"allow": "CRUD"
			}
		}
	}
}
							

iOSApp role

{
	"role": "iOSApp",
	"policies": 
		"tables": {
			"Contents": {
				"allow": "R"
			},
			"Tags": {
				"allow": "R"
			}
		}
	}
}
							

You can find more information about authentication roles here.


Code Hosting configuration

As mentioned we want to authenticate our users with a server-side script in order to make the app more secure. For this we’ll create a custom function using the new Realtime Code Hosting feature. We also want to send a push notification whenever a new content is added. For this we’ll create a database trigger also using the new Realtime Cloud Storage triggers powered by Realtime Code Hosting.

In order to create the endpoints for authentication and to send the push notifications we’ll be using scripts coded in JavaScript.

Scripts creation

To create your scripts you need to activate the Code Hosting option for your Realtime Cloud Storage subscription. To find this option, login into Realtime using your credentials and click the EDIT button of your Realtime Cloud Storage subscription.

In the subsctiption edit page turn the Code Hosting option on and click SAVE.

Realtime will start provisioning your private infrastructure to execute your scripts and when it’s ready select the SCRIPTS button to browser your scripts (by default you’ll have a welcome.js script).

In the following sections we’ll show you how to add new scripts (we call it routes since each script will be mapped to a RESTful route that can be invoked externally using any standard REST client).

Authentication script

For authentication you need to create a script that receives the user, password and authentication role. The script checks for a matching user in user table, and verifies if the password matches. If it does it generates an authentication token and uses the Cloud Storage authenticate method to authenticate the token for the specific role. If this process is successful the token is returned to the app in JSON format. The app will use this token to connect securely to the Cloud Storage backend.

Click the ADD ROUTE button, copy the following code into your script editor and save it.

function authenticate(user,password,role,res,req,modules){

    var tableRef = modules.storageRef.table("Users");
    var itemRef = tableRef.item({
	    primary: user
    });

    itemRef.get(
		function success(itemSnapshot) {
			if(itemSnapshot && itemSnapshot.val().Password === password)
			{
			    var token = generateToken();
			    modules.storageRef.authenticate({
	            	authenticationToken: token,
	            	roles:[role],
	            	timeout: 3600 // in seconds	
	            }, 
	            function success(data) { 
	            	console.log(data); 
	            	res.send(200, { "token":token });
	            }, 
	            function error(data) { 
	            	console.error("Error:", data); 
	            	res.send(400, data);
	            });
	            return;
			}else{
			    res.send(404, {"Error":"User or password invalid"});
			}
		}, 
		function error(data) { 
			res.send(400, e);
		});
}

function generateToken(){
    var token = '';
    for (var i = 0; i < 36; i++) {
        token += randomIntInc(1,10)
    }
    return token;
}

function randomIntInc (low, high) {
    return Math.floor(Math.random() * (high - low + 1) + low);
}

							

Make sure you fill the input fields as shown in the following image:

When you’re ready to save the script, click the “COMMIT & PUSH” button. This will push your changes to the underlying Git repo and deploy the code to your private infrastructure.

Push notifications script

To automate the push notifications you need to create a script to be attached to the AFTER PUT trigger in the Contents table. This script will be called automatically whenever a new item is inserted (put) into the Contents database table.

Basically the script will use the sendPushNotification method to call the Realtime Messaging REST API to send a push notification to the subscribed users, passing in the payload the item key and in the alert message the content title.

In order to receive push notifications the application is using the Realtime Messaging framework to subscribe the channel notifications.

Just copy the following code into your script editor and proceed just like you’ve done with the authenticate script. Make sure you name the script sendPush, select the POST method, check the “Pass request argument” and “Pass the modules argument” checkboxes.

function sendPush(res,req,modules){
    var item = req.body.item;
    
    modules.storageMule.Realtime.sendPushNotification({
            applicationKey: 'YOUR_APP_KEY',
            privateKey: 'YOUR_PRIVATE_KEY',        
            channel: 'notifications',
            message: item.Title,
            payload:'{\"sound\" : \"default\",\"badge\" : \"1\",\"Type\" : \"'+item.Type+'\",\"Timestamp\" : \"'+item.Timestamp+'\"}'
    }, function(err){
            if(err){
                res.send(400, 'Error ' + err);
            } else {
               res.send(200, 'Notification has been sent');            
            }
    });
}
							

After these steps your scripts page should look the following image:

Enabling the after put table trigger

After the script is created we need to attach it to the after put trigger in Contents table. To do this edit the Contents table, select the sendPush script in the Put After trigger dropdown and click submit. From this moment on the Realtime Cloud Storage backend servers will execute the sendPush script whenever a new item is inserted successfully into the Contents table. Simple but powerful, right?

FirstMonthYear script

In order to allow better scalability for our database and also to allow an optimized implementation of infinite scroll, we had to shard our contents using a time-series grouping. We have selected the month and year of the content creation to be our shard key (but it could also be the day or even the year week).

In the app we'll start by requesting the current month (and year) contents, with a limit of 5 items, and when the user reaches the end of the scroll, the app will retrieve another batch of 5 items from the same month. If none are available it will request items from the previous month, and so on until the first month in the database is reached (and the scroll stops). To better optimize the app we’ve decided to create an endpoint that lets the app know in advance the month and year of the first content (no other contents before that, so there's no need to continue scrolling). This endpoint is called FirstMonthYear and the code is shown below (make sure you select the POST method before you commit it).

function firstMonthYear(res){
	res.send(200, {"firstMonthYear":"01/2015"});
}
							

Using swagger for script testing

The Realtime Code Hosting console provides a nice swagger interface for script testing.

Click the SWAGGER button in your Cloud Storage console and expand the authenticate operation by clicking its name. You’ll see the user, password and role parameters text-boxes. Just enter some data, valid or invalid, and click the TRY IT OUT! button.

When you click the TRY IT OUT! button a REST call is performed to the Realtime Code Hosting backend that will redirect the request to one of your infrastructure mules that will execute your script and return the result. Here you can find more about the Code Hosting Mules.


And that’s it for the backend configuration.

Now let’s move forward to the client application tutorial

If you find this interesting please share: