1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
//! Resource descriptor types.
use std::collections::BTreeMap;
/// Descriptor for a resource being accessed.
///
/// # Examples
///
/// ```
/// use secure_authz::resource::ResourceRef;
///
/// let resource = ResourceRef::new("article")
/// .with_id("42")
/// .with_tenant("acme")
/// .with_owner("alice");
/// assert_eq!(resource.kind, "article");
/// assert_eq!(resource.resource_id.as_deref(), Some("42"));
/// ```
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct ResourceRef {
/// The kind/type of the resource (e.g. `"article"`, `"document"`).
pub kind: String,
/// The unique identifier of the specific resource instance.
pub resource_id: Option<String>,
/// The tenant this resource belongs to.
pub tenant_id: Option<String>,
/// The owner of this resource.
pub owner_id: Option<String>,
/// Arbitrary attributes for ABAC evaluation.
pub attributes: BTreeMap<String, String>,
}
impl ResourceRef {
/// Creates a new `ResourceRef` with the given kind.
pub fn new(kind: impl Into<String>) -> Self {
Self {
kind: kind.into(),
..Default::default()
}
}
/// Attaches a tenant identifier to this resource.
pub fn with_tenant(mut self, tenant_id: impl Into<String>) -> Self {
self.tenant_id = Some(tenant_id.into());
self
}
/// Attaches an owner identifier to this resource.
pub fn with_owner(mut self, owner_id: impl Into<String>) -> Self {
self.owner_id = Some(owner_id.into());
self
}
/// Attaches a resource identifier to this resource.
pub fn with_id(mut self, resource_id: impl Into<String>) -> Self {
self.resource_id = Some(resource_id.into());
self
}
/// Attaches an arbitrary attribute for ABAC evaluation.
pub fn with_attribute(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
self.attributes.insert(key.into(), value.into());
self
}
/// Returns a resource attribute as `&str` when present.
#[must_use]
pub fn attr(&self, key: &str) -> Option<&str> {
self.attributes.get(key).map(String::as_str)
}
}