Introduction

Our JavaScript SDK is based on the popular Backbone.js framework. It is compatible with existing Backbone applications with minimal changes on your part. Our goal is to minimize configuration and let you quickly start building your JavaScript and HTML5 app on Parse.

Apps

On Parse, you create an App for each of your mobile applications. Each App has its own application id and JavaScript client key that you apply to your web app. Your account on Parse can accommodate multiple Apps. This is useful even if you have one application, since you can deploy different versions for test and production.

Dependencies

Our JavaScript SDK does not require any external libraries. The only exception is the Parse.View class, which requires that you provide jQuery or a jQuery compatible $ method.

Objects

Parse.Object

Storing data on Parse is built around Parse.Object. Each Parse.Object contains key-value pairs of JSON-compatible data. This data is schemaless, which means that you don't need to specify ahead of time what keys exist on each Parse.Object. You simply set whatever key-value pairs you want, and our backend will store it.

For example, let's say you're tracking high scores for a game. A single Parse.Object could contain:

score: 1337, playerName: "Sean Plott", cheatMode: false

Keys must be alphanumeric strings. Values can be strings, numbers, booleans, or even arrays and dictionaries - anything that can be JSON-encoded.

Each Parse.Object is an instance of a specific subclass with a class name that you can use to distinguish different sorts of data. For example, we could call the high score object a GameScore. We recommend that you NameYourClassesLikeThis and nameYourKeysLikeThis, just to keep your code looking pretty.

To create a new subclass, use the Parse.Object.extend method. Any Parse.Query will return instances of the new class for any Parse.Object with the same classname. If you're familiar with Backbone.Model, then you already know how to use Parse.Object. It's designed to be a drop-in replacement.

// Simple syntax to create a new subclass of Parse.Object.
var GameScore = Parse.Object.extend("GameScore");
// Create a new instance of that class.
var gameScore = new GameScore();
// Alternatively, you can use the typical Backbone syntax.
var Achievement = Parse.Object.extend({
className: "Achievement"
});

You can add additional methods and properties to your subclasses of Parse.Object.

Saving Objects

Let's say you want to save the GameScore described above to the Parse Cloud. The interface is similar to a Backbone.Model, including the save method:

var GameScore = Parse.Object.extend("GameScore");
var gameScore = new GameScore();
gameScore.set("score", 1337);
gameScore.set("playerName", "Sean Plott");
gameScore.set("cheatMode", false);
gameScore.save(null, {
success: function(gameScore) {
// Execute any logic that should take place after the object is saved.
alert('New object created with objectId: ' + gameScore.id);
},
error: function(gameScore, error) {
// Execute any logic that should take place if the save fails.
// error is a Parse.Error with an error code and message.
alert('Failed to create new object, with error code: ' + error.message);
}
});

After this code runs, you will probably be wondering if anything really happened. To make sure the data was saved, you can look at the Data Browser in your app on Parse. You should see something like this:

There are two things to note here. You didn't have to configure or set up a new Class called GameScore before running this code. Your Parse app lazily creates this Class for you when it first encounters it.

There are also a few fields you don't need to specify that are provided as a convenience. objectId is a unique identifier for each saved object. createdAt and updatedAt represent the time that each object was created and last modified in the cloud. Each of these fields is filled in by Parse, so they don't exist on a Parse.Object until a save operation has completed.

If you prefer, you can set attributes directly in your call to save instead.

Parse automatically figures out which data has changed so only "dirty" fields will be sent to the Parse Cloud. You don't need to worry about squashing data that you didn't intend to update.

Counters

The above example contains a common use case. The "score" field is a counter that we'll need to continually update with the player's latest score. Using the above method works but it's cumbersome and can lead to problems if you have multiple clients trying to update the same counter.

To help with storing counter-type data, Parse provides methods that atomically increment (or decrement) any number field. So, the same update can be rewritten as:

gameScore.increment("score");
gameScore.save();

You can also increment by any amount by passing in a second argument to increment. When no amount is specified, 1 is used by default.

Arrays

To help with storing array data, there are three operations that can be used to atomically change an array associated with a given key:

add append the given object to the end of an array field.

addUnique add the given object only if it isn't already contained in an array field. The position of the insert is not guaranteed.

// After this, the playerName field will be empty
myObject.unset("playerName");
// Saves the field deletion to the Parse Cloud
myObject.save();

Relational Data

Objects may have relationships with other objects. For example, in a blogging application, a Post object may have many Comment objects. Parse supports all kind of relationships, including one-to-one, one-to-many, and many-to-many.

One-to-One and One-to-Many Relationships

One-to-one and one-to-many relationships are modeled by saving a Parse.Object as a value in the other object. For example, each Comment in a blogging app might correspond to one Post.

Many-to-Many Relationships

Many-to-many relationships are modeled using Parse.Relation. This works similar to storing an array of Parse.Objects in a key, except that you don't need to fetch all of the objects in a relation at once. In addition, this allows Parse.Relation to scale to many more objects than the array of Parse.Object approach. For example, a User may have many Posts that she might like. In this case, you can store the set of Posts that a User likes using relation. In order to add a Post to the "likes" list of the User, you can do:

