How to create users with different permission levels in Nun-db
We have recently taken an important step towards pushing Nun-db into mainstream use cases. Now, assigning multiple users to a single database and defining different permission levels for each is possible. In this tutorial, we will walk you through the process of creating two different users, one to be used by the front end of your application and one to be used by the back end.
Let’s consider the following use case: you are developing a system, and you need the server to push updates to the client. For example, if the backend is waiting for a payment confirmation webhook, and once it is processed, stored, and fine, the frontend must, as soon as possible, show the user that the process is finished. In this scenario, it is very important that the front end MUST not be able to change the values, but it must watch and read the values. To support that, we must restrict the frontend user to only read keys and allow the server to read and write all keys. That is what this tutorial will show.
First, we must have a Nun-db process running and a database created. Let’s start by running Nun-db with docker on your local computer.
Starting Nun-db locally
docker run --env NUN_USER=user-name --env NUN_PWD=user-pwd --env NUN_DBS_DIR="/data" --mount type=bind,source="/tmp",target=/data -it --rm -p 3013:3013 -p 3012:3012 -p 3014:3014 --name nun-test mateusfreira/nun-db
Nice, now you have Nun-db running on your local computer. Time to create your first database.
Lets use the same docker container to execute the next commands.
Creating your first database
- Connect docker container to execute commands
docker exec -it nun-test /bin/sh
All the following commands will now be executed inside this docker.
- Create the database
nun-db -u user-name -p user-pwd create-db -d sample -t sample-pwd
- Test your database credentials. Note that all commands from this point will use the
use
prefix to get into the sample db context
nun-db -u user-name -p user-pwd exec "use sample sample-pwd; keys" # Response "valid auth\n;empty;keys ,$$token,$connections\n"
- Excellent, now create the user for that database.
In this case, we will create two users, a server
and a client
. Where the server
can write to all keys and the client
can read all keys but only write to keys prefixed with client-*
.
4.1 Create user server
nun-db -u user-name -p user-pwd exec "use sample sample-pwd; create-user server server-pwd;"
4.1.1 Checking the user presence
nun-db -u user-name -p user-pwd exec "use sample sample-pwd; keys;" # Response "valid auth\n;empty;keys ,$$token,$$user_server,$connections\n"
The existence of the key $$user_server
proves the user was created
4.2 Create the user client
nun-db -u user-name -p user-pwd exec "use sample sample-pwd; create-user client client-pwd;"
4.1.1 Checking the client user existence
nun-db -u user-name -p user-pwd exec "use sample sample-pwd; keys;" Response "valid auth\n;empty;keys ,$$token,$$user_client,$$user_server,$connections\n"
The presence of the key $$user_client
proves the command worked.
Setting user permissions
Now, our users are created, and we need to set up permissions for them. In this use case, we want the server to be able to do all operations in all keys and the client to real all but only write in the keys prefixed as client-*
. Let’s start by creating the server permissions.
Server access all keys
This command will set the permission to the user server
to all keys *
to (r
) read, (w
) write, and (x
) delete.
nun-db -u user-name -p user-pwd exec "use sample sample-pwd; set-permissions server rwx *;"
Clean read all keys, write only client-* keys
Here you will need 2 sets of permissions, one to give the read all r *
and read, write and delete client-
keys rwx client-*
when applying more than one rule for a single user you separate them by |
. Remember, resetting the permissions to a user will overwrite the old permissions and not complement them; be careful.
nun-db -u user-name -p user-pwd exec "use sample sample-pwd; set-permissions client r *|rwx client-*;"
Verifying client permissions
To verify a users permission all you need to do is to get the key value $$permission_${user_name_here}
e.g:
nun-db -u user-name -p user-pwd exec "use sample sample-pwd; get \$\$permission_\$client" # Response "valid auth\n;empty;value r *|rwx client-*\n"
Nice, that means our client permissions are set correctly. Lets now write a small Node.js program to use this credentials.
Creating the sample nodejs app to test permissions
Now the next commands must be executed out of the docker container, back to your computer.
mkdir app cd app npm init npm install nun-db touch index.js # edit index.js
Testing client permissions
const NunDb = require('nun-db'); async function run() { const nunDb = new NunDb({ url: "ws://localhost:3012", db: "sample", user: "client", token: "client-pwd"}); const keys = await nunDb.keys(); const value = await nunDb.get("name"); //console.log({ keys, value }); try { await nunDb.set("name", "Jose"); console.error('This should not happen!!'); process.exit(1); } catch (e) { console.log(e.message); console.log(`This is correct`); process.exit(0); } } run();
- When you run that code you shall see the 2 messages print
permission denied
andThis is correct
, that means all your settings are correct until here.
So now lets do the same with the server keys
Now note that the server can perform both operations without throwing any exception.
const NunDb = require('nun-db'); async function run() { const nunDb = new NunDb({ url: "ws://localhost:3012", db: "sample", user: "server", token: "server-pwd"}); const keys = await nunDb.keys(); const value = await nunDb.get("name"); console.log({ keys, value }); try { await nunDb.set("name", "Jose"); console.log(`This is correct`); } catch (e) { console.error('This should not happen!!'); process.exit(1); } } run();
Running that you will see the message This is correct
means your code worked as expected.
Conclusion
In this tutorial, we created two users with very different permissions, 1 the client that must real all keys but only write to a small set of keys and one server that can real and write data to all keys. This is a very common use case where you may want your users to read and watch values updated, but the frontend can only write to a small set of keys (or maybe none).
There are several use cases for this that we will explore in the future HOW Tos posts.
- Code Coverage for Rust Projects with GitHub Actions
- NunDb is now referenced in the Database of Databases
- Real-time Medical Image Collaboration POC Made Easy with OHIF and Nun-db
- How to create users with different permission levels in Nun-db
- Match vs Hashmap! Which one is faster in rust?
- Towards a More Secure Nun-db: Our Latest Security Enhancements
- Building a Trello-like React/Redux App with NunDB with offline and conflict resolution features
- Introduction to managing conflicts in NunDB
- Keepin up with Nun-db 2023
- The new storage engine of Nun-db
- Stop procrastinating and just fix your flaky tests, it may be catching nasty bugs
- An approach to hunt and fix non-reproducible bugs - Case study - Fixing a race conditions in Nun-db replication algorithm in rust
- NunDB the debug command
- Keeping up with Nun-db 2021
- Writing a prometheus exporter in rust from idea to grafana chart
- Integration tests in rust a multi-process test example
- Leader election in rust the journey towards implementing nun-db leader election
- How to make redux TodoMVC example a real-time multiuser app with nun-db in 10 steps
- A fast-to-sync/search and space-optimized replication algorithm written in rust, The Nun-db data replication model
- NunDb How to backup one or all databases
- How to create your simple version of google analytics real-time using Nun-db
- Migrating a chat bot feature from Firebase to Nun-db
- Keepin' up with NunDB
- Going live with NunDB