Skip to content

Commit

Permalink
refactor(client)!: AuthClient::role_grant_permission
Browse files Browse the repository at this point in the history
Signed-off-by: lxl66566 <lxl66566@gmail.com>
  • Loading branch information
lxl66566 committed Aug 15, 2024
1 parent 4bc9bc1 commit 62088fc
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 147 deletions.
14 changes: 3 additions & 11 deletions crates/xline-client/examples/auth_role.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use anyhow::Result;
use xline_client::{
types::auth::{
AuthRoleGrantPermissionRequest, AuthRoleRevokePermissionRequest, Permission, PermissionType,
},
types::auth::{AuthRoleRevokePermissionRequest, PermissionType},
Client, ClientOptions,
};

Expand All @@ -21,16 +19,10 @@ async fn main() -> Result<()> {

// grant permissions to roles
client
.role_grant_permission(AuthRoleGrantPermissionRequest::new(
"role1",
Permission::new(PermissionType::Read, "key1"),
))
.role_grant_permission("role1", PermissionType::Read, "key1", None)
.await?;
client
.role_grant_permission(AuthRoleGrantPermissionRequest::new(
"role2",
Permission::new(PermissionType::Readwrite, "key2"),
))
.role_grant_permission("role2", PermissionType::Readwrite, "key2", None)
.await?;

// list all roles and their permissions
Expand Down
34 changes: 22 additions & 12 deletions crates/xline-client/src/clients/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ use xlineapi::{

use crate::{
error::{Result, XlineClientError},
types::auth::{AuthRoleGrantPermissionRequest, AuthRoleRevokePermissionRequest},
types::{
auth::{AuthRoleRevokePermissionRequest, Permission, PermissionType},
range_end::RangeOption,
},
AuthService, CurpClient,
};

Expand Down Expand Up @@ -660,7 +663,7 @@ impl AuthClient {
///
/// ```no_run
/// use xline_client::{
/// types::auth::{AuthRoleGrantPermissionRequest, Permission, PermissionType},
/// types::auth::{Permission, PermissionType},
/// Client, ClientOptions,
/// };
/// use anyhow::Result;
Expand All @@ -676,10 +679,12 @@ impl AuthClient {
/// // add the role and key
///
/// client
/// .role_grant_permission(AuthRoleGrantPermissionRequest::new(
/// .role_grant_permission(
/// "role",
/// Permission::new(PermissionType::Read, "key"),
/// ))
/// PermissionType::Read,
/// "key",
/// None
/// )
/// .await?;
///
/// Ok(())
Expand All @@ -688,14 +693,19 @@ impl AuthClient {
#[inline]
pub async fn role_grant_permission(
&self,
request: AuthRoleGrantPermissionRequest,
name: impl Into<String>,
perm_type: PermissionType,
perm_key: impl Into<Vec<u8>>,
range_option: Option<RangeOption>,
) -> Result<AuthRoleGrantPermissionResponse> {
if request.inner.perm.is_none() {
return Err(XlineClientError::InvalidArgs(String::from(
"Permission not given",
)));
}
self.handle_req(request.inner, false).await
self.handle_req(
xlineapi::AuthRoleGrantPermissionRequest {
name: name.into(),
perm: Some(Permission::new(perm_type, perm_key.into(), range_option).into()),
},
false,
)
.await
}

/// Revokes role permission.
Expand Down
104 changes: 40 additions & 64 deletions crates/xline-client/src/types/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,35 +8,7 @@ pub use xlineapi::{
AuthenticateResponse, Type as PermissionType,
};

/// Request for `AuthRoleGrantPermission`
#[derive(Debug, PartialEq)]
pub struct AuthRoleGrantPermissionRequest {
/// Inner request
pub(crate) inner: xlineapi::AuthRoleGrantPermissionRequest,
}

impl AuthRoleGrantPermissionRequest {
/// Creates a new `AuthRoleGrantPermissionRequest`
///
/// `role` is the name of the role to grant permission,
/// `perm` is the permission name to grant.
#[inline]
pub fn new(role: impl Into<String>, perm: Permission) -> Self {
Self {
inner: xlineapi::AuthRoleGrantPermissionRequest {
name: role.into(),
perm: Some(perm.into()),
},
}
}
}

impl From<AuthRoleGrantPermissionRequest> for xlineapi::AuthRoleGrantPermissionRequest {
#[inline]
fn from(req: AuthRoleGrantPermissionRequest) -> Self {
req.inner
}
}
use super::range_end::RangeOption;

/// Request for `AuthRoleRevokePermission`
#[derive(Debug, PartialEq)]
Expand Down Expand Up @@ -107,62 +79,66 @@ impl From<AuthRoleRevokePermissionRequest> for xlineapi::AuthRoleRevokePermissio
pub struct Permission {
/// The inner Permission
inner: xlineapi::Permission,
/// The range option
range_option: Option<RangeOption>,
}

impl Permission {
/// Creates a permission with operation type and key
///
/// `perm_type` is the permission type,
/// `key` is the key to grant with the permission.
/// `range_option` is the range option of how to get `range_end` from key.
#[inline]
#[must_use]
pub fn new(perm_type: PermissionType, key: impl Into<Vec<u8>>) -> Self {
Self {
inner: xlineapi::Permission {
perm_type: perm_type.into(),
key: key.into(),
..Default::default()
},
}
pub fn new(
perm_type: PermissionType,
key: impl Into<Vec<u8>>,
range_option: Option<RangeOption>,
) -> Self {
Self::from((perm_type, key.into(), range_option))
}
}

/// If set, Xline will return all keys with the matching prefix
impl From<Permission> for xlineapi::Permission {
#[inline]
#[must_use]
pub fn with_prefix(mut self) -> Self {
if self.inner.key.is_empty() {
self.inner.key = vec![0];
self.inner.range_end = vec![0];
} else {
self.inner.range_end = KeyRange::get_prefix(&self.inner.key);
}
self
fn from(mut perm: Permission) -> Self {
perm.inner.range_end = perm
.range_option
.unwrap_or_default()
.get_range_end(&mut perm.inner.key);
perm.inner
}
}

/// If set, Xline will return all keys that are equal or greater than the given key
impl PartialEq for Permission {
#[inline]
#[must_use]
pub fn with_from_key(mut self) -> Self {
if self.inner.key.is_empty() {
self.inner.key = vec![0];
}
self.inner.range_end = vec![0];
self
fn eq(&self, other: &Self) -> bool {
self.inner == other.inner && self.range_option == other.range_option
}
}

/// `range_end` is the upper bound on the requested range \[key,` range_en`d).
/// If `range_end` is '\0', the range is all keys >= key.
impl Eq for Permission {}

impl From<(PermissionType, Vec<u8>, Option<RangeOption>)> for Permission {
#[inline]
#[must_use]
pub fn with_range_end(mut self, range_end: impl Into<Vec<u8>>) -> Self {
self.inner.range_end = range_end.into();
self
fn from(
(perm_type, key, range_option): (PermissionType, Vec<u8>, Option<RangeOption>),
) -> Self {
Permission {
inner: xlineapi::Permission {
perm_type: perm_type.into(),
key,
..Default::default()
},
range_option,
}
}
}

impl From<Permission> for xlineapi::Permission {
impl From<(PermissionType, &str, Option<RangeOption>)> for Permission {
#[inline]
fn from(perm: Permission) -> Self {
perm.inner
fn from(value: (PermissionType, &str, Option<RangeOption>)) -> Self {
Self::from((value.0, value.1.as_bytes().to_vec(), value.2))
}
}
56 changes: 29 additions & 27 deletions crates/xline-client/tests/it/auth.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
//! The following tests are originally from `etcd-client`
use xline_client::{
error::Result,
types::auth::{
AuthRoleGrantPermissionRequest, AuthRoleRevokePermissionRequest, Permission, PermissionType,
types::{
auth::{AuthRoleRevokePermissionRequest, Permission, PermissionType},
range_end::RangeOption,
},
};

Expand Down Expand Up @@ -42,38 +43,39 @@ async fn permission_operations_should_success_in_normal_path() -> Result<()> {
let client = client.auth_client();

let role1 = "role1";
let perm1 = Permission::new(PermissionType::Read, "123");
let perm2 = Permission::new(PermissionType::Write, "abc").with_from_key();
let perm3 = Permission::new(PermissionType::Readwrite, "hi").with_range_end("hjj");
let perm4 = Permission::new(PermissionType::Write, "pp").with_prefix();
let perm5 = Permission::new(PermissionType::Read, vec![0]).with_from_key();
let perm1 = (PermissionType::Read, "123", None);
let perm2 = (PermissionType::Write, "abc", Some(RangeOption::FromKey));
let perm3 = (
PermissionType::Readwrite,
"hi",
Some(RangeOption::RangeEnd("hjj".into())),
);
let perm4 = (PermissionType::Write, "pp", Some(RangeOption::Prefix));
let perm5 = (PermissionType::Read, vec![0], Some(RangeOption::FromKey));

client.role_add(role1).await?;

client
.role_grant_permission(AuthRoleGrantPermissionRequest::new(role1, perm1.clone()))
.await?;
client
.role_grant_permission(AuthRoleGrantPermissionRequest::new(role1, perm2.clone()))
.await?;
client
.role_grant_permission(AuthRoleGrantPermissionRequest::new(role1, perm3.clone()))
.await?;
client
.role_grant_permission(AuthRoleGrantPermissionRequest::new(role1, perm4.clone()))
.await?;
client
.role_grant_permission(AuthRoleGrantPermissionRequest::new(role1, perm5.clone()))
.await?;
let (p1, p2, p3) = perm1.clone();
client.role_grant_permission(role1, p1, p2, p3).await?;
let (p1, p2, p3) = perm2.clone();
client.role_grant_permission(role1, p1, p2, p3).await?;
let (p1, p2, p3) = perm3.clone();
client.role_grant_permission(role1, p1, p2, p3).await?;
let (p1, p2, p3) = perm4.clone();
client.role_grant_permission(role1, p1, p2, p3).await?;
let (p1, p2, p3) = perm5.clone();
client.role_grant_permission(role1, p1, p2, p3).await?;

{
// get permissions for role1, and validate the result
let resp = client.role_get(role1).await?;
let permissions = resp.perm;
assert!(permissions.contains(&perm1.into()));
assert!(permissions.contains(&perm2.into()));
assert!(permissions.contains(&perm3.into()));
assert!(permissions.contains(&perm4.into()));
assert!(permissions.contains(&perm5.into()));

assert!(permissions.contains(&Permission::from(perm1).into()));
assert!(permissions.contains(&Permission::from(perm2).into()));
assert!(permissions.contains(&Permission::from(perm3).into()));
assert!(permissions.contains(&Permission::from(perm4).into()));
assert!(permissions.contains(&Permission::from(perm5).into()));
}

// revoke all permission
Expand Down
10 changes: 6 additions & 4 deletions crates/xline-test-utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use utils::config::{
LogConfig, MetricsConfig, StorageConfig, TlsConfig, TraceConfig, XlineServerConfig,
};
use xline::server::XlineServer;
use xline_client::types::auth::{AuthRoleGrantPermissionRequest, Permission, PermissionType};
use xline_client::types::{auth::PermissionType, range_end::RangeOption};
pub use xline_client::{clients, types, Client, ClientOptions};

/// Cluster
Expand Down Expand Up @@ -350,10 +350,12 @@ pub async fn set_user(
client.user_grant_role(name, role).await?;
if !key.is_empty() {
client
.role_grant_permission(AuthRoleGrantPermissionRequest::new(
.role_grant_permission(
role,
Permission::new(PermissionType::Readwrite, key).with_range_end(range_end),
))
PermissionType::Readwrite,
key,
Some(RangeOption::RangeEnd(range_end.to_vec())),
)
.await?;
}
Ok(())
Expand Down
Loading

0 comments on commit 62088fc

Please sign in to comment.