OWL ITS + 탐지시스템(인터넷 진흥원)
이민희
2022-01-13 ebfd37816a332308519b30af5bfb017c5052be69
Merge branch 'master' of http://192.168.0.25:9001/r/owl-kisa
12개 파일 변경됨
110 ■■■■ 파일 변경됨
src/main/java/kr/wisestone/owl/config/SecurityConfiguration.java 1 ●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/constant/MsgConstants.java 8 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/repository/WorkflowTransitionRepository.java 3 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/service/impl/IssueServiceImpl.java 6 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/service/impl/WorkflowTransitionServiceImpl.java 2 ●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/web/controller/Api/ApiController.java 42 ●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/web/form/ApiIssueAddForm.java 10 ●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/web/resolver/OwlResponseEntityExceptionHandler.java 10 ●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/resources/META-INF/orm.xml 20 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/i18n/ko/global.json 2 ●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/views/api/apiSettingSpec.html 4 ●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/views/common/header.html 2 ●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/config/SecurityConfiguration.java
@@ -145,6 +145,7 @@
                .antMatchers("/language/change").permitAll()
                .antMatchers("/security/*").permitAll()
                .antMatchers("/api/issue").permitAll()
                .antMatchers("/api/issue/*").permitAll()
                .antMatchers("/**/*").authenticated();
//        http.addFilter(new CustomAuthenticationFilter());
src/main/java/kr/wisestone/owl/constant/MsgConstants.java
@@ -297,6 +297,10 @@
     */
    public static final String API_ISSUE_STATUS_NOT_EXIST = "API_ISSUE_STATUS_NOT_EXIST";
    /**
     * 워크플로우에 해당 이슈 상태를 찾을수 없습니다
     */
    public static final String API_ISSUE_STATUS_NOT_EXIST_IN_WORKFLOW = "API_ISSUE_STATUS_NOT_EXIST_IN_WORKFLOW";
    /**
     * 이슈 상태 값이 없습니다.
     */
    public static final String API_ISSUE_STATUS_IS_NULL = "API_ISSUE_STATUS_IS_NULL";
@@ -308,4 +312,8 @@
     * 이슈 상태가 워크플로우에 포함되어 있지 않습니다
     */
    public static final String API_ISSUE_STATUS_NOT_IN_WORKFLOW = "API_ISSUE_STATUS_NOT_IN_WORKFLOW";
    /**
     * api 이슈 생성 완료
     */
    public static final String API_ADD_ISSUE_OK = "API_ADD_ISSUE_OK";
}
src/main/java/kr/wisestone/owl/repository/WorkflowTransitionRepository.java
@@ -12,4 +12,7 @@
    @Query(name="WorkflowTransition.findBySourceIssueStatusIdAndWorkflowId")
    List<WorkflowTransitionVo> findBySourceIssueStatusIdAndWorkflowId(@Param("sourceIssueStatusId") Long sourceIssueStatusId, @Param("workflowId") Long workflowId);
    @Query(name="WorkflowTransition.findBySourceIssueStatusIdAndTargetIssueStatusIdAndWorkflowId")
    List<WorkflowTransitionVo> findBySourceIssueStatusIdAndTargetIssueStatusIdAndWorkflowId(@Param("sourceIssueStatusId") Long sourceIssueStatusId, @Param("workflowId") Long workflowId);
}
src/main/java/kr/wisestone/owl/service/impl/IssueServiceImpl.java
@@ -212,6 +212,9 @@
    @Autowired
    private IssueRelationMapper issueRelationMapper;
    @Autowired
    private WorkflowTransitionService workflowTransitionService;
    @Override
    protected JpaRepository<Issue, Long> getRepository() {
        return this.issueRepository;
@@ -262,6 +265,9 @@
            }
        } else if (issueApiForm.getIssueStatusId() == null){
            throw new ApiParameterException(this.messageAccessor.getMessage(MsgConstants.API_ISSUE_STATUS_NOT_EXIST));
        } else if (!this.workflowTransitionService.contains(issueApiForm.getIssueStatusId(), workflow.getId())) {
            //이슈 상태 유효성 확인
            throw new ApiParameterException(this.messageAccessor.getMessage(MsgConstants.API_ISSUE_STATUS_NOT_EXIST_IN_WORKFLOW));
        }
        // 프로젝트 입력
