Roles

It's possible to restrict access to fields and structs with boolean role expressions.


# #![allow(unused_variables)]
#fn main() {
use toql::prelude::Toql;

#[derive(Toql)]
#[toql(roles(insert="poweruser", delete="poweruser"))]
struct Book {

    #[toql(key)]
    id : u64,

    #[toql(roles(load="superuser;poweruser", update="poweruser"))]
    rating: u64
}
#}

The role expressions are similar to the Toql query syntax:

  • OR is expressed with ;
  • AND is expressed with ,
  • NOT is expressed with !
  • brackets are allowed

An valid role expression would be (teacher;student), !lazy meaning A teacher OR student AND NOT lazy.

Roles are provided with the context:


# #![allow(unused_variables)]
#fn main() {
use toql::prelude::ContextBuilder;
use std::collections::HashSet;

let mut r = HashSet::new();
r.insert("teacher".to_string());

let context = ContextBuilder::new()
        .with_roles(r)
        .build();
#}

See here for how to get a backend.

Notice that roles can restrict access to columns but not to rows. For row access control, check out the chapter in the appendix.

Load

It's possible to restrict loading, filtering and ordering of a struct or individual fields, joins and merges.

Let's assume a struct Book:


# #![allow(unused_variables)]
#fn main() {
use toql::prelude::{Toql, Join};
#   #[derive(Toql)]
#   #[toql(auto_key)]
#   struct User {
#   	#[toql(key)]
#   	 id: u32,
#   }
#   
#   #[derive(Toql)]
#   struct Edition {
#   	#[toql(key)]
#   	id: u64,
#   }

#[derive(Toql)]
#[toql(roles(load ="book_role"))]
struct Book {
    #[toql(key)]
    id : u64,

    #[toql(roles(load="author_role"))]
    title: Option<String>,

    #[toql(join, roles(load="author_role"))]
    author: Option<Join<User>>,

    #[toql(merge, roles(load="edition_role"))]
    editions: Option<Vec<Edition>>,
}
#}

To load anything from the book, the user requires the book_role. So to load the book's title the user requires the roles book_role and author_role.

Preselected fields

Notice that restricting preselected fields is like restricting the entire struct. See here:


# #![allow(unused_variables)]
#fn main() {
use toql::prelude::Toql;

#[derive(Toql)]
#[toql(roles(load ="book_role"))]
struct Book {
    #[toql(key)]
    id : u64,

    #[toql(roles(load="author_role"))]
    title: String
}
#}

Here Toql needs to load the title field in order to deserialize the struct. Because title is role restricted an error is raised for a missing autor_role.

Wildcard behaviour

If all fields from Book are selected with a wildcard * fields that do not match the role restriction are simply skipped. However, if such a field is selected explictly in the query then an error is raised.

Update

To restrict updating a struct or individual fields:


# #![allow(unused_variables)]
#fn main() {
use toql::prelude::{Toql, Join};
#   #[derive(Toql)]
#   #[toql(auto_key)]
#   struct User {
#   	#[toql(key)]
#   	 id: u32,
#   }
#   
#   #[derive(Toql)]
#   struct Edition {
#   	#[toql(key)]
#   	id: u64,
#   }

#[derive(Toql)]
#[toql(roles(update="book_role"))]
struct Book {

    #[toql(key)]
    id : u64,

    #[toql(roles(update="author_role"))]
    title: Option<String>,

    #[toql(join, roles(update="author_role"))]
    author: Option<Join<User>>,

    #[toql(merge, roles(update="edition_role"))]
    editions: Option<Vec<Edition>>,
}
#}

To update anything on the book, the user requires the book_role. So to update the book's title the user requires the roles book_role and author_role.

The role restriction on the author join applies only to the foreign key author_id in table Book, not to the joined User. To restrict the joined User put a role restriction #[toql(roles(update="user_role")) on top of the struct User

Update restrictions on partials joins are not allowed, since partial joins have no foreign key: Partial joins share the same primary key.

Likewise the role restriction on the editions merge applies only to resizing the Vec not to the fields on the edition table. See the chapter on updating for details.

Wildcard behaviour

Fields that have an invalid role expression are skipped for the field list *. However if the field name is explicitly mentioned in the field list, then an error occurs. This behaviour is similar to loading.

Insert / Delete

To restrict insertion or deltetion of a struct, attribute the struct like so:

use toql::prelude::{Toql, Join};

#[derive(Toql)] {
#[toql(roles(insert="book_role", delete="book_role"))
struct Book {

    #[toql(key)]
    id : u64

    title Option<String>>,

    #[toql(join)]
    author: Option<Join<User>>,

    #[toql(merge)]
    editions: Option<Vec<Edition>>,
}