Crate bonsaidb::core::actionable
Expand description
Actionable provides the basic functionality needed to build an async-based API that has a flexible permissions system integrated.
This crate was designed to be used by BonsaiDb
internally, and as a way for users of BonsaiDb to extend their database
servers with their own APIs.
Permissions
The Permissions struct is constructed from a list of Statements. The
Statement struct is inspired by statements in
IAM.
By default, all actions are denied for all resources.
The ResourceName struct describes a unique name/id of anything in your
application. This is meant to be similar to ARNs in
IAM,
but instead of being restricted to a format by this library, you are able to
define your own syntax.
The Action trait is derive-able, and will convert any enum to something
that can be permitted or denied to any ResourceName. This derive macro
only supports enums with variants that have no parameters, or only have a
single name-less parameter that also implements Action.
An example Action enum might look like:
#[derive(Action, Debug)]
pub enum AllActions {
FlushCache,
User(UserActions),
}
#[derive(Action, Debug)]
pub enum UserActions {
Create,
ChangeUsername,
Delete,
}An example permissions check for users.42 might look like:
let allowed = permissions.allowed_to(
&ResourceName::named("users").and(42),
&AllActions::User(UserActions::Delete),
);Configuration
Along with allowing actions to be taken, Actionable can be used to configure values that may change on a per-role basis. Rate limits are an example of what this API is designed to handle:
let permissions = Permissions::from(Statement::for_any().with("rate-limit", 500_u64));
let effective_rate_limit = permissions
.get(&ResourceName::named("core-api"), "rate-limit")
.and_then(Configuration::to_unsigned);
assert_eq!(effective_rate_limit, Some(500));Permission-driven async API
At the core of many networked APIs written in Rust is an enum that represents a request, and similarly there are usually common response/error types. In these applications, there is usually a manually-written match statement that, for readability and maintainability, simply pass the parameters from the request to a helper method to handle the actual logic of the request.
The goal of the API portion of this crate is to replace the aforementioned
boilerplate match statement with a simple derive macro. For a commented
example, check out
actionable/examples/api-simulator.rs.
Structs
- A unique name of an action.
- An
actionwas denied. - A collection of allowed permissions. This is constructed from a
Vec<Statement>. By default, no actions are allowed on any resources. - A unique name/identifier of a resource.
- A statement of permissions. A statement describes whether one or more
actionsshould beallowedto be taken againstresources.
Enums
- A list of
ActionNames. - A configured value for a resource.
- A single element of a
ResourceName
Traits
- An action that can be allowed or disallowed.
- Dispatches
Tto an appropriate handler. This trait is derivable.
Attribute Macros
Derive Macros
- Derives the
actionable::Actiontrait. - Derives a set of traits that can be used to implement a permissions-driven API. There are options that can be customized with the
#[actionable]attribute at the enum level: - Derives the
Dispatchertrait.