R
G

Back to list2023-295

SurrealDB User Management & Namespaces

This example uses SurrealDB's integrated system user management. It's simple to implement and effective.

Namespaces are separated from one another. It's not possible to move data between them. Giving each user or group of users their own namespace on the same server should therefore be enough to guarantee secure separation of data.

For some basics on how authentication works in SurrealDB check out this overview on how SurrealDB manages users.

Setting up SurrealDB system users

Start server. The root user is required to manage the users.

surreal start --bind 127.0.0.1:8800 --user root --pass 123 --log debug --auth

Now create the namespace and the user owning it.

DEFINE NAMESPACE hugo;
USE NS hugo;
DEFINE USER hugo ON NAMESPACE password '123' ROLES OWNER;

Optional: Define a simple taple to get some response from the server for better testing:

DEFINE DATABASE people;
USE DB people;

DEFINE TABLE friends SCHEMAFUL;
DEFINE FIELD formal_name ON TABLE friends TYPE string;
DEFINE FIELD nickname ON TABLE friends TYPE string;
DEFINE FIELD email ON TABLE friends TYPE string;
DEFINE FIELD bff ON TABLE friends TYPE bool;

CREATE friends SET formal_name="Jane Doe", nickname="Random Jane", email="jane@doe.local", bff=true;

Usage in Rust:

use serde::Serialize;  
use surrealdb::engine::remote::ws::Ws;  
use surrealdb::opt::auth::Namespace;

#[derive(Debug, Serialize)]
struct AuthParams<'a> {
    user: &'a str,
    pass: &'a str,
}

#[tokio::main]
async fn main() -> Result<(), surrealdb::Error> {
    
    let db = Surreal::new::<Ws>("localhost:8000").await?;

    let res = db.signin(Namespace {
        namespace: "hugo",
        username: "hugo",
        password: "123",
    }).await?;

    dbg!(&res);

    let _ = db.use_ns("hugo").await?;
    let _ = db.use_db("people").await?;

    let res = db.query("INFO FOR DB").await?;
    dbg!(&res);

    let res = db.query("SELECT * FROM friends").await?;
    dbg!(&res);

    Ok(())
}

Limitations

This example grants total control over the namespace hugo to the user hugo. Assigning the OWNER rule he's able to create other users. Other roles are EDITOR allowing to edit data but no users and VIEWER which limits the user to read only access.

Check out the official DEFINE USER documentation for more information.

While this might be enough it's not fine grained. Users defined this way are system level users. For a more fine grained approach SurrealDB uses DEFINE SCOPE.

Further resources

On the official surrealDB tutorials site you'll find a basic example using Scopes.

On dev.to you'll find a post by Sebastian Wessel on how to create an application based multi tenant role and permission system.