surrealdb/iam/entities/resources/
actor.rs1use revision::revisioned;
2use std::collections::{HashMap, HashSet};
3use std::ops::Deref;
4use std::str::FromStr;
5
6use cedar_policy::{Entity, EntityId, EntityTypeName, EntityUid, RestrictedExpression};
7use serde::{Deserialize, Serialize};
8
9use super::{Level, Resource, ResourceKind};
10use crate::iam::Role;
11use crate::sql::statements::{DefineTokenStatement, DefineUserStatement};
12
13#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Hash, Serialize, Deserialize)]
17#[revisioned(revision = 1)]
18pub struct Actor {
19 res: Resource,
20 roles: Vec<Role>,
21}
22
23impl Default for Actor {
24 fn default() -> Self {
25 Self {
26 res: ResourceKind::Actor.on_level(Level::No),
27 roles: Vec::new(),
28 }
29 }
30}
31
32impl std::fmt::Display for Actor {
33 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34 if self.res.level() == &Level::No {
35 return write!(f, "Actor::Anonymous");
36 }
37
38 write!(
39 f,
40 "{}{}::{}({})",
41 self.res.level(),
42 self.res.kind(),
43 self.res.id(),
44 self.roles.iter().map(|r| format!("{}", r)).collect::<Vec<String>>().join(", ")
45 )
46 }
47}
48
49impl Actor {
50 pub fn new(id: String, roles: Vec<Role>, level: Level) -> Self {
51 Self {
52 res: Resource::new(id, super::ResourceKind::Actor, level),
53 roles,
54 }
55 }
56
57 pub fn has_role(&self, role: &Role) -> bool {
59 self.roles.contains(role)
60 }
61
62 pub fn cedar_attrs(&self) -> HashMap<String, RestrictedExpression> {
64 [
65 ("type", self.kind().into()),
66 ("level", self.level().into()),
67 ("roles", RestrictedExpression::new_set(self.roles.iter().map(|r| r.into()))),
68 ]
69 .into_iter()
70 .map(|(x, v)| (x.into(), v))
71 .collect()
72 }
73
74 pub fn cedar_parents(&self) -> HashSet<EntityUid> {
75 let mut parents = HashSet::with_capacity(1);
76 parents.insert(self.res.level().into());
77 parents
78 }
79
80 pub fn cedar_entities(&self) -> Vec<Entity> {
81 let mut entities = Vec::new();
82
83 entities.push(self.into());
84
85 for role in self.roles.iter() {
86 entities.push(role.into());
87 }
88
89 for level in self.res.level().cedar_entities() {
90 entities.push(level);
91 }
92
93 entities
94 }
95}
96
97impl Deref for Actor {
98 type Target = Resource;
99 fn deref(&self) -> &Self::Target {
100 &self.res
101 }
102}
103
104impl std::convert::From<&Actor> for EntityUid {
105 fn from(actor: &Actor) -> Self {
106 EntityUid::from_type_name_and_id(
107 EntityTypeName::from_str("Actor").unwrap(),
108 EntityId::from_str(actor.id()).unwrap(),
109 )
110 }
111}
112
113impl std::convert::From<&Actor> for Entity {
114 fn from(actor: &Actor) -> Self {
115 Entity::new(actor.into(), actor.cedar_attrs(), actor.cedar_parents())
116 }
117}
118
119impl std::convert::From<(&DefineUserStatement, Level)> for Actor {
120 fn from(val: (&DefineUserStatement, Level)) -> Self {
121 Self::new(val.0.name.to_string(), val.0.roles.iter().map(Role::from).collect(), val.1)
122 }
123}
124
125impl std::convert::From<(&DefineTokenStatement, Level)> for Actor {
126 fn from(val: (&DefineTokenStatement, Level)) -> Self {
127 Self::new(val.0.name.to_string(), Vec::default(), val.1)
128 }
129}