Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add createPrivilegeGroup/dropPrivilegeGroup/listPrivilegeGroups/addPrivilegesToGroup/removePrivilegesFromGroup #394

Merged
merged 3 commits into from
Dec 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions milvus/const/milvus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -443,3 +443,8 @@ export enum RANKER_TYPE {
RRF = 'rrf',
WEIGHTED = 'weighted',
}

export enum OperatePrivilegeGroupType {
AddPrivilegesToGroup = 0,
RemovePrivilegesFromGroup = 1,
}
198 changes: 198 additions & 0 deletions milvus/grpc/User.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,20 @@ import {
ListGrantsReq,
HasRoleReq,
listRoleReq,
CreatePrivilegeGroupReq,
DropPrivilegeGroupReq,
OperatePrivilegeGroupReq,
AddPrivilegesToGroupReq,
RemovePrivilegesFromGroupReq,
OperatePrivilegeGroupType,
GrpcTimeOut,
ListCredUsersResponse,
ResStatus,
SelectRoleResponse,
SelectUserResponse,
SelectGrantResponse,
HasRoleResponse,
ListPrivilegeGroupsResponse,
promisify,
stringToBase64,
} from '../';
Expand Down Expand Up @@ -680,4 +687,195 @@ export class User extends Resource {
hasRole: result.results.map(r => r.role.name).includes(data.roleName),
};
}

/**
* Create a new privilege group in Milvus.
* @param {CreatePrivilegeGroupReq} data - The privilege group data.
* @param {string} data.group_name - The name of the new privilege group.
* @param {number} [data.timeout] - An optional duration of time in milliseconds to allow for the RPC. If it is set to undefined, the client keeps waiting until the server responds or error occurs. Default is undefined.
*
* @returns {Promise<ResStatus>} The response status.
*
* @example
* ```javascript
* milvusClient.createPrivilegeGroup({
* group_name: 'exampleGroup',
* });
* ```
*/
async createPrivilegeGroup(
data: CreatePrivilegeGroupReq
): Promise<ResStatus> {
const promise = await promisify(
this.channelPool,
'CreatePrivilegeGroup',
data,
data.timeout || this.timeout
);

return promise;
}

/**
* Drop a privilege group in Milvus.
* @param {DropPrivilegeGroupReq} data - The privilege group data.
* @param {string} data.group_name - The name of the privilege group to be dropped.
* @param {number} [data.timeout] - An optional duration of time in milliseconds to allow for the RPC. If it is set to undefined, the client keeps waiting until the server responds or error occurs. Default is undefined.
*
* @returns {Promise<ResStatus>} The response status.
*
* @example
* ```javascript
* await milvusClient.dropPrivilegeGroup({
* group_name: 'exampleGroup',
* });
* ```
*/
async dropPrivilegeGroup(data: DropPrivilegeGroupReq): Promise<ResStatus> {
const promise = await promisify(
this.channelPool,
'DropPrivilegeGroup',
data,
data.timeout || this.timeout
);

return promise;
}

/**
* List all privilege groups in Milvus.
* @param {GrpcTimeOut} data - The data object.
* @param {number} [data.timeout] - An optional duration of time in milliseconds to allow for the RPC. If it is set to undefined, the client keeps waiting until the server responds or error occurs. Default is undefined.
*
* @returns {Promise<ListPrivilegeGroupsResponse>} The response object.
* @returns {ResStatus} response.status - The response status.
* @returns {number} response.status.error_code - The error code number.
* @returns {string} response.status.reason - The cause of the error, if any.
* @returns {PrivelegeGroup[]} response.privilege_groups - An array of privilege groups.
* @returns {string} response.privilege_groups.group_name - The name of the privilege group.
* @returns {PrivilegeEntity[]} response.privilege_groups.privileges - An array of privileges.
* @returns {string} response.privilege_groups.privileges.name - The name of the privilege.
*
* @example
* ```javascript
* await milvusClient.listPrivilegeGroups();
* ```
*/
async listPrivilegeGroups(
data?: GrpcTimeOut
): Promise<ListPrivilegeGroupsResponse> {
const promise = await promisify(
this.channelPool,
'ListPrivilegeGroups',
{},
data?.timeout || this.timeout
);

return promise;
}

