facebook_access_token_api/endpoints/
debug_token.rs

1//! [Ref](https://developers.facebook.com/docs/graph-api/reference/v15.0/debug_token)
2//! [Ref](https://developers.facebook.com/docs/facebook-login/guides/%20access-tokens/debugging)
3
4use http_api_client_endpoint::{
5    http::{
6        header::{ACCEPT, USER_AGENT},
7        Method, StatusCode,
8    },
9    Body, Endpoint, Request, Response, MIME_APPLICATION_JSON,
10};
11use serde::{Deserialize, Serialize};
12use url::Url;
13
14use crate::{
15    endpoints::{
16        common::{EndpointError, EndpointRet},
17        URL_BASE, VERSION,
18    },
19    objects::{DebugTokenResult, ResponseBodyErrJson},
20};
21
22//
23#[derive(Debug, Clone)]
24pub struct DebugTokenEndpoint {
25    pub input_token: Box<str>,
26    pub access_token: Box<str>,
27    //
28    pub version: Option<Box<str>>,
29}
30
31impl DebugTokenEndpoint {
32    pub fn new(
33        input_token: impl AsRef<str>,
34        access_token: impl AsRef<str>,
35        version: impl Into<Option<Box<str>>>,
36    ) -> Self {
37        Self {
38            input_token: input_token.as_ref().into(),
39            access_token: access_token.as_ref().into(),
40            version: version.into(),
41        }
42    }
43}
44
45impl Endpoint for DebugTokenEndpoint {
46    type RenderRequestError = EndpointError;
47
48    type ParseResponseOutput = EndpointRet<DebugTokenResponseBodyOkJson>;
49    type ParseResponseError = EndpointError;
50
51    fn render_request(&self) -> Result<Request<Body>, Self::RenderRequestError> {
52        let url = format!(
53            "{}/{}/debug_token",
54            URL_BASE,
55            self.version.as_deref().unwrap_or(VERSION),
56        );
57        let mut url = Url::parse(&url).map_err(EndpointError::MakeRequestUrlFailed)?;
58
59        url.query_pairs_mut()
60            .append_pair("input_token", &self.input_token)
61            .append_pair("access_token", &self.access_token);
62
63        let request = Request::builder()
64            .method(Method::GET)
65            .uri(url.as_str())
66            .header(USER_AGENT, "facebook-access-token-api")
67            .header(ACCEPT, MIME_APPLICATION_JSON)
68            .body(vec![])
69            .map_err(EndpointError::MakeRequestFailed)?;
70
71        Ok(request)
72    }
73
74    fn parse_response(
75        &self,
76        response: Response<Body>,
77    ) -> Result<Self::ParseResponseOutput, Self::ParseResponseError> {
78        let status = response.status();
79        match status {
80            StatusCode::OK => Ok(EndpointRet::Ok(
81                serde_json::from_slice(response.body())
82                    .map_err(EndpointError::DeResponseBodyOkJsonFailed)?,
83            )),
84            status => match serde_json::from_slice::<ResponseBodyErrJson>(response.body()) {
85                Ok(ok_json) => Ok(EndpointRet::Other((status, Ok(ok_json)))),
86                Err(_) => Ok(EndpointRet::Other((
87                    status,
88                    Err(response.body().to_owned()),
89                ))),
90            },
91        }
92    }
93}
94
95//
96//
97//
98#[derive(Deserialize, Serialize, Debug, Clone)]
99pub struct DebugTokenResponseBodyOkJson {
100    pub data: DebugTokenResult,
101}
102
103#[cfg(test)]
104mod tests {
105    use super::*;
106
107    use crate::objects::debug_token::DebugTokenResultTypeExtra;
108
109    #[test]
110    fn test_de_response_body_ok_json() {
111        //
112        //
113        //
114        //
115        let content =
116            include_str!("../../tests/response_body_json_files/debug_token__app_access_token.json");
117        match serde_json::from_str::<DebugTokenResponseBodyOkJson>(content) {
118            Ok(ok_json) => {
119                // println!("{ok_json:?}");
120                assert!(ok_json.data.error.is_none(),);
121                match ok_json.data.type_extra.unwrap() {
122                    DebugTokenResultTypeExtra::App(info) => {
123                        assert_eq!(info.app_id, 257422819769992);
124                        assert_eq!(info.application, "oauth2-rs-f-b-web-app-demo");
125                    }
126                    DebugTokenResultTypeExtra::User(x) => panic!("{x:?}"),
127                    DebugTokenResultTypeExtra::Page(x) => panic!("{x:?}"),
128                }
129            }
130            Err(err) => panic!("{}", err),
131        }
132
133        //
134        //
135        //
136        //
137        let content = include_str!(
138            "../../tests/response_body_json_files/debug_token__user_access_token_1.json"
139        );
140        match serde_json::from_str::<DebugTokenResponseBodyOkJson>(content) {
141            Ok(ok_json) => {
142                // println!("{ok_json:?}");
143                assert!(ok_json.data.error.is_none(),);
144                match ok_json.data.type_extra.unwrap() {
145                    DebugTokenResultTypeExtra::App(x) => panic!("{x:?}"),
146                    DebugTokenResultTypeExtra::User(info) => {
147                        assert_eq!(info.app_id, 257422819769992);
148                        assert_eq!(info.user_id, 123);
149                        assert!(info.metadata.is_some());
150                    }
151                    DebugTokenResultTypeExtra::Page(x) => panic!("{x:?}"),
152                }
153            }
154            Err(err) => panic!("{}", err),
155        }
156
157        //
158        let content = include_str!(
159            "../../tests/response_body_json_files/debug_token__user_access_token_2.json"
160        );
161        match serde_json::from_str::<DebugTokenResponseBodyOkJson>(content) {
162            Ok(ok_json) => {
163                // println!("{ok_json:?}");
164                assert!(ok_json.data.error.is_none(),);
165                match ok_json.data.type_extra.unwrap() {
166                    DebugTokenResultTypeExtra::App(x) => panic!("{x:?}"),
167                    DebugTokenResultTypeExtra::User(info) => {
168                        assert_eq!(info.app_id, 257422819769992);
169                        assert_eq!(info.user_id, 123);
170                        assert!(info.metadata.is_none());
171                    }
172                    DebugTokenResultTypeExtra::Page(x) => panic!("{x:?}"),
173                }
174            }
175            Err(err) => panic!("{}", err),
176        }
177
178        //
179        let content = include_str!(
180            "../../tests/response_body_json_files/debug_token__user_access_token_3.json"
181        );
182        match serde_json::from_str::<DebugTokenResponseBodyOkJson>(content) {
183            Ok(ok_json) => {
184                // println!("{ok_json:?}");
185                assert!(ok_json.data.error.unwrap().message.contains("has expired"));
186                match ok_json.data.type_extra.unwrap() {
187                    DebugTokenResultTypeExtra::App(x) => panic!("{x:?}"),
188                    DebugTokenResultTypeExtra::User(info) => {
189                        assert_eq!(info.app_id, 257422819769992);
190                        assert_eq!(info.user_id, 123);
191                    }
192                    DebugTokenResultTypeExtra::Page(x) => panic!("{x:?}"),
193                }
194            }
195            Err(err) => panic!("{}", err),
196        }
197
198        //
199        let content = include_str!(
200            "../../tests/response_body_json_files/debug_token__user_access_token_4.json"
201        );
202        match serde_json::from_str::<DebugTokenResponseBodyOkJson>(content) {
203            Ok(ok_json) => {
204                // println!("{ok_json:?}");
205                assert!(ok_json
206                    .data
207                    .error
208                    .unwrap()
209                    .message
210                    .contains("has been invalidated"));
211                match ok_json.data.type_extra.unwrap() {
212                    DebugTokenResultTypeExtra::App(x) => panic!("{x:?}"),
213                    DebugTokenResultTypeExtra::User(info) => {
214                        assert_eq!(info.app_id, 257422819769992);
215                        assert_eq!(info.user_id, 123);
216                        assert!(info.granular_scopes.is_some());
217                    }
218                    DebugTokenResultTypeExtra::Page(x) => panic!("{x:?}"),
219                }
220            }
221            Err(err) => panic!("{}", err),
222        }
223
224        //
225        //
226        //
227        //
228        let content = include_str!(
229            "../../tests/response_body_json_files/debug_token__user_access_token_example_1.json"
230        );
231        match serde_json::from_str::<DebugTokenResponseBodyOkJson>(content) {
232            Ok(_ok_json) => {
233                // println!("{ok_json:?}");
234            }
235            Err(err) => panic!("{}", err),
236        }
237
238        //
239        let content = include_str!(
240            "../../tests/response_body_json_files/debug_token__user_access_token_example_2.json"
241        );
242        match serde_json::from_str::<DebugTokenResponseBodyOkJson>(content) {
243            Ok(_ok_json) => {
244                // println!("{ok_json:?}");
245            }
246            Err(err) => panic!("{}", err),
247        }
248
249        //
250        let content =
251            include_str!("../../tests/response_body_json_files/debug_token__200__example_1.json");
252        match serde_json::from_str::<DebugTokenResponseBodyOkJson>(content) {
253            Ok(_ok_json) => {
254                // println!("{ok_json:?}");
255            }
256            Err(err) => panic!("{}", err),
257        }
258
259        //
260        let content =
261            include_str!("../../tests/response_body_json_files/debug_token__200__example_2.json");
262        match serde_json::from_str::<DebugTokenResponseBodyOkJson>(content) {
263            Ok(ok_json) => {
264                // println!("{ok_json:?}");
265                assert!(ok_json.data.is_valid);
266            }
267            Err(err) => panic!("{}", err),
268        }
269
270        //
271        //
272        //
273        //
274        let content = include_str!(
275            "../../tests/response_body_json_files/debug_token__page_access_token.json"
276        );
277        match serde_json::from_str::<DebugTokenResponseBodyOkJson>(content) {
278            Ok(ok_json) => {
279                // println!("{ok_json:?}");
280                assert!(ok_json.data.error.is_none(),);
281                match ok_json.data.type_extra.unwrap() {
282                    DebugTokenResultTypeExtra::App(x) => panic!("{x:?}"),
283                    DebugTokenResultTypeExtra::User(x) => panic!("{x:?}"),
284                    DebugTokenResultTypeExtra::Page(info) => {
285                        assert_eq!(info.app_id, 257422819769992);
286                        assert_eq!(info.user_id, 123);
287                        assert_eq!(info.profile_id, 103455271248220);
288                        assert!(info.granular_scopes.is_some());
289                        assert_eq!(
290                            info.granular_scopes
291                                .unwrap()
292                                .first()
293                                .cloned()
294                                .unwrap()
295                                .target_ids
296                                .unwrap()
297                                .first()
298                                .cloned()
299                                .unwrap(),
300                            103455271248220
301                        );
302                    }
303                }
304            }
305            Err(err) => panic!("{}", err),
306        }
307
308        //
309        //
310        //
311        //
312        let content = include_str!(
313            "../../tests/response_body_json_files/debug_token__200__access_token_could_not_be_decrypted.json"
314        );
315        match serde_json::from_str::<DebugTokenResponseBodyOkJson>(content) {
316            Ok(ok_json) => {
317                // println!("{ok_json:?}");
318                assert!(ok_json.data.error.is_some(),);
319            }
320            Err(err) => panic!("{}", err),
321        }
322
323        //
324        let content = include_str!(
325            "../../tests/response_body_json_files/debug_token__200__cannot_get_application_info.json"
326        );
327        match serde_json::from_str::<DebugTokenResponseBodyOkJson>(content) {
328            Ok(ok_json) => {
329                // println!("{ok_json:?}");
330                assert!(ok_json.data.error.is_some(),);
331            }
332            Err(err) => panic!("{}", err),
333        }
334    }
335}