etcd_client/rpc/
auth.rs

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