made_client/
authorization.rs1use made_proto::v1::{
2 ApproveAuthorizationOperationRequest, AuthorizationDecisionRecord, AuthorizationPolicyRecord,
3 IssueAuthorizationGrantRequest, IssueAuthorizationGrantResponse,
4 ListAuthorizationDecisionsRequest, ListAuthorizationDecisionsResponse,
5 RevokeAuthorizationGrantRequest, RevokeAuthorizationGrantResponse,
6};
7
8use crate::{MadeClient, MadeClientError};
9
10impl MadeClient {
11 pub async fn approve_authorization_operation(
12 &self,
13 request: ApproveAuthorizationOperationRequest,
14 ) -> Result<AuthorizationDecisionRecord, MadeClientError> {
15 let response = self
16 .rpc()
17 .approve_authorization_operation(Self::request(
18 &self.context(),
19 "/underpass.made.v1.MadeService/ApproveAuthorizationOperation",
20 request,
21 ))
22 .await
23 .map_err(MadeClientError::from_status)?
24 .into_inner();
25 response.decision.ok_or_else(|| {
26 MadeClientError::ProtocolViolation(
27 "approve authorization operation response has no decision".to_owned(),
28 )
29 })
30 }
31
32 pub async fn authorization_policy(&self) -> Result<AuthorizationPolicyRecord, MadeClientError> {
33 let response = self
34 .rpc()
35 .get_authorization_policy(Self::request(
36 &self.context(),
37 "/underpass.made.v1.MadeService/GetAuthorizationPolicy",
38 made_proto::v1::GetAuthorizationPolicyRequest {},
39 ))
40 .await
41 .map_err(MadeClientError::from_status)?
42 .into_inner();
43 response.policy.ok_or_else(|| {
44 MadeClientError::ProtocolViolation(
45 "get authorization policy response has no policy".to_owned(),
46 )
47 })
48 }
49
50 pub async fn issue_authorization_grant(
51 &self,
52 request: IssueAuthorizationGrantRequest,
53 ) -> Result<IssueAuthorizationGrantResponse, MadeClientError> {
54 self.rpc()
55 .issue_authorization_grant(Self::request(
56 &self.context(),
57 "/underpass.made.v1.MadeService/IssueAuthorizationGrant",
58 request,
59 ))
60 .await
61 .map(tonic::Response::into_inner)
62 .map_err(MadeClientError::from_status)
63 }
64
65 pub async fn revoke_authorization_grant(
66 &self,
67 grant_id: impl Into<String>,
68 reason: impl Into<String>,
69 ) -> Result<RevokeAuthorizationGrantResponse, MadeClientError> {
70 self.rpc()
71 .revoke_authorization_grant(Self::request(
72 &self.context(),
73 "/underpass.made.v1.MadeService/RevokeAuthorizationGrant",
74 RevokeAuthorizationGrantRequest {
75 grant_id: grant_id.into(),
76 reason: reason.into(),
77 },
78 ))
79 .await
80 .map(tonic::Response::into_inner)
81 .map_err(MadeClientError::from_status)
82 }
83
84 pub async fn authorization_decisions(
85 &self,
86 after_decision_id: Option<String>,
87 limit: u32,
88 ) -> Result<ListAuthorizationDecisionsResponse, MadeClientError> {
89 self.rpc()
90 .list_authorization_decisions(Self::request(
91 &self.context(),
92 "/underpass.made.v1.MadeService/ListAuthorizationDecisions",
93 ListAuthorizationDecisionsRequest {
94 after_decision_id,
95 limit,
96 },
97 ))
98 .await
99 .map(tonic::Response::into_inner)
100 .map_err(MadeClientError::from_status)
101 }
102}
103
104#[must_use]
109pub fn authorization_target_digest<T: prost::Message>(request: &T) -> String {
110 use sha2::{Digest, Sha256};
111
112 format!("{:x}", Sha256::digest(request.encode_to_vec()))
113}
114
115#[cfg(test)]
116mod tests {
117 use std::collections::BTreeMap;
118
119 use made_proto::v1::BindCeremonyParticipantsRequest;
120
121 use super::authorization_target_digest;
122
123 #[test]
124 fn target_digest_is_stable_for_canonical_protobuf_maps() {
125 let left = BindCeremonyParticipantsRequest {
126 ceremony_id: "ceremony-1".to_owned(),
127 seating: BTreeMap::from([
128 ("reviewer".to_owned(), "review".to_owned()),
129 ("author".to_owned(), "writing".to_owned()),
130 ]),
131 ..Default::default()
132 };
133 let right = BindCeremonyParticipantsRequest {
134 ceremony_id: "ceremony-1".to_owned(),
135 seating: BTreeMap::from([
136 ("author".to_owned(), "writing".to_owned()),
137 ("reviewer".to_owned(), "review".to_owned()),
138 ]),
139 ..Default::default()
140 };
141
142 assert_eq!(
143 authorization_target_digest(&left),
144 authorization_target_digest(&right)
145 );
146 }
147}