-
Notifications
You must be signed in to change notification settings - Fork 4
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
531 refactor dnd module api url edit and enhancement #535
Changes from 5 commits
a1e8dc6
76263ce
9ab612c
173effa
71082c4
d6197bf
013dce8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package peer.backend.controller.dnd; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.*; | ||
import peer.backend.dto.dnd.RequestDnDDTO; | ||
import peer.backend.mongo.entity.TeamDnD; | ||
import peer.backend.service.dnd.DnDService; | ||
|
||
@RestController | ||
@RequiredArgsConstructor | ||
@RequestMapping("/api/v1/dnd-main") | ||
public class DnDController { | ||
private final DnDService dndService; | ||
|
||
@PostMapping("/create") | ||
public ResponseEntity<?> create(@RequestBody TeamDnD data) { | ||
TeamDnD ret; | ||
try { | ||
ret = this.dndService.createDnD(data); | ||
} catch (Exception e) { | ||
return new ResponseEntity<String>(e.getMessage(), HttpStatus.BAD_REQUEST); | ||
} | ||
return new ResponseEntity<TeamDnD>(ret,HttpStatus.CREATED); | ||
} | ||
|
||
@PostMapping("/read") | ||
public ResponseEntity<?> read(@RequestBody peer.backend.dto.dnd.RequestDnDDTO data) { | ||
TeamDnD ret; | ||
try { | ||
ret = this.dndService.getDnD(data); | ||
if (ret == null) | ||
return new ResponseEntity<>("There is no that DnD data", HttpStatus.NOT_FOUND); | ||
} catch (Exception e) { | ||
return new ResponseEntity<String>(e.getMessage(), HttpStatus.BAD_REQUEST); | ||
} | ||
return new ResponseEntity<TeamDnD>(ret,HttpStatus.OK); | ||
} | ||
|
||
@PostMapping("/update") | ||
public ResponseEntity<?> update(@RequestBody TeamDnD data) { | ||
|
||
TeamDnD ret; | ||
try{ | ||
ret = this.dndService.updateDnD(data); | ||
} catch (Exception e) { | ||
return new ResponseEntity<String>(e.getMessage(), HttpStatus.BAD_REQUEST); | ||
} | ||
return new ResponseEntity<TeamDnD>(ret, HttpStatus.OK); | ||
} | ||
|
||
@DeleteMapping("/delete") | ||
public ResponseEntity<?> delete(@RequestBody RequestDnDDTO data) { | ||
try { | ||
this.dndService.deleteDnD(data); | ||
} catch (Exception e) { | ||
return new ResponseEntity<String>(e.getMessage(), HttpStatus.BAD_REQUEST); | ||
} | ||
return new ResponseEntity<>(HttpStatus.OK); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
package peer.backend.controller.dnd; | ||
|
||
import io.swagger.annotations.ApiOperation; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.security.core.Authentication; | ||
import org.springframework.web.bind.annotation.*; | ||
import peer.backend.dto.dndSub.CalendarEventDTO; | ||
import peer.backend.dto.dndSub.DeleteTargetDTO; | ||
import peer.backend.dto.dndSub.MemberDTO; | ||
import peer.backend.entity.team.Team; | ||
import peer.backend.entity.user.User; | ||
import peer.backend.exception.BadRequestException; | ||
import peer.backend.service.dnd.DnDSubService; | ||
|
||
|
||
import java.util.List; | ||
import java.util.NoSuchElementException; | ||
|
||
@RestController | ||
@RequiredArgsConstructor | ||
@RequestMapping(DnDSubController.WIDGET_URL) | ||
public class DnDSubController { | ||
public static final String WIDGET_URL = "api/v1/dnd-sub"; | ||
public static final String CALENDAR_IDENTIFIER = "calendar"; | ||
private final DnDSubService dnDSubService; | ||
|
||
@GetMapping("calendar/team-list") | ||
@ApiOperation(value = "", notes = "달력을 위한 팀 멤버 리스트를 제공합니다.") | ||
public ResponseEntity<Object> getTeamMemberList(Authentication auth, @RequestBody long teamId) { | ||
Team target = this.dnDSubService.getTeamByTeamId(teamId); | ||
|
||
// redis 에 자주 쓸 가능성이 있는 team 정보 저장 | ||
this.dnDSubService.saveTeamDataInRedis(Long.toString(teamId), CALENDAR_IDENTIFIER, target); | ||
|
||
// 유효성 검사 | ||
if (this.dnDSubService.validCheckForTeam(target) | ||
|| this.dnDSubService.validCheckUserWithTeam(target, User.authenticationToUser(auth))) { | ||
return new ResponseEntity<>(HttpStatus.BAD_REQUEST); | ||
} | ||
|
||
// 멤버 리스트 담기 & 에러 핸들링 | ||
List<MemberDTO> ret; | ||
try { | ||
ret = this.dnDSubService.getMemberList(User.authenticationToUser(auth), target); | ||
} | ||
catch (NoSuchElementException | BadRequestException e) { | ||
return new ResponseEntity<>(e, HttpStatus.BAD_REQUEST); | ||
} | ||
if(ret == null) { | ||
return new ResponseEntity<>(HttpStatus.FORBIDDEN); | ||
} | ||
return new ResponseEntity<>(ret, HttpStatus.OK); | ||
} | ||
|
||
@PostMapping("calendar/set-alarm") | ||
@ApiOperation(value = "", notes = "알람으로 기록된 이벤트를 설정합니다.") | ||
public ResponseEntity<Object> setAlarmEvent(Authentication auth, @RequestBody CalendarEventDTO event) { | ||
// redis 에서 team 정보 찾기 | ||
Team target = (Team)this.dnDSubService.getTeamDataInRedis(Long.toString(event.getTeamId()), CALENDAR_IDENTIFIER); | ||
if(target == null) { | ||
target = this.dnDSubService.getTeamByTeamId(event.getTeamId()); | ||
this.dnDSubService.saveTeamDataInRedis(Long.toString(event.getTeamId()), CALENDAR_IDENTIFIER, target); | ||
} | ||
|
||
// 유효성 검사 | ||
if (this.dnDSubService.validCheckForTeam(target) | ||
|| this.dnDSubService.validCheckUserWithTeam(target, User.authenticationToUser(auth))) { | ||
return new ResponseEntity<>(HttpStatus.BAD_REQUEST); | ||
} | ||
|
||
Long eventId; | ||
|
||
try { | ||
eventId = this.dnDSubService.setEventToAlarm(event); | ||
} catch (BadRequestException e) { | ||
return new ResponseEntity<>(e, HttpStatus.BAD_REQUEST); | ||
} | ||
|
||
return new ResponseEntity<>(eventId, HttpStatus.OK); | ||
} | ||
|
||
@DeleteMapping("calendar/delete-alarm") | ||
@ApiOperation(value = "", notes = "알람으로 기록된 이벤트를 삭제합니다.") | ||
public ResponseEntity<Object> deleteAlarmEvent(Authentication auth, @RequestBody DeleteTargetDTO event) { | ||
Team target = (Team)this.dnDSubService.getTeamDataInRedis(Long.toString(event.getTeamId()), CALENDAR_IDENTIFIER); | ||
if(target == null) { | ||
target = this.dnDSubService.getTeamByTeamId(event.getTeamId()); | ||
this.dnDSubService.saveTeamDataInRedis(Long.toString(event.getTeamId()), CALENDAR_IDENTIFIER, target); | ||
} | ||
|
||
// 유효성 검사 | ||
if (this.dnDSubService.validCheckForTeam(target) | ||
|| this.dnDSubService.validCheckUserWithTeam(target, User.authenticationToUser(auth))) { | ||
return new ResponseEntity<>(HttpStatus.BAD_REQUEST); | ||
} | ||
|
||
//대상 삭제 | ||
try { | ||
this.dnDSubService.deleteEventFromAlarm(event); | ||
}catch (NoSuchElementException e) { | ||
return new ResponseEntity<>(e, HttpStatus.BAD_REQUEST); | ||
} | ||
|
||
return new ResponseEntity<>(HttpStatus.OK); | ||
} | ||
|
||
@PostMapping("calendar/update-alarm") | ||
@ApiOperation(value = "", notes = "알람으로 기록된 이벤트를 갱신합니다.") | ||
public ResponseEntity<Object> updateAlarmEvent(Authentication auth, @RequestBody CalendarEventDTO event) { | ||
// redis 에서 team 정보 찾기 | ||
Team target = (Team)this.dnDSubService.getTeamDataInRedis(Long.toString(event.getTeamId()), CALENDAR_IDENTIFIER); | ||
if(target == null) { | ||
target = this.dnDSubService.getTeamByTeamId(event.getTeamId()); | ||
this.dnDSubService.saveTeamDataInRedis(Long.toString(event.getTeamId()), CALENDAR_IDENTIFIER, target); | ||
} | ||
|
||
// 유효성 검사 | ||
if (this.dnDSubService.validCheckForTeam(target) | ||
|| this.dnDSubService.validCheckUserWithTeam(target, User.authenticationToUser(auth))) { | ||
return new ResponseEntity<>(HttpStatus.BAD_REQUEST); | ||
} | ||
|
||
Long eventId; | ||
|
||
try { | ||
eventId = this.dnDSubService.updateEventToAlarm(event); | ||
} catch (BadRequestException e) { | ||
return new ResponseEntity<>(e, HttpStatus.BAD_REQUEST); | ||
} | ||
|
||
if (eventId == -1L){ | ||
return new ResponseEntity<>(new NoSuchElementException("존재하지 않는 이벤트입니다."), HttpStatus.BAD_REQUEST); | ||
} | ||
|
||
return new ResponseEntity<>(HttpStatus.NO_CONTENT); | ||
} | ||
|
||
@GetMapping("calendar/test/total-alarm") | ||
@ApiOperation(value="", notes = "기록된 모든 알람을 호출합니다. 테스트용 코드입니다.") | ||
public ResponseEntity<Object> getTestTotalAlarmList(Authentication auth) { | ||
return new ResponseEntity<>(this.dnDSubService.getAllEvents(), HttpStatus.OK); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package peer.backend.dto.dnd; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
@Getter | ||
@NoArgsConstructor | ||
@AllArgsConstructor | ||
public class RequestDnDDTO { | ||
private Long teamId; | ||
private String type; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package peer.backend.dto.dndSub; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Builder; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
import java.time.LocalDateTime; | ||
import java.util.List; | ||
import java.util.Objects; | ||
|
||
@Getter | ||
@Builder | ||
@NoArgsConstructor | ||
@AllArgsConstructor | ||
public class CalendarEventDTO { | ||
private Long teamId; | ||
private Long eventId; | ||
private String title; | ||
private LocalDateTime start; | ||
private LocalDateTime end; | ||
private List<MemberDTO> member; | ||
|
||
|
||
@Override | ||
public boolean equals(Object o) { | ||
if (this == o) return true; | ||
if (o == null || getClass() != o.getClass()) return false; | ||
CalendarEventDTO target = (CalendarEventDTO) o; | ||
return Objects.equals(eventId, ((CalendarEventDTO) o).eventId) && | ||
Objects.equals(teamId, ((CalendarEventDTO) o).teamId); | ||
} | ||
// HashSet 을 제대로 동작시키기 위한 코드, 같은지 여부를 다각도로 점검한다. | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(teamId, eventId); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package peer.backend.dto.dndSub; | ||
|
||
import lombok.Getter; | ||
|
||
@Getter | ||
public class DeleteTargetDTO { | ||
private Long teamId; | ||
private Long eventId; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package peer.backend.dto.dndSub; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Builder; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
import javax.validation.constraints.Min; | ||
import javax.validation.constraints.NotBlank; | ||
import java.util.Objects; | ||
|
||
@Getter | ||
@Builder | ||
@NoArgsConstructor | ||
@AllArgsConstructor | ||
public class MemberDTO { | ||
@NotBlank | ||
@Min(value = 1, message = "정상적인 userId를 넣어 주십시오.") | ||
private Long userId; | ||
@NotBlank(message = "닉네임은 필수 요소 입니다.") | ||
private String nickname; | ||
|
||
@Override | ||
public boolean equals(Object o) { | ||
if (this == o) return true; | ||
if (o == null || getClass() != o.getClass()) return false; | ||
MemberDTO memberDTO = (MemberDTO) o; | ||
return Objects.equals(userId, memberDTO.userId) && | ||
Objects.equals(nickname, memberDTO.nickname); | ||
} | ||
// HashSet 을 제대로 동작시키기 위한 코드, 같은지 여부를 다각도로 점검한다. | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(userId, nickname); | ||
} | ||
} |
Check failure
Code scanning / SonarCloud
Persistent entities should not be used as arguments of "@RequestMapping" methods High
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
해당 부분의 보안문제는 한마디로 정의하면 다음과 같다.
DTO 형태로 재정의 되지 않은 객체 데이터 형태를 주고 받는 방식은 보안적인 문제를 야기 할 수 있으며, 그렇기에 제한적인 부분만 정재시킨 DTO 형태로의 수정을 요청한 것이다.
하지만 해당 기능의 기획 자체가 프론트에서 사용 가능하도록 만드는 것이었으므로, 그러한 방식으로 프론트-백엔드 간의 협의 방식으로 변경시 의도를 침해하게됨
따라서 향후 이 부분에 대해 다른 방식으로 보안 적용이 필요해 보인다.