Repository: milvus-io/milvus-sdk-go
Pull request #847 (2024-11-20 09:59:14)

enhance: RBAC grant v2 API
issue: https://github.com/milvus-io/milvus/issues/37031

sre-ci-robot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by: *<a href="https://github.com/milvus-io/milvus-sdk-go/pull/847#" title="Author self-approved">shaoting-huang</a>*
To complete the [pull request process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process), please assign **congqixia** after the PR has been reviewed.
You can assign the PR to them by writing `/assign @congqixia` in a comment when ready.

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=milvus-io%2Fmilvus-sdk-go).

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/milvus-io/milvus-sdk-go/blob/master/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["congqixia"]} -->
weiliu1031: /lgtm
sre-ci-robot: New changes are detected. LGTM label has been removed.
weiliu1031: /lgtm
sre-ci-robot: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/milvus-io/milvus-sdk-go/pull/847#pullrequestreview-2450504086" title="Approved">congqixia</a>*, *<a href="https://github.com/milvus-io/milvus-sdk-go/pull/847#" title="Author self-approved">shaoting-huang</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=milvus-io%2Fmilvus-sdk-go).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/milvus-io/milvus-sdk-go/blob/master/OWNERS)~~ [congqixia]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
congqixia: /lgtm

Patch:
diff --git a/client/client.go b/client/client.go
index 14de87d..23b4ce1 100644
--- a/client/client.go
+++ b/client/client.go
@@ -222,6 +222,10 @@ type Client interface {
 	Grant(ctx context.Context, role string, objectType entity.PriviledgeObjectType, object string, privilege string, options ...entity.OperatePrivilegeOption) error
 	// Revoke removes privilege from role.
 	Revoke(ctx context.Context, role string, objectType entity.PriviledgeObjectType, object string, privilege string, options ...entity.OperatePrivilegeOption) error
+	// GrantV2 adds privilege for role.
+	GrantV2(ctx context.Context, role string, privilege string, dbName string, colName string) error
+	// RevokeV2 removes privilege from role.
+	RevokeV2(ctx context.Context, role string, privilege string, dbName string, colName string) error
 
 	// GetLoadingProgress get the collection or partitions loading progress
 	GetLoadingProgress(ctx context.Context, collectionName string, partitionNames []string) (int64, error)
diff --git a/client/rbac.go b/client/rbac.go
index 1495434..462d701 100644
--- a/client/rbac.go
+++ b/client/rbac.go
@@ -393,6 +393,62 @@ func (c *GrpcClient) Revoke(ctx context.Context, role string, objectType entity.
 	return handleRespStatus(resp)
 }
 
+// GrantV2 adds object privilege for role without object type
+func (c *GrpcClient) GrantV2(ctx context.Context, role string, privilege string, dbName string, colName string) error {
+	if c.Service == nil {
+		return ErrClientNotReady
+	}
+
+	req := &milvuspb.OperatePrivilegeV2Request{
+		Role: &milvuspb.RoleEntity{
+			Name: role,
+		},
+		Grantor: &milvuspb.GrantorEntity{
+			Privilege: &milvuspb.PrivilegeEntity{
+				Name: privilege,
+			},
+		},
+		Type:           milvuspb.OperatePrivilegeType_Grant,
+		DbName:         dbName,
+		CollectionName: colName,
+	}
+
+	resp, err := c.Service.OperatePrivilegeV2(ctx, req)
+	if err != nil {
+		return err
+	}
+
+	return handleRespStatus(resp)
+}
+
+// Revoke removes privilege from role without object type
+func (c *GrpcClient) RevokeV2(ctx context.Context, role string, privilege string, dbName string, colName string) error {
+	if c.Service == nil {
+		return ErrClientNotReady
+	}
+
+	req := &milvuspb.OperatePrivilegeV2Request{
+		Role: &milvuspb.RoleEntity{
+			Name: role,
+		},
+		Grantor: &milvuspb.GrantorEntity{
+			Privilege: &milvuspb.PrivilegeEntity{
+				Name: privilege,
+			},
+		},
+		Type:           milvuspb.OperatePrivilegeType_Revoke,
+		DbName:         dbName,
+		CollectionName: colName,
+	}
+
+	resp, err := c.Service.OperatePrivilegeV2(ctx, req)
+	if err != nil {
+		return err
+	}
+
+	return handleRespStatus(resp)
+}
+
 func (c *GrpcClient) BackupRBAC(ctx context.Context) (*entity.RBACMeta, error) {
 	if c.Service == nil {
 		return nil, ErrClientNotReady
diff --git a/go.mod b/go.mod
index 08b1f53..fc285ec 100644
--- a/go.mod
+++ b/go.mod
@@ -7,7 +7,7 @@ require (
 	github.com/go-faker/faker/v4 v4.1.0
 	github.com/golang/protobuf v1.5.2
 	github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
-	github.com/milvus-io/milvus-proto/go-api/v2 v2.3.4-0.20241108105827-266fb751b620
+	github.com/milvus-io/milvus-proto/go-api/v2 v2.3.4-0.20241120015424-93892e628c69
 	github.com/stretchr/testify v1.8.1
 	github.com/tidwall/gjson v1.14.4
 	github.com/x448/float16 v0.8.4
diff --git a/go.sum b/go.sum
index 019bdd9..63eda4d 100644
--- a/go.sum
+++ b/go.sum
@@ -159,6 +159,8 @@ github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i
 github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc=
 github.com/milvus-io/milvus-proto/go-api/v2 v2.3.4-0.20241108105827-266fb751b620 h1:0IWUDtDloift7cQHalhdjuVkL/3qSeiXFqR7MofZBkg=
 github.com/milvus-io/milvus-proto/go-api/v2 v2.3.4-0.20241108105827-266fb751b620/go.mod h1:/6UT4zZl6awVeXLeE7UGDWZvXj3IWkRsh3mqsn0DiAs=
+github.com/milvus-io/milvus-proto/go-api/v2 v2.3.4-0.20241120015424-93892e628c69 h1:Qt0Bv2Fum3EX3OlkuQYHJINBzeU4oEuHy2lXSfB/gZw=
+github.com/milvus-io/milvus-proto/go-api/v2 v2.3.4-0.20241120015424-93892e628c69/go.mod h1:/6UT4zZl6awVeXLeE7UGDWZvXj3IWkRsh3mqsn0DiAs=
 github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
 github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
 github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
diff --git a/mocks/MilvusServiceServer.go b/mocks/MilvusServiceServer.go
index 6179aa1..0eb74bd 100644
--- a/mocks/MilvusServiceServer.go
+++ b/mocks/MilvusServiceServer.go
@@ -4097,6 +4097,61 @@ func (_c *MilvusServiceServer_OperatePrivilegeGroup_Call) RunAndReturn(run func(
 	return _c
 }
 
+// OperatePrivilegeV2 provides a mock function with given fields: _a0, _a1
+func (_m *MilvusServiceServer) OperatePrivilegeV2(_a0 context.Context, _a1 *milvuspb.OperatePrivilegeV2Request) (*commonpb.Status, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *commonpb.Status
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.OperatePrivilegeV2Request) (*commonpb.Status, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.OperatePrivilegeV2Request) *commonpb.Status); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*commonpb.Status)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *milvuspb.OperatePrivilegeV2Request) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// MilvusServiceServer_OperatePrivilegeV2_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'OperatePrivilegeV2'
+type MilvusServiceServer_OperatePrivilegeV2_Call struct {
+	*mock.Call
+}
+
+// OperatePrivilegeV2 is a helper method to define mock.On call
+//   - _a0 context.Context
+//   - _a1 *milvuspb.OperatePrivilegeV2Request
+func (_e *MilvusServiceServer_Expecter) OperatePrivilegeV2(_a0 interface{}, _a1 interface{}) *MilvusServiceServer_OperatePrivilegeV2_Call {
+	return &MilvusServiceServer_OperatePrivilegeV2_Call{Call: _e.mock.On("OperatePrivilegeV2", _a0, _a1)}
+}
+
+func (_c *MilvusServiceServer_OperatePrivilegeV2_Call) Run(run func(_a0 context.Context, _a1 *milvuspb.OperatePrivilegeV2Request)) *MilvusServiceServer_OperatePrivilegeV2_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run(args[0].(context.Context), args[1].(*milvuspb.OperatePrivilegeV2Request))
+	})
+	return _c
+}
+
+func (_c *MilvusServiceServer_OperatePrivilegeV2_Call) Return(_a0 *commonpb.Status, _a1 error) *MilvusServiceServer_OperatePrivilegeV2_Call {
+	_c.Call.Return(_a0, _a1)
+	return _c
+}
+
+func (_c *MilvusServiceServer_OperatePrivilegeV2_Call) RunAndReturn(run func(context.Context, *milvuspb.OperatePrivilegeV2Request) (*commonpb.Status, error)) *MilvusServiceServer_OperatePrivilegeV2_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
 // OperateUserRole provides a mock function with given fields: _a0, _a1
 func (_m *MilvusServiceServer) OperateUserRole(_a0 context.Context, _a1 *milvuspb.OperateUserRoleRequest) (*commonpb.Status, error) {
 	ret := _m.Called(_a0, _a1)


Test patch:
diff --git a/client/client_mock_test.go b/client/client_mock_test.go
index 6472b46..37f3055 100644
--- a/client/client_mock_test.go
+++ b/client/client_mock_test.go
@@ -257,6 +257,7 @@ const (
 	MGetLoadingProgress      ServiceMethod = 110
 	MGetLoadState            ServiceMethod = 111
 	MAlterCollectionField    ServiceMethod = 112
+	MOperatePrivilegeV2      ServiceMethod = 113
 
 	MCreatePartition   ServiceMethod = 201
 	MDropPartition     ServiceMethod = 202
@@ -501,6 +502,15 @@ func (m *MockServer) AlterCollection(ctx context.Context, req *milvuspb.AlterCol
 	return SuccessStatus()
 }
 
+func (m *MockServer) OperatePrivilegeV2(ctx context.Context, req *milvuspb.OperatePrivilegeV2Request) (*commonpb.Status, error) {
+	f := m.GetInjection(MOperatePrivilegeV2)
+	if f != nil {
+		r, err := f(ctx, req)
+		return r.(*commonpb.Status), err
+	}
+	return SuccessStatus()
+}
+
 func (m *MockServer) CreatePartition(ctx context.Context, req *milvuspb.CreatePartitionRequest) (*commonpb.Status, error) {
 	f := m.GetInjection(MCreatePartition)
 	if f != nil {