/**
* Operate a privilege group in Milvus.
* @param {OperatePrivilegeGroupReq} data - The privilege group data.
* @param {string} data.group_name - The name of the privilege group to be operated.
* @param {PrivilegeEntity[]} data.privileges - The privileges to be operated.
* @param {OperatePrivilegeGroupType} data.type - The operation type.
* @param {number} [data.timeout] - An optional duration of time in milliseconds to allow for the RPC. If it is set to undefined, the client keeps waiting until the server responds or error occurs. Default is undefined.
* @returns {Promise<any>} The response object.
*
* @example
* ```javascript
* await milvusClient.operatePrivilegeGroup({
* group_name: 'exampleGroup',
* privileges: [{name: 'CreateCollection'}],
* type: OperatePrivilegeGroupType.AddPrivilegesToGroup,
* });
* ```
*/
async operatePrivilegeGroup(
data: OperatePrivilegeGroupReq
): Promise<ResStatus> {
const promise = await promisify(
this.channelPool,
'OperatePrivilegeGroup',
data,
data.timeout || this.timeout
);

return promise;
}

/**
* add privileges to a privilege group in Milvus.
* @param {AddPrivilegesToGroupReq} data - The privilege group data.
* @param {string} data.group_name - The name of the privilege group to be operated.
* @param {string[]} data.privileges - The privileges to be added to the group.
*
* @returns {Promise<ResStatus>} The response object.
* @returns {ResStatus} response.status - The response status.
* @returns {number} response.status.error_code - The error code number.
* @returns {string} response.status.reason - The cause of the error, if any.
*
* @example
* ```javascript
* await milvusClient.addPrivilegesToGroup({
* group_name: 'exampleGroup',
* privileges: ['CreateCollection', 'DropCollection'],
* });
*
* ```
*/
async addPrivilegesToGroup(
data: AddPrivilegesToGroupReq
): Promise<ResStatus> {
const promise = await promisify(
this.channelPool,
'OperatePrivilegeGroup',
{
group_name: data.group_name,
privileges: data.privileges.map(p => ({ name: p })),
type: OperatePrivilegeGroupType.AddPrivilegesToGroup,
},
data.timeout || this.timeout
);

return promise;
}

