spicedb_rust/entity.rs
1use std::str::FromStr;
2
3use crate::spicedb;
4
5/// An entity is any object in your SpiceDB system
6/// The Id type represents whatever rust type you're using internally, since SpiceDB only uses
7/// Strings to avoid having to convert and deal with errors everywhere we use trait bounds `FromStr` and `Into<String>`
8/// which a lot of common Id types like `Uuid` or `u32` already implement.
9pub trait Entity {
10 type Relations: Relation;
11 type Id: FromStr + Into<String>;
12
13 fn object_type() -> &'static str;
14}
15
16/// Represents possible relations to an `Entity`
17/// Easiest way to implement is implementing `Into<&'static str>` for your enum, which can builder
18/// achieved with `strum::IntoStaticStr`
19pub trait Relation {
20 fn name(self) -> &'static str;
21}
22
23/// A resource is any `Entity` that also has `Permissions` associated
24pub trait Resource: Entity {
25 type Permissions: Permission;
26}
27
28/// Represents possible permissions on a `Resource`
29/// Easiest way to implement is implementing `Into<&'static str>` for your enum, which can builder
30/// achieved with `strum::IntoStaticStr`
31pub trait Permission {
32 fn name(self) -> &'static str;
33}
34
35impl<S> Permission for S
36where
37 S: Into<&'static str>,
38{
39 fn name(self) -> &'static str {
40 self.into()
41 }
42}
43
44impl<S> Relation for S
45where
46 S: Into<&'static str>,
47{
48 fn name(self) -> &'static str {
49 self.into()
50 }
51}
52
53pub trait Caveat {
54 type ContextStruct: Into<prost_types::Struct>;
55 fn name() -> &'static str;
56}
57
58/// Implement the Actor trait for any struct that will represent someone/something taking action in
59/// your system. it could for example be an enum wrapping User/Organization/Service if those are
60/// entities that can take action.
61/// ```rust
62/// pub enum SystemActor {
63/// User(Uuid),
64/// Organization(String),
65/// Service(Uuid),
66/// }
67/// ```
68pub trait Actor {
69 fn to_subject(&self) -> spicedb::SubjectReference;
70}
71
72pub struct NoCaveat;
73
74impl Caveat for NoCaveat {
75 type ContextStruct = prost_types::Struct;
76
77 fn name() -> &'static str {
78 unreachable!()
79 }
80}
81
82/// Use this time for `Relations` when implementing `Entity` for something that will never have a
83/// any relation to.
84pub struct NoRelations;
85
86impl Relation for NoRelations {
87 fn name(self) -> &'static str {
88 unreachable!()
89 }
90}
91
92impl FromStr for NoRelations {
93 type Err = ();
94
95 fn from_str(_: &str) -> Result<Self, Self::Err> {
96 unreachable!()
97 }
98}
99
100/// Use this type to build your wildcard entity types.
101/// Often there already are wildcard shortcuts like `add_wildcard_relationship` in the
102/// `write_relationships_request` builder that can be used instead of this.
103/// However for more niche usecases where you need to pass in a WildCard user for an entity in an
104/// operation that currently doesn't have a shortcut, this can be implemented and used.
105/// ```rust
106/// pub struct WildCardUser;
107///
108/// impl Entity for WildCardUser {
109/// type Id = WildCardId;
110/// type Relations = NoRelations;
111///
112/// fn object_type() -> &'static str {
113/// User::object_type()
114/// }
115/// }
116/// ```
117pub struct WildCardId;
118
119impl FromStr for WildCardId {
120 type Err = ();
121
122 fn from_str(_: &str) -> Result<Self, Self::Err> {
123 unreachable!()
124 }
125}
126
127impl From<WildCardId> for String {
128 fn from(_: WildCardId) -> Self {
129 "*".into()
130 }
131}