grafbase_sdk/types/
authorization.rs

1use crate::wit;
2
3use super::Error;
4
5/// Error identifier to allow re-using the same error for multiple elements. In the gateway
6/// response, the error will be repeated if necessary during serialization.
7#[derive(Clone, Copy)]
8pub struct ErrorId(u32);
9
10/// Authorization decisions for each query elements to be applied by the GraphQL engine.
11pub struct AuthorizationDecisions(wit::AuthorizationDecisions);
12
13impl From<AuthorizationDecisions> for wit::AuthorizationDecisions {
14    fn from(value: AuthorizationDecisions) -> Self {
15        value.0
16    }
17}
18
19impl AuthorizationDecisions {
20    /// Grant access all elements in the query.
21    pub fn grant_all() -> Self {
22        Self(wit::AuthorizationDecisions::GrantAll)
23    }
24
25    /// Deny access to all elements in the query with the specified error
26    pub fn deny_all(error: impl Into<Error>) -> Self {
27        Self(wit::AuthorizationDecisions::DenyAll(Into::<Error>::into(error).into()))
28    }
29
30    /// Create a `DenySomeBuilder` best suited to deny some elements. By
31    /// default, all elements are granted access.
32    pub fn deny_some_builder() -> DenySomeBuilder {
33        DenySomeBuilder(wit::AuthorizationDecisionsDenySome {
34            element_to_error: Vec::new(),
35            errors: Vec::new(),
36        })
37    }
38}
39
40/// To be used when denying some of the elements. By default everything is granted.
41pub struct DenySomeBuilder(wit::AuthorizationDecisionsDenySome);
42
43impl DenySomeBuilder {
44    /// Deny access to the specified element in the query with the specified error.
45    pub fn deny(&mut self, x: impl private::QueryElementOrResponseItem, error: impl Into<Error>) {
46        let error_id = self.push_error(error);
47        self.deny_with_error_id(x, error_id)
48    }
49
50    /// Deny access to the specified element in the query, re-using an existing error.
51    pub fn deny_with_error_id(&mut self, x: impl private::QueryElementOrResponseItem, error_id: ErrorId) {
52        self.0.element_to_error.push((x.ix(), error_id.0));
53    }
54
55    /// Returns an ErrorId that can be used to reference this error later in `deny_with_error_id`.
56    pub fn push_error(&mut self, error: impl Into<Error>) -> ErrorId {
57        let error_ix = self.0.errors.len() as u32;
58        self.0.errors.push(Into::<Error>::into(error).into());
59        ErrorId(error_ix)
60    }
61
62    /// Build the final AuthorizationDecisions
63    pub fn build(self) -> AuthorizationDecisions {
64        AuthorizationDecisions(wit::AuthorizationDecisions::DenySome(self.0))
65    }
66}
67
68pub(super) mod private {
69    /// Either a `QueryElement` or a `ResponseItem`.
70    pub trait QueryElementOrResponseItem: crate::sealed::Sealed {
71        #[doc(hidden)]
72        fn ix(&self) -> u32;
73    }
74}