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

[Feature-14505][UI] Support to set project-level preferences #14573

Merged
merged 17 commits into from
Jul 19, 2023
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/

package org.apache.dolphinscheduler.api.controller;

import static org.apache.dolphinscheduler.api.enums.Status.QUERY_PROJECT_PREFERENCE_ERROR;
import static org.apache.dolphinscheduler.api.enums.Status.UPDATE_PROJECT_PREFERENCE_ERROR;

import org.apache.dolphinscheduler.api.aspect.AccessLogAnnotation;
import org.apache.dolphinscheduler.api.exceptions.ApiException;
import org.apache.dolphinscheduler.api.service.ProjectPreferenceService;
import org.apache.dolphinscheduler.api.utils.Result;
import org.apache.dolphinscheduler.common.constants.Constants;
import org.apache.dolphinscheduler.dao.entity.User;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;

@Tag(name = "PROJECT_PREFERENCE_TAG")
@RestController
@RequestMapping("projects/{projectCode}/project-preference")
@Slf4j
public class ProjectPreferenceController extends BaseController {

@Autowired
private ProjectPreferenceService projectPreferenceService;

@Operation(summary = "updateProjectPreference", description = "UPDATE_PROJECT_PREFERENCE_NOTES")
@Parameters({
@Parameter(name = "projectPreferences", description = "PROJECT_PREFERENCES", schema = @Schema(implementation = String.class)),
})
@PutMapping
@ResponseStatus(HttpStatus.CREATED)
@ApiException(UPDATE_PROJECT_PREFERENCE_ERROR)
@AccessLogAnnotation(ignoreRequestArgs = "loginUser")
public Result updateProjectPreference(@Parameter(hidden = true) @RequestAttribute(value = Constants.SESSION_USER) User loginUser,
@Parameter(name = "projectCode", description = "PROJECT_CODE", required = true) @PathVariable long projectCode,
@RequestParam(value = "projectPreferences", required = true) String projectPreferences) {
return projectPreferenceService.updateProjectPreference(loginUser, projectCode, projectPreferences);
}

@Operation(summary = "queryProjectPreferenceByProjectCode", description = "QUERY_PROJECT_PREFERENCE_NOTES")
@GetMapping()
@ResponseStatus(HttpStatus.OK)
@ApiException(QUERY_PROJECT_PREFERENCE_ERROR)
@AccessLogAnnotation(ignoreRequestArgs = "loginUser")
public Result queryProjectPreferenceByProjectCode(@Parameter(hidden = true) @RequestAttribute(value = Constants.SESSION_USER) User loginUser,
@Parameter(name = "projectCode", description = "PROJECT_CODE", required = true) @PathVariable long projectCode) {
return projectPreferenceService.queryProjectPreferenceByProjectCode(loginUser, projectCode);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,11 @@ public enum Status {

PROJECT_PARAMETER_CODE_EMPTY(10220, "project parameter code empty", "项目参数code为空"),

CREATE_PROJECT_PREFERENCE_ERROR(10300, "create project preference error", "创建项目偏好设置错误"),

UPDATE_PROJECT_PREFERENCE_ERROR(10301, "update project preference error", "更新项目偏好设置错误"),
QUERY_PROJECT_PREFERENCE_ERROR(10302, "query project preference error", "查询项目偏好设置错误"),

UDF_FUNCTION_NOT_EXIST(20001, "UDF function not found", "UDF函数不存在"),
UDF_FUNCTION_EXISTS(20002, "UDF function already exists", "UDF函数已存在"),
RESOURCE_NOT_EXIST(20004, "resource not exist", "资源不存在"),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/

package org.apache.dolphinscheduler.api.service;

import org.apache.dolphinscheduler.api.utils.Result;
import org.apache.dolphinscheduler.dao.entity.User;

public interface ProjectPreferenceService {

Result updateProjectPreference(User loginUser, long projectCode, String preferences);

Result queryProjectPreferenceByProjectCode(User loginUser, long projectCode);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/

package org.apache.dolphinscheduler.api.service.impl;

import static org.apache.dolphinscheduler.api.constants.ApiFuncIdentificationConstant.PROJECT;

import org.apache.dolphinscheduler.api.enums.Status;
import org.apache.dolphinscheduler.api.service.ProjectPreferenceService;
import org.apache.dolphinscheduler.api.service.ProjectService;
import org.apache.dolphinscheduler.api.utils.Result;
import org.apache.dolphinscheduler.common.utils.CodeGenerateUtils;
import org.apache.dolphinscheduler.dao.entity.Project;
import org.apache.dolphinscheduler.dao.entity.ProjectPreference;
import org.apache.dolphinscheduler.dao.entity.User;
import org.apache.dolphinscheduler.dao.mapper.ProjectMapper;
import org.apache.dolphinscheduler.dao.mapper.ProjectPreferenceMapper;

import java.util.Date;
import java.util.Objects;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

@Service
@Slf4j
public class ProjectPreferenceServiceImpl extends BaseServiceImpl
implements
ProjectPreferenceService {

@Autowired
private ProjectPreferenceMapper projectPreferenceMapper;

@Autowired
private ProjectService projectService;

@Autowired
private ProjectMapper projectMapper;

@Override
public Result updateProjectPreference(User loginUser, long projectCode, String preferences) {
Result result = new Result();

// check if the user has the writing permission for project
Project project = projectMapper.queryByCode(projectCode);
boolean hasProjectAndWritePerm = projectService.hasProjectAndWritePerm(loginUser, project, result);
if (!hasProjectAndWritePerm) {
return result;
}

ProjectPreference projectPreference = projectPreferenceMapper
.selectOne(new QueryWrapper<ProjectPreference>().lambda().eq(ProjectPreference::getProjectCode,
projectCode));

Date now = new Date();
if (Objects.isNull(projectPreference)) {
projectPreference = new ProjectPreference();
projectPreference.setProjectCode(projectCode);
projectPreference.setPreferences(preferences);
projectPreference.setUserId(loginUser.getId());
projectPreference.setCode(CodeGenerateUtils.getInstance().genCode());
projectPreference.setCreateTime(now);
projectPreference.setUpdateTime(now);
if (projectPreferenceMapper.insert(projectPreference) > 0) {
log.info("Project preference is created and id is :{}", projectPreference.getId());
result.setData(projectPreference);
putMsg(result, Status.SUCCESS);
} else {
log.error("Project preference create error, projectCode:{}.", projectPreference.getProjectCode());
putMsg(result, Status.CREATE_PROJECT_PREFERENCE_ERROR);
}
} else {
projectPreference.setPreferences(preferences);
projectPreference.setUserId(loginUser.getId());
projectPreference.setUpdateTime(now);

if (projectPreferenceMapper.updateById(projectPreference) > 0) {
log.info("Project preference is updated and id is :{}", projectPreference.getId());
result.setData(projectPreference);
putMsg(result, Status.SUCCESS);
} else {
log.error("Project preference update error, projectCode:{}.", projectPreference.getProjectCode());
putMsg(result, Status.UPDATE_PROJECT_PREFERENCE_ERROR);
}
}
return result;
}

@Override
public Result queryProjectPreferenceByProjectCode(User loginUser, long projectCode) {
Result result = new Result();

Project project = projectMapper.queryByCode(projectCode);
boolean hasProjectAndPerm = projectService.hasProjectAndPerm(loginUser, project, result, PROJECT);
if (!hasProjectAndPerm) {
return result;
}

ProjectPreference projectPreference = projectPreferenceMapper
.selectOne(new QueryWrapper<ProjectPreference>().lambda().eq(ProjectPreference::getProjectCode,
projectCode));

result.setData(projectPreference);

putMsg(result, Status.SUCCESS);
return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -447,4 +447,9 @@ UPDATE_PROJECT_PARAMETER_NOTES=update project parameter
PROJECT_PARAMETER_CODE=project parameter code
DELETE_PROJECT_PARAMETER_NOTES=delete project parameter
QUERY_PROJECT_PARAMETER_LIST_PAGING_NOTES=query project parameter list paging
QUERY_PROJECT_PARAMETER_NOTES=query project parameter
QUERY_PROJECT_PARAMETER_NOTES=query project parameter

PROJECT_PREFERENCE_TAG=project preference related operation
UPDATE_PROJECT_PREFERENCE_NOTES=update project preference
PROJECT_PREFERENCES=project preferences
QUERY_PROJECT_PREFERENCE_NOTES=query project preference
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/

package org.apache.dolphinscheduler.api.controller;

import org.apache.dolphinscheduler.api.enums.Status;
import org.apache.dolphinscheduler.api.service.impl.ProjectPreferenceServiceImpl;
import org.apache.dolphinscheduler.api.utils.Result;
import org.apache.dolphinscheduler.common.enums.UserType;
import org.apache.dolphinscheduler.dao.entity.User;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;

@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
public class ProjectPreferenceControllerTest {

@InjectMocks
private ProjectPreferenceController projectPreferenceController;

@Mock
private ProjectPreferenceServiceImpl projectPreferenceService;

@Test
public void testUpdateProjectPreference() {
User loginUser = getGeneralUser();

Mockito.when(projectPreferenceService.updateProjectPreference(Mockito.any(), Mockito.anyLong(),
Mockito.anyString())).thenReturn(getSuccessResult());

Result result = projectPreferenceController.updateProjectPreference(loginUser, 1, "value");
Assertions.assertEquals(Status.SUCCESS.getCode(), result.getCode());
}

@Test
public void testQueryProjectPreferenceByProjectCode() {
User loginUser = getGeneralUser();

Mockito.when(projectPreferenceService.queryProjectPreferenceByProjectCode(Mockito.any(), Mockito.anyLong()))
.thenReturn(getSuccessResult());
Result result = projectPreferenceController.queryProjectPreferenceByProjectCode(loginUser, 1);
Assertions.assertEquals(Status.SUCCESS.getCode(), result.getCode());
}

private User getGeneralUser() {
User loginUser = new User();
loginUser.setUserType(UserType.GENERAL_USER);
loginUser.setUserName("userName");
loginUser.setId(1);
return loginUser;
}

private Result getSuccessResult() {
Result result = new Result();
result.setCode(Status.SUCCESS.getCode());
result.setMsg(Status.SUCCESS.getMsg());
return result;
}

}
Loading