Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Let’s get started with a barebones authentication example. First, we’ll define a few simple types.

use microrm::prelude::*;

#[derive(Entity)]
struct User {
    #[key]
    username: String,
    password_hash: String,
    authz: microrm::Map<Action>,
}

#[derive(Entity)]
struct Action {
    #[key]
    title: String,
}

#[derive(Schema)]
struct AuthSchema {
    users: microrm::Table<User>,
    actions: microrm::Table<Action>,
}

That’s it; this defines a database schema of users and actions, where users can be configured to be authorized for a set of actions. Now let’s open the database and insert some example data:

let (cpool, schema) =
    microrm::ConnectionPool::open::<AuthSchema>("auth.db")
        .expect("couldn't connect to database");

cpool.run_transaction(1, |txn| {
    // add some users
    let alice = schema.users.insert_and_return(txn, User {
        username: "alice".into(),
        password_hash: "somehash".into(),
        authz: Default::default(),
    })?;
    let barbara = schema.users.insert_and_return(txn, User {
        username: "barbara".into(),
        password_hash: "someotherhash".into(),
        authz: Default::default(),
    })?;

    // now a few different actions as well
    let front_door_id = schema.actions.insert(txn, Action {
        title: "unlock front door".into()
    })?;

    let oven_id = schema.actions.insert(txn, Action {
        title: "turn on the oven".into()
    })?;

    let feed_cat_id = schema.actions.insert(txn, Action {
        title: "feed the cat".into()
    })?;

    // and now let's assign some simple authz
    alice.authz.connect(txn, front_door_id)?;
    alice.authz.connect(txn, feed_cat_id)?;
    barbara.authz.connect(txn, front_door_id)?;
    barbara.authz.connect(txn, oven_id)?;

    Ok(())
}).expect("couldn't insert data into database");

Now we can run queries against the database! For example, is ‘alice’ allowed to ‘turn on the oven’?

let allowed : bool = cpool.run_transaction(1, |txn| {
    Ok(schema
        .users
        .keyed("alice")
        .join(User::Authz)
        .keyed("turn on the oven")
        .count(txn)? > 0
    )
}).expect("couldn't run query");

Barbara forgot to turn off the oven again, let’s revoke her privilege:

cpool.run_transaction(1, |txn| {
    let barbara = schema
        .users
        .keyed("barbara")
        .get(txn)?
        .unwrap();

    let oven_authz = schema
        .authz
        .keyed("turn on the oven")
        .get(txn)?
        .unwrap();

    barbara.authz.disconnect(txn, oven_authz)?;

    Ok(())
}).expect("couldn't run query");

For more possible queries, check out the API documentation.

Congrats! You’ve defined a schema, added some data, and run some queries. For more information on what exactly was happening here, see the next chapter, Entities and Schemas.