1use crate::codec::authorization::{
6 from_wire_add_relationship_response, from_wire_check_access_many_response,
7 from_wire_check_access_response, from_wire_delete_relationship_response,
8 from_wire_get_active_model_ref_response, from_wire_list_active_model_resource_types_response,
9 from_wire_list_relationships_response, from_wire_set_active_model_response,
10 from_wire_set_authorization_state_response, to_wire_add_relationship_request,
11 to_wire_check_access_many_request, to_wire_check_access_request,
12 to_wire_delete_relationship_request, to_wire_list_active_model_resource_types_request,
13 to_wire_list_relationships_request, to_wire_set_active_model_request,
14 to_wire_set_authorization_state_request,
15};
16use crate::codec::host_service::{HostServiceChannel, connect_host_service, plain_channel};
17use crate::generated::v1;
18use crate::rpc_support::GestaltError;
19
20pub type RelationshipTargetType = i32;
22
23pub mod relationship_target_type {
25 pub const RELATIONSHIP_TARGET_TYPE_UNSPECIFIED: i32 = 0;
27 pub const RELATIONSHIP_TARGET_TYPE_SUBJECT: i32 = 1;
29 pub const RELATIONSHIP_TARGET_TYPE_RESOURCE: i32 = 2;
31 pub const RELATIONSHIP_TARGET_TYPE_SUBJECT_SET: i32 = 3;
33}
34
35pub type SourceLayer = i32;
37
38pub mod source_layer {
40 pub const SOURCE_LAYER_UNSPECIFIED: i32 = 0;
42 pub const SOURCE_LAYER_STATIC_CONFIG: i32 = 1;
44 pub const SOURCE_LAYER_RUNTIME: i32 = 2;
46}
47
48#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
50#[serde(rename_all = "camelCase")]
51pub struct Action {
52 pub name: String,
54 pub properties: Option<serde_json::Map<String, serde_json::Value>>,
56}
57
58#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
60#[serde(rename_all = "camelCase")]
61pub struct AddRelationshipRequest {
62 pub relationship: Option<Relationship>,
64}
65
66#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
68#[serde(rename_all = "camelCase")]
69pub struct AddRelationshipResponse {
70 pub relationship: Option<Relationship>,
72}
73
74#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
76#[serde(rename_all = "camelCase")]
77pub struct AuthorizationModel {
78 pub id: String,
80 pub version: String,
82 pub resource_types: Vec<AuthorizationModelResourceType>,
84}
85
86#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
88#[serde(rename_all = "camelCase")]
89pub struct AuthorizationModelRef {
90 pub id: String,
92 pub version: String,
94 #[serde(with = "crate::serde_time")]
95 pub created_at: Option<std::time::SystemTime>,
97}
98
99#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
101#[serde(rename_all = "camelCase")]
102pub struct AuthorizationModelResourceType {
103 pub name: String,
105 pub relations: Vec<ModelRelation>,
107 pub actions: Vec<ModelAction>,
109 pub source_layer: SourceLayer,
111 pub default_role: String,
113}
114
115#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
117#[serde(rename_all = "camelCase")]
118pub struct AuthorizationModelResourceTypeFilter {
119 pub name: String,
121 pub source_layer: SourceLayer,
123}
124
125#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
127#[serde(rename_all = "camelCase")]
128pub struct CheckAccessManyRequest {
129 pub requests: Vec<CheckAccessRequest>,
131}
132
133#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
135#[serde(rename_all = "camelCase")]
136pub struct CheckAccessManyResponse {
137 pub decisions: Vec<CheckAccessResponse>,
139}
140
141#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
143#[serde(rename_all = "camelCase")]
144pub struct CheckAccessRequest {
145 pub subject: Option<Subject>,
147 pub action: Option<Action>,
149 pub resource: Option<Resource>,
151}
152
153#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
155#[serde(rename_all = "camelCase")]
156pub struct CheckAccessResponse {
157 pub allowed: bool,
159 pub model_id: String,
161}
162
163#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
165#[serde(rename_all = "camelCase")]
166pub struct DeleteRelationshipRequest {
167 pub relationship_tuple: Option<RelationshipTuple>,
169}
170
171#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
173#[serde(rename_all = "camelCase")]
174pub struct DeleteRelationshipResponse {}
175
176#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
178#[serde(rename_all = "camelCase")]
179pub struct GetActiveModelRefResponse {
180 pub model: Option<AuthorizationModelRef>,
182}
183
184#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
186#[serde(rename_all = "camelCase")]
187pub struct ListActiveModelResourceTypesRequest {
188 pub filter: Option<AuthorizationModelResourceTypeFilter>,
190 pub page_size: i32,
192 pub page_token: String,
194}
195
196#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
198#[serde(rename_all = "camelCase")]
199pub struct ListActiveModelResourceTypesResponse {
200 pub resource_types: Vec<AuthorizationModelResourceType>,
202 pub next_page_token: String,
204 pub model_id: String,
206}
207
208#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
210#[serde(rename_all = "camelCase")]
211pub struct ListRelationshipsRequest {
212 pub filter: Option<RelationshipFilter>,
214 pub page_size: i32,
216 pub page_token: String,
218}
219
220#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
222#[serde(rename_all = "camelCase")]
223pub struct ListRelationshipsResponse {
224 pub relationships: Vec<Relationship>,
226 pub next_page_token: String,
228}
229
230#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
232#[serde(rename_all = "camelCase")]
233pub struct ModelAction {
234 pub name: String,
236 pub relations: Vec<String>,
238}
239
240#[allow(clippy::enum_variant_names, clippy::large_enum_variant)]
242#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
243pub enum ModelAllowedTargetKind {
244 SubjectType(String),
246 ResourceType(String),
248 SubjectSetType(SubjectSetType),
250}
251
252#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
254#[serde(rename_all = "camelCase")]
255pub struct ModelAllowedTarget {
256 pub kind: Option<ModelAllowedTargetKind>,
258}
259
260#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
262#[serde(rename_all = "camelCase")]
263pub struct ModelRelation {
264 pub name: String,
266 pub allowed_targets: Vec<ModelAllowedTarget>,
268}
269
270#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
272#[serde(rename_all = "camelCase")]
273pub struct Relationship {
274 pub tuple: Option<RelationshipTuple>,
276 pub properties: Option<serde_json::Map<String, serde_json::Value>>,
278 pub source_layer: SourceLayer,
280}
281
282#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
284#[serde(rename_all = "camelCase")]
285pub struct RelationshipFilter {
286 pub target: Option<RelationshipTarget>,
288 pub relation: String,
290 pub resource: Option<Resource>,
292 pub target_type: RelationshipTargetType,
294 pub target_entity_type: String,
296 pub resource_type: String,
298 pub source_layer: SourceLayer,
300}
301
302#[allow(clippy::enum_variant_names, clippy::large_enum_variant)]
304#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
305pub enum RelationshipTargetKind {
306 Subject(Subject),
308 Resource(Resource),
310 SubjectSet(SubjectSet),
312}
313
314#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
316#[serde(rename_all = "camelCase")]
317pub struct RelationshipTarget {
318 pub kind: Option<RelationshipTargetKind>,
320}
321
322#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
324#[serde(rename_all = "camelCase")]
325pub struct RelationshipTuple {
326 pub target: Option<RelationshipTarget>,
328 pub relation: String,
330 pub resource: Option<Resource>,
332}
333
334#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
336#[serde(rename_all = "camelCase")]
337pub struct Resource {
338 pub r#type: String,
340 pub id: String,
342 pub properties: Option<serde_json::Map<String, serde_json::Value>>,
344}
345
346#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
348#[serde(rename_all = "camelCase")]
349pub struct SetActiveModelRequest {
350 pub model: Option<AuthorizationModel>,
352}
353
354#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
356#[serde(rename_all = "camelCase")]
357pub struct SetActiveModelResponse {
358 pub model: Option<AuthorizationModelRef>,
360}
361
362#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
364#[serde(rename_all = "camelCase")]
365pub struct SetAuthorizationStateRequest {
366 pub model: Option<AuthorizationModel>,
368 pub relationships: Vec<Relationship>,
370}
371
372#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
374#[serde(rename_all = "camelCase")]
375pub struct SetAuthorizationStateResponse {
376 pub active_model: Option<AuthorizationModelRef>,
378}
379
380#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
382#[serde(rename_all = "camelCase")]
383pub struct Subject {
384 pub r#type: String,
386 pub id: String,
388 pub properties: Option<serde_json::Map<String, serde_json::Value>>,
390}
391
392#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
394#[serde(rename_all = "camelCase")]
395pub struct SubjectSet {
396 pub resource: Option<Resource>,
398 pub relation: String,
400}
401
402#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
404#[serde(rename_all = "camelCase")]
405pub struct SubjectSetType {
406 pub resource_type: String,
408 pub relation: String,
410}
411
412pub struct Authorization {
414 inner: v1::authorization_client::AuthorizationClient<HostServiceChannel>,
415 timeout: Option<std::time::Duration>,
416}
417
418impl Authorization {
419 pub fn new(channel: tonic::transport::Channel) -> Self {
421 Self {
422 inner: v1::authorization_client::AuthorizationClient::new(plain_channel(channel)),
423 timeout: None,
424 }
425 }
426
427 pub fn with_timeout(mut self, timeout: std::time::Duration) -> Self {
430 self.timeout = Some(timeout);
431 self
432 }
433
434 pub async fn connect() -> Result<Self, GestaltError> {
436 Self::connect_named("").await
437 }
438
439 pub async fn connect_named(name: &str) -> Result<Self, GestaltError> {
441 Ok(Self {
442 inner: v1::authorization_client::AuthorizationClient::new(
443 connect_host_service("authorization", name).await?,
444 ),
445 timeout: None,
446 })
447 }
448
449 pub async fn check_access(
451 &mut self,
452 action: Option<Action>,
453 resource: Option<Resource>,
454 ) -> Result<CheckAccessResponse, GestaltError> {
455 let request = CheckAccessRequest {
456 action,
457 resource,
458 ..Default::default()
459 };
460 let mut tonic_request = tonic::Request::new(to_wire_check_access_request(request));
461 if let Some(timeout) = self.timeout {
462 tonic_request.set_timeout(timeout);
463 }
464 let response = self.inner.check_access(tonic_request).await?;
465 Ok(from_wire_check_access_response(response.into_inner()))
466 }
467
468 pub async fn check_access_raw(
470 &mut self,
471 request: CheckAccessRequest,
472 ) -> Result<CheckAccessResponse, GestaltError> {
473 let mut tonic_request = tonic::Request::new(to_wire_check_access_request(request));
474 if let Some(timeout) = self.timeout {
475 tonic_request.set_timeout(timeout);
476 }
477 let response = self.inner.check_access(tonic_request).await?;
478 Ok(from_wire_check_access_response(response.into_inner()))
479 }
480
481 pub async fn check_access_many(
483 &mut self,
484 requests: Vec<CheckAccessRequest>,
485 ) -> Result<CheckAccessManyResponse, GestaltError> {
486 let request = CheckAccessManyRequest { requests };
487 let mut tonic_request = tonic::Request::new(to_wire_check_access_many_request(request));
488 if let Some(timeout) = self.timeout {
489 tonic_request.set_timeout(timeout);
490 }
491 let response = self.inner.check_access_many(tonic_request).await?;
492 Ok(from_wire_check_access_many_response(response.into_inner()))
493 }
494
495 pub async fn check_access_many_raw(
497 &mut self,
498 request: CheckAccessManyRequest,
499 ) -> Result<CheckAccessManyResponse, GestaltError> {
500 let mut tonic_request = tonic::Request::new(to_wire_check_access_many_request(request));
501 if let Some(timeout) = self.timeout {
502 tonic_request.set_timeout(timeout);
503 }
504 let response = self.inner.check_access_many(tonic_request).await?;
505 Ok(from_wire_check_access_many_response(response.into_inner()))
506 }
507
508 pub async fn list_relationships(
510 &mut self,
511 page_size: i32,
512 page_token: String,
513 filter: Option<RelationshipFilter>,
514 ) -> Result<ListRelationshipsResponse, GestaltError> {
515 let request = ListRelationshipsRequest {
516 page_size,
517 page_token,
518 filter,
519 };
520 let mut tonic_request = tonic::Request::new(to_wire_list_relationships_request(request));
521 if let Some(timeout) = self.timeout {
522 tonic_request.set_timeout(timeout);
523 }
524 let response = self.inner.list_relationships(tonic_request).await?;
525 Ok(from_wire_list_relationships_response(response.into_inner()))
526 }
527
528 pub async fn list_relationships_raw(
530 &mut self,
531 request: ListRelationshipsRequest,
532 ) -> Result<ListRelationshipsResponse, GestaltError> {
533 let mut tonic_request = tonic::Request::new(to_wire_list_relationships_request(request));
534 if let Some(timeout) = self.timeout {
535 tonic_request.set_timeout(timeout);
536 }
537 let response = self.inner.list_relationships(tonic_request).await?;
538 Ok(from_wire_list_relationships_response(response.into_inner()))
539 }
540
541 pub async fn add_relationship(
543 &mut self,
544 relationship: Option<Relationship>,
545 ) -> Result<Option<Relationship>, GestaltError> {
546 let request = AddRelationshipRequest { relationship };
547 let mut tonic_request = tonic::Request::new(to_wire_add_relationship_request(request));
548 if let Some(timeout) = self.timeout {
549 tonic_request.set_timeout(timeout);
550 }
551 let response = from_wire_add_relationship_response(
552 self.inner
553 .add_relationship(tonic_request)
554 .await?
555 .into_inner(),
556 );
557 Ok(response.relationship)
558 }
559
560 pub async fn add_relationship_raw(
562 &mut self,
563 request: AddRelationshipRequest,
564 ) -> Result<AddRelationshipResponse, GestaltError> {
565 let mut tonic_request = tonic::Request::new(to_wire_add_relationship_request(request));
566 if let Some(timeout) = self.timeout {
567 tonic_request.set_timeout(timeout);
568 }
569 let response = self.inner.add_relationship(tonic_request).await?;
570 Ok(from_wire_add_relationship_response(response.into_inner()))
571 }
572
573 pub async fn delete_relationship(
575 &mut self,
576 relationship_tuple: Option<RelationshipTuple>,
577 ) -> Result<DeleteRelationshipResponse, GestaltError> {
578 let request = DeleteRelationshipRequest { relationship_tuple };
579 let mut tonic_request = tonic::Request::new(to_wire_delete_relationship_request(request));
580 if let Some(timeout) = self.timeout {
581 tonic_request.set_timeout(timeout);
582 }
583 let response = self.inner.delete_relationship(tonic_request).await?;
584 Ok(from_wire_delete_relationship_response(
585 response.into_inner(),
586 ))
587 }
588
589 pub async fn delete_relationship_raw(
591 &mut self,
592 request: DeleteRelationshipRequest,
593 ) -> Result<DeleteRelationshipResponse, GestaltError> {
594 let mut tonic_request = tonic::Request::new(to_wire_delete_relationship_request(request));
595 if let Some(timeout) = self.timeout {
596 tonic_request.set_timeout(timeout);
597 }
598 let response = self.inner.delete_relationship(tonic_request).await?;
599 Ok(from_wire_delete_relationship_response(
600 response.into_inner(),
601 ))
602 }
603
604 pub async fn set_authorization_state(
606 &mut self,
607 relationships: Vec<Relationship>,
608 model: Option<AuthorizationModel>,
609 ) -> Result<Option<AuthorizationModelRef>, GestaltError> {
610 let request = SetAuthorizationStateRequest {
611 relationships,
612 model,
613 };
614 let mut tonic_request =
615 tonic::Request::new(to_wire_set_authorization_state_request(request));
616 if let Some(timeout) = self.timeout {
617 tonic_request.set_timeout(timeout);
618 }
619 let response = from_wire_set_authorization_state_response(
620 self.inner
621 .set_authorization_state(tonic_request)
622 .await?
623 .into_inner(),
624 );
625 Ok(response.active_model)
626 }
627
628 pub async fn set_authorization_state_raw(
630 &mut self,
631 request: SetAuthorizationStateRequest,
632 ) -> Result<SetAuthorizationStateResponse, GestaltError> {
633 let mut tonic_request =
634 tonic::Request::new(to_wire_set_authorization_state_request(request));
635 if let Some(timeout) = self.timeout {
636 tonic_request.set_timeout(timeout);
637 }
638 let response = self.inner.set_authorization_state(tonic_request).await?;
639 Ok(from_wire_set_authorization_state_response(
640 response.into_inner(),
641 ))
642 }
643
644 pub async fn get_active_model_ref(
646 &mut self,
647 ) -> Result<Option<AuthorizationModelRef>, GestaltError> {
648 let mut tonic_request = tonic::Request::new(());
649 if let Some(timeout) = self.timeout {
650 tonic_request.set_timeout(timeout);
651 }
652 let response = from_wire_get_active_model_ref_response(
653 self.inner
654 .get_active_model_ref(tonic_request)
655 .await?
656 .into_inner(),
657 );
658 Ok(response.model)
659 }
660
661 pub async fn get_active_model_ref_raw(
663 &mut self,
664 ) -> Result<GetActiveModelRefResponse, GestaltError> {
665 let mut tonic_request = tonic::Request::new(());
666 if let Some(timeout) = self.timeout {
667 tonic_request.set_timeout(timeout);
668 }
669 let response = self.inner.get_active_model_ref(tonic_request).await?;
670 Ok(from_wire_get_active_model_ref_response(
671 response.into_inner(),
672 ))
673 }
674
675 pub async fn set_active_model(
677 &mut self,
678 model: Option<AuthorizationModel>,
679 ) -> Result<Option<AuthorizationModelRef>, GestaltError> {
680 let request = SetActiveModelRequest { model };
681 let mut tonic_request = tonic::Request::new(to_wire_set_active_model_request(request));
682 if let Some(timeout) = self.timeout {
683 tonic_request.set_timeout(timeout);
684 }
685 let response = from_wire_set_active_model_response(
686 self.inner
687 .set_active_model(tonic_request)
688 .await?
689 .into_inner(),
690 );
691 Ok(response.model)
692 }
693
694 pub async fn set_active_model_raw(
696 &mut self,
697 request: SetActiveModelRequest,
698 ) -> Result<SetActiveModelResponse, GestaltError> {
699 let mut tonic_request = tonic::Request::new(to_wire_set_active_model_request(request));
700 if let Some(timeout) = self.timeout {
701 tonic_request.set_timeout(timeout);
702 }
703 let response = self.inner.set_active_model(tonic_request).await?;
704 Ok(from_wire_set_active_model_response(response.into_inner()))
705 }
706
707 pub async fn list_active_model_resource_types(
709 &mut self,
710 page_size: i32,
711 page_token: String,
712 filter: Option<AuthorizationModelResourceTypeFilter>,
713 ) -> Result<ListActiveModelResourceTypesResponse, GestaltError> {
714 let request = ListActiveModelResourceTypesRequest {
715 page_size,
716 page_token,
717 filter,
718 };
719 let mut tonic_request =
720 tonic::Request::new(to_wire_list_active_model_resource_types_request(request));
721 if let Some(timeout) = self.timeout {
722 tonic_request.set_timeout(timeout);
723 }
724 let response = self
725 .inner
726 .list_active_model_resource_types(tonic_request)
727 .await?;
728 Ok(from_wire_list_active_model_resource_types_response(
729 response.into_inner(),
730 ))
731 }
732
733 pub async fn list_active_model_resource_types_raw(
735 &mut self,
736 request: ListActiveModelResourceTypesRequest,
737 ) -> Result<ListActiveModelResourceTypesResponse, GestaltError> {
738 let mut tonic_request =
739 tonic::Request::new(to_wire_list_active_model_resource_types_request(request));
740 if let Some(timeout) = self.timeout {
741 tonic_request.set_timeout(timeout);
742 }
743 let response = self
744 .inner
745 .list_active_model_resource_types(tonic_request)
746 .await?;
747 Ok(from_wire_list_active_model_resource_types_response(
748 response.into_inner(),
749 ))
750 }
751}