oauth2_wechat/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_sns_userinfo_endpoint::{
7    SnsUserinfo, SnsUserinfoEndpoint, SnsUserinfoEndpointError,
8};
9
10//
11#[derive(Debug, Clone)]
12pub struct WechatUserInfoEndpoint {
13    inner: SnsUserinfoEndpoint,
14}
15impl WechatUserInfoEndpoint {
16    pub fn new(access_token: impl AsRef<str>, openid: impl AsRef<str>) -> Self {
17        Self {
18            inner: SnsUserinfoEndpoint::new(access_token, openid),
19        }
20    }
21}
22
23impl Endpoint for WechatUserInfoEndpoint {
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        UserInfo::try_from(self.inner.parse_response(response)?)
38            .map_err(EndpointParseResponseError::ToOutputFailed)
39    }
40}
41
42//
43impl From<SnsUserinfoEndpointError> for EndpointRenderRequestError {
44    fn from(err: SnsUserinfoEndpointError) -> Self {
45        match err {
46            SnsUserinfoEndpointError::MakeRequestFailed(err) => Self::MakeRequestFailed(err),
47            SnsUserinfoEndpointError::DeResponseBodyFailed(err) => Self::Other(Box::new(err)),
48        }
49    }
50}
51impl From<SnsUserinfoEndpointError> for EndpointParseResponseError {
52    fn from(err: SnsUserinfoEndpointError) -> Self {
53        match err {
54            SnsUserinfoEndpointError::MakeRequestFailed(err) => Self::Other(Box::new(err)),
55            SnsUserinfoEndpointError::DeResponseBodyFailed(err) => Self::DeResponseBodyFailed(err),
56        }
57    }
58}
59
60//
61impl TryFrom<SnsUserinfo> for UserInfo {
62    type Error = Box<dyn std::error::Error + Send + Sync>;
63
64    fn try_from(sns_userinfo: SnsUserinfo) -> Result<Self, Self::Error> {
65        Ok(Self {
66            uid: sns_userinfo.openid.to_owned(),
67            name: sns_userinfo.nickname.to_owned(),
68            email: None,
69            raw: serde_json::to_value(sns_userinfo)
70                .map(|x| x.as_object().cloned())?
71                .ok_or_else(|| "unreachable".to_owned())?,
72        })
73    }
74}