diff --git a/Backend-feedme/feedme/.gitignore b/Backend-feedme/feedme/.gitignore new file mode 100644 index 0000000..4125023 --- /dev/null +++ b/Backend-feedme/feedme/.gitignore @@ -0,0 +1,39 @@ +HELP.md +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +.env + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ diff --git a/Backend-feedme/feedme/Dockerfile b/Backend-feedme/feedme/Dockerfile index 58c8dbd..bcedaa9 100644 --- a/Backend-feedme/feedme/Dockerfile +++ b/Backend-feedme/feedme/Dockerfile @@ -27,4 +27,4 @@ RUN ./gradlew clean build -x test ENTRYPOINT ["java", "-jar", "-Dspring.profiles.active=prod", "/app/build/libs/feedme-0.0.1-SNAPSHOT.jar"] # Expose port 8080 -EXPOSE 8080 +EXPOSE 8085 diff --git a/Backend-feedme/feedme/build.gradle b/Backend-feedme/feedme/build.gradle index ec92ef2..bed2937 100644 --- a/Backend-feedme/feedme/build.gradle +++ b/Backend-feedme/feedme/build.gradle @@ -37,18 +37,31 @@ dependencies { // table 보이기 implementation("com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.9.1") - //스웨거 안됌 ㅠ - implementation 'org.springdoc:springdoc-openapi-ui:1.7.0' - implementation 'org.springdoc:springdoc-openapi-data-rest:1.7.0' - implementation 'org.springdoc:springdoc-openapi-security:1.7.0' + // 시큐리티 설정 + implementation 'org.springframework.boot:spring-boot-starter-security' + implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6' + testImplementation 'org.springframework.security:spring-security-test' - implementation 'io.springfox:springfox-boot-starter:3.0.0' - implementation 'io.springfox:springfox-swagger-ui:3.0.0' - //스웨거 끝 + //스웨거 + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0' //MongoDB implementation 'org.springframework.boot:spring-boot-starter-data-mongodb' + //JWT + testImplementation 'org.projectlombok:lombok' + implementation 'io.jsonwebtoken:jjwt:0.9.1' + implementation 'javax.xml.bind:jaxb-api:2.3.1' + + //OAuth 2.0 + implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' + + //redis + implementation 'org.springframework.boot:spring-boot-starter-data-redis' + + // .env 받아오기 + implementation 'io.github.cdimascio:java-dotenv:5.2.2' + //JUnit4 추가 testImplementation("org.junit.vintage:junit-vintage-engine") { exclude group: "org.hamcrest", module: "hamcrest-core" diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/AlarmResponseDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/AlarmResponseDTO.java new file mode 100644 index 0000000..0d86140 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/AlarmResponseDTO.java @@ -0,0 +1,10 @@ +package com.todoslave.feedme.DTO; + +import lombok.Data; + +@Data +public class AlarmResponseDTO { + + private String content; + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/AlarmSetRequestDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/AlarmSetRequestDTO.java new file mode 100644 index 0000000..bf6069c --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/AlarmSetRequestDTO.java @@ -0,0 +1,10 @@ +package com.todoslave.feedme.DTO; + +import lombok.Getter; + +@Getter +public class AlarmSetRequestDTO { + + int alarmTime; + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/CreatureInfoResponseDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/CreatureInfoResponseDTO.java new file mode 100644 index 0000000..e52f952 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/CreatureInfoResponseDTO.java @@ -0,0 +1,16 @@ +package com.todoslave.feedme.DTO; + +import lombok.Data; + +import java.sql.Timestamp; + +@Data +public class CreatureInfoResponseDTO { + + private String name; + private String img; + private int level; + private int exp; + private int day; + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/CreatureMakeRequestDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/CreatureMakeRequestDTO.java new file mode 100644 index 0000000..555eeae --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/CreatureMakeRequestDTO.java @@ -0,0 +1,16 @@ +package com.todoslave.feedme.DTO; + +import lombok.Data; + +@Data +public class CreatureMakeRequestDTO { + + String creatureName; + + String keyword; + + // AI 구현시 이걸로 바꿔야함 + // MultipartFile photo; + String photo; + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/CreatureTodoDailyRequestDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/CreatureTodoDailyRequestDTO.java new file mode 100644 index 0000000..c17e561 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/CreatureTodoDailyRequestDTO.java @@ -0,0 +1,13 @@ +package com.todoslave.feedme.DTO; + +import lombok.Data; + +import java.time.LocalDate; + +@Data +public class CreatureTodoDailyRequestDTO { + + private LocalDate date; + private int next; + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/CreatureTodoResponseDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/CreatureTodoResponseDTO.java new file mode 100644 index 0000000..1f66343 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/CreatureTodoResponseDTO.java @@ -0,0 +1,16 @@ +package com.todoslave.feedme.DTO; + +import lombok.Builder; +import lombok.Data; + +import java.time.LocalDate; + +@Builder +@Data +public class CreatureTodoResponseDTO { + private int id; + private String content; + private LocalDate createdAt; + private int isCompleted; +// private boolean diaryIsCompleted; +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/CretureTodoRequestDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/CretureTodoRequestDTO.java new file mode 100644 index 0000000..b8e8784 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/CretureTodoRequestDTO.java @@ -0,0 +1,11 @@ +package com.todoslave.feedme.DTO; + +import lombok.Data; + +import java.time.LocalDate; + +@Data +public class CretureTodoRequestDTO { + private LocalDate date; + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/DiaryRequestDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/DiaryRequestDTO.java new file mode 100644 index 0000000..a1a54c8 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/DiaryRequestDTO.java @@ -0,0 +1,11 @@ +package com.todoslave.feedme.DTO; + +import lombok.Data; + + +@Data +public class DiaryRequestDTO { + + private int skip; + private int limit; +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/DiaryResponseDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/DiaryResponseDTO.java new file mode 100644 index 0000000..bc1c07f --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/DiaryResponseDTO.java @@ -0,0 +1,14 @@ +package com.todoslave.feedme.DTO; + +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class DiaryResponseDTO { + + private String content; + private LocalDateTime createdAt; + private String diaryImg; + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/FeedCommentDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/FeedCommentDTO.java new file mode 100644 index 0000000..bb738f4 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/FeedCommentDTO.java @@ -0,0 +1,14 @@ +package com.todoslave.feedme.DTO; + +import lombok.Data; + +import java.util.List; + +@Data +public class FeedCommentDTO { + private String email; + private int feedComentId; + private String nickname; + private String comment; + private String time; +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/FeedCommentRequestDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/FeedCommentRequestDTO.java new file mode 100644 index 0000000..cb54d06 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/FeedCommentRequestDTO.java @@ -0,0 +1,8 @@ +package com.todoslave.feedme.DTO; + +import lombok.Data; + +@Data +public class FeedCommentRequestDTO { + private String content; +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/FeedCommentResponseDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/FeedCommentResponseDTO.java new file mode 100644 index 0000000..d40ad8f --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/FeedCommentResponseDTO.java @@ -0,0 +1,12 @@ +package com.todoslave.feedme.DTO; + +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class FeedCommentResponseDTO { + private String nickname; + private String content; + private LocalDateTime createdAt; +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/FeedDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/FeedDTO.java new file mode 100644 index 0000000..f6d6f03 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/FeedDTO.java @@ -0,0 +1,21 @@ +package com.todoslave.feedme.DTO; + +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; + +@Data +public class FeedDTO { + private int feedId; + private String email; + private String nickname; + private String img; + private String caption; + private LocalDateTime lastCreateTime; + private int likes; + private boolean myLike; + + private List comments; + } + diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/FeedModifyRequest.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/FeedModifyRequest.java new file mode 100644 index 0000000..effca46 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/FeedModifyRequest.java @@ -0,0 +1,8 @@ +package com.todoslave.feedme.DTO; + +import lombok.Data; + +@Data +public class FeedModifyRequest { + private String content; +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/FeedReplyDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/FeedReplyDTO.java new file mode 100644 index 0000000..a170504 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/FeedReplyDTO.java @@ -0,0 +1,10 @@ +package com.todoslave.feedme.DTO; + +import lombok.Data; + +@Data +public class FeedReplyDTO { + private String name; + private String comment; + private String time; +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/FeedRequestDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/FeedRequestDTO.java new file mode 100644 index 0000000..aab1a27 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/FeedRequestDTO.java @@ -0,0 +1,14 @@ +package com.todoslave.feedme.DTO; + +import lombok.Data; + +import java.time.LocalDate; + +@Data +public class FeedRequestDTO { + + private LocalDate diaryDate; //언제 + + private String content; + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/FeedResponseDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/FeedResponseDTO.java new file mode 100644 index 0000000..7b688d2 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/FeedResponseDTO.java @@ -0,0 +1,20 @@ +package com.todoslave.feedme.DTO; + +import lombok.Data; + +import java.sql.Timestamp; +import java.time.LocalDateTime; + + +@Data +public class FeedResponseDTO { + + private int id; + private String img; + private String content; + private String author; + private String likeCnt; + + private LocalDateTime createdAt; + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/FriendInfoResponseDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/FriendInfoResponseDTO.java new file mode 100644 index 0000000..955399d --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/FriendInfoResponseDTO.java @@ -0,0 +1,16 @@ +package com.todoslave.feedme.DTO; + +import lombok.Data; + +@Data +public class FriendInfoResponseDTO { + + private int friendId; + private String nickname; + private String creatureNickname; + private String creatureImg; + private int level; + private int exp; + private int join; + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/FriendReqResponseDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/FriendReqResponseDTO.java new file mode 100644 index 0000000..98530b0 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/FriendReqResponseDTO.java @@ -0,0 +1,17 @@ +package com.todoslave.feedme.DTO; + +import lombok.Data; + +@Data +public class FriendReqResponseDTO { + + // 친구 요청 ID + private int id; + + // 상대방 닉네임 + private String counterpartNickname; + + // 상대방 크리쳐 이미지 + private String creatureImg; + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/FriendRequestDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/FriendRequestDTO.java new file mode 100644 index 0000000..3a503d8 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/FriendRequestDTO.java @@ -0,0 +1,12 @@ +package com.todoslave.feedme.DTO; + +import lombok.Data; +import lombok.Getter; + +@Data +public class FriendRequestDTO { + + // 상대방 닉네임 + private String counterpartNickname; + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/FriendResponseDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/FriendResponseDTO.java new file mode 100644 index 0000000..5583183 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/FriendResponseDTO.java @@ -0,0 +1,12 @@ +package com.todoslave.feedme.DTO; + +import lombok.Data; + +@Data +public class FriendResponseDTO { + + private int friendId; + private String counterpartNickname; + private String creatureimg; + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/MemberChatBuildRequestDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/MemberChatBuildRequestDTO.java new file mode 100644 index 0000000..feb0393 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/MemberChatBuildRequestDTO.java @@ -0,0 +1,10 @@ +package com.todoslave.feedme.DTO; + +import lombok.Getter; + +@Getter +public class MemberChatBuildRequestDTO { + + private String CounterpartNickname; + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/MemberChatListResponseDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/MemberChatListResponseDTO.java new file mode 100644 index 0000000..2d69028 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/MemberChatListResponseDTO.java @@ -0,0 +1,17 @@ +package com.todoslave.feedme.DTO; + +import lombok.Data; + +@Data +public class MemberChatListResponseDTO { + + // 방 번호 + private String id; + // 상대방 닉네임 + private String nickname; + // 상대방 크리쳐 이미지 + private String creatureImage; + // 최근에 채팅방 읽었는 지 확인 + private int isChecked; + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/MemberChatMessageRequestDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/MemberChatMessageRequestDTO.java new file mode 100644 index 0000000..2c64ec4 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/MemberChatMessageRequestDTO.java @@ -0,0 +1,10 @@ +package com.todoslave.feedme.DTO; + +import lombok.Getter; + +@Getter +public class MemberChatMessageRequestDTO { + + private String message; + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/MemberChatMessageResponseDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/MemberChatMessageResponseDTO.java new file mode 100644 index 0000000..b2a046d --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/MemberChatMessageResponseDTO.java @@ -0,0 +1,15 @@ +package com.todoslave.feedme.DTO; + +import java.time.LocalDateTime; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +public class MemberChatMessageResponseDTO { + + private String sendNickname; // 보내는 사람 닉네임 + private String message; // 메세지 내용 + private LocalDateTime transmitAt; // 전송 시간 + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/MemberChatRenewResponseDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/MemberChatRenewResponseDTO.java new file mode 100644 index 0000000..a70dd44 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/MemberChatRenewResponseDTO.java @@ -0,0 +1,10 @@ +package com.todoslave.feedme.DTO; + +public class MemberChatRenewResponseDTO { + + private int roomId; + private String message; + private int counterpartId; + private int isChecked; + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/MemberSearchRequestDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/MemberSearchRequestDTO.java new file mode 100644 index 0000000..7a9b9a7 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/MemberSearchRequestDTO.java @@ -0,0 +1,7 @@ +package com.todoslave.feedme.DTO; + +public class MemberSearchRequestDTO { + + // STring 이라서 굳이 안쓸듯 + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/MemberSearchResponseDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/MemberSearchResponseDTO.java new file mode 100644 index 0000000..f581e29 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/MemberSearchResponseDTO.java @@ -0,0 +1,11 @@ +package com.todoslave.feedme.DTO; + +import lombok.Data; + +@Data +public class MemberSearchResponseDTO { + String nickname; + boolean isFriend; + boolean isRequested; + String creatureImg; +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/MemberSignup.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/MemberSignup.java new file mode 100644 index 0000000..40732c0 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/MemberSignup.java @@ -0,0 +1,18 @@ +package com.todoslave.feedme.DTO; + +import lombok.Data; + +import java.sql.Timestamp; + +@Data +public class MemberSignup { + + String email; + + String nickname; + + String userRole; + + Timestamp birthday; + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/MemberSignupRequestDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/MemberSignupRequestDTO.java new file mode 100644 index 0000000..9af8a4e --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/MemberSignupRequestDTO.java @@ -0,0 +1,18 @@ +package com.todoslave.feedme.DTO; + +import lombok.Data; + +import java.sql.Timestamp; + +@Data +public class MemberSignupRequestDTO { + + String email; + + String nickname; + + String userRole = "ROLE_USER"; + + Timestamp birthday; + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/MypageResponseDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/MypageResponseDTO.java new file mode 100644 index 0000000..f76088a --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/MypageResponseDTO.java @@ -0,0 +1,18 @@ +package com.todoslave.feedme.DTO; + +import lombok.Data; + +import java.time.LocalDate; +@Data +public class MypageResponseDTO { + private String nickname; + private String email; + private LocalDate brithday; + + private int creatureId; + private String creatureName; + private int exp; + private int level; + private String image; + private int togetherDay; +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/PaginationRequest.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/PaginationRequestDTO.java similarity index 74% rename from Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/PaginationRequest.java rename to Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/PaginationRequestDTO.java index 86abedc..ab96fdf 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/PaginationRequest.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/PaginationRequestDTO.java @@ -3,7 +3,7 @@ import lombok.Data; @Data -public class PaginationRequest { +public class PaginationRequestDTO { private int skip; private int limit; diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/TodoCalendarResponseDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/TodoCalendarResponseDTO.java new file mode 100644 index 0000000..c2d5407 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/TodoCalendarResponseDTO.java @@ -0,0 +1,14 @@ +package com.todoslave.feedme.DTO; + +import java.time.LocalDate; +import lombok.Data; + +@Data +public class TodoCalendarResponseDTO { + + private LocalDate date; + private int inCompleted; + private int completed; + private int total; + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/TodoCategoryRequestDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/TodoCategoryRequestDTO.java new file mode 100644 index 0000000..bae5591 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/TodoCategoryRequestDTO.java @@ -0,0 +1,11 @@ +package com.todoslave.feedme.DTO; + +import lombok.Getter; + +@Getter +public class TodoCategoryRequestDTO { + + private int id; + private String name; + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/TodoCategoryResponseDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/TodoCategoryResponseDTO.java new file mode 100644 index 0000000..7a1db39 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/TodoCategoryResponseDTO.java @@ -0,0 +1,11 @@ +package com.todoslave.feedme.DTO; + +import lombok.Data; + +@Data +public class TodoCategoryResponseDTO { + + private int id; + private String name; + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/TodoCreateRequestDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/TodoCreateRequestDTO.java new file mode 100644 index 0000000..d84c44a --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/TodoCreateRequestDTO.java @@ -0,0 +1,12 @@ +package com.todoslave.feedme.DTO; + +import lombok.Data; +import lombok.Getter; + +@Data +public class TodoCreateRequestDTO { + + private String content; + private int categoryId; + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/TodoDailyRequestDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/TodoDailyRequestDTO.java new file mode 100644 index 0000000..31571f5 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/TodoDailyRequestDTO.java @@ -0,0 +1,14 @@ +package com.todoslave.feedme.DTO; + +import java.time.LocalDate; + +import lombok.Data; +import lombok.Getter; + +@Data +public class TodoDailyRequestDTO { + + private LocalDate date; + private int next; + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/TodoMainResponseDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/TodoMainResponseDTO.java new file mode 100644 index 0000000..a5c3618 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/TodoMainResponseDTO.java @@ -0,0 +1,12 @@ +package com.todoslave.feedme.DTO; + +import lombok.Data; + +@Data +public class TodoMainResponseDTO { + + private int id; + private String content; + private int isCompleted; + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/TodoModifyRequestDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/TodoModifyRequestDTO.java new file mode 100644 index 0000000..eab8bf4 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/TodoModifyRequestDTO.java @@ -0,0 +1,12 @@ +package com.todoslave.feedme.DTO; + +import lombok.Data; +import lombok.Getter; + +@Data +public class TodoModifyRequestDTO { + + private int id; + private String content; + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/TodoRequestDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/TodoRequestDTO.java new file mode 100644 index 0000000..c2d2bad --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/TodoRequestDTO.java @@ -0,0 +1,13 @@ +package com.todoslave.feedme.DTO; + +import java.time.LocalDate; + +import lombok.Data; +import lombok.Getter; + +@Data +public class TodoRequestDTO { + + private LocalDate date; + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/TodoResponseDTO.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/TodoResponseDTO.java new file mode 100644 index 0000000..382a3d0 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/DTO/TodoResponseDTO.java @@ -0,0 +1,16 @@ +package com.todoslave.feedme.DTO; + +import java.time.LocalDate; +import lombok.Data; + +@Data +public class TodoResponseDTO { + + private int id; + private int categoryId; + private String categoryName; + private String content; + private LocalDate createdAt; + private int isCompleted; + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/FeedmeApplication.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/FeedmeApplication.java index 98e61a1..abe624d 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/FeedmeApplication.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/FeedmeApplication.java @@ -1,13 +1,8 @@ package com.todoslave.feedme; -import com.todoslave.feedme.domain.entity.membership.Emotion; -import com.todoslave.feedme.domain.entity.membership.Member; -import com.todoslave.feedme.service.MemberService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.CommandLineRunner; +import io.github.cdimascio.dotenv.Dotenv; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; import org.springframework.scheduling.annotation.EnableScheduling; @@ -16,32 +11,21 @@ @EnableJpaRepositories(basePackages = "com.todoslave.feedme.repository") @EnableMongoRepositories(basePackages = "com.todoslave.feedme.repository") @EnableScheduling -public class FeedmeApplication implements CommandLineRunner { - - private final MemberService memberService; - - @Autowired - public FeedmeApplication(MemberService memberService) { - this.memberService = memberService; - } +public class FeedmeApplication { public static void main(String[] args) { + // Load environment variables from .env file + Dotenv dotenv = Dotenv.load(); + System.setProperty("NAVER_CLIENT_ID", dotenv.get("NAVER_CLIENT_ID")); + System.setProperty("NAVER_CLIENT_SECRET", dotenv.get("NAVER_CLIENT_SECRET")); + System.setProperty("KAKAO_CLIENT_ID", dotenv.get("KAKAO_CLIENT_ID")); + System.setProperty("KAKAO_CLIENT_SECRET", dotenv.get("KAKAO_CLIENT_SECRET")); + System.setProperty("DB_USERNAME", dotenv.get("DB_USERNAME")); + System.setProperty("DB_PASSWORD", dotenv.get("DB_PASSWORD")); + System.setProperty("JWT_SECRET_KEY", dotenv.get("JWT_SECRET_KEY")); + + // Run the Spring Boot application SpringApplication.run(FeedmeApplication.class, args); } - @Override - public void run(String... args) throws Exception { - Member member = new Member(); - - member.setEmail("asdf@gmail.com"); - member.setToken("ABC"); - member.setExp(0); - member.setStatus(Emotion.SAD); - member.setNickname("테스트1"); - member.setLatitude(12.4); - member.setLongitude(12.4); - - int saveId = memberService.Join(member); - System.out.println("Member saved with ID: " + saveId); - } } diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/Hello.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/Hello.java deleted file mode 100644 index 0a12b4d..0000000 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/Hello.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.todoslave.feedme; - -import lombok.Getter; -import lombok.Setter; - -@Getter @Setter -public class Hello { - - private String data; - -} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/CorsConfig.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/CorsConfig.java index 249fe63..df77c03 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/CorsConfig.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/CorsConfig.java @@ -11,9 +11,10 @@ public class CorsConfig implements WebMvcConfigurer{ @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") - .allowedOrigins("http://localhost:8080", "null") // 'null' 오리진 허용 + .allowedOrigins("https://i11b104.p.ssafy.io/api/", "https://i11b104.p.ssafy.io") // 'null' 오리진 허용 .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") .allowedHeaders("*") .allowCredentials(true); } } + diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/SwaggerConfig.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/SwaggerConfig.java index 160550d..104259e 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/SwaggerConfig.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/SwaggerConfig.java @@ -1,18 +1,35 @@ package com.todoslave.feedme.config; +import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.security.SecurityRequirement; +import io.swagger.v3.oas.models.security.SecurityScheme; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class SwaggerConfig { - @Bean - public OpenAPI customOpenAPI() { + public OpenAPI openAPI() { + String jwt = "JWT"; + SecurityRequirement securityRequirement = new SecurityRequirement().addList(jwt); + Components components = new Components().addSecuritySchemes(jwt, new SecurityScheme() + .name(jwt) + .type(SecurityScheme.Type.HTTP) + .scheme("bearer") + .bearerFormat("JWT") + ); return new OpenAPI() - .info(new Info().title("Feedme API") - .version("1.0") - .description("Feedme API documentation")); + .components(new Components()) + .info(apiInfo()) + .addSecurityItem(securityRequirement) + .components(components); + } + private Info apiInfo() { + return new Info() + .title("API Test") // API의 제목 + .description("Let's practice Swagger UI") // API에 대한 설명 + .version("1.0.0"); // API의 버전 } } diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/TransactionManagerConfig.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/TransactionManagerConfig.java index ec9ce04..3135b43 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/TransactionManagerConfig.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/TransactionManagerConfig.java @@ -1,17 +1,17 @@ -package com.todoslave.feedme.config; - - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.jdbc.datasource.DataSourceTransactionManager; - -import javax.sql.DataSource; - -@Configuration -public class TransactionManagerConfig { - - @Bean - public DataSourceTransactionManager transactionManager(DataSource dataSource) { - return new DataSourceTransactionManager(dataSource); - } -} +//package com.todoslave.feedme.config; +// +// +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Configuration; +//import org.springframework.jdbc.datasource.DataSourceTransactionManager; +// +//import javax.sql.DataSource; +// +//@Configuration +//public class TransactionManagerConfig { +// +// @Bean +// public DataSourceTransactionManager transactionManager(DataSource dataSource) { +// return new DataSourceTransactionManager(dataSource); +// } +//} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/WebSocketConfig.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/WebSocketConfig.java index aa43205..02b3f18 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/WebSocketConfig.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/WebSocketConfig.java @@ -1,3 +1,30 @@ +//package com.todoslave.feedme.config; +// +//import org.springframework.context.annotation.Configuration; +//import org.springframework.messaging.simp.config.MessageBrokerRegistry; +//import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; +//import org.springframework.web.socket.config.annotation.StompEndpointRegistry; +//import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; +// +//@Configuration +//@EnableWebSocketMessageBroker +//public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { +// +// @Override +// public void configureMessageBroker(MessageBrokerRegistry config) { +// config.enableSimpleBroker("/chatting", "/chatRoom"); +// config.setApplicationDestinationPrefixes("/chat"); +// } +// +// @Override +// public void registerStompEndpoints(StompEndpointRegistry registry) { +// registry.addEndpoint("/friendChat") +// .setAllowedOriginPatterns("http://localhost:8080","null") // 명시적인 오리진 사용 +// .withSockJS(); +// } +//} + +//0810 진기가 보내준 파일 package com.todoslave.feedme.config; import org.springframework.context.annotation.Configuration; @@ -18,8 +45,10 @@ public void configureMessageBroker(MessageBrokerRegistry config) { @Override public void registerStompEndpoints(StompEndpointRegistry registry) { - registry.addEndpoint("/friendChat") - .setAllowedOriginPatterns("http://localhost:8080", "null") // 명시적인 오리진 사용 + registry.addEndpoint("/ws/friendChat") + + .setAllowedOriginPatterns("*") .withSockJS(); + } -} +} \ No newline at end of file diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/gpt/OpenAiConfig.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/gpt/OpenAiConfig.java new file mode 100644 index 0000000..b771919 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/gpt/OpenAiConfig.java @@ -0,0 +1,21 @@ +package com.todoslave.feedme.config.gpt; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; + +@Configuration +public class OpenAiConfig { + @Value("${openai.api.key}") + private String openAiKey; + @Bean + public RestTemplate template(){ + RestTemplate restTemplate = new RestTemplate(); + restTemplate.getInterceptors().add((request, body, execution) -> { + request.getHeaders().add("Authorization", "Bearer " + openAiKey); + return execution.execute(request, body); + }); + return restTemplate; + } +} \ No newline at end of file diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/jwt/JwtProperties.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/jwt/JwtProperties.java new file mode 100644 index 0000000..66072f4 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/jwt/JwtProperties.java @@ -0,0 +1,17 @@ +package com.todoslave.feedme.config.jwt; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +@Setter +@Getter +@Component +@ConfigurationProperties("jwt") +public class JwtProperties { + + private String issuer; + private String secretKey; +} + diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/security/RedisConfig.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/security/RedisConfig.java new file mode 100644 index 0000000..7f73431 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/security/RedisConfig.java @@ -0,0 +1,42 @@ +package com.todoslave.feedme.config.security; + +import lombok.RequiredArgsConstructor; +import org.springframework.boot.autoconfigure.data.redis.RedisProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.connection.RedisStandaloneConfiguration; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.repository.configuration.EnableRedisRepositories; + +@Configuration +@EnableRedisRepositories +@RequiredArgsConstructor +public class RedisConfig { + + private final RedisProperties redisProperties; + + @Bean + public RedisConnectionFactory redisConnectionFactory() { + RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(); + redisStandaloneConfiguration.setHostName(redisProperties.getHost()); + redisStandaloneConfiguration.setPort(redisProperties.getPort()); + redisStandaloneConfiguration.setPassword(redisProperties.getPassword()); + return new LettuceConnectionFactory(redisStandaloneConfiguration); + } + + @Bean + public RedisTemplate redisTemplate() { + + // redisTemplate 를 받아와서 set, get, delete 를 사용 + RedisTemplate redisTemplate = new RedisTemplate<>(); + /* + * setKeySerializer, setValueSerializer 설정 + * redis-cli 을 통해 직접 데이터를 조회 시 알아볼 수 없는 형태로 출력되는 것을 방지 + */ + redisTemplate.setConnectionFactory(redisConnectionFactory()); + + return redisTemplate; + } +} \ No newline at end of file diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/security/RedisProperties.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/security/RedisProperties.java new file mode 100644 index 0000000..b51f69a --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/security/RedisProperties.java @@ -0,0 +1,15 @@ +package com.todoslave.feedme.config.security; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +@Data +@Component +@ConfigurationProperties(prefix = "spring.redis") +public class RedisProperties { + + private String host; + private int port; + private String password; +} \ No newline at end of file diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/security/SecurityConfig.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/security/SecurityConfig.java new file mode 100644 index 0000000..23aa5db --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/security/SecurityConfig.java @@ -0,0 +1,79 @@ +package com.todoslave.feedme.config.security; + +import com.todoslave.feedme.config.security.filter.JwtAuthFilter; +import com.todoslave.feedme.config.security.filter.JwtExceptionFilter; +import com.todoslave.feedme.login.Handler.MyAuthenticationFailureHandler; +import com.todoslave.feedme.login.Handler.MyAuthenticationSuccessHandler; +import com.todoslave.feedme.login.Service.CustomOAuth2UserService; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.Customizer; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.CsrfConfigurer; +import org.springframework.security.config.annotation.web.configurers.HttpBasicConfigurer; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.CorsConfigurationSource; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; + +@Configuration +@EnableWebSecurity +@RequiredArgsConstructor +public class SecurityConfig { + private final MyAuthenticationSuccessHandler oAuth2LoginSuccessHandler; + private final CustomOAuth2UserService customOAuth2UserService; + private final JwtAuthFilter jwtAuthFilter; + private final MyAuthenticationFailureHandler oAuth2LoginFailureHandler; + private final JwtExceptionFilter jwtExceptionFilter; + + @Bean + public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + + http.httpBasic(HttpBasicConfigurer::disable) + .csrf(CsrfConfigurer::disable) + .cors(Customizer.withDefaults()) + + .sessionManagement(configurer -> configurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) +// .sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 세션관리 정책을 STATELESS(세션이 있으면 쓰지도 않고, 없으면 만들지도 않는다) + .authorizeHttpRequests((requests) -> requests + .requestMatchers("/token/**", "/bot/**").permitAll() + .requestMatchers("/", "/css/**", "/images/**", "/js/**", "/favicon.ico", "/h2-console/**").permitAll() + .requestMatchers("/login/oauth2/code/**", "/login/**", "/testsite", "/signup", "/user", "/v3/api-docs/**", + "/swagger-ui/**", "/creature", "/swagger-ui.html", "/users/**").permitAll() // 유저 설정 + .requestMatchers("/ws/**").permitAll() + .anyRequest().authenticated() + ) + .oauth2Login(oauth2 -> oauth2 + .loginPage("https://i11b104.p.ssafy.io") + .userInfoEndpoint(userInfo -> userInfo.userService(customOAuth2UserService)) // OAuth2 로그인시 사용자 정보를 가져오는 엔드포인트와 사용자 서비스를 설정 + .failureHandler(oAuth2LoginFailureHandler) // OAuth2 로그인 실패시 처리할 핸들러를 지정해준다. + .successHandler(oAuth2LoginSuccessHandler) // OAuth2 로그인 성공시 처리할 핸들러를 지정해준다. + ); + + + // JWT 인증 필터를 UsernamePasswordAuthenticationFilter 앞에 추가한다. + return http.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class) + .addFilterBefore(jwtExceptionFilter, JwtAuthFilter.class) + .build(); + } + + + @Bean + // CORS 설정 + CorsConfigurationSource corsConfigurationSource() { + CorsConfiguration configuration = new CorsConfiguration(); + configuration.addAllowedOrigin("https://i11b104.p.ssafy.io"); // 특정 도메인 허용 + configuration.addAllowedOriginPattern("*"); + configuration.addAllowedMethod("*"); // 모든 HTTP 메서드 허용 + configuration.addAllowedHeader("*"); // 모든 헤더 허용 + configuration.setAllowCredentials(true); // 자격 증명 허용 설정 + + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", configuration); // 모든 경로에 대해 CORS 구성 적용 + return source; + } +} \ No newline at end of file diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/security/StatusResponseDto.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/security/StatusResponseDto.java new file mode 100644 index 0000000..319b656 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/security/StatusResponseDto.java @@ -0,0 +1,29 @@ +package com.todoslave.feedme.config.security; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.AllArgsConstructor; + +import lombok.Getter; + +@Getter +@AllArgsConstructor +@JsonInclude(JsonInclude.Include.NON_NULL) // DTO 를 JSON으로 변환 시 null값인 field 제외 +public class StatusResponseDto { + private Integer status; + private Object data; + + public StatusResponseDto(Integer status) { + this.status = status; + } + + public static StatusResponseDto addStatus(Integer status) { + return new StatusResponseDto(status); + } + + public static StatusResponseDto success(){ + return new StatusResponseDto(200); + } + public static StatusResponseDto success(Object data){ + return new StatusResponseDto(200, data); + } +} \ No newline at end of file diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/security/WebConfig.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/security/WebConfig.java new file mode 100644 index 0000000..37973e3 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/security/WebConfig.java @@ -0,0 +1,24 @@ +//package com.todoslave.feedme.config.security; +// +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Configuration; +//import org.springframework.web.servlet.config.annotation.CorsRegistry; +//import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +// +//@Configuration +//public class WebConfig { +// +// @Bean +// public WebMvcConfigurer corsConfigurer() { +// return new WebMvcConfigurer() { +// @Override +// public void addCorsMappings(CorsRegistry registry) { +// registry.addMapping("/**") +// .allowedOrigins("http://localhost:3000") +// .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") +// .allowedHeaders("*") +// .allowCredentials(true); +// } +// }; +// } +//} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/security/WebSecurityConfig.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/security/WebSecurityConfig.java new file mode 100644 index 0000000..a3f0ba1 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/security/WebSecurityConfig.java @@ -0,0 +1,297 @@ + ////package com.todoslave.feedme.config.security; +////// +//////import com.todoslave.feedme.service.UserDetailService; +//////import lombok.RequiredArgsConstructor; +//////import org.springframework.context.annotation.Bean; +//////import org.springframework.context.annotation.Configuration; +//////import org.springframework.security.authentication.AuthenticationManager; +//////import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +//////import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; +//////import org.springframework.security.config.annotation.web.builders.HttpSecurity; +//////import org.springframework.security.core.userdetails.UserDetailsService; +//////import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +//////import org.springframework.security.web.SecurityFilterChain; +//////import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +//////import org.springframework.web.servlet.config.annotation.CorsRegistry; +//////import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +////// +//////@RequiredArgsConstructor +//////@Configuration +//////public class WebSecurityConfig { +////// +////// private final UserDetailService userService; +////// +//////// @Bean //CORS 설정 +//////// public WebMvcConfigurer corsConfigurer() { +//////// return new WebMvcConfigurer() { +//////// @Override +//////// public void addCorsMappings(CorsRegistry registry) { +//////// registry.addMapping("/**") +//////// .allowedOrigins("*") +//////// .allowedMethods("GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS") +//////// .allowedHeaders("*") +//////// .allowCredentials(true); +//////// } +//////// }; +//////// } +////// +////// @Bean +////// public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { +////// http +////// .authorizeHttpRequests(authorize -> authorize +////// .requestMatchers("/login", "/signup", "/user", "/v3/api-docs/**", "/swagger-ui/**", "/swagger-ui.html","/user/**").permitAll() +////// .anyRequest().authenticated() +////// ) +////// .formLogin(form -> form +////// .loginPage("/login") // 기본 로그인 필요하면 위치 +////// .defaultSuccessUrl("/articles") //로그인에 성공하면 위치 +////// ) +////// .logout(logout -> logout +////// .logoutSuccessUrl("/login") //로그인에 성공하면 위치 +////// .invalidateHttpSession(true) //세션 만료 +////// ) +////// .csrf(csrf -> csrf.disable()); +////// +////// return http.build(); +////// } +////// +////// @Bean +////// public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception { +////// return authenticationConfiguration.getAuthenticationManager(); +////// } +////// +////// @Bean +////// public BCryptPasswordEncoder bCryptPasswordEncoder() { +////// return new BCryptPasswordEncoder(); +////// } +//////} +//// +//// +//// +//////package com.todoslave.feedme.config.security; +//// +//// +////import com.todoslave.feedme.login.Service.CustomOAuth2UserService; +////import org.springframework.context.annotation.Bean; +////import org.springframework.context.annotation.Configuration; +////import org.springframework.security.authentication.AuthenticationManager; +////import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; +////import org.springframework.security.config.annotation.web.builders.HttpSecurity; +////import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +////import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +////import org.springframework.security.config.http.SessionCreationPolicy; +////import org.springframework.security.core.userdetails.UserDetailsService; +////import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +////import org.springframework.security.web.SecurityFilterChain; +////import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher; +////import org.springframework.web.cors.CorsConfiguration; +////import org.springframework.web.cors.CorsConfigurationSource; +////import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +////import org.springframework.web.servlet.handler.HandlerMappingIntrospector; +//// +////import java.util.Collections; +//// +////@Configuration +////@EnableWebSecurity +////public class WebSecurityConfig { +//// +//// private final UserDetailsService userDetailsService; +//// +//// public WebSecurityConfig(UserDetailsService userDetailsService) { +//// this.userDetailsService = userDetailsService; +//// } +//// +//// @Bean +//// public BCryptPasswordEncoder passwordEncoder() { +//// return new BCryptPasswordEncoder(); +//// } +//// +//// @Bean +//// CorsConfigurationSource corsConfigurationSource() { +//// UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); +//// CorsConfiguration config = new CorsConfiguration(); +//// config.setAllowedHeaders(Collections.singletonList("*")); +//// config.setAllowedMethods(Collections.singletonList("*")); +//// config.setAllowedOriginPatterns(Collections.singletonList("http://localhost:3000")); // 허용할 origin +//// config.setAllowCredentials(true); +//// source.registerCorsConfiguration("/**", config); +//// return source; +//// } +//// +////// @Bean +////// public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { +////// http +////// .httpBasic(httpBasicConfigurer -> httpBasicConfigurer.disable()) +////// .cors(corsConfigurer -> corsConfigurer.configurationSource(corsConfigurationSource())) +////// .csrf(AbstractHttpConfigurer::disable) +////// .authorizeHttpRequests(authorize -> +////// authorize +////// .requestMatchers("/login", "/signup", "/user", "/v3/api-docs/**", "/swagger-ui/**", "/swagger-ui.html", "/users/**").permitAll() +////// .anyRequest().authenticated() +////// ) +////// .formLogin(form -> form +////// .loginPage("/login") +////// .defaultSuccessUrl("/articles") +////// ) +////// .logout(logout -> logout +////// .logoutSuccessUrl("/login") +////// .invalidateHttpSession(true) +////// ); +////// +////// return http.build(); +////// } +//// +//// //되는거 +////// @Bean +////// public SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector, CustomOAuth2UserService customOAuth2UserService) throws Exception { +////// http +////// +////// .csrf(AbstractHttpConfigurer::disable) +////// .sessionManagement((sessionManagement) -> +////// sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS) +////// ) +////// .formLogin(AbstractHttpConfigurer::disable) +////// .httpBasic(AbstractHttpConfigurer::disable) +////// .authorizeHttpRequests((authorizeRequests) -> authorizeRequests +////// .requestMatchers(new MvcRequestMatcher(introspector, "/api/user")).permitAll() +////// .anyRequest().authenticated() +////// ) +////// .oauth2Login(oauth2Login -> +////// oauth2Login.userInfoEndpoint(userInfoEndpointConfig -> +////// userInfoEndpointConfig.userService(customOAuth2UserService))) +////// .formLogin(form -> form +////// .loginPage("/login") // 기본 로그인 필요하면 위치 +////// +////// ) +////// ; +////// return http.build(); +////// } +//// @Bean +//// public SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector, CustomOAuth2UserService customOAuth2UserService) throws Exception { +//// http +//// .httpBasic(httpBasicConfigurer -> httpBasicConfigurer.disable()) +//// .cors(corsConfigurer -> corsConfigurer.configurationSource(corsConfigurationSource())) +//// .csrf(AbstractHttpConfigurer::disable) +//// .authorizeHttpRequests(authorize -> +//// authorize +//// .requestMatchers("/login", "/signup", "/user", "/v3/api-docs/**", "/swagger-ui/**", "/swagger-ui.html", "/users/**").permitAll() +//// .requestMatchers(new MvcRequestMatcher(introspector, "/api/user")).permitAll() +//// .anyRequest().authenticated() +//// ) +//// .formLogin(form -> form +//// .loginPage("/login") +//// .defaultSuccessUrl("/login") +//// ) +//// .logout(logout -> logout +//// .logoutSuccessUrl("/login") +//// .invalidateHttpSession(true) +//// ) +//// .sessionManagement(sessionManagement -> +//// sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS) +//// ) +//// .oauth2Login(oauth2Login -> +//// oauth2Login.userInfoEndpoint(userInfoEndpointConfig -> +//// userInfoEndpointConfig.userService(customOAuth2UserService)) +//// ); +//// +//// return http.build(); +//// } +//// @Bean +//// public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception { +//// return authenticationConfiguration.getAuthenticationManager(); +//// } +////} +//package com.todoslave.feedme.config.security; +// +//import com.todoslave.feedme.login.Service.CustomOAuth2UserService; +//import lombok.RequiredArgsConstructor; +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Configuration; +//import org.springframework.security.authentication.AuthenticationManager; +//import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; +//import org.springframework.security.config.annotation.web.builders.HttpSecurity; +//import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +//import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer; +//import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +//import org.springframework.security.config.http.SessionCreationPolicy; +//import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +//import org.springframework.security.web.SecurityFilterChain; +//import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler; +//import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher; +//import org.springframework.web.cors.CorsConfiguration; +//import org.springframework.web.cors.CorsConfigurationSource; +//import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +//import org.springframework.web.servlet.handler.HandlerMappingIntrospector; +// +//import java.util.Collections; +// +//@Configuration +//@EnableWebSecurity +//@RequiredArgsConstructor +//public class WebSecurityConfig { +// +// private final CustomOAuth2UserService customOAuth2UserService; +// +// +// @Bean //security를 적용할것 설절 +// public WebSecurityCustomizer webSecurityCustomizer() { +// return web -> web.ignoring() +// .requestMatchers("/error", "/favicon.ico"); +// } +// +// @Bean // 암호화 친구 +// public BCryptPasswordEncoder passwordEncoder() { +// return new BCryptPasswordEncoder(); +// } +// +// +// @Bean +// CorsConfigurationSource corsConfigurationSource() { // 의미 없고 +// UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); +// CorsConfiguration config = new CorsConfiguration(); +// config.setAllowedHeaders(Collections.singletonList("*")); +// config.setAllowedMethods(Collections.singletonList("*")); +// config.setAllowedOriginPatterns(Collections.singletonList("http://localhost:3000")); // 허용할 origin +// config.setAllowCredentials(true); +// source.registerCorsConfiguration("/**", config); +// return source; +// } +// +// @Bean +// public SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception { +// http +// .httpBasic(httpBasicConfigurer -> httpBasicConfigurer.disable()) // 이게 폼 +// .cors(corsConfigurer -> corsConfigurer.configurationSource(corsConfigurationSource())) //CORS 설정 +// .csrf(AbstractHttpConfigurer::disable) +// .authorizeHttpRequests(authorize -> +// authorize +// .requestMatchers("/login","/testsite" ,"/signup", "/user", "/v3/api-docs/**", "/swagger-ui/**", "/swagger-ui.html", "/users/**").permitAll() // 유저 설정 +// .requestMatchers(new MvcRequestMatcher(introspector, "/api/user")).permitAll() +// .anyRequest().authenticated() +// ) +// +// .oauth2Login(oauth2Login -> +// oauth2Login.userInfoEndpoint(userInfoEndpointConfig -> +// userInfoEndpointConfig.userService(customOAuth2UserService)) +// .loginPage("/login") // 소셜 로그인 페이지 +// .successHandler(new SimpleUrlAuthenticationSuccessHandler("/templates/testsite.html")) // 로그인 성공 시 리디렉션 URL +// ) +// .logout(logout -> logout +// .logoutUrl("/logout") +// .logoutSuccessUrl("/login") +// .invalidateHttpSession(true) +// .deleteCookies("JSESSIONID") +// .permitAll() +// ) +// .sessionManagement(sessionManagement -> +// sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS) +// ); +// +// return http.build(); +// } +// +// @Bean +// public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception { +// return authenticationConfiguration.getAuthenticationManager(); +// } +//} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/security/filter/JwtAuthFilter.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/security/filter/JwtAuthFilter.java new file mode 100644 index 0000000..d55b80e --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/security/filter/JwtAuthFilter.java @@ -0,0 +1,216 @@ +//package com.todoslave.feedme.config.security.filter; +// +// +//import com.todoslave.feedme.login.dto.RefreshToken; +//import com.todoslave.feedme.login.dto.TokenResponseStatus; +//import com.todoslave.feedme.login.util.SecurityUserDto; +//import com.todoslave.feedme.domain.entity.membership.Member; +//import com.todoslave.feedme.login.Handler.JWTUtill; +//import com.todoslave.feedme.repository.MemberRepository; +//import com.todoslave.feedme.repository.RefreshTokenRepository; +//import jakarta.servlet.FilterChain; +//import jakarta.servlet.ServletException; +//import jakarta.servlet.http.HttpServletRequest; +//import jakarta.servlet.http.HttpServletResponse; +//import lombok.RequiredArgsConstructor; +//import lombok.extern.slf4j.Slf4j; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.http.ResponseEntity; +//import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +//import org.springframework.security.core.Authentication; +//import org.springframework.security.core.authority.SimpleGrantedAuthority; +//import org.springframework.security.core.context.SecurityContextHolder; +//import org.springframework.security.oauth2.jwt.JwtException; +//import org.springframework.stereotype.Component; +//import org.springframework.util.StringUtils; +//import org.springframework.web.filter.OncePerRequestFilter; +// +//import java.io.IOException; +//import java.util.List; +//import java.util.Optional; +// +//@RequiredArgsConstructor +//@Slf4j +//@Component +//public class JwtAuthFilter extends OncePerRequestFilter { +// +// private final JWTUtill jwtUtil; +// private final MemberRepository memberRepository; +// +// private final RefreshTokenRepository tokenRepository; +// +// @Override +// protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException { +// return request.getRequestURI().contains("token/"); +// } +// +// @Override +// protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { +// +// // request Header에서 AccessToken을 가져온다. +// String atc = request.getHeader("Authorization"); +// +// +// +// // 토큰 검사 생략(모두 허용 URL의 경우 토큰 검사 통과) +// if (!StringUtils.hasText(atc)) { +// doFilter(request, response, filterChain); +// return; +// } +// +// // AccessToken을 검증하고, 만료되었을경우 예외를 발생시킨다. +// if (!jwtUtil.verifyToken(atc)) { +// +// Optional refreshToken = tokenRepository.findByAccessToken(atc); +// +//// System.out.println("access token: " + atc + "이고요"); +//// System.out.println("refresh token: " + refreshToken+"입니다"); +//// System.out.println(refreshToken.toString()); +//// System.out.println("refresh token: " + refreshToken.get().getRefreshToken()+"입니다"); +// +// if (refreshToken.isPresent() && jwtUtil.verifyToken(refreshToken.get().getRefreshToken())) { +// +// +// // RefreshToken 객체를 꺼내온다. +// RefreshToken resultToken = refreshToken.get(); +// // 권한과 아이디를 추출해 새로운 액세스토큰을 만든다. +// String newAccessToken = jwtUtil.generateAccessToken(resultToken.getId(), jwtUtil.getRole(resultToken.getRefreshToken())); +// // 액세스 토큰의 값을 수정해준다. +// resultToken.updateAccessToken(newAccessToken); +// tokenRepository.save(resultToken); +// +// // 새로운 액세스 토큰을 헤더에 추가 +// response.setHeader("Authorization", "Bearer " + newAccessToken); +// +// // 기존 요청을 업데이트된 토큰과 함께 다시 처리 +// request.setAttribute("Authorization", "Bearer " + newAccessToken); +// SecurityContextHolder.getContext().setAuthentication(getAuthentication(SecurityUserDto.builder() +// .id(Integer.valueOf(resultToken.getId())) +// .email(jwtUtil.getUid(resultToken.getAccessToken())) +// .role(jwtUtil.getRole(resultToken.getAccessToken())) +// .build())); +// +// // 기존 필터 체인을 다시 호출 +// filterChain.doFilter(request, response); +// +// } else{ +// throw new JwtException("Refresh 토큰과 Access Token 모두 만료되었습니다."); // 로그아웃 처리 +// } +// } +// +// // AccessToken의 값이 있고, 유효한 경우에 진행한다. +// if (jwtUtil.verifyToken(atc)) { +// +// // AccessToken 내부의 payload에 있는 email로 user를 조회한다. 없다면 예외를 발생시킨다 -> 정상 케이스가 아님 +// Member findMember = memberRepository.findByEmail(jwtUtil.getUid(atc)) +// .orElseThrow(IllegalStateException::new); +// +// // SecurityContext에 등록할 User 객체를 만들어준다. +// SecurityUserDto userDto = SecurityUserDto.builder() +// .id(findMember.getId()) +// .email(findMember.getEmail()) +// .role("ROLE_".concat(findMember.getUserRole())) +// .nickname(findMember.getNickname()) +// .build(); +// +// // SecurityContext에 인증 객체를 등록해준다. +// Authentication auth = getAuthentication(userDto); +// SecurityContextHolder.getContext().setAuthentication(auth); +// } +// +// filterChain.doFilter(request, response); +// } +// +// +// +// public Authentication getAuthentication(SecurityUserDto member) { +// return new UsernamePasswordAuthenticationToken(member, "", +// List.of(new SimpleGrantedAuthority(member.getRole()))); +// } +// +//} + +package com.todoslave.feedme.config.security.filter; + + +import com.todoslave.feedme.login.util.SecurityUserDto; +import com.todoslave.feedme.domain.entity.membership.Member; +import com.todoslave.feedme.login.Handler.JWTUtill; +import com.todoslave.feedme.repository.MemberRepository; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.oauth2.jwt.JwtException; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; +import org.springframework.web.filter.OncePerRequestFilter; + +import java.io.IOException; +import java.util.List; + +@RequiredArgsConstructor +@Slf4j +@Component +public class JwtAuthFilter extends OncePerRequestFilter { + + private final JWTUtill jwtUtil; + private final MemberRepository memberRepository; + + @Override + protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException { + return request.getRequestURI().contains("token/refresh"); + } + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { + // request Header에서 AccessToken을 가져온다. + String atc = request.getHeader("Authorization"); + + // 토큰 검사 생략(모두 허용 URL의 경우 토큰 검사 통과) + if (!StringUtils.hasText(atc)) { + doFilter(request, response, filterChain); + return; + } + + // AccessToken을 검증하고, 만료되었을경우 예외를 발생시킨다. + if (!jwtUtil.verifyToken(atc)) { + throw new JwtException("Access Token 만료!"); + } + + // AccessToken의 값이 있고, 유효한 경우에 진행한다. + if (jwtUtil.verifyToken(atc)) { + + // AccessToken 내부의 payload에 있는 email로 user를 조회한다. 없다면 예외를 발생시킨다 -> 정상 케이스가 아님 + Member findMember = memberRepository.findByEmail(jwtUtil.getUid(atc)) + .orElseThrow(IllegalStateException::new); + + // SecurityContext에 등록할 User 객체를 만들어준다. + SecurityUserDto userDto = SecurityUserDto.builder() + .id(findMember.getId()) + .email(findMember.getEmail()) + .role("ROLE_".concat(findMember.getUserRole())) + .nickname(findMember.getNickname()) + .build(); + + // SecurityContext에 인증 객체를 등록해준다. + Authentication auth = getAuthentication(userDto); + SecurityContextHolder.getContext().setAuthentication(auth); + } + + filterChain.doFilter(request, response); + } + + + + public Authentication getAuthentication(SecurityUserDto member) { + return new UsernamePasswordAuthenticationToken(member, "", + List.of(new SimpleGrantedAuthority(member.getRole()))); + } + +} \ No newline at end of file diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/security/filter/JwtExceptionFilter.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/security/filter/JwtExceptionFilter.java new file mode 100644 index 0000000..29d2007 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/config/security/filter/JwtExceptionFilter.java @@ -0,0 +1,36 @@ +package com.todoslave.feedme.config.security.filter; + + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.todoslave.feedme.config.security.StatusResponseDto; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.http.MediaType; +import org.springframework.security.oauth2.jwt.JwtException; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; + + +import java.io.IOException; + +@Component +@RequiredArgsConstructor +public class JwtExceptionFilter extends OncePerRequestFilter { + + private final ObjectMapper objectMapper; + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { + try { + filterChain.doFilter(request, response); + } catch (JwtException e) { + response.setStatus(401); + response.setContentType(MediaType.APPLICATION_JSON_VALUE); + response.setCharacterEncoding("UTF-8"); + objectMapper.writeValue(response.getWriter(), StatusResponseDto.addStatus(401)); + } + } +} \ No newline at end of file diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/AlarmController.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/AlarmController.java new file mode 100644 index 0000000..4e49712 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/AlarmController.java @@ -0,0 +1,52 @@ +package com.todoslave.feedme.controller; + +import com.todoslave.feedme.DTO.AlarmResponseDTO; +import com.todoslave.feedme.DTO.AlarmSetRequestDTO; +import com.todoslave.feedme.login.util.SecurityUtil; +import com.todoslave.feedme.DTO.PaginationRequestDTO; +import com.todoslave.feedme.domain.entity.alarm.Alarm; +import com.todoslave.feedme.service.AlarmService; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Slice; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/alarms") +public class AlarmController { + + @Autowired + private final SecurityUtil securityUtil; + @Autowired + private AlarmService alarmService; + + @GetMapping(value = "/subscribe/alarm") + public SseEmitter subscribe(){ + return alarmService.createEmitter(); + } + + @GetMapping(value = "/subscribe/chat") + public SseEmitter chatSubscribe(){ + return alarmService.renewCreateEmitter(); + } + + @PostMapping("/time") + public ResponseEntity alarmTimeSetting(@RequestBody AlarmSetRequestDTO alarmSetRequestDTO){ + alarmService.createAlarmtime(alarmSetRequestDTO); + return ResponseEntity.noContent().build(); + } + + // 생일, 투두 + @GetMapping() + private ResponseEntity> loadAlarms(@RequestParam("skip") int skip, @RequestParam("limit") int limit) { + PaginationRequestDTO paginationRequestDTO = new PaginationRequestDTO(); + paginationRequestDTO.setSkip(skip); + paginationRequestDTO.setLimit(limit); + return ResponseEntity.ok(alarmService.loadAlarms(paginationRequestDTO)); + } + + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/AuthController.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/AuthController.java new file mode 100644 index 0000000..ec1fda2 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/AuthController.java @@ -0,0 +1,63 @@ +package com.todoslave.feedme.controller; + +import com.todoslave.feedme.config.security.StatusResponseDto; +import com.todoslave.feedme.login.Handler.JWTUtill; +import com.todoslave.feedme.login.dto.RefreshToken; +import com.todoslave.feedme.login.dto.TokenResponseStatus; +import com.todoslave.feedme.repository.RefreshTokenRepository; +import com.todoslave.feedme.login.Service.RefreshTokenService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Optional; + +@Slf4j +@RestController +@RequiredArgsConstructor +public class AuthController { + + @Autowired + private final RefreshTokenRepository tokenRepository; + @Autowired + private final RefreshTokenService tokenService; + @Autowired + private final JWTUtill jwtUtil; + + @PostMapping("token/logout") + public ResponseEntity logout(@RequestHeader("Authorization") final String accessToken) { + // 엑세스 토큰으로 현재 Redis 정보 삭제 + tokenService.removeRefreshToken(accessToken); + + return ResponseEntity.ok(StatusResponseDto.addStatus(200)); + } + + @PostMapping("/token/refresh") + public ResponseEntity refresh(@RequestHeader("Authorization") final String accessToken) { + System.out.println("이게되야해"); + // 액세스 토큰으로 Refresh 토큰 객체를 조회 + Optional refreshToken = tokenRepository.findByAccessToken(accessToken); + + // RefreshToken이 존재하고 유효하다면 실행 + if (refreshToken.isPresent() && jwtUtil.verifyToken(refreshToken.get().getRefreshToken())) { + + // RefreshToken 객체를 꺼내온다. + RefreshToken resultToken = refreshToken.get(); + // 권한과 아이디를 추출해 새로운 액세스토큰을 만든다. + String newAccessToken = jwtUtil.generateAccessToken(resultToken.getId(), jwtUtil.getRole(resultToken.getRefreshToken())); + // 액세스 토큰의 값을 수정해준다. + resultToken.updateAccessToken(newAccessToken); + tokenRepository.save(resultToken); + + // 새로운 액세스 토큰을 반환해준다. + return ResponseEntity.ok(TokenResponseStatus.addStatus(200, newAccessToken)); + } + + return ResponseEntity.badRequest().body(TokenResponseStatus.addStatus(400, null)); + } + +} \ No newline at end of file diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/CreatureController.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/CreatureController.java new file mode 100644 index 0000000..15006cc --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/CreatureController.java @@ -0,0 +1,69 @@ +package com.todoslave.feedme.controller; + +import com.todoslave.feedme.DTO.CreatureInfoResponseDTO; +import com.todoslave.feedme.DTO.CreatureMakeRequestDTO; +import com.todoslave.feedme.domain.entity.avatar.Creature; +import com.todoslave.feedme.domain.entity.membership.Member; +import com.todoslave.feedme.login.util.SecurityUtil; +import com.todoslave.feedme.service.CreatureService; +import io.swagger.v3.oas.annotations.Operation; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.Map; + +@RestController +@RequestMapping("/creature") +@RequiredArgsConstructor +public class CreatureController { + + private final CreatureService creatureService; + + + @Operation(summary = "크리쳐 생성") + @PostMapping + public ResponseEntity createCreature(@RequestBody CreatureMakeRequestDTO request, @RequestHeader("Authorization") final String accessToken) { + Member member = SecurityUtil.getCurrentMember(); + + Creature creature = creatureService.createFristCreature(request.getKeyword(), request.getPhoto(), request.getCreatureName()); + + return ResponseEntity.ok(Map.of("creatureId", creature.getId(), "message", "크리쳐가 성공적으로 생성되었습니다.")); + } + +// @Operation(summary = "크리쳐 생성") 이거는!!! 나중에 파일 전송시에! +// @PostMapping("/creature") +// public ResponseEntity createCreature(@ModelAttribute CreatureMakeRequestDTO request, +// @RequestHeader("Authorization") final String accessToken) { +// Member member = SecurityUtil.getCurrentMember(); +// +// Creature creature = creatureService.createFristCreature(request.getKeyword(), +// request.getPhoto(), +// request.getCreatureName()); +// +// return ResponseEntity.ok(Map.of("creatureId", creature.getId(), "message", "크리쳐가 성공적으로 생성되었습니다.")); +// } + + + @Operation(summary = "크리쳐 보기") + @GetMapping + public ResponseEntity getCreatures(@RequestHeader("Authorization") final String accessToken) { + + CreatureInfoResponseDTO creature = creatureService.creatureInfo(SecurityUtil.getCurrentMember()); + + return new ResponseEntity(creature, HttpStatus.OK); + } + + @Operation(summary = "크리쳐 삭제") + @DeleteMapping + public ResponseEntity delectCreature(@RequestHeader("Authorization") final String accessToken) { + if(creatureService.removeCreature()){ + return new ResponseEntity("삭제되었습니다.", HttpStatus.OK);}else{ + return new ResponseEntity("해당 크리쳐를 찾을 수 없습니다.", HttpStatus.BAD_REQUEST); + } + } + + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/CreatureTodoController.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/CreatureTodoController.java new file mode 100644 index 0000000..3aa0104 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/CreatureTodoController.java @@ -0,0 +1,72 @@ +package com.todoslave.feedme.controller; + +import com.todoslave.feedme.DTO.*; +import com.todoslave.feedme.service.CreatureTodoService; +import io.swagger.v3.oas.annotations.Operation; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +@RestController +@RequestMapping("/creatureTodo") +@RequiredArgsConstructor +public class CreatureTodoController { + + @Autowired + final private CreatureTodoService creatureTodoService; + + // 크리쳐 투두 생성 + @Operation(summary = "크리쳐 투두 생성 / 있으면 생성 X") + @GetMapping("/{weather}") + public ResponseEntity> createTodo(@PathVariable String weather) { + System.out.println("이거 맞아?"); + List list = new ArrayList<>(); + list = creatureTodoService.insertTodo(weather); + return ResponseEntity.ok(list); + } + + // 투두 완료 + @PostMapping("/complete/{id}") + @Operation(summary = "투두 일정 하나 완료/취소") + public ResponseEntity completeTodo(@PathVariable int id){ + return ResponseEntity.ok(creatureTodoService.completeTodo(id)); + } + + // 오늘 완료되지 않은 투두 목록 가져오기 + @GetMapping("/main/daily") + @Operation(summary = "오늘 완료되지 않은 크리쳐 투두 목록 가져오기") + public ResponseEntity> getCreatureTodoMainDaily() { + List list = creatureTodoService.getCreatureTodoMainDaily(); + return ResponseEntity.ok(list); + } + + // 메인 달력에서 일정 불러오기 + @GetMapping("/calendar/daily") + @Operation(summary = "해당일의 크리쳐 투두 목록 가져오기") + public ResponseEntity> findCalendarCreatureTodoList(@RequestParam("date") LocalDate date) { + CretureTodoRequestDTO cretureTodoRequestDTO = new CretureTodoRequestDTO(); + cretureTodoRequestDTO.setDate(date); + List list = creatureTodoService.getCreatureTodoCalendarDaily(cretureTodoRequestDTO); + return ResponseEntity.ok(list); + } + + // 할일 목록에서 일정(일) 불러오기 + @Operation(summary = "할일 목록에서 일정(일) 불러오기 - 다음날 이동 가능하게") + @GetMapping("/todolist/daily") + public ResponseEntity> findDailyCreatureTodoList(@RequestParam("date") LocalDate date, + @RequestParam("next") int next){ + CreatureTodoDailyRequestDTO creatureTodoDailyRequestDTO = new CreatureTodoDailyRequestDTO(); + creatureTodoDailyRequestDTO.setDate(date); + creatureTodoDailyRequestDTO.setNext(next); + return ResponseEntity.ok(creatureTodoService.getCreatureTodoListDaily(creatureTodoDailyRequestDTO)); + } + + + +} \ No newline at end of file diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/DayOffController.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/DayOffController.java new file mode 100644 index 0000000..657900e --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/DayOffController.java @@ -0,0 +1,48 @@ +package com.todoslave.feedme.controller; + +import com.todoslave.feedme.login.util.SecurityUtil; +import com.todoslave.feedme.service.DayOffService; +import io.swagger.v3.oas.annotations.Operation; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.time.LocalDate; + +@RestController +@RequestMapping("/dayoff") +@RequiredArgsConstructor +public class DayOffController { + + private final DayOffService dayOffService; + + //여기서 기존에 일기 쓴 기록이 있거나, 아니면 해당일에 한게 아무것도 없으면 버튼이 안눌리게 만들어 줘야해 + @Operation(summary = "일기 생성 버튼 활성화") + @GetMapping("/{canFinishDay}") + public ResponseEntity checkDiaryCreationEligibility(@PathVariable LocalDate canFinishDay) { + + int userId = SecurityUtil.getCurrentUserId(); + + // 해당 날짜에 이미 완료된 작업이 있는지 확인 + boolean actionAllowed = dayOffService.isActionAllowed(userId, canFinishDay); + + // 해당 날짜에 기록이 없는지 확인 (기록이 없으면 true) + boolean hasNoClearData = dayOffService.notFindClearData(canFinishDay); + + System.out.println("테스팅"); + System.out.println(actionAllowed); // 있어서 false + System.out.println(hasNoClearData); // 없어서 true + + // 버튼이 비활성화 되어야 하는 경우 (이미 완료된 작업이 있거나 기록이 없는 경우) + if (!actionAllowed || !hasNoClearData) { + return ResponseEntity.ok(false); + } + + // 버튼이 활성화 되어야 하는 경우 + return ResponseEntity.ok(true); + } + + + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/DiaryController.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/DiaryController.java new file mode 100644 index 0000000..ca1717c --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/DiaryController.java @@ -0,0 +1,34 @@ + +package com.todoslave.feedme.controller; + +import com.todoslave.feedme.DTO.DiaryRequestDTO; +import com.todoslave.feedme.DTO.DiaryResponseDTO; +import com.todoslave.feedme.service.DiaryService; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/diary") +public class DiaryController { + + private final DiaryService diaryService; + + @PostMapping("/list") + public ResponseEntity> getDiaryList( + @RequestBody DiaryRequestDTO paginationRequest) { + + int skip = paginationRequest.getSkip(); + int limit = paginationRequest.getLimit(); + + Pageable pageable = PageRequest.of(skip / limit, limit, Sort.by("createdAt").descending()); + Page diaryPage = diaryService.getDiaryList(pageable); + + return ResponseEntity.ok(diaryPage); + } +} \ No newline at end of file diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/FeedCommentController.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/FeedCommentController.java new file mode 100644 index 0000000..caa1809 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/FeedCommentController.java @@ -0,0 +1,52 @@ +package com.todoslave.feedme.controller; + +import com.todoslave.feedme.DTO.*; +import com.todoslave.feedme.domain.entity.Feed.FeedComment; +import com.todoslave.feedme.service.FeedCommentService; +import io.swagger.v3.oas.annotations.Operation; +import jakarta.servlet.http.HttpSession; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/feedComment") +@RequiredArgsConstructor +public class FeedCommentController { + + private final FeedCommentService feedCommentService; + + // 피드 생성 + @Operation(summary = "댓글 생성") + @PostMapping("/{feed_id}") + public ResponseEntity registComment(@PathVariable("feed_id") int feedId, @RequestBody FeedCommentRequestDTO feedCommentRequestDTO) { + return ResponseEntity.ok(feedCommentService.insertFeedCommend(feedCommentRequestDTO,feedId)); + } + + // 피드 수정 + @Operation(summary = "댓글 수정") + @PatchMapping("/{feedComment_Id}") + public ResponseEntity modifyComment(@PathVariable("feedComment_Id") int feedcommantId, @RequestBody FeedCommentRequestDTO feedCommentRequestDTO) { + FeedCommentResponseDTO dto = feedCommentService.modifyComment(feedCommentRequestDTO, feedcommantId); + if (dto == null) { + String msg = "내가 쓴 글이 아니거나, 삭제된 글 입니다."; + return new ResponseEntity(msg, HttpStatus.BAD_REQUEST); + } + return ResponseEntity.ok(dto); + } + + // 피드 삭제 + @Operation(summary = "댓글 삭제") + @DeleteMapping("/{feedComment_Id}") + public ResponseEntity delectFeedComment(@PathVariable int feedComment_Id) { + boolean succes = feedCommentService.delectFeedComment(feedComment_Id); + if (succes) { + String msg = "삭제되었습니다"; + return new ResponseEntity(msg, HttpStatus.OK); + } + String msg = "내가 쓴 글이 아니거나, 삭제된 글 입니다."; + return new ResponseEntity(msg, HttpStatus.BAD_REQUEST); + } + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/FeedController.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/FeedController.java index f98a4ca..1cf1efd 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/FeedController.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/FeedController.java @@ -1,5 +1,73 @@ package com.todoslave.feedme.controller; +import com.todoslave.feedme.DTO.FeedDTO; +import com.todoslave.feedme.DTO.FeedModifyRequest; +import com.todoslave.feedme.DTO.FeedRequestDTO; +import com.todoslave.feedme.DTO.FeedResponseDTO; +import com.todoslave.feedme.service.FeedService; +import io.swagger.v3.oas.annotations.Operation; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/feed") +@RequiredArgsConstructor public class FeedController { + @Autowired + private final FeedService feedService; + + // 피드 생성 + @Operation(summary = "피드 생성") + @PostMapping + public ResponseEntity createFeed(@RequestBody FeedRequestDTO feedRequestDTO) { + FeedResponseDTO dto = feedService.insertFeed(feedRequestDTO); + return ResponseEntity.ok(dto); + } + + // 피드 수정 + @Operation(summary = "피드 수정") + @PatchMapping("/{feedId}") + public ResponseEntity modifyFeed(@PathVariable int feedId, @RequestBody FeedModifyRequest feedModifyRequest) { + FeedResponseDTO dto = feedService.modifyFeed(feedId ,feedModifyRequest); + return ResponseEntity.ok(dto); + } + + // 피드 삭제 + @Operation(summary = "피드 삭제") + @DeleteMapping("/{feedId}") + public ResponseEntity delectFeed(@PathVariable int feedId) { + if(feedService.delectFeed(feedId)){ + return new ResponseEntity("삭제되었습니다.", HttpStatus.OK); + }else{ + return new ResponseEntity("본인글만 지우세요", HttpStatus.BAD_REQUEST); + } + } + + // 좋아요/좋아요 취소 버튼 + @Operation(summary = "피드 좋아요/취소") + @PostMapping("/{feedId}/like") + public void likeButton(@PathVariable int feedId) { + feedService.toggleLike(feedId); + } + + // 피드 보기 + @Operation(summary = "피드 보기(테스트)") + @GetMapping + public List getRecentFeeds() { + return feedService.getRecentFeeds(); + } + + // 친구 피드 보기 + @Operation(summary = " 1달치 친구 피드 보기") + @GetMapping("/recent/friends") + public List getRecentFeedsByFriends() { + return feedService.getRecentFeedsByFriends(); + } + } diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/FeedReCommentController.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/FeedReCommentController.java new file mode 100644 index 0000000..46f4253 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/FeedReCommentController.java @@ -0,0 +1,13 @@ +package com.todoslave.feedme.controller; + +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/feedReComment") +@RequiredArgsConstructor +public class FeedReCommentController { + + //피드 대댓글 스펙아웃 +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/FriendController.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/FriendController.java index 22e39de..89c6881 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/FriendController.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/FriendController.java @@ -1,89 +1,92 @@ -//package com.todoslave.feedme.controller; -// -//import com.todoslave.feedme.domain.entity.communication.Friend; -//import com.todoslave.feedme.domain.entity.communication.FriendRequest; -//import com.todoslave.feedme.service.FriendService; -//import lombok.RequiredArgsConstructor; -//import org.springframework.http.RequestEntity; -//import org.springframework.http.ResponseEntity; -//import org.springframework.web.bind.annotation.*; -// -//import java.util.List; -// -//@RestController -//@RequiredArgsConstructor -//@RequestMapping("/friends") -//public class FriendController { -// -// static private FriendService friendService; -// -// // 친구 추가하기 -// @PostMapping -// public ResponseEntity addFriend(@RequestParam("token") String token, @RequestParam("counterEmail") String email){ -// -// // token으로부터 memberId를 찾는 로직 -// int memberId; -// -// friendService.insertFriend(memberId, email); -// -// return ResponseEntity.noContent().build(); -// } -// -// // 친구 삭제하기 -// @DeleteMapping("/{id}") -// public ResponseEntity removeFriend(@RequestHeader("Authorization") String token, @RequestParam("id") String friendId){ -// -// // token으로부터 memberId를 찾는 로직 -// int memberId; -// -// friendService.deleteFriend(friendId); -// -// return ResponseEntity.noContent().build(); -// } -// -// // 친구 목록 불러오기 -// @GetMapping -// public ResponseEntity> findFriends(@RequestHeader("Authorization")String token){ -// //token으로부터 memberId를 찾는 로직 -// int memberId; -// -// return ResponseEntity.ok(friendService.getFriends(memberId)); -// } -// -// // 친구 요청 목록 조회 -// @GetMapping("/request") -// public ResponseEntity> findRequestFriend(@RequestHeader("Authorization") String token){ -// //token으로부터 memberId를 찾는 로직 -// int memberId; -// -// return ResponseEntity.ok(friendService.getRequestFriend(memberId)); -// } -// -// // 친구 수락하기 -// @PostMapping("/{id}/accept") -// public ResponseEntity acceptFriendship(@RequestHeader("Authorization") String token, @PathVariable("id") int requestId){ -// // token 인증 -// if(true) { -// friendService.insertFriendship(requestId); -// } -// -// return ResponseEntity.noContent().build(); -// } -// -// // 친구 거절하기 -// @PostMapping("/{id}/reject") -// public ResponseEntity rejectFriendship(@RequestHeader("Authorization") String token, @PathVariable("id") int requestId){ -// // token 인증 -// if(true){ -// friendService.deleteRequestFriend(requestId); -// } -// -// return ResponseEntity.noContent().build(); -// } -// -// // 친구 활동 피드 -// -// // 친구 일정 공유 -// -// -//} +package com.todoslave.feedme.controller; + +import com.todoslave.feedme.DTO.FriendInfoResponseDTO; +import com.todoslave.feedme.DTO.FriendReqResponseDTO; +import com.todoslave.feedme.DTO.FriendRequestDTO; +import com.todoslave.feedme.DTO.FriendResponseDTO; +import com.todoslave.feedme.DTO.MemberChatListResponseDTO; +import com.todoslave.feedme.DTO.PaginationRequestDTO; +import com.todoslave.feedme.domain.entity.communication.FriendRequest; +import com.todoslave.feedme.service.AlarmService; +import com.todoslave.feedme.service.FriendService; +import com.todoslave.feedme.service.MemberChatService; +import com.todoslave.feedme.service.MemberService; +import io.swagger.v3.oas.annotations.Operation; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Slice; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/friends") +public class FriendController { + + @Autowired + MemberService memberService; + @Autowired + FriendService friendService; + @Autowired + AlarmService alarmService; + @Autowired + MemberChatService memberChatService; + + // 친구 요청하기 + @PostMapping + public ResponseEntity addFriend(@RequestBody FriendRequestDTO friendReqRequestDTO){ + friendService.requestFriend(friendReqRequestDTO); + return ResponseEntity.noContent().build(); + } + + // 친구 삭제하기 + @DeleteMapping() + public ResponseEntity removeFriend(@RequestParam("counterpartNickname") String counterpartNickname){ + FriendRequestDTO friendRequestDTO = new FriendRequestDTO(); + friendRequestDTO.setCounterpartNickname(counterpartNickname); + friendService.deleteFriend(friendRequestDTO); + return ResponseEntity.noContent().build(); + } + + //친구 정보 얻기 + @Operation(summary = "친구 닉네임 검색") + @GetMapping("/info") + public ResponseEntity findFriendInfo(@RequestParam String counterpartNickname){ + FriendRequestDTO friendRequestDTO = new FriendRequestDTO(); + friendRequestDTO.setCounterpartNickname(counterpartNickname); + return ResponseEntity.ok(friendService.getFriendInfo(friendRequestDTO)); + } + + // 친구 목록 불러오기 + @GetMapping("/list") + public ResponseEntity> findFriends(){ + return ResponseEntity.ok(friendService.getFriends()); + } + + // 친구 요청 목록 조회 + @GetMapping("/request") + public ResponseEntity> findRequestFriend( + @RequestParam("skip") int skip, @RequestParam("limit") int limit) { + PaginationRequestDTO paginationRequestDTO = new PaginationRequestDTO(); + paginationRequestDTO.setSkip(skip); + paginationRequestDTO.setLimit(limit); + return ResponseEntity.ok(friendService.getRequestFriend(paginationRequestDTO)); + } + + // 친구 요청 수락하기 + @PostMapping("/accept/{id}") + public ResponseEntity acceptFriendship(@PathVariable("id") int requestId){ + return ResponseEntity.ok(friendService.insertFriendship(requestId)); + } + + // 친구 요청 거절하기 + @PostMapping("/reject/{id}") + public ResponseEntity rejectFriendship(@PathVariable("id") int requestId){ + friendService.deleteRequestFriend(requestId); + return ResponseEntity.noContent().build(); + } + + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/MemberChatController.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/MemberChatController.java index a48e0dc..10395a4 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/MemberChatController.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/MemberChatController.java @@ -1,26 +1,34 @@ package com.todoslave.feedme.controller; -import com.todoslave.feedme.DTO.PaginationRequest; +import com.todoslave.feedme.DTO.*; import com.todoslave.feedme.domain.entity.communication.MemberChatMessage; import com.todoslave.feedme.domain.entity.communication.MemberChatRoom; +import com.todoslave.feedme.domain.entity.membership.Member; +import com.todoslave.feedme.login.util.SecurityUtil; import com.todoslave.feedme.service.MemberChatService; +import com.todoslave.feedme.service.MemberService; +import java.io.IOException; import java.util.ArrayList; import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.event.EventListener; import org.springframework.data.domain.Slice; +import org.springframework.data.redis.connection.Message; +import org.springframework.data.redis.connection.MessageListener; import org.springframework.http.ResponseEntity; import org.springframework.messaging.handler.annotation.DestinationVariable; import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.messaging.handler.annotation.Payload; import org.springframework.messaging.handler.annotation.SendTo; +import org.springframework.messaging.simp.stomp.StompHeaderAccessor; import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.socket.messaging.SessionConnectEvent; +import org.springframework.web.socket.messaging.SessionDisconnectEvent; @RequiredArgsConstructor @RestController @@ -29,53 +37,46 @@ public class MemberChatController { @Autowired private final MemberChatService chatService; + @Autowired + private final MemberService memberService; - // 이 유저가 누구랑 채팅방을 갖고 있는 지 찾기 - @GetMapping - public ResponseEntity> findChatRoomList(@RequestHeader("Authorization") String token){ - - MemberChatRoom room = new MemberChatRoom(); - List members = new ArrayList<>(); - - // jwt 토큰에서 id 얻어오기 - String memberId = "-1"; - - members.add(memberId); - room.setParticipantIds(members); - - return ResponseEntity.ok(chatService.getChatRooms(room)); - } - - // 채팅방 ID 찾기 - @PostMapping - public ResponseEntity findChatRoom(@RequestHeader("Authorization") String token, - @RequestParam("counterpartId") String counterpartId) { + @EventListener + public void handleWebSocketConnectListener(SessionConnectEvent event) { + StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(event.getMessage()); + String sessionId = headerAccessor.getSessionId(); + // 추가적인 연결 초기화 로직을 여기에 작성할 수 있습니다. - String memberId = "-1"; + String destination = headerAccessor.getDestination(); - if ( memberId == null || counterpartId == null) { - return ResponseEntity.badRequest().build(); + if (destination != null && destination.startsWith("/chatRoom/")) { + String[] pathSegments = destination.split("/"); + if (pathSegments.length > 2) { + String roomId = pathSegments[pathSegments.length - 1]; + } } - MemberChatRoom room = new MemberChatRoom(); - - List members = new ArrayList<>(); + } - members.add(memberId); - members.add(counterpartId); + @EventListener + public void handleWebSocketDisconnectListener(SessionDisconnectEvent event) { + StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(event.getMessage()); + String sessionId = headerAccessor.getSessionId(); + // 연결 종료 시 처리할 로직을 여기에 작성할 수 있습니다. - room.setParticipantIds(members); + } - return ResponseEntity.ok(chatService.getChatRoom(room)); + // 유저의 채팅방 목록들 불러오기 + @GetMapping + public ResponseEntity> findChatRoomList(){ + return ResponseEntity.ok(chatService.getChatRooms()); } // 메세지 불러오기 @MessageMapping("/loadMessages/{roomId}") @SendTo("/chatRoom/loadMessages/{roomId}") public Slice findMessages(@DestinationVariable String roomId, - @Payload PaginationRequest request){ - System.out.println("receive message?"); + @Payload PaginationRequestDTO request){ Slice messages = chatService.getChatMessage(roomId, request.getSkip(), request.getLimit()); for (MemberChatMessage message : messages) { @@ -88,8 +89,11 @@ public Slice findMessages(@DestinationVariable String roomId, // 메세지 저장 @MessageMapping("/messages/{roomId}") @SendTo("/chatRoom/messages/{roomId}") - public MemberChatMessage sendMessage(@DestinationVariable String roomId, @Payload MemberChatMessage memberChatMessage) { - memberChatMessage.setMemberChatRoomId(roomId); - return chatService.insertChatMessage(memberChatMessage); + public MemberChatMessageResponseDTO sendMessage(@DestinationVariable String roomId, @Payload MemberChatMessageRequestDTO memberChatMessageRequestDTO) + throws IOException { + return chatService.insertChatMessage(roomId, memberChatMessageRequestDTO); } + + + } diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/MemberController.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/MemberController.java new file mode 100644 index 0000000..a1361a6 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/MemberController.java @@ -0,0 +1,143 @@ +package com.todoslave.feedme.controller; + +import com.todoslave.feedme.DTO.FriendInfoResponseDTO; +import com.todoslave.feedme.DTO.MemberSearchResponseDTO; +import com.todoslave.feedme.DTO.MemberSignupRequestDTO; +import com.todoslave.feedme.DTO.MypageResponseDTO; +import com.todoslave.feedme.config.jwt.JwtProperties; + +import com.todoslave.feedme.domain.entity.membership.Member; + +import com.todoslave.feedme.login.Handler.JWTUtill; +import com.todoslave.feedme.login.Service.RefreshTokenService; +import com.todoslave.feedme.login.Service.TokenBlacklistService; +import com.todoslave.feedme.login.dto.TokenResponseStatus; +import com.todoslave.feedme.login.util.SecurityUtil; +import com.todoslave.feedme.repository.MemberRepository; +import com.todoslave.feedme.service.MemberService; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.PostConstruct; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; +import org.springframework.web.bind.annotation.*; + +import java.util.Base64; +import java.util.Date; +import java.util.List; + +@RestController +@RequestMapping("/users") +@Tag(name = "회원 CRUD") +@RequiredArgsConstructor +public class MemberController { + + + private final JwtProperties jwtProperties; + private final MemberService memberService; + private final TokenBlacklistService tokenBlacklistService; + private final RefreshTokenService tokenService; + private String secretKey; + + @PostConstruct + protected void init() { + secretKey = Base64.getEncoder().encodeToString(jwtProperties.getSecretKey().getBytes()); + } + + + @Operation(summary = "맴버 검색 (for 친구추가)") + @GetMapping("/{searchvalue}") + public ResponseEntity> getUsers(@PathVariable String searchvalue) { + List list = memberService.getMemberList(searchvalue); + return new ResponseEntity>(list, HttpStatus.OK); + } + + + @Operation(summary = "맴버 가입") + @PostMapping + public ResponseEntity signupMember(@RequestBody MemberSignupRequestDTO memberSignupRequestDTO){ + + // 닉네임 중복 체크 + if (memberService.checkNickname(memberSignupRequestDTO.getNickname())) { + return ResponseEntity.status(HttpStatus.CONFLICT) + .body("Nickname already exists"); + } + + Member member = memberService.registerMember(memberSignupRequestDTO); + return ResponseEntity.ok(member); + } + + @Operation(summary = "맴버 수정") + @PatchMapping + public ResponseEntity updateMember(@RequestBody MemberSignupRequestDTO memberSignupRequestDTO){ + + // 닉네임 중복 체크 + if (memberService.checkNickname(memberSignupRequestDTO.getNickname())) { + return ResponseEntity.status(HttpStatus.CONFLICT) + .body("Nickname already exists"); + } + + Member member = memberService.updateMember(memberSignupRequestDTO); + + return ResponseEntity.ok(member); + } + + @Operation(summary = "맴버 정보 가져오기 (테스트용)") + @GetMapping("/holder/test") + public Member getCurrentMember() { + return SecurityUtil.getCurrentMember(); + } + + @Operation(summary = "내 정보 페이지") + @GetMapping("/mypage") + public ResponseEntity getMypage(@RequestHeader("Authorization") final String accessToken) { + + return ResponseEntity.ok(memberService.getMyPage()); + } + + @Operation(summary = "로그아웃") + @GetMapping("/logout") + public ResponseEntity logout(@RequestHeader("Authorization") final String accessToken) { + + // 토큰을 블랙리스트에 추가하여 무효화 + Claims claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(accessToken).getBody(); + Date expiryDate = claims.getExpiration(); + + // 블랙리스트 서비스에 토큰을 추가 + tokenBlacklistService.addToBlacklist(accessToken, expiryDate); + + //레디스에서 제거 + tokenService.removeRefreshToken(accessToken); + + return new ResponseEntity<>("Logged out successfully", HttpStatus.OK); + } + + + @Operation(summary = "맴버 탈퇴") + @DeleteMapping + public ResponseEntity deleteMember(@RequestHeader("Authorization") final String accessToken) { + int id = SecurityUtil.getCurrentUserId(); + + if (id == -1) { + return ResponseEntity.badRequest().body("로그인 상태를 확인해주세요."); + } + + boolean isDeleted = memberService.removeMember(); // id를 인자로 전달하도록 수정 + + if (isDeleted) { + return ResponseEntity.ok("정상적으로 삭제되었습니다."); + } else { + return ResponseEntity.status(HttpStatus.CONFLICT).body("이미 삭제된 회원이거나, 로그인 상태를 확인해주세요."); + } + } + + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/TodoCategoryController.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/TodoCategoryController.java new file mode 100644 index 0000000..5dec52a --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/TodoCategoryController.java @@ -0,0 +1,53 @@ +package com.todoslave.feedme.controller; + +import com.todoslave.feedme.DTO.TodoCategoryRequestDTO; +import com.todoslave.feedme.DTO.TodoCategoryResponseDTO; +import com.todoslave.feedme.domain.entity.task.TodoCategory; +import com.todoslave.feedme.service.TodoCategoryService; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/category") +public class TodoCategoryController { + + @Autowired + private TodoCategoryService todoCategoryService; + + @GetMapping + public ResponseEntity> findTodoCategories(){ + return ResponseEntity.ok(todoCategoryService.getCategories()); + } + + @PostMapping("/{name}") + public ResponseEntity createTodoCategory(@PathVariable("name") String name){ + System.out.println(name+"되어요?"); + return ResponseEntity.ok(todoCategoryService.insertCategory(name)); + } + + @DeleteMapping + public ResponseEntity removeTodoCategory(@RequestBody TodoCategoryRequestDTO category){ + todoCategoryService.deleteCategory(category.getId()); + return ResponseEntity.noContent().build(); + } + + @PatchMapping + public ResponseEntity modifyTodoCategory(@RequestBody + TodoCategoryRequestDTO category){ + return ResponseEntity.ok(todoCategoryService.updateCategory(category)); + } + + + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/TodoController.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/TodoController.java index 01d1eb4..d1a7598 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/TodoController.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/TodoController.java @@ -1,57 +1,100 @@ package com.todoslave.feedme.controller; -import com.todoslave.feedme.domain.entity.task.Todo; +import com.todoslave.feedme.DTO.TodoCalendarResponseDTO; +import com.todoslave.feedme.DTO.TodoCreateRequestDTO; +import com.todoslave.feedme.DTO.TodoDailyRequestDTO; +import com.todoslave.feedme.DTO.TodoMainResponseDTO; +import com.todoslave.feedme.DTO.TodoModifyRequestDTO; +import com.todoslave.feedme.DTO.TodoRequestDTO; +import com.todoslave.feedme.DTO.TodoResponseDTO; import com.todoslave.feedme.service.TodoService; -import java.sql.Date; -import java.sql.Timestamp; + +import java.time.LocalDate; import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PatchMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestHeader; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; @RequiredArgsConstructor @RestController @RequestMapping("/todos") public class TodoController { - @Autowired - private final TodoService todoservice; + private final TodoService todoService; + + // 할일 목록에서 일정(일) 불러오기 + @GetMapping("/todolist/daily") + public ResponseEntity> findDailyTodoList(@RequestParam("date")LocalDate date, + @RequestParam("next")int next){ + TodoDailyRequestDTO todoDailyRequestDTO = new TodoDailyRequestDTO(); + todoDailyRequestDTO.setDate(date); + todoDailyRequestDTO.setNext(next); + return ResponseEntity.ok(todoService.getTodoListDaily(todoDailyRequestDTO)); + } + + // 메인 달력에서 일정 불러오기 + @GetMapping("/calendar/daily") + public ResponseEntity> findCalendarTodoList(@RequestParam("date")LocalDate date){ + TodoRequestDTO todoRequestDTO = new TodoRequestDTO(); + todoRequestDTO.setDate(date); + return ResponseEntity.ok(todoService.getTodoCalendarDaily(todoRequestDTO)); + } + + // 메인 화면에서 당일 안한 일정들 불러오기 + @GetMapping("/main/daily") + public ResponseEntity> findMainInCompleted(){ - @GetMapping("/daily") - public ResponseEntity> findTodoDaily(@RequestHeader("Authorization") String token, @RequestBody Todo todo){ - Timestamp timestamp = todo.getCreatedAt(); - Date createdAt = new Date(timestamp.getTime()); - return ResponseEntity.ok(todoservice.getTodoDaily(todo.getMember().getId(), createdAt)); + return ResponseEntity.ok(todoService.getTodoMainDaily()); } + // 월별 일정 완/미완 불러오기 + @GetMapping("/calendar") + public ResponseEntity> findCalendarIsCompleted(@RequestParam("date")LocalDate date){ + TodoRequestDTO todoRequestDTO = new TodoRequestDTO(); + todoRequestDTO.setDate(date); + return ResponseEntity.ok(todoService.getTodoCalendarCompleted(todoRequestDTO)); + } + + // 투두 생성 @PostMapping - public ResponseEntity createTodo(@RequestHeader("Authorization") String token, @RequestBody Todo todo){ - return ResponseEntity.ok(todoservice.insertTodo(todo)); + public ResponseEntity createTodo(@RequestParam("content")String content, + @RequestParam("categoryId")int categoryId){ + TodoCreateRequestDTO todo = new TodoCreateRequestDTO(); + todo.setContent(content); + todo.setCategoryId(categoryId); + return ResponseEntity.ok(todoService.insertTodo(todo)); } + // 투두 삭제 @DeleteMapping("/{id}") - public ResponseEntity removeTodo(@RequestHeader("Authorization") String token, @PathVariable int id){ - todoservice.deleteTodo(id); + public ResponseEntity removeTodo(@PathVariable int id){ + todoService.deleteTodo(id); return ResponseEntity.noContent().build(); } + // 투두 수정 @PatchMapping() - public ResponseEntity modifyTodo(@RequestHeader("Authorization") String token, @RequestBody Todo todo){ - return ResponseEntity.ok(todoservice.updateTodoContent(todo.getId(), todo.getContent())); + public ResponseEntity modifyTodo(@RequestParam("id") int id, @RequestParam("content")String content){ + TodoModifyRequestDTO todoModifyRequestDTO = new TodoModifyRequestDTO(); + todoModifyRequestDTO.setId(id); + todoModifyRequestDTO.setContent(content); + return ResponseEntity.ok(todoService.updateTodo(todoModifyRequestDTO)); } - @PostMapping("/{id}/complete") - public ResponseEntity completeTodo(@RequestHeader("Authorization") String token, @PathVariable int id){ - return ResponseEntity.ok(todoservice.completeTodo(id)); + // 투두 완료 + @PostMapping("/complete/{id}") + public ResponseEntity completeTodo(@PathVariable int id){ + return ResponseEntity.ok(todoService.completeTodo(id)); } + //오늘 (어제 포함) 일정 완료하기 + @PostMapping("/complete/complateAll") + public ResponseEntity allCompleteTodo(@RequestParam("date")LocalDate date){ + TodoRequestDTO todoRequestDTO = new TodoRequestDTO(); + todoRequestDTO.setDate(date); + return ResponseEntity.ok(todoService.AllcompleteTodo(todoRequestDTO)); + } + + } diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/UserViewController.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/UserViewController.java new file mode 100644 index 0000000..f9035ab --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/controller/UserViewController.java @@ -0,0 +1,30 @@ +package com.todoslave.feedme.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; + +//웹 페이지 로그인 테스트용 +@Controller +public class UserViewController { + + @GetMapping("/login") + public String login() { + return "login"; + } + + @GetMapping("/signup") + public String signup() { + return "signup"; + } + + @GetMapping("/test") + public String test() { + return "test"; + } + + @GetMapping("/testsite") + public String testsite() { + return "testsite"; + } + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/Feed/Feed.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/Feed/Feed.java index 7d440e9..25160be 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/Feed/Feed.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/Feed/Feed.java @@ -7,6 +7,7 @@ import org.hibernate.annotations.CreationTimestamp; import org.hibernate.annotations.UpdateTimestamp; +import java.time.LocalDate; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -17,7 +18,7 @@ public class Feed { // 피드 아이디 @Id - @GeneratedValue + @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; // 회원 ID @@ -26,6 +27,14 @@ public class Feed { @JsonBackReference private Member member; + //그림일기 날자 + @Column(name = "diary_day") + private LocalDate diaryDay; + + //닉네임 + @Column(name = "nickname") + private String nickname; + // 피드 내용 @Lob @Column(name = "content", columnDefinition = "TEXT") diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/Feed/FeedComment.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/Feed/FeedComment.java index 8bfaf62..9050f78 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/Feed/FeedComment.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/Feed/FeedComment.java @@ -16,7 +16,7 @@ public class FeedComment { //피드 댓글 ID @Id - @GeneratedValue + @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; //피드 ID @@ -40,7 +40,6 @@ public class FeedComment { @Column(name = "created_at", nullable = false, updatable = false) private LocalDateTime createdAt; - // 대댓글과 매핑 @OneToMany(mappedBy = "feedComment", cascade = CascadeType.ALL) private List feedRecomments = new ArrayList<>(); diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/Feed/FeedLike.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/Feed/FeedLike.java index 9a1ec75..873d218 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/Feed/FeedLike.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/Feed/FeedLike.java @@ -1,11 +1,12 @@ -package com.todoslave.feedme.domain.entity.Feed; +package com.todoslave.feedme.domain.entity.Feed;//package com.todoslave.feedme.domain.entity.Feed; -import com.fasterxml.jackson.annotation.JsonBackReference; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.todoslave.feedme.domain.entity.membership.Member; -import jakarta.persistence.*; import lombok.Data; import lombok.EqualsAndHashCode; +import lombok.ToString; +import jakarta.persistence.*; import java.io.Serializable; @Entity @@ -13,37 +14,34 @@ public class FeedLike { @EmbeddedId - private LikeId id; + private LikeId id = new LikeId(); @ManyToOne(fetch = FetchType.LAZY) @MapsId("memberId") @JoinColumn(name = "member_id") - @JsonBackReference + @JsonIgnore // 순환 참조 방지를 위해 JSON 변환 시 이 필드를 무시합니다. + @ToString.Exclude // Lombok의 toString()에서 이 필드를 제외합니다. private Member member; @ManyToOne(fetch = FetchType.LAZY) @MapsId("feedId") @JoinColumn(name = "feed_id") + @JsonIgnore // 순환 참조 방지를 위해 JSON 변환 시 이 필드를 무시합니다. + @ToString.Exclude // Lombok의 toString()에서 이 필드를 제외합니다. private Feed feed; @Data @EqualsAndHashCode @Embeddable - public static class LikeId implements Serializable { //왜 빨간줄이 뜰까? + public static class LikeId implements Serializable { private int memberId; private int feedId; - } - //==연관관계 메서드==// - public void setMember(Member member) { - this.member = member; - member.getFeedLikes().add(this); - } + public LikeId() {} - public void setFeed(Feed feed) { - this.feed = feed; - feed.getFeedLikes().add(this); + public LikeId(int memberId, int feedId) { + this.memberId = memberId; + this.feedId = feedId; + } } - - } diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/Feed/FeedRecomment.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/Feed/FeedRecomment.java index 1784ec9..4613334 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/Feed/FeedRecomment.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/Feed/FeedRecomment.java @@ -13,7 +13,7 @@ public class FeedRecomment { // 피드 대댓글 ID @Id - @GeneratedValue + @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; //피드 ID diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/check/Alarm.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/alarm/Alarm.java similarity index 71% rename from Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/check/Alarm.java rename to Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/alarm/Alarm.java index f6fa86e..d07e514 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/check/Alarm.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/alarm/Alarm.java @@ -1,4 +1,4 @@ -package com.todoslave.feedme.domain.entity.check; +package com.todoslave.feedme.domain.entity.alarm; import com.fasterxml.jackson.annotation.JsonBackReference; @@ -14,7 +14,7 @@ public class Alarm { // 알람 ID @Id - @GeneratedValue + @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; // 회원 ID @@ -23,7 +23,7 @@ public class Alarm { @JsonBackReference private Member member; - //컨텐츠 + // 내용 @Column(nullable = false) private String content; @@ -32,13 +32,11 @@ public class Alarm { @Column(name = "receive_at", nullable = false, updatable = false) private LocalDateTime receiveAt; -// @Column() -// private boolean read; - //==연관관계 메서드==// - public void setMember(Member member) { - this.member = member; - member.getAlarms().add(this); - } +// //==연관관계 메서드==// +// public void setMember(Member member) { +// this.member = member; +// member.getAlarms().add(this); +// } } diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/avatar/Creature.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/avatar/Creature.java index b4076fd..01b041e 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/avatar/Creature.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/avatar/Creature.java @@ -1,34 +1,51 @@ package com.todoslave.feedme.domain.entity.avatar; import com.fasterxml.jackson.annotation.JsonBackReference; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonManagedReference; import com.todoslave.feedme.domain.entity.membership.Member; import jakarta.persistence.*; import lombok.Data; +import lombok.ToString; @Entity @Data @Table(name = "creature") +@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"}) +@ToString public class Creature { // 크리쳐 ID - @Id @GeneratedValue + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; //회원 ID - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "member_id") + @OneToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id", referencedColumnName = "id") @JsonBackReference private Member member; - //진화단계 + // 레벨 @Column(nullable = false) - private int level = 1 ; //레벨 1로 초기화 한다는 뜻 + private int level = 0 ; //레벨 1로 초기화 한다는 뜻 + + // 경험치 + @Column(name = "exp", nullable = false) + private int exp = 0 ; + + //크리쳐 이름 + @Column(name = "creature_name") + private String creatureName; + + @Column(name = "creature_keyword") + private String creatureKeyword; + //==연관관계 메서드==// public void setMember(Member member) { this.member = member; - member.getCreatures().add(this); + member.setCreature(this); } - } \ No newline at end of file diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/communication/Friend.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/communication/Friend.java index dbb35d1..1cb6d8d 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/communication/Friend.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/communication/Friend.java @@ -11,7 +11,7 @@ public class Friend { //친구 ID @Id - @GeneratedValue + @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; // 본인 회원번호 diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/communication/FriendRequest.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/communication/FriendRequest.java index c7a14a2..889a246 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/communication/FriendRequest.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/communication/FriendRequest.java @@ -11,7 +11,7 @@ public class FriendRequest { //친구요청 ID - @Id @GeneratedValue + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; //본인 회원번호 diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/communication/MemberChatMessage.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/communication/MemberChatMessage.java index 0ab1140..7488062 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/communication/MemberChatMessage.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/communication/MemberChatMessage.java @@ -9,6 +9,7 @@ import lombok.NoArgsConstructor; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.mongodb.core.mapping.Document; +import org.springframework.data.mongodb.core.mapping.Field; @Data @Builder @@ -19,11 +20,14 @@ public class MemberChatMessage { @Id private String id; + @Field("memberChatRoom_id") private String memberChatRoomId; - private String sendId; + @Field("send_id") + private int sendId; private String content; @CreatedDate + @Field("transmit_at") private LocalDateTime transmitAt; @Override diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/communication/MemberChatRoom.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/communication/MemberChatRoom.java index b3bd10c..8d0b34c 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/communication/MemberChatRoom.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/communication/MemberChatRoom.java @@ -2,6 +2,7 @@ import com.todoslave.feedme.domain.entity.membership.Member; import jakarta.persistence.*; +import java.time.LocalDateTime; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -13,19 +14,23 @@ import org.hibernate.annotations.CreationTimestamp; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.mongodb.core.mapping.Document; +import org.springframework.data.mongodb.core.mapping.Field; @Data @Builder -@NoArgsConstructor @AllArgsConstructor @Document(collection = "memberchatroom") public class MemberChatRoom { @Id private String id; - private List participantIds; + @Field("participant_ids") + private List participantIds; + @Field("receive_time") + private LocalDateTime receiveTime; - @CreatedDate - private LocalDate createdAt; + public MemberChatRoom(){ + receiveTime = LocalDateTime.MIN; + } } diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/communication/MemberChatRoomChecked.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/communication/MemberChatRoomChecked.java new file mode 100644 index 0000000..d544140 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/communication/MemberChatRoomChecked.java @@ -0,0 +1,31 @@ +package com.todoslave.feedme.domain.entity.communication; + +import jakarta.persistence.Id; +import java.time.LocalDateTime; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.data.mongodb.core.mapping.Document; +import org.springframework.data.mongodb.core.mapping.Field; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Document(collection = "memberchatroomchecked") +public class MemberChatRoomChecked { + + @Id + private String id; + + @Field("memberChatRoom_id") + private String memberChatRoomId; + + @Field("member_id") + private int memberId; + + @Field("is_checked") + private int isChecked; + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/diary/PictureDiary.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/diary/PictureDiary.java index 3a11b46..51bd4e8 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/diary/PictureDiary.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/diary/PictureDiary.java @@ -13,7 +13,7 @@ public class PictureDiary { // 그림일기 ID @Id - @GeneratedValue + @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; // 회원 ID @@ -22,16 +22,15 @@ public class PictureDiary { @JsonBackReference private Member member; + //일기쓴 날 + @Column(name = "created_at", nullable = false, updatable = false) + private LocalDateTime createdAt; + //일기 내용 @Lob @Column(name = "content", nullable = false, columnDefinition = "TEXT") private String content; - //일기쓴 날 - @CreationTimestamp - @Column(name = "created_at", nullable = false, updatable = false) - private LocalDateTime createdAt; - //==연관관계 메서드==// public void setMember(Member member) { this.member = member; diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/membership/Member.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/membership/Member.java index 6c63644..aa6e2c0 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/membership/Member.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/membership/Member.java @@ -1,79 +1,79 @@ package com.todoslave.feedme.domain.entity.membership; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonManagedReference; + import com.todoslave.feedme.domain.entity.avatar.Creature; import com.todoslave.feedme.domain.entity.Feed.Feed; import com.todoslave.feedme.domain.entity.Feed.FeedComment; import com.todoslave.feedme.domain.entity.Feed.FeedLike; import com.todoslave.feedme.domain.entity.Feed.FeedRecomment; -import com.todoslave.feedme.domain.entity.check.Alarm; + +import com.todoslave.feedme.domain.entity.alarm.Alarm; import com.todoslave.feedme.domain.entity.communication.Friend; import com.todoslave.feedme.domain.entity.communication.FriendRequest; import com.todoslave.feedme.domain.entity.diary.PictureDiary; import com.todoslave.feedme.domain.entity.task.CreatureTodo; +import com.todoslave.feedme.domain.entity.task.DayOff; import com.todoslave.feedme.domain.entity.task.Todo; import com.todoslave.feedme.domain.entity.task.TodoCategory; import jakarta.persistence.*; +import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; import org.hibernate.annotations.CreationTimestamp; + import java.sql.Timestamp; import java.time.LocalDateTime; import java.util.ArrayList; +import java.util.Collection; import java.util.List; @Entity @Getter @Setter @Table(name = "member") -public class Member { +@NoArgsConstructor +@AllArgsConstructor +@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"}) +public class Member { //유저 디테일은 사용자 인증 정보를 담아두는 인터페이스이다. //회원 ID @Id - @GeneratedValue + @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; - //GeneratedValue에 관하여 설명 - /** - DB마다 다른데 어떤 DB는 seq를 만들기도 하고(MYSQL) 어떤 애들은 테이블을 만드는데, 이러면 항상 ID값이 보장이 된다. - persist 할때 필요 => 영속성 컨텍스트에 값을 딱 넣어야 하는데, 그때 이제 키/밸류가 되는데 - - **/ - + //GeneratedValue에 관하여 설명 /** + // DB마다 다른데 어떤 DB는 seq를 만들기도 하고(MYSQL) 어떤 애들은 테이블을 만드는데, 이러면 항상 ID값이 보장이 된다. + // persist 할때 필요 => 영속성 컨텍스트에 값을 딱 넣어야 하는데, 그때 이제 키/밸류가 되는데 + // + // **/ //이메일 @Column(nullable = false) private String email; //닉네임 - @Column(nullable = false) + @Column (nullable = false) private String nickname; //생일 + @Column //(nullable = false) private Timestamp birthday; - //토큰 - @Column(nullable = false) - private String token; - - //유저를 하나로 합침 - - // 경험치 - @Column(name = "exp", nullable = false, updatable = false) - private int exp; - // 상태 @Column(name = "status", nullable = false) @Enumerated(EnumType.STRING) - private Emotion status; // BASIC, JOY, SAD + private Emotion status = Emotion.BASIC; // BASIC, JOY, SAD //위도 - @Column(name = "latitude") + @Column private Double latitude; //경도 - @Column(name = "longitude") + @Column private Double longitude; //가입일 @@ -81,27 +81,17 @@ public class Member { @Column(name = "created_at", nullable = false, updatable = false) private LocalDateTime joinDate; - - // - - - - //여기부터 1대1 - -// //회원 상세와 매핑 -// @OneToOne(mappedBy = "member", cascade = CascadeType.ALL, orphanRemoval = true) -// private MemberDetail memberDetail; -// -// //회원 갱신 정보와 매핑 -// @OneToOne(mappedBy = "member", cascade = CascadeType.ALL, orphanRemoval = true) -// private MemberRenewInfo memberRenewInfo; -// -// //회원 위치와 매핑 -// @OneToOne(mappedBy = "member", cascade = CascadeType.ALL, orphanRemoval = true) -// private MemberSpace memberSpace; + //유저 인증 정보 + @Column(name = "user_role") + private String userRole; //여기부터 1대 N + //크리쳐와 매핑 + @OneToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.LAZY, orphanRemoval = true) //1:1 중에 1을 맡는다. + @JsonManagedReference + private Creature creature; + //친구와 매핑 @OneToMany(mappedBy = "member", cascade = CascadeType.ALL) @JsonManagedReference @@ -127,10 +117,10 @@ public class Member { @JsonManagedReference private List creatureTodos = new ArrayList<>(); - //크리쳐와 매핑 - @OneToMany(mappedBy = "member", cascade = CascadeType.ALL) - @JsonManagedReference - private List creatures = new ArrayList<>(); +// //크리쳐와 매핑 +// @OneToMany(mappedBy = "member", cascade = CascadeType.ALL) +// @JsonManagedReference +// private List creatures = new ArrayList<>(); // 그림일기와 매핑 @OneToMany(mappedBy = "member", cascade = CascadeType.ALL, orphanRemoval = true) @@ -160,7 +150,222 @@ public class Member { //알람과 매핑 @OneToMany(mappedBy = "member", cascade = CascadeType.ALL, orphanRemoval = true) @JsonManagedReference - private List alarms = new ArrayList<>(); + private List alarms = new ArrayList<>(); + //끝내는 날과 매핑 + @OneToMany(mappedBy = "member", cascade = CascadeType.ALL, orphanRemoval = true) + @JsonManagedReference + private List dayOffs= new ArrayList<>(); } + +// 메인에 있던건데, 뭐에 쓰는교?! +// @Override +// public Collection getAuthorities() { +// return List.of(new SimpleGrantedAuthority("MEMBER")); +// } + +// @Override +// public String getPassword() { +// return ""; +// } + +// @Override +// public String getUsername() { +// return ""; +// } + + + +//package com.todoslave.feedme.domain.entity.membership; +// +//import com.fasterxml.jackson.annotation.JsonManagedReference; +//import com.todoslave.feedme.domain.entity.avatar.Creature; +//import com.todoslave.feedme.domain.entity.Feed.Feed; +//import com.todoslave.feedme.domain.entity.Feed.FeedComment; +//import com.todoslave.feedme.domain.entity.Feed.FeedLike; +//import com.todoslave.feedme.domain.entity.Feed.FeedRecomment; +//import com.todoslave.feedme.domain.entity.check.Alarm; +//import com.todoslave.feedme.domain.entity.communication.Friend; +//import com.todoslave.feedme.domain.entity.communication.FriendRequest; +//import com.todoslave.feedme.domain.entity.diary.PictureDiary; +//import com.todoslave.feedme.domain.entity.task.CreatureTodo; +//import com.todoslave.feedme.domain.entity.task.Todo; +//import com.todoslave.feedme.domain.entity.task.TodoCategory; +//import jakarta.persistence.*; +//import lombok.*; +//import org.hibernate.annotations.CreationTimestamp; +//import org.springframework.security.core.GrantedAuthority; +//import org.springframework.security.core.authority.SimpleGrantedAuthority; +//import org.springframework.security.core.userdetails.UserDetails; +// +//import java.io.Serializable; +//import java.sql.Timestamp; +//import java.time.LocalDateTime; +//import java.util.ArrayList; +//import java.util.Collection; +//import java.util.List; +// +//@Entity +//@Getter +//@Setter +//@Table(name = "member") +//@NoArgsConstructor +//@AllArgsConstructor +//public class Member implements UserDetails { //유저 디테일은 사용자 인증 정보를 담아두는 인터페이스이다. +// +// //회원 ID +// @Id +// @GeneratedValue(strategy = GenerationType.IDENTITY) +// private int id; +// +// //GeneratedValue에 관하여 설명 +// /** +// DB마다 다른데 어떤 DB는 seq를 만들기도 하고(MYSQL) 어떤 애들은 테이블을 만드는데, 이러면 항상 ID값이 보장이 된다. +// persist 할때 필요 => 영속성 컨텍스트에 값을 딱 넣어야 하는데, 그때 이제 키/밸류가 되는데 +// +// **/ +// +// //이메일 +// @Column(nullable = false) +// private String email; +// +// //닉네임 +// @Column //(nullable = false) +// private String nickname; +// +// //생일 +// @Column //(nullable = false) +// private Timestamp birthday; +// +// //토큰 +// @Column +// private String token; +// +// //유저를 하나로 합침 +// +// // 경험치 +// @Column(name = "exp", nullable = false, updatable = false) +// private int exp = 0 ; +// +// // 상태 +// @Column(name = "status", nullable = false) +// @Enumerated(EnumType.STRING) +// private Emotion status = Emotion.BASIC; // BASIC, JOY, SAD +// +// //위도 +// @Column +// private Double latitude; +// +// //경도 +// @Column +// private Double longitude; +// +// //가입일 +// @CreationTimestamp +// @Column(name = "created_at", nullable = false, updatable = false) +// private LocalDateTime joinDate; +// +// //유저 인증 정보 +// @Column(name = "user_role") +// private String userRole; +// +// //여기부터 1대 N +// +// //친구와 매핑 +// @OneToMany(mappedBy = "member", cascade = CascadeType.ALL) +// @JsonManagedReference +// private List friends = new ArrayList<>(); +// +// //친구요청과 매핑 +// @OneToMany(mappedBy = "member", cascade = CascadeType.ALL) +// @JsonManagedReference +// private List friendRequests = new ArrayList<>(); +// +// // 투두와 매핑 +// @OneToMany(mappedBy = "member", cascade = CascadeType.ALL, orphanRemoval = true) +// @JsonManagedReference +// private List todos = new ArrayList<>(); +// +// // 투두 카테고리와 매핑 +// @OneToMany(mappedBy = "member", cascade = CascadeType.ALL, orphanRemoval = true) +// @JsonManagedReference +// private List todoCategories = new ArrayList<>(); +// +// // 크리쳐 숙제와 매핑 +// @OneToMany(mappedBy = "member", cascade = CascadeType.ALL, orphanRemoval = true) +// @JsonManagedReference +// private List creatureTodos = new ArrayList<>(); +// +// //크리쳐와 매핑 +// @OneToMany(mappedBy = "member", cascade = CascadeType.ALL) +// @JsonManagedReference +// private List creatures = new ArrayList<>(); +// +// // 그림일기와 매핑 +// @OneToMany(mappedBy = "member", cascade = CascadeType.ALL, orphanRemoval = true) +// @JsonManagedReference +// private List pictureDiary = new ArrayList<>(); +// +// // 피드와 매핑 +// @OneToMany(mappedBy = "member", cascade = CascadeType.ALL, orphanRemoval = true) +// @JsonManagedReference +// private List feeds = new ArrayList<>(); +// +// //좋아요 매핑 +// @OneToMany(mappedBy = "member", cascade = CascadeType.ALL, orphanRemoval = true) +// @JsonManagedReference +// private List feedLikes = new ArrayList<>(); +// +// //피드 댓글과 매핑 +// @OneToMany(mappedBy = "member", cascade = CascadeType.ALL, orphanRemoval = true) +// @JsonManagedReference +// private List feedComments = new ArrayList<>(); +// +// //피드 대댓글과 매핑 +// @OneToMany(mappedBy = "member", cascade = CascadeType.ALL, orphanRemoval = true) +// @JsonManagedReference +// private List feedRecomments = new ArrayList<>(); +// +// //알람과 매핑 +// @OneToMany(mappedBy = "member", cascade = CascadeType.ALL, orphanRemoval = true) +// @JsonManagedReference +// private List alarms = new ArrayList<>(); +// +// +// @Override +// public Collection getAuthorities() { +// return List.of(new SimpleGrantedAuthority("MEMBER")); +// } +// +// @Override +// public String getPassword() { +// return null; +// } +// +// @Override +// public String getUsername() { +// return email; +// } +// +// @Override +// public boolean isAccountNonExpired() { +// return true; +// } +// +// @Override +// public boolean isAccountNonLocked() { +// return true; +// } +// +// @Override +// public boolean isCredentialsNonExpired() { +// return true; +// } +// +// @Override +// public boolean isEnabled() { +// return true; +// } +// +//} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/membership/MemberAlarm.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/membership/MemberAlarm.java new file mode 100644 index 0000000..b469006 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/membership/MemberAlarm.java @@ -0,0 +1,35 @@ +package com.todoslave.feedme.domain.entity.membership; + +import com.fasterxml.jackson.annotation.JsonBackReference; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import java.sql.Time; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; + +@Entity +@Data +@Table(name = "memberAlarm") +public class MemberAlarm { + + @Id + @GeneratedValue + private int id; + + // 회원 ID + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id") + @JsonBackReference + private Member member; + + @Column(name = "alarm_time") + private int alarmTime; + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/membership/RefreshToken.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/membership/RefreshToken.java new file mode 100644 index 0000000..eea440c --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/membership/RefreshToken.java @@ -0,0 +1,34 @@ +package com.todoslave.feedme.domain.entity.membership; + +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter +@Entity +public class RefreshToken { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id", updatable = false) + private int id; + + @Column(name = "user_id", nullable = false, unique = true) + private int userId; + + @Column(name = "refresh_token", nullable = false) + private String refreshToken; + + public RefreshToken(int userId, String refreshToken) { + this.userId = userId; + this.refreshToken = refreshToken; + } + + public RefreshToken update(String newRefreshToken) { + this.refreshToken = newRefreshToken; + + return this; + } +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/mission/Mission.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/mission/Mission.java new file mode 100644 index 0000000..2d6ba37 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/mission/Mission.java @@ -0,0 +1,28 @@ +package com.todoslave.feedme.domain.entity.mission; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Entity +@Getter +@Setter +@NoArgsConstructor +public class Mission { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String weatherCondition; + private String mission; + + public Mission(String weatherCondition, String mission) { + this.weatherCondition = weatherCondition; + this.mission = mission; + } +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/task/CreatureTodo.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/task/CreatureTodo.java index 581d687..f9b7d21 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/task/CreatureTodo.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/task/CreatureTodo.java @@ -7,6 +7,7 @@ import org.hibernate.annotations.CreationTimestamp; import java.sql.Timestamp; +import java.time.LocalDate; @Entity @@ -16,7 +17,7 @@ public class CreatureTodo { //크리쳐 숙제 ID @Id - @GeneratedValue + @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; // 회원 ID @@ -32,11 +33,11 @@ public class CreatureTodo { // 생성일자 @CreationTimestamp @Column(name = "created_at", nullable = false, updatable = false) - private Timestamp createdAt; + private LocalDate createdAt; // 완료여부 @Column(name = "is_completed") - private boolean isCompleted; + private int isCompleted = 0; //==연관관계 메서드==// public void setMember(Member member) { diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/task/DayOff.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/task/DayOff.java new file mode 100644 index 0000000..643a302 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/task/DayOff.java @@ -0,0 +1,35 @@ +package com.todoslave.feedme.domain.entity.task; + +import com.fasterxml.jackson.annotation.JsonBackReference; +import com.todoslave.feedme.domain.entity.membership.Member; +import jakarta.persistence.*; +import lombok.Data; + +import java.time.LocalDate; + +@Entity +@Data +@Table(name = "dayoff") +public class DayOff { + + //날자 ID + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private int id; + + // 회원 ID + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id") + @JsonBackReference + private Member member; + + // 생성일자 + @Column(name = "end_day", nullable = false) + private LocalDate endDay; + + // 연관관계 메서드 + public void setMember(Member member) { + this.member = member; + member.getDayOffs().add(this); + } +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/task/Todo.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/task/Todo.java index 412a98e..6f8ffc9 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/task/Todo.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/task/Todo.java @@ -3,6 +3,7 @@ import com.fasterxml.jackson.annotation.JsonBackReference; import com.todoslave.feedme.domain.entity.membership.Member; import jakarta.persistence.*; +import java.time.LocalDate; import lombok.Data; import lombok.Getter; import org.hibernate.annotations.CreationTimestamp; @@ -15,7 +16,7 @@ public class Todo { // 할일 ID - @Id @GeneratedValue + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; // 회원 ID @@ -36,11 +37,11 @@ public class Todo { // 생성 일자 @CreationTimestamp @Column(name = "created_at", nullable = false, updatable = false) - private Timestamp createdAt; + private LocalDate createdAt; //완료 여부 @Column(name = "is_completed",nullable = false) - private boolean isCompleted; + private int isCompleted; //==연관관계 메서드==// public void setMember(Member member) { diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/task/TodoCategory.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/task/TodoCategory.java index 3e9fa54..71592b1 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/task/TodoCategory.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/domain/entity/task/TodoCategory.java @@ -14,7 +14,7 @@ public class TodoCategory { // 할일 카테고리 ID - @Id @GeneratedValue + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; // 회원 ID diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/gpt/dto/ChatGPTRequest.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/gpt/dto/ChatGPTRequest.java new file mode 100644 index 0000000..0ea3dd0 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/gpt/dto/ChatGPTRequest.java @@ -0,0 +1,18 @@ +package com.todoslave.feedme.gpt.dto; + +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; + +@Data +public class ChatGPTRequest { + private String model; + private List messages; + + public ChatGPTRequest(String model, String prompt) { + this.model = model; + this.messages = new ArrayList<>(); + this.messages.add(new Message("user", prompt)); + } +} \ No newline at end of file diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/gpt/dto/ChatGPTResponse.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/gpt/dto/ChatGPTResponse.java new file mode 100644 index 0000000..4a6231b --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/gpt/dto/ChatGPTResponse.java @@ -0,0 +1,24 @@ +package com.todoslave.feedme.gpt.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class ChatGPTResponse { + private List choices; + + + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class Choice { + private int index; + private Message message; + + } +} \ No newline at end of file diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/gpt/dto/CustomBotController.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/gpt/dto/CustomBotController.java new file mode 100644 index 0000000..bb273c0 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/gpt/dto/CustomBotController.java @@ -0,0 +1,24 @@ +//package com.todoslave.feedme.gpt.dto; +// +// +// +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.web.bind.annotation.GetMapping; +//import org.springframework.web.bind.annotation.RequestMapping; +//import org.springframework.web.bind.annotation.RequestParam; +//import org.springframework.web.bind.annotation.RestController; +// +//@RestController +//@RequestMapping("/bot") +//public class CustomBotController { +// +// @Autowired +// private CustomBotService botService; +// +// @GetMapping("/chat") +// public String chat(@RequestParam(name = "prompt") String prompt, +// @RequestParam(name = "format", required = false, defaultValue = "{response}") String format) { +// return botService.chat(prompt, format); +// } +// +//} \ No newline at end of file diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/gpt/dto/CustomBotService.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/gpt/dto/CustomBotService.java new file mode 100644 index 0000000..ff5d75c --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/gpt/dto/CustomBotService.java @@ -0,0 +1,46 @@ +package com.todoslave.feedme.gpt.dto; + +import com.todoslave.feedme.gpt.dto.ChatGPTRequest; +import com.todoslave.feedme.gpt.dto.ChatGPTResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +@Service +public class CustomBotService { + + @Value("${openai.model}") + private String model; + + @Value("${openai.api.url}") + private String apiURL; + + @Autowired + private RestTemplate template; + + public String chat(String prompt) { + // ChatGPT 요청 생성 및 응답 받기 + ChatGPTRequest request = new ChatGPTRequest(model, prompt); + ChatGPTResponse chatGPTResponse = template.postForObject(apiURL, request, ChatGPTResponse.class); + String responseContent = chatGPTResponse.getChoices().get(0).getMessage().getContent(); + + // 요청에 포함된 형식에 맞춰 데이터를 가공 + return processRequestBasedOnFormat(prompt, responseContent); + } + + private String processRequestBasedOnFormat(String prompt, String responseContent) { + // 요청에 "20개의 자료", " ,로 이어서" 등 특정 패턴이 있는지 검사 + if (prompt.contains("20개의 자료") && prompt.contains(",로 이어서")) { + // 데이터를 20개로 나누고 콤마로 연결 + List dataList = Arrays.asList(responseContent.split("\\s+")).subList(0, Math.min(20, responseContent.split("\\s+").length)); + return String.join(", ", dataList); + } + // 다른 형식의 처리도 추가 가능 + return responseContent; + } +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/gpt/dto/Message.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/gpt/dto/Message.java new file mode 100644 index 0000000..2ab05a6 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/gpt/dto/Message.java @@ -0,0 +1,14 @@ +package com.todoslave.feedme.gpt.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class Message { + private String role; + private String content; + +} \ No newline at end of file diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/imageUtil.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/imageUtil.java new file mode 100644 index 0000000..bac5bad --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/imageUtil.java @@ -0,0 +1,25 @@ +package com.todoslave.feedme; + +import com.todoslave.feedme.domain.entity.avatar.Creature; +import com.todoslave.feedme.domain.entity.membership.Member; +import org.springframework.stereotype.Component; + +@Component +public class imageUtil { + + + + //크리쳐 이미지 주소 + public static String generateCreatureImgPath(Member member) { + Creature creature = member.getCreature(); + int creatureLevel = creature.getLevel(); + int creatureId = creature.getId(); + return "http://localhost:8080/image/creature/" + creatureId + "_" +creatureLevel; + } + +// public static String generateDiaryImgPath(Member member){ +// Creature creature = member.getCreature(); +// feedDTO.setImg("http://localhost:8080/image/pictureDiary/"+SecurityUtil.getCurrentUserId()+"_"+feed.getDiaryDay()); +// } + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/Handler/JWTUtill.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/Handler/JWTUtill.java new file mode 100644 index 0000000..dc1e724 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/Handler/JWTUtill.java @@ -0,0 +1,146 @@ +package com.todoslave.feedme.login.Handler; + +import com.todoslave.feedme.config.jwt.JwtProperties; +import com.todoslave.feedme.login.Service.RefreshTokenService; +import com.todoslave.feedme.login.Service.TokenBlacklistService; +import com.todoslave.feedme.login.dto.GeneratedToken; +import com.todoslave.feedme.service.MemberService; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jws; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import jakarta.annotation.PostConstruct; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.Base64; +import java.util.Date; + +//토큰 발행 및 토큰 검증에 쓰이는 유틸 입니다. + +@Slf4j +@Service +@RequiredArgsConstructor +public class JWTUtill { + private final JwtProperties jwtProperties; + private final RefreshTokenService tokenService; + private final MemberService memberService; + private final TokenBlacklistService tokenBlacklistService; + private String secretKey; + + @PostConstruct + protected void init() { + secretKey = Base64.getEncoder().encodeToString(jwtProperties.getSecretKey().getBytes()); + } + + public GeneratedToken generateToken(String email, String role) { + // refreshToken과 accessToken을 생성한다. + String refreshToken = generateRefreshToken(email, role); + String accessToken = generateAccessToken(email, role); + + // 토큰을 Redis에 저장한다. + tokenService.saveTokenInfo(email, refreshToken, accessToken); + + //토큰을 MY SQL에 저장한다. +// memberService.settoken(email, refreshToken); + + return new GeneratedToken(accessToken, refreshToken); + } + + + + public String generateRefreshToken(String email, String role) { + // 토큰의 유효 기간을 밀리초 단위로 설정. + long refreshPeriod = 1000L * 60L * 60L * 24L * 14; // 2주 + + // 새로운 클레임 객체를 생성하고, 이메일과 역할(권한)을 셋팅 + Claims claims = Jwts.claims().setSubject(email); + claims.put("role", role); + + // 현재 시간과 날짜를 가져온다. + Date now = new Date(); + + return Jwts.builder() + // Payload를 구성하는 속성들을 정의한다. + .setClaims(claims) + // 발행일자를 넣는다. + .setIssuedAt(now) + // 토큰의 만료일시를 설정한다. + .setExpiration(new Date(now.getTime() + refreshPeriod)) + // 지정된 서명 알고리즘과 비밀 키를 사용하여 토큰을 서명한다. + .signWith(SignatureAlgorithm.HS256, secretKey) + .compact(); + } + + + public String generateAccessToken(String email, String role) { + long tokenPeriod = 1000L * 60L * 30L * 8; // 4시간 +// long tokenPeriod = 1000L * 30L; + Claims claims = Jwts.claims().setSubject(email); + claims.put("role", role); + + Date now = new Date(); + return + Jwts.builder() + // Payload를 구성하는 속성들을 정의한다. + .setClaims(claims) + // 발행일자를 넣는다. + .setIssuedAt(now) + // 토큰의 만료일시를 설정한다. + .setExpiration(new Date(now.getTime() + tokenPeriod)) + // 지정된 서명 알고리즘과 비밀 키를 사용하여 토큰을 서명한다. + .signWith(SignatureAlgorithm.HS256, secretKey) + .compact(); + + } + + +// public boolean verifyToken(String token) { //토큰 검증 하기 (시간 체크) +// try { +// Jws claims = Jwts.parser() +// .setSigningKey(secretKey) // 비밀키를 설정하여 파싱한다. +// .parseClaimsJws(token); // 주어진 토큰을 파싱하여 Claims 객체를 얻는다. +// // 토큰의 만료 시간과 현재 시간비교 +// return claims.getBody() +// .getExpiration() +// .after(new Date()); // 만료 시간이 현재 시간 이후인지 확인하여 유효성 검사 결과를 반환 +// } catch (Exception e) { +// return false; +// } +// } +public boolean verifyToken(String token) { + try { + if (tokenBlacklistService.isBlacklisted(token)) { + return false; + } + Jws claims = Jwts.parser() + .setSigningKey(secretKey) + .parseClaimsJws(token); + return claims.getBody() + .getExpiration() + .after(new Date()); + } catch (Exception e) { + return false; + } +} + //토큰을 블랙리스트에 추가 + public void invalidateToken(String token) { + // 토큰의 만료 날짜를 얻음 + Claims claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody(); + Date expiryDate = claims.getExpiration(); + // 블랙리스트 서비스에 토큰을 추가 + tokenBlacklistService.addToBlacklist(token, expiryDate); + } + + // 토큰에서 Email을 추출한다. + public String getUid(String token) { + return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody().getSubject(); + } + + // 토큰에서 ROLE(권한)만 추출한다. + public String getRole(String token) { + return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody().get("role", String.class); + } + +} \ No newline at end of file diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/Handler/MyAuthenticationFailureHandler.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/Handler/MyAuthenticationFailureHandler.java new file mode 100644 index 0000000..ee2a8d8 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/Handler/MyAuthenticationFailureHandler.java @@ -0,0 +1,23 @@ +package com.todoslave.feedme.login.Handler; + +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.AuthenticationFailureHandler; +import org.springframework.stereotype.Component; + +import java.io.IOException; + +//인증 실패시 이동 +@Component +@Slf4j +public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler { + @Override + public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { + // 인증 실패시 메인 페이지로 이동 + response.sendRedirect("https://i11b104.p.ssafy.io"); + } + +} \ No newline at end of file diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/Handler/MyAuthenticationSuccessHandler.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/Handler/MyAuthenticationSuccessHandler.java new file mode 100644 index 0000000..33ba1a1 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/Handler/MyAuthenticationSuccessHandler.java @@ -0,0 +1,85 @@ +package com.todoslave.feedme.login.Handler; + +import com.todoslave.feedme.domain.entity.membership.Member; +import com.todoslave.feedme.login.Handler.JWTUtill; +import com.todoslave.feedme.login.dto.GeneratedToken; +import com.todoslave.feedme.repository.MemberRepository; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.core.Authentication; +import org.springframework.security.oauth2.core.user.OAuth2User; +import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler; +import org.springframework.stereotype.Component; +import org.springframework.web.util.UriComponentsBuilder; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +//로그인 성공시 이동 + +@Slf4j +@Component +@RequiredArgsConstructor +public class MyAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler { + + private final JWTUtill jwtUtil; + private final MemberRepository memberRepository; + + @Override + public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { + + // OAuth2User로 캐스팅하여 인증된 사용자 정보를 가져온다. + OAuth2User oAuth2User = (OAuth2User) authentication.getPrincipal(); + // 사용자 이메일을 가져온다. + String email = oAuth2User.getAttribute("email"); + // 서비스 제공 플랫폼(GOOGLE, KAKAO, NAVER)이 어디인지 가져온다. + String provider = oAuth2User.getAttribute("provider"); + + // CustomOAuth2UserService에서 셋팅한 로그인한 회원 존재 여부를 가져온다. + boolean isExist = oAuth2User.getAttribute("exist"); + // OAuth2User로 부터 Role을 얻어온다. + String role = oAuth2User.getAuthorities().stream(). + findFirst() // 첫번째 Role을 찾아온다. + .orElseThrow(IllegalAccessError::new) // 존재하지 않을 시 예외를 던진다. + .getAuthority(); // Role을 가져온다. + + if (isExist) { + // 회원이 존재하면 jwt token 발행을 시작한다. + GeneratedToken token = jwtUtil.generateToken(email, role); + log.info("jwtToken = {}", token.getAccessToken()); + + // 해당 멤버의 크리쳐가 있는지 체크하기 + Member member = memberRepository.findByEmail(email).orElse(null); + boolean hasCreature = member != null && member.getCreature() != null; + +// // accessToken을 헤더에 추가 +// response.setHeader("Authorization", "Bearer " + token.getAccessToken()); + + // 크리쳐 존재 여부를 쿼리스트링에 담는 url을 만들어준다. + String targetUrl = UriComponentsBuilder.fromUriString("https://i11b104.p.ssafy.io/LoginLoding") + .queryParam("hasCreature", hasCreature) + .queryParam("accessToken", token.getAccessToken()) + .build() + .encode(StandardCharsets.UTF_8) + .toUriString(); + log.info("redirect 준비"); + // 로그인 확인 페이지로 리다이렉트 시킨다. + getRedirectStrategy().sendRedirect(request, response, targetUrl); + + } else { + + // 회원이 존재하지 않을경우, 서비스 제공자와 email을 쿼리스트링으로 전달하는 url을 만들어준다. + String targetUrl = UriComponentsBuilder.fromUriString("https://i11b104.p.ssafy.io/Signup") + .queryParam("email", (String) oAuth2User.getAttribute("email")) + .queryParam("provider", provider) + .build() + .encode(StandardCharsets.UTF_8) + .toUriString(); + // 회원가입 페이지로 리다이렉트 시킨다. + getRedirectStrategy().sendRedirect(request, response, targetUrl); + } + } +} \ No newline at end of file diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/Service/CustomOAuth2UserService.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/Service/CustomOAuth2UserService.java new file mode 100644 index 0000000..b4d0290 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/Service/CustomOAuth2UserService.java @@ -0,0 +1,91 @@ +package com.todoslave.feedme.login.Service; + +import com.todoslave.feedme.domain.entity.membership.Member; +import com.todoslave.feedme.login.dto.OAuth2Attribute; +import com.todoslave.feedme.service.MemberService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService; +import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; +import org.springframework.security.oauth2.client.userinfo.OAuth2UserService; +import org.springframework.security.oauth2.core.OAuth2AuthenticationException; +import org.springframework.security.oauth2.core.user.DefaultOAuth2User; +import org.springframework.security.oauth2.core.user.OAuth2User; +import org.springframework.stereotype.Service; + +import java.util.Collections; +import java.util.Map; +import java.util.Optional; + +@Slf4j +@Service +@RequiredArgsConstructor +public class CustomOAuth2UserService implements OAuth2UserService { + + private final MemberService memberService; + + @Override // 유저를 가져오려고 한다.OAuth2User 라는 객체 형태로 + public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException { + + // 기본 OAuth2UserService 객체 생성 과정 + OAuth2UserService oAuth2UserService = new DefaultOAuth2UserService(); + + // OAuth2UserService를 사용하여 OAuth2User 정보를 가져온다. + OAuth2User oAuth2User = oAuth2UserService.loadUser(userRequest); + + // 클라이언트 등록 ID(naver, kakao)와 사용자 이름 속성을 가져온다. + String registrationId = userRequest.getClientRegistration().getRegistrationId(); + + String userNameAttributeName = userRequest.getClientRegistration() //사용자 이름 가져오기 + .getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName(); + +// System.out.println(registrationId); +// System.out.println(userNameAttributeName); +// System.out.println("이거야!!"); + + // OAuth2UserService를 사용하여 가져온 OAuth2User 정보로 OAuth2Attribute 객체를 만든다. + OAuth2Attribute oAuth2Attribute = + OAuth2Attribute.of(registrationId, userNameAttributeName, oAuth2User.getAttributes()); + + // OAuth2Attribute의 속성값들을 Map으로 반환 받는다. + Map memberAttribute = oAuth2Attribute.convertToMap(); + + // 사용자 email(또는 id) 정보를 가져온다. + String email = (String) memberAttribute.get("email"); + + System.out.println(email); + + + // 이메일로 가입된 회원인지 조회한다. + Optional findMember = memberService.findByEmail(email); + + if (findMember.isEmpty()) { + // 회원이 존재하지 않을경우, memberAttribute의 exist 값을 false로 넣어준다. + + memberAttribute.put("exist", false); + // 회원의 권한(회원이 존재하지 않으므로 기본권한인 ROLE_USER를 넣어준다), + // 회원속성, 속성이름을 이용해 DefaultOAuth2User 객체를 생성해 반환한다. + return new DefaultOAuth2User( + Collections.singleton(new SimpleGrantedAuthority("ROLE_USER")), + memberAttribute, "email"); + } + + //일단 아이디 잘 따지나 체크 + System.out.println(findMember.get().getId()); + System.out.println("ROLE_".concat(findMember.get().getUserRole())); + + // 여기는 회원인 사람 -> SuccessHandler 에서 jwt 토큰을 발급해서 프론트로 넘겨 주게 된다!! + + // 회원이 존재할경우, memberAttribute의 exist 값을 true로 넣어준다. + //SuccessHandler 에서 exist 변수의 값에 따라서 회원가입을 했는지 안했는지 여부를 체크하고 처리할 수 있게 넣어준다. + memberAttribute.put("exist", true); + + + // 회원의 권한과, 회원속성, 속성이름을 이용해 DefaultOAuth2User 객체를 생성해 반환한다. + return new DefaultOAuth2User( + Collections.singleton(new SimpleGrantedAuthority("ROLE_".concat(findMember.get().getUserRole()))), + memberAttribute, "email"); + + } +} \ No newline at end of file diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/Service/RefreshTokenService.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/Service/RefreshTokenService.java new file mode 100644 index 0000000..bd04f2c --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/Service/RefreshTokenService.java @@ -0,0 +1,29 @@ +package com.todoslave.feedme.login.Service; + +import com.todoslave.feedme.login.dto.RefreshToken; +import com.todoslave.feedme.repository.RefreshTokenRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +public class RefreshTokenService { + + private final RefreshTokenRepository repository; + + @Transactional + public void saveTokenInfo(String email, String refreshToken, String accessToken) { + repository.save(new RefreshToken(email, accessToken, refreshToken)); + } + + @Transactional + public void removeRefreshToken(String accessToken) { + RefreshToken token = repository.findByAccessToken(accessToken) + .orElseThrow(IllegalArgumentException::new); + + repository.delete(token); + } + + +} \ No newline at end of file diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/Service/TokenBlacklistService.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/Service/TokenBlacklistService.java new file mode 100644 index 0000000..dd807e5 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/Service/TokenBlacklistService.java @@ -0,0 +1,27 @@ +package com.todoslave.feedme.login.Service; + +import com.todoslave.feedme.login.TokenBlacklist; +import com.todoslave.feedme.repository.TokenBlacklistRepository; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.Date; +import java.util.Optional; + +@Service +@RequiredArgsConstructor +public class TokenBlacklistService { + + private final TokenBlacklistRepository tokenBlacklistRepository; + + public void addToBlacklist(String token, Date expiryDate) { + TokenBlacklist tokenBlacklist = new TokenBlacklist(token, expiryDate); + tokenBlacklistRepository.save(tokenBlacklist); + } + + public boolean isBlacklisted(String token) { + Optional tokenBlacklist = tokenBlacklistRepository.findByToken(token); + return tokenBlacklist.isPresent(); + } +} \ No newline at end of file diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/TokenBlacklist.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/TokenBlacklist.java new file mode 100644 index 0000000..5da0111 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/TokenBlacklist.java @@ -0,0 +1,36 @@ +package com.todoslave.feedme.login; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Column; +import jakarta.persistence.Table; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.util.Date; + +@Entity +@Table(name = "token_blacklist") +@Getter +@Setter +@NoArgsConstructor +public class TokenBlacklist { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false, unique = true) + private String token; + + @Column(nullable = false) + private Date expiryDate; + + public TokenBlacklist(String token, Date expiryDate) { + this.token = token; + this.expiryDate = expiryDate; + } +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/dto/GeneratedToken.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/dto/GeneratedToken.java new file mode 100644 index 0000000..2c73881 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/dto/GeneratedToken.java @@ -0,0 +1,15 @@ +package com.todoslave.feedme.login.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.ToString; + +@Getter +@AllArgsConstructor +@Builder @ToString +public class GeneratedToken { + + private String accessToken; + private String refreshToken; +} \ No newline at end of file diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/dto/OAuth2Attribute.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/dto/OAuth2Attribute.java new file mode 100644 index 0000000..5dcf530 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/dto/OAuth2Attribute.java @@ -0,0 +1,189 @@ +package com.todoslave.feedme.login.dto;//package com.todoslave.feedme.login.set; +// +//import lombok.AccessLevel; +//import lombok.Builder; +//import lombok.Getter; +//import lombok.ToString; +// +//import java.util.HashMap; +//import java.util.Map; +// +//@ToString +//@Builder(access = AccessLevel.PRIVATE) // Builder 메서드를 외부에서 사용하지 않으므로, Private 제어자로 지정 +//@Getter +//public class OAuth2Attribute { +// private Map attributes; // 사용자 속성 정보를 담는 Map +// private String attributeKey; // 사용자 속성의 키 값 +// private String email; // 이메일 정보 +//// private String name; // 이름 정보 +//// private String picture; // 프로필 사진 정보 +// private String provider; // 제공자 정보 +// +// // 서비스에 따라 OAuth2Attribute 객체를 생성하는 메서드 +// public static OAuth2Attribute of(String provider, String attributeKey, +// Map attributes) { +// switch (provider) { +// case "google": +// return ofGoogle(provider, attributeKey, attributes); +// case "kakao": +// return ofKakao(provider,"email", attributes); +// case "naver": +// return ofNaver(provider, "id", attributes); +// default: +// throw new RuntimeException(); +// } +// } +// +// /* +// * Google 로그인일 경우 사용하는 메서드, 사용자 정보가 따로 Wrapping 되지 않고 제공되어, +// * 바로 get() 메서드로 접근이 가능하다. +// * */ +// private static OAuth2Attribute ofGoogle(String provider, String attributeKey, +// Map attributes) { +// return OAuth2Attribute.builder() +// .email((String) attributes.get("email")) +// .provider(provider) +// .attributes(attributes) +// .attributeKey(attributeKey) +// .build(); +// } +// +// /* +// * Kakao 로그인일 경우 사용하는 메서드, 필요한 사용자 정보가 kakaoAccount -> kakaoProfile 두번 감싸져 있어서, +// * 두번 get() 메서드를 이용해 사용자 정보를 담고있는 Map을 꺼내야한다. +// * */ +// private static OAuth2Attribute ofKakao(String provider, String attributeKey, +// Map attributes) { +// Map kakaoAccount = (Map) attributes.get("kakao_account"); +// Map kakaoProfile = (Map) kakaoAccount.get("profile"); +// +// return OAuth2Attribute.builder() +// .email((String) kakaoAccount.get("email")) +// .provider(provider) +// .attributes(kakaoAccount) +// .attributeKey(attributeKey) +// .build(); +// } +// +// /* +// * Naver 로그인일 경우 사용하는 메서드, 필요한 사용자 정보가 response Map에 감싸져 있어서, +// * 한번 get() 메서드를 이용해 사용자 정보를 담고있는 Map을 꺼내야한다. +// * */ +// private static OAuth2Attribute ofNaver(String provider, String attributeKey, +// Map attributes) { +// Map response = (Map) attributes.get("response"); +// +// return OAuth2Attribute.builder() +// .email((String) response.get("email")) +// .attributes(response) +// .provider(provider) +// .attributeKey(attributeKey) +// .build(); +// } +// +// // OAuth2User 객체에 넣어주기 위해서 Map으로 값들을 반환해준다. +// public Map convertToMap() { +// Map map = new HashMap<>(); +// map.put("id", attributeKey); +// map.put("key", attributeKey); +// map.put("email", email); +// map.put("provider", provider); +// +// return map; +// } +//} + + +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.ToString; + +import java.util.HashMap; +import java.util.Map; + +@ToString +@Builder(access = AccessLevel.PRIVATE) // Builder 메서드를 외부에서 사용하지 않으므로, Private 제어자로 지정 +@Getter +public class OAuth2Attribute { + private Map attributes; // 사용자 속성 정보를 담는 Map + private String attributeKey; // 사용자 속성의 키 값 + private String email; // 이메일 정보 +// private String name; // 이름 정보 +// private String picture; // 프로필 사진 정보 + private String provider; // 제공자 정보 + + // 서비스에 따라 OAuth2Attribute 객체를 생성하는 메서드 + public static OAuth2Attribute of(String provider, String attributeKey, + Map attributes) { + switch (provider) { + case "google": + return ofGoogle(provider, attributeKey, attributes); + case "kakao": + return ofKakao(provider,"email", attributes); + case "naver": + return ofNaver(provider, "id", attributes); + default: + throw new RuntimeException(); + } + } + + /* + * Google 로그인일 경우 사용하는 메서드, 사용자 정보가 따로 Wrapping 되지 않고 제공되어, + * 바로 get() 메서드로 접근이 가능하다. + * */ + private static OAuth2Attribute ofGoogle(String provider, String attributeKey, + Map attributes) { + return OAuth2Attribute.builder() + .email((String) attributes.get("email")) + .provider(provider) + .attributes(attributes) + .attributeKey(attributeKey) + .build(); + } + + /* + * Kakao 로그인일 경우 사용하는 메서드, 필요한 사용자 정보가 kakaoAccount -> kakaoProfile 두번 감싸져 있어서, + * 두번 get() 메서드를 이용해 사용자 정보를 담고있는 Map을 꺼내야한다. + * */ + private static OAuth2Attribute ofKakao(String provider, String attributeKey, + Map attributes) { + Map kakaoAccount = (Map) attributes.get("kakao_account"); + Map kakaoProfile = (Map) kakaoAccount.get("profile"); + + return OAuth2Attribute.builder() + .email((String) kakaoAccount.get("email")) + .provider(provider) + .attributes(kakaoAccount) + .attributeKey(attributeKey) + .build(); + } + + /* + * Naver 로그인일 경우 사용하는 메서드, 필요한 사용자 정보가 response Map에 감싸져 있어서, + * 한번 get() 메서드를 이용해 사용자 정보를 담고있는 Map을 꺼내야한다. + * */ + private static OAuth2Attribute ofNaver(String provider, String attributeKey, + Map attributes) { + Map response = (Map) attributes.get("response"); + + return OAuth2Attribute.builder() + .email((String) response.get("email")) + .attributes(response) + .provider(provider) + .attributeKey(attributeKey) + .build(); + } + + + // OAuth2User 객체에 넣어주기 위해서 Map으로 값들을 반환해준다. + public Map convertToMap() { + Map map = new HashMap<>(); + map.put("id", attributeKey); + map.put("key", attributeKey); + map.put("email", email); + map.put("provider", provider); + + return map; + } +} \ No newline at end of file diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/dto/RefreshToken.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/dto/RefreshToken.java new file mode 100644 index 0000000..48f4562 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/dto/RefreshToken.java @@ -0,0 +1,30 @@ +package com.todoslave.feedme.login.dto; + +import jakarta.persistence.Id; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.ToString; +import org.springframework.data.redis.core.RedisHash; +import org.springframework.data.redis.core.index.Indexed; + +import java.io.Serializable; + +@Getter +@AllArgsConstructor +@ToString +@RedisHash(value = "jwtToken", timeToLive = 60 * 60 * 24 * 14) +public class RefreshToken implements Serializable { + + @Id + private String id; + + @Indexed + private String accessToken; + + private String refreshToken; + + public void updateAccessToken(String accessToken) { + this.accessToken = accessToken; + } + +} \ No newline at end of file diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/dto/TokenResponseStatus.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/dto/TokenResponseStatus.java new file mode 100644 index 0000000..fe1ee28 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/dto/TokenResponseStatus.java @@ -0,0 +1,16 @@ +package com.todoslave.feedme.login.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public class TokenResponseStatus { + + private Integer status; + private String accessToken; + + public static TokenResponseStatus addStatus(Integer status, String accessToken) { + return new TokenResponseStatus(status, accessToken); + } +} \ No newline at end of file diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/util/CookieUtil.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/util/CookieUtil.java new file mode 100644 index 0000000..4e0c55c --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/util/CookieUtil.java @@ -0,0 +1,50 @@ +package com.todoslave.feedme.login.util; + +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.util.SerializationUtils; + +import java.util.Base64; + +public class CookieUtil { + + public static void addCookie(HttpServletResponse response, String name, String value, int maxAge) { + Cookie cookie = new Cookie(name, value); + cookie.setPath("/"); + cookie.setMaxAge(maxAge); + + response.addCookie(cookie); + } + + public static void deleteCookie(HttpServletRequest request, HttpServletResponse response, String name) { + Cookie[] cookies = request.getCookies(); + + if (cookies == null) { + return; + } + + for (Cookie cookie : cookies) { + if (name.equals(cookie.getName())) { + cookie.setValue(""); + cookie.setPath("/"); + cookie.setMaxAge(0); + response.addCookie(cookie); + } + } + } + + public static String serialize(Object obj) { + return Base64.getUrlEncoder() + .encodeToString(SerializationUtils.serialize(obj)); + } + + public static T deserialize(Cookie cookie, Class cls) { + return cls.cast( + SerializationUtils.deserialize( + Base64.getUrlDecoder().decode(cookie.getValue()) + ) + ); + } +} + diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/util/SecurityUserDto.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/util/SecurityUserDto.java new file mode 100644 index 0000000..1fd83a5 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/util/SecurityUserDto.java @@ -0,0 +1,16 @@ +package com.todoslave.feedme.login.util; + + +import lombok.*; + +@NoArgsConstructor +@Getter +@ToString +@AllArgsConstructor +@Builder +public class SecurityUserDto { + private Integer id; + private String email; + private String nickname; + private String role; +} \ No newline at end of file diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/util/SecurityUtil.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/util/SecurityUtil.java new file mode 100644 index 0000000..4b17487 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/login/util/SecurityUtil.java @@ -0,0 +1,42 @@ +package com.todoslave.feedme.login.util; + +import com.todoslave.feedme.domain.entity.membership.Member; +import com.todoslave.feedme.repository.MemberRepository; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.Authentication; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class SecurityUtil { + + private static MemberRepository memberRepository; + + @Autowired + public SecurityUtil(MemberRepository memberRepository) { + SecurityUtil.memberRepository = memberRepository; + } + + public static SecurityUserDto getCurrentUser() { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + + if (authentication != null && authentication.getPrincipal() instanceof SecurityUserDto) { + return (SecurityUserDto) authentication.getPrincipal(); + } + + return null; // 인증 정보가 없는 경우 처리 + } + + public static int getCurrentUserId() { + SecurityUserDto userDto = getCurrentUser(); + return (userDto != null) ? userDto.getId() : -1; // -1로 대체하여 null 피하기 + } + + public static Member getCurrentMember() { + SecurityUserDto userDto = getCurrentUser(); + if (userDto != null) { + return memberRepository.findById(userDto.getId()).orElse(null); + } + return null; + } +} \ No newline at end of file diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/mapper/AlarmMapper.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/mapper/AlarmMapper.java new file mode 100644 index 0000000..37c59b7 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/mapper/AlarmMapper.java @@ -0,0 +1,14 @@ +package com.todoslave.feedme.mapper; + +import com.todoslave.feedme.DTO.AlarmResponseDTO; +import com.todoslave.feedme.domain.entity.alarm.Alarm; + +public class AlarmMapper { + + public static AlarmResponseDTO toDto(Alarm alarm){ + AlarmResponseDTO dto = new AlarmResponseDTO(); + dto.setContent(alarm.getContent()); + return dto; + } + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/mapper/FriendRequestMapper.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/mapper/FriendRequestMapper.java new file mode 100644 index 0000000..249690f --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/mapper/FriendRequestMapper.java @@ -0,0 +1,23 @@ +package com.todoslave.feedme.mapper; + +import com.todoslave.feedme.DTO.FriendReqResponseDTO; +import com.todoslave.feedme.domain.entity.avatar.Creature; +import com.todoslave.feedme.domain.entity.communication.FriendRequest; +import com.todoslave.feedme.repository.CreatureRepository; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class FriendRequestMapper { + + private static CreatureRepository creatureRepository; + + public static FriendReqResponseDTO toDto(FriendRequest friendRequest){ + FriendReqResponseDTO dto = new FriendReqResponseDTO(); + dto.setId(friendRequest.getId()); + dto.setCounterpartNickname(friendRequest.getCounterpartId().getNickname()); + Creature creature = creatureRepository.findByMemberId(friendRequest.getId()); + dto.setCreatureImg("https://i11b104.p.ssafy.io/image/creature/"+creature.getMember().getId()+"_"+creature.getLevel()); + return dto; + } + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/AlarmRepository.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/AlarmRepository.java index 01317fa..6a0dee3 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/AlarmRepository.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/AlarmRepository.java @@ -1,12 +1,15 @@ package com.todoslave.feedme.repository; -import com.todoslave.feedme.domain.entity.check.Alarm; +import com.todoslave.feedme.domain.entity.alarm.Alarm; +import java.time.LocalDateTime; import java.util.List; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; import org.springframework.data.jpa.repository.JpaRepository; public interface AlarmRepository extends JpaRepository { -// List findByMemberIdAndReadFalse(int memberId, boolean read); + Slice findByMemberId(int memberId, Pageable pageable); } diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/CreatureRepository.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/CreatureRepository.java new file mode 100644 index 0000000..22b824a --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/CreatureRepository.java @@ -0,0 +1,12 @@ +package com.todoslave.feedme.repository; + +import com.todoslave.feedme.domain.entity.avatar.Creature; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface CreatureRepository extends JpaRepository { + + Creature findByMemberId(int memberId); + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/CreatureTodoReposito.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/CreatureTodoReposito.java new file mode 100644 index 0000000..502b637 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/CreatureTodoReposito.java @@ -0,0 +1,20 @@ +package com.todoslave.feedme.repository; + +import com.todoslave.feedme.domain.entity.task.CreatureTodo; +import com.todoslave.feedme.domain.entity.task.Todo; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.sql.Timestamp; +import java.time.LocalDate; +import java.util.List; +import java.util.Optional; + +@Repository +public interface CreatureTodoReposito extends JpaRepository { + List findByMemberIdAndCreatedAt(int memberId, LocalDate createdAt); + Optional findById(int memberId); + + // 특정 날짜와 완료 여부로 CreatureTodo의 개수를 계산하는 메서드 + long countByCreatedAtAndIsCompleted(LocalDate createdAt, int isCompleted); +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/DayOffRepository.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/DayOffRepository.java new file mode 100644 index 0000000..7b6ccb6 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/DayOffRepository.java @@ -0,0 +1,17 @@ +package com.todoslave.feedme.repository; + +import com.todoslave.feedme.domain.entity.task.DayOff; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.time.LocalDate; +import java.util.List; +import java.util.Optional; + +@Repository +public interface DayOffRepository extends JpaRepository { + + // 특정 회원의 특정 날짜의 DayOff를 찾습니다. + Optional findByMemberIdAndEndDay(int memberId, LocalDate endDay); + long countByMemberIdAndEndDay(int memberId, LocalDate date); +} \ No newline at end of file diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/DiaryRepository.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/DiaryRepository.java new file mode 100644 index 0000000..1aa5dbf --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/DiaryRepository.java @@ -0,0 +1,7 @@ +package com.todoslave.feedme.repository; + +import com.todoslave.feedme.domain.entity.diary.PictureDiary; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface DiaryRepository extends JpaRepository { +} \ No newline at end of file diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/FeedCommentRepository.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/FeedCommentRepository.java new file mode 100644 index 0000000..60cf365 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/FeedCommentRepository.java @@ -0,0 +1,11 @@ +package com.todoslave.feedme.repository; + +import com.todoslave.feedme.domain.entity.Feed.Feed; +import com.todoslave.feedme.domain.entity.Feed.FeedComment; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface FeedCommentRepository extends JpaRepository { + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/FeedLikeRepository.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/FeedLikeRepository.java new file mode 100644 index 0000000..d2221fc --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/FeedLikeRepository.java @@ -0,0 +1,14 @@ +package com.todoslave.feedme.repository; + +import com.todoslave.feedme.domain.entity.Feed.Feed; +import com.todoslave.feedme.domain.entity.Feed.FeedLike; +import com.todoslave.feedme.domain.entity.membership.Member; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface FeedLikeRepository extends JpaRepository { + boolean existsByMemberAndFeed(Member member, Feed feed); + FeedLike findByMemberAndFeed(Member member, Feed feed); + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/FeedRepository.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/FeedRepository.java new file mode 100644 index 0000000..0133359 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/FeedRepository.java @@ -0,0 +1,21 @@ +package com.todoslave.feedme.repository; + +import com.todoslave.feedme.domain.entity.Feed.Feed; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +import java.time.LocalDateTime; +import java.util.List; + +@Repository +public interface FeedRepository extends JpaRepository { + + @Query("SELECT f FROM Feed f WHERE f.createdAt >= :startDate ORDER BY f.createdAt DESC") + List findRecentFeeds(@Param("startDate") LocalDateTime startDate); + + @Query("SELECT f FROM Feed f WHERE f.createdAt >= :startDate AND (f.member.id = :memberId OR f.member.id IN (SELECT fr.counterpart.id FROM Friend fr WHERE fr.member.id = :memberId)) ORDER BY f.createdAt DESC") + List findRecentFeedsByFriendsAndMe(@Param("startDate") LocalDateTime startDate, @Param("memberId") int memberId); + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/FriendRepository.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/FriendRepository.java index ef56edc..e30f4d7 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/FriendRepository.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/FriendRepository.java @@ -2,13 +2,18 @@ import com.todoslave.feedme.domain.entity.communication.Friend; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; import java.util.List; +@Repository public interface FriendRepository extends JpaRepository { List findAllByMemberId(int memberId); + int findByMemberIdAndCounterpartId(int memberId, int counterpartId); + boolean existsByMemberIdAndCounterpartId(int memberId, int counterpartId); + boolean existsByCounterpartIdAndMemberId(int counterpartId, int memberId); } diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/FriendRequestRepository.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/FriendRequestRepository.java index 6c3d42e..b3b0768 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/FriendRequestRepository.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/FriendRequestRepository.java @@ -1,13 +1,19 @@ package com.todoslave.feedme.repository; +import com.todoslave.feedme.domain.entity.communication.Friend; import com.todoslave.feedme.domain.entity.communication.FriendRequest; +import com.todoslave.feedme.domain.entity.membership.Member; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; import java.util.List; +import java.util.Optional; public interface FriendRequestRepository extends JpaRepository { FriendRequest findById(int id); - List findAllByMemberId(int memberId); - + Slice findAllByMemberId(int memberId, Pageable pageable); + Optional findByMember_IdAndCounterpartId_Id(int memberId, int counterpartId); } diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/MemberAlarmRepository.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/MemberAlarmRepository.java new file mode 100644 index 0000000..03251e7 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/MemberAlarmRepository.java @@ -0,0 +1,14 @@ +package com.todoslave.feedme.repository; + +import com.todoslave.feedme.domain.entity.alarm.Alarm; +import com.todoslave.feedme.domain.entity.membership.MemberAlarm; +import java.util.List; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.repository.query.Param; + + +public interface MemberAlarmRepository extends JpaRepository { + + + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/MemberChatRoomCheckedRepository.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/MemberChatRoomCheckedRepository.java new file mode 100644 index 0000000..8950ea5 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/MemberChatRoomCheckedRepository.java @@ -0,0 +1,11 @@ +package com.todoslave.feedme.repository; + +import com.todoslave.feedme.domain.entity.communication.MemberChatRoomChecked; +import org.springframework.data.mongodb.repository.MongoRepository; + +public interface MemberChatRoomCheckedRepository + extends MongoRepository { + + MemberChatRoomChecked findByMemberChatRoomIdAndMemberId(String memberChatRoomId, int memberId); + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/MemberChatRoomRepository.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/MemberChatRoomRepository.java index 549646a..1fb2450 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/MemberChatRoomRepository.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/MemberChatRoomRepository.java @@ -11,10 +11,10 @@ public interface MemberChatRoomRepository extends MongoRepository participantIds); + MemberChatRoom findByParticipantIdsContainingAll(List participantIds); // 방 여러개 얻어오기 - List findAllByParticipantIdsContaining(List participantIds); + List findAllByParticipantIdsContainingOrderByReceiveTime(List participantIds); // save 메서드는 이미 몽고디비에 존재하므로 재 정의 할 필요 X diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/MemberRepository.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/MemberRepository.java index 801f871..a082772 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/MemberRepository.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/MemberRepository.java @@ -6,35 +6,19 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.time.LocalDate; import java.util.List; +import java.util.Optional; -//@Repository //Component가 들어가있다. +@Repository public interface MemberRepository extends JpaRepository { -// @PersistenceContext //여기에 JPA의 em를 자기가 주입을 해줘서 스프링이 알아서 해준다. -// private EntityManager em; //이 엔티티매니저를 이렇게 해주면 스프링이 엔티티 매니져를 만들어서 주입해준다. - -// //맴버 저장 -// public void save(Member member) { -// em.persist(member); -// } -// -// // ID로 찾기 -// public Member findById(int id) { -// return em.find(Member.class, id); -// } -// -// // 모든 맴버 찾기 -// public List findAll() { -// return em.createQuery("select m from Member m", Member.class) -// .getResultList(); -// } -// -// // 이름으로 찾기 -// public List findByName(String nickname) { -// return em.createQuery("select m from Member m where m.nickname = :nickname", Member.class) -// .setParameter("nickname", nickname) -// .getResultList(); -// } - + Optional findByEmail(String email); + Optional findById(Integer id); + List findByNicknameContaining(String searchValue); + Optional findByNickname(String nickname); + List findAllByBirthday(LocalDate date); + boolean existsByNickname(String nickname); + } + diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/MissionRepository.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/MissionRepository.java new file mode 100644 index 0000000..7995167 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/MissionRepository.java @@ -0,0 +1,11 @@ +package com.todoslave.feedme.repository; +import com.todoslave.feedme.domain.entity.mission.Mission; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface MissionRepository extends JpaRepository { + List findByWeatherCondition(String weatherCondition); +} \ No newline at end of file diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/RefreshTokenRepository.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/RefreshTokenRepository.java new file mode 100644 index 0000000..bfae470 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/RefreshTokenRepository.java @@ -0,0 +1,15 @@ +package com.todoslave.feedme.repository; + +import com.todoslave.feedme.login.dto.RefreshToken; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface RefreshTokenRepository extends CrudRepository { + + // accessToken으로 RefreshToken을 찾아온다. + Optional findByAccessToken(String accessToken); + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/TestRepository.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/TestRepository.java deleted file mode 100644 index c4223a4..0000000 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/TestRepository.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.todoslave.feedme.repository; - -public class TestRepository { -} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/TodoCategoryRepository.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/TodoCategoryRepository.java new file mode 100644 index 0000000..5aad93e --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/TodoCategoryRepository.java @@ -0,0 +1,13 @@ +package com.todoslave.feedme.repository; + +import com.todoslave.feedme.domain.entity.task.TodoCategory; +import java.util.List; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface TodoCategoryRepository extends JpaRepository { + + List findAllByMemberId(int memberId); + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/TodoRepository.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/TodoRepository.java index c8b7e1b..63757f2 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/TodoRepository.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/TodoRepository.java @@ -1,9 +1,12 @@ package com.todoslave.feedme.repository; import com.todoslave.feedme.domain.entity.task.Todo; +import java.time.LocalDate; import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Optional; + import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; @@ -13,6 +16,16 @@ public interface TodoRepository extends JpaRepository { @Query("SELECT t FROM Todo t WHERE t.member.id = :memberId AND FUNCTION('DATE', t.createdAt) = :createdAt") - List findAllByMemberIdAndCreatedAt(@Param("memberId") int memberId, @Param("createdAt") Date createdAt); + List findAllByMemberIdAndCreatedAt(@Param("memberId") int memberId, @Param("createdAt") LocalDate createdAt); + + @Query("SELECT t FROM Todo t WHERE t.member.id = :memberId AND FUNCTION('DATE', t.createdAt) = :createdAt AND t.isCompleted = :isCompleted") + List findAllByMemberIdAndCreatedAtIsCompleted(@Param("memberId") int memberID, @Param("createdAt") LocalDate createdAt,@Param("isCompleted") int isCompleted); + + @Query("SELECT t.member.id FROM Todo t WHERE t.createdAt = :createdAt AND t.isCompleted = 0") + List findMemberIdAllByCreatedAtAndIsCompleted(LocalDate createdAt); + + @Query("SELECT COUNT(t) FROM Todo t WHERE t.createdAt = :date AND t.isCompleted = :isCompleted") + long countTodoByDateAndIsCompleted(@Param("date") LocalDate date, @Param("isCompleted") int isCompleted); + List findByMemberIdAndCreatedAt(int memberId, LocalDate createdAt); } diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/TokenBlacklistRepository.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/TokenBlacklistRepository.java new file mode 100644 index 0000000..7083dbf --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/repository/TokenBlacklistRepository.java @@ -0,0 +1,10 @@ +package com.todoslave.feedme.repository; + +import com.todoslave.feedme.login.TokenBlacklist; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface TokenBlacklistRepository extends JpaRepository { + Optional findByToken(String token); +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/AlarmService.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/AlarmService.java index ba5baa7..b0a7e61 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/AlarmService.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/AlarmService.java @@ -1,5 +1,29 @@ package com.todoslave.feedme.service; +import com.todoslave.feedme.DTO.AlarmResponseDTO; +import com.todoslave.feedme.DTO.AlarmSetRequestDTO; +import com.todoslave.feedme.DTO.FriendReqResponseDTO; +import com.todoslave.feedme.DTO.MemberChatListResponseDTO; +import com.todoslave.feedme.DTO.PaginationRequestDTO; +import com.todoslave.feedme.domain.entity.alarm.Alarm; +import com.todoslave.feedme.domain.entity.communication.MemberChatMessage; +import com.todoslave.feedme.domain.entity.membership.Member; +import java.io.IOException; +import java.time.LocalDateTime; +import org.springframework.data.domain.Slice; +import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; + public interface AlarmService { + void createAlarmtime(AlarmSetRequestDTO alarmSetRequestDTO); + SseEmitter createEmitter(); + void todoCompleted() throws IOException; + void requestFriendship(FriendReqResponseDTO friendReqResponseDTO) throws IOException; + void congratsBirthday() throws IOException; + SseEmitter renewCreateEmitter(); + void renewChattingRoom(MemberChatListResponseDTO room, int memberId) throws IOException; + public void sendAlarm(T alarm, int type) throws IOException; + Slice loadAlarms(PaginationRequestDTO paginationRequestDTO); + + } diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/AlarmServiceImpl.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/AlarmServiceImpl.java index ea4f6f4..0fc66d6 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/AlarmServiceImpl.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/AlarmServiceImpl.java @@ -1,14 +1,221 @@ package com.todoslave.feedme.service; +import com.todoslave.feedme.DTO.AlarmResponseDTO; +import com.todoslave.feedme.DTO.AlarmSetRequestDTO; +import com.todoslave.feedme.DTO.FriendReqResponseDTO; +import com.todoslave.feedme.DTO.MemberChatListResponseDTO; +import com.todoslave.feedme.DTO.PaginationRequestDTO; +import com.todoslave.feedme.domain.entity.alarm.Alarm; +import com.todoslave.feedme.domain.entity.avatar.Creature; +import com.todoslave.feedme.domain.entity.communication.MemberChatMessage; +import com.todoslave.feedme.domain.entity.communication.MemberChatRoomChecked; +import com.todoslave.feedme.domain.entity.membership.Member; +import com.todoslave.feedme.domain.entity.membership.MemberAlarm; +import com.todoslave.feedme.login.util.SecurityUserDto; +import com.todoslave.feedme.login.util.SecurityUtil; +import com.todoslave.feedme.mapper.AlarmMapper; import com.todoslave.feedme.repository.AlarmRepository; +import com.todoslave.feedme.repository.CreatureRepository; +import com.todoslave.feedme.repository.MemberAlarmRepository; +import com.todoslave.feedme.repository.MemberChatRoomCheckedRepository; +import com.todoslave.feedme.repository.MemberRepository; +import com.todoslave.feedme.repository.TodoRepository; +import jakarta.transaction.Transactional; +import java.io.IOException; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import javax.swing.text.html.parser.Entity; import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; +import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; @RequiredArgsConstructor +@Service public class AlarmServiceImpl implements AlarmService{ - private AlarmRepository alarmRepository; + private final AlarmRepository alarmRepository; + private final MemberAlarmRepository memberAlarmRepository; + private final TodoRepository todoRepository; + private final MemberRepository memberRepository; + private final CreatureRepository creatureRepository; + private final MemberChatRoomCheckedRepository memberChatRoomCheckedRepository; + private final Map emitters = new ConcurrentHashMap<>(); + private final Map chatEmitters = new ConcurrentHashMap<>(); + + + @Override + public void createAlarmtime(AlarmSetRequestDTO alarmSetRequestDTO) { + + Member member = SecurityUtil.getCurrentMember(); + + MemberAlarm memberAlarm = new MemberAlarm(); + + memberAlarm.setMember(member); + memberAlarm.setAlarmTime(alarmSetRequestDTO.getAlarmTime()); + + memberAlarm = memberAlarmRepository.save(memberAlarm); + + } + + @Override + public SseEmitter createEmitter() { + + int memberId = SecurityUtil.getCurrentUserId(); + + SseEmitter emitter = new SseEmitter(); + emitters.put(memberId, emitter); + + emitter.onCompletion(() -> emitters.remove(memberId)); + emitter.onTimeout(() -> emitters.remove(memberId)); + emitter.onError((e) -> emitters.remove(memberId)); + + return emitter; + } + + //1시간 마다 확인, 일정 완료 했는지 여부 + @Scheduled(cron = "0 0 * * * ?") + public void todoCompleted() throws IOException { + + LocalDate currentDay = LocalDate.now(); + List members = todoRepository.findMemberIdAllByCreatedAtAndIsCompleted(currentDay); + + for(int memberId : members) { + + LocalTime currentTime = LocalTime.now(); + int time = currentTime.getHour(); + + Alarm alarm = new Alarm(); + + Member member = new Member(); + member.setId(memberId); + + Creature creature = creatureRepository.findByMemberId(memberId); + + alarm.setMember(member); + alarm.setContent("배고픈 " + creature.getCreatureName() + ".. 밥 줄 사람 없나요?"); + alarmRepository.save(alarm); + + sendAlarm(alarm, 0); + + } + } + + //친구 요청 알림 + public void requestFriendship(FriendReqResponseDTO friendReqResponseDTO) throws IOException { + + int memberId = SecurityUtil.getCurrentUserId(); + sendAlarm(friendReqResponseDTO,1); + + } + + //생일 알림 + @Scheduled(cron = "0 0 0 * * *") + public void congratsBirthday() throws IOException { + + LocalDate date = LocalDate.now(); + List birthdayPerson = memberRepository.findAllByBirthday(date); + + Alarm alarm = new Alarm(); + + for(Member member : birthdayPerson){ + + alarm.setMember(member); + alarm.setContent(member.getNickname()+"님! 생일 축하합니다!"); + + alarmRepository.save(alarm); + sendAlarm(alarm, 0); + + } + + } + + // 채팅방 목록 페이지 들어왔을 때 + @Override + public SseEmitter renewCreateEmitter() { + int memberId = SecurityUtil.getCurrentUserId(); + + SseEmitter emitter = new SseEmitter(); + chatEmitters.put(memberId, emitter); + + emitter.onCompletion(() -> chatEmitters.remove(memberId)); + emitter.onTimeout(() -> chatEmitters.remove(memberId)); + emitter.onError((e) -> emitters.remove(memberId)); + + return emitter; + } + + // 채팅방 갱신 + @Override + @Transactional + public void renewChattingRoom(MemberChatListResponseDTO room, int memberId) throws IOException { + + SseEmitter emitter = chatEmitters.get(memberId); + + if(emitter!=null) { + SseEmitter.SseEventBuilder event = SseEmitter.event() + .name("chattingRoom") + .data(room); + + emitter.send(event); + }else{ + System.out.println("Sse Connection fail"); + } + + } + + // 알람 받아라 + @Override + public void sendAlarm(T alarm, int type) throws IOException { + + int memberId = SecurityUtil.getCurrentUserId(); + SseEmitter emitter = emitters.get(memberId); + + if(emitter!=null){ + + if(type==0) { + AlarmResponseDTO dto = AlarmMapper.toDto((Alarm) alarm); + + SseEmitter.SseEventBuilder event = SseEmitter.event() + .name("alarm") + .data(dto); + + emitter.send(event); + }else if(type==1){ + SseEmitter.SseEventBuilder event = SseEmitter.event() + .name("friend") + .data(alarm); + + emitter.send(event); + } + + }else{ + System.out.println("Sse connect fail"); + } + + } + + public Slice loadAlarms(PaginationRequestDTO paginationRequestDTO){ + Pageable pageable = PageRequest.of(paginationRequestDTO.getSkip() / paginationRequestDTO.getLimit(), + paginationRequestDTO.getLimit()); + + int memberId = SecurityUtil.getCurrentUserId(); + + Slice alarm = alarmRepository.findByMemberId(memberId, pageable); + + return alarm.map(AlarmMapper::toDto); + } } diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/CreatureService.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/CreatureService.java new file mode 100644 index 0000000..a747e98 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/CreatureService.java @@ -0,0 +1,27 @@ +package com.todoslave.feedme.service; + + +import com.todoslave.feedme.DTO.CreatureInfoResponseDTO; +import com.todoslave.feedme.domain.entity.avatar.Creature; + +import com.todoslave.feedme.domain.entity.membership.Member; +import org.springframework.web.multipart.MultipartFile; + +import javax.swing.*; + + +public interface CreatureService { + + + //크리쳐 만들기 + Creature createFristCreature(String keyword, String photo, String creatureName); + //크리쳐 정보 가져오기 + CreatureInfoResponseDTO creatureInfo(Member member); + //크리쳐 삭제하기 + boolean removeCreature(); + //크리쳐 경험치 올리기 + void expUp(int toDoCnt); + + + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/CreatureServiceImpl.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/CreatureServiceImpl.java new file mode 100644 index 0000000..44742a5 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/CreatureServiceImpl.java @@ -0,0 +1,194 @@ +package com.todoslave.feedme.service; + +import com.todoslave.feedme.DTO.CreatureInfoResponseDTO; +import com.todoslave.feedme.domain.entity.avatar.Creature; +import com.todoslave.feedme.domain.entity.membership.Emotion; +import com.todoslave.feedme.domain.entity.membership.Member; +import com.todoslave.feedme.login.util.SecurityUtil; +import com.todoslave.feedme.repository.CreatureRepository; +import com.todoslave.feedme.repository.MemberRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.multipart.MultipartFile; + +import javax.swing.*; +import java.time.LocalDate; +import java.time.Period; + +@Service +@RequiredArgsConstructor +public class CreatureServiceImpl implements CreatureService { + + @Autowired + final private MemberRepository memberRepository; + @Autowired + final private CreatureRepository creatureRepository; + + //크리쳐 만들기 + @Override + public Creature createFristCreature(String keyword, String photo, String creatureName) { + //멤버 가져오고 + Member member = SecurityUtil.getCurrentMember(); + //크리쳐 만들고 + Creature creature = new Creature(); + //이름 설정하고 + creature.setCreatureName(creatureName); + //멤버와 매핑 시켜주고 + creature.setMember(member); + //경험치와 레벨은 자동 0으로 설정 + + creature.setCreatureKeyword(keyword); + creatureRepository.save(creature); //저장 + + //여기서 사진 만들라고 명령 내리시고!!!!!!!!!!!!!!!!!!!!!! + + return creature; + } + + +// @Override +// public Creature createFristCreature(String keyword, MultipartFile photo, String creatureName) { +// Member member = SecurityUtil.getCurrentMember(); +// +// Creature creature = new Creature(); +// creature.setCreatureName(creatureName); +// creature.setMember(member); +// creature.setCreatureKeyword(keyword); + +// // 사진을 AI 서버로 바로 전송 +// sendPhotoToAIServer(photo, keyword); +// +// creatureRepository.save(creature); +// +// return creature; +// } +// +// private void sendPhotoToAIServer(MultipartFile photo, String keyword) { +// // HTTP 클라이언트를 사용하여 파일을 AI 서버에 전송하는 로직 작성 +// // 예시로 RestTemplate 사용 +// RestTemplate restTemplate = new RestTemplate(); +// +// MultiValueMap body = new LinkedMultiValueMap<>(); +// body.add("file", photo.getResource()); // MultipartFile을 바로 전송 +// body.add("keyword", keyword); // 추가로 필요한 파라미터들 +// +// HttpHeaders headers = new HttpHeaders(); +// headers.setContentType(MediaType.MULTIPART_FORM_DATA); +// +// HttpEntity> requestEntity = new HttpEntity<>(body, headers); +// +// String aiServerUrl = "http://ai-server-url/endpoint"; // AI 서버의 URL +// +// ResponseEntity response = restTemplate.postForEntity(aiServerUrl, requestEntity, String.class); +// +// if (!response.getStatusCode().is2xxSuccessful()) { +// throw new RuntimeException("AI 서버로 사진 전송에 실패했습니다."); +// } +// } + + + + + + // 크리쳐 보기 + @Override + + public CreatureInfoResponseDTO creatureInfo(Member member) { + + CreatureInfoResponseDTO creatureInfoResponseDTO = new CreatureInfoResponseDTO(); + creatureInfoResponseDTO.setName(member.getCreature().getCreatureName()); + creatureInfoResponseDTO.setLevel(member.getCreature().getLevel()); + creatureInfoResponseDTO.setExp(member.getCreature().getExp()); + creatureInfoResponseDTO.setImg(generateCreatureImgPath(member)); + + // 현재 날짜 가져오기 + LocalDate currentDate = LocalDate.now(); + // 가입 날짜 가져오기 (Timestamp를 LocalDate로 변환) + LocalDate joinDate = member.getJoinDate().toLocalDate(); + // 가입한 날로부터 며칠째인지 계산 + int daysSinceJoin = Period.between(joinDate, currentDate).getDays(); + + // day 설정 + creatureInfoResponseDTO.setDay(daysSinceJoin); + + return creatureInfoResponseDTO; + } + + //크리쳐 삭제(재발급을 위한) + @Override + public boolean removeCreature() { + Member member = SecurityUtil.getCurrentMember(); + Creature creature = member.getCreature(); + creatureRepository.delete(creature); + member.setCreature(null); + memberRepository.save(member); + return true; + } + + //크리쳐 성장 + @Override + public void expUp(int toDoCnt) { + + Creature creature = SecurityUtil.getCurrentMember().getCreature(); + + System.out.println(creature.toString()); + + // 하루 오를 수 있는 최대한의 경험치 제한 + if (toDoCnt > 7) { + toDoCnt = 7; + } + + int nowExp = creature.getExp() + toDoCnt; + + // 현재 레벨에 따른 경험치와 레벨업 조건 처리 + switch (creature.getLevel()) { + case 0: // 알 + if (nowExp >= 10) { // 레벨업 조건 + creature.setLevel(1); + creature.setExp(nowExp - 10); + } else { + System.out.println(nowExp); + creature.setExp(nowExp); + } + break; + case 1: // 1레벨 + if (nowExp >= 30) { // 레벨업 조건 + creature.setLevel(2); + creature.setExp(nowExp - 30); + } else { + creature.setExp(nowExp); + } + break; + case 2: // 2레벨 + if (nowExp >= 100) { // 레벨업 조건 + creature.setLevel(3); + creature.setExp(nowExp - 100); + } else { + creature.setExp(nowExp); + } + break; + case 3: // 3레벨 + default: + creature.setExp(nowExp); + break; + } + creatureRepository.save(creature); + } + + + //크리쳐 이미지 주소 + private String generateCreatureImgPath(Member member) { + Creature creature = member.getCreature(); + int creatureLevel = creature.getLevel(); + int creatureId = creature.getId(); + return "https://i11b104.p.ssafy.io/image/creature/" + creatureId + "_" +creatureLevel; + } +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/CreatureTodoService.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/CreatureTodoService.java new file mode 100644 index 0000000..9d453c6 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/CreatureTodoService.java @@ -0,0 +1,28 @@ +package com.todoslave.feedme.service; + +import com.todoslave.feedme.DTO.*; + +import java.time.LocalDate; +import java.util.List; + +public interface CreatureTodoService { + + // 크리쳐 일정 생성 (날씨 영향) + List insertTodo(String weather); + + // 해당 날의 일정 가져오기 + List getCreatureTodoCalendarDaily(CretureTodoRequestDTO cretureTodoRequestDTO); + + // 내일날 어제날 가져올 수 있게! + List getCreatureTodoListDaily(CreatureTodoDailyRequestDTO creatureTodoDailyRequestDTO); + + // 일정 하나 완료/취소 하기 + CreatureTodoResponseDTO completeTodo(int CreaturetoId); + + // 메인화면에서 당일 안한 일정들 불러오기 (할일 목록에서 일정 불러오기) + List getCreatureTodoMainDaily(); + + + + +} \ No newline at end of file diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/CreatureTodoServiceImpl.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/CreatureTodoServiceImpl.java new file mode 100644 index 0000000..4981228 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/CreatureTodoServiceImpl.java @@ -0,0 +1,175 @@ +package com.todoslave.feedme.service; + +import com.todoslave.feedme.DTO.CreatureTodoDailyRequestDTO; +import com.todoslave.feedme.DTO.CreatureTodoResponseDTO; +import com.todoslave.feedme.DTO.CretureTodoRequestDTO; +import com.todoslave.feedme.DTO.TodoRequestDTO; +import com.todoslave.feedme.domain.entity.mission.Mission; +import com.todoslave.feedme.domain.entity.task.CreatureTodo; +import com.todoslave.feedme.login.util.SecurityUtil; +import com.todoslave.feedme.repository.CreatureTodoReposito; +import com.todoslave.feedme.repository.DayOffRepository; +import com.todoslave.feedme.repository.MissionRepository; +import com.todoslave.feedme.repository.TodoRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.sql.Timestamp; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +@Service +@RequiredArgsConstructor +public class CreatureTodoServiceImpl implements CreatureTodoService{ + + final private DayOffRepository dayOffRepository; + + + @Autowired + final private MissionRepository missionRepository; + @Autowired + final private CreatureTodoReposito creatureTodoRepository; + private Random random = new Random(); + // 로그인시에 없으면 생성 + + @Override + public List insertTodo(String weather) { + + int memberId = SecurityUtil.getCurrentMember().getId(); + LocalDate today = LocalDate.now(); + List todayTodos = creatureTodoRepository.findByMemberIdAndCreatedAt(memberId, today); + + if (!todayTodos.isEmpty()) { + return null; // 오늘의 미션이 이미 생성되었으면 null 반환 + } + + + List missions = missionRepository.findByWeatherCondition(weather); + + if (missions.isEmpty()) { + missions = missionRepository.findByWeatherCondition("default"); + } + + System.out.println(missions.size()+"감자테"); + Mission selectedMission = missions.get(random.nextInt(missions.size())); + + List Dmissions= missionRepository.findByWeatherCondition("default"); + Mission selectedDMission = Dmissions.get(random.nextInt(Dmissions.size())); + + CreatureTodo creatureTodo1 = new CreatureTodo(); + creatureTodo1.setContent(selectedMission.getMission()); + creatureTodo1.setMember(SecurityUtil.getCurrentMember()); + + CreatureTodo creatureTodo2 = new CreatureTodo(); + creatureTodo2.setContent(selectedDMission.getMission()); + creatureTodo2.setMember(SecurityUtil.getCurrentMember()); + + creatureTodoRepository.save(creatureTodo1); + creatureTodoRepository.save(creatureTodo2); + + // ResponseDTO 리스트 생성 + List responseDTOList = new ArrayList<>(); + responseDTOList.add(toResponseDTO(creatureTodo1)); + responseDTOList.add(toResponseDTO(creatureTodo2)); + + return responseDTOList; + } + + //일정을 완료 했는지 안했는지 체크 + public boolean isActionAllowed(int memberId, LocalDate date) { + return dayOffRepository.countByMemberIdAndEndDay(memberId, date) == 0; + } + + //DTO 변환 + private CreatureTodoResponseDTO toResponseDTO(CreatureTodo creatureTodo) { + + + return CreatureTodoResponseDTO.builder() + .id(creatureTodo.getId()) + .content(creatureTodo.getContent()) + .createdAt(creatureTodo.getCreatedAt()) + .isCompleted(creatureTodo.getIsCompleted()) +// .diaryIsCompleted(!checked) //그래서 역전 + .build(); + } + + //해당일 정보 가져오기 + @Override + public List getCreatureTodoCalendarDaily(CretureTodoRequestDTO cretureTodoRequestDTO) { + + int memberId = SecurityUtil.getCurrentMember().getId(); + List todayTodos = creatureTodoRepository.findByMemberIdAndCreatedAt(memberId, cretureTodoRequestDTO.getDate()); + + List responseDTOList = new ArrayList<>(); + for (CreatureTodo creatureTodo : todayTodos) { + responseDTOList.add(toResponseDTO(creatureTodo)); + } + return responseDTOList; + } + + + //일 하나 완료하기 + @Override + public CreatureTodoResponseDTO completeTodo(int CreaturetoId) { + // 나중가서 ㅇㅋ 취소는 할 수 있음 단 경험치는 안줌 + CreatureTodo creatureTodo = creatureTodoRepository.findById(CreaturetoId).orElse(null); + + if (creatureTodo.getIsCompleted()==1) { + creatureTodo.setIsCompleted(0); + }else{ + creatureTodo.setIsCompleted(1); + } + creatureTodoRepository.save(creatureTodo); + return toResponseDTO(creatureTodo); + } + + //오늘 안한것만 당겨오게 + @Override + public List getCreatureTodoMainDaily() { + LocalDate today = LocalDate.now(); + int memberId = SecurityUtil.getCurrentMember().getId(); + List todayTodos = creatureTodoRepository.findByMemberIdAndCreatedAt(memberId, today); + + List responseDTOList = new ArrayList<>(); + + for (CreatureTodo creatureTodo : todayTodos) { + if (creatureTodo.getIsCompleted()==0) { + responseDTOList.add(toResponseDTO(creatureTodo)); + } + } + + return responseDTOList; + } + + //매서드 이름 바꿨네 + @Override + public List getCreatureTodoListDaily(CreatureTodoDailyRequestDTO creatureTodoDailyRequestDTO) { + + //현재 날자 + LocalDate date = creatureTodoDailyRequestDTO.getDate(); + //멤버 + int memberId = SecurityUtil.getCurrentUserId(); + + //누른 버튼 + if(creatureTodoDailyRequestDTO.getNext() < 0 ){ //-1 일때 + date.minusDays(1); + }else{ + date.plusDays(1); + } + + + //크리쳐 투두 내가 만들거 싹 가져와!! + List todayTodos = creatureTodoRepository.findByMemberIdAndCreatedAt(memberId, date); + List responseDTOList = new ArrayList<>(); + + //바꿔서 보내줘! + for (CreatureTodo creatureTodo : todayTodos) { + responseDTOList.add(toResponseDTO(creatureTodo)); + } + + return responseDTOList; + } +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/DayOffService.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/DayOffService.java new file mode 100644 index 0000000..0a34171 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/DayOffService.java @@ -0,0 +1,28 @@ +package com.todoslave.feedme.service; + +import com.todoslave.feedme.domain.entity.task.DayOff; + +import java.time.LocalDate; +import java.util.Optional; + +public interface DayOffService { + + // 맴버 아이디와 날짜로 DayOff 찾기 + Optional findDayOffByMemberIdAndDate(int memberId, LocalDate date); + + // DayOff 생성 + DayOff saveDayOff(DayOff dayOff); + + // 특정 날짜에 DayOff가 있는지 확인 -> 이거로 확인하고 + boolean isActionAllowed(int memberId, LocalDate date); + + // 이게 이제 그날의 끝낸게 있나 없나 확인 + boolean notFindClearData(LocalDate date); + + // DayOff 삭제 + void deleteDayOff(int id); + + + + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/DayOffServiceImpl.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/DayOffServiceImpl.java new file mode 100644 index 0000000..5a1bfd2 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/DayOffServiceImpl.java @@ -0,0 +1,117 @@ +package com.todoslave.feedme.service; + +import com.todoslave.feedme.domain.entity.task.DayOff; +import com.todoslave.feedme.login.util.SecurityUtil; +import com.todoslave.feedme.repository.CreatureTodoReposito; +import com.todoslave.feedme.repository.DayOffRepository; +import com.todoslave.feedme.repository.TodoRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.time.LocalDate; +import java.util.Optional; + + +@Service +public class DayOffServiceImpl implements DayOffService { + + private final DayOffRepository dayOffRepository; + + @Autowired + private TodoRepository todoRepository; + @Autowired + private CreatureTodoReposito creatureTodoReposito; + + @Autowired + public DayOffServiceImpl(DayOffRepository dayOffRepository) { + this.dayOffRepository = dayOffRepository; + } + + @Override + public Optional findDayOffByMemberIdAndDate(int memberId, LocalDate date) { + return dayOffRepository.findByMemberIdAndEndDay(memberId, date); + } + + @Override + public DayOff saveDayOff(DayOff dayOff) { + return dayOffRepository.save(dayOff); + } + + @Override + public boolean isActionAllowed(int memberId, LocalDate date) { + return dayOffRepository.countByMemberIdAndEndDay(memberId, date) == 0; + } + + @Override + public boolean notFindClearData(LocalDate date) { + long inCompleted = todoRepository.countTodoByDateAndIsCompleted(date, 1)+creatureTodoReposito.countByCreatedAtAndIsCompleted(date,1); + if(inCompleted == 0){ //그날에 한게 없다? + return false; + } + return true; //그날에 한것이 있다! + } + + @Override + public void deleteDayOff(int id) { + dayOffRepository.deleteById(id); + } + + + +// //false면 있는거 이게 한 적이 있나 없나 +// boolean checked = isActionAllowed(SecurityUtil.getCurrentMember().getId(), creatureTodo.getCreatedAt()); +// +// +// //아 생각해보니까 이러면 없는날에 안되네,,, +// long inCompleted = todoRepository.countTodoByDateAndIsCompleted(creatureTodo.getCreatedAt(), 0)+creatureTodoReposito.countByCreatedAtAndIsCompleted(creatureTodo.getCreatedAt(),0); +// if(inCompleted==0){ +// checked=false; +// } + + + +} + + +//package com.todoslave.feedme.service; +// +// +//import com.todoslave.feedme.domain.entity.task.DayOff; +//import com.todoslave.feedme.repository.DayOffRepository; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.stereotype.Service; +// +//import java.time.LocalDate; +//import java.util.List; +//import java.util.Optional; +// +//@Service +//public class DayOffService { +// +// private final DayOffRepository dayOffRepository; +// +// +// @Autowired +// public DayOffService(DayOffRepository dayOffRepository) { +// this.dayOffRepository = dayOffRepository; +// } +// //맴버 아이디랑 날자로 찾기 +// public Optional findDayOffByMemberIdAndDate(int memberId, LocalDate date) { +// return dayOffRepository.findByMemberIdAndEndDay(memberId, date); +// } +// //데이오프 만들기 +// public DayOff saveDayOff(DayOff dayOff) { +// return dayOffRepository.save(dayOff); +// } +// +// //있는지 검사 +// public boolean isActionAllowed(int memberId, LocalDate date) { +// // 특정 날짜에 한 개라도 DayOff가 있으면 false 반환 +// return dayOffRepository.countByMemberIdAndEndDay(memberId, date) == 0; +// } +// //쓸일 없어 +// public void deleteDayOff(int id) { +// dayOffRepository.deleteById(id); +// } +//} \ No newline at end of file diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/DiaryService.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/DiaryService.java new file mode 100644 index 0000000..e2b5c9b --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/DiaryService.java @@ -0,0 +1,9 @@ +package com.todoslave.feedme.service; + +import com.todoslave.feedme.DTO.DiaryResponseDTO; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +public interface DiaryService { + Page getDiaryList(Pageable pageable); +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/DiaryServiceImpl.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/DiaryServiceImpl.java new file mode 100644 index 0000000..63d703b --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/DiaryServiceImpl.java @@ -0,0 +1,36 @@ +package com.todoslave.feedme.service; + + +import com.todoslave.feedme.DTO.DiaryResponseDTO; +import com.todoslave.feedme.domain.entity.diary.PictureDiary; +import com.todoslave.feedme.login.util.SecurityUtil; +import com.todoslave.feedme.repository.DiaryRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; + +@Service +public class DiaryServiceImpl implements DiaryService { + + private final DiaryRepository diaryRepository; + + @Autowired + public DiaryServiceImpl(DiaryRepository diaryRepository) { + this.diaryRepository = diaryRepository; + } + + @Override + public Page getDiaryList(Pageable pageable) { + return diaryRepository.findAll(pageable) + .map(this::convertToDTO); + } + + private DiaryResponseDTO convertToDTO(PictureDiary diary) { + DiaryResponseDTO dto = new DiaryResponseDTO(); + dto.setContent(diary.getContent()); + dto.setCreatedAt(diary.getCreatedAt()); + dto.setDiaryImg("https://i11b104.p.ssafy.io/image/pictureDiary/"+ SecurityUtil.getCurrentUserId() +"_"+diary.getCreatedAt()); + return dto; + } +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/FeedCommentService.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/FeedCommentService.java new file mode 100644 index 0000000..1f9b197 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/FeedCommentService.java @@ -0,0 +1,18 @@ +package com.todoslave.feedme.service; + +import com.todoslave.feedme.DTO.*; + +public interface FeedCommentService { + + //댓글 등록 + FeedCommentResponseDTO insertFeedCommend(FeedCommentRequestDTO FeedCommentRequestDTO, int feedid); + + //댓글 수정 + FeedCommentResponseDTO modifyComment(FeedCommentRequestDTO feedCommentRequestDTO, int feedcommantId); + + //댓글 삭제 + boolean delectFeedComment(int feedId); + + + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/FeedCommentServiceImpl.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/FeedCommentServiceImpl.java new file mode 100644 index 0000000..52b6cf7 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/FeedCommentServiceImpl.java @@ -0,0 +1,86 @@ +package com.todoslave.feedme.service; + +import com.todoslave.feedme.DTO.FeedCommentRequestDTO; +import com.todoslave.feedme.DTO.FeedCommentResponseDTO; +import com.todoslave.feedme.domain.entity.Feed.Feed; +import com.todoslave.feedme.domain.entity.Feed.FeedComment; +import com.todoslave.feedme.login.util.SecurityUtil; +import com.todoslave.feedme.repository.FeedCommentRepository; +import com.todoslave.feedme.repository.FeedRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.sql.Date; +import java.time.LocalDateTime; + + +@RequiredArgsConstructor +@Service +public class FeedCommentServiceImpl implements FeedCommentService { + + private final FeedRepository feedRepository; + private final FeedCommentRepository commentRepository; + private final FeedCommentRepository feedCommentRepository; + + //피드 댓글 작성 + @Override + public FeedCommentResponseDTO insertFeedCommend(FeedCommentRequestDTO feedCommentRequestDTO, int feedid) { + FeedComment feedComment = new FeedComment(); + Feed feed = feedRepository.findById(feedid).orElse(null); + + if (feed == null) { + // Feed가 존재하지 않으면 예외를 던지거나 적절한 처리를 합니다. + throw new IllegalArgumentException("Feed가 존재하지 않습니다."); + } + + feedComment.setFeed(feed); + feedComment.setMember(SecurityUtil.getCurrentMember()); + feedComment.setContent(feedCommentRequestDTO.getContent()); + + commentRepository.save(feedComment); + + return convertCommentToDTO(feedComment); + } + + + //댓글 수정 + @Override + public FeedCommentResponseDTO modifyComment(FeedCommentRequestDTO feedCommentRequestDTO, int feedcommantId) { + FeedComment feedComment = feedCommentRepository.findById(feedcommantId).orElse(null); + //못찾아 왓을 때 + if (feedComment == null) { + return null; + } + //내가 쓴 글이 아닐 때 + if (SecurityUtil.getCurrentMember().getId() != feedComment.getMember().getId()) { + return null; + } + + feedComment.setContent(feedCommentRequestDTO.getContent()); + feedComment.setCreatedAt(LocalDateTime.now()); + commentRepository.save(feedComment); + return convertCommentToDTO(feedComment); + } + + //댓글 삭제 + @Override + public boolean delectFeedComment(int feedId) { + FeedComment feedComment = feedCommentRepository.findById(feedId).orElse(null); + if (feedComment == null|| SecurityUtil.getCurrentMember().getId() != feedComment.getMember().getId()) { + return false; + } + commentRepository.delete(feedComment); + return true; + } + + + //변환하기 댓글 -> FeedCommentResponseDTO로 + private FeedCommentResponseDTO convertCommentToDTO(FeedComment feedComment) { + FeedCommentResponseDTO dto = new FeedCommentResponseDTO(); + dto.setNickname(feedComment.getMember().getNickname()); // Member 엔티티에서 닉네임 가져오기 + dto.setContent(feedComment.getContent()); + dto.setCreatedAt(feedComment.getCreatedAt()); + return dto; + } + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/FeedService.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/FeedService.java index 1f21ea6..c115f82 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/FeedService.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/FeedService.java @@ -1,5 +1,23 @@ package com.todoslave.feedme.service; +import com.todoslave.feedme.DTO.FeedDTO; +import com.todoslave.feedme.DTO.FeedModifyRequest; +import com.todoslave.feedme.DTO.FeedRequestDTO; +import com.todoslave.feedme.DTO.FeedResponseDTO; + +import java.util.List; + public interface FeedService { + FeedResponseDTO insertFeed(FeedRequestDTO feedRequestDTO); + + FeedResponseDTO modifyFeed(int feedId, FeedModifyRequest feedModifyRequest); + + boolean delectFeed(int feedId); + + void toggleLike(int feedId); + + List getRecentFeeds(); + + List getRecentFeedsByFriends(); } diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/FeedServiceImpl.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/FeedServiceImpl.java index f7f1c45..6a28b44 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/FeedServiceImpl.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/FeedServiceImpl.java @@ -1,8 +1,173 @@ package com.todoslave.feedme.service; +import com.todoslave.feedme.DTO.*; +import com.todoslave.feedme.domain.entity.Feed.Feed; +import com.todoslave.feedme.domain.entity.Feed.FeedComment; +import com.todoslave.feedme.domain.entity.Feed.FeedLike; +import com.todoslave.feedme.domain.entity.membership.Member; +import com.todoslave.feedme.login.util.SecurityUtil; +import com.todoslave.feedme.repository.FeedLikeRepository; +import com.todoslave.feedme.repository.FeedRepository; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import java.sql.Time; +import java.sql.Timestamp; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; + + +@Service +@RequiredArgsConstructor public class FeedServiceImpl implements FeedService{ + @PersistenceContext + private EntityManager entityManager; + + private final FeedRepository feedRepository; + private final FeedLikeRepository feedLikeRepository; + + + //피드 생성 + @Override + public FeedResponseDTO insertFeed(FeedRequestDTO feedRequestDTO) { + Feed feed = new Feed(); + feed.setContent(feedRequestDTO.getContent()); + feed.setMember(SecurityUtil.getCurrentMember()); + feed.setDiaryDay(feedRequestDTO.getDiaryDate()); + feed.setNickname(SecurityUtil.getCurrentMember().getNickname()); + + feedRepository.save(feed); + return convertToDTO(feed); + } + + //피드 수정 + @Override + public FeedResponseDTO modifyFeed(int feedId, FeedModifyRequest feedModifyRequest) { + Feed feed = feedRepository.findById(feedId).orElse(null); + if (feed == null) {return null;} + + feed.setContent(feedModifyRequest.getContent()); + feed.setUpdatedAt(LocalDateTime.now()); + feedRepository.save(feed); + return convertToDTO(feed); + } + + //피드 삭제 + @Override + public boolean delectFeed(int feedId) { + Feed feed = feedRepository.findById(feedId).orElse(null); + if (feed == null) {return false;} + if(SecurityUtil.getCurrentMember().equals(feed.getMember())) { + feedRepository.delete(feed); + return true; + } + return false; + } + + //피드 좋아요 + @Transactional + public void toggleLike(int feedId) { + Member member = SecurityUtil.getCurrentMember(); + Feed feed = feedRepository.findById(feedId).orElseThrow(() -> + new IllegalArgumentException("해당 피드가 존재하지 않습니다.")); + + // 이미 좋아요를 눌렀는지 확인 + FeedLike existingFeedLike = feedLikeRepository.findByMemberAndFeed(member, feed); + + if (existingFeedLike != null) { + // 이미 좋아요를 눌렀으므로 삭제 + feed.setLikeCount(feed.getLikeCount() -1); + feedRepository.save(feed); + feedLikeRepository.delete(existingFeedLike); + } else { + // 좋아요를 누르지 않았으므로 새로운 좋아요 추가 + feed.setLikeCount(feed.getLikeCount() + 1); + FeedLike feedLike = new FeedLike(); + feedLike.setMember(member); + feedLike.setFeed(feed); + feedRepository.save(feed); + feedLikeRepository.save(feedLike); + } + } + + // 친구의 피드만 가져오는 메서드 + public List getRecentFeedsByFriends() { + int memberId = SecurityUtil.getCurrentMember().getId(); + LocalDateTime thirtyDaysAgo = LocalDateTime.now().minusDays(30); + + List recentFeedsByFriends = feedRepository.findRecentFeedsByFriendsAndMe(thirtyDaysAgo, memberId); + return recentFeedsByFriends.stream() + .map(this::convertToFeedDTO) + .collect(Collectors.toList()); + } + + + //피드 가져오기 + public List getRecentFeeds() { + LocalDateTime thirtyDaysAgo = LocalDateTime.now().minusDays(30); + List recentFeeds = feedRepository.findRecentFeeds(thirtyDaysAgo); + // 친구껏만 feed오는 뭔가!!! + + // + + return recentFeeds.stream() + .map(this::convertToFeedDTO) + .collect(Collectors.toList()); + } + + private FeedDTO convertToFeedDTO(Feed feed) { + FeedDTO feedDTO = new FeedDTO(); + + FeedLike existingFeedLike = feedLikeRepository.findByMemberAndFeed(SecurityUtil.getCurrentMember(), feed); + + if (existingFeedLike != null) { + feedDTO.setMyLike(false); + }else { + feedDTO.setMyLike(true); + } + + feedDTO.setEmail(feed.getMember().getEmail()); + feedDTO.setFeedId(feed.getId()); + feedDTO.setNickname(feed.getNickname()); + feedDTO.setImg("https://i11b104.p.ssafy.io/image/pictureDiary/"+SecurityUtil.getCurrentUserId()+"_"+feed.getDiaryDay()); // 이미지 처리 로직 필요 + feedDTO.setCaption(feed.getContent()); + feedDTO.setLastCreateTime(feed.getUpdatedAt()); + feedDTO.setLikes(feed.getLikeCount()); + + feedDTO.setComments(feed.getFeedComments().stream() + .map(this::convertToCommentDTO) + .collect(Collectors.toList())); + return feedDTO; + } + + private FeedCommentDTO convertToCommentDTO(FeedComment comment) { + FeedCommentDTO commentDTO = new FeedCommentDTO(); + commentDTO.setFeedComentId(comment.getId()); + commentDTO.setNickname(comment.getMember().getNickname()); + commentDTO.setComment(comment.getContent()); + commentDTO.setTime(comment.getCreatedAt().toString()); + commentDTO.setEmail(comment.getMember().getEmail()); + return commentDTO; + } + + // Feed 엔티티를 FeedResponseDTO로 변환하는 메서드 + public FeedResponseDTO convertToDTO(Feed feed) { + FeedResponseDTO dto = new FeedResponseDTO(); + dto.setId(feed.getId()); + dto.setImg("https://i11b104.p.ssafy.io/image/pictureDiary/"+SecurityUtil.getCurrentUserId()+"_"+feed.getDiaryDay()); // 이미지 URL이 엔티티에 없다면 필요에 따라 설정 + dto.setContent(feed.getContent()); + dto.setAuthor(feed.getNickname()); + dto.setLikeCnt(String.valueOf(feed.getLikeCount())); + dto.setCreatedAt(feed.getCreatedAt()); + return dto; + } } + + diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/FriendService.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/FriendService.java index 50107d1..ed5f591 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/FriendService.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/FriendService.java @@ -1,28 +1,39 @@ package com.todoslave.feedme.service; -import com.todoslave.feedme.domain.entity.communication.Friend; -import com.todoslave.feedme.domain.entity.communication.FriendRequest; +import com.todoslave.feedme.DTO.FriendInfoResponseDTO; +import com.todoslave.feedme.DTO.FriendRequestDTO; +import com.todoslave.feedme.DTO.FriendReqResponseDTO; +import com.todoslave.feedme.DTO.FriendResponseDTO; +import com.todoslave.feedme.DTO.MemberChatListResponseDTO; +import com.todoslave.feedme.DTO.PaginationRequestDTO; import java.util.List; +import org.springframework.data.domain.Slice; public interface FriendService { // 친구 추가 - void insertFriend(int memberId, String email); + void requestFriend(FriendRequestDTO friendRequestDTO); // 친구 삭제 - void deleteFriend(int friendId); + void deleteFriend(FriendRequestDTO friendRequestDTO); + + // 친구 정보 불러오기 + FriendInfoResponseDTO getFriendInfo(FriendRequestDTO friendRequestDTO); // 친구 목록 조회 - List getFriends(Integer memberId); + List getFriends(); // 친구 요청 목록 조회 - List getRequestFriend(Integer memberId); + Slice getRequestFriend(PaginationRequestDTO paginationRequestDTO); // 친구 수락 - void insertFriendship(int requestId); + MemberChatListResponseDTO insertFriendship(int requestId); // 친구 거절 void deleteRequestFriend(int requestId); + //친구인지 확인 + boolean isFriend(int memberId, int friendId); + } diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/FriendServiceImpl.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/FriendServiceImpl.java index b2c9a67..ef03417 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/FriendServiceImpl.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/FriendServiceImpl.java @@ -1,73 +1,202 @@ -//package com.todoslave.feedme.service; -// -//import com.todoslave.feedme.domain.entity.communication.Friend; -//import com.todoslave.feedme.domain.entity.communication.FriendRequest; -//import com.todoslave.feedme.domain.entity.membership.Member; -//import com.todoslave.feedme.repository.FriendRepository; -//import com.todoslave.feedme.repository.FriendRequestRepository; -//import com.todoslave.feedme.repository.MemberRepository; -//import jakarta.persistence.EntityNotFoundException; -//import jakarta.transaction.Transactional; -//import lombok.RequiredArgsConstructor; -// -//import java.util.List; -// -//@RequiredArgsConstructor -//public class FriendServiceImpl implements FriendService{ -// +package com.todoslave.feedme.service; + +import com.todoslave.feedme.DTO.CreatureInfoResponseDTO; +import com.todoslave.feedme.DTO.FriendInfoResponseDTO; +import com.todoslave.feedme.DTO.FriendRequestDTO; +import com.todoslave.feedme.DTO.FriendReqResponseDTO; +import com.todoslave.feedme.DTO.FriendResponseDTO; +import com.todoslave.feedme.DTO.MemberChatListResponseDTO; +import com.todoslave.feedme.DTO.PaginationRequestDTO; +import com.todoslave.feedme.domain.entity.avatar.Creature; +import com.todoslave.feedme.domain.entity.communication.Friend; +import com.todoslave.feedme.domain.entity.communication.FriendRequest; +import com.todoslave.feedme.domain.entity.membership.Member; +import com.todoslave.feedme.login.util.SecurityUtil; +import com.todoslave.feedme.mapper.FriendRequestMapper; +import com.todoslave.feedme.repository.FriendRepository; +import com.todoslave.feedme.repository.FriendRequestRepository; +import com.todoslave.feedme.repository.MemberRepository; +import jakarta.transaction.Transactional; +import java.util.ArrayList; +import lombok.RequiredArgsConstructor; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class FriendServiceImpl implements FriendService{ + + + private final MemberChatService memberChatService; + private final CreatureService creatureService; + private final MemberRepository memberRepository; + private final FriendRepository friendRepository; + private final FriendRequestRepository friendRequestRepository; + + +// @Autowired +// MemberService memberService; + +// @Autowired +// MemberChatService memberChatService; +// @Autowired +// CreatureService creatureService; +// @Autowired // MemberRepository memberRepository; + +// @Autowired // FriendRepository friendRepository; +// @Autowired // FriendRequestRepository friendRequestRepository; -// -// @Override -// public void insertFriend(int memberId, String email) { -// -// int counterId; -// -// FriendRequest friendRequest = new FriendRequest(); -// friendRequest.setMember(memberId); -// friendRequest.setCounterpart_id(counterId); -// -// friendRequestRepository.save(friendRequest); -// -// } -// -// @Override -// @Transactional -// public void deleteFriend(int friendId) { -// -// friendRequestRepository.deleteById(friendId); -// -// } -// -// @Override -// public List getFriends(Integer memberId) { -// return friendRepository.findAllByMemberId(memberId); -// } -// -// @Override -// public List getRequestFriend(Integer memberId) { -// return friendRequestRepository.findAllByMemberId(memberId); -// } -// -// @Override -// public void insertFriendship(int id) { -// -// FriendRequest friendRequest = friendRequestRepository.findById(id); -// -// Friend friend = new Friend(); -// Member member = friendRequest.getMember(); -// friend.setMember(member); -// friend.setCounterpart_id(friendRequest.getCounterpart_id()); -// -// friendRepository.save(friend); -// -// } -// -// @Override -// public void deleteRequestFriend(int requestId) { -// -// friendRequestRepository.deleteById(requestId); -// -// } -//} + + //유틸 닉네임으로 찾기 + private Member findByNickname(String nickname) { + return memberRepository.findByNickname(nickname).orElse(null); + } + + + // 친구 요청 + @Override + public void requestFriend(FriendRequestDTO friendRequestDTO) { + + Member member = SecurityUtil.getCurrentMember(); + Member counterpart = findByNickname(friendRequestDTO.getCounterpartNickname()); + + FriendRequest friendRequest = new FriendRequest(); + + friendRequest.setMember(member); + friendRequest.setCounterpartId(counterpart); + + friendRequestRepository.save(friendRequest); + + } + + // 친구 삭제 + @Override + @Transactional + public void deleteFriend(FriendRequestDTO friendRequestDTO) { + + Member friend = memberRepository.findByNickname(friendRequestDTO.getCounterpartNickname()).orElseThrow(); + int memberId = SecurityUtil.getCurrentUserId(); + int friendId = friendRepository.findByMemberIdAndCounterpartId(memberId, friend.getId()); + friendRepository.deleteById(friendId); + + } + + // 친구 정보 불러오기 + public FriendInfoResponseDTO getFriendInfo(FriendRequestDTO friendRequestDTO){ + + FriendInfoResponseDTO response = new FriendInfoResponseDTO(); + + Member member = findByNickname(friendRequestDTO.getCounterpartNickname()); + + response.setFriendId(member.getId()); + response.setNickname(member.getNickname()); + + CreatureInfoResponseDTO creatureInfoResponseDTO = creatureService.creatureInfo(member); + response.setCreatureNickname(creatureInfoResponseDTO.getName()); + response.setCreatureImg(creatureInfoResponseDTO.getImg()); + response.setLevel(creatureInfoResponseDTO.getLevel()); + response.setExp(creatureInfoResponseDTO.getExp()); + response.setJoin(creatureInfoResponseDTO.getDay()); + + return response; + } + + // 친구 목록 불러오기 + @Override + public List getFriends() { + + int memberId = SecurityUtil.getCurrentUserId(); + + List f = friendRepository.findAllByMemberId(memberId); + List friends = new ArrayList<>(); + + for(Friend friend : f){ + + Member counterpart = friend.getCounterpart(); + FriendResponseDTO friendResponseDTO = new FriendResponseDTO(); + friendResponseDTO.setFriendId(friend.getId()); + friendResponseDTO.setCounterpartNickname(counterpart.getNickname()); +// friendResponseDTO.setCreatureimg(imageUtill.); + friends.add(friendResponseDTO); + + } + + return friends; + } + + //크리쳐 이미지 주소 + private String generateCreatureImgPath(Member member) { + Creature creature = member.getCreature(); + int creatureLevel = creature.getLevel(); + int creatureId = creature.getId(); + return "https://i11b104.p.ssafy.io/image/creature/" + creatureId + "_" +creatureLevel; + } + + // 친구 요청 불러오기 + @Override + public Slice getRequestFriend(PaginationRequestDTO paginationRequestDTO) { + + int memberId = SecurityUtil.getCurrentUserId(); + + Pageable pageable = PageRequest.of(paginationRequestDTO.getSkip() / paginationRequestDTO.getLimit(), + paginationRequestDTO.getLimit()); + + Slice friendRequests = friendRequestRepository.findAllByMemberId(memberId, pageable); + + return friendRequests.map(FriendRequestMapper::toDto); + } + + // 친구 수락 + @Override + public MemberChatListResponseDTO insertFriendship(int requestId) { + + FriendRequest friendRequest = friendRequestRepository.findById(requestId); + + Friend friend = new Friend(); + + Member member = SecurityUtil.getCurrentMember(); + Member counterpart = friendRequest.getCounterpartId(); + + friend.setMember(member); + friend.setCounterpart(counterpart); + + // 친구 추가 + friendRepository.save(friend); + + friend.setMember(counterpart); + friend.setCounterpart(member); + + friendRepository.save(friend); + + friendRequestRepository.deleteById(requestId); + + List members = new ArrayList<>(); + + members.add(member.getId()); + members.add(counterpart.getId()); + + // 채팅방 생성 + return memberChatService.insertChatRoom(members); + } + + // 친구 거절 + @Override + public void deleteRequestFriend(int requestId) { + + friendRequestRepository.deleteById(requestId); + + } + + // 친구 인지 확인하기 + public boolean isFriend(int memberId, int friendId) { + return friendRepository.existsByMemberIdAndCounterpartId(memberId, friendId) || + friendRepository.existsByCounterpartIdAndMemberId(friendId, memberId); + } +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/MemberChatService.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/MemberChatService.java index 4a12f2b..b70692c 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/MemberChatService.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/MemberChatService.java @@ -1,7 +1,11 @@ package com.todoslave.feedme.service; +import com.todoslave.feedme.DTO.MemberChatListResponseDTO; +import com.todoslave.feedme.DTO.MemberChatMessageRequestDTO; +import com.todoslave.feedme.DTO.MemberChatMessageResponseDTO; import com.todoslave.feedme.domain.entity.communication.MemberChatMessage; import com.todoslave.feedme.domain.entity.communication.MemberChatRoom; +import java.io.IOException; import java.util.List; import org.springframework.data.domain.Slice; import org.springframework.stereotype.Service; @@ -9,15 +13,17 @@ @Service public interface MemberChatService { - public List getChatRooms(MemberChatRoom room); + // 채팅방 목록 불러오기 + public List getChatRooms(); - // 채팅방 생성 or 불러오기 - public MemberChatRoom getChatRoom(MemberChatRoom room); + // 채팅방 생성 + public MemberChatListResponseDTO insertChatRoom(List members); // 채팅방 메세지 불러오기 public Slice getChatMessage(String roomId, int page, int size); // 채팅방 메세지 저장 - public MemberChatMessage insertChatMessage(MemberChatMessage message); + public MemberChatMessageResponseDTO insertChatMessage(String roomId, MemberChatMessageRequestDTO memberChatMessageRequestDTO) + throws IOException; } \ No newline at end of file diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/MemberChatServiceImpl.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/MemberChatServiceImpl.java index b876445..9b0d9ba 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/MemberChatServiceImpl.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/MemberChatServiceImpl.java @@ -1,11 +1,25 @@ package com.todoslave.feedme.service; +import com.todoslave.feedme.DTO.MemberChatListResponseDTO; +import com.todoslave.feedme.DTO.MemberChatMessageRequestDTO; +import com.todoslave.feedme.DTO.MemberChatMessageResponseDTO; +import com.todoslave.feedme.domain.entity.avatar.Creature; import com.todoslave.feedme.domain.entity.communication.MemberChatMessage; import com.todoslave.feedme.domain.entity.communication.MemberChatRoom; +import com.todoslave.feedme.domain.entity.communication.MemberChatRoomChecked; +import com.todoslave.feedme.domain.entity.membership.Member; +import com.todoslave.feedme.login.util.SecurityUtil; +import com.todoslave.feedme.repository.CreatureRepository; import com.todoslave.feedme.repository.MemberChatMessageRepository; +import com.todoslave.feedme.repository.MemberChatRoomCheckedRepository; import com.todoslave.feedme.repository.MemberChatRoomRepository; +import com.todoslave.feedme.repository.MemberRepository; +import jakarta.transaction.Transactional; +import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.Map; +import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; @@ -13,49 +27,173 @@ import org.springframework.stereotype.Service; @Service +@RequiredArgsConstructor public class MemberChatServiceImpl implements MemberChatService{ @Autowired - private MemberChatMessageRepository messageRepository; - + private final MemberChatMessageRepository messageRepository; + @Autowired + private final MemberChatRoomRepository roomRepository; + @Autowired + private final MemberChatRoomCheckedRepository roomCheckedRepository; + @Autowired + private final AlarmService alarmService; + @Autowired + private final MemberRepository memberRepository; + @Autowired + private final MemberChatRoomCheckedRepository memberChatRoomCheckedRepository; @Autowired - private MemberChatRoomRepository roomRepository; + private final CreatureRepository creatureRepository; + + // 채팅방 목록들 가져오기 @Override - public List getChatRooms(MemberChatRoom room) { - List rooms = roomRepository.findAllByParticipantIdsContaining(room.getParticipantIds()); - System.out.println(rooms); - return rooms; + public List getChatRooms() { + + int memberId = SecurityUtil.getCurrentUserId(); + + MemberChatRoom memberChatRoom = new MemberChatRoom(); + List members = new ArrayList<>(); + members.add(memberId); + + List rooms = roomRepository.findAllByParticipantIdsContainingOrderByReceiveTime(members); + List chatListResponse = new ArrayList<>(); + + for(MemberChatRoom room : rooms){ + + MemberChatListResponseDTO chatResponse = new MemberChatListResponseDTO(); + chatResponse.setId(room.getId()); + + members = room.getParticipantIds(); + int counterPartId = 0; + + for(int m : members){ + if(m!=memberId){ + counterPartId=m; + } + } + + String nickname = memberRepository.findById(counterPartId).orElseThrow().getNickname(); + chatResponse.setNickname(nickname); + Creature creature = creatureRepository.findByMemberId(counterPartId); + + chatResponse.setCreatureImage( + "https://i11b104.p.ssafy.io/image/creature/"+creature.getMember().getId()+"_"+creature.getLevel()); + MemberChatRoomChecked checked = memberChatRoomCheckedRepository.findByMemberChatRoomIdAndMemberId(room.getId(),memberId); + chatResponse.setIsChecked(checked.getIsChecked()); + + } + + return chatListResponse; } - public MemberChatRoom getChatRoom(MemberChatRoom room){ + // 채팅방 생성 + public MemberChatListResponseDTO insertChatRoom(List members){ + + MemberChatRoom room = new MemberChatRoom(); + room.setParticipantIds(members); + room = roomRepository.save(room); + + MemberChatRoomChecked checked = new MemberChatRoomChecked(); + checked.setMemberId(members.get(0)); + checked.setIsChecked(1); + checked.setMemberChatRoomId(room.getId()); + roomCheckedRepository.save(checked); - MemberChatRoom result = roomRepository.findByParticipantIdsContainingAll(room.getParticipantIds()); + checked.setMemberId(members.get(1)); + roomCheckedRepository.save(checked); - System.out.println(room); + Member countpart = null; - if(result==null){ - result = roomRepository.save(room); + for(int m : members){ + if(m!=SecurityUtil.getCurrentUserId()){ + countpart = memberRepository.findById(m).orElseThrow(); + } } - System.out.println(result); + Creature creature = creatureRepository.findByMemberId(countpart.getId()); - return result; + MemberChatListResponseDTO memberChatListResponseDTO = new MemberChatListResponseDTO(); + memberChatListResponseDTO.setId(room.getId()); + memberChatListResponseDTO.setNickname(countpart.getNickname()); + memberChatListResponseDTO.setCreatureImage( + "https://i11b104.p.ssafy.io/image/creature/"+creature.getMember().getId()+"_"+creature.getLevel()); + memberChatListResponseDTO.setIsChecked(1); + + return memberChatListResponseDTO; } + // 채팅방 메세지 불러오기 + @Transactional public Slice getChatMessage(String roomId, int skip, int limit){ + if(roomRepository.findById(roomId).orElseThrow()==null){ + return null; + } + System.out.println("receive message? service"); Pageable pageable = PageRequest.of(skip / limit, limit); Slice messages = messageRepository.findByMemberChatRoomIdOrderByTransmitAtDesc(roomId, pageable); + int memberId = SecurityUtil.getCurrentUserId(); + MemberChatRoomChecked checked = memberChatRoomCheckedRepository.findByMemberChatRoomIdAndMemberId(roomId,memberId); + checked.setIsChecked(1); + return messages; } - public MemberChatMessage insertChatMessage(MemberChatMessage message) { - System.out.println(message); - return messageRepository.save(message); + // 채팅방 메세지 저장 + public MemberChatMessageResponseDTO insertChatMessage(String roomId, MemberChatMessageRequestDTO memberChatMessageRequestDTO) + throws IOException { + MemberChatMessage memberChatMessage = new MemberChatMessage(); + + int memberId = SecurityUtil.getCurrentUserId(); + + MemberChatRoom memberChatRoom = roomRepository.findById(roomId).orElseThrow(); + String counterpartNickname = null; + int counterPartId = 0; + + for(int m : memberChatRoom.getParticipantIds()){ + if(m!=memberId){ + counterPartId = m; + counterpartNickname = memberRepository.findById(m).orElseThrow().getNickname(); + } + } + + memberChatMessage.setMemberChatRoomId(roomId); + memberChatMessage.setContent(memberChatMessageRequestDTO.getMessage()); + memberChatMessage.setSendId(memberId); + + // 메세지 저장 + memberChatMessage = messageRepository.save(memberChatMessage); + + MemberChatListResponseDTO memberChatListResponseDTO = new MemberChatListResponseDTO(); + memberChatListResponseDTO.setId(roomId); + memberChatListResponseDTO.setNickname(counterpartNickname); + Creature creature = creatureRepository.findByMemberId(counterPartId); + + memberChatListResponseDTO.setCreatureImage("https://i11b104.p.ssafy.io/image/creature/"+creature.getMember().getId()+"_"+creature.getLevel()); + + // 채팅방 갱신 (나) + alarmService.renewChattingRoom(memberChatListResponseDTO, SecurityUtil.getCurrentUserId()); + + memberChatListResponseDTO.setNickname(SecurityUtil.getCurrentMember().getNickname()); + creature = creatureRepository.findByMemberId(memberId); + + memberChatListResponseDTO.setCreatureImage("https://i11b104.p.ssafy.io/image/creature/"+creature.getMember().getId()+"_"+creature.getLevel()); + + // 채팅방 갱신 (상대) + alarmService.renewChattingRoom(memberChatListResponseDTO, counterPartId); + + + MemberChatMessageResponseDTO response = new MemberChatMessageResponseDTO(); + + response.setMessage(memberChatMessage.getContent()); + response.setTransmitAt(memberChatMessage.getTransmitAt()); + response.setSendNickname(SecurityUtil.getCurrentMember().getNickname()); + + return response; } } diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/MemberService.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/MemberService.java index cd39e11..decbc3f 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/MemberService.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/MemberService.java @@ -1,47 +1,51 @@ package com.todoslave.feedme.service; +import com.todoslave.feedme.DTO.MemberSearchResponseDTO; +import com.todoslave.feedme.DTO.MemberSignupRequestDTO; +import com.todoslave.feedme.DTO.MypageResponseDTO; import com.todoslave.feedme.domain.entity.membership.Member; -import com.todoslave.feedme.repository.MemberRepository; - -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; import java.util.List; +import java.util.Optional; + +// import java.util.stream.Collectors; + +//@Service +// @Transactional +// public class MemberService { + +// @Autowired +// MemberRepository memberRepository; +// @Autowired +// FriendService friendService; + + +public interface MemberService { + + // 아이디로 회원 찾기 + Member findById(int userId); + + // 이메일로 회원 찾기 + Optional findByEmail(String email); + + // 닉네임으로 회원 찾기 + Member findByNickname(String nickname); + + // 회원 가입 처리 + Member registerMember(MemberSignupRequestDTO memberSignupRequestDTO); + + // 회원 정보 수정 + Member updateMember(MemberSignupRequestDTO memberSignupRequestDTO); + + // 회원 탈퇴 + boolean removeMember(); -@Service -@Transactional(readOnly = true) //조회에선 -@RequiredArgsConstructor // 생성자 만들어 주는 얘 -public class MemberService { - - // @Autowired - private final MemberRepository memberRepository; - - // 회원가입 - @Transactional //가입시에 - public int Join(Member member) { -// sameNameCheck(member); // 중복 회원 검증 - memberRepository.save(member); - return member.getId(); - } - - // 회원 전체 조회 - public List findMembers() { - return memberRepository.findAll(); - } - - // 단수 조회 -// public Member findOne(int id) { -// return memberRepository.findById(id); -// } - - // 중복 체크 -// private void sameNameCheck(Member member) { -// List findMembers = memberRepository.findByName(member.getNickname()); -// if(!findMembers.isEmpty()) { -// throw new IllegalStateException("중복 닉네임"); -// } -// } + // 닉네임으로 회원 검색 + List getMemberList(String searchvalue); + // 닉네임 중복 체크 + boolean checkNickname(String nickname); + // 마이페이지 불러오기 + MypageResponseDTO getMyPage(); } diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/MemberServiceImpl.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/MemberServiceImpl.java new file mode 100644 index 0000000..b29fe2b --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/MemberServiceImpl.java @@ -0,0 +1,180 @@ +package com.todoslave.feedme.service; + +import com.todoslave.feedme.DTO.MemberSearchResponseDTO; +import com.todoslave.feedme.DTO.MemberSignupRequestDTO; +import com.todoslave.feedme.DTO.MypageResponseDTO; +import com.todoslave.feedme.domain.entity.avatar.Creature; +import com.todoslave.feedme.domain.entity.communication.FriendRequest; +import com.todoslave.feedme.domain.entity.membership.Member; +import com.todoslave.feedme.login.util.SecurityUtil; +import com.todoslave.feedme.repository.FriendRepository; +import com.todoslave.feedme.repository.FriendRequestRepository; +import com.todoslave.feedme.repository.MemberRepository; + +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.sql.Timestamp; +import java.time.LocalDate; +import java.time.Period; +import java.time.ZoneId; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +@Service +@Transactional +@RequiredArgsConstructor +public class MemberServiceImpl implements MemberService { + + private final MemberRepository memberRepository; + + private final FriendRepository friendRepository; + + private final FriendRequestRepository friendRequestRepository; + + @Override + public Member findById(int userId) { + return memberRepository.findById(userId) + .orElseThrow(() -> new RuntimeException("Member not found by id: " + userId)); + } + + @Override + public Optional findByEmail(String email) { + return memberRepository.findByEmail(email); + } + + @Override + public Member findByNickname(String nickname) { + return memberRepository.findByNickname(nickname).orElse(null); + } + + + @Override + public Member registerMember(MemberSignupRequestDTO memberSignupRequestDTO) { + Member member = new Member(); + member.setEmail(memberSignupRequestDTO.getEmail()); + member.setBirthday(memberSignupRequestDTO.getBirthday()); + member.setNickname(memberSignupRequestDTO.getNickname()); + member.setUserRole(memberSignupRequestDTO.getUserRole()); + + return memberRepository.save(member); + } + + @Override + public Member updateMember(MemberSignupRequestDTO memberSignupRequestDTO) { + int id = SecurityUtil.getCurrentUserId(); + + Member member = memberRepository.findById(id) + .orElseThrow(() -> new IllegalArgumentException("사용자를 찾을 수 없습니다.")); + + member.setNickname(memberSignupRequestDTO.getNickname()); + member.setBirthday(memberSignupRequestDTO.getBirthday()); + member.setUserRole(memberSignupRequestDTO.getUserRole()); + + return memberRepository.save(member); + } + + @Override + public boolean removeMember() { + Member member = SecurityUtil.getCurrentMember(); + + if (member == null) { + return false; + } + memberRepository.delete(member); + return true; + } + + + + + // 친구 인지 확인하기!!! + public boolean isFriend(int memberId, int friendId) { + return friendRepository.existsByMemberIdAndCounterpartId(memberId, friendId) || + friendRepository.existsByCounterpartIdAndMemberId(friendId, memberId); + } + + @Override //맴버 리스트 검색 가져오기 + public List getMemberList(String searchvalue) { + + List members = memberRepository.findByNicknameContaining(searchvalue); + List memberSearchResponse = new ArrayList<>(); + + for (Member member : members) { + MemberSearchResponseDTO mem = new MemberSearchResponseDTO(); + mem.setNickname(member.getNickname()); + + if (member.getCreature() != null) { + mem.setCreatureImg(generateCreatureImgPath(member)); + } else { + mem.setCreatureImg("알 이미지"); + } + + if (member.getId() == SecurityUtil.getCurrentUserId()) { + continue; + } + + + if (isFriend(member.getId(), SecurityUtil.getCurrentUserId())) { + mem.setFriend(true); + } else { + mem.setFriend(false); + } + + // 친구 신청을 보냈는지 체크 + Optional friendRequest = friendRequestRepository.findByMember_IdAndCounterpartId_Id(SecurityUtil.getCurrentUserId(), member.getId()); + mem.setRequested(friendRequest.isPresent()); + + memberSearchResponse.add(mem); + } + + return memberSearchResponse; + } + + @Override + public boolean checkNickname(String nickname) { + return memberRepository.findByNickname(nickname).isPresent(); + } + + @Override + public MypageResponseDTO getMyPage() { + Member member = SecurityUtil.getCurrentMember(); + Creature creature = member.getCreature(); + + MypageResponseDTO myPage = new MypageResponseDTO(); + + myPage.setNickname(member.getNickname()); + myPage.setEmail(member.getEmail()); + + Timestamp birthdayTimestamp = member.getBirthday(); + LocalDate birthdayLocalDate = birthdayTimestamp.toInstant() + .atZone(ZoneId.systemDefault()) + .toLocalDate(); + + myPage.setBrithday(birthdayLocalDate); + + myPage.setCreatureId(creature.getId()); + myPage.setCreatureName(creature.getCreatureName()); + myPage.setExp(creature.getExp()); + myPage.setLevel(creature.getLevel()); + myPage.setImage(generateCreatureImgPath(member)); + + LocalDate currentDate = LocalDate.now(); + LocalDate joinDate = member.getJoinDate().toLocalDate(); + int daysSinceJoin = Period.between(joinDate, currentDate).getDays(); + + myPage.setTogetherDay(daysSinceJoin); + + return myPage; + } + + private String generateCreatureImgPath(Member member) { + Creature creature = member.getCreature(); + int creatureLevel = creature.getLevel(); + int creatureId = creature.getId(); + return "https://i11b104.p.ssafy.io/image/creature/" + creatureId + "_" + creatureLevel; + } +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/MissionService.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/MissionService.java new file mode 100644 index 0000000..7ec987a --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/MissionService.java @@ -0,0 +1,24 @@ +package com.todoslave.feedme.service; + +import com.todoslave.feedme.domain.entity.mission.Mission; + +public interface MissionService { + + // 지정된 인덱스 범위 내에서 임의의 미션을 가져옵니다. + Mission getRandomMissionByIndices(int startIndex, int endIndex); + + // 비가 오는 날의 미션을 가져옵니다. + Mission getRainyMission(); + + // 눈이 오는 날의 미션을 가져옵니다. + Mission getSnowyMission(); + + // 맑은 날의 미션을 가져옵니다. + Mission getSunnyMission(); + + // 흐린 날의 미션을 가져옵니다. + Mission getCloudyMission(); + + // 기본 미션을 가져옵니다. + Mission getDefaultMission(); +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/MissionServiceImpl.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/MissionServiceImpl.java new file mode 100644 index 0000000..f7f81e3 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/MissionServiceImpl.java @@ -0,0 +1,100 @@ +package com.todoslave.feedme.service; + +import com.todoslave.feedme.domain.entity.mission.Mission; +import com.todoslave.feedme.repository.MissionRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Random; + +@Service +public class MissionServiceImpl implements MissionService { + + @Autowired + private MissionRepository missionRepository; + + private Random random = new Random(); + + @Override + public Mission getRandomMissionByIndices(int startIndex, int endIndex) { + List missions = missionRepository.findAll(); + if (missions.isEmpty() || endIndex > missions.size()) { + return null; + } + return missions.get(startIndex - 1 + random.nextInt(endIndex - startIndex + 1)); + } + + @Override + public Mission getRainyMission() { + return getRandomMissionByIndices(1, 20); + } + + @Override + public Mission getSnowyMission() { + return getRandomMissionByIndices(21, 40); + } + + @Override + public Mission getSunnyMission() { + return getRandomMissionByIndices(41, 60); + } + + @Override + public Mission getCloudyMission() { + return getRandomMissionByIndices(61, 80); + } + + @Override + public Mission getDefaultMission() { + return getRandomMissionByIndices(81, 100); + } +} + + +//package com.todoslave.feedme.service; +// +//import com.todoslave.feedme.domain.entity.mission.Mission; +//import com.todoslave.feedme.repository.MissionRepository; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.stereotype.Service; +// +//import java.util.List; +//import java.util.Random; +// +//@Service +//public class MissionService { +// +// @Autowired +// private MissionRepository missionRepository; +// +// private Random random = new Random(); +// +// public Mission getRandomMissionByIndices(int startIndex, int endIndex) { +// List missions = missionRepository.findAll(); +// if (missions.isEmpty() || endIndex > missions.size()) { +// return null; +// } +// return missions.get(startIndex - 1 + random.nextInt(endIndex - startIndex + 1)); +// } +// +// public Mission getRainyMission() { +// return getRandomMissionByIndices(1, 20); +// } +// +// public Mission getSnowyMission() { +// return getRandomMissionByIndices(21, 40); +// } +// +// public Mission getSunnyMission() { +// return getRandomMissionByIndices(41, 60); +// } +// +// public Mission getCloudyMission() { +// return getRandomMissionByIndices(61, 80); +// } +// +// public Mission getDefaultMission() { +// return getRandomMissionByIndices(81, 100); +// } +//} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/TodoCategoryService.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/TodoCategoryService.java new file mode 100644 index 0000000..094a712 --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/TodoCategoryService.java @@ -0,0 +1,17 @@ +package com.todoslave.feedme.service; + +import com.todoslave.feedme.DTO.TodoCategoryRequestDTO; +import com.todoslave.feedme.DTO.TodoCategoryResponseDTO; +import java.util.List; + +public interface TodoCategoryService { + + public List getCategories(); + + public TodoCategoryResponseDTO updateCategory(TodoCategoryRequestDTO todoCategoryRequestDTO); + + public void deleteCategory(int id); + + public TodoCategoryResponseDTO insertCategory(String name); + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/TodoCategoryServiceImpl.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/TodoCategoryServiceImpl.java new file mode 100644 index 0000000..604afbd --- /dev/null +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/TodoCategoryServiceImpl.java @@ -0,0 +1,97 @@ +package com.todoslave.feedme.service; + +import com.todoslave.feedme.DTO.TodoCategoryRequestDTO; +import com.todoslave.feedme.DTO.TodoCategoryResponseDTO; +import com.todoslave.feedme.domain.entity.membership.Member; +import com.todoslave.feedme.domain.entity.task.TodoCategory; +import com.todoslave.feedme.login.util.SecurityUtil; +import com.todoslave.feedme.repository.MemberRepository; +import com.todoslave.feedme.repository.TodoCategoryRepository; +import jakarta.transaction.Transactional; +import java.util.ArrayList; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class TodoCategoryServiceImpl implements TodoCategoryService { + + @Autowired + private TodoCategoryRepository todoCategoryRepository; + @Autowired + private MemberRepository memberRepository; + + + // 카테고리들 가져오기 + @Override + public List getCategories() { + + int memberId = SecurityUtil.getCurrentUserId(); + List result = todoCategoryRepository.findAllByMemberId(memberId); + + List categories = new ArrayList<>(); + + for(TodoCategory todoCategory : result){ + + TodoCategoryResponseDTO todoCategoryResponseDTO = new TodoCategoryResponseDTO(); + todoCategoryResponseDTO.setId(todoCategory.getId()); + todoCategoryResponseDTO.setName(todoCategory.getName()); + categories.add(todoCategoryResponseDTO); + + } + + return categories; + } + + // 카테고리 수정 + @Override + @Transactional + public TodoCategoryResponseDTO updateCategory(TodoCategoryRequestDTO todoCategoryRequestDTO) { + + TodoCategory todoCategory = todoCategoryRepository.findById(todoCategoryRequestDTO.getId()).orElseThrow(); + todoCategory.setName(todoCategoryRequestDTO.getName()); + TodoCategoryResponseDTO result = new TodoCategoryResponseDTO(); + result.setName(todoCategory.getName()); + result.setId(todoCategory.getId()); + + return result; + } + + // 카테고리 삭제 + @Override + @Transactional + public void deleteCategory(int id) { + + todoCategoryRepository.deleteById(id); + + } + + // 카테고리 등록 + @Override + public TodoCategoryResponseDTO insertCategory(String name) { + + if(name==null){ + System.out.println("null인데용?"); + } + + Member member = SecurityUtil.getCurrentMember(); + + TodoCategory todoCategory = new TodoCategory(); + + System.out.println(" - -- 출력되나?"+name); + System.out.println("- - - 출력되ㅣ시나요>"+member); + + todoCategory.setName(name); + todoCategory.setMember(member); + todoCategory = todoCategoryRepository.save(todoCategory); + + TodoCategoryResponseDTO todoCategoryResponseDTO = new TodoCategoryResponseDTO(); + todoCategoryResponseDTO.setId(todoCategory.getId()); + todoCategoryResponseDTO.setName(todoCategory.getName()); + + return todoCategoryResponseDTO; + } + +} diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/TodoService.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/TodoService.java index 39085fd..a8db632 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/TodoService.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/TodoService.java @@ -1,27 +1,45 @@ package com.todoslave.feedme.service; +import com.todoslave.feedme.DTO.TodoCalendarResponseDTO; +import com.todoslave.feedme.DTO.TodoCreateRequestDTO; +import com.todoslave.feedme.DTO.TodoDailyRequestDTO; +import com.todoslave.feedme.DTO.TodoResponseDTO; +import com.todoslave.feedme.DTO.TodoMainResponseDTO; +import com.todoslave.feedme.DTO.TodoModifyRequestDTO; +import com.todoslave.feedme.DTO.TodoRequestDTO; import com.todoslave.feedme.domain.entity.task.Todo; -import java.util.Date; + +import java.time.LocalDate; import java.util.List; public interface TodoService { - // 하루 일정 불러오기 - public List getTodoDaily(int memberId, Date createdAt); + // 할일 목록에서 일정 불러오기 + public List getTodoListDaily(TodoDailyRequestDTO todoDailyRequestDTO); + + // 메인 달력에서 일정 불러오기 + public List getTodoCalendarDaily(TodoRequestDTO todoRequestDTO); + + // 메인화면에서 당일 안한 일정들 불러오기 + public List getTodoMainDaily(); + + // 월별 일정 완/미완 불러오기 (크리쳐 미션 포함) + public List getTodoCalendarCompleted(TodoRequestDTO todoRequestDTO); // 일정 추가하기 - public Todo insertTodo(Todo todo); + public TodoResponseDTO insertTodo(TodoCreateRequestDTO todoCreateRequestDTO); //일정 삭제하기 public void deleteTodo(int todoId); //일정 수정하기 - public Todo updateTodoContent(int todoId, String content); + public TodoResponseDTO updateTodo(TodoModifyRequestDTO todoModifyRequestDTO); //일정 완료하기 - public Todo completeTodo(int todo); + public TodoResponseDTO completeTodo(int todoId); - //모든 일정 완료하기 + //모든 일정 끝내기 (크리쳐 미션 포함) + public boolean AllcompleteTodo(TodoRequestDTO todoRequestDTO); // 그림일기 생성 diff --git a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/TodoServiceImpl.java b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/TodoServiceImpl.java index afaf9d2..5538cec 100644 --- a/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/TodoServiceImpl.java +++ b/Backend-feedme/feedme/src/main/java/com/todoslave/feedme/service/TodoServiceImpl.java @@ -1,49 +1,352 @@ package com.todoslave.feedme.service; +import com.todoslave.feedme.DTO.TodoCalendarResponseDTO; +import com.todoslave.feedme.DTO.TodoCreateRequestDTO; +import com.todoslave.feedme.DTO.TodoDailyRequestDTO; +import com.todoslave.feedme.DTO.TodoResponseDTO; +import com.todoslave.feedme.DTO.TodoMainResponseDTO; +import com.todoslave.feedme.DTO.TodoModifyRequestDTO; +import com.todoslave.feedme.DTO.TodoRequestDTO; +import com.todoslave.feedme.domain.entity.task.CreatureTodo; +import com.todoslave.feedme.domain.entity.task.DayOff; import com.todoslave.feedme.domain.entity.task.Todo; +import com.todoslave.feedme.gpt.dto.ChatGPTRequest; +import com.todoslave.feedme.gpt.dto.ChatGPTResponse; +import com.todoslave.feedme.login.util.SecurityUtil; +import com.todoslave.feedme.repository.CreatureTodoReposito; +import com.todoslave.feedme.repository.TodoCategoryRepository; import com.todoslave.feedme.repository.TodoRepository; -import jakarta.persistence.EntityNotFoundException; import jakarta.transaction.Transactional; -import java.util.Date; +import java.time.LocalDate; +import java.time.YearMonth; +import java.util.ArrayList; import java.util.List; import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; @RequiredArgsConstructor @Service public class TodoServiceImpl implements TodoService { + @Autowired private final TodoRepository todoRepository; + @Autowired + private final TodoCategoryRepository todoCategoryRepository; + @Autowired + private final CreatureTodoReposito creatureTodoReposito; + @Autowired + private final DayOffService dayOffService; + @Autowired + private final CreatureService creatureService; + @Autowired + private RestTemplate template; + // 할일 목록에서 일정(일) 불러오기 @Override - public List getTodoDaily(int memberId, Date createdAt) { - return todoRepository.findAllByMemberIdAndCreatedAt(memberId, createdAt); + public List getTodoListDaily(TodoDailyRequestDTO todoDailyRequestDTO) { + + LocalDate date = todoDailyRequestDTO.getDate(); + + if(todoDailyRequestDTO.getNext()<0){ + date.minusDays(1); + }else{ + date.plusDays(1); + } + + int memberId = SecurityUtil.getCurrentUserId(); + + List query = todoRepository.findAllByMemberIdAndCreatedAt(memberId, date); + List todos = new ArrayList<>(); + + for(Todo todo : query){ + + TodoResponseDTO responseDto = new TodoResponseDTO(); + responseDto.setId(todo.getId()); + responseDto.setCategoryId(todo.getTodoCategory().getId()); + responseDto.setCategoryName(todo.getTodoCategory().getName()); + responseDto.setContent(todo.getContent()); + responseDto.setCreatedAt(todo.getCreatedAt()); + responseDto.setIsCompleted(todo.getIsCompleted()); + + todos.add(responseDto); + + } + + return todos; } + // 메인 달력에서 일정 불러오기 @Override - public Todo insertTodo(Todo todo) { - return todoRepository.save(todo); + public List getTodoCalendarDaily(TodoRequestDTO todoRequestDTO) { + + LocalDate date = todoRequestDTO.getDate(); + + int memberId = SecurityUtil.getCurrentUserId(); + List query = todoRepository.findAllByMemberIdAndCreatedAt(memberId, date); + List todos = new ArrayList<>(); + + for(Todo todo : query){ + + TodoResponseDTO responseDto = new TodoResponseDTO(); + responseDto.setId(todo.getId()); + responseDto.setCategoryId(todo.getTodoCategory().getId()); + responseDto.setCategoryName(todo.getTodoCategory().getName()); + responseDto.setContent(todo.getContent()); + responseDto.setCreatedAt(todo.getCreatedAt()); + responseDto.setIsCompleted(todo.getIsCompleted()); + + todos.add(responseDto); + + } + + return todos; + } + // 메인화면에서 당일 안한 일정들 불러오기 + @Override + public List getTodoMainDaily() { + + LocalDate date = LocalDate.now(); + + int memberId = SecurityUtil.getCurrentUserId(); + List query = todoRepository.findAllByMemberIdAndCreatedAtIsCompleted(memberId, date, 0); + + List todos = new ArrayList<>(); + + for(Todo todo : query){ + + TodoMainResponseDTO responseDto = new TodoMainResponseDTO(); + responseDto.setId(todo.getId()); + responseDto.setContent(todo.getContent()); + responseDto.setIsCompleted(todo.getIsCompleted()); + + todos.add(responseDto); + + } + + return todos; + + } + + // 월별 일정 완/미완 불러오기 + @Override + public List getTodoCalendarCompleted(TodoRequestDTO todoRequestDTO) { + + int year = todoRequestDTO.getDate().getYear(); + int month = todoRequestDTO.getDate().getMonthValue(); + + YearMonth yearMonth = YearMonth.of(year, month); + LocalDate firstDay = yearMonth.atDay(1); + LocalDate lastDay = yearMonth.atEndOfMonth(); + //리스트 만들고 + List todoCounts = new ArrayList<>(); + + //1~31일까지 쭉 불러와 + for (LocalDate date = firstDay; !date.isAfter(lastDay); date = date.plusDays(1)) { + + TodoCalendarResponseDTO todoCalendarResponseDTO = new TodoCalendarResponseDTO(); + + //안한거 갯수 더라기 + long inCompleted = todoRepository.countTodoByDateAndIsCompleted(date, 0)+creatureTodoReposito.countByCreatedAtAndIsCompleted(date,0); + + todoCalendarResponseDTO.setInCompleted((int)inCompleted); + + long completed = todoRepository.countTodoByDateAndIsCompleted(date, 1)+creatureTodoReposito.countByCreatedAtAndIsCompleted(date,1); + + todoCalendarResponseDTO.setCompleted((int)completed); + + todoCalendarResponseDTO.setTotal((int)(inCompleted+completed)); + todoCalendarResponseDTO.setDate(date); + + todoCounts.add(todoCalendarResponseDTO); + + } + + + return todoCounts; + } + + // 일정 추가하기 + @Override + public TodoResponseDTO insertTodo(TodoCreateRequestDTO todoCreateRequestDTO) { + + Todo todo = new Todo(); + todo.setMember(SecurityUtil.getCurrentMember()); + todo.setTodoCategory(todoCategoryRepository.findById(todoCreateRequestDTO.getCategoryId()).orElseThrow()); + todo.setContent(todoCreateRequestDTO.getContent()); + todo = todoRepository.save(todo); + + TodoResponseDTO todoResponseDTO = new TodoResponseDTO(); + todoResponseDTO.setId(todo.getId()); + todoResponseDTO.setContent(todo.getContent()); + todoResponseDTO.setCategoryId(todo.getTodoCategory().getId()); + todoResponseDTO.setCategoryName(todo.getTodoCategory().getName()); + todoResponseDTO.setCreatedAt(todo.getCreatedAt()); + todoResponseDTO.setIsCompleted(todo.getIsCompleted()); + + return todoResponseDTO; + } + + //일정 삭제하기 @Override - @Transactional public void deleteTodo(int todoId) { todoRepository.deleteById(todoId); } + //일정 수정하기 @Override @Transactional - public Todo updateTodoContent(int todoId, String content) { - Todo newTodo = todoRepository.findById(todoId).orElseThrow(() -> new EntityNotFoundException("Todo not found")); - newTodo.setContent(content); - return newTodo; + public TodoResponseDTO updateTodo(TodoModifyRequestDTO todoModifyRequestDTO) { + Todo todo = todoRepository.findById(todoModifyRequestDTO.getId()).orElseThrow(); + todo.setContent(todoModifyRequestDTO.getContent()); + + TodoResponseDTO todoResponseDTO = new TodoResponseDTO(); + todoResponseDTO.setId(todo.getId()); + todoResponseDTO.setContent(todo.getContent()); + todoResponseDTO.setCategoryId(todo.getTodoCategory().getId()); + todoResponseDTO.setCategoryName(todo.getTodoCategory().getName()); + todoResponseDTO.setCreatedAt(todo.getCreatedAt()); + todoResponseDTO.setIsCompleted(todo.getIsCompleted()); + + return todoResponseDTO; } + //일정 완료하기 @Override @Transactional - public Todo completeTodo(int todoId) { - Todo newTodo = todoRepository.findById(todoId).orElseThrow(() -> new EntityNotFoundException("Todo not found")); - newTodo.setCompleted(true); - return newTodo; + public TodoResponseDTO completeTodo(int todoId) { + + Todo todo = todoRepository.findById(todoId).orElseThrow(); + todo.setIsCompleted(1); + + TodoResponseDTO todoResponseDTO = new TodoResponseDTO(); + todoResponseDTO.setId(todo.getId()); + todoResponseDTO.setContent(todo.getContent()); + todoResponseDTO.setCategoryId(todo.getTodoCategory().getId()); + todoResponseDTO.setCategoryName(todo.getTodoCategory().getName()); + todoResponseDTO.setCreatedAt(todo.getCreatedAt()); + todoResponseDTO.setIsCompleted(todo.getIsCompleted()); + + return todoResponseDTO; } + + @Override + public boolean AllcompleteTodo(TodoRequestDTO todoRequestDTO) { + LocalDate date = todoRequestDTO.getDate(); + + //만약에 완료를 이미 했다면 + if(!dayOffService.isActionAllowed(SecurityUtil.getCurrentUserId(),date)){ + return false; + } + + //완료처리 + DayOff dayOff = new DayOff(); + dayOff.setEndDay(date); + dayOff.setMember(SecurityUtil.getCurrentMember()); + dayOffService.saveDayOff(dayOff); + + //일정 끝내기 + List todoList = todoRepository.findByMemberIdAndCreatedAt(SecurityUtil.getCurrentUserId(),date); + //크리쳐 일정 끝내기 + List creatureTodoList = creatureTodoReposito.findByMemberIdAndCreatedAt(SecurityUtil.getCurrentUserId(),date); + + + // StringBuilder로 문자열 누적 + StringBuilder todoAllBuilder = new StringBuilder(); + int completedTodos = 0; + int completedCreatureTodos = 0; + + for (Todo todo : todoList) { + if (todo.getIsCompleted() == 1) { + todoAllBuilder.append(todo.getTodoCategory().getName()).append(" - ").append(todo.getContent()).append("\n"); + completedTodos++; + } + } + + for (CreatureTodo creatureTodo : creatureTodoList) { + if (creatureTodo.getIsCompleted() == 1) { + todoAllBuilder.append(creatureTodo.getContent()).append("\n"); + completedCreatureTodos++; + } + } + + // todoAll을 String으로 변환 + String todoAll = todoAllBuilder.toString(); + + String generatedDiaryEntry = generateDiaryEntry(todoAll);// 여기서 AI가 했던일을 일기로 만들어줌 + +// System.out.println(todoAll); +// System.out.println("이거야"); +// System.out.println(generatedDiaryEntry); +// +// +// //요청할때 날자랑 내 id 줘야함 +// // AI 요청!!!!!!!!!!!!!!!!!!!!! +// +// +//// int completedTodos = (int) todoList.stream().filter(todo -> todo.getIsCompleted() == 1).count(); +//// int completedCreatureTodos = (int) creatureTodoList.stream().filter(creatureTodo -> creatureTodo.getIsCompleted() == 1).count(); +// +// System.out.println(completedTodos+completedCreatureTodos); + + //경험치 올리기 + creatureService.expUp(completedTodos+completedCreatureTodos); + + + //예본 해 + return true; + } + + + // GPT API 호출을 통해 일기를 생성하는 메서드 + @Value("${openai.api.url}") + private String apiURL; + + private String generateDiaryEntry(String todoAll) { + String prompt = "다음 항목들을 바탕으로 한글로 일기를 작성해주세요. 150자 이내로 없는 얘기를 꾸며쓰지는말고, 자연스럽게 요약해 주세요:\n" + todoAll; + + // GPT API 호출 + ChatGPTRequest request = new ChatGPTRequest("gpt-3.5-turbo", prompt); + ChatGPTResponse response = template.postForObject(apiURL, request, ChatGPTResponse.class); + + // 응답 처리 + if (response != null && !response.getChoices().isEmpty()) { + String diaryEntry = response.getChoices().get(0).getMessage().getContent(); + + // 줄바꿈 제거 + diaryEntry = diaryEntry.replaceAll("\n+", " ").replaceAll("\\s+", " ").trim(); + + // 150자 이내로 요약 + if (diaryEntry.length() > 150) { + diaryEntry = truncateToNearestSentence(diaryEntry, 150); + } + + return diaryEntry; + } + + // 기본 응답 또는 오류 처리 + return "일기 작성에 실패했습니다."; + } + + //만약에 150자가 넘어간다면 + private String truncateToNearestSentence(String text, int maxLength) { + if (text.length() <= maxLength) { + return text; + } + + // 최대 길이에서 가장 가까운 문장의 끝 (마침표)을 찾습니다. + int end = text.lastIndexOf(". ", maxLength); + if (end == -1) { + // 문장이 없으면 최대 길이에서 잘라냅니다. + return text.substring(0, maxLength).trim(); + } + + // 문장이 있으면 해당 문장까지만 반환합니다. + return text.substring(0, end + 1).trim(); + } + } diff --git a/Backend-feedme/feedme/src/main/resources/application.properties b/Backend-feedme/feedme/src/main/resources/application.properties deleted file mode 100644 index 5e2ed67..0000000 --- a/Backend-feedme/feedme/src/main/resources/application.properties +++ /dev/null @@ -1,28 +0,0 @@ -spring.application.name=feedme -spring.main.application-class=com.todoslave.FeedmeApplication - -# MySQL ?? -spring.datasource.url=jdbc:mysql://localhost:3306/feedme -spring.datasource.username=ssafy -spring.datasource.password=ssafy -spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver - -# MongoDB ?? -spring.data.mongodb.host=localhost -spring.data.mongodb.port=27017 -spring.data.mongodb.database=feedme -spring.data.mongodb.uri=mongodb://localhost:27017/feedme - -spring.jpa.hibernate.ddl-auto=update -# 'create'? ?????? ?? ? ?? DB? ???? ?? ????. -# 'update'? ?? ???? ????? ??? ?? ??? ?????. - -spring.jpa.show-sql=true -spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect -spring.jpa.properties.hibernate.format_sql=true - -logging.level.org.hibernate.SQL=debug -logging.level.org.hibernate.type=trace -# Hibernate? ??? SQL? ???? ??? ?? ??? ?????. - - diff --git a/Backend-feedme/feedme/src/main/resources/application.yml b/Backend-feedme/feedme/src/main/resources/application.yml new file mode 100644 index 0000000..c53601c --- /dev/null +++ b/Backend-feedme/feedme/src/main/resources/application.yml @@ -0,0 +1,184 @@ +#spring: +# application: +# name: feedme +# admin: +# enabled: false # Spring Boot Admin 비활성화 +# jmx: +# enabled: false # JMX 비활성화 +## main: +## application-class: com.todoslave.FeedmeApplication +# +# security: +# oauth2: +# client: +# registration: +# naver: +# client-id: ${NAVER_CLIENT_ID} +# client-secret: ${NAVER_CLIENT_SECRET} +# client-name: Naver +# redirect-uri: http://localhost:8080/login/oauth2/code/naver +# authorization-grant-type: authorization_code +# scope: +# - name +# - email +# kakao: +# client-id: ${KAKAO_CLIENT_ID} +# client-secret: ${KAKAO_CLIENT_SECRET} +# client-name: Kakao +# client-authentication-method: client_secret_post +# redirect-uri: http://localhost:8080/login/oauth2/code/kakao +# authorization-grant-type: authorization_code +# scope: +# - profile_nickname +# - account_email +# provider: +# naver: +# authorization-uri: https://nid.naver.com/oauth2.0/authorize +# token-uri: https://nid.naver.com/oauth2.0/token +# user-info-uri: https://openapi.naver.com/v1/nid/me +# user-name-attribute: response +# kakao: +# authorizationUri: https://kauth.kakao.com/oauth/authorize +# tokenUri: https://kauth.kakao.com/oauth/token +# userInfoUri: https://kapi.kakao.com/v2/user/me +# userNameAttribute: id +# +# datasource: +# url: jdbc:mysql://localhost:3306/feedme +# username: ${DB_USERNAME} +# password: ${DB_PASSWORD} +# driver-class-name: com.mysql.cj.jdbc.Driver +# +# data: +# mongodb: +# host: localhost +# port: 27017 +# database: feedme +# uri: mongodb://localhost:27017/feedme +# +# jpa: +# hibernate: +# ddl-auto: update +# show-sql: true +# properties: +# hibernate: +# dialect: org.hibernate.dialect.MySQL8Dialect +# format_sql: true +# +#logging: +# level: +# org: +# hibernate: +# SQL: debug +# type: trace +# +#redis: +# host: localhost +# port: 6379 +# +#jwt: +# issuer: todoslave@ssafy.com +# secret_key: ${JWT_SECRET_KEY} +# +# +# #이건 살림 +#openai: +# model: "gpt-3.5-turbo" +# api: +# key: "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" +# url: "https://api.openai.com/v1/chat/completions" +# +# + + +spring: + application: + name: feedme + admin: + enabled: false # Spring Boot Admin 비활성화 + jmx: + enabled: false # JMX 비활성화 + main: + application-class: com.todoslave.FeedmeApplication + + security: + oauth2: + client: + registration: + naver: + client-id: ${NAVER_CLIENT_ID} + client-secret: ${NAVER_CLIENT_SECRET} + client-name: Naver + redirect-uri: https://i11b104.p.ssafy.io/api/login/oauth2/code/naver + authorization-grant-type: authorization_code + scope: + - name + - email + kakao: + client-id: ${KAKAO_CLIENT_ID} + client-secret: ${KAKAO_CLIENT_SECRET} + client-name: Kakao + client-authentication-method: client_secret_post + redirect-uri: https://i11b104.p.ssafy.io/api/login/oauth2/code/kakao + authorization-grant-type: authorization_code + scope: + - profile_nickname + - account_email + provider: + naver: + authorization-uri: https://nid.naver.com/oauth2.0/authorize + token-uri: https://nid.naver.com/oauth2.0/token + user-info-uri: https://openapi.naver.com/v1/nid/me + user-name-attribute: response + kakao: + authorizationUri: https://kauth.kakao.com/oauth/authorize + tokenUri: https://kauth.kakao.com/oauth/token + userInfoUri: https://kapi.kakao.com/v2/user/me + userNameAttribute: id + + datasource: + url: jdbc:mysql://mysql:3306/feedme # MySQL 컨테이너 이름 사용 + username: ${DB_USERNAME} + password: ${DB_PASSWORD} + driver-class-name: com.mysql.cj.jdbc.Driver + + data: + mongodb: + host: mongodb # MongoDB 컨테이너 이름 사용 + port: 27017 + database: feedme + uri: mongodb://mongodb:27017/feedme + + redis: + host: redis + port: 6379 + + + jpa: + hibernate: + ddl-auto: update + show-sql: true + properties: + hibernate: + dialect: org.hibernate.dialect.MySQL8Dialect + format_sql: true + +logging: + level: + org: + hibernate: + SQL: debug + type: trace + +jwt: + issuer: todoslave@ssafy.com + secret_key: ${JWT_SECRET_KEY} + +openai: + model: "gpt-3.5-turbo" + api: + key: "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" + url: "https://api.openai.com/v1/chat/completions" + +server: + port: 8085 diff --git a/Backend-feedme/feedme/src/main/resources/templates/articleList.html b/Backend-feedme/feedme/src/main/resources/templates/articleList.html new file mode 100644 index 0000000..cd396b6 --- /dev/null +++ b/Backend-feedme/feedme/src/main/resources/templates/articleList.html @@ -0,0 +1,35 @@ + + + + + 블로그 글 목록 + + + +
+

