oso_cloud/
local_filtering.rs1use serde::{Deserialize, Serialize};
2
3use crate::{Oso, Value};
4
5type Result<T> = core::result::Result<T, crate::Error>;
6
7#[derive(Clone, Debug)]
11pub struct LocalFilteringHandle<S> {
12 oso: Oso,
13 data_bindings: S,
14}
15
16impl Oso {
17 pub fn into_local_filtering_handle<S>(self, data_bindings: S) -> LocalFilteringHandle<S> {
19 LocalFilteringHandle {
20 oso: self,
21 data_bindings,
22 }
23 }
24}
25
26impl<S> LocalFilteringHandle<S> {
27 pub fn oso(&self) -> &Oso {
29 &self.oso
30 }
31}
32
33#[derive(Deserialize)]
34struct LocalQueryResult {
35 sql: String,
36}
37
38impl<S: AsRef<str>> LocalFilteringHandle<S> {
39 pub async fn authorize_local(
50 &self,
51 actor: impl Into<Value<'_>>,
52 action: &str,
53 resource: impl Into<Value<'_>>,
54 ) -> Result<String> {
55 #[derive(Debug, Serialize)]
56 struct AuthorizeRequest<'a> {
57 actor_type: &'a str,
58 actor_id: &'a str,
59 action: &'a str,
60 resource_type: &'a str,
61 resource_id: &'a str,
62 }
63 #[derive(Debug, Serialize)]
64 struct LocalAuthQuery<'a> {
65 query: AuthorizeRequest<'a>,
66 data_bindings: &'a str,
67 }
68
69 let actor = actor.into();
70 let resource = resource.into();
71 let (Some(actor_type), Some(actor_id)) = (actor.type_.as_ref(), actor.id.as_ref()) else {
72 return Err(crate::Error::Input(
73 "Actor must be a concrete value. Try `oso.query` if you want to get all permitted actors".to_owned(),
74 ));
75 };
76 let (Some(resource_type), Some(resource_id)) = (resource.type_.as_ref(), resource.id.as_ref()) else {
77 return Err(crate::Error::Input(
78 "Resource must be a concrete value. Try `oso.list` if you want to get all allowed resources".to_owned(),
79 ));
80 };
81
82 let query = AuthorizeRequest {
83 actor_type,
84 actor_id,
85 action,
86 resource_type,
87 resource_id,
88 };
89
90 let body = LocalAuthQuery {
91 query,
92 data_bindings: self.data_bindings.as_ref(),
93 };
94
95 let resp: LocalQueryResult = self.oso.client.post("authorize_query", &body, false).await?;
96
97 Ok(resp.sql)
98 }
99
100 pub async fn list_local(
103 &self,
104 actor: impl Into<Value<'_>>,
105 action: &str,
106 resource_type: &str,
107 column: &str,
108 ) -> Result<String> {
109 #[derive(Debug, Serialize)]
110 struct ListRequest<'a> {
111 actor_type: &'a str,
112 actor_id: &'a str,
113 action: &'a str,
114 resource_type: &'a str,
115 }
116 #[derive(Debug, Serialize)]
117 struct LocalListQuery<'a> {
118 query: ListRequest<'a>,
119 column: &'a str,
120 data_bindings: &'a str,
121 }
122
123 let actor = actor.into();
124
125 let (Some(actor_type), Some(actor_id)) = (actor.type_.as_ref(), actor.id.as_ref()) else {
126 return Err(crate::Error::Input(
127 "Actor must be a concrete value. Try `oso.query` if you want to get all permitted actors".to_owned(),
128 ));
129 };
130
131 let query = ListRequest {
132 actor_type,
133 actor_id,
134 action,
135 resource_type,
136 };
137
138 let body = LocalListQuery {
139 query,
140 column,
141 data_bindings: self.data_bindings.as_ref(),
142 };
143
144 let resp: LocalQueryResult = self.oso.client.post("list_query", &body, false).await?;
145 Ok(resp.sql)
146 }
147}