oauth2_zoho/extensions/
user_info_endpoint.rs

1use oauth2_client::{
2    extensions::{EndpointParseResponseError, EndpointRenderRequestError, UserInfo},
3    re_exports::{serde_json, Body, Endpoint, Request, Response},
4};
5
6use super::internal_oauth_user_info_endpoint::{
7    OauthUserInfoEndpoint, OauthUserInfoEndpointError, OauthUserInfoResponseBodyOkJson,
8};
9
10//
11#[derive(Debug, Clone)]
12pub struct ZohoUserInfoEndpoint {
13    inner: OauthUserInfoEndpoint,
14}
15impl ZohoUserInfoEndpoint {
16    pub fn new(access_token: impl AsRef<str>) -> Self {
17        Self {
18            inner: OauthUserInfoEndpoint::new(access_token),
19        }
20    }
21}
22
23impl Endpoint for ZohoUserInfoEndpoint {
24    type RenderRequestError = EndpointRenderRequestError;
25
26    type ParseResponseOutput = UserInfo;
27    type ParseResponseError = EndpointParseResponseError;
28
29    fn render_request(&self) -> Result<Request<Body>, Self::RenderRequestError> {
30        self.inner.render_request().map_err(Into::into)
31    }
32
33    fn parse_response(
34        &self,
35        response: Response<Body>,
36    ) -> Result<Self::ParseResponseOutput, Self::ParseResponseError> {
37        UserInfoWrapper::try_from(self.inner.parse_response(response)?)
38            .map(|x| x.0)
39            .map_err(EndpointParseResponseError::ToOutputFailed)
40    }
41}
42
43//
44impl From<OauthUserInfoEndpointError> for EndpointRenderRequestError {
45    fn from(err: OauthUserInfoEndpointError) -> Self {
46        match err {
47            OauthUserInfoEndpointError::MakeRequestFailed(err) => Self::MakeRequestFailed(err),
48            OauthUserInfoEndpointError::DeResponseBodyOkJsonFailed(err) => {
49                Self::Other(Box::new(err))
50            }
51            OauthUserInfoEndpointError::ResponseBodyError(status_code, body) => {
52                Self::Other(format!("status_code:{status_code} body:{body:?}").into())
53            }
54        }
55    }
56}
57impl From<OauthUserInfoEndpointError> for EndpointParseResponseError {
58    fn from(err: OauthUserInfoEndpointError) -> Self {
59        match err {
60            OauthUserInfoEndpointError::MakeRequestFailed(err) => Self::Other(Box::new(err)),
61            OauthUserInfoEndpointError::DeResponseBodyOkJsonFailed(err) => {
62                Self::DeResponseBodyFailed(err)
63            }
64            OauthUserInfoEndpointError::ResponseBodyError(status_code, body) => {
65                Self::Other(format!("status_code:{status_code} body:{body:?}").into())
66            }
67        }
68    }
69}
70
71//
72struct UserInfoWrapper(UserInfo);
73impl TryFrom<OauthUserInfoResponseBodyOkJson> for UserInfoWrapper {
74    type Error = Box<dyn std::error::Error + Send + Sync>;
75
76    fn try_from(ok_json: OauthUserInfoResponseBodyOkJson) -> Result<Self, Self::Error> {
77        Ok(Self(UserInfo {
78            uid: ok_json.zuid.to_string(),
79            name: Some(ok_json.display_name.to_owned()),
80            email: Some(ok_json.email.to_owned()),
81            raw: serde_json::to_value(ok_json)
82                .map(|x| x.as_object().cloned())?
83                .ok_or_else(|| "unreachable".to_owned())?,
84        }))
85    }
86}