backbone-bucket 0.3.0

Bucket Bounded Context: File Storage Module for Backbone Framework
Documentation
//! Permission types and traits
//!
//! Generated by backbone-schema

use serde::{Deserialize, Serialize};
use std::collections::HashSet;

/// Actions that can be performed on resources
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Action {
    Create,
    Read,
    Update,
    Delete,
    List,
    Restore,
}

impl Action {
    /// Get all actions
    pub fn all() -> Vec<Self> {
        vec![
            Self::Create,
            Self::Read,
            Self::Update,
            Self::Delete,
            Self::List,
            Self::Restore,
        ]
    }
}

/// Field restriction types
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum FieldRestriction {
    /// Allow all fields
    All,
    /// Only these fields
    Only(HashSet<String>),
    /// All except these fields
    Except(HashSet<String>),
}

impl FieldRestriction {
    /// Check if a field is allowed
    pub fn is_allowed(&self, field: &str) -> bool {
        match self {
            Self::All => true,
            Self::Only(fields) => fields.contains(field),
            Self::Except(fields) => !fields.contains(field),
        }
    }

    /// Get allowed fields from a list
    pub fn filter_fields<'a>(&self, fields: &[&'a str]) -> Vec<&'a str> {
        fields.iter().copied().filter(|f| self.is_allowed(f)).collect()
    }
}

/// A single permission rule
#[derive(Debug, Clone)]
pub struct PermissionRule {
    /// The action this rule applies to
    pub action: Action,
    /// Whether the action is allowed
    pub allowed: bool,
    /// Field restrictions (optional)
    pub fields: Option<FieldRestriction>,
    /// Optional condition name (for runtime evaluation)
    pub condition: Option<String>,
}

/// Permission error
#[derive(Debug, Clone, thiserror::Error)]
pub enum PermissionError {
    #[error("Action '{action:?}' not allowed for role '{role}'")]
    ActionNotAllowed { action: Action, role: String },

    #[error("Field '{field}' not accessible for action '{action:?}'")]
    FieldNotAccessible { field: String, action: Action },

    #[error("Condition not met for action '{action:?}'")]
    ConditionNotMet { action: Action },

    #[error("Role '{0}' not found")]
    RoleNotFound(String),
}

/// Result type for permission checks
pub type PermissionResult = Result<(), PermissionError>;

/// Trait for permission checking
pub trait PermissionChecker {
    /// Check if an action is allowed for a role
    fn can(&self, role: &str, action: Action) -> bool;

    /// Check if a field is accessible for an action
    fn can_access_field(&self, role: &str, action: Action, field: &str) -> bool;

    /// Get allowed fields for an action
    fn allowed_fields(&self, role: &str, action: Action) -> Vec<String>;

    /// Get all available roles
    fn roles(&self) -> Vec<&str>;
}