grafbase_hooks/hooks/authorization/
edge_node_post_execution_arguments.rs

1/// Arguments passed to the `authorize_edge_node_post_execution` hook.
2pub struct EdgeNodePostExecutionArguments {
3    definition: crate::wit::EdgeDefinition,
4    nodes: Vec<String>,
5    metadata: String,
6}
7
8impl EdgeNodePostExecutionArguments {
9    pub(crate) fn new(definition: crate::wit::EdgeDefinition, nodes: Vec<String>, metadata: String) -> Self {
10        Self {
11            definition,
12            nodes,
13            metadata,
14        }
15    }
16
17    /// The name of the parent type of the edge.
18    ///
19    /// For the following GraphQL schema:
20    ///
21    /// ```graphql
22    /// type User {
23    ///     id: Int!
24    ///     name: String!
25    /// }
26    ///
27    /// type Query {
28    ///     users: [User!]! @authorized(node: "id")
29    /// }
30    /// ```
31    ///
32    /// And the query:
33    ///
34    /// ```graphql
35    /// query {
36    ///     users { name }
37    /// }
38    /// ```
39    ///
40    /// The parent type name is `Query`.
41    pub fn parent_type_name(&self) -> &str {
42        &self.definition.parent_type_name
43    }
44
45    /// The name of the authorized edge.
46    ///
47    /// For the following GraphQL schema:
48    ///
49    /// ```graphql
50    /// type User {
51    ///     id: Int!
52    ///     name: String!
53    /// }
54    ///
55    /// type Query {
56    ///     users: [User!]! @authorized(node: "id")
57    /// }
58    /// ```
59    ///
60    /// And the query:
61    ///
62    /// ```graphql
63    /// query {
64    ///     users { name }
65    /// }
66    /// ```
67    ///
68    /// The field name is `users`.
69    pub fn field_name(&self) -> &str {
70        &self.definition.field_name
71    }
72
73    /// The nodes of the edge, serialized as a JSON objects.
74    /// This method will deserialize the nodes into either `serde_json::Value` or a custom struct.
75    ///
76    /// For the following GraphQL schema:
77    ///
78    /// ```graphql
79    /// type User {
80    ///     id: Int!
81    ///     name: String!
82    /// }
83    ///
84    /// type Query {
85    ///     users: [User!]! @authorized(node: "id")
86    /// }
87    /// ```
88    ///
89    /// And the query:
90    ///
91    /// ```graphql
92    /// query {
93    ///     users { name }
94    /// }
95    /// ```
96    ///
97    /// The query returns two entities:
98    ///
99    /// ```json
100    /// [
101    ///   {
102    ///     "id": 1,
103    ///     "name": "Alice"
104    ///   },
105    ///   {
106    ///     "id": 2,
107    ///     "name": "Bob"
108    ///   }
109    /// ]
110    /// ```
111    ///
112    /// The arguments can be deserialized into a custom struct like:
113    ///
114    /// ```rust
115    /// #[derive(serde::Deserialize)]
116    /// struct User {
117    ///    id: u64,
118    /// }
119    ///
120    /// # fn foo(arguments: grafbase_hooks::EdgeNodePostExecutionArguments) -> Result<(), serde_json::Error> {
121    /// let parents: Vec<User> = arguments.nodes()?;
122    /// # Ok(())
123    /// # }
124    /// ```
125    ///
126    /// The directive defines the `node` argument as `id`, so the hook gets an object of all
127    /// ids of the returned users.
128    pub fn nodes<'a, T>(&'a self) -> Result<Vec<T>, serde_json::Error>
129    where
130        T: serde::Deserialize<'a>,
131    {
132        self.nodes.iter().map(|parent| serde_json::from_str(parent)).collect()
133    }
134
135    /// The metadata passed to the `@authorized` directive. The metadata is
136    /// serialized as a JSON object. This method will deserialize the metadata
137    /// into either `serde_json::Value` or a custom struct.
138    ///
139    /// For the following GraphQL schema:
140    ///
141    /// ```graphql
142    /// type User {
143    ///     id: Int!
144    ///     name: String!
145    /// }
146    ///
147    /// type Query {
148    ///     users: [User!]! @authorized(node: "id", metadata: { role: "admin" })
149    /// }
150    /// ```
151    ///
152    /// When executing a query like:
153    ///
154    /// ```graphql
155    /// query {
156    ///   users { name }
157    /// }
158    /// ```
159    ///
160    /// The metadata is `{"role": "admin"}`.
161    ///
162    /// The metadata can be deserialized into a custom struct like:
163    ///
164    /// ```rust
165    /// #[derive(serde::Deserialize)]
166    /// #[serde(untagged, rename = "snake_case")]
167    /// enum Role {
168    ///    Admin,
169    ///    User,
170    /// }
171    ///
172    /// #[derive(serde::Deserialize)]
173    /// struct Metadata {
174    ///    role: Role,
175    /// }
176    ///
177    /// # fn foo(arguments: grafbase_hooks::EdgePreExecutionArguments) -> Result<(), serde_json::Error> {
178    /// let arguments: Metadata = arguments.metadata()?;
179    /// # Ok(())
180    /// # }
181    /// ```
182    pub fn metadata<'a, T>(&'a self) -> Result<T, serde_json::Error>
183    where
184        T: serde::Deserialize<'a>,
185    {
186        serde_json::from_str(&self.metadata)
187    }
188}