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