Browse Source

add user service api

Signed-off-by: nameczz <zizhao.chen@zilliz.com>
nameczz 3 years ago
parent
commit
3515d45b1c

+ 1 - 1
server/src/__tests__/__mocks__/consts.ts

@@ -7,7 +7,7 @@ export const insightCacheForTest = new LRUCache({
 });
 
 // mock data
-export const mockAddress = '127.0.0.1';
+export const mockAddress = '127.0.0.1:19530';
 export const mockCollectionNames = [{ name: 'c1' }, { name: 'c2' }];
 export const mockCollections = [
   {

+ 17 - 4
server/src/__tests__/__mocks__/milvus/milvusClient.ts

@@ -25,6 +25,7 @@ import {
   ShowPartitionsReq,
 } from '@zilliz/milvus2-sdk-node/dist/milvus/types';
 import { DeleteEntitiesReq } from '@zilliz/milvus2-sdk-node/dist/milvus/types/Data';
+import { CreateUserReq } from '@zilliz/milvus2-sdk-node/dist/milvus/types/User';
 import { QueryDto } from '../../../collections/dto';
 import {
   CodeEnum,
@@ -89,8 +90,7 @@ const mockMilvusClient = jest.fn().mockImplementation((address: string) => {
             status: mockStatusInfo(CodeEnum.error, ERR_NO_COLLECTION),
           };
         }
-        const res =
-          mockCollections.find((c) => c.name === collection_name) || {};
+        const res = mockCollections.find(c => c.name === collection_name) || {};
         return {
           status: mockStatusInfo(CodeEnum.success),
           ...res,
@@ -229,8 +229,7 @@ const mockMilvusClient = jest.fn().mockImplementation((address: string) => {
           return { status: mockStatusInfo(CodeEnum.error, ERR_NO_COLLECTION) };
         }
         const data =
-          mockIndexState.find((i) => i.collection_name === collection_name) ||
-          {};
+          mockIndexState.find(i => i.collection_name === collection_name) || {};
         return {
           status: mockStatusInfo(CodeEnum.success),
           ...data,
@@ -347,6 +346,20 @@ const mockMilvusClient = jest.fn().mockImplementation((address: string) => {
         };
       },
     },
+    userManager: {
+      listUsers: () => {
+        return { ...mockStatusInfo(CodeEnum.success), usernames: ['root'] };
+      },
+      createUser: () => {
+        return { ...mockStatusInfo(CodeEnum.success) };
+      },
+      deleteUser: () => {
+        return { ...mockStatusInfo(CodeEnum.success) };
+      },
+      updateUser: () => {
+        return { ...mockStatusInfo(CodeEnum.success) };
+      },
+    },
   };
 });
 

+ 65 - 0
server/src/__tests__/users/users.service.test.ts

@@ -0,0 +1,65 @@
+import mockMilvusClient from '../__mocks__/milvus/milvusClient';
+import { MilvusService } from '../../milvus/milvus.service';
+import { CodeEnum, ERR_NO_COLLECTION } from '../utils/constants';
+import { PartitionsService } from '../../partitions/partitions.service';
+import { insightCacheForTest, mockAddress } from '../__mocks__/consts';
+import { MilvusClient } from '@zilliz/milvus2-sdk-node/dist/milvus';
+import { UserService } from '../../users/users.service';
+
+// mock Milvus client
+jest.mock('@zilliz/milvus2-sdk-node', () => {
+  return {
+    MilvusClient: mockMilvusClient,
+  };
+});
+
+describe('Test partitions service', () => {
+  let milvusService: any;
+  let service: UserService;
+
+  beforeAll(async () => {
+    // setup Milvus service and connect to mock Milvus client
+    milvusService = new MilvusService();
+    MilvusService.activeAddress = mockAddress;
+    MilvusService.activeMilvusClient = new MilvusClient(mockAddress);
+
+    await milvusService.connectMilvus(
+      { address: mockAddress },
+      insightCacheForTest
+    );
+    service = new UserService(milvusService);
+  });
+
+  afterAll(() => {
+    milvusService = null;
+    service = null;
+  });
+
+  test('test user manager after connected to Milvus', () => {
+    expect(service.userManager).toBeDefined();
+  });
+
+  test('test getUsers method', async () => {
+    const res = await service.getUsers();
+    expect(res.usernames.length).toEqual(1);
+  });
+
+  test('test create user method', async () => {
+    const res = await service.createUser({ username: '1', password: '2' });
+    expect(res.error_code).toEqual(CodeEnum.success);
+  });
+
+  test('test delete user method', async () => {
+    const res = await service.deleteUser({ username: '1' });
+    expect(res.error_code).toEqual(CodeEnum.success);
+  });
+
+  test('test update user method', async () => {
+    const res = await service.updateUser({
+      username: '1',
+      oldPassword: '1',
+      newPassword: '2',
+    });
+    expect(res.error_code).toEqual(CodeEnum.success);
+  });
+});

+ 3 - 0
server/src/app.ts

@@ -8,6 +8,8 @@ import { router as collectionsRouter } from './collections';
 import { router as partitionsRouter } from './partitions';
 import { router as schemaRouter } from './schema';
 import { router as cronsRouter } from './crons';
+import { router as userRouter } from './users';
+
 import { pubSub } from './events';
 import {
   TransformResMiddlerware,
@@ -115,6 +117,7 @@ getDirectories(SRC_PLUGIN_DIR, async (dirErr: Error, dirRes: string[]) => {
   router.use('/partitions', partitionsRouter);
   router.use('/schema', schemaRouter);
   router.use('/crons', cronsRouter);
+  router.use('/users', userRouter);
 
   router.get('/healthy', (req, res, next) => {
     res.json({ status: 200 });

+ 5 - 0
server/src/milvus/milvus.service.ts

@@ -35,6 +35,11 @@ export class MilvusService {
     return MilvusService.activeMilvusClient.dataManager;
   }
 
+  get userManager() {
+    this.checkMilvus();
+    return MilvusService.activeMilvusClient.userManager;
+  }
+
   static formatAddress(address: string) {
     return address.replace(/(http|https):\/\//, '');
   }

+ 25 - 0
server/src/users/dto.ts

@@ -0,0 +1,25 @@
+import { IsString } from 'class-validator';
+
+export class CreateUserDto {
+  @IsString()
+  readonly username: string;
+
+  @IsString()
+  readonly password: string;
+}
+
+export class UpdateUserDto {
+  @IsString()
+  readonly username: string;
+
+  @IsString()
+  readonly oldPassword: string;
+
+  @IsString()
+  readonly newPassword: string;
+}
+
+export class DeleteUserDto {
+  @IsString()
+  readonly username: string;
+}

+ 6 - 0
server/src/users/index.ts

@@ -0,0 +1,6 @@
+import { UserController } from './users.controller';
+
+const userManager = new UserController();
+const router = userManager.generateRoutes();
+
+export { router };

+ 83 - 0
server/src/users/users.controller.ts

@@ -0,0 +1,83 @@
+import { NextFunction, Request, Response, Router } from 'express';
+import { dtoValidationMiddleware } from '../middlewares/validation';
+import { UserService } from './users.service';
+import { milvusService } from '../milvus';
+
+import { CreateUserDto, UpdateUserDto, DeleteUserDto } from './dto';
+
+export class UserController {
+  private router: Router;
+  private userService: UserService;
+
+  constructor() {
+    this.userService = new UserService(milvusService);
+    this.router = Router();
+  }
+
+  generateRoutes() {
+    this.router.get('/', this.getUsers.bind(this));
+
+    this.router.post(
+      '/',
+      dtoValidationMiddleware(CreateUserDto),
+      this.createUsers.bind(this)
+    );
+
+    this.router.put(
+      '/',
+      dtoValidationMiddleware(UpdateUserDto),
+      this.updateUsers.bind(this)
+    );
+
+    this.router.delete(
+      '/',
+      dtoValidationMiddleware(DeleteUserDto),
+      this.deleteUsers.bind(this)
+    );
+
+    return this.router;
+  }
+
+  async getUsers(req: Request, res: Response, next: NextFunction) {
+    try {
+      const result = await this.userService.getUsers();
+      res.send(result);
+    } catch (error) {
+      next(error);
+    }
+  }
+
+  async createUsers(req: Request, res: Response, next: NextFunction) {
+    const { username, password } = req.body;
+    try {
+      const result = this.userService.createUser({ username, password });
+      res.send(result);
+    } catch (error) {
+      next(error);
+    }
+  }
+
+  async updateUsers(req: Request, res: Response, next: NextFunction) {
+    const { username, oldPassword, newPassword } = req.body;
+    try {
+      const result = this.userService.updateUser({
+        username,
+        oldPassword,
+        newPassword,
+      });
+      res.send(result);
+    } catch (error) {
+      next(error);
+    }
+  }
+
+  async deleteUsers(req: Request, res: Response, next: NextFunction) {
+    const { username } = req.body;
+    try {
+      const result = this.userService.deleteUser({ username });
+      res.send(result);
+    } catch (error) {
+      next(error);
+    }
+  }
+}

+ 34 - 0
server/src/users/users.service.ts

@@ -0,0 +1,34 @@
+import { MilvusService } from '../milvus/milvus.service';
+import {
+  CreateUserReq,
+  UpdateUserReq,
+  DeleteUserReq,
+} from '@zilliz/milvus2-sdk-node/dist/milvus/types/User';
+
+export class UserService {
+  constructor(private milvusService: MilvusService) {}
+
+  get userManager() {
+    return this.milvusService.userManager;
+  }
+
+  async getUsers() {
+    const result = await this.userManager.listUsers();
+    return result;
+  }
+
+  async createUser(data: CreateUserReq) {
+    const result = await this.userManager.createUser(data);
+    return result;
+  }
+
+  async updateUser(data: UpdateUserReq) {
+    const result = await this.userManager.updateUser(data);
+    return result;
+  }
+
+  async deleteUser(data: DeleteUserReq) {
+    const result = await this.userManager.deleteUser(data);
+    return result;
+  }
+}