grafbase_sdk/extension/
authorization.rs

1use crate::{
2    component::AnyExtension,
3    host::AuthorizationContext,
4    types::{AuthorizationDecisions, Configuration, ErrorResponse, QueryElements, ResponseElements},
5    Error,
6};
7
8/// A trait that extends `Extension` and provides authorization functionality.
9#[allow(unused_variables)]
10pub trait AuthorizationExtension: Sized + 'static {
11    /// Creates a new instance of the extension.
12    ///
13    /// # Arguments
14    ///
15    /// * `config` - The configuration for this extension, from the gateway TOML.
16    ///
17    /// # Returns
18    ///
19    /// Returns an instance of this resolver. Upon failure, every call to this extension will fail.
20    fn new(config: Configuration) -> Result<Self, Error>;
21
22    /// Authorize query elements before sending any subgraph requests.
23    /// The query elements will contain every element in the operation with a definition annotated
24    /// with one of the extension's authorization directive. This naturally includes fields, but
25    /// also objects, interfaces, unions, enums and scalars.
26    ///
27    /// Only elements explicitly mentioned in the query will be taken into account. Authorization
28    /// on a object behind an interface won't be called if it's not explicitly mentioned, so if
29    /// only interface fields are used.
30    fn authorize_query(
31        &mut self,
32        ctx: AuthorizationContext,
33        elements: QueryElements<'_>,
34    ) -> Result<impl IntoQueryAuthorization, ErrorResponse>;
35
36    fn authorize_response(
37        &mut self,
38        ctx: AuthorizationContext,
39        state: Vec<u8>,
40        elements: ResponseElements<'_>,
41    ) -> Result<AuthorizationDecisions, Error> {
42        Err("Response authorization not implemented".into())
43    }
44}
45
46pub trait IntoQueryAuthorization {
47    fn into_query_authorization(self) -> (AuthorizationDecisions, Vec<u8>);
48}
49
50impl IntoQueryAuthorization for AuthorizationDecisions {
51    fn into_query_authorization(self) -> (AuthorizationDecisions, Vec<u8>) {
52        (self, Vec::new())
53    }
54}
55
56impl IntoQueryAuthorization for (AuthorizationDecisions, Vec<u8>) {
57    fn into_query_authorization(self) -> (AuthorizationDecisions, Vec<u8>) {
58        self
59    }
60}
61
62#[doc(hidden)]
63pub fn register<T: AuthorizationExtension>() {
64    pub(super) struct Proxy<T: AuthorizationExtension>(T);
65
66    impl<T: AuthorizationExtension> AnyExtension for Proxy<T> {
67        fn authorize_query(
68            &mut self,
69            ctx: AuthorizationContext,
70            elements: QueryElements<'_>,
71        ) -> Result<(AuthorizationDecisions, Vec<u8>), ErrorResponse> {
72            AuthorizationExtension::authorize_query(&mut self.0, ctx, elements)
73                .map(IntoQueryAuthorization::into_query_authorization)
74        }
75    }
76
77    crate::component::register_extension(Box::new(|_, config| {
78        <T as AuthorizationExtension>::new(config).map(|extension| Box::new(Proxy(extension)) as Box<dyn AnyExtension>)
79    }))
80}