Skip to main content

etcd_client/rpc/
auth.rs

1//! Etcd Auth RPC.
2
3pub use crate::rpc::pb::authpb::permission::Type as PermissionType;
4
5use crate::error::Result;
6use crate::intercept::InterceptedChannel;
7use crate::rpc::pb::authpb::{Permission as PbPermission, UserAddOptions as PbUserAddOptions};
8use crate::rpc::pb::etcdserverpb::auth_client::AuthClient as PbAuthClient;
9use crate::rpc::pb::etcdserverpb::{
10    AuthDisableRequest as PbAuthDisableRequest, AuthDisableResponse as PbAuthDisableResponse,
11    AuthEnableRequest as PbAuthEnableRequest, AuthEnableResponse as PbAuthEnableResponse,
12    AuthRoleAddRequest as PbAuthRoleAddRequest, AuthRoleAddResponse as PbAuthRoleAddResponse,
13    AuthRoleDeleteRequest as PbAuthRoleDeleteRequest,
14    AuthRoleDeleteResponse as PbAuthRoleDeleteResponse, AuthRoleGetRequest as PbAuthRoleGetRequest,
15    AuthRoleGetResponse as PbAuthRoleGetResponse,
16    AuthRoleGrantPermissionRequest as PbAuthRoleGrantPermissionRequest,
17    AuthRoleGrantPermissionResponse as PbAuthRoleGrantPermissionResponse,
18    AuthRoleListRequest as PbAuthRoleListRequest, AuthRoleListResponse as PbAuthRoleListResponse,
19    AuthRoleRevokePermissionRequest as PbAuthRoleRevokePermissionRequest,
20    AuthRoleRevokePermissionResponse as PbAuthRoleRevokePermissionResponse,
21    AuthUserAddRequest as PbAuthUserAddRequest, AuthUserAddResponse as PbAuthUserAddResponse,
22    AuthUserChangePasswordRequest as PbAuthUserChangePasswordRequest,
23    AuthUserChangePasswordResponse as PbAuthUserChangePasswordResponse,
24    AuthUserDeleteRequest as PbAuthUserDeleteRequest,
25    AuthUserDeleteResponse as PbAuthUserDeleteResponse, AuthUserGetRequest as PbAuthUserGetRequest,
26    AuthUserGetResponse as PbAuthUserGetResponse,
27    AuthUserGrantRoleRequest as PbAuthUserGrantRoleRequest,
28    AuthUserGrantRoleResponse as PbAuthUserGrantRoleResponse,
29    AuthUserListRequest as PbAuthUserListRequest, AuthUserListResponse as PbAuthUserListResponse,
30    AuthUserRevokeRoleRequest as PbAuthUserRevokeRoleRequest,
31    AuthUserRevokeRoleResponse as PbAuthUserRevokeRoleResponse,
32    AuthenticateRequest as PbAuthenticateRequest, AuthenticateResponse as PbAuthenticateResponse,
33};
34use crate::rpc::ResponseHeader;
35use crate::rpc::{get_prefix, KeyRange};
36use tonic::{IntoRequest, Request};
37
38/// Client for Auth operations.
39#[derive(Clone)]
40pub struct AuthClient {
41    inner: PbAuthClient<InterceptedChannel>,
42}
43
44impl AuthClient {
45    /// Creates an auth client.
46    #[inline]
47    pub(crate) fn new(channel: InterceptedChannel) -> Self {
48        let inner = PbAuthClient::new(channel);
49        Self { inner }
50    }
51
52    /// Enables authentication for the etcd cluster.
53    #[inline]
54    pub async fn auth_enable(&mut self) -> Result<AuthEnableResponse> {
55        let resp = self
56            .inner
57            .auth_enable(AuthEnableOptions::new())
58            .await?
59            .into_inner();
60        Ok(AuthEnableResponse::new(resp))
61    }
62
63    /// Disables authentication for the etcd cluster.
64    #[inline]
65    pub async fn auth_disable(&mut self) -> Result<AuthDisableResponse> {
66        let resp = self
67            .inner
68            .auth_disable(AuthDisableOptions::new())
69            .await?
70            .into_inner();
71        Ok(AuthDisableResponse::new(resp))
72    }
73
74    /// Sends an authenticate request.
75    ///
76    /// Note that this does not set or update client-side authentication settings.
77    /// Call [`crate::Client::refresh_token`] instead.
78    #[inline]
79    pub async fn authenticate(
80        &mut self,
81        name: String,
82        password: String,
83    ) -> Result<AuthenticateResponse> {
84        let resp = self
85            .inner
86            .authenticate(AuthenticateOptions::new().with_user(name, password))
87            .await?
88            .into_inner();
89        Ok(AuthenticateResponse::new(resp))
90    }
91
92    /// Adds role
93    #[inline]
94    pub async fn role_add(&mut self, name: impl Into<String>) -> Result<RoleAddResponse> {
95        let resp = self
96            .inner
97            .role_add(RoleAddOptions::new(name.into()))
98            .await?
99            .into_inner();
100        Ok(RoleAddResponse::new(resp))
101    }
102
103    /// Deletes role
104    #[inline]
105    pub async fn role_delete(&mut self, name: impl Into<String>) -> Result<RoleDeleteResponse> {
106        let resp = self
107            .inner
108            .role_delete(RoleDeleteOptions::new(name.into()))
109            .await?
110            .into_inner();
111        Ok(RoleDeleteResponse::new(resp))
112    }
113
114    /// Gets role
115    #[inline]
116    pub async fn role_get(&mut self, name: impl Into<String>) -> Result<RoleGetResponse> {
117        let resp = self
118            .inner
119            .role_get(RoleGetOptions::new(name.into()))
120            .await?
121            .into_inner();
122        Ok(RoleGetResponse::new(resp))
123    }
124
125    /// Lists role
126    #[inline]
127    pub async fn role_list(&mut self) -> Result<RoleListResponse> {
128        let resp = self
129            .inner
130            .role_list(AuthRoleListOptions {})
131            .await?
132            .into_inner();
133        Ok(RoleListResponse::new(resp))
134    }
135
136    /// Grants role permission
137    #[inline]
138    pub async fn role_grant_permission(
139        &mut self,
140        name: impl Into<String>,
141        perm: Permission,
142    ) -> Result<RoleGrantPermissionResponse> {
143        let resp = self
144            .inner
145            .role_grant_permission(RoleGrantPermissionOptions::new(name.into(), perm))
146            .await?
147            .into_inner();
148        Ok(RoleGrantPermissionResponse::new(resp))
149    }
150
151    /// Revokes role permission
152    #[inline]
153    pub async fn role_revoke_permission(
154        &mut self,
155        name: impl Into<String>,
156        key: impl Into<Vec<u8>>,
157        options: Option<RoleRevokePermissionOptions>,
158    ) -> Result<RoleRevokePermissionResponse> {
159        let resp = self
160            .inner
161            .role_revoke_permission(
162                options
163                    .unwrap_or_default()
164                    .with_name(name.into())
165                    .with_key(key.into()),
166            )
167            .await?
168            .into_inner();
169        Ok(RoleRevokePermissionResponse::new(resp))
170    }
171
172    /// Adds user
173    #[inline]
174    pub async fn user_add(
175        &mut self,
176        name: impl Into<String>,
177        password: impl Into<String>,
178        options: Option<UserAddOptions>,
179    ) -> Result<UserAddResponse> {
180        let resp = self
181            .inner
182            .user_add(
183                options
184                    .unwrap_or_default()
185                    .with_name(name.into())
186                    .with_pwd(password.into()),
187            )
188            .await?
189            .into_inner();
190        Ok(UserAddResponse::new(resp))
191    }
192
193    /// Gets user
194    #[inline]
195    pub async fn user_get(&mut self, name: impl Into<String>) -> Result<UserGetResponse> {
196        let resp = self
197            .inner
198            .user_get(UserGetOptions::new(name.into()))
199            .await?
200            .into_inner();
201        Ok(UserGetResponse::new(resp))
202    }
203
204    /// Lists user
205    #[inline]
206    pub async fn user_list(&mut self) -> Result<UserListResponse> {
207        let resp = self
208            .inner
209            .user_list(AuthUserListOptions {})
210            .await?
211            .into_inner();
212        Ok(UserListResponse::new(resp))
213    }
214
215    /// Deletes user
216    #[inline]
217    pub async fn user_delete(&mut self, name: impl Into<String>) -> Result<UserDeleteResponse> {
218        let resp = self
219            .inner
220            .user_delete(UserDeleteOptions::new(name.into()))
221            .await?
222            .into_inner();
223        Ok(UserDeleteResponse::new(resp))
224    }
225
226    /// Change user's password
227    #[inline]
228    pub async fn user_change_password(
229        &mut self,
230        name: impl Into<String>,
231        password: impl Into<String>,
232    ) -> Result<UserChangePasswordResponse> {
233        let resp = self
234            .inner
235            .user_change_password(UserChangePasswordOptions::new(name.into(), password.into()))
236            .await?
237            .into_inner();
238        Ok(UserChangePasswordResponse::new(resp))
239    }
240
241    /// Grant role for an user
242    #[inline]
243    pub async fn user_grant_role(
244        &mut self,
245        name: impl Into<String>,
246        role: impl Into<String>,
247    ) -> Result<UserGrantRoleResponse> {
248        let resp = self
249            .inner
250            .user_grant_role(UserGrantRoleOptions::new(name.into(), role.into()))
251            .await?
252            .into_inner();
253        Ok(UserGrantRoleResponse::new(resp))
254    }
255
256    /// Revoke role for an user
257    #[inline]
258    pub async fn user_revoke_role(
259        &mut self,
260        name: impl Into<String>,
261        role: impl Into<String>,
262    ) -> Result<UserRevokeRoleResponse> {
263        let resp = self
264            .inner
265            .user_revoke_role(UserRevokeRoleOptions::new(name.into(), role.into()))
266            .await?
267            .into_inner();
268        Ok(UserRevokeRoleResponse::new(resp))
269    }
270}
271
272/// Options for `AuthEnable` operation.
273#[derive(Debug, Default, Clone)]
274pub struct AuthEnableOptions(PbAuthEnableRequest);
275
276impl AuthEnableOptions {
277    /// Creates a `AuthEnableOptions`.
278    #[inline]
279    pub const fn new() -> Self {
280        Self(PbAuthEnableRequest {})
281    }
282}
283
284impl From<AuthEnableOptions> for PbAuthEnableRequest {
285    #[inline]
286    fn from(options: AuthEnableOptions) -> Self {
287        options.0
288    }
289}
290
291impl IntoRequest<PbAuthEnableRequest> for AuthEnableOptions {
292    #[inline]
293    fn into_request(self) -> Request<PbAuthEnableRequest> {
294        Request::new(self.into())
295    }
296}
297
298/// Response for `AuthEnable` operation.
299#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
300#[derive(Debug, Default, Clone)]
301#[repr(transparent)]
302pub struct AuthEnableResponse(PbAuthEnableResponse);
303
304impl AuthEnableResponse {
305    /// Creates a new `AuthEnableResponse` from pb auth response.
306    #[inline]
307    const fn new(resp: PbAuthEnableResponse) -> Self {
308        Self(resp)
309    }
310
311    /// Gets response header.
312    #[inline]
313    pub fn header(&self) -> Option<&ResponseHeader> {
314        self.0.header.as_ref().map(From::from)
315    }
316
317    /// Takes the header out of the response, leaving a [`None`] in its place.
318    #[inline]
319    pub fn take_header(&mut self) -> Option<ResponseHeader> {
320        self.0.header.take().map(ResponseHeader::new)
321    }
322}
323
324/// Options for `AuthDisable` operation.
325#[derive(Debug, Default, Clone)]
326pub struct AuthDisableOptions(PbAuthDisableRequest);
327
328impl AuthDisableOptions {
329    /// Creates a `AuthDisableOptions`.
330    #[inline]
331    pub const fn new() -> Self {
332        Self(PbAuthDisableRequest {})
333    }
334}
335
336impl From<AuthDisableOptions> for PbAuthDisableRequest {
337    #[inline]
338    fn from(options: AuthDisableOptions) -> Self {
339        options.0
340    }
341}
342
343impl IntoRequest<PbAuthDisableRequest> for AuthDisableOptions {
344    #[inline]
345    fn into_request(self) -> Request<PbAuthDisableRequest> {
346        Request::new(self.into())
347    }
348}
349
350/// Response for `AuthDisable` operation.
351#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
352#[derive(Debug, Default, Clone)]
353#[repr(transparent)]
354pub struct AuthDisableResponse(PbAuthDisableResponse);
355
356impl AuthDisableResponse {
357    /// Creates a new `AuthDisableResponse` from pb auth response.
358    #[inline]
359    const fn new(resp: PbAuthDisableResponse) -> Self {
360        Self(resp)
361    }
362
363    /// Gets response header.
364    #[inline]
365    pub fn header(&self) -> Option<&ResponseHeader> {
366        self.0.header.as_ref().map(From::from)
367    }
368
369    /// Takes the header out of the response, leaving a [`None`] in its place.
370    #[inline]
371    pub fn take_header(&mut self) -> Option<ResponseHeader> {
372        self.0.header.take().map(ResponseHeader::new)
373    }
374}
375
376/// Options for `Authenticate` operation.
377#[derive(Debug, Default, Clone)]
378#[repr(transparent)]
379pub struct AuthenticateOptions(PbAuthenticateRequest);
380
381impl AuthenticateOptions {
382    /// Sets user's name and password.
383    #[inline]
384    fn with_user(mut self, name: String, password: String) -> Self {
385        self.0.name = name;
386        self.0.password = password;
387        self
388    }
389
390    /// Creates a `AuthenticateOptions`.
391    #[inline]
392    pub const fn new() -> Self {
393        Self(PbAuthenticateRequest {
394            name: String::new(),
395            password: String::new(),
396        })
397    }
398}
399
400impl From<AuthenticateOptions> for PbAuthenticateRequest {
401    #[inline]
402    fn from(options: AuthenticateOptions) -> Self {
403        options.0
404    }
405}
406
407impl IntoRequest<PbAuthenticateRequest> for AuthenticateOptions {
408    #[inline]
409    fn into_request(self) -> Request<PbAuthenticateRequest> {
410        Request::new(self.into())
411    }
412}
413
414/// Response for `Authenticate` operation.
415#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
416#[derive(Debug, Default, Clone)]
417#[repr(transparent)]
418pub struct AuthenticateResponse(PbAuthenticateResponse);
419
420impl AuthenticateResponse {
421    /// Creates a new `AuthenticateResponse` from pb auth response.
422    #[inline]
423    const fn new(resp: PbAuthenticateResponse) -> Self {
424        Self(resp)
425    }
426
427    /// Gets response header.
428    #[allow(dead_code)]
429    #[inline]
430    pub fn header(&self) -> Option<&ResponseHeader> {
431        self.0.header.as_ref().map(From::from)
432    }
433
434    /// Takes the header out of the response, leaving a [`None`] in its place.
435    #[allow(dead_code)]
436    #[inline]
437    pub fn take_header(&mut self) -> Option<ResponseHeader> {
438        self.0.header.take().map(ResponseHeader::new)
439    }
440
441    /// An authorized token that can be used in succeeding RPCs
442    #[inline]
443    pub fn token(&self) -> &str {
444        &self.0.token
445    }
446}
447
448/// Options for `RoleAddOptions` operation.
449#[derive(Debug, Default, Clone)]
450#[repr(transparent)]
451pub struct RoleAddOptions(PbAuthRoleAddRequest);
452
453impl RoleAddOptions {
454    /// Creates a `RoleAddOptions`.
455    #[inline]
456    pub fn new(name: String) -> Self {
457        Self(PbAuthRoleAddRequest { name })
458    }
459}
460
461impl From<RoleAddOptions> for PbAuthRoleAddRequest {
462    #[inline]
463    fn from(options: RoleAddOptions) -> Self {
464        options.0
465    }
466}
467
468impl IntoRequest<PbAuthRoleAddRequest> for RoleAddOptions {
469    #[inline]
470    fn into_request(self) -> Request<PbAuthRoleAddRequest> {
471        Request::new(self.into())
472    }
473}
474
475/// Response for role add operation.
476#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
477#[derive(Debug, Clone)]
478#[repr(transparent)]
479pub struct RoleAddResponse(PbAuthRoleAddResponse);
480
481impl RoleAddResponse {
482    /// Creates a new `RoleAddResponse` from pb role add response.
483    #[inline]
484    const fn new(resp: PbAuthRoleAddResponse) -> Self {
485        Self(resp)
486    }
487
488    /// Gets response header.
489    #[inline]
490    pub fn header(&self) -> Option<&ResponseHeader> {
491        self.0.header.as_ref().map(From::from)
492    }
493
494    /// Takes the header out of the response, leaving a [`None`] in its place.
495    #[inline]
496    pub fn take_header(&mut self) -> Option<ResponseHeader> {
497        self.0.header.take().map(ResponseHeader::new)
498    }
499}
500
501/// Options for delete role operation.
502#[derive(Debug, Default, Clone)]
503#[repr(transparent)]
504pub struct RoleDeleteOptions(PbAuthRoleDeleteRequest);
505
506impl RoleDeleteOptions {
507    /// Creates a `RoleDeleteOptions` to delete role.
508    #[inline]
509    pub fn new(name: String) -> Self {
510        Self(PbAuthRoleDeleteRequest { role: name })
511    }
512}
513
514impl From<RoleDeleteOptions> for PbAuthRoleDeleteRequest {
515    #[inline]
516    fn from(options: RoleDeleteOptions) -> Self {
517        options.0
518    }
519}
520
521impl IntoRequest<PbAuthRoleDeleteRequest> for RoleDeleteOptions {
522    #[inline]
523    fn into_request(self) -> Request<PbAuthRoleDeleteRequest> {
524        Request::new(self.into())
525    }
526}
527
528/// Response for delete role operation.
529#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
530#[derive(Debug, Clone)]
531#[repr(transparent)]
532pub struct RoleDeleteResponse(PbAuthRoleDeleteResponse);
533
534impl RoleDeleteResponse {
535    /// Creates a new `RoleDeleteResponse` from pb role delete response.
536    #[inline]
537    const fn new(resp: PbAuthRoleDeleteResponse) -> Self {
538        Self(resp)
539    }
540
541    /// Gets response header.
542    #[inline]
543    pub fn header(&self) -> Option<&ResponseHeader> {
544        self.0.header.as_ref().map(From::from)
545    }
546
547    /// Takes the header out of the response, leaving a [`None`] in its place.
548    #[inline]
549    pub fn take_header(&mut self) -> Option<ResponseHeader> {
550        self.0.header.take().map(ResponseHeader::new)
551    }
552}
553
554/// Options for get role operation.
555#[derive(Debug, Default, Clone)]
556#[repr(transparent)]
557pub struct RoleGetOptions(PbAuthRoleGetRequest);
558
559impl RoleGetOptions {
560    /// Creates a `RoleGetOptions` to get role.
561    #[inline]
562    pub fn new(name: String) -> Self {
563        Self(PbAuthRoleGetRequest { role: name })
564    }
565}
566
567impl From<RoleGetOptions> for PbAuthRoleGetRequest {
568    #[inline]
569    fn from(options: RoleGetOptions) -> Self {
570        options.0
571    }
572}
573
574impl IntoRequest<PbAuthRoleGetRequest> for RoleGetOptions {
575    #[inline]
576    fn into_request(self) -> Request<PbAuthRoleGetRequest> {
577        Request::new(self.into())
578    }
579}
580
581/// Role access permission.
582#[derive(Debug, Clone)]
583pub struct Permission {
584    inner: PbPermission,
585    with_prefix: bool,
586    with_from_key: bool,
587}
588
589impl Permission {
590    /// Creates a permission with operation type and key
591    #[inline]
592    pub fn new(perm_type: PermissionType, key: impl Into<Vec<u8>>) -> Self {
593        Self {
594            inner: PbPermission {
595                perm_type: perm_type.into(),
596                key: key.into(),
597                range_end: Vec::new(),
598            },
599            with_prefix: false,
600            with_from_key: false,
601        }
602    }
603
604    /// Creates a read permission with key
605    #[inline]
606    pub fn read(key: impl Into<Vec<u8>>) -> Self {
607        Permission::new(PermissionType::Read, key)
608    }
609
610    /// Creates a write permission with key
611    #[inline]
612    pub fn write(key: impl Into<Vec<u8>>) -> Self {
613        Permission::new(PermissionType::Write, key)
614    }
615
616    /// Creates a read write permission with key
617    #[inline]
618    pub fn read_write(key: impl Into<Vec<u8>>) -> Self {
619        Permission::new(PermissionType::Readwrite, key)
620    }
621
622    /// Sets range end for the permission
623    #[inline]
624    pub fn with_range_end(mut self, range_end: impl Into<Vec<u8>>) -> Self {
625        self.inner.range_end = range_end.into();
626        self.with_prefix = false;
627        self.with_from_key = false;
628        self
629    }
630
631    /// Sets the permission with all keys >= key.
632    #[inline]
633    pub fn with_from_key(mut self) -> Self {
634        self.with_from_key = true;
635        self.with_prefix = false;
636        self
637    }
638
639    /// Sets the permission with all keys prefixed with key.
640    #[inline]
641    pub fn with_prefix(mut self) -> Self {
642        self.with_prefix = true;
643        self.with_from_key = false;
644        self
645    }
646
647    /// Sets the permission with all keys.
648    #[inline]
649    pub fn with_all_keys(mut self) -> Self {
650        self.inner.key.clear();
651        self.with_from_key()
652    }
653
654    /// The key in bytes. An empty key is not allowed.
655    #[inline]
656    pub fn key(&self) -> &[u8] {
657        &self.inner.key
658    }
659
660    /// The range end in bytes. maybe empty
661    #[inline]
662    pub fn range_end(&self) -> &[u8] {
663        &self.inner.range_end
664    }
665
666    /// The key in string. An empty key is not allowed.
667    #[inline]
668    pub fn key_str(&self) -> Result<&str> {
669        std::str::from_utf8(self.key()).map_err(From::from)
670    }
671
672    /// The key in string. An empty key is not allowed.
673    ///
674    /// # Safety
675    /// This function is unsafe because it does not check that the bytes of the key are valid UTF-8.
676    /// If this constraint is violated, undefined behavior results,
677    /// as the rest of Rust assumes that [`&str`]s are valid UTF-8.
678    #[inline]
679    pub unsafe fn key_str_unchecked(&self) -> &str {
680        std::str::from_utf8_unchecked(self.key())
681    }
682
683    /// The range end in string.
684    #[inline]
685    pub fn range_end_str(&self) -> Result<&str> {
686        std::str::from_utf8(self.range_end()).map_err(From::from)
687    }
688
689    /// The range end in string.
690    ///
691    /// # Safety
692    /// This function is unsafe because it does not check that the bytes of the key are valid UTF-8.
693    /// If this constraint is violated, undefined behavior results,
694    /// as the rest of Rust assumes that [`&str`]s are valid UTF-8.
695    #[inline]
696    pub unsafe fn range_end_str_unchecked(&self) -> &str {
697        std::str::from_utf8_unchecked(self.key())
698    }
699
700    /// Gets the operation type of permission.
701    #[inline]
702    pub const fn get_type(&self) -> i32 {
703        self.inner.perm_type
704    }
705
706    /// Indicates whether permission is with keys >= key.
707    #[inline]
708    pub const fn is_from_key(&self) -> bool {
709        self.with_from_key
710    }
711
712    /// Indicates whether permission is with all keys prefixed with key.
713    #[inline]
714    pub const fn is_prefix(&self) -> bool {
715        self.with_prefix
716    }
717}
718
719impl PartialEq for Permission {
720    #[inline]
721    fn eq(&self, other: &Self) -> bool {
722        if (self.with_prefix == other.with_prefix)
723            && (self.with_from_key == other.with_from_key)
724            && (self.inner.perm_type == other.inner.perm_type)
725        {
726            if self.inner.key == other.inner.key {
727                true
728            } else {
729                (self.inner.key.is_empty() && other.inner.key == *b"\0")
730                    || (self.inner.key == *b"\0" && other.inner.key.is_empty())
731            }
732        } else {
733            false
734        }
735    }
736}
737
738impl From<&PbPermission> for Permission {
739    #[inline]
740    fn from(src: &PbPermission) -> Self {
741        let mut perm = Permission {
742            inner: PbPermission {
743                perm_type: src.perm_type,
744                key: src.key.clone(),
745                range_end: src.range_end.clone(),
746            },
747            with_from_key: false,
748            with_prefix: false,
749        };
750
751        if perm.inner.range_end == *b"\0" {
752            perm.with_from_key = true;
753        } else if !perm.inner.range_end.is_empty() {
754            let prefix = get_prefix(&perm.inner.key);
755            if prefix == perm.inner.range_end {
756                perm.with_prefix = true;
757            }
758        }
759        perm
760    }
761}
762
763impl From<Permission> for PbPermission {
764    #[inline]
765    fn from(mut perm: Permission) -> Self {
766        let mut key_range = KeyRange::new();
767        key_range.with_key(perm.inner.key);
768        key_range.with_range(perm.inner.range_end);
769        if perm.with_prefix {
770            key_range.with_prefix();
771        } else if perm.with_from_key {
772            key_range.with_from_key();
773        }
774        let (key, range_end) = key_range.build();
775        perm.inner.key = key;
776        perm.inner.range_end = range_end;
777        perm.inner
778    }
779}
780
781/// Response for get role operation.
782#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
783#[derive(Debug, Clone)]
784#[repr(transparent)]
785pub struct RoleGetResponse(PbAuthRoleGetResponse);
786
787impl RoleGetResponse {
788    /// Creates a new `RoleGetResponse` from pb role get response.
789    #[inline]
790    const fn new(resp: PbAuthRoleGetResponse) -> Self {
791        Self(resp)
792    }
793
794    /// Gets response header.
795    #[inline]
796    pub fn header(&self) -> Option<&ResponseHeader> {
797        self.0.header.as_ref().map(From::from)
798    }
799
800    /// Takes the header out of the response, leaving a [`None`] in its place.
801    #[inline]
802    pub fn take_header(&mut self) -> Option<ResponseHeader> {
803        self.0.header.take().map(ResponseHeader::new)
804    }
805
806    /// The list of permissions by the `Get` request.
807    #[inline]
808    pub fn permissions(&self) -> Vec<Permission> {
809        let mut perms = Vec::new();
810        for p in &self.0.perm {
811            perms.push(p.into());
812        }
813        perms
814    }
815}
816
817/// Options for list role operation.
818use PbAuthRoleListRequest as AuthRoleListOptions;
819
820/// Response for list role operation.
821#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
822#[derive(Debug, Clone)]
823#[repr(transparent)]
824pub struct RoleListResponse(PbAuthRoleListResponse);
825
826impl RoleListResponse {
827    /// Creates a new `RoleListResponse` from pb role list response.
828    #[inline]
829    const fn new(resp: PbAuthRoleListResponse) -> Self {
830        Self(resp)
831    }
832
833    /// Gets response header.
834    #[inline]
835    pub fn header(&self) -> Option<&ResponseHeader> {
836        self.0.header.as_ref().map(From::from)
837    }
838
839    /// Takes the header out of the response, leaving a [`None`] in its place.
840    #[inline]
841    pub fn take_header(&mut self) -> Option<ResponseHeader> {
842        self.0.header.take().map(ResponseHeader::new)
843    }
844
845    /// Gets roles in response.
846    #[inline]
847    pub fn roles(&self) -> &[String] {
848        self.0.roles.as_slice()
849    }
850}
851
852/// Options for grant role permission operation.
853#[derive(Debug, Default, Clone)]
854#[repr(transparent)]
855pub struct RoleGrantPermissionOptions(PbAuthRoleGrantPermissionRequest);
856
857impl RoleGrantPermissionOptions {
858    /// Creates a "RoleGrantPermissionOptions" to grant role permission
859    #[inline]
860    pub fn new(name: String, perm: Permission) -> Self {
861        Self(PbAuthRoleGrantPermissionRequest {
862            name,
863            perm: Some(perm.into()),
864        })
865    }
866}
867
868impl From<RoleGrantPermissionOptions> for PbAuthRoleGrantPermissionRequest {
869    #[inline]
870    fn from(options: RoleGrantPermissionOptions) -> Self {
871        options.0
872    }
873}
874
875impl IntoRequest<PbAuthRoleGrantPermissionRequest> for RoleGrantPermissionOptions {
876    #[inline]
877    fn into_request(self) -> Request<PbAuthRoleGrantPermissionRequest> {
878        Request::new(self.into())
879    }
880}
881
882/// Response for grant role permission operation.
883#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
884#[derive(Debug, Clone)]
885#[repr(transparent)]
886pub struct RoleGrantPermissionResponse(PbAuthRoleGrantPermissionResponse);
887
888impl RoleGrantPermissionResponse {
889    /// Creates a new `RoleGrantPermissionResponse` from pb role grant permission response.
890    #[inline]
891    const fn new(resp: PbAuthRoleGrantPermissionResponse) -> Self {
892        Self(resp)
893    }
894
895    /// Gets response header.
896    #[inline]
897    pub fn header(&self) -> Option<&ResponseHeader> {
898        self.0.header.as_ref().map(From::from)
899    }
900
901    /// Takes the header out of the response, leaving a [`None`] in its place.
902    #[inline]
903    pub fn take_header(&mut self) -> Option<ResponseHeader> {
904        self.0.header.take().map(ResponseHeader::new)
905    }
906}
907
908/// Options for grant role permission operation.
909#[derive(Debug, Default, Clone)]
910pub struct RoleRevokePermissionOptions {
911    req: PbAuthRoleRevokePermissionRequest,
912    key_range: KeyRange,
913}
914
915impl RoleRevokePermissionOptions {
916    /// Create a new `RoleRevokePermissionOption` from pb role revoke permission.
917    #[inline]
918    pub const fn new() -> Self {
919        Self {
920            req: PbAuthRoleRevokePermissionRequest {
921                role: String::new(),
922                key: Vec::new(),
923                range_end: Vec::new(),
924            },
925            key_range: KeyRange::new(),
926        }
927    }
928
929    /// Sets name.
930    #[inline]
931    fn with_name(mut self, name: String) -> Self {
932        self.req.role = name;
933        self
934    }
935
936    /// Sets key.
937    #[inline]
938    fn with_key(mut self, key: impl Into<Vec<u8>>) -> Self {
939        self.key_range.with_key(key);
940        self
941    }
942
943    /// Specifies the range end.
944    /// `end_key` must be lexicographically greater than start key.
945    #[inline]
946    pub fn with_range_end(mut self, range_end: impl Into<Vec<u8>>) -> Self {
947        self.key_range.with_range(range_end);
948        self
949    }
950
951    /// Sets all keys prefixed with key.
952    #[inline]
953    pub fn with_prefix(mut self) -> Self {
954        self.key_range.with_prefix();
955        self
956    }
957
958    /// Sets all keys >= key.
959    #[inline]
960    pub fn with_from_key(mut self) -> Self {
961        self.key_range.with_from_key();
962        self
963    }
964
965    /// Sets all keys.
966    #[inline]
967    pub fn with_all_keys(mut self) -> Self {
968        self.key_range.with_all_keys();
969        self
970    }
971}
972
973impl From<RoleRevokePermissionOptions> for PbAuthRoleRevokePermissionRequest {
974    #[inline]
975    fn from(mut option: RoleRevokePermissionOptions) -> Self {
976        let (key, range_end) = option.key_range.build();
977        option.req.key = key;
978        option.req.range_end = range_end;
979        option.req
980    }
981}
982
983impl IntoRequest<PbAuthRoleRevokePermissionRequest> for RoleRevokePermissionOptions {
984    #[inline]
985    fn into_request(self) -> Request<PbAuthRoleRevokePermissionRequest> {
986        Request::new(self.into())
987    }
988}
989
990/// Response for revoke role permission operation.
991#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
992#[derive(Debug, Clone)]
993#[repr(transparent)]
994pub struct RoleRevokePermissionResponse(PbAuthRoleRevokePermissionResponse);
995
996impl RoleRevokePermissionResponse {
997    /// Creates a new `RoleRevokePermissionResponse` from pb role revoke permission response.
998    #[inline]
999    const fn new(resp: PbAuthRoleRevokePermissionResponse) -> Self {
1000        Self(resp)
1001    }
1002
1003    /// Gets response header.
1004    #[inline]
1005    pub fn header(&self) -> Option<&ResponseHeader> {
1006        self.0.header.as_ref().map(From::from)
1007    }
1008
1009    /// Takes the header out of the response, leaving a [`None`] in its place.
1010    #[inline]
1011    pub fn take_header(&mut self) -> Option<ResponseHeader> {
1012        self.0.header.take().map(ResponseHeader::new)
1013    }
1014}
1015
1016/// Options for `UserAdd` operation.
1017#[derive(Debug, Default, Clone)]
1018#[repr(transparent)]
1019pub struct UserAddOptions(PbAuthUserAddRequest);
1020
1021impl UserAddOptions {
1022    /// Creates a `UserAddOptions`.
1023    #[inline]
1024    pub const fn new() -> Self {
1025        Self(PbAuthUserAddRequest {
1026            name: String::new(),
1027            password: String::new(),
1028            options: Some(PbUserAddOptions { no_password: false }),
1029            hashed_password: String::new(),
1030        })
1031    }
1032
1033    /// Set name.
1034    #[inline]
1035    fn with_name(mut self, name: impl Into<String>) -> Self {
1036        self.0.name = name.into();
1037        self
1038    }
1039
1040    /// Set password.
1041    #[inline]
1042    fn with_pwd(mut self, password: impl Into<String>) -> Self {
1043        self.0.password = password.into();
1044        self
1045    }
1046
1047    /// Set no password.
1048    #[inline]
1049    pub const fn with_no_pwd(mut self) -> Self {
1050        self.0.options = Some(PbUserAddOptions { no_password: true });
1051        self
1052    }
1053}
1054
1055impl From<UserAddOptions> for PbAuthUserAddRequest {
1056    #[inline]
1057    fn from(options: UserAddOptions) -> Self {
1058        options.0
1059    }
1060}
1061
1062impl IntoRequest<PbAuthUserAddRequest> for UserAddOptions {
1063    #[inline]
1064    fn into_request(self) -> Request<PbAuthUserAddRequest> {
1065        Request::new(self.into())
1066    }
1067}
1068
1069/// Response for use add operation.
1070#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
1071#[derive(Debug, Clone)]
1072#[repr(transparent)]
1073pub struct UserAddResponse(PbAuthUserAddResponse);
1074
1075impl UserAddResponse {
1076    /// Creates a new `UserAddReqResponse` from pb user add response.
1077    #[inline]
1078    const fn new(resp: PbAuthUserAddResponse) -> Self {
1079        Self(resp)
1080    }
1081
1082    /// Gets response header.
1083    #[inline]
1084    pub fn header(&self) -> Option<&ResponseHeader> {
1085        self.0.header.as_ref().map(From::from)
1086    }
1087
1088    /// Takes the header out of the response, leaving a [`None`] in its place.
1089    #[inline]
1090    pub fn take_header(&mut self) -> Option<ResponseHeader> {
1091        self.0.header.take().map(ResponseHeader::new)
1092    }
1093}
1094
1095/// Options for get user operation.
1096#[derive(Debug, Default, Clone)]
1097#[repr(transparent)]
1098pub struct UserGetOptions(PbAuthUserGetRequest);
1099
1100impl UserGetOptions {
1101    /// Creates a `UserGetOptions` to get user.
1102    #[inline]
1103    pub fn new(name: String) -> Self {
1104        Self(PbAuthUserGetRequest { name })
1105    }
1106}
1107
1108impl From<UserGetOptions> for PbAuthUserGetRequest {
1109    #[inline]
1110    fn from(options: UserGetOptions) -> Self {
1111        options.0
1112    }
1113}
1114
1115impl IntoRequest<PbAuthUserGetRequest> for UserGetOptions {
1116    #[inline]
1117    fn into_request(self) -> Request<PbAuthUserGetRequest> {
1118        Request::new(self.into())
1119    }
1120}
1121
1122/// Response for get user operation.
1123#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
1124#[derive(Debug, Clone)]
1125#[repr(transparent)]
1126pub struct UserGetResponse(PbAuthUserGetResponse);
1127
1128impl UserGetResponse {
1129    /// Creates a new `UserGetResponse` from pb user get response.
1130    #[inline]
1131    const fn new(resp: PbAuthUserGetResponse) -> Self {
1132        Self(resp)
1133    }
1134
1135    /// Gets response header.
1136    #[inline]
1137    pub fn header(&self) -> Option<&ResponseHeader> {
1138        self.0.header.as_ref().map(From::from)
1139    }
1140
1141    /// Takes the header out of the response, leaving a [`None`] in its place.
1142    #[inline]
1143    pub fn take_header(&mut self) -> Option<ResponseHeader> {
1144        self.0.header.take().map(ResponseHeader::new)
1145    }
1146
1147    /// Gets roles of the user in response.
1148    #[inline]
1149    pub fn roles(&self) -> &[String] {
1150        &self.0.roles
1151    }
1152}
1153
1154/// Options for list user operation.
1155use PbAuthUserListRequest as AuthUserListOptions;
1156
1157/// Response for list user operation.
1158#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
1159#[derive(Debug, Clone)]
1160#[repr(transparent)]
1161pub struct UserListResponse(PbAuthUserListResponse);
1162
1163impl UserListResponse {
1164    /// Creates a new `UserListResponse` from pb user list response.
1165    #[inline]
1166    const fn new(resp: PbAuthUserListResponse) -> Self {
1167        Self(resp)
1168    }
1169
1170    /// Gets response header.
1171    #[inline]
1172    pub fn header(&self) -> Option<&ResponseHeader> {
1173        self.0.header.as_ref().map(From::from)
1174    }
1175
1176    /// Takes the header out of the response, leaving a [`None`] in its place.
1177    #[inline]
1178    pub fn take_header(&mut self) -> Option<ResponseHeader> {
1179        self.0.header.take().map(ResponseHeader::new)
1180    }
1181
1182    /// Gets users in response.
1183    #[inline]
1184    pub fn users(&self) -> &[String] {
1185        &self.0.users
1186    }
1187}
1188
1189/// Options for delete user operation.
1190#[derive(Debug, Default, Clone)]
1191#[repr(transparent)]
1192pub struct UserDeleteOptions(PbAuthUserDeleteRequest);
1193
1194impl UserDeleteOptions {
1195    /// Creates a `UserDeleteOptions` to delete user.
1196    #[inline]
1197    pub fn new(name: String) -> Self {
1198        Self(PbAuthUserDeleteRequest { name })
1199    }
1200}
1201
1202impl From<UserDeleteOptions> for PbAuthUserDeleteRequest {
1203    #[inline]
1204    fn from(options: UserDeleteOptions) -> Self {
1205        options.0
1206    }
1207}
1208
1209impl IntoRequest<PbAuthUserDeleteRequest> for UserDeleteOptions {
1210    #[inline]
1211    fn into_request(self) -> Request<PbAuthUserDeleteRequest> {
1212        Request::new(self.into())
1213    }
1214}
1215
1216/// Response for delete user operation.
1217#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
1218#[derive(Debug, Clone)]
1219#[repr(transparent)]
1220pub struct UserDeleteResponse(PbAuthUserDeleteResponse);
1221
1222impl UserDeleteResponse {
1223    /// Creates a new `UserDeleteResponse` from pb user delete response.
1224    #[inline]
1225    const fn new(resp: PbAuthUserDeleteResponse) -> Self {
1226        Self(resp)
1227    }
1228
1229    /// Gets response header.
1230    #[inline]
1231    pub fn header(&self) -> Option<&ResponseHeader> {
1232        self.0.header.as_ref().map(From::from)
1233    }
1234
1235    /// Takes the header out of the response, leaving a [`None`] in its place.
1236    #[inline]
1237    pub fn take_header(&mut self) -> Option<ResponseHeader> {
1238        self.0.header.take().map(ResponseHeader::new)
1239    }
1240}
1241
1242/// Options for change user's password operation.
1243#[derive(Debug, Default, Clone)]
1244#[repr(transparent)]
1245pub struct UserChangePasswordOptions(PbAuthUserChangePasswordRequest);
1246
1247impl UserChangePasswordOptions {
1248    /// Creates a `UserChangePasswordOptions` to change user's password.
1249    #[inline]
1250    pub fn new(name: String, new_password: String) -> Self {
1251        Self(PbAuthUserChangePasswordRequest {
1252            name,
1253            password: new_password,
1254            hashed_password: String::new(),
1255        })
1256    }
1257}
1258
1259impl From<UserChangePasswordOptions> for PbAuthUserChangePasswordRequest {
1260    #[inline]
1261    fn from(options: UserChangePasswordOptions) -> Self {
1262        options.0
1263    }
1264}
1265
1266impl IntoRequest<PbAuthUserChangePasswordRequest> for UserChangePasswordOptions {
1267    #[inline]
1268    fn into_request(self) -> Request<PbAuthUserChangePasswordRequest> {
1269        Request::new(self.into())
1270    }
1271}
1272
1273/// Response for change user's password operation.
1274#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
1275#[derive(Debug, Clone)]
1276#[repr(transparent)]
1277pub struct UserChangePasswordResponse(PbAuthUserChangePasswordResponse);
1278
1279impl UserChangePasswordResponse {
1280    /// Creates a new `UserChangePasswordResponse` from pb user change password response.
1281    #[inline]
1282    const fn new(resp: PbAuthUserChangePasswordResponse) -> Self {
1283        Self(resp)
1284    }
1285
1286    /// Gets response header.
1287    #[inline]
1288    pub fn header(&self) -> Option<&ResponseHeader> {
1289        self.0.header.as_ref().map(From::from)
1290    }
1291
1292    /// Takes the header out of the response, leaving a [`None`] in its place.
1293    #[inline]
1294    pub fn take_header(&mut self) -> Option<ResponseHeader> {
1295        self.0.header.take().map(ResponseHeader::new)
1296    }
1297}
1298
1299/// Options for grant role for an user operation.
1300#[derive(Debug, Default, Clone)]
1301#[repr(transparent)]
1302pub struct UserGrantRoleOptions(PbAuthUserGrantRoleRequest);
1303
1304impl UserGrantRoleOptions {
1305    /// Creates a `UserGrantRoleOptions` to grant role for an user.
1306    #[inline]
1307    pub fn new(name: String, role: String) -> Self {
1308        Self(PbAuthUserGrantRoleRequest { user: name, role })
1309    }
1310}
1311
1312impl From<UserGrantRoleOptions> for PbAuthUserGrantRoleRequest {
1313    #[inline]
1314    fn from(options: UserGrantRoleOptions) -> Self {
1315        options.0
1316    }
1317}
1318
1319impl IntoRequest<PbAuthUserGrantRoleRequest> for UserGrantRoleOptions {
1320    #[inline]
1321    fn into_request(self) -> Request<PbAuthUserGrantRoleRequest> {
1322        Request::new(self.into())
1323    }
1324}
1325
1326/// Response for grant role for an user operation.
1327#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
1328#[derive(Debug, Clone)]
1329#[repr(transparent)]
1330pub struct UserGrantRoleResponse(PbAuthUserGrantRoleResponse);
1331
1332impl UserGrantRoleResponse {
1333    /// Creates a new `UserGrantRoleResponse` from pb user grant role response.
1334    #[inline]
1335    const fn new(resp: PbAuthUserGrantRoleResponse) -> Self {
1336        Self(resp)
1337    }
1338
1339    /// Gets response header.
1340    #[inline]
1341    pub fn header(&self) -> Option<&ResponseHeader> {
1342        self.0.header.as_ref().map(From::from)
1343    }
1344
1345    /// Takes the header out of the response, leaving a [`None`] in its place.
1346    #[inline]
1347    pub fn take_header(&mut self) -> Option<ResponseHeader> {
1348        self.0.header.take().map(ResponseHeader::new)
1349    }
1350}
1351
1352/// Options for revoke role for an user operation.
1353#[derive(Debug, Default, Clone)]
1354#[repr(transparent)]
1355pub struct UserRevokeRoleOptions(PbAuthUserRevokeRoleRequest);
1356
1357impl UserRevokeRoleOptions {
1358    /// Creates a `UserRevokeRoleOptions` to revoke role for an user.
1359    #[inline]
1360    pub fn new(name: String, role: String) -> Self {
1361        Self(PbAuthUserRevokeRoleRequest { name, role })
1362    }
1363}
1364
1365impl From<UserRevokeRoleOptions> for PbAuthUserRevokeRoleRequest {
1366    #[inline]
1367    fn from(options: UserRevokeRoleOptions) -> Self {
1368        options.0
1369    }
1370}
1371
1372impl IntoRequest<PbAuthUserRevokeRoleRequest> for UserRevokeRoleOptions {
1373    #[inline]
1374    fn into_request(self) -> Request<PbAuthUserRevokeRoleRequest> {
1375        Request::new(self.into())
1376    }
1377}
1378
1379/// Response for revoke role for an user operation.
1380#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
1381#[derive(Debug, Clone)]
1382#[repr(transparent)]
1383pub struct UserRevokeRoleResponse(PbAuthUserRevokeRoleResponse);
1384
1385impl UserRevokeRoleResponse {
1386    /// Creates a new `UserRevokeRoleResponse` from pb user revoke role response.
1387    #[inline]
1388    const fn new(resp: PbAuthUserRevokeRoleResponse) -> Self {
1389        Self(resp)
1390    }
1391
1392    /// Gets response header.
1393    #[inline]
1394    pub fn header(&self) -> Option<&ResponseHeader> {
1395        self.0.header.as_ref().map(From::from)
1396    }
1397
1398    /// Takes the header out of the response, leaving a [`None`] in its place.
1399    #[inline]
1400    pub fn take_header(&mut self) -> Option<ResponseHeader> {
1401        self.0.header.take().map(ResponseHeader::new)
1402    }
1403}