Skip to content

Commit ee18485

Browse files
Jerry7X谢锐davidli2010
authored
Auth Role APIs(etcdv3#5)
Auth Role APIs Co-authored-by: 谢锐 <[email protected]> Co-authored-by: David Li <[email protected]>
1 parent c9cc942 commit ee18485

File tree

5 files changed

+951
-27
lines changed

5 files changed

+951
-27
lines changed

examples/auth_role.rs

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
//! Auth role example.
2+
3+
use etcd_client::*;
4+
5+
#[allow(unused_must_use)]
6+
#[tokio::main]
7+
async fn main() -> Result<(), Error> {
8+
let mut client = Client::connect(["localhost:2379"], None).await?;
9+
let role1 = "role1";
10+
let role2 = "role2";
11+
12+
// ignore result
13+
client.role_delete(role1).await;
14+
client.role_delete(role2).await;
15+
16+
client.role_add(role1).await?;
17+
println!("add role1 successfully");
18+
19+
client.role_add(role2).await?;
20+
println!("add role2 successfully");
21+
22+
let perm = Permission::read("456").with_range_end("457");
23+
client.role_grant_permission(role1, perm).await?;
24+
println!("grant role1 permission successfully");
25+
26+
let perm1 = Permission::read("abc");
27+
client.role_grant_permission(role1, perm1).await?;
28+
println!("grant role1 permission successfully");
29+
30+
let perm2 = Permission::read_write("123").with_prefix();
31+
client.role_grant_permission(role1, perm2).await?;
32+
println!("grant role1 permission successfully");
33+
34+
let perm3 = Permission::read("a");
35+
client.role_grant_permission(role1, perm3).await?;
36+
println!("grant role1 permission successfully");
37+
38+
let perm4 = Permission::write("b").with_prefix();
39+
let resp = client.role_grant_permission(role1, perm4).await?;
40+
println!("{:?}", resp.header());
41+
42+
let perm5 = Permission::read_write("d").with_range_end("h");
43+
let resp = client.role_grant_permission(role1, perm5).await?;
44+
println!("{:?}", resp.header());
45+
46+
let resp = client.role_get(role1).await?;
47+
//show the result
48+
println!("Role {:?}\n{:?}", role1, resp);
49+
50+
let resp = client.role_revoke_permission(role1, "abc", None).await?;
51+
println!("{:?}", resp.header());
52+
53+
let resp = client
54+
.role_revoke_permission(
55+
role1,
56+
"456",
57+
Some(RoleRevokePermissionOptions::new().with_range_end("457")),
58+
)
59+
.await?;
60+
println!("{:?}", resp.header());
61+
62+
let resp = client
63+
.role_revoke_permission(
64+
role1,
65+
"b",
66+
Some(RoleRevokePermissionOptions::new().with_prefix()),
67+
)
68+
.await?;
69+
println!("{:?}", resp.header());
70+
71+
let resp = client.role_get(role1).await?;
72+
//show the result
73+
println!("Role {:?}\n{:?}", role1, resp);
74+
75+
let resp = client.role_list().await?;
76+
//show the result
77+
println!("Roles: \n {:?} ", resp.roles());
78+
79+
client.role_delete(role1).await?;
80+
println!("delete role1 successfully",);
81+
client.role_delete(role2).await?;
82+
println!("delete role2 successfully",);
83+
84+
let resp = client.role_list().await?;
85+
//show the result
86+
println!("Roles: \n {:?} ", resp.roles());
87+
88+
Ok(())
89+
}

src/client.rs

+167-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
//! Asynchronous client & synchronous client.
22
33
use crate::error::{Error, Result};
4+
use crate::rpc::auth::Permission;
45
use crate::rpc::auth::{AuthClient, AuthDisableResponse, AuthEnableResponse};
6+
use crate::rpc::auth::{
7+
RoleAddResponse, RoleDeleteResponse, RoleGetResponse, RoleGrantPermissionResponse,
8+
RoleListResponse, RoleRevokePermissionOptions, RoleRevokePermissionResponse,
9+
};
510
use crate::rpc::kv::{
611
CompactionOptions, CompactionResponse, DeleteOptions, DeleteResponse, GetOptions, GetResponse,
712
KvClient, PutOptions, PutResponse, Txn, TxnResponse,
@@ -233,6 +238,51 @@ impl Client {
233238
pub async fn auth_disable(&mut self) -> Result<AuthDisableResponse> {
234239
self.auth.auth_disable().await
235240
}
241+
242+
/// Adds role.
243+
#[inline]
244+
pub async fn role_add(&mut self, name: impl Into<String>) -> Result<RoleAddResponse> {
245+
self.auth.role_add(name).await
246+
}
247+
248+
/// Deletes role.
249+
#[inline]
250+
pub async fn role_delete(&mut self, name: impl Into<String>) -> Result<RoleDeleteResponse> {
251+
self.auth.role_delete(name).await
252+
}
253+
254+
/// Gets role.
255+
#[inline]
256+
pub async fn role_get(&mut self, name: impl Into<String>) -> Result<RoleGetResponse> {
257+
self.auth.role_get(name).await
258+
}
259+
260+
/// Lists role.
261+
#[inline]
262+
pub async fn role_list(&mut self) -> Result<RoleListResponse> {
263+
self.auth.role_list().await
264+
}
265+
266+
/// Grants role permission.
267+
#[inline]
268+
pub async fn role_grant_permission(
269+
&mut self,
270+
name: impl Into<String>,
271+
perm: Permission,
272+
) -> Result<RoleGrantPermissionResponse> {
273+
self.auth.role_grant_permission(name, perm).await
274+
}
275+
276+
/// Revokes role permission.
277+
#[inline]
278+
pub async fn role_revoke_permission(
279+
&mut self,
280+
name: impl Into<String>,
281+
key: impl Into<Vec<u8>>,
282+
options: Option<RoleRevokePermissionOptions>,
283+
) -> Result<RoleRevokePermissionResponse> {
284+
self.auth.role_revoke_permission(name, key, options).await
285+
}
236286
}
237287

238288
/// Options for `Connect` operation.
@@ -260,7 +310,7 @@ impl ConnectOptions {
260310
#[cfg(test)]
261311
mod tests {
262312
use super::*;
263-
use crate::{Compare, CompareOp, EventType, TxnOp, TxnOpResponse};
313+
use crate::{Compare, CompareOp, EventType, PermissionType, TxnOp, TxnOpResponse};
264314

265315
/// Get client for testing.
266316
async fn get_client() -> Result<Client> {
@@ -637,4 +687,120 @@ mod tests {
637687

638688
Ok(())
639689
}
690+
691+
#[tokio::test]
692+
async fn test_role() -> Result<()> {
693+
let mut client = get_client().await?;
694+
695+
let role1 = "role1";
696+
let role2 = "role2";
697+
698+
let _resp = client.role_delete(role1).await;
699+
let _resp = client.role_delete(role2).await;
700+
client.role_add(role1).await?;
701+
702+
let resp = client.role_get(role1).await;
703+
if let Err(_) = resp {
704+
assert!(false);
705+
}
706+
707+
client.role_delete(role1).await?;
708+
let resp = client.role_get(role1).await;
709+
if let Ok(_) = resp {
710+
assert!(false);
711+
}
712+
713+
client.role_add(role2).await?;
714+
let resp = client.role_get(role2).await;
715+
if let Err(_) = resp {
716+
assert!(false);
717+
}
718+
719+
let resp = client.role_list().await;
720+
if let Err(_) = resp {
721+
assert!(false);
722+
}
723+
724+
if let Ok(l) = resp {
725+
assert!(l.roles().contains(&role2.to_string()));
726+
}
727+
728+
client
729+
.role_grant_permission(role2, Permission::read("123"))
730+
.await?;
731+
client
732+
.role_grant_permission(role2, Permission::write("abc").with_from_key())
733+
.await?;
734+
client
735+
.role_grant_permission(role2, Permission::read_write("hi").with_range_end("hjj"))
736+
.await?;
737+
client
738+
.role_grant_permission(
739+
role2,
740+
Permission::new(PermissionType::Write, "pp").with_prefix(),
741+
)
742+
.await?;
743+
client
744+
.role_grant_permission(
745+
role2,
746+
Permission::new(PermissionType::Read, "xyz").with_all_keys(),
747+
)
748+
.await?;
749+
750+
let resp = client.role_get(role2).await;
751+
if let Err(_) = resp {
752+
assert!(false);
753+
}
754+
if let Ok(r) = resp {
755+
let permissions = r.permissions();
756+
assert!(permissions.contains(&Permission::read("123")));
757+
assert!(permissions.contains(&Permission::write("abc").with_from_key()));
758+
assert!(permissions.contains(&Permission::read_write("hi").with_range_end("hjj")));
759+
assert!(permissions.contains(&Permission::write("pp").with_prefix()));
760+
assert!(permissions.contains(&Permission::read("xyz").with_all_keys()));
761+
}
762+
763+
//revoke all permission
764+
client.role_revoke_permission(role2, "123", None).await?;
765+
client
766+
.role_revoke_permission(
767+
role2,
768+
"abc",
769+
Some(RoleRevokePermissionOptions::new().with_from_key()),
770+
)
771+
.await?;
772+
client
773+
.role_revoke_permission(
774+
role2,
775+
"hi",
776+
Some(RoleRevokePermissionOptions::new().with_range_end("hjj")),
777+
)
778+
.await?;
779+
client
780+
.role_revoke_permission(
781+
role2,
782+
"pp",
783+
Some(RoleRevokePermissionOptions::new().with_prefix()),
784+
)
785+
.await?;
786+
client
787+
.role_revoke_permission(
788+
role2,
789+
"xyz",
790+
Some(RoleRevokePermissionOptions::new().with_all_keys()),
791+
)
792+
.await?;
793+
794+
let resp = client.role_get(role2).await;
795+
if let Err(_) = resp {
796+
assert!(false);
797+
}
798+
if let Ok(r) = resp {
799+
assert!(r.permissions().is_empty());
800+
}
801+
802+
client.role_delete(role2).await?;
803+
804+
Ok(())
805+
}
640806
}

src/lib.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ mod rpc;
66

77
pub use crate::client::{Client, ConnectOptions};
88
pub use crate::error::Error;
9+
pub use crate::rpc::auth::{
10+
AuthDisableResponse, AuthEnableResponse, Permission, PermissionType, RoleAddResponse,
11+
RoleDeleteResponse, RoleGetResponse, RoleGrantPermissionResponse, RoleListResponse,
12+
RoleRevokePermissionOptions, RoleRevokePermissionResponse,
13+
};
914
pub use crate::rpc::kv::{
1015
CompactionOptions, CompactionResponse, Compare, CompareOp, DeleteOptions, DeleteResponse,
1116
GetOptions, GetResponse, PutOptions, PutResponse, SortOrder, SortTarget, Txn, TxnOp,
@@ -16,10 +21,8 @@ pub use crate::rpc::lease::{
1621
LeaseKeeper, LeaseLeasesResponse, LeaseRevokeResponse, LeaseStatus, LeaseTimeToLiveOptions,
1722
LeaseTimeToLiveResponse,
1823
};
24+
pub use crate::rpc::lock::{LockClient, LockOptions, LockResponse, UnlockResponse};
1925
pub use crate::rpc::watch::{
2026
Event, EventType, WatchFilterType, WatchOptions, WatchResponse, WatchStream, Watcher,
2127
};
2228
pub use crate::rpc::{KeyValue, ResponseHeader};
23-
24-
pub use crate::rpc::auth::{AuthDisableResponse, AuthEnableResponse};
25-
pub use crate::rpc::lock::{LockClient, LockOptions, LockResponse, UnlockResponse};

0 commit comments

Comments
 (0)