For more details on Parse.Query, please look at the query portion of this guide. A Parse.Relation behaves similar to an array of Parse.Object for querying purposes, so any query you can do on an array of objects, you can do on a Parse.Relation.

Data Types

So far we've used values with type String, Number, and Parse.Object. Parse also supports JavaScript Dates and null.

You can nest JavaScript Objects and JavaScript Arrays to store more structured data within a single Parse.Object.

For more information about how Parse handles data, check out our documentation on Data & Security.

Queries

We've already seen how a Parse.Query with get can retrieve a single Parse.Object from Parse. There are many other ways to retrieve data with Parse.Query - you can retrieve many objects at once, put conditions on the objects you wish to retrieve, and more.

Basic Queries

In many cases, get isn't powerful enough to specify which objects you want to retrieve. Parse.Query offers different ways to retrieve a list of objects rather than just a single object.

The general pattern is to create a Parse.Query, put conditions on it, and then retrieve an Array of matching Parse.Objects using find. For example, to retrieve of the scores with a particular playerName, use the equalTo method to constrain the value for a key.

If you want to retrieve objects matching several different values, you can use containedIn, providing an array of acceptable values. This is often useful to replace multiple queries with a single query. For example, if you want to retrieve scores made by any player in a particular list:

If you want to retrieve objects that do not match any of several values you can use notContainedIn, providing an array of acceptable values. For example if you want to retrieve scores from players besides those in a list:

If you want to retrieve objects that have a particular key set, you can use exists. Conversely, if you want to retrieve objects without a particular key set, you can use doesNotExist.

// Finds objects that have the score set
query.exists("score");
// Finds objects that don't have the score set
query.doesNotExist("score");

You can use the matchesKeyInQuery method to get objects where a key matches the value of a key in a set of objects resulting from another query. For example, if you have a class containing sports teams and you store a user's hometown in the user class, you can issue one query to find the list of users whose hometown teams have winning records. The query would look like:

var Team = Parse.Object.extend("Team");
var teamQuery = new Parse.Query(Team);
teamQuery.greaterThan("winPct", 0.5);
var userQuery = new Parse.Query(Parse.User);
userQuery.matchesKeyInQuery("hometown", "city", teamQuery);
userQuery.find({
success: function(results) {
// results has the list of users with a hometown team with a winning record
}
});

Conversely, to get objects where a key does not match the value of a key in a set of objects resulting from another query, use doesNotMatchKeyInQuery. For example, to find users whose hometown teams have losing records:

var losingUserQuery = new Parse.Query(Parse.User);
losingUserQuery.doesNotMatchKeyInQuery("hometown", "city", teamQuery);
losingUserQuery.find({
success: function(results) {
// results has the list of users with a hometown team with a losing record
}
});

You can restrict the fields returned by calling select with a list of keys. To retrieve documents that contain only the score and playerName fields (and also special built-in fields such as objectId, createdAt, and updatedAt):

The remaining fields can be fetched later by calling fetch on the returned objects:

query.first().then(function(result) {
// only the selected fields of the object will now be available here.
return result.fetch();
}).then(function(result) {
// all fields of the object will now be available here.
});

Queries on Array Values

For keys with an array type, you can find objects where the key's array value contains 2 by:

Relational Queries

There are several ways to issue queries for relational data. If you want to retrieve objects where a field matches a particular Parse.Object, you can use equalTo just like for other data types. For example, if each Comment has a Post object in its post field, you can fetch comments for a particular Post:

If you want to retrieve objects where a field contains a Parse.Object that matches a different query, you can use matchesQuery. Note that the default limit of 100 and maximum limit of 1000 apply to the inner query as well, so with large data sets you may need to construct queries carefully to get the desired behavior. In order to find comments for posts containing images, you can do:

If you want to retrieve objects where a field contains a Parse.Object that does not match a different query, you can use doesNotMatchQuery. In order to find comments for posts without images, you can do:

In some situations, you want to return multiple types of related objects in one query. You can do this with the include method. For example, let's say you are retrieving the last ten comments, and you want to retrieve their related posts at the same time:

var query = new Parse.Query(Comment);
// Retrieve the most recent ones
query.descending("createdAt");
// Only retrieve the last ten
query.limit(10);
// Include the post data with each comment
query.include("post");
query.find({
success: function(comments) {
// Comments now contains the last ten comments, and the "post" field
// has been populated. For example:
for (var i = 0; i < comments.length; i++) {
// This does not require a network access.
var post = comments[i].get("post");
}
}
});

You can also do multi level includes using dot notation. If you wanted to include the post for a comment and the post's author as well you can do:

query.include(["post.author"]);

You can issue a query with multiple fields included by calling include multiple times. This functionality also works with Parse.Query helpers like first and get.

Counting Objects

