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

Authorization Guide

Role-based access control (RBAC) and permission management in Oxidite.

Installation

[dependencies]
oxidite = { version = "1.0", features = ["auth", "database"] }

Quick Start

#![allow(unused)]
fn main() {
use oxidite::prelude::*;
use oxidite_auth::{RequirePermission, RequireRole};

// Protect routes with permissions
app.delete("/users/:id", delete_user)
    .layer(RequirePermission::new("users.delete"));

app.get("/admin", admin_panel)
    .layer(RequireRole::new("admin"));
}

Roles and Permissions

The oxidite-auth crate provides database models for Role and Permission. You can manage these in your application logic.

#![allow(unused)]
fn main() {
// Example: Creating a role and assigning it to a user
// (This is a simplified example, your actual implementation may vary)

// Create role
let admin_role = Role::create("admin", &db).await?;

// Create permission
let create_users_perm = Permission::create("users.create", &db).await?;

// Add permission to role
admin_role.add_permission(&create_users_perm, &db).await?;

// Assign role to user
user.assign_role(&admin_role, &db).await?;

// Check permission
if user.has_permission("users.create", &db).await? {
    // Allow action
}

// Check role
if user.has_role("admin", &db).await? {
    // Allow access
}
}

Middleware

#![allow(unused)]
fn main() {
use oxidite_auth::{RequirePermission, RequireRole, RequireAnyPermission};

// Require specific permission
app.post("/posts", create_post)
    .layer(RequirePermission::new("posts.create"));

// Require specific role
app.get("/admin/dashboard", dashboard)
    .layer(RequireRole::new("admin"));

// Require any of multiple permissions
app.put("/posts/:id", update_post)
    .layer(RequireAnyPermission::new(vec![
        "posts.update.own".to_string(),
        "posts.update.all".to_string()
    ]));
}

In Handlers

You can also perform authorization checks within your handlers.

#![allow(unused)]
fn main() {
use oxidite_auth::Auth;

async fn delete_user(
    auth: Auth,
    Path(id): Path<i64>,
    State(db): State<Arc<Database>>,
) -> Result<OxiditeResponse> {
    let user = User::find(auth.user_id, &db).await?;

    if !user.has_permission("users.delete", &db).await? {
        return Err(Error::Forbidden("You do not have permission to delete users.".to_string()));
    }

    User::delete(id, &db).await?;

    Ok(OxiditeResponse::json(json!({ "status": "ok" })))
}
}

Dynamic Permissions

For more complex scenarios, you can implement custom logic in your handlers.

#![allow(unused)]
fn main() {
// Check at runtime
async fn can_edit_post(user: &User, post: &Post, db: &Database) -> Result<bool> {
    Ok(user.has_permission("posts.update.all", db).await? ||
    (user.has_permission("posts.update.own", db).await? && post.user_id == user.id))
}
}