1use secrecy::{ExposeSecret, SecretString};
2use serde::{Deserialize, Serialize};
3use std::fmt;
4use std::time::Duration;
5
6#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
8pub struct AppId(String);
9
10impl AppId {
11 pub fn new(id: impl Into<String>) -> Self {
12 Self(id.into())
13 }
14
15 pub fn as_str(&self) -> &str {
16 &self.0
17 }
18}
19
20impl fmt::Display for AppId {
21 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22 write!(f, "{}", self.0)
23 }
24}
25
26#[derive(Clone)]
28pub struct AppSecret(SecretString);
29
30impl AppSecret {
31 pub fn new(secret: impl Into<String>) -> Self {
32 Self(SecretString::new(secret.into()))
33 }
34
35 pub fn expose_secret(&self) -> &str {
36 self.0.expose_secret()
37 }
38}
39
40impl fmt::Debug for AppSecret {
41 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42 f.debug_tuple("AppSecret").field(&"[REDACTED]").finish()
43 }
44}
45
46impl Serialize for AppSecret {
47 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
48 where
49 S: serde::Serializer,
50 {
51 serializer.serialize_str(self.0.expose_secret())
52 }
53}
54
55impl<'de> Deserialize<'de> for AppSecret {
56 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
57 where
58 D: serde::Deserializer<'de>,
59 {
60 let s = String::deserialize(deserializer)?;
61 Ok(Self::new(s))
62 }
63}
64
65#[derive(Clone)]
67pub struct AuthorizationCode(SecretString);
68
69impl AuthorizationCode {
70 pub fn new(code: impl Into<String>) -> Self {
71 Self(SecretString::new(code.into()))
72 }
73
74 pub fn expose_secret(&self) -> &str {
75 self.0.expose_secret()
76 }
77}
78
79impl fmt::Debug for AuthorizationCode {
80 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81 f.debug_tuple("AuthorizationCode")
82 .field(&"[REDACTED]")
83 .finish()
84 }
85}
86
87impl Serialize for AuthorizationCode {
88 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
89 where
90 S: serde::Serializer,
91 {
92 serializer.serialize_str(self.0.expose_secret())
93 }
94}
95
96impl<'de> Deserialize<'de> for AuthorizationCode {
97 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
98 where
99 D: serde::Deserializer<'de>,
100 {
101 let s = String::deserialize(deserializer)?;
102 Ok(Self::new(s))
103 }
104}
105
106#[derive(Clone)]
108pub struct AccessToken(SecretString);
109
110impl AccessToken {
111 pub fn new(token: impl Into<String>) -> Self {
112 Self(SecretString::new(token.into()))
113 }
114
115 pub fn expose_secret(&self) -> &str {
116 self.0.expose_secret()
117 }
118}
119
120impl fmt::Debug for AccessToken {
121 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
122 f.debug_tuple("AccessToken").field(&"[REDACTED]").finish()
123 }
124}
125
126impl Serialize for AccessToken {
127 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
128 where
129 S: serde::Serializer,
130 {
131 serializer.serialize_str(self.0.expose_secret())
132 }
133}
134
135impl<'de> Deserialize<'de> for AccessToken {
136 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
137 where
138 D: serde::Deserializer<'de>,
139 {
140 let s = String::deserialize(deserializer)?;
141 Ok(Self::new(s))
142 }
143}
144
145#[derive(Clone)]
147pub struct RefreshToken(SecretString);
148
149impl RefreshToken {
150 pub fn new(token: impl Into<String>) -> Self {
151 Self(SecretString::new(token.into()))
152 }
153
154 pub fn expose_secret(&self) -> &str {
155 self.0.expose_secret()
156 }
157}
158
159impl fmt::Debug for RefreshToken {
160 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
161 f.debug_tuple("RefreshToken").field(&"[REDACTED]").finish()
162 }
163}
164
165impl Serialize for RefreshToken {
166 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
167 where
168 S: serde::Serializer,
169 {
170 serializer.serialize_str(self.0.expose_secret())
171 }
172}
173
174impl<'de> Deserialize<'de> for RefreshToken {
175 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
176 where
177 D: serde::Deserializer<'de>,
178 {
179 let s = String::deserialize(deserializer)?;
180 Ok(Self::new(s))
181 }
182}
183
184#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
186pub struct OpenId(String);
187
188impl OpenId {
189 pub fn new(id: impl Into<String>) -> Self {
190 Self(id.into())
191 }
192
193 pub fn as_str(&self) -> &str {
194 &self.0
195 }
196}
197
198impl fmt::Display for OpenId {
199 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
200 write!(f, "{}", self.0)
201 }
202}
203
204#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
206pub struct UnionId(String);
207
208impl UnionId {
209 pub fn new(id: impl Into<String>) -> Self {
210 Self(id.into())
211 }
212
213 pub fn as_str(&self) -> &str {
214 &self.0
215 }
216}
217
218impl fmt::Display for UnionId {
219 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
220 write!(f, "{}", self.0)
221 }
222}
223
224#[derive(Debug, Deserialize)]
226pub(crate) struct RawResponse<T> {
227 #[serde(default)]
228 pub errcode: Option<i32>,
229 #[serde(default)]
230 pub errmsg: Option<String>,
231 #[serde(flatten)]
232 pub data: Option<T>,
233}
234
235#[derive(Debug, Deserialize)]
237pub(crate) struct RawTokenResponse {
238 pub access_token: String,
239 #[serde(default)]
240 pub refresh_token: Option<String>,
241 pub openid: String,
242 #[serde(default)]
243 pub unionid: Option<String>,
244 pub expires_in: i64,
245 pub scope: String,
246}
247
248#[derive(Debug, Clone, Serialize, Deserialize)]
250pub struct TokenResponse {
251 pub access_token: AccessToken,
252 pub refresh_token: RefreshToken,
253 pub openid: OpenId,
254 pub unionid: Option<UnionId>,
255 pub expires_in: Duration,
256 pub scope: String,
257}
258
259impl From<RawTokenResponse> for TokenResponse {
260 fn from(raw: RawTokenResponse) -> Self {
261 Self {
262 access_token: AccessToken::new(raw.access_token),
263 refresh_token: RefreshToken::new(raw.refresh_token.unwrap_or_default()),
264 openid: OpenId::new(raw.openid),
265 unionid: raw.unionid.map(UnionId::new),
266 expires_in: Duration::from_secs(raw.expires_in as u64),
267 scope: raw.scope,
268 }
269 }
270}
271
272#[derive(Debug, Clone, Serialize, Deserialize)]
274pub struct UserInfo {
275 pub openid: OpenId,
277 pub nickname: String,
279 pub sex: u8,
281 pub province: String,
283 pub city: String,
285 pub country: String,
287 pub headimgurl: String,
289 #[serde(default)]
291 pub unionid: Option<UnionId>,
292 #[serde(default)]
294 pub privilege: Vec<String>,
295}