Caveat: Count queries are rate limited to a maximum of 160 requests per minute. They can also return inaccurate results for classes with more than 1,000 objects. Thus, it is preferable to architect your application to avoid this sort of count operation (by using counters, for example.)

If you just need to count how many objects match a query, but you do not need to retrieve all the objects that match, you can use count instead of find. For example, to count how many games have been played by a particular player:

Compound Queries

If you want to find objects that match one of several queries, you can use Parse.Query.or method to construct a query that is an OR of the queries passed in. For instance if you want to find players who either have a lot of wins or a few wins, you can do:

var lotsOfWins = new Parse.Query("Player");
lotsOfWins.greaterThan("wins", 150);
var fewWins = new Parse.Query("Player");
fewWins.lessThan("wins", 5);
var mainQuery = Parse.Query.or(lotsOfWins, fewWins);
mainQuery.find({
success: function(results) {
// results contains a list of players that either have won a lot of games or won only a few games.
},
error: function(error) {
// There was an error.
}
});

You can add additional constraints to the newly created Parse.Query
that act as an 'and' operator.

Note that we do not, however, support GeoPoint or non-filtering constraints
(e.g. near, withinGeoBox, limit, skip, ascending/descending, include)
in the subqueries of the compound query.

Promises

In addition to callbacks, every asynchronous method in the Parse JavaScript SDK returns a Promise. With promises, your code can be much cleaner than the nested code you get with callbacks.

The then Method

Every Promise has a method named then which takes a pair of callbacks. The first callback is called if the promise is resolved, while the second is called if the promise is rejected.

Chaining Promises Together

Promises are a little bit magical, in that they let you chain them without nesting. If a callback for a promise returns a new promise, then the first one will not be resolved until the second one is. This lets you perform multiple actions without incurring the pyramid code you would get with callbacks.

Error Handling

If any Promise in a chain returns an error, all of the success callbacks after it will be skipped until an error callback is encountered. The error callback can transform the error, or it can handle it by returning a new Promise that isn't rejected. You can think of rejected promises kind of like throwing an exception. An error callback is like a catch block that can handle the error or rethrow it.

var query = new Parse.Query("Student");
query.descending("gpa");
query.find().then(function(students) {
students[0].set("valedictorian", true);
// Force this callback to fail.
return Parse.Promise.error("There was an error.");
}).then(function(valedictorian) {
// Now this will be skipped.
return query.find();
}).then(function(students) {
// This will also be skipped.
students[1].set("salutatorian", true);
return students[1].save();
}, function(error) {
// This error handler WILL be called. error will be "There was an error.".
// Let's handle the error by returning a new promise.
return Parse.Promise.as("Hello!");
}).then(function(hello) {
// Everything is done!
}, function(error) {
// This isn't called because the error was already handled.
});

It's often convenient to have a long chain of success callbacks with only one error handler at the end.

Creating Promises

When you're getting started, you can just use the promises returned from methods like find or save. However, for more advanced scenarios, you may want to make your own promises. After you create a Promise, you'll need to call resolve or reject to trigger its callbacks.

Promises in Parallel

You can also use promises to perform several tasks in parallel, using the when method. You can start multiple operations at once, and use Parse.Promise.when to create a new promise that will be resolved when all of its input promises is resolved. The new promise will be successful if none of the passed-in promises fail; otherwise, it will fail with the last error. Performing operations in parallel will be faster than doing them serially, but may consume more system resources and bandwidth.

var query = new Parse.Query("Comments");
query.equalTo("post", 123);
query.find().then(function(results) {
// Collect one promise for each delete into an array.
var promises = [];
_.each(results, function(result) {
// Start this delete immediately and add its promise to the list.
promises.push(result.destroy());
});
// Return a new promise that is resolved when all of the deletes are finished.
return Parse.Promise.when(promises);
}).then(function() {
// Every comment was deleted.
});

Creating Async Methods

With these tools, it's easy to make your own asynchronous functions that return promises. For example, you can make a promisified version of setTimeout.

Collections

A Parse.Collection is an ordered set of Parse.Objects. It is compatible with Backbone.Collection, and has all the same functionality. You can create a new subclass using either a model class, or a particular Parse.Query.

Files

Creating a Parse.File

Parse.File lets you store application files in the cloud that would otherwise be too large or cumbersome to fit into a regular Parse.Object. The most common use case is storing images, but you can also use it for documents, videos, music, and any other binary data (up to 10 megabytes).

Getting started with Parse.File is easy. There are a couple of ways to create a file. The first is with a base64-encoded String.

Parse will auto-detect the type of file you are uploading based on the file extension, but you can specify the Content-Type with a third parameter:

var file = new Parse.File("myfile.zzz", fileData, "image/png");

But most commonly for HTML5 apps, you'll want to use an html form with a file upload control. On modern browsers, this is easy. Create a file input tag which allows the user to pick a file from their local drive to upload:

<input type="file" id="profilePhotoFileUpload">

Then, in a click handler or other function, get a reference to that file:

