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
43/// Either a `QueryElement` or a `ResponseItem`.
44pub trait QueryElementOrResponseItem: crate::sealed::Sealed {
45    #[doc(hidden)]
46    fn ix(&self) -> u32;
47}
48
49impl DenySomeBuilder {
50    /// Deny access to the specified element in the query with the specified error.
51    pub fn deny(&mut self, element: impl QueryElementOrResponseItem, error: impl Into<Error>) {
52        let error_id = self.push_error(error);
53        self.deny_with_error_id(element, error_id)
54    }
55
56    /// Deny access to the specified element in the query, re-using an existing error.
57    pub fn deny_with_error_id(&mut self, element: impl QueryElementOrResponseItem, error_id: ErrorId) {
58        self.0.element_to_error.push((element.ix(), error_id.0));
59    }
60
61    /// Returns an ErrorId that can be used to reference this error later in `deny_with_error_id`.
62    pub fn push_error(&mut self, error: impl Into<Error>) -> ErrorId {
63        let error_ix = self.0.errors.len() as u32;
64        self.0.errors.push(Into::<Error>::into(error).into());
65        ErrorId(error_ix)
66    }
67
68    /// Build the final AuthorizationDecisions
69    pub fn build(self) -> AuthorizationDecisions {
70        AuthorizationDecisions(wit::AuthorizationDecisions::DenySome(self.0))
71    }
72}