From e0bfcbc71826eea43810e7eb5b5222561b014730 Mon Sep 17 00:00:00 2001 From: star <15031259256@163.com> Date: Thu, 2 Nov 2023 10:01:41 +0800 Subject: [PATCH] feat(controller): add overview for project (#2923) --- client/starwhale/base/client/models/models.py | 1 + .../mlops/api/ProjectController.java | 12 ++++++++++ .../project/UpdateProjectRequest.java | 3 +++ .../mlops/domain/project/ProjectService.java | 8 ++++++- .../domain/project/mapper/ProjectMapper.java | 12 +++++++--- .../domain/project/po/ProjectEntity.java | 2 ++ .../V0_4_0_028__add_readme_for_project.sql | 18 +++++++++++++++ .../mlops/api/ProjectControllerTest.java | 6 ++--- .../domain/project/ProjectServiceTest.java | 12 +++++----- .../project/mapper/ProjectMapperTest.java | 22 +++++++++++++++++-- 10 files changed, 81 insertions(+), 15 deletions(-) create mode 100644 server/controller/src/main/resources/db/migration/v0_4_0/V0_4_0_028__add_readme_for_project.sql diff --git a/client/starwhale/base/client/models/models.py b/client/starwhale/base/client/models/models.py index 4d78b15b33..550823e1d4 100644 --- a/client/starwhale/base/client/models/models.py +++ b/client/starwhale/base/client/models/models.py @@ -36,6 +36,7 @@ class UpdateProjectRequest(SwBaseModel): ) privacy: Optional[str] = None description: Optional[str] = None + readme: Optional[str] = None class ResponseMessageObject(SwBaseModel): diff --git a/server/controller/src/main/java/ai/starwhale/mlops/api/ProjectController.java b/server/controller/src/main/java/ai/starwhale/mlops/api/ProjectController.java index 334e6ffbdf..539770b3c5 100644 --- a/server/controller/src/main/java/ai/starwhale/mlops/api/ProjectController.java +++ b/server/controller/src/main/java/ai/starwhale/mlops/api/ProjectController.java @@ -166,6 +166,17 @@ ResponseEntity> getProjectByUrl( return ResponseEntity.ok(Code.success.asResponse(vo)); } + @Operation(summary = "Get a project readme by Url", description = "Returns readme content.") + @GetMapping(value = "/project/{projectUrl}/readme", produces = MediaType.APPLICATION_JSON_VALUE) + @PreAuthorize("hasAnyRole('OWNER', 'MAINTAINER', 'GUEST')") + ResponseEntity> getProjectReadmeByUrl( + @PathVariable String projectUrl + ) { + var readme = projectService.getReadme(projectUrl); + return ResponseEntity.ok(Code.success.asResponse(readme)); + } + + @Operation(summary = "Modify project information") @PutMapping(value = "/project/{projectUrl}", produces = MediaType.APPLICATION_JSON_VALUE) @PreAuthorize("hasAnyRole('OWNER', 'MAINTAINER')") @@ -177,6 +188,7 @@ ResponseEntity> updateProject( projectUrl, updateProjectRequest.getProjectName(), updateProjectRequest.getDescription(), + updateProjectRequest.getReadme(), updateProjectRequest.getPrivacy() ); if (!res) { diff --git a/server/controller/src/main/java/ai/starwhale/mlops/api/protocol/project/UpdateProjectRequest.java b/server/controller/src/main/java/ai/starwhale/mlops/api/protocol/project/UpdateProjectRequest.java index 87fc003174..603a397e89 100644 --- a/server/controller/src/main/java/ai/starwhale/mlops/api/protocol/project/UpdateProjectRequest.java +++ b/server/controller/src/main/java/ai/starwhale/mlops/api/protocol/project/UpdateProjectRequest.java @@ -36,4 +36,7 @@ public class UpdateProjectRequest { @JsonProperty("description") private String description; + + @JsonProperty("readme") + private String readme; } diff --git a/server/controller/src/main/java/ai/starwhale/mlops/domain/project/ProjectService.java b/server/controller/src/main/java/ai/starwhale/mlops/domain/project/ProjectService.java index 31a9d6a0eb..2775e8b5de 100644 --- a/server/controller/src/main/java/ai/starwhale/mlops/domain/project/ProjectService.java +++ b/server/controller/src/main/java/ai/starwhale/mlops/domain/project/ProjectService.java @@ -156,6 +156,10 @@ public ProjectVo getProjectVo(String projectUrl) { return ProjectVo.fromBo(findProject(projectUrl), idConvertor); } + public String getReadme(String projectUrl) { + return projectMapper.getReadme(projectDao.getProjectId(projectUrl)); + } + public PageInfo listProject(String projectName, OrderParams orderParams, User user) { boolean showAll = false; List sysRoles = userService.getProjectRolesOfUser(user, Project.system()); @@ -326,7 +330,8 @@ public Long recoverProject(String projectUrl) { } @Transactional - public Boolean updateProject(String projectUrl, String projectName, String description, String privacy) { + public Boolean updateProject( + String projectUrl, String projectName, String description, String readme, String privacy) { ProjectEntity project = projectDao.getProject(projectUrl); Long projectId = project.getId(); if (StrUtil.isNotEmpty(projectName)) { @@ -352,6 +357,7 @@ public Boolean updateProject(String projectUrl, String projectName, String descr .id(projectId) .projectName(projectName) .projectDescription(description) + .readme(readme) .privacy(privacyEnum.getValue()) .build(); int res = projectMapper.update(entity); diff --git a/server/controller/src/main/java/ai/starwhale/mlops/domain/project/mapper/ProjectMapper.java b/server/controller/src/main/java/ai/starwhale/mlops/domain/project/mapper/ProjectMapper.java index 4ae09cf99c..efdd0e0c76 100644 --- a/server/controller/src/main/java/ai/starwhale/mlops/domain/project/mapper/ProjectMapper.java +++ b/server/controller/src/main/java/ai/starwhale/mlops/domain/project/mapper/ProjectMapper.java @@ -38,8 +38,8 @@ public interface ProjectMapper { String COLUMNS = "id,project_name,owner_id,privacy,project_description," + "is_default,is_deleted,created_time,modified_time"; - @Insert("insert into project_info(project_name, owner_id, privacy, project_description, is_default)" - + " values (#{projectName}, #{ownerId}, #{privacy}, #{projectDescription}, #{isDefault})") + @Insert("insert into project_info(project_name, owner_id, privacy, project_description, readme, is_default)" + + " values (#{projectName}, #{ownerId}, #{privacy}, #{projectDescription}, #{readme}, #{isDefault})") @Options(useGeneratedKeys = true, keyColumn = "id", keyProperty = "id") int insert(@NotNull ProjectEntity project); @@ -59,6 +59,9 @@ public interface ProjectMapper { + " where id = #{id}") ProjectEntity find(@Param("id") Long id); + @Select("select readme from project_info where id = #{id}") + String getReadme(@Param("id") Long id); + @Select("select " + COLUMNS + " from project_info" + " where project_name = #{projectName}" + " and is_deleted = 0") @@ -127,9 +130,12 @@ public String updateSql(ProjectEntity project) { if (StrUtil.isNotEmpty(project.getProjectName())) { SET("project_name = #{projectName}"); } - if (StrUtil.isNotEmpty(project.getProjectDescription())) { + if (Objects.nonNull(project.getProjectDescription())) { SET("project_description = #{projectDescription}"); } + if (Objects.nonNull(project.getReadme())) { + SET("readme = #{readme}"); + } if (Objects.nonNull(project.getOwnerId())) { SET("owner_id = #{ownerId}"); } diff --git a/server/controller/src/main/java/ai/starwhale/mlops/domain/project/po/ProjectEntity.java b/server/controller/src/main/java/ai/starwhale/mlops/domain/project/po/ProjectEntity.java index 1c8ed3ab30..0b71016441 100644 --- a/server/controller/src/main/java/ai/starwhale/mlops/domain/project/po/ProjectEntity.java +++ b/server/controller/src/main/java/ai/starwhale/mlops/domain/project/po/ProjectEntity.java @@ -40,6 +40,8 @@ public class ProjectEntity extends BaseEntity { private String projectDescription; + private String readme; + private Integer isDeleted; private Integer isDefault; diff --git a/server/controller/src/main/resources/db/migration/v0_4_0/V0_4_0_028__add_readme_for_project.sql b/server/controller/src/main/resources/db/migration/v0_4_0/V0_4_0_028__add_readme_for_project.sql new file mode 100644 index 0000000000..87a31e5263 --- /dev/null +++ b/server/controller/src/main/resources/db/migration/v0_4_0/V0_4_0_028__add_readme_for_project.sql @@ -0,0 +1,18 @@ +/* + * Copyright 2022 Starwhale, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +ALTER TABLE project_info ADD readme LONGTEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL; diff --git a/server/controller/src/test/java/ai/starwhale/mlops/api/ProjectControllerTest.java b/server/controller/src/test/java/ai/starwhale/mlops/api/ProjectControllerTest.java index 11692c298f..eb76cebc51 100644 --- a/server/controller/src/test/java/ai/starwhale/mlops/api/ProjectControllerTest.java +++ b/server/controller/src/test/java/ai/starwhale/mlops/api/ProjectControllerTest.java @@ -201,13 +201,13 @@ public void testGetProject() { @Test public void testUpdateProject() { - given(projectService.updateProject(anyString(), any(), any(), any())) + given(projectService.updateProject(anyString(), any(), any(), any(), any())) .willReturn(true); String errUrl = "err_url"; - given(projectService.updateProject(same(errUrl), any(), any(), any())) + given(projectService.updateProject(same(errUrl), any(), any(), any(), any())) .willReturn(false); String errName = "err_name"; - given(projectService.updateProject(anyString(), same(errName), any(), any())) + given(projectService.updateProject(anyString(), same(errName), any(), any(), any())) .willThrow(StarwhaleApiException.class); UpdateProjectRequest request = new UpdateProjectRequest(); diff --git a/server/controller/src/test/java/ai/starwhale/mlops/domain/project/ProjectServiceTest.java b/server/controller/src/test/java/ai/starwhale/mlops/domain/project/ProjectServiceTest.java index 4c4e8d47bd..937792a31f 100644 --- a/server/controller/src/test/java/ai/starwhale/mlops/domain/project/ProjectServiceTest.java +++ b/server/controller/src/test/java/ai/starwhale/mlops/domain/project/ProjectServiceTest.java @@ -264,23 +264,23 @@ public void testModifyProject() { .willReturn(1); given(projectMapper.findByNameForUpdateAndOwner(same("p2"), any())) .willReturn(ProjectEntity.builder().id(2L).projectName("p2").build()); - var res = service.updateProject("1", "pro1", null, "PUBLIC"); + var res = service.updateProject("1", "pro1", null, null, "PUBLIC"); assertThat(res, is(true)); - res = service.updateProject("p1", "pro1", null, "PUBLIC"); + res = service.updateProject("p1", "pro1", null, null, "PUBLIC"); assertThat(res, is(true)); - res = service.updateProject("2", "pro1", null, "PUBLIC"); + res = service.updateProject("2", "pro1", null, null, "PUBLIC"); assertThat(res, is(false)); - res = service.updateProject("1", "pro1", null, "PUBLIC"); + res = service.updateProject("1", "pro1", null, null, "PUBLIC"); assertThat(res, is(true)); - res = service.updateProject("2", "p2", null, "PUBLIC"); + res = service.updateProject("2", "p2", null, null, "PUBLIC"); assertThat(res, is(false)); assertThrows(StarwhaleApiException.class, - () -> service.updateProject("1", "p2", "", "PUBLIC")); + () -> service.updateProject("1", "p2", "", "", "PUBLIC")); } @Test diff --git a/server/controller/src/test/java/ai/starwhale/mlops/domain/project/mapper/ProjectMapperTest.java b/server/controller/src/test/java/ai/starwhale/mlops/domain/project/mapper/ProjectMapperTest.java index 9a848152b6..075c311f11 100644 --- a/server/controller/src/test/java/ai/starwhale/mlops/domain/project/mapper/ProjectMapperTest.java +++ b/server/controller/src/test/java/ai/starwhale/mlops/domain/project/mapper/ProjectMapperTest.java @@ -72,7 +72,12 @@ public class ProjectMapperTest extends MySqlContainerHolder { public void setUp() { user = UserEntity.builder().userEnabled(0).userName("un12").userPwdSalt("x").userPwd("up").build(); userMapper.insert(user); - project = ProjectEntity.builder().projectName("pjn").ownerId(user.getId()).privacy(1).isDefault(1) + project = ProjectEntity.builder() + .projectName("pjn") + .readme("readme") + .ownerId(user.getId()) + .privacy(1) + .isDefault(1) .build(); projectMapper.insert(project); project2 = ProjectEntity.builder().projectName("pxn2").ownerId(user.getId()).privacy(0).isDefault(0) @@ -128,12 +133,25 @@ public void testFindProjectByName() { @Test public void testModifyProject() { - ProjectEntity project3 = ProjectEntity.builder().projectName("pxn3").ownerId(user.getId()).privacy(0) + ProjectEntity project3 = ProjectEntity.builder() + .projectName("pxn3") + .ownerId(user.getId()) + .privacy(0) + .readme(null) .isDefault(0) .build(); project3.setId(project.getId()); projectMapper.update(project3); + validProject(project3, user, projectMapper.find(project.getId())); + Assertions.assertEquals("readme", projectMapper.getReadme(project.getId())); + + project3 = ProjectEntity.builder() + .id(project.getId()) + .readme("readme-new") // new readme content + .build(); + projectMapper.update(project3); + Assertions.assertEquals("readme-new", projectMapper.getReadme(project.getId())); } @Test