Notice in this example that we give the file a name of photo.jpg. There's two things to note here:

You don't need to worry about filename collisions. Each upload gets a unique identifier so there's no problem with uploading multiple files named photo.jpg.

It's important that you give a name to the file that has a file extension. This lets Parse figure out the file type and handle it accordingly. So, if you're storing PNG images, make sure your filename ends with .png.

Next you'll want to save the file up to the cloud. As with Parse.Object, there are many variants of the save method you can use depending on what sort of callback and error handling suits you.

parseFile.save().then(function() {
// The file has been saved to Parse.
}, function(error) {
// The file either could not be read, or could not be saved to Parse.
});

Finally, after the save completes, you can associate a Parse.File with a Parse.Object just like any other piece of data:

Retrieving File Contents

How to best retrieve the file contents back depends on the context of your application. Because of cross-domain request issues, it's best if you can make the browser do the work for you. Typically, that means rendering the file's URL into the DOM. Here we render an uploaded profile photo on a page with jQuery:

You can delete files that are referenced by objects using the
REST API. You will need to provide the master key in order to be allowed to delete a file.

If your files are not referenced by any object in your app, it is not possible to delete them through
the REST API. You may request a cleanup of unused files in your app's Settings page. Keep in mind that
doing so may break functionality which depended on accessing unreferenced files through their URL property.
Files that are currently associated with an object will not be affected.

Analytics

Parse provides a number of hooks for you to
get a glimpse into the ticking heart of your app.
We understand that it's important to understand
what your app is doing, how frequently, and when.

While this section will cover different ways to instrument your app
to best take advantage of Parse's analytics backend,
developers using Parse to store and retrieve data can
already take advantage of metrics on Parse.

Without having to implement any client-side logic,
you can view real-time graphs and breakdowns
(by device type, Parse class name, or REST verb)
of your API Requests in your app's dashboard and
save these graph filters to quickly access just the data you're interested in.

Custom Analytics

Parse.Analytics also allows you to track free-form events,
with a handful of string keys and values.
These extra dimensions allow segmentation of your custom events
via your app's Dashboard.

Say your app offers search functionality for apartment listings,
and you want to track how often the feature is used, with some additional metadata.

Parse.Analytics can even be used as a lightweight error tracker —
simply invoke the following and you'll have access to
an overview of the rate and frequency of errors,
broken down by error code, in your application:

Note that Parse currently only stores the first eight dimension pairs
per call to Parse.Analytics.track().

Config

Parse Config

Parse.Config is a way to configure your applications remotely by storing a single configuration object on Parse.
It enables you to add things like feature gating or a simple "Message of the Day".
To start using Parse.Config you need to add a few key/value pairs (parameters) to your app on the Parse Config Dashboard.

After that you will be able to fetch the Parse.Config on the client, like in this example:

Retrieving Config

ParseConfig is built to be as robust and reliable as possible, even in the face of poor internet connections.
Caching is used by default to ensure that the latest successfully fetched config is always available.
In the below example we use get to retrieve the latest version of config from the server,
and if the fetch fails we can simply fall back to the version that we successfully fetched before via current.

Current Config

Every Parse.Config instance that you get is always immutable.
When you retrieve a new Parse.Config in the future from the network,
it will not modify any existing Parse.Config instance,
but will instead create a new one and make it available via Parse.Config.current().
Therefore, you can safely pass around any current() object and safely assume that it will not automatically change.

It might be troublesome to retrieve the config from the server every time you want to use it.
You can avoid this by simply using the cached current() object and fetching the config only once in a while.

Parameters

ParseConfig supports most of the data types supported by Parse.Object:

string

number

Date

Parse.File

Parse.GeoPoint

JS Array

JS Object

We currently allow up to 100 parameters in your config and a total size of 128KB across all parameters.

Users

At the core of many apps, there is a notion of user accounts that lets users access their information in a secure manner. We provide a specialized user class called Parse.User that automatically handles much of the functionality required for user account management.

With this class, you'll be able to add user account functionality in your app.

Parse.User is a subclass of Parse.Object, and has all the same features, such as flexible schema, automatic persistence, and a key value interface. All the methods that are on Parse.Object also exist in Parse.User. The difference is that Parse.User has some special additions specific to user accounts.

Properties

Parse.User has several values that set it apart from Parse.Object:

username: The username for the user (required).

password: The password for the user (required on signup).

email: The email address for the user (optional).

We'll go through each of these in detail as we run through the various use cases for users.

Signing Up

The first thing your app will do is probably ask the user to sign up. The following code illustrates a typical sign up:

This call will asynchronously create a new user in your Parse App. Before it does this, it also checks to make sure that both the username and email are unique. Also, it securely hashes the password in the cloud. We never store passwords in plaintext, nor will we ever transmit passwords back to the client in plaintext.

Note that we used the signUp method, not the save method. New Parse.Users should always be created using the signUp method. Subsequent updates to a user can be done by calling save.