/**
* remove privileges from a privilege group in Milvus.
* @param {RemovePrivilegesFromGroupReq} data - The privilege group data.
* @param {string} data.group_name - The name of the privilege group to be operated.
* @param {string[]} data.privileges - The privileges to be removed from the group.
*
* @returns {Promise<ResStatus>} The response object.
* @returns {ResStatus} response.status - The response status.
* @returns {number} response.status.error_code - The error code number.
* @returns {string} response.status.reason - The cause of the error, if any.
*
* @example
* ```javascript
* await milvusClient.removePrivilegesFromGroup({
* group_name: 'exampleGroup',
* privileges: ['CreateCollection', 'DropCollection'],
* });
*
* ```
*/
async removePrivilegesFromGroup(
data: RemovePrivilegesFromGroupReq
): Promise<ResStatus> {
const promise = await promisify(
this.channelPool,
'OperatePrivilegeGroup',
{
group_name: data.group_name,
privileges: data.privileges.map(p => ({ name: p })),
type: OperatePrivilegeGroupType.RemovePrivilegesFromGroup,
},
data.timeout || this.timeout
);

return promise;
}
}
3 changes: 2 additions & 1 deletion milvus/types/Common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ export interface GrpcTimeOut {
export type PrivilegesTypes =
| CollectionPrivileges
| UserPrivileges
| GlobalPrivileges;
| GlobalPrivileges
| string;

export interface ResStatus {
error_code: string | number;
Expand Down
35 changes: 34 additions & 1 deletion milvus/types/User.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { GrpcTimeOut, PrivilegesTypes, resStatusResponse } from './Common';
import { RbacObjects } from '../';
import { RbacObjects, OperatePrivilegeGroupType } from '../';

// base
export interface usernameReq extends GrpcTimeOut {
Expand Down Expand Up @@ -84,3 +84,36 @@ export interface SelectGrantResponse extends resStatusResponse {
export interface HasRoleResponse extends resStatusResponse {
hasRole: boolean;
}

export interface CreatePrivilegeGroupReq extends GrpcTimeOut {
group_name: string; // required, name
}

export interface DropPrivilegeGroupReq extends GrpcTimeOut {
group_name: string; // required, name
}

export type PrivelegeGroup = {
group_name: string; // name
privileges: PrivilegeEntity[]; // privileges
};

export interface ListPrivilegeGroupsResponse extends resStatusResponse {
privilege_groups: PrivelegeGroup[]; // privilege groups
}

export interface OperatePrivilegeGroupReq extends GrpcTimeOut {
group_name: string; // required, group name
privileges: PrivilegeEntity[]; // required, privileges
type: OperatePrivilegeGroupType; // required, operation type
}

export interface AddPrivilegesToGroupReq extends GrpcTimeOut {
group_name: string; // required, group name
privileges: PrivilegesTypes[]; // required, privileges
}

export interface RemovePrivilegesFromGroupReq extends GrpcTimeOut {
group_name: string; // required, group name
privileges: PrivilegesTypes[]; // required, privileges
}
55 changes: 53 additions & 2 deletions test/grpc/User.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import exp from 'constants';
import {
MilvusClient,
ERROR_REASONS,
Expand All @@ -6,17 +7,19 @@ import {
Roles,
Privileges,
RbacObjects,
OperatePrivilegeGroupType,
} from '../../milvus';
import { timeoutTest } from '../tools';
import { IP, genCollectionParams, GENERATE_NAME } from '../tools';

const milvusClient = new MilvusClient({ address: IP });
const milvusClient = new MilvusClient({ address: IP, logLevel: 'info' });
let authClient: MilvusClient;
const USERNAME = 'username';
const PASSWORD = '123456';
const NEW_PASSWORD = '1234567';
const ROLE_NAME = GENERATE_NAME('role');
const COLLECTION_NAME = GENERATE_NAME();
const PRIVILEGE_GRP_NAME = GENERATE_NAME('privilege');

describe(`User Api`, () => {
beforeAll(async () => {
Expand Down Expand Up @@ -274,9 +277,57 @@ describe(`User Api`, () => {
}
});

// last test
// last test for user
it(`Auth client delete user expect success`, async () => {
const res = await authClient.deleteUser({ username: USERNAME });
expect(res.error_code).toEqual(ErrorCode.SUCCESS);
});

it(`create a privilege group`, async () => {
const res = await authClient.createPrivilegeGroup({
group_name: PRIVILEGE_GRP_NAME,
});
expect(res.error_code).toEqual(ErrorCode.SUCCESS);
});

it(`add privileges to a privilege group`, async () => {
const res = await authClient.addPrivilegesToGroup({
group_name: PRIVILEGE_GRP_NAME,
privileges: [Privileges.Query],
});

expect(res.error_code).toEqual(ErrorCode.SUCCESS);

const res2 = await authClient.operatePrivilegeGroup({
group_name: PRIVILEGE_GRP_NAME,
privileges: [{ name: Privileges.Search }],
type: OperatePrivilegeGroupType.AddPrivilegesToGroup,
});
expect(res2.error_code).toEqual(ErrorCode.SUCCESS);
});

it(`remove privileges from a privilege group`, async () => {
const res = await authClient.removePrivilegesFromGroup({
group_name: PRIVILEGE_GRP_NAME,
privileges: [Privileges.Query],
});
expect(res.error_code).toEqual(ErrorCode.SUCCESS);
});

it(`list privilege groups`, async () => {
const res = await authClient.listPrivilegeGroups();
expect(res.privilege_groups.length).toBeGreaterThan(0);
const grp = res.privilege_groups.find(
g => g.group_name === PRIVILEGE_GRP_NAME
)!;
expect(grp.group_name).toEqual(PRIVILEGE_GRP_NAME);
expect(grp.privileges.map(p => p.name)).toContain(Privileges.Search);
});

it(`drop a privilege group`, async () => {
const res = await authClient.dropPrivilegeGroup({
group_name: PRIVILEGE_GRP_NAME,
});
expect(res.error_code).toEqual(ErrorCode.SUCCESS);
});
});
Loading