Skip to main content

authz_core/
traits.rs

1//! Core datastore traits — TupleReader, TupleWriter, PolicyReader, PolicyWriter.
2
3use async_trait::async_trait;
4
5use crate::error::AuthzError;
6
7/// A relationship tuple: object#relation@subject (optionally with condition).
8#[derive(Debug, Clone, PartialEq, Eq)]
9pub struct Tuple {
10    pub object_type: String,
11    pub object_id: String,
12    pub relation: String,
13    pub subject_type: String,
14    pub subject_id: String,
15    pub condition: Option<String>,
16}
17
18/// Filter for tuple queries. All fields are optional.
19#[derive(Debug, Clone, Default)]
20pub struct TupleFilter {
21    pub object_type: Option<String>,
22    pub object_id: Option<String>,
23    pub relation: Option<String>,
24    pub subject_type: Option<String>,
25    pub subject_id: Option<String>,
26}
27
28/// Authorization policy (DSL definition).
29#[derive(Debug, Clone, PartialEq, Eq)]
30pub struct AuthorizationPolicy {
31    pub id: String,
32    pub definition: String,
33}
34
35/// Pagination for list operations.
36#[derive(Debug, Clone, Default)]
37pub struct Pagination {
38    pub page_size: usize,
39    pub continuation_token: Option<String>,
40}
41
42/// Reads tuples from the datastore.
43#[async_trait]
44pub trait TupleReader: Send + Sync {
45    async fn read_tuples(&self, filter: &TupleFilter) -> Result<Vec<Tuple>, AuthzError>;
46    async fn read_user_tuple(
47        &self,
48        object_type: &str,
49        object_id: &str,
50        relation: &str,
51        subject_type: &str,
52        subject_id: &str,
53    ) -> Result<Option<Tuple>, AuthzError>;
54    async fn read_userset_tuples(
55        &self,
56        object_type: &str,
57        object_id: &str,
58        relation: &str,
59    ) -> Result<Vec<Tuple>, AuthzError>;
60    async fn read_starting_with_user(
61        &self,
62        subject_type: &str,
63        subject_id: &str,
64    ) -> Result<Vec<Tuple>, AuthzError>;
65
66    /// Batch read: check if any of the given relations match for a user.
67    /// Returns the first matching tuple, or None if no match found.
68    async fn read_user_tuple_batch(
69        &self,
70        object_type: &str,
71        object_id: &str,
72        relations: &[String],
73        subject_type: &str,
74        subject_id: &str,
75    ) -> Result<Option<Tuple>, AuthzError>;
76}
77
78/// Writes tuples to the datastore.
79#[async_trait]
80pub trait TupleWriter: Send + Sync {
81    async fn write_tuples(&self, writes: &[Tuple], deletes: &[Tuple])
82    -> Result<String, AuthzError>;
83}
84
85/// Reads authorization policies.
86#[async_trait]
87pub trait PolicyReader: Send + Sync {
88    async fn read_authorization_policy(
89        &self,
90        id: &str,
91    ) -> Result<Option<AuthorizationPolicy>, AuthzError>;
92    async fn read_latest_authorization_policy(
93        &self,
94    ) -> Result<Option<AuthorizationPolicy>, AuthzError>;
95    async fn list_authorization_policies(
96        &self,
97        pagination: &Pagination,
98    ) -> Result<Vec<AuthorizationPolicy>, AuthzError>;
99}
100
101/// Writes authorization policies.
102#[async_trait]
103pub trait PolicyWriter: Send + Sync {
104    async fn write_authorization_policy(
105        &self,
106        policy: &AuthorizationPolicy,
107    ) -> Result<String, AuthzError>;
108}
109
110/// Reads revision information from the datastore.
111#[async_trait]
112pub trait RevisionReader: Send + Sync {
113    /// Read the latest revision ID from the datastore.
114    /// Returns "0" if no revisions exist yet (bootstrap case).
115    async fn read_latest_revision(&self) -> Result<String, AuthzError>;
116}