From 6a277351ef32b8a6988285b3fb2bd8b8ae509494 Mon Sep 17 00:00:00 2001 From: imdh Date: Wed, 24 May 2023 23:23:41 +0900 Subject: [PATCH 01/36] =?UTF-8?q?=EC=95=8C=EB=A6=BC=20=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80(#483)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [feat] FCM 연결 로직 추가(#483) * [feat] Alarm 테이블 및 Update API 추가 * [feat] Mypage 조회시 알림 정보 추가 * [feat] Alarm Update API에 Validation 추가 * [feat] Alarm API RestDoc 문서에 추가 --- build.gradle | 3 + src/docs/asciidoc/Alarm-API.adoc | 12 + src/docs/asciidoc/api.adoc | 2 + .../alarm/controller/AlarmController.java | 42 ++ .../domain/alarm/dto/ReqUpdateDiaryAlarm.java | 23 + .../alarm/dto/ReqUpdateRetrospectAlarm.java | 23 + .../backend/domain/alarm/entity/Alarm.java | 59 ++ .../alarm/repository/AlarmRepository.java | 12 + .../domain/alarm/service/AlarmService.java | 38 + .../backend/domain/auth/entity/Member.java | 36 +- .../domain/auth/service/ClientKakao.java | 18 +- .../backend/domain/diary/entity/Diary.java | 1 - .../mypage/dto/resp/RespGetUserDto.java | 23 + .../domain/mypage/service/MypageService.java | 8 +- src/main/resources/static/docs/Alarm-API.html | 655 ++++++++++++++++++ .../resources/static/docs/MyPage-API.html | 28 +- src/main/resources/static/docs/api.html | 238 ++++++- .../alarm/controller/AlarmControllerTest.java | 103 +++ .../controller/MypageControllerTest.java | 8 +- 19 files changed, 1303 insertions(+), 29 deletions(-) create mode 100644 src/docs/asciidoc/Alarm-API.adoc create mode 100644 src/main/java/com/nanal/backend/domain/alarm/controller/AlarmController.java create mode 100644 src/main/java/com/nanal/backend/domain/alarm/dto/ReqUpdateDiaryAlarm.java create mode 100644 src/main/java/com/nanal/backend/domain/alarm/dto/ReqUpdateRetrospectAlarm.java create mode 100644 src/main/java/com/nanal/backend/domain/alarm/entity/Alarm.java create mode 100644 src/main/java/com/nanal/backend/domain/alarm/repository/AlarmRepository.java create mode 100644 src/main/java/com/nanal/backend/domain/alarm/service/AlarmService.java create mode 100644 src/main/resources/static/docs/Alarm-API.html create mode 100644 src/test/java/com/nanal/backend/domain/alarm/controller/AlarmControllerTest.java diff --git a/build.gradle b/build.gradle index 940ff5db..e6f32467 100644 --- a/build.gradle +++ b/build.gradle @@ -78,6 +78,9 @@ dependencies { implementation("com.slack.api:bolt-jetty:1.27.3") implementation('com.github.maricn:logback-slack-appender:1.6.1') + // Push Alarm + implementation 'com.google.firebase:firebase-admin:8.1.0' + // Email 인증 implementation 'org.springframework.boot:spring-boot-starter-mail' diff --git a/src/docs/asciidoc/Alarm-API.adoc b/src/docs/asciidoc/Alarm-API.adoc new file mode 100644 index 00000000..4d73b81a --- /dev/null +++ b/src/docs/asciidoc/Alarm-API.adoc @@ -0,0 +1,12 @@ +[[Alarm-API]] +== Alarm API + +[[Alarm-일기-알림-변경]] +=== Alarm 일기 알림 변경 +operation::alarm-controller-test/일기_알림_변경[snippets='http-request,request-fields,http-response,response-fields'] + +--- + +[[Alarm-회고-알림-변경]] +=== Alarm 회고 알림 변경 +operation::alarm-controller-test/회고_알림_변경[snippets='http-request,request-fields,http-response,response-fields'] diff --git a/src/docs/asciidoc/api.adoc b/src/docs/asciidoc/api.adoc index ab82a208..1339481e 100644 --- a/src/docs/asciidoc/api.adoc +++ b/src/docs/asciidoc/api.adoc @@ -14,6 +14,8 @@ include::OnBoarding-API.adoc[] include::MyPage-API.adoc[] +include::Alarm-API.adoc[] + include::Diary-API.adoc[] include::Retrospect-API.adoc[] diff --git a/src/main/java/com/nanal/backend/domain/alarm/controller/AlarmController.java b/src/main/java/com/nanal/backend/domain/alarm/controller/AlarmController.java new file mode 100644 index 00000000..4e371d1a --- /dev/null +++ b/src/main/java/com/nanal/backend/domain/alarm/controller/AlarmController.java @@ -0,0 +1,42 @@ +package com.nanal.backend.domain.alarm.controller; + +import com.nanal.backend.domain.alarm.dto.ReqUpdateDiaryAlarm; +import com.nanal.backend.domain.alarm.dto.ReqUpdateRetrospectAlarm; +import com.nanal.backend.domain.alarm.service.AlarmService; +import com.nanal.backend.global.response.CommonResponse; +import com.nanal.backend.global.response.ErrorCode; +import com.nanal.backend.global.security.User; +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; + +@RequiredArgsConstructor +@RestController +public class AlarmController { + + private final AlarmService alarmService; + + @PutMapping("/alarm/diary") + public CommonResponse updateDiaryAlarm( + @AuthenticationPrincipal User user, + @RequestBody @Valid ReqUpdateDiaryAlarm reqUpdateDiaryAlarm) { + + alarmService.updateDiaryAlarm(user.getSocialId(), reqUpdateDiaryAlarm); + + return new CommonResponse<>(ErrorCode.SUCCESS); + } + + @PutMapping("/alarm/retrospect") + public CommonResponse updateRetrospectAlarm( + @AuthenticationPrincipal User user, + @RequestBody @Valid ReqUpdateRetrospectAlarm reqUpdateRetrospectAlarm) { + + alarmService.updateRetrospectAlarm(user.getSocialId(), reqUpdateRetrospectAlarm); + + return new CommonResponse<>(ErrorCode.SUCCESS); + } +} diff --git a/src/main/java/com/nanal/backend/domain/alarm/dto/ReqUpdateDiaryAlarm.java b/src/main/java/com/nanal/backend/domain/alarm/dto/ReqUpdateDiaryAlarm.java new file mode 100644 index 00000000..6384d82e --- /dev/null +++ b/src/main/java/com/nanal/backend/domain/alarm/dto/ReqUpdateDiaryAlarm.java @@ -0,0 +1,23 @@ +package com.nanal.backend.domain.alarm.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; + +@NoArgsConstructor +@AllArgsConstructor +@Data +public class ReqUpdateDiaryAlarm { + + @NotNull(message = "diaryAlarmActive 값이 올바르지 않습니다.") + private Boolean diaryAlarmActive; + + @NotBlank(message = "diaryAlarmTime 는 비어있을 수 없습니다.") + @Pattern(message = "diaryAlarmTime 값이 올바르지 않습니다.", + regexp = "^(0[0-9]|1[0-9]|2[0-3]):([0-5][0-9])$") + private String diaryAlarmTime; +} diff --git a/src/main/java/com/nanal/backend/domain/alarm/dto/ReqUpdateRetrospectAlarm.java b/src/main/java/com/nanal/backend/domain/alarm/dto/ReqUpdateRetrospectAlarm.java new file mode 100644 index 00000000..ba718d60 --- /dev/null +++ b/src/main/java/com/nanal/backend/domain/alarm/dto/ReqUpdateRetrospectAlarm.java @@ -0,0 +1,23 @@ +package com.nanal.backend.domain.alarm.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; + +@NoArgsConstructor +@AllArgsConstructor +@Data +public class ReqUpdateRetrospectAlarm { + + @NotNull(message = "retrospectAlarmActive 값이 올바르지 않습니다.") + private Boolean retrospectAlarmActive; + + @NotBlank(message = "retrospectAlarmTime 는 비어있을 수 없습니다.") + @Pattern(message = "retrospectAlarmTime 값이 올바르지 않습니다.", + regexp = "^(0[0-9]|1[0-9]|2[0-3]):([0-5][0-9])$") + private String retrospectAlarmTime; +} diff --git a/src/main/java/com/nanal/backend/domain/alarm/entity/Alarm.java b/src/main/java/com/nanal/backend/domain/alarm/entity/Alarm.java new file mode 100644 index 00000000..6bf468cb --- /dev/null +++ b/src/main/java/com/nanal/backend/domain/alarm/entity/Alarm.java @@ -0,0 +1,59 @@ +package com.nanal.backend.domain.alarm.entity; + +import com.nanal.backend.domain.alarm.dto.ReqUpdateDiaryAlarm; +import com.nanal.backend.domain.alarm.dto.ReqUpdateRetrospectAlarm; +import com.nanal.backend.domain.auth.entity.Member; +import com.nanal.backend.global.config.BaseTime; +import lombok.*; + +import javax.persistence.*; + +@Getter +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Builder +@Table(name = "alarm") +@Entity +public class Alarm extends BaseTime { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "alarm_id") + private Long alarmId; + + @Column(nullable = false) + private Boolean diaryActive; + + @Column(length = 5, nullable = false) + private String diaryTime; + + @Column(nullable = false) + private Boolean retrospectActive; + + @Column(length = 5, nullable = false) + private String retrospectTime; + + @OneToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id") + private Member member; + + public static Alarm createAlarm(Member member) { + return Alarm.builder() + .diaryActive(true) + .diaryTime("20:00") + .retrospectActive(true) + .retrospectTime("20:00") + .member(member) + .build(); + } + + public void updateDiaryAlarm(ReqUpdateDiaryAlarm reqUpdateDiaryAlarm) { + this.diaryActive = reqUpdateDiaryAlarm.getDiaryAlarmActive(); + this.diaryTime = reqUpdateDiaryAlarm.getDiaryAlarmTime(); + } + + public void updateRetrospectAlarm(ReqUpdateRetrospectAlarm reqUpdateRetrospectAlarm) { + this.retrospectActive = reqUpdateRetrospectAlarm.getRetrospectAlarmActive(); + this.retrospectTime = reqUpdateRetrospectAlarm.getRetrospectAlarmTime(); + } +} diff --git a/src/main/java/com/nanal/backend/domain/alarm/repository/AlarmRepository.java b/src/main/java/com/nanal/backend/domain/alarm/repository/AlarmRepository.java new file mode 100644 index 00000000..f8db42cd --- /dev/null +++ b/src/main/java/com/nanal/backend/domain/alarm/repository/AlarmRepository.java @@ -0,0 +1,12 @@ +package com.nanal.backend.domain.alarm.repository; + +import com.nanal.backend.domain.alarm.entity.Alarm; +import com.nanal.backend.domain.auth.entity.Member; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface AlarmRepository extends JpaRepository { + + Optional findByMember(Member member); +} diff --git a/src/main/java/com/nanal/backend/domain/alarm/service/AlarmService.java b/src/main/java/com/nanal/backend/domain/alarm/service/AlarmService.java new file mode 100644 index 00000000..9aac0bf5 --- /dev/null +++ b/src/main/java/com/nanal/backend/domain/alarm/service/AlarmService.java @@ -0,0 +1,38 @@ +package com.nanal.backend.domain.alarm.service; + +import com.nanal.backend.domain.alarm.dto.ReqUpdateDiaryAlarm; +import com.nanal.backend.domain.alarm.dto.ReqUpdateRetrospectAlarm; +import com.nanal.backend.domain.alarm.entity.Alarm; +import com.nanal.backend.domain.alarm.repository.AlarmRepository; +import com.nanal.backend.domain.auth.entity.Member; +import com.nanal.backend.domain.auth.repository.MemberRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; + +@Transactional +@RequiredArgsConstructor +@Service +public class AlarmService { + + private final MemberRepository memberRepository; + + public void updateDiaryAlarm(String socialId, ReqUpdateDiaryAlarm reqUpdateDiaryAlarm) { + // socialId 로 유저 조회 + Member member = memberRepository.findMember(socialId); + + Alarm alarm = member.getAlarm(); + + alarm.updateDiaryAlarm(reqUpdateDiaryAlarm); + } + + public void updateRetrospectAlarm(String socialId, ReqUpdateRetrospectAlarm reqUpdateRetrospectAlarm) { + // socialId 로 유저 조회 + Member member = memberRepository.findMember(socialId); + + Alarm alarm = member.getAlarm(); + + alarm.updateRetrospectAlarm(reqUpdateRetrospectAlarm); + } +} diff --git a/src/main/java/com/nanal/backend/domain/auth/entity/Member.java b/src/main/java/com/nanal/backend/domain/auth/entity/Member.java index b94f9db4..5ef03f99 100644 --- a/src/main/java/com/nanal/backend/domain/auth/entity/Member.java +++ b/src/main/java/com/nanal/backend/domain/auth/entity/Member.java @@ -1,5 +1,7 @@ package com.nanal.backend.domain.auth.entity; +import com.nanal.backend.domain.alarm.entity.Alarm; +import com.nanal.backend.domain.auth.dto.KakaoUserResponseDto; import com.nanal.backend.domain.auth.dto.req.ReqRegisterDto; import com.nanal.backend.domain.auth.enumerate.MemberProvider; import com.nanal.backend.domain.diary.entity.Diary; @@ -72,6 +74,9 @@ public class Member extends BaseTime { @Enumerated(value = EnumType.STRING) private Role role; + @OneToOne(mappedBy = "member", fetch = FetchType.LAZY, cascade = CascadeType.ALL) + private Alarm alarm; + @OneToMany(mappedBy = "member", cascade = CascadeType.ALL) private List diaries = new ArrayList<>(); @@ -121,8 +126,29 @@ public static Member createNewMember(ReqRegisterDto reqRegisterDto) { .build(); } + public static Member createKakaoMember(KakaoUserResponseDto kakaoUserResponseDto) { + Member newMember = Member.builder() + .socialId(MemberProvider.KAKAO + "@" + kakaoUserResponseDto.getId()) + .provider(MemberProvider.KAKAO) + .name(kakaoUserResponseDto.getProperties().getNickname()) + .email(kakaoUserResponseDto.getKakaoAccount().getEmail()) + .password("undef") + // 당일로 회고일 설정 + .retrospectDay(LocalDate.now().getDayOfWeek()) + .prevRetrospectDate(LocalDateTime.now().minusDays(30)) + .nickname(kakaoUserResponseDto.getProperties().getNickname()) + .gender(kakaoUserResponseDto.getKakaoAccount().getGender()) + .ageRange(kakaoUserResponseDto.getKakaoAccount().getAgeRange()) + .role(Member.Role.ONBOARDER) + .build(); + + newMember.setAlarm(Alarm.createAlarm(newMember)); + + return newMember; + } + public static Member createAppleMember(String socialId, String email) { - return Member.builder() + Member newMember = Member.builder() .socialId(MemberProvider.APPLE + "@" + socialId) .provider(MemberProvider.APPLE) .name("나나리") @@ -134,11 +160,17 @@ public static Member createAppleMember(String socialId, String email) { .nickname("나나리") .ageRange("undef") .gender("undef") - .role(Member.Role.ONBOARDER) + .role(Role.ONBOARDER) .build(); + + newMember.setAlarm(Alarm.createAlarm(newMember)); + + return newMember; } //==수정 메서드==// + private void setAlarm(Alarm alarm) { this.alarm = alarm; } + public void updateNickname(String nickname) { this.nickname = nickname; } public void updateRetrospectDay(DayOfWeek retrospectDay) { diff --git a/src/main/java/com/nanal/backend/domain/auth/service/ClientKakao.java b/src/main/java/com/nanal/backend/domain/auth/service/ClientKakao.java index ba3ed43b..eb08e8de 100644 --- a/src/main/java/com/nanal/backend/domain/auth/service/ClientKakao.java +++ b/src/main/java/com/nanal/backend/domain/auth/service/ClientKakao.java @@ -1,5 +1,7 @@ package com.nanal.backend.domain.auth.service; +import com.nanal.backend.domain.alarm.entity.Alarm; +import com.nanal.backend.domain.alarm.repository.AlarmRepository; import com.nanal.backend.domain.auth.dto.KakaoAccessTokenResponseDto; import com.nanal.backend.domain.auth.dto.KakaoUserResponseDto; import com.nanal.backend.domain.auth.entity.Member; @@ -41,21 +43,7 @@ public Member getUserData(String accessToken) { kakaoUserResponseDto.adaptResponse(); - // 닉네임 길이체크해야함 - return Member.builder() - .socialId(MemberProvider.KAKAO + "@" + kakaoUserResponseDto.getId()) - .provider(MemberProvider.KAKAO) - .name(kakaoUserResponseDto.getProperties().getNickname()) - .email(kakaoUserResponseDto.getKakaoAccount().getEmail()) - .password("undef") - // 당일로 회고일 설정 - .retrospectDay(LocalDate.now().getDayOfWeek()) - .prevRetrospectDate(LocalDateTime.now().minusDays(30)) - .nickname(kakaoUserResponseDto.getProperties().getNickname()) - .gender(kakaoUserResponseDto.getKakaoAccount().getGender()) - .ageRange(kakaoUserResponseDto.getKakaoAccount().getAgeRange()) - .role(Member.Role.ONBOARDER) - .build(); + return Member.createKakaoMember(kakaoUserResponseDto); } public void verifyAccessToken(String accessToken) { diff --git a/src/main/java/com/nanal/backend/domain/diary/entity/Diary.java b/src/main/java/com/nanal/backend/domain/diary/entity/Diary.java index a71be1da..26e9e518 100644 --- a/src/main/java/com/nanal/backend/domain/diary/entity/Diary.java +++ b/src/main/java/com/nanal/backend/domain/diary/entity/Diary.java @@ -13,7 +13,6 @@ import java.util.List; import java.util.stream.Collectors; -@Data @Getter @AllArgsConstructor @NoArgsConstructor(access = AccessLevel.PROTECTED) diff --git a/src/main/java/com/nanal/backend/domain/mypage/dto/resp/RespGetUserDto.java b/src/main/java/com/nanal/backend/domain/mypage/dto/resp/RespGetUserDto.java index 2bc46761..60143cd1 100644 --- a/src/main/java/com/nanal/backend/domain/mypage/dto/resp/RespGetUserDto.java +++ b/src/main/java/com/nanal/backend/domain/mypage/dto/resp/RespGetUserDto.java @@ -1,5 +1,7 @@ package com.nanal.backend.domain.mypage.dto.resp; +import com.nanal.backend.domain.alarm.entity.Alarm; +import com.nanal.backend.domain.auth.entity.Member; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -17,4 +19,25 @@ public class RespGetUserDto { private String email; private DayOfWeek retrospectDay; + + private Boolean diaryAlarmActive; + + private String diaryAlarmTime; + + private Boolean retrospectAlarmActive; + + private String retrospectAlarmTime; + + public static RespGetUserDto createRespGetUserDto(Member member) { + Alarm alarm = member.getAlarm(); + return RespGetUserDto.builder() + .email(member.getEmail()) + .nickname(member.getNickname()) + .retrospectDay(member.getRetrospectDay()) + .diaryAlarmActive(alarm.getDiaryActive()) + .diaryAlarmTime(alarm.getDiaryTime()) + .retrospectAlarmActive(alarm.getRetrospectActive()) + .retrospectAlarmTime(alarm.getRetrospectTime()) + .build(); + } } diff --git a/src/main/java/com/nanal/backend/domain/mypage/service/MypageService.java b/src/main/java/com/nanal/backend/domain/mypage/service/MypageService.java index 63617d4a..68e20ef2 100644 --- a/src/main/java/com/nanal/backend/domain/mypage/service/MypageService.java +++ b/src/main/java/com/nanal/backend/domain/mypage/service/MypageService.java @@ -1,5 +1,7 @@ package com.nanal.backend.domain.mypage.service; +import com.nanal.backend.domain.alarm.entity.Alarm; +import com.nanal.backend.domain.alarm.repository.AlarmRepository; import com.nanal.backend.domain.auth.entity.Member; import com.nanal.backend.domain.auth.repository.MemberRepository; import com.nanal.backend.domain.mypage.repository.FeedbackRepository; @@ -36,11 +38,7 @@ public RespGetUserDto getUser(String socialId) { // socialId 로 유저 조회 Member member = findMember(socialId); - return RespGetUserDto.builder() - .email(member.getEmail()) - .nickname(member.getNickname()) - .retrospectDay(member.getRetrospectDay()) - .build(); + return RespGetUserDto.createRespGetUserDto(member); } @Counted("mypage.api.count") diff --git a/src/main/resources/static/docs/Alarm-API.html b/src/main/resources/static/docs/Alarm-API.html new file mode 100644 index 00000000..60c5c006 --- /dev/null +++ b/src/main/resources/static/docs/Alarm-API.html @@ -0,0 +1,655 @@ + + + + + + + +Alarm API + + + + + +
+
+

Alarm API

+
+
+

Alarm 일기 알림 변경

+
+

HTTP request

+
+
+
PUT /alarm/diary HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+Token: ACCESS_TOKEN
+Content-Length: 64
+Host: localhost:8080
+
+{
+  "diaryAlarmActive" : true,
+  "diaryAlarmTime" : "20:00"
+}
+
+
+
+
+

Request fields

+ +++++ + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

diaryAlarmActive

Boolean

일기 알림 활성화 여부

diaryAlarmTime

String

일기 알림 시간

+
+
+

HTTP response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Length: 94
+
+{
+  "isSuccess" : true,
+  "code" : 200,
+  "message" : "요청에 성공하였습니다."
+}
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

isSuccess

Boolean

성공 여부

code

Number

상태 코드

message

String

결과 메시지

+
+
+
+
+

Alarm 회고 알림 변경

+
+

HTTP request

+
+
+
PUT /alarm/retrospect HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+Token: ACCESS_TOKEN
+Content-Length: 74
+Host: localhost:8080
+
+{
+  "retrospectAlarmActive" : true,
+  "retrospectAlarmTime" : "20:00"
+}
+
+
+
+
+

Request fields

+ +++++ + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

retrospectAlarmActive

Boolean

회고 알림 활성화 여부

retrospectAlarmTime

String

회고 알림 시간

+
+
+

HTTP response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Length: 94
+
+{
+  "isSuccess" : true,
+  "code" : 200,
+  "message" : "요청에 성공하였습니다."
+}
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

isSuccess

Boolean

성공 여부

code

Number

상태 코드

message

String

결과 메시지

+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/static/docs/MyPage-API.html b/src/main/resources/static/docs/MyPage-API.html index c2c995b1..00a78fd4 100644 --- a/src/main/resources/static/docs/MyPage-API.html +++ b/src/main/resources/static/docs/MyPage-API.html @@ -482,7 +482,7 @@

HTTP response

HTTP/1.1 200 OK
 Content-Type: application/json;charset=UTF-8
-Content-Length: 226
+Content-Length: 366
 
 {
   "isSuccess" : true,
@@ -491,7 +491,11 @@ 

HTTP response

"result" : { "nickname" : "사용자 닉네임", "email" : "유저 이메일", - "retrospectDay" : "THURSDAY" + "retrospectDay" : "THURSDAY", + "diaryAlarmActive" : true, + "diaryAlarmTime" : "20:00", + "retrospectAlarmActive" : true, + "retrospectAlarmTime" : "20:00" } }
@@ -543,6 +547,26 @@

Response fields

String

유저의 회고일

+ +

result.diaryAlarmActive

+

Boolean

+

일기 알림 활성화 여부

+ + +

result.diaryAlarmTime

+

String

+

일기 알림 시간

+ + +

result.retrospectAlarmActive

+

Boolean

+

회고 알림 활성화 여부

+ + +

result.retrospectAlarmTime

+

String

+

회고 알림 시간

+ diff --git a/src/main/resources/static/docs/api.html b/src/main/resources/static/docs/api.html index d439e167..4a75e2dd 100644 --- a/src/main/resources/static/docs/api.html +++ b/src/main/resources/static/docs/api.html @@ -480,6 +480,12 @@

Nanal API Doc

  • MyPage 회원탈퇴
  • +
  • Alarm API + +
  • Diary API
  • +
  • Sponsor API + +
  • @@ -5106,11 +5111,130 @@

    + +
    +
    + +
    + +
    +
    +
    POST /sponsor HTTP/1.1
    +Content-Type: application/json;charset=UTF-8
    +Token: ACCESS_TOKEN
    +Content-Length: 23
    +Host: localhost:8080
    +
    +{
    +  "code" : "code"
    +}
    +
    +
    +
    +
    + + ++++ + + + + + + + + + + + + +
    NameDescription

    Token

    접근 토큰

    +
    +
    + + +++++ + + + + + + + + + + + + + + +
    PathTypeDescription

    code

    String

    인증 코드

    +
    +
    + +
    +
    +
    HTTP/1.1 200 OK
    +Content-Type: application/json;charset=UTF-8
    +Content-Length: 94
    +
    +{
    +  "isSuccess" : true,
    +  "code" : 200,
    +  "message" : "요청에 성공하였습니다."
    +}
    +
    +
    +
    +
    + + +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
    PathTypeDescription

    isSuccess

    Boolean

    성공 여부

    code

    Number

    상태 코드

    message

    String

    결과 메시지

    +
    +
    +
    + diff --git a/src/test/java/com/nanal/backend/domain/sponsor/controller/SponsorControllerTest.java b/src/test/java/com/nanal/backend/domain/sponsor/controller/SponsorControllerTest.java new file mode 100644 index 00000000..844a5721 --- /dev/null +++ b/src/test/java/com/nanal/backend/domain/sponsor/controller/SponsorControllerTest.java @@ -0,0 +1,61 @@ +package com.nanal.backend.domain.sponsor.controller; + +import com.nanal.backend.config.CommonControllerTest; +import com.nanal.backend.domain.sponsor.dto.req.ReqCheckSponsorDto; +import com.nanal.backend.domain.sponsor.service.SponsorService; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.ResultActions; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.willDoNothing; +import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; +import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; +import static org.springframework.restdocs.payload.PayloadDocumentation.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@WebMvcTest(SponsorController.class) +public class SponsorControllerTest extends CommonControllerTest { + + @MockBean + SponsorService sponsorService; + + @Test + public void 후원자_인증() throws Exception { + //given + String code = "code"; + ReqCheckSponsorDto reqCheckSponsorDto = new ReqCheckSponsorDto(code); + willDoNothing().given(sponsorService).checkSponsor(any(), any()); //void일때는 willDoNothing 사용 + + //when + ResultActions actions = mockMvc.perform( + post("/sponsor") + .header("Token", "ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(reqCheckSponsorDto)) + ); + + //then + actions + .andExpect(status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Token").description("접근 토큰") + ), + requestFields( + fieldWithPath("code").description("인증 코드") + ), + responseFields( + fieldWithPath("isSuccess").description("성공 여부"), + fieldWithPath("code").description("상태 코드"), + fieldWithPath("message").description("결과 메시지") + ) + ) + ); + + } +} From 33c371e46ca661deffcfdf4ad0124307cd21487d Mon Sep 17 00:00:00 2001 From: imdh Date: Wed, 28 Jun 2023 02:26:33 +0900 Subject: [PATCH 18/36] =?UTF-8?q?[Search]=20=EC=82=AC=EC=9A=A9=EC=9E=90=20?= =?UTF-8?q?=EC=8B=9D=EB=B3=84=EA=B0=92=20=EC=B6=94=EA=B0=80=20(#557)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [feat] 일기, 회고 조회시 사용자 식별값 추가 * [refactor] 검색 관련 문자열 파싱 수정 --- .gitignore | 1 + .../search/controller/SearchController.java | 7 +++++-- .../backend/domain/search/dto/DiaryInfo.java | 2 +- .../domain/search/dto/RetrospectInfo.java | 2 +- .../search/repository/SearchDiaryRepository.java | 15 +++++++++++---- .../repository/SearchRetrospectRepository.java | 16 ++++++++++++---- .../domain/search/service/SearchService.java | 14 +++++++++----- src/main/resources/static/docs/Alarm-API.html | 2 +- src/main/resources/static/docs/Auth-API.html | 2 +- src/main/resources/static/docs/Diary-API.html | 2 +- src/main/resources/static/docs/MyPage-API.html | 2 +- .../resources/static/docs/OnBoarding-API.html | 2 +- src/main/resources/static/docs/Overview.html | 2 +- .../resources/static/docs/Retrospect-API.html | 2 +- src/main/resources/static/docs/Search-API.html | 2 +- src/main/resources/static/docs/Sponsor-API.html | 2 +- src/main/resources/static/docs/api.html | 2 +- .../search/controller/SearchControllerTest.java | 2 +- 18 files changed, 51 insertions(+), 28 deletions(-) diff --git a/.gitignore b/.gitignore index 6b1095b9..56234a71 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ Dockerfile-dev prometheus.yml grafana_data logs +pinpoint-agent-2.5.0 ### STS ### .apt_generated diff --git a/src/main/java/com/nanal/backend/domain/search/controller/SearchController.java b/src/main/java/com/nanal/backend/domain/search/controller/SearchController.java index 11044bfb..d3449ad0 100644 --- a/src/main/java/com/nanal/backend/domain/search/controller/SearchController.java +++ b/src/main/java/com/nanal/backend/domain/search/controller/SearchController.java @@ -5,7 +5,9 @@ import com.nanal.backend.domain.search.service.SearchService; import com.nanal.backend.global.exception.customexception.BindingResultException; import com.nanal.backend.global.response.CommonResponse; +import com.nanal.backend.global.security.User; import lombok.RequiredArgsConstructor; +import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @@ -19,13 +21,14 @@ public class SearchController { private final SearchService searchService; @GetMapping("/search") - public CommonResponse search(@Valid ReqSearchDto reqSearchDto, + public CommonResponse search(@AuthenticationPrincipal User user, + @Valid ReqSearchDto reqSearchDto, BindingResult bindingResult) { if(bindingResult.hasErrors()) throw new BindingResultException(bindingResult.getFieldErrors()); - RespSearchDto respSearchDto = searchService.search(reqSearchDto); + RespSearchDto respSearchDto = searchService.search(user.getSocialId() ,reqSearchDto); return new CommonResponse<>(respSearchDto); } } diff --git a/src/main/java/com/nanal/backend/domain/search/dto/DiaryInfo.java b/src/main/java/com/nanal/backend/domain/search/dto/DiaryInfo.java index 906fe6c1..dfbc7052 100644 --- a/src/main/java/com/nanal/backend/domain/search/dto/DiaryInfo.java +++ b/src/main/java/com/nanal/backend/domain/search/dto/DiaryInfo.java @@ -63,7 +63,7 @@ public static String parseContent(String content, String searchWord) { } } - if (targetIndex >= 3) { + if (targetIndex > 3) { return "... " + String.join(" ", Arrays.asList(words).subList(targetIndex - 3, targetIndex + 1)); } else { return content; diff --git a/src/main/java/com/nanal/backend/domain/search/dto/RetrospectInfo.java b/src/main/java/com/nanal/backend/domain/search/dto/RetrospectInfo.java index a2915dc3..e12627e3 100644 --- a/src/main/java/com/nanal/backend/domain/search/dto/RetrospectInfo.java +++ b/src/main/java/com/nanal/backend/domain/search/dto/RetrospectInfo.java @@ -71,7 +71,7 @@ public static String parseAnswer(String content, String searchWord) { } } - if (targetIndex >= 3) { + if (targetIndex > 3) { return "... " + String.join(" ", Arrays.asList(words).subList(targetIndex - 3, targetIndex + 1)); } else { return content; diff --git a/src/main/java/com/nanal/backend/domain/search/repository/SearchDiaryRepository.java b/src/main/java/com/nanal/backend/domain/search/repository/SearchDiaryRepository.java index c8e4a607..4614456b 100644 --- a/src/main/java/com/nanal/backend/domain/search/repository/SearchDiaryRepository.java +++ b/src/main/java/com/nanal/backend/domain/search/repository/SearchDiaryRepository.java @@ -24,7 +24,7 @@ public class SearchDiaryRepository { private final JPAQueryFactory queryFactory; - public List searchDiary(ReqSearchDto reqSearchDto) { + public List searchDiary(ReqSearchDto reqSearchDto, Long memberId) { return queryFactory .selectDistinct(diary) @@ -32,7 +32,8 @@ public List searchDiary(ReqSearchDto reqSearchDto) { .join(diary.keywords, keyword) .where( betweenDate(reqSearchDto.getStartDate(), reqSearchDto.getEndDate()) - .and(containWord(reqSearchDto.getSearchWord())) + .and(containWord(reqSearchDto.getSearchWord()) + .and(isEqualMember(memberId))) ) .orderBy(diary.writeDate.desc()) .offset(reqSearchDto.getOffset()) @@ -40,14 +41,15 @@ public List searchDiary(ReqSearchDto reqSearchDto) { .fetch(); } - public Integer countLeftDiary(ReqSearchDto reqSearchDto) { + public Integer countLeftDiary(ReqSearchDto reqSearchDto, Long memberId) { return queryFactory .selectDistinct(diary.diaryId) .from(diary) .join(diary.keywords, keyword) .where( betweenDate(reqSearchDto.getStartDate(), reqSearchDto.getEndDate()) - .and(containWord(reqSearchDto.getSearchWord())) + .and(containWord(reqSearchDto.getSearchWord()) + .and(isEqualMember(memberId))) ) .orderBy(diary.writeDate.desc()) .offset(reqSearchDto.getOffset() + reqSearchDto.getLimit()) @@ -56,6 +58,11 @@ public Integer countLeftDiary(ReqSearchDto reqSearchDto) { .size(); } + private BooleanBuilder isEqualMember(Long memberId) { + if(memberId != null) return new BooleanBuilder(diary.member.memberId.eq(memberId)); + else return new BooleanBuilder(); + } + private BooleanBuilder containWordInContent(String word) { if(hasText(word)) return new BooleanBuilder(diary.content.contains(word)); else return new BooleanBuilder(); diff --git a/src/main/java/com/nanal/backend/domain/search/repository/SearchRetrospectRepository.java b/src/main/java/com/nanal/backend/domain/search/repository/SearchRetrospectRepository.java index b8128df4..9f8c6afe 100644 --- a/src/main/java/com/nanal/backend/domain/search/repository/SearchRetrospectRepository.java +++ b/src/main/java/com/nanal/backend/domain/search/repository/SearchRetrospectRepository.java @@ -21,10 +21,11 @@ public class SearchRetrospectRepository { private final JPAQueryFactory queryFactory; + QRetrospect retrospect = QRetrospect.retrospect; QRetrospectContent retrospectContent = QRetrospectContent.retrospectContent; - public List searchRetrospect(ReqSearchDto reqSearchDto) { + public List searchRetrospect(ReqSearchDto reqSearchDto, Long memberId) { return queryFactory .selectDistinct(retrospect) @@ -32,7 +33,8 @@ public List searchRetrospect(ReqSearchDto reqSearchDto) { .join(retrospect.retrospectContents, retrospectContent) .where( betweenDate(reqSearchDto.getStartDate(), reqSearchDto.getEndDate()) - .and(containWordInAnswer(reqSearchDto.getSearchWord())) + .and(containWordInAnswer(reqSearchDto.getSearchWord()) + .and(isEqualMember(memberId))) ) .orderBy(retrospect.writeDate.desc()) .offset(reqSearchDto.getOffset()) @@ -41,7 +43,7 @@ public List searchRetrospect(ReqSearchDto reqSearchDto) { } - public Integer countLeftRetrospect(ReqSearchDto reqSearchDto) { + public Integer countLeftRetrospect(ReqSearchDto reqSearchDto, Long memberId) { return queryFactory .selectDistinct(retrospect.retrospectId) @@ -49,7 +51,8 @@ public Integer countLeftRetrospect(ReqSearchDto reqSearchDto) { .join(retrospect.retrospectContents, retrospectContent) .where( betweenDate(reqSearchDto.getStartDate(), reqSearchDto.getEndDate()) - .and(containWordInAnswer(reqSearchDto.getSearchWord())) + .and(containWordInAnswer(reqSearchDto.getSearchWord()) + .and(isEqualMember(memberId))) ) .orderBy(retrospect.writeDate.desc()) .offset(reqSearchDto.getOffset() + reqSearchDto.getLimit()) @@ -58,6 +61,11 @@ public Integer countLeftRetrospect(ReqSearchDto reqSearchDto) { .size(); } + private BooleanBuilder isEqualMember(Long memberId) { + if(memberId != null) return new BooleanBuilder(retrospect.member.memberId.eq(memberId)); + else return new BooleanBuilder(); + } + private BooleanBuilder containWordInAnswer(String word) { if(hasText(word)) return new BooleanBuilder(retrospectContent.answer.contains(word)); else return new BooleanBuilder(); diff --git a/src/main/java/com/nanal/backend/domain/search/service/SearchService.java b/src/main/java/com/nanal/backend/domain/search/service/SearchService.java index 74869b70..8133974d 100644 --- a/src/main/java/com/nanal/backend/domain/search/service/SearchService.java +++ b/src/main/java/com/nanal/backend/domain/search/service/SearchService.java @@ -1,5 +1,7 @@ package com.nanal.backend.domain.search.service; +import com.nanal.backend.domain.auth.entity.Member; +import com.nanal.backend.domain.auth.repository.MemberRepository; import com.nanal.backend.domain.diary.entity.Diary; import com.nanal.backend.domain.retrospect.entity.Retrospect; import com.nanal.backend.domain.search.dto.req.ReqSearchDto; @@ -19,18 +21,20 @@ @Service public class SearchService { + private final MemberRepository memberRepository; private final SearchDiaryRepository searchDiaryRepository; private final SearchRetrospectRepository searchRetrospectRepository; - public RespSearchDto search(ReqSearchDto reqSearchDto) { + public RespSearchDto search(String socialId, ReqSearchDto reqSearchDto) { + Member member = memberRepository.findMember(socialId); // 일기 검색 - List diaryList = searchDiaryRepository.searchDiary(reqSearchDto); - Integer nextDiaryCount = searchDiaryRepository.countLeftDiary(reqSearchDto); + List diaryList = searchDiaryRepository.searchDiary(reqSearchDto, member.getMemberId()); + Integer nextDiaryCount = searchDiaryRepository.countLeftDiary(reqSearchDto, member.getMemberId()); // 회고 검색 - List retrospectList = searchRetrospectRepository.searchRetrospect(reqSearchDto); - Integer nextRetrospectCount = searchRetrospectRepository.countLeftRetrospect(reqSearchDto); + List retrospectList = searchRetrospectRepository.searchRetrospect(reqSearchDto, member.getMemberId()); + Integer nextRetrospectCount = searchRetrospectRepository.countLeftRetrospect(reqSearchDto, member.getMemberId()); return new RespSearchDto(reqSearchDto.getSearchWord(), diaryList, retrospectList, nextDiaryCount, nextRetrospectCount); } diff --git a/src/main/resources/static/docs/Alarm-API.html b/src/main/resources/static/docs/Alarm-API.html index f7209143..981656ca 100644 --- a/src/main/resources/static/docs/Alarm-API.html +++ b/src/main/resources/static/docs/Alarm-API.html @@ -648,7 +648,7 @@

    Response fields

    diff --git a/src/main/resources/static/docs/Auth-API.html b/src/main/resources/static/docs/Auth-API.html index ed6765d6..65f07196 100644 --- a/src/main/resources/static/docs/Auth-API.html +++ b/src/main/resources/static/docs/Auth-API.html @@ -1029,7 +1029,7 @@

    Response fields

    diff --git a/src/main/resources/static/docs/Diary-API.html b/src/main/resources/static/docs/Diary-API.html index 4ba70ab8..c69b01cd 100644 --- a/src/main/resources/static/docs/Diary-API.html +++ b/src/main/resources/static/docs/Diary-API.html @@ -1305,7 +1305,7 @@

    Response fields

    diff --git a/src/main/resources/static/docs/MyPage-API.html b/src/main/resources/static/docs/MyPage-API.html index d43ee9e8..96d0118a 100644 --- a/src/main/resources/static/docs/MyPage-API.html +++ b/src/main/resources/static/docs/MyPage-API.html @@ -1275,7 +1275,7 @@

    Response fields

    diff --git a/src/main/resources/static/docs/OnBoarding-API.html b/src/main/resources/static/docs/OnBoarding-API.html index d0ffbbba..85e2cc6d 100644 --- a/src/main/resources/static/docs/OnBoarding-API.html +++ b/src/main/resources/static/docs/OnBoarding-API.html @@ -542,7 +542,7 @@

    Response fields diff --git a/src/main/resources/static/docs/Overview.html b/src/main/resources/static/docs/Overview.html index 63231be7..0cc994e8 100644 --- a/src/main/resources/static/docs/Overview.html +++ b/src/main/resources/static/docs/Overview.html @@ -659,7 +659,7 @@

    Retrospect Status Codes

    diff --git a/src/main/resources/static/docs/Retrospect-API.html b/src/main/resources/static/docs/Retrospect-API.html index 7bf42051..ca179ced 100644 --- a/src/main/resources/static/docs/Retrospect-API.html +++ b/src/main/resources/static/docs/Retrospect-API.html @@ -2017,7 +2017,7 @@

    Response fields

    diff --git a/src/main/resources/static/docs/Search-API.html b/src/main/resources/static/docs/Search-API.html index 055d5e8f..1c2aaa81 100644 --- a/src/main/resources/static/docs/Search-API.html +++ b/src/main/resources/static/docs/Search-API.html @@ -665,7 +665,7 @@

    Response fields

    diff --git a/src/main/resources/static/docs/Sponsor-API.html b/src/main/resources/static/docs/Sponsor-API.html index ca538809..19e2673c 100644 --- a/src/main/resources/static/docs/Sponsor-API.html +++ b/src/main/resources/static/docs/Sponsor-API.html @@ -563,7 +563,7 @@ diff --git a/src/main/resources/static/docs/api.html b/src/main/resources/static/docs/api.html index d34e82ac..026eea97 100644 --- a/src/main/resources/static/docs/api.html +++ b/src/main/resources/static/docs/api.html @@ -5234,7 +5234,7 @@