My Blog

+

블로그에 오신 것을 환영합니다.

+
+ +
+ +
+
+
+
+
+
+

+ 보러가기 +
+
+
+
+ + +
+ + + diff --git a/Backend-feedme/feedme/src/main/resources/templates/index.html b/Backend-feedme/feedme/src/main/resources/templates/index.html new file mode 100644 index 0000000..536b98f --- /dev/null +++ b/Backend-feedme/feedme/src/main/resources/templates/index.html @@ -0,0 +1,13 @@ + + + + + Title + + +

Hello Spring Boot

+Google Login +Naver Login +Kakao Login + + \ No newline at end of file diff --git a/Backend-feedme/feedme/src/main/resources/templates/login.html b/Backend-feedme/feedme/src/main/resources/templates/login.html new file mode 100644 index 0000000..b10cad9 --- /dev/null +++ b/Backend-feedme/feedme/src/main/resources/templates/login.html @@ -0,0 +1,13 @@ + + + + + Title + + +

Hello Spring Boot

+Google Login +Naver Login +Kakao Login + + \ No newline at end of file diff --git a/Backend-feedme/feedme/src/main/resources/templates/loginSuccess.html b/Backend-feedme/feedme/src/main/resources/templates/loginSuccess.html new file mode 100644 index 0000000..588fcef --- /dev/null +++ b/Backend-feedme/feedme/src/main/resources/templates/loginSuccess.html @@ -0,0 +1,15 @@ + + + + + Login Success + + +

