shopify_sdk/rest/resources/v2025_10/
user.rs1use serde::{Deserialize, Serialize};
39
40use crate::clients::RestClient;
41use crate::rest::{ReadOnlyResource, ResourceError, ResourceOperation, ResourcePath, ResourceResponse, RestResource};
42use crate::HttpMethod;
43
44#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
72pub struct User {
73 #[serde(skip_serializing)]
75 pub id: Option<u64>,
76
77 #[serde(skip_serializing)]
79 pub first_name: Option<String>,
80
81 #[serde(skip_serializing)]
83 pub last_name: Option<String>,
84
85 #[serde(skip_serializing)]
87 pub email: Option<String>,
88
89 #[serde(skip_serializing)]
91 pub phone: Option<String>,
92
93 #[serde(skip_serializing)]
95 pub url: Option<String>,
96
97 #[serde(skip_serializing)]
99 pub bio: Option<String>,
100
101 #[serde(skip_serializing)]
103 pub im: Option<String>,
104
105 #[serde(skip_serializing)]
107 pub screen_name: Option<String>,
108
109 #[serde(skip_serializing)]
111 pub locale: Option<String>,
112
113 #[serde(skip_serializing)]
115 pub user_type: Option<String>,
116
117 #[serde(skip_serializing)]
119 pub account_owner: Option<bool>,
120
121 #[serde(skip_serializing)]
123 pub receive_announcements: Option<i32>,
124
125 #[serde(skip_serializing)]
127 pub permissions: Option<Vec<String>>,
128
129 #[serde(skip_serializing)]
131 pub admin_graphql_api_id: Option<String>,
132}
133
134impl User {
135 pub async fn current(client: &RestClient) -> Result<ResourceResponse<Self>, ResourceError> {
147 let url = "users/current";
148 let response = client.get(url, None).await?;
149
150 if !response.is_ok() {
151 return Err(ResourceError::from_http_response(
152 response.code,
153 &response.body,
154 Self::NAME,
155 Some("current"),
156 response.request_id(),
157 ));
158 }
159
160 let key = Self::resource_key();
161 ResourceResponse::from_http_response(response, &key)
162 }
163}
164
165impl RestResource for User {
166 type Id = u64;
167 type FindParams = UserFindParams;
168 type AllParams = UserListParams;
169 type CountParams = ();
170
171 const NAME: &'static str = "User";
172 const PLURAL: &'static str = "users";
173
174 const PATHS: &'static [ResourcePath] = &[
179 ResourcePath::new(
180 HttpMethod::Get,
181 ResourceOperation::Find,
182 &["id"],
183 "users/{id}",
184 ),
185 ResourcePath::new(HttpMethod::Get, ResourceOperation::All, &[], "users"),
186 ];
189
190 fn get_id(&self) -> Option<Self::Id> {
191 self.id
192 }
193}
194
195impl ReadOnlyResource for User {}
196
197#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
199pub struct UserFindParams {
200 #[serde(skip_serializing_if = "Option::is_none")]
202 pub fields: Option<String>,
203}
204
205#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
207pub struct UserListParams {
208 #[serde(skip_serializing_if = "Option::is_none")]
210 pub limit: Option<u32>,
211
212 #[serde(skip_serializing_if = "Option::is_none")]
214 pub page_info: Option<String>,
215}
216
217#[cfg(test)]
218mod tests {
219 use super::*;
220 use crate::rest::{get_path, ReadOnlyResource, ResourceOperation, RestResource};
221
222 #[test]
223 fn test_user_implements_read_only_resource() {
224 fn assert_read_only<T: ReadOnlyResource>() {}
225 assert_read_only::<User>();
226 }
227
228 #[test]
229 fn test_user_deserialization() {
230 let json = r#"{
231 "id": 548380009,
232 "first_name": "John",
233 "last_name": "Smith",
234 "email": "john@example.com",
235 "phone": "+1-555-0100",
236 "url": "https://store.myshopify.com/admin/users/548380009",
237 "bio": "Store manager",
238 "im": null,
239 "screen_name": null,
240 "locale": "en",
241 "user_type": "regular",
242 "account_owner": false,
243 "receive_announcements": 1,
244 "permissions": ["full"],
245 "admin_graphql_api_id": "gid://shopify/StaffMember/548380009"
246 }"#;
247
248 let user: User = serde_json::from_str(json).unwrap();
249
250 assert_eq!(user.id, Some(548380009));
251 assert_eq!(user.first_name, Some("John".to_string()));
252 assert_eq!(user.last_name, Some("Smith".to_string()));
253 assert_eq!(user.email, Some("john@example.com".to_string()));
254 assert_eq!(user.phone, Some("+1-555-0100".to_string()));
255 assert_eq!(user.locale, Some("en".to_string()));
256 assert_eq!(user.user_type, Some("regular".to_string()));
257 assert_eq!(user.account_owner, Some(false));
258 assert_eq!(user.receive_announcements, Some(1));
259 assert_eq!(user.permissions, Some(vec!["full".to_string()]));
260 }
261
262 #[test]
263 fn test_user_read_only_paths() {
264 let find_path = get_path(User::PATHS, ResourceOperation::Find, &["id"]);
266 assert!(find_path.is_some());
267 assert_eq!(find_path.unwrap().template, "users/{id}");
268
269 let all_path = get_path(User::PATHS, ResourceOperation::All, &[]);
271 assert!(all_path.is_some());
272 assert_eq!(all_path.unwrap().template, "users");
273
274 let count_path = get_path(User::PATHS, ResourceOperation::Count, &[]);
276 assert!(count_path.is_none());
277
278 let create_path = get_path(User::PATHS, ResourceOperation::Create, &[]);
280 assert!(create_path.is_none());
281
282 let update_path = get_path(User::PATHS, ResourceOperation::Update, &["id"]);
283 assert!(update_path.is_none());
284
285 let delete_path = get_path(User::PATHS, ResourceOperation::Delete, &["id"]);
286 assert!(delete_path.is_none());
287 }
288
289 #[test]
290 fn test_user_current_method_exists() {
291 let _: fn(&RestClient) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<ResourceResponse<User>, ResourceError>> + Send + '_>> = |client| Box::pin(User::current(client));
295 }
296
297 #[test]
298 fn test_user_constants() {
299 assert_eq!(User::NAME, "User");
300 assert_eq!(User::PLURAL, "users");
301 }
302
303 #[test]
304 fn test_user_get_id() {
305 let user_with_id = User {
306 id: Some(548380009),
307 first_name: Some("John".to_string()),
308 ..Default::default()
309 };
310 assert_eq!(user_with_id.get_id(), Some(548380009));
311
312 let user_without_id = User::default();
313 assert_eq!(user_without_id.get_id(), None);
314 }
315
316 #[test]
317 fn test_user_all_fields_are_read_only() {
318 let user = User {
320 id: Some(548380009),
321 first_name: Some("John".to_string()),
322 last_name: Some("Smith".to_string()),
323 email: Some("john@example.com".to_string()),
324 phone: Some("+1-555-0100".to_string()),
325 locale: Some("en".to_string()),
326 user_type: Some("regular".to_string()),
327 account_owner: Some(true),
328 receive_announcements: Some(1),
329 permissions: Some(vec!["full".to_string()]),
330 ..Default::default()
331 };
332
333 let json = serde_json::to_value(&user).unwrap();
334 assert_eq!(json, serde_json::json!({}));
336 }
337}