Skip to main content

acls_rs/
resource.rs

1//! Resource type with required permissions.
2
3use crate::algebra::Monoid;
4use crate::permission::{AtomicPermission, PermissionSet};
5use crate::Subject;
6
7#[cfg(feature = "serde")]
8use serde::{Deserialize, Serialize};
9
10/// A resource that requires certain permissions to access.
11#[derive(Debug, Clone)]
12#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
13pub struct Resource {
14    /// Unique identifier for this resource.
15    pub id: String,
16    /// Permissions required to access this resource.
17    pub required_permissions: PermissionSet,
18    /// Classification or type of this resource.
19    pub resource_type: String,
20}
21
22impl Resource {
23    /// Create a new resource with no required permissions.
24    pub fn new(id: impl Into<String>) -> Self {
25        Self {
26            id: id.into(),
27            required_permissions: PermissionSet::identity(),
28            resource_type: String::new(),
29        }
30    }
31
32    /// Add a required permission for accessing this resource.
33    pub fn requires(mut self, perm: AtomicPermission) -> Self {
34        self.required_permissions.extend([perm]);
35        self
36    }
37
38    /// Set the resource type classification.
39    pub fn resource_type(mut self, rt: impl Into<String>) -> Self {
40        self.resource_type = rt.into();
41        self
42    }
43
44    /// Returns `true` if the subject has all required permissions.
45    pub fn can_access(&self, subject: &Subject) -> bool {
46        let effective = subject.effective_permissions();
47        self.required_permissions.is_subset_of(&effective)
48    }
49
50    /// Returns the set of required permissions the subject lacks.
51    pub fn missing_permissions(&self, subject: &Subject) -> PermissionSet {
52        let effective = subject.effective_permissions();
53        self.required_permissions.difference(&effective)
54    }
55}