If a signup isn't successful, you should read the error object that is returned. The most likely case is that the username or email has already been taken by another user. You should clearly communicate this to your users, and ask them try a different username.

You are free to use an email address as the username. Simply ask your users to enter their email, but fill it in the username property — Parse.User will work as normal. We'll go over how this is handled in the reset password section.

Logging In

Of course, after you allow users to sign up, you need to let them log in to their account in the future. To do this, you can use the class method logIn.

Verifying Emails

Enabling email verification in an application's settings allows the application to reserve part of its experience for users with confirmed email addresses. Email verification adds the emailVerified key to the Parse.User object. When a Parse.User's email is set or modified, emailVerified is set to false. Parse then emails the user a link which will set emailVerified to true.

There are three emailVerified states to consider:

true - the user confirmed his or her email address by clicking on the link Parse emailed them. Parse.Users can never have a true value when the user account is first created.

false - at the time the Parse.User object was last refreshed, the user had not confirmed his or her email address. If emailVerified is false, consider calling fetch on the Parse.User.

missing - the Parse.User was created when email verification was off or the Parse.User does not have an email.

Current User

It would be bothersome if the user had to log in every time they open your app. You can avoid this by using the cached current Parse.User object.

Whenever you use any signup or login methods, the user is cached in localStorage. You can treat this cache as a session, and automatically assume the user is logged in:

Parse.User.logOut();
var currentUser = Parse.User.current(); // this will now be null

Setting the Current User

If you’ve created your own authentication routines, or otherwise logged in a user on the server side, you can now pass the session token to the client and use the become method. This method will ensure the session token is valid before setting the current user.

Parse.User.become("session-token-here").then(function (user) {
// The current user is now set to user.
}, function (error) {
// The token could not be validated.
});

Security For User Objects

The Parse.User class is secured by default. Data stored in a Parse.User can only be modified by that user. By default, the data can still be read by any client. Thus, some Parse.User objects are authenticated and can be modified, whereas others are read-only.

Specifically, you are not able to invoke any of the save or delete methods unless the Parse.User was obtained using an authenticated method, like logIn or signUp. This ensures that only the user can alter their own data.

The Parse.User obtained from Parse.User.current() will always be authenticated.

If you need to check if a Parse.User is authenticated, you can invoke the authenticated method. You do not need to check authenticated with Parse.User objects that are obtained via an authenticated method.

Security For Other Objects

The same security model that applies to the Parse.User can be applied to other objects. For any object, you can specify which users are allowed to read the object, and which users are allowed to modify an object. To support this type of security, each object has an access control list, implemented by the Parse.ACL class.

The simplest way to use a Parse.ACL is to specify that an object may only be read or written by a single user. To create such an object, there must first be a logged in Parse.User. Then, new Parse.ACL(user) generates a Parse.ACL that limits access to that user. An object's ACL is updated when the object is saved, like any other property. Thus, to create a private note that can only be accessed by the current user:

This note will then only be accessible to the current user, although it will be accessible to any device where that user is signed in. This functionality is useful for applications where you want to enable access to user data across multiple devices, like a personal todo list.

Permissions can also be granted on a per-user basis. You can add permissions individually to a Parse.ACL using setReadAccess and setWriteAccess. For example, let's say you have a message that will be sent to a group of several users, where each of them have the rights to read and delete that message:

You can also grant permissions to all users at once using setPublicReadAccess and setPublicWriteAccess. This allows patterns like posting comments on a message board. For example, to create a post that can only be edited by its author, but can be read by anyone:

Operations that are forbidden, such as deleting an object that you do not have write access to, result in a Parse.Error.OBJECT_NOT_FOUND error code. For security purposes, this prevents clients from distinguishing which object ids exist but are secured, versus which object ids do not exist at all.

Resetting Passwords

It's a fact that as soon as you introduce passwords into a system, users will forget them. In such cases, our library provides a way to let them securely reset their password.

To kick off the password reset flow, ask the user for their email address, and call:

This will attempt to match the given email with the user's email or username field, and will send them a password reset email. By doing this, you can opt to have users use their email as their username, or you can collect it separately and store it in the email field.

The flow for password reset is as follows:

User requests that their password be reset by typing in their email.

Parse sends an email to their address, with a special password reset link.

User clicks on the reset link, and is directed to a special Parse page that will allow them type in a new password.

User types in a new password. Their password has now been reset to a value they specify.

Note that the messaging in this flow will reference your app by the name that you specified when you created this app on Parse.

Querying

To query for users, you can simple create a new Parse.Query for Parse.Users:

Users in the Data Browser

The User class is a special class that is dedicated to storing Parse.User objects. In the data browser, you'll see a little person icon next to the User class:

Sessions

