Skip to content

Commit

Permalink
feat: #26 - 피드백 반영
Browse files Browse the repository at this point in the history
  • Loading branch information
2522001 authored May 29, 2024
2 parents fd96280 + 6853b1a commit 79a5c1d
Show file tree
Hide file tree
Showing 16 changed files with 81 additions and 31 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package se.issuetrackingsystem.comment.controller;

import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
Expand All @@ -21,7 +22,7 @@ public class CommentController {
private final CommentService commentService;

@PostMapping
public ResponseEntity<List<CommentResponse>> commentCreate(@RequestParam("issueId") Long issueId,@RequestBody CommentRequest commentRequest){
public ResponseEntity<List<CommentResponse>> commentCreate(@RequestParam("issueId") Long issueId, @Valid @RequestBody CommentRequest commentRequest){
commentService.create(issueId,commentRequest.getMessage(),commentRequest.getAuthorId());
List<Comment> comments = commentService.getList(issueId);
List<CommentResponse> responses = new ArrayList<>();
Expand All @@ -37,7 +38,7 @@ public ResponseEntity<Comment> commentDelete(@RequestParam("commentId") Long com
}

@PatchMapping
public ResponseEntity<Comment> commentModify(@RequestParam("commentId") Long commentId, @RequestBody CommentRequest commentRequest){
public ResponseEntity<Comment> commentModify(@RequestParam("commentId") Long commentId, @Valid @RequestBody CommentRequest commentRequest){
return ResponseEntity.ok(commentService.modify(commentId, commentRequest.getMessage()));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
@Getter
@Setter
public class CommentRequest {
@NotBlank

@NotBlank(message = "Message는 공백이 될 수 없습니다.")
private String message;

@NotBlank
private Long authorId;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ public enum ErrorCode {
* 400 BAD_REQUEST: 잘못된 요청
*/
BAD_REQUEST(HttpStatus.BAD_REQUEST, "잘못된 요청입니다."),
ROLE_BAD_REQUEST(HttpStatus.BAD_REQUEST, "역할이 올바르지 않습니다."),
PASSWORD_BAD_REQUEST(HttpStatus.BAD_REQUEST, "비밀번호가 올바르지 않습니다."),

/*
* 403 Forbidden: 승인을 거부함
*/
USERNAME_FORBIDDEN(HttpStatus.FORBIDDEN, "존재하는 회원 이름입니다."),
ROLE_FORBIDDEN(HttpStatus.FORBIDDEN, "역할이 올바르지 않습니다."),
PASSWORD_FORBIDDEN(HttpStatus.FORBIDDEN, "비밀번호가 올바르지 않습니다."),

/*
* 404 NOT_FOUND: 리소스를 찾을 수 없음
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
package se.issuetrackingsystem.common.exception;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.HashMap;
import java.util.Map;

@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
Expand All @@ -21,6 +27,20 @@ protected ResponseEntity<ErrorResponse> handleCustomException(final CustomExcept
.body(new ErrorResponse(e.getErrorCode()));
}

/*
* 유효성 검사 오류 메시지 반환
* */
@ExceptionHandler(MethodArgumentNotValidException.class)
protected ResponseEntity<Map<String, String>> handleValidationExceptions(MethodArgumentNotValidException e) {
Map<String, String> errors = new HashMap<>();
e.getBindingResult().getAllErrors().forEach((error) -> {
String fieldName = ((FieldError) error).getField();
String errorMessage = error.getDefaultMessage();
errors.put(fieldName, errorMessage);
});
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errors);
}

/*
* HTTP 405 Exception
* */
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package se.issuetrackingsystem.issue.controller;


import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
Expand All @@ -24,7 +25,7 @@ public class IssueController {
private final IssueService issueService;

@PostMapping
public ResponseEntity<List<IssueResponse>> issueCreate(@RequestBody IssueRequest issueRequest, @RequestParam("projectId") Long projectId){
public ResponseEntity<List<IssueResponse>> issueCreate(@Valid @RequestBody IssueRequest issueRequest, @RequestParam("projectId") Long projectId){
issueService.create(projectId,issueRequest.getTitle(),issueRequest.getDescription(),issueRequest.getUserid(),issueRequest.getPriority());
List<Issue> issues = issueService.getList(projectId);
List<IssueResponse> responses = new ArrayList<>();
Expand Down Expand Up @@ -57,13 +58,13 @@ public ResponseEntity<IssueResponse> issueDelete(@RequestParam("issueId") Long i
}

@PatchMapping
public ResponseEntity<IssueResponse> issueModify(@RequestBody IssueRequest issueRequest,@RequestParam("issueId") Long issueId){
public ResponseEntity<Issue> issueModify(@Valid @RequestBody IssueRequest issueRequest,@RequestParam("issueId") Long issueId){
Issue issue = issueService.modify(issueId,issueRequest.getTitle(),issueRequest.getDescription(),issueRequest.getPriority(),issueRequest.getUserid());
return ResponseEntity.ok(new IssueResponse(issue));
}

@PostMapping("/assignees")
public ResponseEntity<IssueResponse> issueSetAssignee(@RequestBody IssueRequest issueRequest,@RequestParam("issueId") Long issueId){
public ResponseEntity<Issue> issueSetAssignee(@Valid @RequestBody IssueRequest issueRequest,@RequestParam("issueId") Long issueId){
Issue issue = issueService.setAssignee(issueId,issueRequest.getUserid(),issueRequest.getAssigneeId());
return ResponseEntity.ok(new IssueResponse(issue));
}
Expand All @@ -79,7 +80,7 @@ public ResponseEntity<List<IssueResponse>> issueCheckByStatus(@PathVariable("sta
}

@PatchMapping("/status")
public ResponseEntity<IssueResponse> issueChangeStatus(@RequestBody IssueRequest issueRequest,@RequestParam("issueId") Long issueId){
public ResponseEntity<Issue> issueChangeStatus(@Valid @RequestBody IssueRequest issueRequest,@RequestParam("issueId") Long issueId){
Issue issue = issueService.changeStatus(issueRequest.getUserid(),issueId);
return ResponseEntity.ok(new IssueResponse(issue));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package se.issuetrackingsystem.issue.dto;

import jakarta.validation.constraints.NotBlank;
import lombok.Getter;
import lombok.Setter;
import se.issuetrackingsystem.issue.domain.Issue;

@Getter
@Setter
public class IssueRequest {

@NotBlank(message = "Title은 공백이 될 수 없습니다.")
private String title;

private String description;
Expand All @@ -15,7 +18,7 @@ public class IssueRequest {

private Issue.Status status;

private Long userid;
private Long userId;

private Long assigneeId;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ public Issue setAssignee(Long issueId, Long userId, Long assigneeId){
User user = userRepository.findById(userId).orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND));
User assignee = userRepository.findById(assigneeId).orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND));
if (!user.canSetAssignee()||!assignee.canChangeIssueStateAssignedToFixed()) {
throw new CustomException(ErrorCode.ROLE_FORBIDDEN);
throw new CustomException(ErrorCode.ROLE_BAD_REQUEST);
}
issue.setAssignee(assignee);
issue.setStatus(Issue.Status.ASSIGNED);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package se.issuetrackingsystem.project.controller;

import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
Expand All @@ -17,7 +18,7 @@ public class ProjectController {
private final ProjectService projectService;

@PostMapping
public ResponseEntity<ProjectResponse> createProject(@RequestBody ProjectRequest request) {
public ResponseEntity<ProjectResponse> createProject(@Valid @RequestBody ProjectRequest request) {
return ResponseEntity.ok(projectService.createProject(request));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,10 @@
@RequiredArgsConstructor
public class ProjectRequest {

@NotBlank
@NotBlank(message = "Title은 공백이 될 수 없습니다.")
private final String title;

@NotBlank
private final Long adminId;

private final List<Long> contributorIds;

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package se.issuetrackingsystem.user.controller;

import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
Expand All @@ -18,12 +19,12 @@ public class UserController {
private final UserService userService;

@PostMapping("/register")
public ResponseEntity<UserResponse> register(@RequestBody RegisterRequest request) {
public ResponseEntity<UserResponse> register(@Valid @RequestBody RegisterRequest request) {
return ResponseEntity.ok(userService.register(request));
}

@PostMapping("/login")
public ResponseEntity<UserResponse> login(@RequestBody LoginRequest request) {
public ResponseEntity<UserResponse> login(@Valid @RequestBody LoginRequest request) {
return ResponseEntity.ok(userService.login(request));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
@RequiredArgsConstructor
public class LoginRequest {

@NotBlank
@NotBlank(message = "Username은 공백이 될 수 없습니다.")
private final String username;

@NotBlank
@NotBlank(message = "Password는 공백이 될 수 없습니다.")
private final String password;
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
@RequiredArgsConstructor
public class RegisterRequest {

@NotBlank
@NotBlank(message = "Username은 공백이 될 수 없습니다.")
private final String username;

@NotBlank
@NotBlank(message = "Password는 공백이 될 수 없습니다.")
private final String password;

@NotBlank
@NotBlank(message = "Role은 공백이 될 수 없습니다.")
private final String role;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,8 @@
@Getter
public class UserResponse {

@NotBlank
private final Long userId;

@NotBlank
private final String username;

@NotBlank
private final String role;

public UserResponse(User user) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package se.issuetrackingsystem.user.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import se.issuetrackingsystem.user.domain.User;

Expand All @@ -10,4 +11,7 @@
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByUsername(String username);

@Query("SELECT u FROM users u WHERE TYPE(u) IN (PL, Dev, Tester)")
Optional<List<User>> findContributors();
}
16 changes: 14 additions & 2 deletions src/main/java/se/issuetrackingsystem/user/service/UserService.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public UserResponse login(LoginRequest request) {
.orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND));

if (!passwordEncoder.matches(request.getPassword(), user.getPassword())) {
throw new CustomException(ErrorCode.PASSWORD_FORBIDDEN);
throw new CustomException(ErrorCode.PASSWORD_BAD_REQUEST);
}

return new UserResponse(user);
Expand All @@ -66,6 +66,18 @@ public List<UserResponse> getUsers() {
.toList();
}

@Transactional(readOnly = true)
public List<UserResponse> getContributors() {

List<User> users = userRepository.findContributors()
.orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND));

return users
.stream()
.map(UserResponse::new)
.toList();
}

private boolean isDuplicateUsername(String username) {
Optional<User> user = userRepository.findByUsername(username);
return user.isPresent();
Expand All @@ -77,7 +89,7 @@ private User createUser(String role, String username, String password) {
case "PL" -> new PL(username, password);
case "Dev" -> new Dev(username, password);
case "Tester" -> new Tester(username, password);
default -> throw new CustomException(ErrorCode.ROLE_FORBIDDEN);
default -> throw new CustomException(ErrorCode.ROLE_BAD_REQUEST);
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.springframework.transaction.annotation.Transactional;
import se.issuetrackingsystem.common.exception.CustomException;
import se.issuetrackingsystem.common.exception.ErrorCode;
import se.issuetrackingsystem.user.domain.Admin;
import se.issuetrackingsystem.user.domain.Dev;
import se.issuetrackingsystem.user.domain.Tester;
import se.issuetrackingsystem.user.dto.LoginRequest;
Expand Down Expand Up @@ -99,4 +100,17 @@ void getUsers() {
assertTrue(response.stream().anyMatch(u -> "TestDev".equals(u.getUsername())));
assertTrue(response.stream().anyMatch(u -> "TestTester".equals(u.getUsername())));
}

@Test
void getContributors() {
Admin user1 = new Admin("TestAdmin", passwordEncoder.encode("0000"));
Tester user2 = new Tester("TestTester", passwordEncoder.encode("0000"));
userRepository.save(user1);
userRepository.save(user2);

List<UserResponse> response = userService.getContributors();

assertEquals(1, response.size());
assertTrue(response.stream().anyMatch(u -> "TestTester".equals(u.getUsername())));
}
}

0 comments on commit 79a5c1d

Please sign in to comment.