Administrating users in RethinkDB

Written by Ulises Avila
in rethinkdb at 15 October 2018

Introduction

When managing databases, one is in the need to configure mechanisms of authentication which can extend to authorization mechanisms. RethinkDB has a plain simple users mechanism to control user creation, permissions given and scope of action.

In this tutorial you will apply several configurations of permissions to three different users.

Requeriments

  • Have one server with RethinkDB running.

Setting things up

This administrative task is done via web panel. So after ssh login to your dopplet run rethinkdb or rethinkdb --bind all depending if you are tunneling or not so you can access your panel via domain_name:8080 or dopplet_url:8080. Everything is done in the Data Explorer section placed in the navbar.

RethinkDB makes you the admin user when accessing it via web panel, so you have total control of the node.

Adding users

To avoid confusion between examples we are going to have several users, one per example. Users are stored in the table users in the rethinkdb database. To create them you use the insert function passing a JSON object, to finish this step you are going to pass a JSON array of 3 members like this:

r.db('rethinkdb').table('users').insert([
    {id: 'john', password: 'pass1'},
    {id: 'jack', password: 'pass2'},
    {id: 'joe', password: 'pass3'},
    ])

If everything went ok, you will get as response an object like this:

{
    "deleted": 0 ,
    "errors": 0 ,
    "inserted": 3 ,
    "replaced": 0 ,
    "skipped": 0 ,
    "unchanged": 0
}

It is important to note that once created you cannot modify the id of the users, you have to delete the entire user so you can add it again with the desired name.

Adding tables

To encapsulate the tests you are adding two tables into test database, CompactCameras and DslrCameras, you are executing two times the create method:

r.db('test').tableCreate('CompactCameras')
r.db('test').tableCreate('DslrCameras')

If everything went fine, you will get as response one medium sized JSON object telling you the details of each table.

With this you are ready to jump to the examples.

Example 1

In this example john gets to read and write from the table CompactCameras with the help of the grant method:

r.db('test').table('CompactCameras').grant('john', {read: true, write: true});

After executing this command you will get an answer like this:

{

"granted": 1 ,
"permissions_changes": [
    {
        "new_val": {
            "read": true ,
            "write": true
        } ,
        "old_val": null
    }
]

}

It is telling that permissions have gotten changes. It is also reporting the state of the configuration between old_val and new_val.

There is not anything left to do for configuring permission to this user, you could go and use this user in your application's authentication and everything would be working. Now you can review the second example.

Example 2

In this example jack gets to read and write from the table CompactCameras and read from DslrCameras, seeing the last example you can infer that you have to execute the command two times,each for every table to modify:
r.db('test').table('CompactCameras').grant('jack', {read: true, write: true}); r.db('test').table('DslrCameras').grant('jack', {read: true});

You will get one response as the one from example 1 telling you the changes that have been done. The important thing in this example is that one user can have active permissions on different elements at the same time.

Example 3

In this example joe gets access to all configurations of test database with the exception of DslrCameras, again you have to execute each command separately:

r.db('test').grant('joe', {read: true, write: true});
r.db('test').table('DslrCameras').grant('joe', {read: false, write: false});

The first thing to note in this example is that the grant command can be applied to any level of the structure, where the levels are: r as all the database, r.db as one database and r.db.table as one table in one database.

The second thing to note is that permissions in broader scopes get inherited to smaller scopes, using example 3 for this leads to say that joe have read and write access to any element in test database until it is specified that he cannot do it in the table DslrCameras. There is one example left.

Example 4

Any global permission must be written directly to r such as letting joe full access to the server with the following:

r.grant('joe', {read: true, write: true, config: true, connect: true});

The last thing to note is that the connect option is only eligible for global scope.

Conclusion

When a user is added it does not have any permissions, but you can set values with the grant method, after that permissions not set are considered as false. The simplicity of RethinkDB does not let us to login to the admin panel as any of the users created in this tutorial, then the next step would be to create an app that connects to your server so you can test your user permissions. You can go and check the official RethinkDB and see the offering of drivers for your programming language of choice.