Skip to main content

modkit_security/
access_scope.rs

1use uuid::Uuid;
2
3/// Access scope defining which tenants and resources a request can access.
4///
5/// An empty scope (no tenants, no resources) is considered a "deny all" scope.
6/// To access data, the scope must contain at least one tenant ID or resource ID.
7#[derive(Clone, Debug, PartialEq, Eq, Default, serde::Serialize, serde::Deserialize)]
8pub struct AccessScope {
9    pub(crate) tenant_ids: Vec<Uuid>,
10    pub(crate) types: Vec<Uuid>,
11    pub(crate) resource_ids: Vec<Uuid>,
12}
13
14impl AccessScope {
15    #[inline]
16    #[must_use]
17    pub fn tenant_ids(&self) -> &[Uuid] {
18        &self.tenant_ids
19    }
20
21    #[inline]
22    #[must_use]
23    pub fn resource_ids(&self) -> &[Uuid] {
24        &self.resource_ids
25    }
26
27    /// Returns true if this scope is empty (no tenants, no resources).
28    /// An empty scope results in a "deny all" condition in queries.
29    #[must_use]
30    pub fn is_empty(&self) -> bool {
31        self.tenant_ids.is_empty() && self.resource_ids.is_empty()
32    }
33
34    #[must_use]
35    pub fn has_tenants(&self) -> bool {
36        !self.tenant_ids.is_empty()
37    }
38
39    #[must_use]
40    pub fn has_resources(&self) -> bool {
41        !self.resource_ids.is_empty()
42    }
43
44    #[must_use]
45    pub fn tenants_only(tenant_ids: Vec<Uuid>) -> Self {
46        Self {
47            tenant_ids,
48            types: vec![],
49            resource_ids: vec![],
50        }
51    }
52
53    #[must_use]
54    pub fn resources_only(resource_ids: Vec<Uuid>) -> Self {
55        Self {
56            tenant_ids: vec![],
57            types: vec![],
58            resource_ids,
59        }
60    }
61
62    #[must_use]
63    pub fn tenant(tenant_id: Uuid) -> Self {
64        Self::tenants_only(vec![tenant_id])
65    }
66
67    #[must_use]
68    pub fn resource(resource_id: Uuid) -> Self {
69        Self::resources_only(vec![resource_id])
70    }
71
72    /// Create a scope with both tenant and resource constraints (AND).
73    /// This is less common but useful for very specific access scenarios.
74    #[must_use]
75    pub fn both(tenant_ids: Vec<Uuid>, resource_ids: Vec<Uuid>) -> Self {
76        Self {
77            tenant_ids,
78            types: vec![],
79            resource_ids,
80        }
81    }
82}