From a1e8dc63b0b2d28fd31a68668854cda1f48b2df9 Mon Sep 17 00:00:00 2001 From: hansol Date: Mon, 25 Dec 2023 14:36:03 +0900 Subject: [PATCH 1/6] WIP --- .../backend/controller/dnd/DnDController.java | 61 ++++++++++ .../peer/backend/service/dnd/DnDService.java | 115 ++++++++++++++++++ 2 files changed, 176 insertions(+) create mode 100644 src/main/java/peer/backend/controller/dnd/DnDController.java create mode 100644 src/main/java/peer/backend/service/dnd/DnDService.java diff --git a/src/main/java/peer/backend/controller/dnd/DnDController.java b/src/main/java/peer/backend/controller/dnd/DnDController.java new file mode 100644 index 000000000..8418d0658 --- /dev/null +++ b/src/main/java/peer/backend/controller/dnd/DnDController.java @@ -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.temp.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(e.getMessage(), HttpStatus.BAD_REQUEST); + } + return new ResponseEntity(ret,HttpStatus.CREATED); + } + + @PostMapping("/read") + public ResponseEntity read(@RequestBody 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(e.getMessage(), HttpStatus.BAD_REQUEST); + } + return new ResponseEntity(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(e.getMessage(), HttpStatus.BAD_REQUEST); + } + return new ResponseEntity(ret, HttpStatus.OK); + } + + @DeleteMapping("/delete") + public ResponseEntity delete(@RequestBody RequestDnDDTO data) { + try { + this.dndService.deleteDnD(data); + } catch (Exception e) { + return new ResponseEntity(e.getMessage(), HttpStatus.BAD_REQUEST); + } + return new ResponseEntity<>(HttpStatus.OK); + } +} diff --git a/src/main/java/peer/backend/service/dnd/DnDService.java b/src/main/java/peer/backend/service/dnd/DnDService.java new file mode 100644 index 000000000..a05e1318d --- /dev/null +++ b/src/main/java/peer/backend/service/dnd/DnDService.java @@ -0,0 +1,115 @@ +package peer.backend.service.dnd; + +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Example; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import peer.backend.dto.temp.RequestDnDDTO; +import peer.backend.entity.team.Team; +import peer.backend.mongo.entity.TeamDnD; +import peer.backend.mongo.repository.PeerLogDnDRepository; +import peer.backend.mongo.repository.TeamDnDRepository; +import peer.backend.repository.team.TeamRepository; + +import java.util.NoSuchElementException; +import java.util.Optional; + +@Service +@RequiredArgsConstructor +public class DnDService { + + private final TeamDnDRepository teamDnDRepository; + private final PeerLogDnDRepository peerLogDnDRepository; + private final TeamRepository teamRepository; + + @Transactional + public TeamDnD createDnD(TeamDnD data) throws RuntimeException { + Optional target = teamRepository.findById(data.getTeamId()); + if (target.isEmpty()) { + throw new NoSuchElementException("Plz, check, There is no team id"); + } + TeamDnD saveData = TeamDnD.builder() + .teamId(data.getTeamId()) + .type(data.getType()) + .widgets(data.getWidgets()) + .build(); + + TeamDnD ret; + try { + if (data.getType().equals("team")) + ret = this.teamDnDRepository.save(saveData); + else + ret = this.peerLogDnDRepository.save(saveData); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("DB Server makes an error."); + } + return ret; + } + + @Transactional(readOnly = true) + public TeamDnD getDnD(RequestDnDDTO data) throws NoSuchElementException { + TeamDnD ret; + if (data.getType().equals("team")) { + ret = this.teamDnDRepository.findByTeamId(data.getTeamId()); + } + else { + ret = this.peerLogDnDRepository.findByTeamId(data.getTeamId()); + } + if (ret == null) { + throw new NoSuchElementException("There is no DnD Data"); + } + return ret; + } + + @Transactional + public TeamDnD updateDnD(TeamDnD data) throws Exception { + TeamDnD example = new TeamDnD(); + TeamDnD ret; + example.setTeamId(data.getTeamId()); + try { + if (data.getType().equals("team")) { + if (!this.teamDnDRepository.exists(Example.of(example))){ + throw new NoSuchElementException("There is no that Dnd File."); + } + example = this.teamDnDRepository.findByTeamId(data.getTeamId()); + example.setWidgets(data.getWidgets()); + ret = this.teamDnDRepository.save(example); + } else { + if (!this.peerLogDnDRepository.exists(Example.of(example))){ + throw new NoSuchElementException("There is no that Dnd File."); + } + example = this.peerLogDnDRepository.findByTeamId(data.getTeamId()); + example.setWidgets(data.getWidgets()); + ret = this.peerLogDnDRepository.save(data); + } + } catch (Exception e) { + e.printStackTrace(); + throw new Exception("DnD file update failed!"); + } + return ret; + } + + @Transactional + public void deleteDnD(RequestDnDDTO data) throws RuntimeException { + TeamDnD example = new TeamDnD(); + example.setTeamId(data.getTeamId()); + try { + if (data.getType().equals("team")) { + if (!this.teamDnDRepository.exists(Example.of(example))){ + throw new NoSuchElementException("There is no that Dnd File."); + } + this.teamDnDRepository.deleteByTeamId(data.getTeamId()); + } + else { + if (!this.peerLogDnDRepository.exists(Example.of(example))){ + throw new NoSuchElementException("There is no that Dnd File."); + } + this.peerLogDnDRepository.deleteByTeamId(data.getTeamId()); + } + } catch (Exception e) { + throw new RuntimeException("DnD file delete is failed!"); + } + + } +} From 9ab612c6991b686db5deaa9c18079fc9ed64453c Mon Sep 17 00:00:00 2001 From: hansol Date: Sun, 31 Dec 2023 18:00:04 +0900 Subject: [PATCH 2/6] WIP: up to controller, service, dto for calendar widget --- .../controller/dnd/DnDSubController.java | 59 +++++++++++++++++++ .../backend/dto/dndSub/CalendarEventDTO.java | 22 +++++++ .../backend/dto/dndSub/DeleteTargetDTO.java | 9 +++ .../peer/backend/dto/dndSub/MemberDTO.java | 21 +++++++ .../backend/service/dnd/DnDSubService.java | 24 ++++++++ 5 files changed, 135 insertions(+) create mode 100644 src/main/java/peer/backend/controller/dnd/DnDSubController.java create mode 100644 src/main/java/peer/backend/dto/dndSub/CalendarEventDTO.java create mode 100644 src/main/java/peer/backend/dto/dndSub/DeleteTargetDTO.java create mode 100644 src/main/java/peer/backend/dto/dndSub/MemberDTO.java create mode 100644 src/main/java/peer/backend/service/dnd/DnDSubService.java diff --git a/src/main/java/peer/backend/controller/dnd/DnDSubController.java b/src/main/java/peer/backend/controller/dnd/DnDSubController.java new file mode 100644 index 000000000..106ac636b --- /dev/null +++ b/src/main/java/peer/backend/controller/dnd/DnDSubController.java @@ -0,0 +1,59 @@ +package peer.backend.controller.dnd; + +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.apache.tomcat.util.net.openssl.ciphers.Authentication; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import peer.backend.dto.dndSub.CalendarEventDTO; +import peer.backend.dto.dndSub.DeleteTargetDTO; +import peer.backend.service.dnd.DnDSubService; + +@RestController +@RequiredArgsConstructor +@RequestMapping(DnDSubController.WIDGET_URL) +public class DnDSubController { + public static final String WIDGET_URL = "api/v1/dnd-sub"; + private final DnDSubService dnDSubService; + + @GetMapping("calendar/team-list") + @ApiOperation(value = "", notes = "달력을 위한 팀 멤버 리스트를 제공합니다.") + public ResponseEntity getTeamMemberList(Authentication auth, @RequestBody long teamId) { + // 인증 작업(팀 멤버 여부, 정상 팀 여부 등) + // 팀 멤버 객체 생성 + return new ResponseEntity<>(HttpStatus.OK); + } + + @PostMapping("calendar/set-alarm") + @ApiOperation(value = "", notes = "알람으로 기록된 이벤트를 설정합니다.") + public ResponseEntity setAlarmEvent(Authentication auth, @RequestBody CalendarEventDTO event) { + // 인증 작업(팀 멤버 여부, 정상 팀 여부 등) + // 이벤트 파악 작업(중복 이벤트 여부, 이미 지난 이벤트 여부, 비정상 입력 여부 start-end 대비 team 일정 파악) + return new ResponseEntity<>(HttpStatus.OK); + } + + @DeleteMapping("calendar/delete-alarm") + @ApiOperation(value = "", notes = "알람으로 기록된 이벤트를 삭제합니다.") + public ResponseEntity deleteAlarmEvent(Authentication auth, @RequestBody DeleteTargetDTO target) { + // 인증 작업(팀 멤버 여부, 정상 팀 여부 등) + // 삭제 처리 + return new ResponseEntity<>(HttpStatus.OK); + } + + @PostMapping("calendar/update-alarm") + @ApiOperation(value = "", notes = "알람으로 기록된 이벤트를 갱신합니다.") + public ResponseEntity updateAlarmEvent(Authentication auth, @RequestBody CalendarEventDTO event) { + // 인증 작업(팀 멤버 여부, 정상 팀 여부 등) + // 중복 여부 판단 + // 이벤트 파악 작업(중복 이벤트 여부, 이미 지난 이벤트 여부, 비정상 입력 여부 start-end 대비 team 일정 파악) + // 갱신 + return new ResponseEntity<>(HttpStatus.OK); + } + + @GetMapping("calendar/test/total-alarm") + @ApiOperation(value="", notes = "") + public ResponseEntity getTestTotalAlarmList(Authentication auth) { + return new ResponseEntity<>(HttpStatus.OK); + } +} diff --git a/src/main/java/peer/backend/dto/dndSub/CalendarEventDTO.java b/src/main/java/peer/backend/dto/dndSub/CalendarEventDTO.java new file mode 100644 index 000000000..df31eeb92 --- /dev/null +++ b/src/main/java/peer/backend/dto/dndSub/CalendarEventDTO.java @@ -0,0 +1,22 @@ +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; + +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class CalendarEventDTO { + private Long teamId; + private Long eventId; + private String title; + private LocalDateTime start; + private LocalDateTime end; + private List member; +} diff --git a/src/main/java/peer/backend/dto/dndSub/DeleteTargetDTO.java b/src/main/java/peer/backend/dto/dndSub/DeleteTargetDTO.java new file mode 100644 index 000000000..620e724eb --- /dev/null +++ b/src/main/java/peer/backend/dto/dndSub/DeleteTargetDTO.java @@ -0,0 +1,9 @@ +package peer.backend.dto.dndSub; + +import lombok.Getter; + +@Getter +public class DeleteTargetDTO { + private Long teamId; + private Long eventId; +} diff --git a/src/main/java/peer/backend/dto/dndSub/MemberDTO.java b/src/main/java/peer/backend/dto/dndSub/MemberDTO.java new file mode 100644 index 000000000..d712b2ef4 --- /dev/null +++ b/src/main/java/peer/backend/dto/dndSub/MemberDTO.java @@ -0,0 +1,21 @@ +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; + +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MemberDTO { + @NotBlank + @Min(value = 1, message = "정상적인 userId를 넣어 주십시오.") + private Long userId; + @NotBlank(message = "닉네임은 필수 요소 입니다.") + private String nickname; +} diff --git a/src/main/java/peer/backend/service/dnd/DnDSubService.java b/src/main/java/peer/backend/service/dnd/DnDSubService.java new file mode 100644 index 000000000..0af803768 --- /dev/null +++ b/src/main/java/peer/backend/service/dnd/DnDSubService.java @@ -0,0 +1,24 @@ +package peer.backend.service.dnd; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import peer.backend.dto.dndSub.CalendarEventDTO; +import peer.backend.repository.team.TeamRepository; +import peer.backend.repository.user.UserRepository; + +import java.util.List; + +@Service +@RequiredArgsConstructor +@EnableWebMvc +@Slf4j +public class DnDSubService { + private final UserRepository userRepository; + private final TeamRepository teamRepository; + + private final List tempMemeoryEventList; + +} From 173effad48083a84f3f0d534dbb81c2626e96692 Mon Sep 17 00:00:00 2001 From: hansol Date: Tue, 2 Jan 2024 06:15:14 +0900 Subject: [PATCH 3/6] FEAT : Make DnDWidget Tempoary Controller MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 임시 컨트롤러 작업 완료 - 위젯 이벤트에 대한 CRUD 완성 - 임시로 이벤트가 등록되었는지 여부 파악을 위한 전체 리스트 보여주는 API - 알람 이벤트 컨트롤러가 아직, 이벤트 알람이 가진 않음 --- .../controller/dnd/DnDSubController.java | 122 +++++++++++++++--- .../backend/dto/dndSub/CalendarEventDTO.java | 17 +++ .../peer/backend/dto/dndSub/MemberDTO.java | 16 +++ .../backend/service/dnd/DnDSubService.java | 115 ++++++++++++++++- 4 files changed, 249 insertions(+), 21 deletions(-) diff --git a/src/main/java/peer/backend/controller/dnd/DnDSubController.java b/src/main/java/peer/backend/controller/dnd/DnDSubController.java index 106ac636b..3e5d3166c 100644 --- a/src/main/java/peer/backend/controller/dnd/DnDSubController.java +++ b/src/main/java/peer/backend/controller/dnd/DnDSubController.java @@ -2,58 +2,144 @@ import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; -import org.apache.tomcat.util.net.openssl.ciphers.Authentication; 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 getTeamMemberList(Authentication auth, @RequestBody long teamId) { - // 인증 작업(팀 멤버 여부, 정상 팀 여부 등) - // 팀 멤버 객체 생성 - return new ResponseEntity<>(HttpStatus.OK); + 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 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 setAlarmEvent(Authentication auth, @RequestBody CalendarEventDTO event) { - // 인증 작업(팀 멤버 여부, 정상 팀 여부 등) - // 이벤트 파악 작업(중복 이벤트 여부, 이미 지난 이벤트 여부, 비정상 입력 여부 start-end 대비 team 일정 파악) - return new ResponseEntity<>(HttpStatus.OK); + // 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 deleteAlarmEvent(Authentication auth, @RequestBody DeleteTargetDTO target) { - // 인증 작업(팀 멤버 여부, 정상 팀 여부 등) - // 삭제 처리 + public ResponseEntity 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 updateAlarmEvent(Authentication auth, @RequestBody CalendarEventDTO event) { - // 인증 작업(팀 멤버 여부, 정상 팀 여부 등) - // 중복 여부 판단 - // 이벤트 파악 작업(중복 이벤트 여부, 이미 지난 이벤트 여부, 비정상 입력 여부 start-end 대비 team 일정 파악) - // 갱신 - return new ResponseEntity<>(HttpStatus.OK); + // 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 = "") + @ApiOperation(value="", notes = "기록된 모든 알람을 호출합니다. 테스트용 코드입니다.") public ResponseEntity getTestTotalAlarmList(Authentication auth) { - return new ResponseEntity<>(HttpStatus.OK); + return new ResponseEntity<>(this.dnDSubService.getAllEvents(), HttpStatus.OK); } -} +} \ No newline at end of file diff --git a/src/main/java/peer/backend/dto/dndSub/CalendarEventDTO.java b/src/main/java/peer/backend/dto/dndSub/CalendarEventDTO.java index df31eeb92..dadafe0c5 100644 --- a/src/main/java/peer/backend/dto/dndSub/CalendarEventDTO.java +++ b/src/main/java/peer/backend/dto/dndSub/CalendarEventDTO.java @@ -7,6 +7,7 @@ import java.time.LocalDateTime; import java.util.List; +import java.util.Objects; @Getter @Builder @@ -19,4 +20,20 @@ public class CalendarEventDTO { private LocalDateTime start; private LocalDateTime end; private List 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); + } } diff --git a/src/main/java/peer/backend/dto/dndSub/MemberDTO.java b/src/main/java/peer/backend/dto/dndSub/MemberDTO.java index d712b2ef4..d04c813ee 100644 --- a/src/main/java/peer/backend/dto/dndSub/MemberDTO.java +++ b/src/main/java/peer/backend/dto/dndSub/MemberDTO.java @@ -7,6 +7,7 @@ import javax.validation.constraints.Min; import javax.validation.constraints.NotBlank; +import java.util.Objects; @Getter @Builder @@ -18,4 +19,19 @@ public class MemberDTO { 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); + } } diff --git a/src/main/java/peer/backend/service/dnd/DnDSubService.java b/src/main/java/peer/backend/service/dnd/DnDSubService.java index 0af803768..d3fc2cda2 100644 --- a/src/main/java/peer/backend/service/dnd/DnDSubService.java +++ b/src/main/java/peer/backend/service/dnd/DnDSubService.java @@ -2,14 +2,23 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import org.springframework.web.servlet.config.annotation.EnableWebMvc; 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.team.TeamUser; +import peer.backend.entity.team.enums.TeamStatus; +import peer.backend.entity.user.User; +import peer.backend.exception.BadRequestException; import peer.backend.repository.team.TeamRepository; import peer.backend.repository.user.UserRepository; -import java.util.List; +import java.util.*; +import java.util.concurrent.atomic.AtomicBoolean; @Service @RequiredArgsConstructor @@ -19,6 +28,106 @@ public class DnDSubService { private final UserRepository userRepository; private final TeamRepository teamRepository; - private final List tempMemeoryEventList; + private Long eventCnt = 0L; + private RedisTemplate redisTemplate; + + private final HashSet tempMemeoryEventList; + + public void saveTeamDataInRedis(String key, String identifier, Object value) { + String newKey = key + "-" + identifier; + redisTemplate.opsForValue().set(newKey, value); + } + + public Object getTeamDataInRedis(String key, String identifier) { + return redisTemplate.opsForValue().get(key + "-" + identifier); + } + + public Team getTeamByTeamId(Long teamId){ + return this.teamRepository.findById(teamId).orElseThrow(() -> new NoSuchElementException("존재하지 않는 팀입니다.")); + } + + public boolean validCheckForTeam(Team target) { + return !target.getStatus().equals(TeamStatus.COMPLETE); + } + + public boolean validCheckUserWithTeam(Team target, User requester) { + return target.getTeamUsers() + .stream() + .anyMatch(member -> member.getUserId().equals(requester.getId())); + } + + public Long makeTemporaryEventId() { + Long id; + id = this.eventCnt++; + + return id; + } + + public List getMemberList(User requesterUser, Team targetTeam) { + + HashSet ret = new HashSet<>(); + for (TeamUser target : targetTeam.getTeamUsers()) { + User targetUser = target.getUser(); + MemberDTO member = MemberDTO.builder() + .nickname(targetUser.getNickname()) + .userId(targetUser.getId()) + .build(); + ret.add(member); + } + MemberDTO requester = MemberDTO.builder() + .nickname(requesterUser.getNickname()) + .userId(requesterUser.getId()) + .build(); + if (!ret.contains(requester)) + throw new BadRequestException("요청자가 팀 멤버가 아닙니다."); + return new ArrayList<>(ret); + } + + public Long setEventToAlarm(CalendarEventDTO data) { + Long id = this.makeTemporaryEventId(); + + if(data.getTeamId() == -1L){ + throw new BadRequestException("비정상적인 요청입니다."); + } + + CalendarEventDTO saveEvent = CalendarEventDTO.builder() + .eventId(id) + .teamId(data.getTeamId()) + .end(data.getEnd()) + .start(data.getStart()) + .member(data.getMember()) + .title(data.getTitle()) + .build(); + + this.tempMemeoryEventList.add(saveEvent); + + return id; + } + + public Long updateEventToAlarm(CalendarEventDTO data){ + if (this.tempMemeoryEventList.stream().noneMatch(event -> event.getEventId().equals(data.getEventId()))) { + return -1L; + } + this.tempMemeoryEventList.remove(data); + this.tempMemeoryEventList.add(data); + return data.getEventId(); + } + + public void deleteEventFromAlarm(DeleteTargetDTO target) { + CalendarEventDTO filtered = this.tempMemeoryEventList.stream() + .filter(event -> event.getEventId().equals(target.getEventId())) + .findFirst() + .orElse(null); + + if (filtered == null) + throw new NoSuchElementException("이벤트가 존재하지 않습니다."); + + this.tempMemeoryEventList.remove(filtered); + return; + } + + public List getAllEvents() { + return new ArrayList<>(this.tempMemeoryEventList); + } } From 71082c4e135ae65584e55b2c9201adac6ff71c43 Mon Sep 17 00:00:00 2001 From: hansol Date: Tue, 2 Jan 2024 06:31:26 +0900 Subject: [PATCH 4/6] FIX: Failed compile problem --- .../peer/backend/controller/dnd/DnDController.java | 4 ++-- .../java/peer/backend/dto/dnd/RequestDnDDTO.java | 13 +++++++++++++ .../java/peer/backend/service/dnd/DnDService.java | 2 +- 3 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 src/main/java/peer/backend/dto/dnd/RequestDnDDTO.java diff --git a/src/main/java/peer/backend/controller/dnd/DnDController.java b/src/main/java/peer/backend/controller/dnd/DnDController.java index 8418d0658..3d9a2bea3 100644 --- a/src/main/java/peer/backend/controller/dnd/DnDController.java +++ b/src/main/java/peer/backend/controller/dnd/DnDController.java @@ -4,7 +4,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import peer.backend.dto.temp.RequestDnDDTO; +import peer.backend.dto.dnd.RequestDnDDTO; import peer.backend.mongo.entity.TeamDnD; import peer.backend.service.dnd.DnDService; @@ -26,7 +26,7 @@ public ResponseEntity create(@RequestBody TeamDnD data) { } @PostMapping("/read") - public ResponseEntity read(@RequestBody RequestDnDDTO data) { + public ResponseEntity read(@RequestBody peer.backend.dto.dnd.RequestDnDDTO data) { TeamDnD ret; try { ret = this.dndService.getDnD(data); diff --git a/src/main/java/peer/backend/dto/dnd/RequestDnDDTO.java b/src/main/java/peer/backend/dto/dnd/RequestDnDDTO.java new file mode 100644 index 000000000..cb4a0c164 --- /dev/null +++ b/src/main/java/peer/backend/dto/dnd/RequestDnDDTO.java @@ -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; +} diff --git a/src/main/java/peer/backend/service/dnd/DnDService.java b/src/main/java/peer/backend/service/dnd/DnDService.java index a05e1318d..caaaa5c4e 100644 --- a/src/main/java/peer/backend/service/dnd/DnDService.java +++ b/src/main/java/peer/backend/service/dnd/DnDService.java @@ -4,7 +4,7 @@ import org.springframework.data.domain.Example; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import peer.backend.dto.temp.RequestDnDDTO; +import peer.backend.dto.dnd.RequestDnDDTO; import peer.backend.entity.team.Team; import peer.backend.mongo.entity.TeamDnD; import peer.backend.mongo.repository.PeerLogDnDRepository; From d6197bf9e3fef85e898d987dcc2551cd1ef912cd Mon Sep 17 00:00:00 2001 From: hansol Date: Tue, 2 Jan 2024 06:34:20 +0900 Subject: [PATCH 5/6] FIX: security hotspot fixed --- src/main/java/peer/backend/service/dnd/DnDService.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/peer/backend/service/dnd/DnDService.java b/src/main/java/peer/backend/service/dnd/DnDService.java index caaaa5c4e..4f738dd9f 100644 --- a/src/main/java/peer/backend/service/dnd/DnDService.java +++ b/src/main/java/peer/backend/service/dnd/DnDService.java @@ -41,7 +41,6 @@ public TeamDnD createDnD(TeamDnD data) throws RuntimeException { else ret = this.peerLogDnDRepository.save(saveData); } catch (Exception e) { - e.printStackTrace(); throw new RuntimeException("DB Server makes an error."); } return ret; From 013dce8d7b35491f2e94b8e9f168c05160f9f046 Mon Sep 17 00:00:00 2001 From: hansol Date: Tue, 2 Jan 2024 06:37:36 +0900 Subject: [PATCH 6/6] FIX: fix security hotspot --- src/main/java/peer/backend/service/dnd/DnDService.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/peer/backend/service/dnd/DnDService.java b/src/main/java/peer/backend/service/dnd/DnDService.java index 4f738dd9f..cd56f68a5 100644 --- a/src/main/java/peer/backend/service/dnd/DnDService.java +++ b/src/main/java/peer/backend/service/dnd/DnDService.java @@ -83,7 +83,6 @@ public TeamDnD updateDnD(TeamDnD data) throws Exception { ret = this.peerLogDnDRepository.save(data); } } catch (Exception e) { - e.printStackTrace(); throw new Exception("DnD file update failed!"); } return ret;