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}