src/main/java/kr/wisestone/owl/service/impl/WorkflowTransitionServiceImpl.java
@@ -134,7 +134,7 @@
    // 워크플로우에 사용되는 이슈 상태인지 확인한다
    @Override
    public boolean contains(Long issueStatusId, Long workflowId) {
        List<WorkflowTransitionVo> workflowTransitionVos = this.findBySourceIssueStatusIdAndWorkflowId(issueStatusId, workflowId);
        List<WorkflowTransitionVo> workflowTransitionVos = workflowTransitionRepository.findBySourceIssueStatusIdAndTargetIssueStatusIdAndWorkflowId(issueStatusId, workflowId);
        return workflowTransitionVos != null && workflowTransitionVos.size() > 0;
    }
src/main/java/kr/wisestone/owl/web/controller/Api/ApiController.java
@@ -1,7 +1,9 @@
package kr.wisestone.owl.web.controller.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import kr.wisestone.owl.constant.Constants;
import kr.wisestone.owl.constant.MsgConstants;
import kr.wisestone.owl.domain.Issue;
import kr.wisestone.owl.exception.ApiParameterException;
@@ -46,11 +48,21 @@
     */
    @PostMapping(value = "/issue")
    @ApiOperation(value = "이슈 추가", notes = "새로운 이슈를 추가한다.")
    @ApiImplicitParam(name = "files", dataType = "file")
    @ApiImplicitParams(
            {
                    @ApiImplicitParam(name = "files", dataType = "file"),
                    @ApiImplicitParam(name = "token", paramType = "form"),
                    @ApiImplicitParam(name = "title", paramType = "form"),
                    @ApiImplicitParam(name = "description", paramType = "form"),
                    @ApiImplicitParam(name = "issueTypeId", paramType = "form"),
                    @ApiImplicitParam(name = "customFields", paramType = "form")
            }
    )
    @ResponseStatus(HttpStatus.CREATED)
    public
    @ResponseBody
    void addIssue(ApiIssueAddForm apiIssueAddForm, @RequestParam("files") List<MultipartFile> files)
    Map<String, Object> addIssue(ApiIssueAddForm apiIssueAddForm, @RequestParam("files") List<MultipartFile> files)
            throws OwlRuntimeException, CloneNotSupportedException {
        Map<String, Object> resJsonData = new HashMap<>();
@@ -66,9 +78,16 @@
        List<Issue> issues = this.issueService.addApiIssue(issueApiForm);
        //  버전 생성
        StringBuilder sb = new StringBuilder();
        for (Issue issue : issues) {
            this.issueService.addIssueVersion(issue.getId(), issue.getRegisterId());
            if (sb.length() > 0)
                sb.append(",");
            sb.append(issue.getProject().getProjectKey()).append("-").append(issue.getIssueNumber());
        }
        resJsonData.put(Constants.RES_KEY_MSG_SUCCESS, sb.toString());
        return resJsonData;
    }
    /**
@@ -78,23 +97,32 @@
     * @throws OwlRuntimeException 파라미터 오류시 발생
     * @throws CloneNotSupportedException 이슈 복사 시에 발생
     */
    @PutMapping(value = "/issue")
    @PostMapping(value = "/issue/status")
    @ApiOperation(value = "이슈 상태 수정", notes = "사용자 정의 필드가 동일한 기존 이슈를 변경한다.")
    @ResponseStatus(HttpStatus.OK)
    public
    @ResponseBody
    void modifyIssue(ApiIssueModifyForm apiIssueModifyForm) throws OwlRuntimeException, CloneNotSupportedException {
    Map<String, Object> modifyIssue(ApiIssueModifyForm apiIssueModifyForm) throws OwlRuntimeException, CloneNotSupportedException {
        Map<String, Object> resJsonData = new HashMap<>();
        IssueApiForm issueApiForm = ConvertUtil.copyProperties(apiIssueModifyForm, IssueApiForm.class);
        issueApiForm.parseCustomFields(apiIssueModifyForm.getCustomFields());
        issueApiForm.setApiType(IssueApiForm.ApiType.add);
        issueApiForm.setApiType(IssueApiForm.ApiType.modify);
        // 사용자 정의 필드가 없을 경우 검색을 할 수 없기 때문에 예외처리
        if (issueApiForm.getCustomFieldValues() == null || issueApiForm.getCustomFieldValues().size() == 0) {
            throw new OwlRuntimeException(this.messageAccessor.getMessage(MsgConstants.API_CUSTOM_FIELD_NOT_EXIST));
        }
        this.issueService.modifyIssue(issueApiForm, new ArrayList<>());
        List<Issue> issues = this.issueService.modifyIssue(issueApiForm, new ArrayList<>());
        if (issues != null && issues.size() > 0) {
            StringBuilder sb = new StringBuilder();
            for (Issue issue : issues) {
                if (sb.length() > 0)
                    sb.append(",");
                sb.append(issue.getProject().getProjectKey()).append("-").append(issue.getIssueNumber());
            }
            resJsonData.put(Constants.RES_KEY_MSG_SUCCESS, sb.toString());
        }
        return resJsonData;
    }
}
src/main/java/kr/wisestone/owl/web/form/ApiIssueAddForm.java
@@ -7,15 +7,15 @@
 * API 이슈 추가용 Form class
 */
