Skip to main content

proxmox_api/generated/access/
users.rs

1pub mod userid;
2#[derive(Debug, Clone)]
3pub struct UsersClient<T> {
4    client: T,
5    path: String,
6}
7impl<T> UsersClient<T>
8where
9    T: crate::client::Client,
10{
11    pub fn new(client: T, parent_path: &str) -> Self {
12        Self {
13            client,
14            path: format!("{}{}", parent_path, "/users"),
15        }
16    }
17}
18impl<T> UsersClient<T>
19where
20    T: crate::client::Client,
21{
22    #[doc = "User index."]
23    #[doc = ""]
24    #[doc = "The returned list is restricted to users where you have 'User.Modify' or 'Sys.Audit' permissions on '/access/groups' or on a group the user belongs too. But it always includes the current (authenticated) user."]
25    pub async fn get(&self, params: GetParams) -> Result<Vec<GetOutputItems>, T::Error> {
26        let path = self.path.to_string();
27        let optional_vec: Option<Vec<GetOutputItems>> = self.client.get(&path, &params).await?;
28        Ok(optional_vec.unwrap_or_default())
29    }
30}
31impl<T> UsersClient<T>
32where
33    T: crate::client::Client,
34{
35    #[doc = "Create new user."]
36    #[doc = ""]
37    #[doc = "Permission check: and(userid-param(\"Realm.AllocateUser\"), userid-group([\"User.Modify\"], groups_param=\"create\"))"]
38    #[doc = "You need 'Realm.AllocateUser' on '/access/realm/\\<realm\\>' on the realm of user \\<userid\\>, and 'User.Modify' permissions to '/access/groups/\\<group\\>' for any group specified (or 'User.Modify' on '/access/groups' if you pass no groups."]
39    pub async fn post(&self, params: PostParams) -> Result<(), T::Error> {
40        let path = self.path.to_string();
41        self.client.post(&path, &params).await
42    }
43}
44impl GetOutputItems {
45    pub fn new(userid: UseridStr) -> Self {
46        Self {
47            userid,
48            comment: ::std::default::Default::default(),
49            email: ::std::default::Default::default(),
50            enable: ::std::default::Default::default(),
51            expire: ::std::default::Default::default(),
52            firstname: ::std::default::Default::default(),
53            groups: ::std::default::Default::default(),
54            keys: ::std::default::Default::default(),
55            lastname: ::std::default::Default::default(),
56            realm_type: ::std::default::Default::default(),
57            tfa_locked_until: ::std::default::Default::default(),
58            tokens: ::std::default::Default::default(),
59            totp_locked: ::std::default::Default::default(),
60            additional_properties: ::std::default::Default::default(),
61        }
62    }
63}
64#[derive(Clone, Debug, :: serde :: Serialize, :: serde :: Deserialize)]
65pub struct GetOutputItems {
66    #[serde(skip_serializing_if = "Option::is_none", default)]
67    pub comment: Option<CommentStr>,
68    #[serde(skip_serializing_if = "Option::is_none", default)]
69    pub email: Option<EmailStr>,
70    #[serde(
71        serialize_with = "crate::types::serialize_bool_optional",
72        deserialize_with = "crate::types::deserialize_bool_optional"
73    )]
74    #[serde(skip_serializing_if = "Option::is_none", default)]
75    #[doc = "Enable the account (default). You can set this to '0' to disable the account"]
76    #[doc = ""]
77    pub enable: Option<bool>,
78    #[serde(
79        serialize_with = "crate::types::serialize_unsigned_int_optional",
80        deserialize_with = "crate::types::deserialize_unsigned_int_optional"
81    )]
82    #[serde(skip_serializing_if = "Option::is_none", default)]
83    #[doc = "Account expiration date (seconds since epoch). '0' means no expiration date."]
84    #[doc = ""]
85    pub expire: Option<u64>,
86    #[serde(skip_serializing_if = "Option::is_none", default)]
87    pub firstname: Option<FirstnameStr>,
88    #[serde(skip_serializing_if = "Option::is_none", default)]
89    pub groups: Option<String>,
90    #[serde(skip_serializing_if = "Option::is_none", default)]
91    #[doc = "Keys for two factor auth (yubico)."]
92    #[doc = ""]
93    pub keys: Option<KeysStr>,
94    #[serde(skip_serializing_if = "Option::is_none", default)]
95    pub lastname: Option<LastnameStr>,
96    #[serde(rename = "realm-type")]
97    #[serde(skip_serializing_if = "Option::is_none", default)]
98    #[doc = "The type of the users realm"]
99    #[doc = ""]
100    pub realm_type: Option<String>,
101    #[serde(rename = "tfa-locked-until")]
102    #[serde(
103        serialize_with = "crate::types::serialize_int_optional",
104        deserialize_with = "crate::types::deserialize_int_optional"
105    )]
106    #[serde(skip_serializing_if = "Option::is_none", default)]
107    #[doc = "Contains a timestamp until when a user is locked out of 2nd factors."]
108    #[doc = ""]
109    pub tfa_locked_until: Option<i64>,
110    #[serde(skip_serializing_if = "::std::vec::Vec::is_empty", default)]
111    pub tokens: Vec<TokensGetOutputItemsTokensItems>,
112    #[serde(rename = "totp-locked")]
113    #[serde(
114        serialize_with = "crate::types::serialize_bool_optional",
115        deserialize_with = "crate::types::deserialize_bool_optional"
116    )]
117    #[serde(skip_serializing_if = "Option::is_none", default)]
118    #[doc = "True if the user is currently locked out of TOTP factors."]
119    #[doc = ""]
120    pub totp_locked: Option<bool>,
121    #[doc = "Full User ID, in the `name@realm` format."]
122    #[doc = ""]
123    pub userid: UseridStr,
124    #[serde(
125        flatten,
126        default,
127        skip_serializing_if = "::std::collections::HashMap::is_empty"
128    )]
129    pub additional_properties: ::std::collections::HashMap<String, ::serde_json::Value>,
130}
131#[derive(Clone, Debug, :: serde :: Serialize, :: serde :: Deserialize, Default)]
132pub struct GetParams {
133    #[serde(
134        serialize_with = "crate::types::serialize_bool_optional",
135        deserialize_with = "crate::types::deserialize_bool_optional"
136    )]
137    #[serde(skip_serializing_if = "Option::is_none", default)]
138    #[doc = "Optional filter for enable property."]
139    #[doc = ""]
140    pub enabled: Option<bool>,
141    #[serde(
142        serialize_with = "crate::types::serialize_bool_optional",
143        deserialize_with = "crate::types::deserialize_bool_optional"
144    )]
145    #[serde(skip_serializing_if = "Option::is_none", default)]
146    #[doc = "Include group and token information."]
147    #[doc = ""]
148    pub full: Option<bool>,
149    #[serde(
150        flatten,
151        default,
152        skip_serializing_if = "::std::collections::HashMap::is_empty"
153    )]
154    pub additional_properties: ::std::collections::HashMap<String, ::serde_json::Value>,
155}
156impl PostParams {
157    pub fn new(userid: UseridStr) -> Self {
158        Self {
159            userid,
160            comment: ::std::default::Default::default(),
161            email: ::std::default::Default::default(),
162            enable: ::std::default::Default::default(),
163            expire: ::std::default::Default::default(),
164            firstname: ::std::default::Default::default(),
165            groups: ::std::default::Default::default(),
166            keys: ::std::default::Default::default(),
167            lastname: ::std::default::Default::default(),
168            password: ::std::default::Default::default(),
169            additional_properties: ::std::default::Default::default(),
170        }
171    }
172}
173#[derive(Clone, Debug, :: serde :: Serialize, :: serde :: Deserialize)]
174pub struct PostParams {
175    #[serde(skip_serializing_if = "Option::is_none", default)]
176    pub comment: Option<CommentStr>,
177    #[serde(skip_serializing_if = "Option::is_none", default)]
178    pub email: Option<EmailStr>,
179    #[serde(
180        serialize_with = "crate::types::serialize_bool_optional",
181        deserialize_with = "crate::types::deserialize_bool_optional"
182    )]
183    #[serde(skip_serializing_if = "Option::is_none", default)]
184    #[doc = "Enable the account (default). You can set this to '0' to disable the account"]
185    #[doc = ""]
186    pub enable: Option<bool>,
187    #[serde(
188        serialize_with = "crate::types::serialize_unsigned_int_optional",
189        deserialize_with = "crate::types::deserialize_unsigned_int_optional"
190    )]
191    #[serde(skip_serializing_if = "Option::is_none", default)]
192    #[doc = "Account expiration date (seconds since epoch). '0' means no expiration date."]
193    #[doc = ""]
194    pub expire: Option<u64>,
195    #[serde(skip_serializing_if = "Option::is_none", default)]
196    pub firstname: Option<FirstnameStr>,
197    #[serde(skip_serializing_if = "Option::is_none", default)]
198    pub groups: Option<String>,
199    #[serde(skip_serializing_if = "Option::is_none", default)]
200    #[doc = "Keys for two factor auth (yubico)."]
201    #[doc = ""]
202    pub keys: Option<KeysStr>,
203    #[serde(skip_serializing_if = "Option::is_none", default)]
204    pub lastname: Option<LastnameStr>,
205    #[serde(skip_serializing_if = "Option::is_none", default)]
206    #[doc = "Initial password."]
207    #[doc = ""]
208    pub password: Option<PasswordStr>,
209    #[doc = "Full User ID, in the `name@realm` format."]
210    #[doc = ""]
211    pub userid: UseridStr,
212    #[serde(
213        flatten,
214        default,
215        skip_serializing_if = "::std::collections::HashMap::is_empty"
216    )]
217    pub additional_properties: ::std::collections::HashMap<String, ::serde_json::Value>,
218}
219impl TokensGetOutputItemsTokensItems {
220    pub fn new(tokenid: TokenidStr) -> Self {
221        Self {
222            tokenid,
223            comment: ::std::default::Default::default(),
224            expire: ::std::default::Default::default(),
225            privsep: ::std::default::Default::default(),
226            additional_properties: ::std::default::Default::default(),
227        }
228    }
229}
230#[derive(Clone, Debug, :: serde :: Serialize, :: serde :: Deserialize)]
231pub struct TokensGetOutputItemsTokensItems {
232    #[serde(skip_serializing_if = "Option::is_none", default)]
233    pub comment: Option<String>,
234    #[serde(
235        serialize_with = "crate::types::serialize_unsigned_int_optional",
236        deserialize_with = "crate::types::deserialize_unsigned_int_optional"
237    )]
238    #[serde(skip_serializing_if = "Option::is_none", default)]
239    #[doc = "API token expiration date (seconds since epoch). '0' means no expiration date."]
240    #[doc = ""]
241    pub expire: Option<u64>,
242    #[serde(
243        serialize_with = "crate::types::serialize_bool_optional",
244        deserialize_with = "crate::types::deserialize_bool_optional"
245    )]
246    #[serde(skip_serializing_if = "Option::is_none", default)]
247    #[doc = "Restrict API token privileges with separate ACLs (default), or give full privileges of corresponding user."]
248    #[doc = ""]
249    pub privsep: Option<bool>,
250    #[doc = "User-specific token identifier."]
251    #[doc = ""]
252    pub tokenid: TokenidStr,
253    #[serde(
254        flatten,
255        default,
256        skip_serializing_if = "::std::collections::HashMap::is_empty"
257    )]
258    pub additional_properties: ::std::collections::HashMap<String, ::serde_json::Value>,
259}
260#[derive(Debug, Clone, PartialEq, PartialOrd)]
261pub struct CommentStr {
262    value: String,
263}
264impl crate::types::bounded_string::BoundedString for CommentStr {
265    const MIN_LENGTH: Option<usize> = None::<usize>;
266    const MAX_LENGTH: Option<usize> = Some(2048usize);
267    const DEFAULT: Option<&'static str> = None::<&'static str>;
268    const PATTERN: Option<&'static str> = None::<&'static str>;
269    const TYPE_DESCRIPTION: &'static str = "a string with length at most 2048";
270    fn get_value(&self) -> &str {
271        &self.value
272    }
273    fn new(value: String) -> Result<Self, crate::types::bounded_string::BoundedStringError> {
274        Self::validate(&value)?;
275        Ok(Self { value })
276    }
277}
278impl std::convert::TryFrom<String> for CommentStr {
279    type Error = crate::types::bounded_string::BoundedStringError;
280    fn try_from(value: String) -> Result<Self, Self::Error> {
281        crate::types::bounded_string::BoundedString::new(value)
282    }
283}
284impl ::serde::Serialize for CommentStr {
285    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
286    where
287        S: ::serde::Serializer,
288    {
289        crate::types::bounded_string::serialize_bounded_string(self, serializer)
290    }
291}
292impl<'de> ::serde::Deserialize<'de> for CommentStr {
293    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
294    where
295        D: ::serde::Deserializer<'de>,
296    {
297        crate::types::bounded_string::deserialize_bounded_string(deserializer)
298    }
299}
300#[derive(Debug, Clone, PartialEq, PartialOrd)]
301pub struct EmailStr {
302    value: String,
303}
304impl crate::types::bounded_string::BoundedString for EmailStr {
305    const MIN_LENGTH: Option<usize> = None::<usize>;
306    const MAX_LENGTH: Option<usize> = Some(254usize);
307    const DEFAULT: Option<&'static str> = None::<&'static str>;
308    const PATTERN: Option<&'static str> = None::<&'static str>;
309    const TYPE_DESCRIPTION: &'static str = "a string with length at most 254";
310    fn get_value(&self) -> &str {
311        &self.value
312    }
313    fn new(value: String) -> Result<Self, crate::types::bounded_string::BoundedStringError> {
314        Self::validate(&value)?;
315        Ok(Self { value })
316    }
317}
318impl std::convert::TryFrom<String> for EmailStr {
319    type Error = crate::types::bounded_string::BoundedStringError;
320    fn try_from(value: String) -> Result<Self, Self::Error> {
321        crate::types::bounded_string::BoundedString::new(value)
322    }
323}
324impl ::serde::Serialize for EmailStr {
325    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
326    where
327        S: ::serde::Serializer,
328    {
329        crate::types::bounded_string::serialize_bounded_string(self, serializer)
330    }
331}
332impl<'de> ::serde::Deserialize<'de> for EmailStr {
333    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
334    where
335        D: ::serde::Deserializer<'de>,
336    {
337        crate::types::bounded_string::deserialize_bounded_string(deserializer)
338    }
339}
340#[derive(Debug, Clone, PartialEq, PartialOrd)]
341pub struct FirstnameStr {
342    value: String,
343}
344impl crate::types::bounded_string::BoundedString for FirstnameStr {
345    const MIN_LENGTH: Option<usize> = None::<usize>;
346    const MAX_LENGTH: Option<usize> = Some(1024usize);
347    const DEFAULT: Option<&'static str> = None::<&'static str>;
348    const PATTERN: Option<&'static str> = None::<&'static str>;
349    const TYPE_DESCRIPTION: &'static str = "a string with length at most 1024";
350    fn get_value(&self) -> &str {
351        &self.value
352    }
353    fn new(value: String) -> Result<Self, crate::types::bounded_string::BoundedStringError> {
354        Self::validate(&value)?;
355        Ok(Self { value })
356    }
357}
358impl std::convert::TryFrom<String> for FirstnameStr {
359    type Error = crate::types::bounded_string::BoundedStringError;
360    fn try_from(value: String) -> Result<Self, Self::Error> {
361        crate::types::bounded_string::BoundedString::new(value)
362    }
363}
364impl ::serde::Serialize for FirstnameStr {
365    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
366    where
367        S: ::serde::Serializer,
368    {
369        crate::types::bounded_string::serialize_bounded_string(self, serializer)
370    }
371}
372impl<'de> ::serde::Deserialize<'de> for FirstnameStr {
373    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
374    where
375        D: ::serde::Deserializer<'de>,
376    {
377        crate::types::bounded_string::deserialize_bounded_string(deserializer)
378    }
379}
380#[derive(Debug, Clone, PartialEq, PartialOrd)]
381pub struct KeysStr {
382    value: String,
383}
384impl crate::types::bounded_string::BoundedString for KeysStr {
385    const MIN_LENGTH: Option<usize> = None::<usize>;
386    const MAX_LENGTH: Option<usize> = None::<usize>;
387    const DEFAULT: Option<&'static str> = None::<&'static str>;
388    const PATTERN: Option<&'static str> = Some("[0-9a-zA-Z!=]{0,4096}");
389    const TYPE_DESCRIPTION: &'static str =
390        "a string with pattern r\"[0-9a-zA-Z!=]{0,4096}\" and no length constraints";
391    fn get_value(&self) -> &str {
392        &self.value
393    }
394    fn new(value: String) -> Result<Self, crate::types::bounded_string::BoundedStringError> {
395        Self::validate(&value)?;
396        Ok(Self { value })
397    }
398}
399impl std::convert::TryFrom<String> for KeysStr {
400    type Error = crate::types::bounded_string::BoundedStringError;
401    fn try_from(value: String) -> Result<Self, Self::Error> {
402        crate::types::bounded_string::BoundedString::new(value)
403    }
404}
405impl ::serde::Serialize for KeysStr {
406    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
407    where
408        S: ::serde::Serializer,
409    {
410        crate::types::bounded_string::serialize_bounded_string(self, serializer)
411    }
412}
413impl<'de> ::serde::Deserialize<'de> for KeysStr {
414    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
415    where
416        D: ::serde::Deserializer<'de>,
417    {
418        crate::types::bounded_string::deserialize_bounded_string(deserializer)
419    }
420}
421#[derive(Debug, Clone, PartialEq, PartialOrd)]
422pub struct LastnameStr {
423    value: String,
424}
425impl crate::types::bounded_string::BoundedString for LastnameStr {
426    const MIN_LENGTH: Option<usize> = None::<usize>;
427    const MAX_LENGTH: Option<usize> = Some(1024usize);
428    const DEFAULT: Option<&'static str> = None::<&'static str>;
429    const PATTERN: Option<&'static str> = None::<&'static str>;
430    const TYPE_DESCRIPTION: &'static str = "a string with length at most 1024";
431    fn get_value(&self) -> &str {
432        &self.value
433    }
434    fn new(value: String) -> Result<Self, crate::types::bounded_string::BoundedStringError> {
435        Self::validate(&value)?;
436        Ok(Self { value })
437    }
438}
439impl std::convert::TryFrom<String> for LastnameStr {
440    type Error = crate::types::bounded_string::BoundedStringError;
441    fn try_from(value: String) -> Result<Self, Self::Error> {
442        crate::types::bounded_string::BoundedString::new(value)
443    }
444}
445impl ::serde::Serialize for LastnameStr {
446    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
447    where
448        S: ::serde::Serializer,
449    {
450        crate::types::bounded_string::serialize_bounded_string(self, serializer)
451    }
452}
453impl<'de> ::serde::Deserialize<'de> for LastnameStr {
454    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
455    where
456        D: ::serde::Deserializer<'de>,
457    {
458        crate::types::bounded_string::deserialize_bounded_string(deserializer)
459    }
460}
461#[derive(Debug, Clone, PartialEq, PartialOrd)]
462pub struct PasswordStr {
463    value: String,
464}
465impl crate::types::bounded_string::BoundedString for PasswordStr {
466    const MIN_LENGTH: Option<usize> = Some(8usize);
467    const MAX_LENGTH: Option<usize> = Some(64usize);
468    const DEFAULT: Option<&'static str> = None::<&'static str>;
469    const PATTERN: Option<&'static str> = None::<&'static str>;
470    const TYPE_DESCRIPTION: &'static str = "a string with length between 8 and 64";
471    fn get_value(&self) -> &str {
472        &self.value
473    }
474    fn new(value: String) -> Result<Self, crate::types::bounded_string::BoundedStringError> {
475        Self::validate(&value)?;
476        Ok(Self { value })
477    }
478}
479impl std::convert::TryFrom<String> for PasswordStr {
480    type Error = crate::types::bounded_string::BoundedStringError;
481    fn try_from(value: String) -> Result<Self, Self::Error> {
482        crate::types::bounded_string::BoundedString::new(value)
483    }
484}
485impl ::serde::Serialize for PasswordStr {
486    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
487    where
488        S: ::serde::Serializer,
489    {
490        crate::types::bounded_string::serialize_bounded_string(self, serializer)
491    }
492}
493impl<'de> ::serde::Deserialize<'de> for PasswordStr {
494    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
495    where
496        D: ::serde::Deserializer<'de>,
497    {
498        crate::types::bounded_string::deserialize_bounded_string(deserializer)
499    }
500}
501#[derive(Debug, Clone, PartialEq, PartialOrd)]
502pub struct TokenidStr {
503    value: String,
504}
505impl crate::types::bounded_string::BoundedString for TokenidStr {
506    const MIN_LENGTH: Option<usize> = None::<usize>;
507    const MAX_LENGTH: Option<usize> = None::<usize>;
508    const DEFAULT: Option<&'static str> = None::<&'static str>;
509    const PATTERN: Option<&'static str> = Some("(?^:[A-Za-z][A-Za-z0-9\\.\\-_]+)");
510    const TYPE_DESCRIPTION: &'static str =
511        "a string with pattern r\"(?^:[A-Za-z][A-Za-z0-9\\.\\-_]+)\" and no length constraints";
512    fn get_value(&self) -> &str {
513        &self.value
514    }
515    fn new(value: String) -> Result<Self, crate::types::bounded_string::BoundedStringError> {
516        Self::validate(&value)?;
517        Ok(Self { value })
518    }
519}
520impl std::convert::TryFrom<String> for TokenidStr {
521    type Error = crate::types::bounded_string::BoundedStringError;
522    fn try_from(value: String) -> Result<Self, Self::Error> {
523        crate::types::bounded_string::BoundedString::new(value)
524    }
525}
526impl ::serde::Serialize for TokenidStr {
527    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
528    where
529        S: ::serde::Serializer,
530    {
531        crate::types::bounded_string::serialize_bounded_string(self, serializer)
532    }
533}
534impl<'de> ::serde::Deserialize<'de> for TokenidStr {
535    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
536    where
537        D: ::serde::Deserializer<'de>,
538    {
539        crate::types::bounded_string::deserialize_bounded_string(deserializer)
540    }
541}
542#[derive(Debug, Clone, PartialEq, PartialOrd)]
543pub struct UseridStr {
544    value: String,
545}
546impl crate::types::bounded_string::BoundedString for UseridStr {
547    const MIN_LENGTH: Option<usize> = None::<usize>;
548    const MAX_LENGTH: Option<usize> = Some(64usize);
549    const DEFAULT: Option<&'static str> = None::<&'static str>;
550    const PATTERN: Option<&'static str> = None::<&'static str>;
551    const TYPE_DESCRIPTION: &'static str = "a string with length at most 64";
552    fn get_value(&self) -> &str {
553        &self.value
554    }
555    fn new(value: String) -> Result<Self, crate::types::bounded_string::BoundedStringError> {
556        Self::validate(&value)?;
557        Ok(Self { value })
558    }
559}
560impl std::convert::TryFrom<String> for UseridStr {
561    type Error = crate::types::bounded_string::BoundedStringError;
562    fn try_from(value: String) -> Result<Self, Self::Error> {
563        crate::types::bounded_string::BoundedString::new(value)
564    }
565}
566impl ::serde::Serialize for UseridStr {
567    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
568    where
569        S: ::serde::Serializer,
570    {
571        crate::types::bounded_string::serialize_bounded_string(self, serializer)
572    }
573}
574impl<'de> ::serde::Deserialize<'de> for UseridStr {
575    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
576    where
577        D: ::serde::Deserializer<'de>,
578    {
579        crate::types::bounded_string::deserialize_bounded_string(deserializer)
580    }
581}
582impl<T> UsersClient<T>
583where
584    T: crate::client::Client,
585{
586    pub fn userid(&self, userid: &str) -> userid::UseridClient<T> {
587        userid::UseridClient::<T>::new(self.client.clone(), &self.path, userid)
588    }
589}