Login Success

+

Access Token:

+ + + diff --git a/Backend-feedme/feedme/src/main/resources/templates/signup.html b/Backend-feedme/feedme/src/main/resources/templates/signup.html new file mode 100644 index 0000000..98e4e74 --- /dev/null +++ b/Backend-feedme/feedme/src/main/resources/templates/signup.html @@ -0,0 +1,17 @@ + + + + + Signup + + +

Signup Page

+

Email:

+

Provider:

+ + + diff --git a/Backend-feedme/feedme/src/main/resources/templates/test.html b/Backend-feedme/feedme/src/main/resources/templates/test.html new file mode 100644 index 0000000..75e40f1 --- /dev/null +++ b/Backend-feedme/feedme/src/main/resources/templates/test.html @@ -0,0 +1,11 @@ + + + + + Title + + +

요기요!!

+ + + \ No newline at end of file diff --git a/Backend-feedme/feedme/src/main/resources/templates/testsite.html b/Backend-feedme/feedme/src/main/resources/templates/testsite.html new file mode 100644 index 0000000..fa26db2 --- /dev/null +++ b/Backend-feedme/feedme/src/main/resources/templates/testsite.html @@ -0,0 +1,10 @@ + + + + + Title + + +

요기요!!

+ + \ No newline at end of file