public class ApiIssueAddForm {
    @ApiParam(value = "사용자 토큰", required = true)
    @ApiParam(value = "사용자 토큰", required = true, type = "form")
    private String token;
    @ApiParam(value = "이슈 제목")
    @ApiParam(value = "이슈 제목", type = "form")
    private String title;
    @ApiParam(value = "이슈 내용")
    @ApiParam(value = "이슈 내용", type = "form")
    private String description;
    @ApiParam(value = "이슈 타입 ID", required = true)
    @ApiParam(value = "이슈 타입 ID", required = true, type = "form")
    private Long issueTypeId;
    @ApiParam(value = "사용자 정의 필드", required = true)
    @ApiParam(value = "사용자 정의 필드", required = true, type = "form")
    private String customFields;
    public ApiIssueAddForm() {
src/main/java/kr/wisestone/owl/web/resolver/OwlResponseEntityExceptionHandler.java
@@ -57,7 +57,7 @@
        Map<String, Object> resJsonData = new HashMap<String, Object>();
        resJsonData.put(Constants.RES_KEY_MESSAGE, this.messageAccessor.getResMessage(ex, Constants.RES_KEY_MSG_FAIL));
        return this.handleExceptionInternal(ex, resJsonData, new HttpHeaders(), HttpStatus.OK, request);
        return this.handleExceptionInternal(ex, resJsonData, new HttpHeaders(), HttpStatus.BAD_REQUEST, request);
    }
    @ExceptionHandler({ StackOverflowError.class,
@@ -66,7 +66,7 @@
        Map<String, Object> resJsonData = new HashMap<String, Object>();
        resJsonData.put(Constants.RES_KEY_MESSAGE, this.messageAccessor.getResMessage(MsgConstants.NOT_READABLE_JSON_DATA, Constants.RES_KEY_MSG_FAIL));
        return this.handleExceptionInternal(ex, resJsonData, new HttpHeaders(), HttpStatus.OK, request);
        return this.handleExceptionInternal(ex, resJsonData, new HttpHeaders(), HttpStatus.REQUEST_TIMEOUT, request);
    }
    @ExceptionHandler({ Exception.class })
@@ -74,7 +74,7 @@
        Map<String, Object> resJsonData = new HashMap<String, Object>();
        resJsonData.put(Constants.RES_KEY_MESSAGE, this.messageAccessor.getResMessage(MsgConstants.NOT_READABLE_JSON_DATA, Constants.RES_KEY_MSG_FAIL));
        return this.handleExceptionInternal(ex, resJsonData, new HttpHeaders(), HttpStatus.OK, request);
        return this.handleExceptionInternal(ex, resJsonData, new HttpHeaders(), HttpStatus.BAD_REQUEST, request);
    }
    @Override
@@ -85,7 +85,7 @@
        resJsonData.put(Constants.RES_KEY_MESSAGE,
                this.messageAccessor.getResMessage(MsgConstants.NOT_READABLE_JSON_DATA, Constants.RES_KEY_MSG_FAIL));
        return this.handleExceptionInternal(ex, resJsonData, headers, HttpStatus.OK, request);
        return this.handleExceptionInternal(ex, resJsonData, headers, HttpStatus.BAD_REQUEST, request);
    }
    @Override