Session APIs are only available in apps with revocable sessions enabled.
Parse apps created after March 25, 2015 have this enabled by default ("Require Revocable
Sessions" toggle in your Parse.com app settings page). If you have an
existing app, you can upgrade to revocable sessions by following the
Session Migration Tutorial.

Sessions represent an instance of a user logged into a device. Sessions are
automatically created when users log in or sign up. They are automatically
deleted when users log out. There is one distinct
Parse.Session
object for each user-installation pair; if a user issues a login request from
a device they're already logged into, that user's previous
Parse.Session
object for that Installation is automatically deleted.
Parse.Session
objects are stored on Parse in the Session class, and you can view them on
the Parse.com Data Browser. We provide a set of APIs to manage
Parse.Session
objects in your app.

Parse.Session
is a subclass of
Parse.Object,
so you can query, update, and delete sessions in the same way that you
manipulate normal objects on Parse. Because the Parse Cloud automatically
creates sessions when you log in or sign up users, you should not manually create
Parse.Session
objects unless you are building a "Parse for IoT" app (e.g.
Arduino or Embedded C). Deleting a
Parse.Session
will log the user out of the device that is currently using this session's token.

Unlike other Parse objects, the
Parse.Session
class does not have Cloud Code triggers.
So you cannot register a beforeSave or afterSave handler for the Session class.

Properties

The
Parse.Session
object has these special fields:

sessionToken (readonly): String token for authentication on Parse API requests.
In the response of
Parse.Session
queries, only your current
Parse.Session
object will contain a session token.

user: (readonly) Pointer to the Parse.User object that this session is for.

createdWith (readonly): Information about how this session was created (e.g. { "action": "login", "authProvider": "password"}).

action could have values: login, signup, or create.
The create action is when the developer manually creates the session by saving a
Parse.Session
object.

authProvider could have values: password, anonymous, facebook, or twitter.

restricted (readonly): Boolean for whether this session is restricted.

Restricted sessions do not have write permissions on
Parse.User,
Parse.Session, and
Parse.Installation
classes on Parse. Restricted sessions also cannot read unrestricted sessions.

All sessions that the Parse Cloud automatically creates during user login/signup will be unrestricted.
All sessions that the developer manually creates by saving a new
Parse.Session
object from the client (only needed for "Parse for IoT" apps) will be restricted.

installationId (can be set only once): String referring to the Parse.Installation where the session is logged in from.
For Parse SDKs, this field will be automatically set when users log in or sign up.

All special fields except installationId can only be set automatically by
the Parse Cloud. You can add custom fields onto
Parse.Session
objects, but please keep in mind that any logged-in device (with session token) can read
other sessions that belong to the same user (unless you disable Class-Level Permissions, see below).

Handling Invalid Session Token Error

Apps created before March 25, 2015 use legacy session tokens until you migrate
them to use the new revocable sessions. On API requests with legacy tokens, if
the token is invalid (e.g. User object was deleted), then the request is executed
as a non-logged in user and no error was returned. On API requests with revocable
session tokens, an invalid session token will always fail with the "invalid
session token" error. This new behavior lets you know when you need to ask
the user to log in again.

With revocable sessions, your current session token could become invalid if its corresponding
Parse.Session
object is deleted from the Parse Cloud. This could happen if you implement a Session Manager
UI that lets users log out of other devices, or if you manually delete the session via
Cloud Code, REST API, or Data Browser. Sessions could also be deleted due to
automatic expiration (if configured in app settings). When a device's session token no longer corresponds to a
Parse.Session
object on the Parse Cloud, all API requests from that device will fail with “Error 209: invalid session token”.

To handle this error, we recommend writing a global utility function that is called by all of
your Parse request error callbacks. You can then handle the "invalid session token" error in
this global function. You should prompt the user to login again so that they can obtain a new
session token. This code could look like this:

Security

Parse.Session
objects can only be accessed by the user specified in the user field. All
Parse.Session
objects have an ACL that is read and write by that user only. You cannot change this ACL.
This means querying for sessions will only return objects that match the current logged-in user.

When you log in a user via
Parse.User.login(),
Parse will automatically create a new unrestricted
Parse.Session
object in the Parse Cloud. Same for signups and Facebook/Twitter logins.

Session objects manually created from client SDKs (by creating an instance of
Parse.Session,
and saving it) are always restricted. You cannot manually create an unrestricted
sessions using the object creation API.

Restricted sessions are prohibited from creating, modifying, or deleting any data in the
Parse.User,
Parse.Session, and
Parse.Installation
classes. Restricted session also cannot read unrestricted sessions. Restricted Sessions are useful
for "Parse for IoT" devices (e.g Arduino or
Embedded C)
that may run in a less-trusted physical environment than mobile apps.
However, please keep in mind that restricted sessions can still read data on
Parse.User,
Parse.Session, and
Parse.Installation
classes, and can read/write data in any other class just like a normal session.
So it is still important for IoT devices to be in a safe physical environment and
ideally use encrypted storage to store the session token.

If you want to prevent restricted Sessions from modifying classes other than
Parse.User,
Parse.Session, and
Parse.Installation
you can write a Cloud Code beforeSave handler for that class:

You can configure Class-Level Permissions (CLPs) for the Session class just like other classes on Parse.
CLPs restrict reading/writing of sessions via the
Parse.Session
API, but do not restrict Parse Cloud's automatic session creation/deletion when users log in, sign up, and log out.
We recommend that you disable all CLPs not needed by your app. Here are some common use cases for Session CLPs:

Find, Delete — Useful for building a UI screen that allows users to see
their active session on all devices, and log out of sessions on other devices.
If your app does not have this feature, you should disable these permissions.

Create — Useful for "Parse for IoT" apps (e.g.
Arduino or
Embedded C) that provision restricted user sessions for
other devices from the phone app. You should disable this permission when building apps for
mobile and web. For "Parse for IoT" apps, you should check whether your IoT device actually
needs to access user-specific data. If not, then your IoT device does not need a user session,
and you should disable this permission.

Get, Update, Add Field — Unless you need these operations, you should disable these permissions.

Roles

As your app grows in scope and user-base, you may find yourself needing more coarse-grained control over access to pieces of your data than
user-linked ACLs can provide. To address this requirement, Parse supports a form of
Role-based Access Control.
Roles provide a logical way of grouping users with common access privileges to your Parse data. Roles are
named objects that contain users and other roles. Any permission granted to a role is implicitly granted to its users as well as to the
users of any roles that it contains.

For example, in your application with curated content, you may have a number of users that are considered "Moderators" and can modify and
delete content created by other users. You may also have a set of users that are "Administrators" and are allowed all of the same
privileges as Moderators, but can also modify the global settings for the application. By adding users to these roles, you
can ensure that new users can be made moderators or administrators, without having to manually grant permission to every resource for each
user.

We provide a specialized class called Parse.Role that represents these role objects in your client code.
Parse.Role is a subclass of Parse.Object, and has all of the same features, such as a flexible
schema, automatic persistence, and a key value interface. All the methods that are on Parse.Object also
exist on Parse.Role. The difference is that Parse.Role has some additions specific to management of roles.

Properties

Parse.Role has several properties that set it apart from Parse.Object:

name: The name for the role. This value is required, and can only be set once as a role is being created. The name
must consist of alphanumeric characters, spaces, -, or _. This name will be used to identify the Role without needing
its objectId.

users: A relation to the set of users that will inherit permissions granted to the containing role.

roles: A relation to the set of roles whose users and roles will inherit permissions granted to the
containing role.

Security for Role Objects

The Parse.Role uses the same security scheme (ACLs) as all other objects on Parse, except that it requires an ACL
to be set explicitly. Generally, only users with greatly elevated privileges (e.g. a master user or Administrator) should be able
to create or modify a Role, so you should define its ACLs accordingly. Remember, if you give write-access to a
Parse.Role to a user, that user can add other users to the role, or even delete the role altogether.

To create a new Parse.Role, you would write:

// By specifying no write privileges for the ACL, we can ensure the role cannot be altered.
var roleACL = new Parse.ACL();
roleACL.setPublicReadAccess(true);
var role = new Parse.Role("Administrator", roleACL);
role.save();

You can add users and roles that should inherit your new role's permissions through the "users" and "roles" relations on Parse.Role:

Take great care when assigning ACLs to your roles so that they can only be modified by those who should have permissions to modify them.

Security for Other Objects

Now that you have created a set of roles for use in your application, you can use them with ACLs to define the privileges that their users will receive.
Each Parse.Object can specify a Parse.ACL, which provides an access control list that indicates which users and roles
should be granted read or write access to the object.

Giving a role read or write permission to an object is straightforward. You can either use the Parse.Role:

Role Hierarchy

As described above, one role can contain another, establishing a parent-child relationship between the two roles. The consequence of this
relationship is that any permission granted to the parent role is implicitly granted to all of its child roles.

These types of relationships are commonly found in applications with user-managed content, such as forums. Some small subset of users
are "Administrators", with the highest level of access to tweaking the application's settings, creating new forums, setting global
messages, and so on. Another set of users are "Moderators", who are responsible for ensuring that the content created by users remains
appropriate. Any user with Administrator privileges should also be granted the permissions of any Moderator. To establish this relationship,
you would make your "Administrators" role a child role of "Moderators", like this:

Facebook Users

Parse provides an easy way to integrate Facebook with your application. The Parse.FacebookUtils class integrates Parse.User and the Facebook Javascript SDK to make linking your users to their Facebook identities easy.

Using our Facebook integration, you can associate an authenticated Facebook user with a Parse.User. With just a few lines of code, you'll be able to provide a "log in with Facebook" option in your app, and be able to save their data to Parse.

Setup

To start using Facebook with Parse, you need to:

Set up a Facebook app, if you haven't already. Choose the "Website with Facebook Login" option under "Select how your app integrates with Facebook" and enter your site's URL.

The function assigned to fbAsyncInit is run as soon as the Facebook JavaScript SDK has completed loading. Any code that you want to run after the Facebook JavaScript SDK is loaded should be placed within this function and after the call to Parse.FacebookUtils.init().

The steps that happen when linking are very similar to log in. The difference is that on successful login,
the existing Parse.User is updated with the Facebook information. Future logins via
Facebook will now log the user into their existing account.

Facebook SDK and Parse

Facebook login using the Parse SDK requires that the Facebook SDK already be loaded before calling Parse.FacebookUtils.init().

Our library manages the FB object for you. The FB singleton is synchronized with the current user by default, so
any methods you call on it will be acting on the Facebook user associated with the current
Parse.User. Calling FB.login() or FB.logOut() explicitly will cause the Parse.User and FB object to fall out of synchronization, and is not recommended.

Cloud Functions

Cloud Functions can be called from JavaScript using Parse.Cloud.run.
For example, to call the Cloud Function named hello:

GeoPoints

Parse allows you to associate real-world latitude and longitude coordinates with an object. Adding a Parse.GeoPoint to a Parse.Object allows queries to take into account the proximity of an object to a reference point. This allows you to easily do things like find out what user is closest to another user or which places are closest to a user.

Parse.GeoPoint

To associate a point with an object you first need to create a Parse.GeoPoint. For example, to create a point with latitude of 40.0 degrees and -30.0 degrees longitude:

var point = new Parse.GeoPoint({latitude: 40.0, longitude: -30.0});

This point is then stored in the object as a regular field.

placeObject.set("location", point);

Note: Currently only one key in a class may be a Parse.GeoPoint.

Geo Queries

Now that you have a bunch of objects with spatial coordinates, it would be nice to find out which objects are closest to a point. This can be done by adding another restriction to Parse.Query using near. Getting a list of ten places that are closest to a user may look something like:

At this point placesObjects will be an array of objects ordered by distance
(nearest to farthest) from userGeoPoint.
Note that if an additional ascending()/descending()
order-by constraint is applied,
it will take precedence over the distance ordering.

To limit the results using distance, check out withinMiles, withinKilometers, and withinRadians.

It's also possible to query for the set of objects that are contained within a particular area. To find the objects in a rectangular bounding box, add the withinGeoBox restriction to your Parse.Query.

Caveats

Each Parse.Object class may only have one key with a Parse.GeoPoint object.

Using the near constraint will also limit results to within 100 miles.

Points should not equal or exceed the extreme ends of the ranges. Latitude should not be -90.0 or 90.0. Longitude should not be -180.0 or 180.0. Attempting to set latitude or longitude out of bounds will cause an error.

Push Notifications

Views

We've included Parse.View which is just a copy of Backbone.View. Feel free to use it for constructing views in your app. Take a look at the Backbone.View API for details on how to use this class. Note that once you use Parse.View, you will need to include jQuery or a jQuery compatible $ method.

Converting Backbone Apps

If you already have an existing Backbone application, it's easy to convert it to use our JavaScript SDK. After converting, you'll end up with a collection of static files that contain all your app's functionality.

Our JavaScript SDK is Backbone compatible, which means that our Parse.Object and Parse.Collection can be dropped in for Backbone.Model and Backbone.Collection with minor tweaks. Here's how to convert your app:

Replace all instances of Backbone.Collection with Parse.Collection and specify the Parse.Object class as the model. You should also specify a query so that the collection knows how to fetch the objects:

Anywhere you were constructing models from a server you'll need to construct a Parse.Query to grab the objects that you're interested in, similar to what we had to do for the query attribute on the Parse.Collection.

And that's it. Your app should be functional and using Parse as the backend.

Error Handling

Most Parse JavaScript functions report their success or failure using an object with callbacks, similar to a Backbone "options" object. The two primary callbacks used are success and error. success is called whenever an operation completes without errors. Generally, its parameter will be either the Parse.Object in the case of save or get, or an array of Parse.Object for find.

error is called for any kind of error that occurs when interacting with the Parse Cloud over the network. These errors are either related to problems connecting to the cloud or problems performing the requested operation. Let's take a look at another example. In the code below, we try to fetch an object with a non-existent objectId. The Parse Cloud will return an error - so here's how to handle it properly in your callback:

For methods like save and signUp that affect a particular Parse.Object, the first argument to the error function will be the object itself, and the second will be the Parse.Error object. This is for compatibility with Backbone-type frameworks. For a list of all possible Parse.Error codes, see the Error Codes section of the JavaScript API.

Security

We strongly recommend that you build your applications to restrict access to data as much as possible.
Our Data & Security Guide has detailed descriptions of the various ways Parse can help keep your app's data safe.
It also explains the purpose of your application keys (e.g. JavaScript key vs. master key). Using them appropriately is crucial for securing your app.

Settings

In addition to coding securely, please review the settings pages for your applications to select options that will restrict access to your applications as much as is appropriate for your needs.
For example, if users should be unable to log in without a Facebook account linked to their application, disable all other login mechanisms.
Specify your Facebook application IDs, Twitter consumer keys, and other such information to enable server-side validation of your users' login attempts.