A User Collection extends a Collection, adding the functionality needed to authenticate users with your app. You can create one by choosing "User Collection" when adding a Resource.
User Collections can have the same properties as a Collection, with two additional non-removable properties:
username
- The user's identifier; must be unique.password
- An encrypted password. It can never be retrieved from the database, only queried against.In addition to the above constraints, these two properties can only be modified by:
A User Collection can be accessed in the same ways as a Collection, both with dpd.js and HTTP. It also adds new methods to the API for authentication.
The examples below use a User Collection called /users
with the following schema:
id
username
password
displayName
Log in a user with their username and password. If successful, the browser will save a secure cookie for their session. This request responds with the session details:
{
"id": "s0446b993caaad577a..." //Session id
"path": "/users" // The path of the User Collection - useful if you have different types of users.
"uid": "ec54ad870eaca95f" //The id of the user
}
If the username or password is incorrect, Deployd will respond with a generic error:
{
"status": 401,
"message: "bad credentials"
}
For security reasons, users should not be informed which of their credentials (username, password, or both) were incorrect.
To authenticate a user, use the .login(credentials, fn)
function, including the username
and password
properties in the request body.
dpd.users.login({
username: "johnsmith",
password: "password"
}, function(result, error) {
// Do something
});
You can also use the .exec('login', credentials, fn)
function. This is useful if you have accessed the collection by using dpd()
as a function and the login()
function is unavailable.
dpd('users').exec('login', {
username: "johnsmith",
password: "password"
}, function(result, error) {
// Do something
});
To authenticate a user, send a POST
request to /login
with username
and password
properties in the request body.
POST /users/login
{
"username": "johnsmith",
"password": "password"
}
Logging out will remove the session cookie on the browser and destroy the current session. It does not return a result.
To log out a user, use the .logout(fn)
function.
dpd.users.logout(function(result, error) {
// Do something
});
result
will always be null.
You can also use the .exec('logout', fn)
function. This is useful if you have accessed the collection by using dpd()
as a function and the logout()
function is unavailable.
dpd('users').exec('logout', function(result, error) {
// Do something
});
To log out a user, send a POST
request to /logout
. Include the sid
cookie to identify your session.
POST /users/logout
Cookie: sid=6009c5b070d834a2d336224a93...
The response body will always be empty unless there was an error.
This will return the current user.
{
"id": "2975ff2778493818",
"username": "johnsmith",
"displayName": "John Smith"
}
If there is no current user, it will not return a value.
To get the current user, use the .me(fn)
function.
dpd.users.me(function(result, error) {
// Do something
});
If there is no current user, result
will be null.
You can also use the .get('me', fn)
function. This is useful if you have accessed the collection by using dpd()
as a function and the me()
function is unavailable.
dpd('users').get('me', function(result, error) {
// Do something
});
To get the current user, send a GET
request to /me
. Include the sid
cookie to identify your session.
GET /users/me
Cookie: sid=6009c5b070d834a2d336224a93...
If there is no current user, the response body will be blank:
204 No Content
Since HTTP is a stateless protocol, a mechanism is required to tie independent requests and connections to a single remote session. In Deployd, sessions are maintained by signing each request with a session id. Currently the only mechanism for signing requests is HTTP cookies.
If a request does not contain a sid
cookie with an existing session id, a session will be created and set as a cookie on the response.
WebSocket connections are identified and attached to sessions by the cookies sent during the upgrade request of a websocket.
As of v0.6
the sessions
API is very limited. In upcoming versions the API will include the following:
This app demonstrates how to create a microblogging app (similar to Twitter) using User Collections. It also demonstrates how to use dpd.js with AngularJS on the front-end.
The app supports registering, logging in, making posts, and mentioning other users in posts with their @username.
Events:
mentions
property)Front-end:
This app demonstrates how to use the "login", "logout", and "me" functions on a User Collection.
In any Collection Event, the me
object refers to the current user. You can use this to secure your app and protect your users. This page lists a few examples of how to use the me
object effectively.
// On Post /todo-lists
cancelUnless(me, "You must be logged in to create a todo list", 401);
this.creatorId = me.id;
You can ensure that only the creator of an object can update it:
// On Put /todos
if (!(me && me.id === this.creatorId)) {
cancel("This is not your todo", 401);
}
If you store an array
of roles
on your User Collection, you can use that to verify that the current user can perform an action:
// On POST /blog-posts
if (!(me && me.roles.indexOf("author") !== -1)) {
cancel("You must be an author to create a blog post", 401);
}
In a gamification setup, you might want to award the user some points for creating an object:
// On POST /answers
if (me) {
dpd.users.put(me.id, {
points: {$inc: 1}
}, function() {});
}
// On PUT /users
// External APIs should not be able to edit the point value
if (!internal) {
protect('points');
}
Let us know if you have any ideas to improve our docs. Open an issue on github, send us an email, or tweet us.
This entire site, including documentation written in markdown is available on github. Pull requests are appreciated!