@@ -93,7 +93,7 @@
            final MethodArgumentNotValidException ex, final HttpHeaders headers,
            final HttpStatus status, final WebRequest request) {
        final String bodyOfResponse = "This should be application specific4";
        return this.handleExceptionInternal(ex, bodyOfResponse, headers, HttpStatus.OK, request);
        return this.handleExceptionInternal(ex, bodyOfResponse, headers, HttpStatus.BAD_REQUEST, request);
    }
    @Override
src/main/resources/META-INF/orm.xml
@@ -183,6 +183,26 @@
        </query>
    </named-query>
    <named-query name="WorkflowTransition.findBySourceIssueStatusIdAndTargetIssueStatusIdAndWorkflowId">
        <query>
            SELECT new kr.wisestone.owl.vo.WorkflowTransitionVo(
            wt.id
            , sis.id
            , sis.name
            , tis.id
            , tis.name
            , wt.correctX
            , wt.correctY
            , wt.direct
            )
            FROM WorkflowTransition wt
            INNER JOIN wt.workflow w
            INNER JOIN wt.sourceIssueStatus sis
            INNER JOIN wt.targetIssueStatus tis
            WHERE (sis.id = ?1 OR tis.id = ?1) AND w.id = ?2
        </query>
    </named-query>
</entity-mappings>
src/main/webapp/i18n/ko/global.json
@@ -953,7 +953,7 @@
        "successToApiIssueOverlap" : "중복값 설정 완료",
        "failedToApiIssueOverlap" : "중복값 설정 실패",
        "failedToApiMonitor": "API 기록 조회 실패",
        "requestSample": "API 요청 샘플",
        "requestSample": "사용자 정의 필드 JSON 샘플",
        "requestSampleAdd": "이슈 추가",
        "requestSampleModify": "이슈 상태 수정",
        "downIssueOverlapSetting" : "하위 이슈 처리 기준 항목",
src/main/webapp/views/api/apiSettingSpec.html
@@ -46,6 +46,7 @@
    </form>
</div>
<!--
<div class="row">
    <div class="col-md-4">
        <label for="issue-detectingInfo" class="issue-label">
@@ -85,4 +86,5 @@
            </div>
        </div>
    </div>
</div>
</div>
-->
src/main/webapp/views/common/header.html
@@ -35,7 +35,7 @@
                       owl-auto-focus
                       ng-model="vm.searchAll.keyWord"
                       placeholder="{{'issue.pleaseEnterIssueKeyWord' | translate}}"
                       ng-enter="fn.searchAll(0)">
                       ng-enter="fn.searchAll(0)">ㅐ
                <div class="input-group-prepend ml-10">
                    <button class="btn btn-navy" ng-click="fn.searchAll(0)"> <span translate="common.search">검색</span></button>
                </div>