Setting Up A Parse Server As An Alternative Backend
Tags: parse, api, node, backend
Published: 2020-09-24 16:23:09

---
title: Setting Up A Parse Server As An Alternative Backend
published: true
description: Parse is a full-fledged mobile backend platform that can be self-hosted. Follow our tutorial to understand how it works and how to set it up.
tags: parse, api, node, backend
canonical_url: https://blog.jscrambler.com/setting-up-a-parse-server-as-an-alternative-backend/
cover_image: https://blog.jscrambler.com/content/images/2020/09/jscrambler-blog-setting-up-a-parse-server-as-an-alternative-backend.jpg
---

Sometimes, we encounter situations when it's not feasible to develop a full-fledged backend from the ground up. In such situations, we rely on services like [Firebase](https://blog.jscrambler.com/integrating-firebase-with-react-native/?utm_source=dev.to&utm_medium=referral&utm_campaign=parse-server) to speed up development.

Parse is an open-source mobile Backend As a Service (mBAAS) platform. Previously, Parse was a backend platform similar to Firebase. In 2016, Facebook open-sourced the platform code and sunsetted their hosting services. In this article, we will be taking a brief look at Parse and seeing how it allows us to deploy applications quickly.
    
## Overview
[Parse](https://parseplatform.org/) is a full-fledged backend with support for REST API and GraphQL which can be self-hosted. It is open source and is being actively maintained by communities.

It has SDKs available for iOS, Android, JavaScript, and other platforms, as well as support for Push Notifications including campaigns, out-of-the-box user management, support for [OAuth providers](https://docs.parseplatform.org/parse-server/guide/#oauth-and-3rd-party-authentication) (including Facebook, Twitter, Google, GitHub, and LDAP), support for Docker, deployment options to various [platforms](https://github.com/parse-community/parse-server/wiki#community-links) (including AWS and Heroku), as well as support for different storage adapters.

Parse is extensible with webhooks, jobs, and config, and has quite a few community plugins. You can use it together with Express.js.

## Setting up Parse 

Parse requires Node 8+, MongoDB or PostgreSQL to set up. On UNIX like systems, it's advisable to use NVM for Node.js installations. The steps are as follows:

```bash
npm install -g parse-server mongodb-runner
mongodb-runner start
parse-server --appId APPLICATION_ID --masterKey MASTER_KEY --databaseURI mongodb://localhost/test
```

We can also use Docker to start Parse:

```bash
git clone https://github.com/parse-community/parse-server
cd parse-server
docker build --tag parse-server .
docker run --name my-mongo -d mongo
docker run --name my-parse-server -v cloud-code-vol:/parse-server/cloud -v config-vol:/parse-server/config -p 1337:1337 --link my-mongo:mongo -d parse-server --appId APPLICATION_ID --masterKey MASTER_KEY --databaseURI mongodb://mongo/test
```
`APPLICATION_ID` is the name of the application and can be user-generated. `MASTER_KEY` is a key that can override all permissions. Other parameters are listed below:

- `databaseURI`: Connection string URI for your MongoDB.
- `cloud`: Path to your app’s Cloud Code.
- `appId`: A unique identifier for your app.
- `fileKey`: A key that specifies a prefix used for file storage. For migrated apps, this is necessary to provide access to files already hosted on Parse.
- `masterKey`: A key that overrides all permissions. Keep this secret.
- `clientKey`: The client key for your app. (optional)
- `restAPIKey`: The REST API key for your app. (optional)
- `javascriptKey`: The JavaScript key for your app. (optional)
- `dotNetKey`: The .NET key for your app. (optional)
- `push`: An object containing push configuration. See Push
- `filesAdapter`: An object that implements the FilesAdapter interface. For example, the S3 files adapter
- `auth`: Configure support for 3rd party authentication.
- `maxUploadSize`: Maximum file upload size. 

And that's it! We have a Parse backend running successfully in minutes. 

For convenience, we can install the Parse dashboard - a visual admin panel for the Parse server. To run `parse-dashboard`, we need to install it globally.

```
npm -i g parse-dashboard

parse-dashboard --dev --appId APPLICATION_ID --masterKey MASTER_KEY --serverURL "http://localhost:1337/parse/" --appName SimpleFileStorage
```

We can access the dashboard on `localhost:4040`. For this tutorial, we will be using the REST API.

## Backend Features 
### Storing Data
As mentioned earlier, Parse allows us to store data easily. The base unit of all data is the objects API. For example, if we define a vehicle class with the keys manufacturer and model, we can perform CRUD REST operations using a simple curl request.

```
curl -X POST \
  -H "X-Parse-Application-Id: simple_file_storage" \
  -H "X-Parse-REST-API-Key: ${REST_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{"manufacturer": "Lamborghini", "model":  "Gallardo"}' \
  http://localhost:1337/parse/classes/vehicle

```
We get `objectId` and `created _date` in response. Further operations on the object can be performed using `objectid`.

```
curl -X GET \
  -H "X-Parse-Application-Id: simple_file_storage" \
  -H "X-Parse-REST-API-Key: ${REST_API_KEY}" \
  -H "Content-Type: application/json" \
  http://localhost:1337/parse/classes/vehicle/objectId
```
```
curl -X PUT \
  -H "X-Parse-Application-Id: simple_file_storage" \
  -H "X-Parse-REST-API-Key: ${REST_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{"manufacturer": "Lamborghini", "model":  "Murcielago"}' \
  http://localhost:1337/parse/classes/vehicle/objectId
```
```
curl -X DELETE \
  -H "X-Parse-Application-Id: simple_file_storage" \
  -H "X-Parse-REST-API-Key: ${REST_API_KEY}" \
  http://localhost:1337/parse/classes/objectId

```
In case a class is not predefined, it will be created by the server. We can use Parse Dashboard to create custom classes. As far as data types are concerned, Parse has support for string, number, boolean, arrays, JSON Objects, Date-Time, File, and Null. Additionally Parse has two custom datatypes, Pointer to Another Parse Object and Relation to another Parse Class. Data types in Parse are locked in. Once a datatype is set, it will return an error if you try to save anything else.

## Files 

As with data, file upload is straightforward. The files URL is the `/files` route and the file name.
However, we have to manually handle the content type.

```
curl -X POST \
  -H "X-Parse-Application-Id: simple_file_storage" \
  -H "X-Parse-REST-API-Key: REST_API_KEY" \
  -H "Content-Type: image/jpeg" \
  --data-binary '@myPicture.jpg' \
  http://localhost:1337/parse/files/pic.jpg
```

As a response, we receive the file location and name of the saved file. A unique identifier is appended to the file name.

```
{
  "url": "http://localhost:1337/parse/files/simple_file_storage/d840137c22d89d126075ec7fa875c54f_pic.jpg",
  "name": "d840137c22d89d126075ec7fa875c54f_pic.jpg"
}

```

## Authentication & Security
Parse provides out-of-the-box user authentication. This includes token-based authentication, user actions like sign up, login, email verification, reset passwords, token-based session management, and role-based access management. The routes for users are `/parse/users`, the routes for roles are `/parse/roles` and the routes for sessions are `/parse/sessions`. 

To secure data, Parse provides Class Level Permissions (CLP) and Access Control Lists (ACL). CLP provides fine-grained control over data access to roles. Using Class Level Permissions we can define Roles which will have the ability to:

- Create new Classes;
- Add Fields to Classes;
- Read or Query Data from classes;

Furthermore, using ACLs we can restrict access to objects to individuals and roles. An example snippet of ACL is:

```json
{
  classLevelPermissions:
  {
    "find": {
      "requiresAuthentication": true,
      "role:admin": true
    },
    "get": {
      "requiresAuthentication": true,
      "role:admin": true
    },
    "create": { "role:admin": true },
    "update": { "role:admin": true },
    "delete": { "role:admin": true }
  }
}
```

This particular object:
- is inaccessible to guests;
- requires authentication to view and query objects;
- has a predefined role admin, can perform all operations.

The picture below, from the Parse docs, demonstrates how CLPs and ACLs interact.

![clp_vs_acl_diagram](https://blog.jscrambler.com/content/images/2020/09/clp_vs_acl_diagram.png)


## Miscellaneous Features 

- Cloud Functions allow us to define custom functions in the Parse backend. 
- Hooks allow us to run custom code in other languages and extend server-side logic.
- Jobs allow us to run long-running functions so we don't have to wait for a response.
- Triggers allow us to write custom code before/after data is modified.
- Analytics allows us to add dimensions and metrics to our application.
- Push Dashboard allows us to create custom push campaigns for our mobile apps.
- Geo points allow us to associate real-world latitudes and longitudes with an object.
- Config allows us to save config parameters on the server.

## Extending Parse with Chisel and Parse Auditor

### Chisel CMS

[Chisel](https://chiselcms.com/) is an API-first headless CMS built upon Parse. Setting up Chisel over Parse is quite straightforward.

```sh
npm install -g chisel-cms
chisel-cms --appId "APP_ID" --serverURL "https://YOURSERVER.com/parse"
```

Chisel will start at `localhost:9000`.

Chisel provides an admin panel where we can set up multiple sites. Additionally, it has its own [Parse server](https://github.com/beachio/chisel-parse-server-starter). While you can run Chisel on any Parse server, Chisel's server has helpful templates like blog and knowledge base.
It's advisable to check the [data structures](https://chiselcms.com/docs/data-structure) and [content publishing](https://chiselcms.com/docs/content-publishing-lifecycle) life cycle before diving in.

### Parse Auditor 
[Parse auditor](https://github.com/Blackburn-Labs/parse-auditor) is a module inspired by the Envers Project. It adds automated data tracking/auditing to classes. This is useful when the app is needed to adhere to regulations like HIPAA. Parse Auditor has to be used in the cloud code. Let's take a look at how Parse Auditor works

Let's assume we have `ImportantData` and `SortOfImportanData` classes in Parse. We would like to track data changes in both classes and know if `ImportantData` was accessed. 

To set up Parse Auditor, we need to edit the cloud code. First, shut down any running instance of the Parse server and dashboard. Then, navigate to the cloud folder of your Parse installation. If there is no cloud folder, then create a `main.js` file inside a cloud folder. We need the absolute path of the cloud folder. It should look like this:

```
C:\somefolder\Parse\cloud\main.js
```

Inside the cloud folder, add `parse-auditor` to the dependencies in `package.json`

```json
{
  "dependencies": {
    "parse-auditor": "*"
  }
}

```

Now, edit the `main.js` file as follows:

```js
const ParseAuditor = require('parse-auditor');
ParseAuditor(['ImportantData', 'SortOfImportantData'],['ImportantData'])
```

The first param takes an array of Class names and tracks them in a separate `Class_AUD` class. The second param takes an array of Class names and tracks views in the `Class_AUD` class.

By default, changes to `ImportantData` and `SortOfImportantData` will be tracked in `ImportantData_AUD` and `SortOfImportantData_AUD`. Views of `ImportantData` will be tracked in `SortOfImportantData_AUD`. Four extra fields are attached to audit logs:

- meta_actor: The user involved in this event. Either the user who made the update or the one who viewed this record.
- meta_action: Will be "SAVE", "DELETE", or "FIND" depending on the action the user took.
- meta_class: The name of the class, convenient when combining complex audit histories across many classes.
- meta_subject: The row being edited/viewed.

The plugin can be configured further using these fields:

```js
{
    classPrefix: '', //Class Prefix
    classPostfix: '_AUD', //Class Postfix
    fieldPrefix: 'meta_', //field Postfix
    fieldPostfix: '', // field Postfix
    parseSDK: Parse, //SDK Object
    useMasterKey: false, //MasterKey
    clp: {} //Class Level Permissions 
}
```
Consider the example below:

```js
const ParseAuditor = require('parse-auditor');
const customConfig = { classPostfix: '_LOGS' };
ParseAuditor(['ImportantData', 'SortOfImportantData'], ['ImportantData'], customConfig);
```

This will log the data to a class sufficed with _LOGS. To start the server, we will have to pass `main.js` to the cloud param as below.

```
parse-server --appId APPLICATION_ID --masterKey MASTER_KEY --databaseURI mongodb://localhost/test --cloud "C:\somefolder\Parse\cloud\main.js"
```

With this, we have successfully set up Parse with custom logging.


## Final Thoughts

In this article, we have seen how we quickly generate an app backend using Parse.

We have covered how Parse handles permissions and how they can be used to secure data. Also, we have covered two useful tools that can be used with Parse: Chisel CMS and Parse Auditor.