From 80513c0146e62420e9bac2c60a94d4c37f9ced2d Mon Sep 17 00:00:00 2001 From: jungmin Date: Mon, 15 Jul 2024 13:14:21 +0900 Subject: [PATCH 001/197] =?UTF-8?q?feat:=20=EC=B4=88=EA=B8=B0=EC=84=A4?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/build.gradle | 35 ++++------ .../edufocus/video/controller/Controller.java | 64 +++++++++++++++++++ .../src/main/resources/application.properties | 16 +++++ 3 files changed, 94 insertions(+), 21 deletions(-) create mode 100644 backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java diff --git a/backend/build.gradle b/backend/build.gradle index d1068ef..6c0680f 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -1,38 +1,31 @@ plugins { id 'java' - id 'org.springframework.boot' version '3.3.1' - id 'io.spring.dependency-management' version '1.1.5' + id 'org.springframework.boot' version '3.2.7' + id 'io.spring.dependency-management' version '1.1.0' } -group = 'com.edufocus' +group = 'io.openvidu' version = '0.0.1-SNAPSHOT' - -java { - toolchain { - languageVersion = JavaLanguageVersion.of(17) - } -} - -configurations { - compileOnly { - extendsFrom annotationProcessor - } -} +description = 'Basic server application built for Java with Spring Boot' +sourceCompatibility = '17' +targetCompatibility = '17' repositories { mavenCentral() } dependencies { - implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-web' - compileOnly 'org.projectlombok:lombok' - runtimeOnly 'com.mysql:mysql-connector-j' - annotationProcessor 'org.projectlombok:lombok' + implementation 'org.openpnp:opencv:4.9.0-0' + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'io.livekit:livekit-server:0.5.11' + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'mysql:mysql-connector-java:8.0.33' testImplementation 'org.springframework.boot:spring-boot-starter-test' - testRuntimeOnly 'org.junit.platform:junit-platform-launcher' + implementation group: 'io.livekit', name: 'livekit-server', version: '0.6.1' + } -tasks.named('test') { +test { useJUnitPlatform() } diff --git a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java new file mode 100644 index 0000000..ab3a751 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java @@ -0,0 +1,64 @@ +package com.edufocus.edufocus.video.controller; + +import io.livekit.server.AccessToken; +import io.livekit.server.RoomJoin; +import io.livekit.server.RoomName; +import io.livekit.server.WebhookReceiver; +import livekit.LivekitWebhook.WebhookEvent; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.Map; + +@CrossOrigin(origins = "*") +@RestController +public class Controller { + + @Value("${livekit.api.key}") + private String LIVEKIT_API_KEY; + + @Value("${livekit.api.secret}") + private String LIVEKIT_API_SECRET; + + /** + * @param params JSON object with roomName and participantName + * @return JSON object with the JWT token + */ + @PostMapping(value = "/token") + public ResponseEntity> createToken(@RequestBody Map params) { + String roomName = params.get("roomName"); + String participantName = params.get("participantName"); + + if (roomName == null || participantName == null) { + return ResponseEntity.badRequest().body(Map.of("errorMessage", "roomName and participantName are required")); + } + + AccessToken token = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); + + + token.setName(participantName); + token.setIdentity(participantName); + token.addGrants(new RoomJoin(true), new RoomName(roomName)); + + // 방이름으로 입장하는건데 + // 만약 수강생에 DB에 신청한 강의명이 없다면 들어갈수 없음 + // 검증 로직만 추가하면 될듯? + + + return ResponseEntity.ok(Map.of("token", token.toJwt())); + } + + @PostMapping(value = "/webhook", consumes = "application/webhook+json") + public ResponseEntity receiveWebhook(@RequestHeader("Authorization") String authHeader, @RequestBody String body) { + WebhookReceiver webhookReceiver = new WebhookReceiver(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); + try { + WebhookEvent event = webhookReceiver.receive(body, authHeader); + System.out.println("LiveKit Webhook: " + event.toString()); + } catch (Exception e) { + System.err.println("Error validating webhook event: " + e.getMessage()); + } + return ResponseEntity.ok("ok"); + } + +} diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index d5ad940..172132c 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -1 +1,17 @@ spring.application.name=edufocus + +server.port=${SERVER_PORT:6080} +server.ssl.enabled=false + +# LiveKit configuration +livekit.api.key=${LIVEKIT_API_KEY:devkey} +livekit.api.secret=${LIVEKIT_API_SECRET:secret} + +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver +spring.datasource.url=jdbc:mysql://localhost:3306/edufocus?serverTimezone=Asia/Seoul +spring.datasource.username=root +spring.datasource.password=root + +spring.jpa.database=mysql +spring.jpa.hibernate.ddl-auto=update +spring.jpa.show-sql=true From ea611db970003af690f80a3f97cac970d6401ee3 Mon Sep 17 00:00:00 2001 From: jungmin Date: Mon, 15 Jul 2024 17:09:19 +0900 Subject: [PATCH 002/197] =?UTF-8?q?feat:=EC=9C=A0=EC=A0=80=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/build.gradle | 4 ++ .../edufocus/swagger/SwaggerConfig.java | 20 +++++++++ .../user/controller/UserController.java | 41 ++++++++++++++++++ .../edufocus/user/model/entity/User.java | 28 ++++++++++++ .../edufocus/user/model/entity/UserRole.java | 5 +++ .../user/model/exception/UserException.java | 8 ++++ .../user/model/repository/UserRepository.java | 8 ++++ .../user/model/service/UserService.java | 8 ++++ .../user/model/service/UserServiceImpl.java | 43 +++++++++++++++++++ .../src/main/resources/application.properties | 8 ++-- 10 files changed, 170 insertions(+), 3 deletions(-) create mode 100644 backend/src/main/java/com/edufocus/edufocus/swagger/SwaggerConfig.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/user/model/entity/User.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/user/model/entity/UserRole.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/user/model/exception/UserException.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/user/model/repository/UserRepository.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java diff --git a/backend/build.gradle b/backend/build.gradle index 6c0680f..ad4e920 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -23,6 +23,10 @@ dependencies { implementation 'mysql:mysql-connector-java:8.0.33' testImplementation 'org.springframework.boot:spring-boot-starter-test' implementation group: 'io.livekit', name: 'livekit-server', version: '0.6.1' + implementation 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok' + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0' + } diff --git a/backend/src/main/java/com/edufocus/edufocus/swagger/SwaggerConfig.java b/backend/src/main/java/com/edufocus/edufocus/swagger/SwaggerConfig.java new file mode 100644 index 0000000..7d71ef7 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/swagger/SwaggerConfig.java @@ -0,0 +1,20 @@ +package com.edufocus.edufocus.swagger; + +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Info; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class SwaggerConfig { + + @Bean + public OpenAPI openAPI() { + return new OpenAPI() + .info(new Info() + .title("에듀포커스 API") + .description("") + .version("1.0.0")); + } + } \ No newline at end of file diff --git a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java new file mode 100644 index 0000000..19b306d --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java @@ -0,0 +1,41 @@ +package com.edufocus.edufocus.user.controller; + +import com.edufocus.edufocus.user.model.entity.User; +import com.edufocus.edufocus.user.model.service.UserService; +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.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/user") +@Slf4j +@RequiredArgsConstructor +public class UserController { + + private final UserService userService; + + @PostMapping("/join") + public ResponseEntity join(@RequestBody User user) throws Exception { + + System.out.println("!!!"); + userService.join(user); + return ResponseEntity.ok("User registered successfully"); + } + + + @PostMapping("/login") + public ResponseEntity login(@RequestBody User user) { + try { + User loggedInUser = userService.login(user); + return ResponseEntity.ok(loggedInUser); + + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/User.java b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/User.java new file mode 100644 index 0000000..8914cd3 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/User.java @@ -0,0 +1,28 @@ +package com.edufocus.edufocus.user.model.entity; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Entity +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class User { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) // 자동 증가 설정 + private Long id; + + private String user_id; + private String email; + private String password; + @Enumerated(EnumType.STRING) // 혹은 EnumType.ORDINAL + private UserRole role; + + + +} diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/UserRole.java b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/UserRole.java new file mode 100644 index 0000000..48f8cc1 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/UserRole.java @@ -0,0 +1,5 @@ +package com.edufocus.edufocus.user.model.entity; + +public enum UserRole { + STUDENT,ADMIN +} diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/exception/UserException.java b/backend/src/main/java/com/edufocus/edufocus/user/model/exception/UserException.java new file mode 100644 index 0000000..5c73dc1 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/exception/UserException.java @@ -0,0 +1,8 @@ +package com.edufocus.edufocus.user.model.exception; + +public class UserException extends RuntimeException{ + + public UserException(String message){ + super(message); + } +} diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/repository/UserRepository.java b/backend/src/main/java/com/edufocus/edufocus/user/model/repository/UserRepository.java new file mode 100644 index 0000000..d05e98e --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/repository/UserRepository.java @@ -0,0 +1,8 @@ +package com.edufocus.edufocus.user.model.repository; + +import com.edufocus.edufocus.user.model.entity.User; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface UserRepository extends JpaRepository { + +} diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java new file mode 100644 index 0000000..ba32a4f --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java @@ -0,0 +1,8 @@ +package com.edufocus.edufocus.user.model.service; + +import com.edufocus.edufocus.user.model.entity.User; + +public interface UserService { + void join(User user) throws Exception; + User login(User user) throws Exception; +} diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java new file mode 100644 index 0000000..e2719bf --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java @@ -0,0 +1,43 @@ +package com.edufocus.edufocus.user.model.service; + + +import com.edufocus.edufocus.user.model.entity.User; +import com.edufocus.edufocus.user.model.exception.UserException; +import com.edufocus.edufocus.user.model.repository.UserRepository; +import jakarta.transaction.Transactional; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.sql.SQLException; +import java.util.Optional; + +@Service +@Transactional +@RequiredArgsConstructor +public class UserServiceImpl implements UserService{ + + @Autowired + private final UserRepository userRepository; + + + public void join(User user) + { + userRepository.save(user); + } + + public User login(User user) throws SQLException + { + Optional findUser = userRepository.findById(user.getId()); + + if(findUser.isEmpty()) + { + throw new UserException("없는 유저"); + + } + return findUser.get(); + } + + + +} diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 172132c..8ec1189 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -1,6 +1,6 @@ spring.application.name=edufocus +server.port=8080 -server.port=${SERVER_PORT:6080} server.ssl.enabled=false # LiveKit configuration @@ -8,10 +8,12 @@ livekit.api.key=${LIVEKIT_API_KEY:devkey} livekit.api.secret=${LIVEKIT_API_SECRET:secret} spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver -spring.datasource.url=jdbc:mysql://localhost:3306/edufocus?serverTimezone=Asia/Seoul +spring.datasource.url=jdbc:mysql://localhost:3306/edufocus?useSSL=false spring.datasource.username=root spring.datasource.password=root +spring.mvc.pathmatch.matching-strategy=ant_path_matcher spring.jpa.database=mysql -spring.jpa.hibernate.ddl-auto=update +spring.jpa.hibernate.ddl-auto=create spring.jpa.show-sql=true + From ed966e985ebad8cb8a13848c62129e3a6a8fa16c Mon Sep 17 00:00:00 2001 From: kgc9007 Date: Tue, 16 Jul 2024 13:20:16 +0900 Subject: [PATCH 003/197] =?UTF-8?q?feat:=20lecture=20lecture=20entity,=20r?= =?UTF-8?q?epository,=20service,=20controller=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/build.gradle | 6 +- .../lecture/controller/LectureController.java | 56 +++++++++++++++++++ .../edufocus/lecture/entity/Lecture.java | 40 +++++++++++++ .../lecture/repository/LectureRepository.java | 15 +++++ .../lecture/service/LectureService.java | 23 ++++++++ .../lecture/service/LectureServiceImpl.java | 45 +++++++++++++++ .../src/main/resources/application.properties | 9 +-- 7 files changed, 189 insertions(+), 5 deletions(-) create mode 100644 backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/lecture/repository/LectureRepository.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java diff --git a/backend/build.gradle b/backend/build.gradle index 6c0680f..68902bf 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -23,9 +23,13 @@ dependencies { implementation 'mysql:mysql-connector-java:8.0.33' testImplementation 'org.springframework.boot:spring-boot-starter-test' implementation group: 'io.livekit', name: 'livekit-server', version: '0.6.1' + implementation 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok' + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0' + } test { useJUnitPlatform() -} +} \ No newline at end of file diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java b/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java new file mode 100644 index 0000000..ca8e1ff --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java @@ -0,0 +1,56 @@ +package com.edufocus.edufocus.lecture.controller; + +import com.edufocus.edufocus.lecture.entity.Lecture; +import com.edufocus.edufocus.lecture.service.LectureService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/lecture") +@Slf4j +@RequiredArgsConstructor +public class LectureController { + + private final LectureService lectureService; + + @PostMapping + public ResponseEntity createLecture (@RequestBody Lecture lecture) { + lectureService.createLecture(lecture); + return new ResponseEntity<>(HttpStatus.CREATED); + } + + @DeleteMapping("/{lectureId}") + public ResponseEntity deleteLecture (@PathVariable long lectureId) { + lectureService.deleteLecture(lectureId); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + @GetMapping + public ResponseEntity findAllLecture () { + List lectures = lectureService.findAllLecture(); + return new ResponseEntity<>(lectures, HttpStatus.OK); + } + + @GetMapping("/teacherId/{teacherId}") + public ResponseEntity findByTeacherId (@PathVariable String teacherId) { + List lectures = lectureService.findLectureByTeacherId(teacherId); + return new ResponseEntity<>(lectures, HttpStatus.OK); + } + + @GetMapping("/title/{title}") + public ResponseEntity findByTitle (@PathVariable String title) { + Lecture lecture = lectureService.findLectureByTitle(title); + + if (lecture == null) { + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + return new ResponseEntity<>(lecture, HttpStatus.OK); + } + +} diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java new file mode 100644 index 0000000..c006240 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java @@ -0,0 +1,40 @@ +package com.edufocus.edufocus.lecture.entity; + +import jakarta.persistence.*; +import lombok.Getter; +import lombok.Setter; + +import java.util.Date; + +@Entity +@Getter +@Setter +public class Lecture { + + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column + private Long id; + + @Column(name = "teacher_id") + private String teacherId; + + @Column + private String title; + + @Lob + private String description; + + @Column(name = "start_date") + @Temporal(TemporalType.DATE) + private Date startDate; + + @Column(name = "end_date") + @Temporal(TemporalType.DATE) + private Date endDate; + + @Lob + private String plan; + + + +} diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/repository/LectureRepository.java b/backend/src/main/java/com/edufocus/edufocus/lecture/repository/LectureRepository.java new file mode 100644 index 0000000..032085b --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/repository/LectureRepository.java @@ -0,0 +1,15 @@ +package com.edufocus.edufocus.lecture.repository; + +import com.edufocus.edufocus.lecture.entity.Lecture; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface LectureRepository extends JpaRepository { + Lecture findByTitle(@Param("title") String title); + + List findByTeacherId(@Param("teacherId") String teacherId); +} diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java new file mode 100644 index 0000000..777fd58 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java @@ -0,0 +1,23 @@ +package com.edufocus.edufocus.lecture.service; + +import com.edufocus.edufocus.lecture.entity.Lecture; +import jakarta.transaction.Transactional; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + + +@Service +public interface LectureService { + + void createLecture(Lecture lecture); + + void deleteLecture(long lectureId); + + Lecture findLectureByTitle(String title); + + List findLectureByTeacherId(String teacherId); + + List findAllLecture(); +} diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java new file mode 100644 index 0000000..0431045 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java @@ -0,0 +1,45 @@ +package com.edufocus.edufocus.lecture.service; + +import com.edufocus.edufocus.lecture.entity.Lecture; +import com.edufocus.edufocus.lecture.repository.LectureRepository; +import jakarta.transaction.Transactional; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; + +@Service +@Transactional +@RequiredArgsConstructor +public class LectureServiceImpl implements LectureService { + + @Autowired + private final LectureRepository lectureRepository; + + @Override + public void createLecture(Lecture lecture) { + lectureRepository.save(lecture); + } + + @Override + public void deleteLecture(long lectureId) { + lectureRepository.deleteById(lectureId); + } + + @Override + public Lecture findLectureByTitle(String title) { + return lectureRepository.findByTitle(title); + } + + @Override + public List findLectureByTeacherId(String teacherId) { + return lectureRepository.findByTeacherId(teacherId); + } + + @Override + public List findAllLecture() { + return lectureRepository.findAll(); + } +} diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 172132c..b1eeab4 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -1,6 +1,6 @@ spring.application.name=edufocus +server.port=8080 -server.port=${SERVER_PORT:6080} server.ssl.enabled=false # LiveKit configuration @@ -8,10 +8,11 @@ livekit.api.key=${LIVEKIT_API_KEY:devkey} livekit.api.secret=${LIVEKIT_API_SECRET:secret} spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver -spring.datasource.url=jdbc:mysql://localhost:3306/edufocus?serverTimezone=Asia/Seoul +spring.datasource.url=jdbc:mysql://localhost:3306/edufocus?useSSL=false spring.datasource.username=root spring.datasource.password=root +spring.mvc.pathmatch.matching-strategy=ant_path_matcher spring.jpa.database=mysql -spring.jpa.hibernate.ddl-auto=update -spring.jpa.show-sql=true +spring.jpa.hibernate.ddl-auto=create +spring.jpa.show-sql=true \ No newline at end of file From 92a21b61c1f9170a4950bdbad23b5e1f0a17d6a9 Mon Sep 17 00:00:00 2001 From: kgc9007 Date: Tue, 16 Jul 2024 17:48:27 +0900 Subject: [PATCH 004/197] =?UTF-8?q?feat:=20Registration=20Registration=20E?= =?UTF-8?q?ntity,=20Repository,=20Service,=20Controller=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/lecture/entity/Lecture.java | 2 + .../controller/RegistrationController.java | 42 +++++++++++++++++ .../registration/entity/Registration.java | 28 +++++++++++ .../entity/RegistrationStatus.java | 5 ++ .../repository/RegistrationRepository.java | 11 +++++ .../service/RegistrationService.java | 17 +++++++ .../service/RegistrationServiceImpl.java | 46 +++++++++++++++++++ 7 files changed, 151 insertions(+) create mode 100644 backend/src/main/java/com/edufocus/edufocus/registration/controller/RegistrationController.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/registration/entity/Registration.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/registration/entity/RegistrationStatus.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/registration/repository/RegistrationRepository.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationService.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java index c006240..5ae3972 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java @@ -35,6 +35,8 @@ public class Lecture { @Lob private String plan; + @Column + private boolean online; } diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/controller/RegistrationController.java b/backend/src/main/java/com/edufocus/edufocus/registration/controller/RegistrationController.java new file mode 100644 index 0000000..fc6e67d --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/registration/controller/RegistrationController.java @@ -0,0 +1,42 @@ +package com.edufocus.edufocus.registration.controller; + +import com.edufocus.edufocus.registration.entity.Registration; +import com.edufocus.edufocus.registration.service.RegistrationService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/registration") +@Slf4j +public class RegistrationController { + + private final RegistrationService registrationServiceImpl; + + public RegistrationController(RegistrationService registrationServiceImpl) { + this.registrationServiceImpl = registrationServiceImpl; + } + + @PostMapping + public ResponseEntity register(@RequestBody Registration registration) { + registrationServiceImpl.createRegistration(registration); + + return new ResponseEntity<>(HttpStatus.OK); + } + + @PatchMapping("/registrationId/{registrationId}") + public ResponseEntity acceptRigistration(@PathVariable long registrationId) { + registrationServiceImpl.acceptRegistration(registrationId); + + return new ResponseEntity<>(HttpStatus.OK); + } + + @DeleteMapping("/registrationId/{registrationId}") + public ResponseEntity deleteRigistration(@PathVariable long registrationId) { + registrationServiceImpl.deleteRegistration(registrationId); + + return new ResponseEntity<>(HttpStatus.OK); + } + +} diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/entity/Registration.java b/backend/src/main/java/com/edufocus/edufocus/registration/entity/Registration.java new file mode 100644 index 0000000..7e1cce6 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/registration/entity/Registration.java @@ -0,0 +1,28 @@ +package com.edufocus.edufocus.registration.entity; + +import com.edufocus.edufocus.lecture.entity.Lecture; +import com.edufocus.edufocus.user.model.entity.User; +import jakarta.persistence.*; +import lombok.Getter; +import lombok.Setter; + +@Entity +@Getter +@Setter +public class Registration { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private long id; + + @ManyToOne + @JoinColumn(name = "user_id") + private User user; + + @ManyToOne + @JoinColumn(name = "lecture_id") + private Lecture lecture; + + @Enumerated(EnumType.STRING) + private RegistrationStatus status ; +} diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/entity/RegistrationStatus.java b/backend/src/main/java/com/edufocus/edufocus/registration/entity/RegistrationStatus.java new file mode 100644 index 0000000..5540eed --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/registration/entity/RegistrationStatus.java @@ -0,0 +1,5 @@ +package com.edufocus.edufocus.registration.entity; + +public enum RegistrationStatus { + WAITING, ACCEPTED +} diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/repository/RegistrationRepository.java b/backend/src/main/java/com/edufocus/edufocus/registration/repository/RegistrationRepository.java new file mode 100644 index 0000000..f8dc7db --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/registration/repository/RegistrationRepository.java @@ -0,0 +1,11 @@ +package com.edufocus.edufocus.registration.repository; + +import com.edufocus.edufocus.registration.entity.Registration; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +@Repository +public interface RegistrationRepository extends JpaRepository { + +} diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationService.java b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationService.java new file mode 100644 index 0000000..fcaac94 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationService.java @@ -0,0 +1,17 @@ +package com.edufocus.edufocus.registration.service; + +import com.edufocus.edufocus.registration.entity.Registration; +import org.springframework.stereotype.Service; + +@Service +public interface RegistrationService { + + void createRegistration(Registration registration); + + void acceptRegistration(long RegistrationId); + + void deleteRegistration(long registrationId); + + boolean isAcceptedRegistration(long registrationId); + +} diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java new file mode 100644 index 0000000..6eadce6 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java @@ -0,0 +1,46 @@ +package com.edufocus.edufocus.registration.service; + +import com.edufocus.edufocus.registration.entity.Registration; +import com.edufocus.edufocus.registration.entity.RegistrationStatus; +import com.edufocus.edufocus.registration.repository.RegistrationRepository; +import jakarta.transaction.Transactional; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.Optional; + +@Service +@Transactional +@RequiredArgsConstructor +public class RegistrationServiceImpl implements RegistrationService { + + private final RegistrationRepository registrationRepository; + + @Override + public void createRegistration(Registration registration) { + registrationRepository.save(registration); + } + + @Override + public void acceptRegistration(long registrationId) { + Optional registration = registrationRepository.findById(registrationId); + + if (registration.isPresent()) { + Registration reg = registration.get(); + reg.setStatus(RegistrationStatus.valueOf("ACCEPTED")); + registrationRepository.save(reg); + } + } + + @Override + public void deleteRegistration(long registrationId) { + registrationRepository.deleteById(registrationId); + } + + @Override + public boolean isAcceptedRegistration(long registrationId) { + Optional registration = registrationRepository.findById(registrationId); + + return registration.isPresent() && registration.get().getStatus().equals("ACCEPTED"); + } +} From 4f5d367e016330d711363b493d4112e4952bc464 Mon Sep 17 00:00:00 2001 From: yulmam Date: Wed, 17 Jul 2024 17:14:36 +0900 Subject: [PATCH 005/197] =?UTF-8?q?feat=20:=20=EA=B2=8C=EC=8B=9C=ED=8C=90?= =?UTF-8?q?=20controller?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../board/controller/BoardController.java | 147 ++++++++++++++++++ .../entity/dto/RequestBoardDetailDto.java | 2 + .../board/entity/dto/RequestCommentDto.java | 2 + .../entity/dto/ResponseBoardDetailDto.java | 2 + .../board/entity/dto/ResponseBoardDto.java | 2 + .../edufocus/board/entity/vo/Board.java | 2 + .../edufocus/board/entity/vo/Comment.java | 2 + .../edufocus/board/service/BoardService.java | 2 + .../board/service/BoardServiceImpl.java | 2 + 9 files changed, 163 insertions(+) create mode 100644 backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/board/entity/dto/RequestBoardDetailDto.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/board/entity/dto/RequestCommentDto.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardDetailDto.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardDto.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/board/service/BoardService.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/board/service/BoardServiceImpl.java diff --git a/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java b/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java new file mode 100644 index 0000000..848335b --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java @@ -0,0 +1,147 @@ +package com.edufocus.edufocus.board.controller; + +import com.edufocus.edufocus.board.entity.dto.RequestBoardDetailDto; +import com.edufocus.edufocus.board.entity.dto.RequestCommentDto; +import com.edufocus.edufocus.board.entity.dto.ResponseBoardDetailDto; +import com.edufocus.edufocus.board.entity.dto.ResponseBoardDto; +import com.edufocus.edufocus.board.entity.vo.Comment; +import com.edufocus.edufocus.board.service.BoardService; +import jakarta.validation.constraints.Positive; +import org.springframework.data.domain.Pageable; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + + +/** + * @author Haneol Kim + */ +@RestController("/board") +public class BoardController { + + private final BoardService boardService; + + public BoardController(BoardService boardService){ + this.boardService = boardService; + } + + @GetMapping() + public ResponseEntity searchBoards( + Pageable pageable, + @RequestParam(value = "userId", required = true) int userId + ){ + + if(boardService.checkRegistration(userId, lectureId)){ + throw new RuntimeException(); + } + + List boards = boardService.findBoards(userId, category, lectureId); + + if(boards.isEmpty()){ + return ResponseEntity.noContent().build(); + } + + return ResponseEntity.ok(boards); + } + + @GetMapping(value = "/{boardId}") + public ResponseEntity getBoardDetail( + @PathVariable @Positive int boardId, + @RequestParam(value = "userId", required = true) @Positive int userId + ){ + ResponseBoardDetailDto responseBoardDetail = boardService.findBoardDetail(userId, boardId); + + return ResponseEntity.ok(responseBoardDetail); + } + + @PostMapping + public ResponseEntity addBoard( + @RequestBody RequestBoardDetailDto requestBoardDetailDto, + @RequestParam(value = "userId", required = true) @Positive int userId + ){ + if(boardService.checkRegistration(userId, requestBoardDetailDto.getLectureId())){ + throw new RuntimeException(); + } + + boardService.createBoard(userId, requestBoardDetailDto); + + return new ResponseEntity<>(HttpStatus.OK); + } + + @PutMapping(value = "/{boardId}") + public ResponseEntity updateBoard( + @PathVariable @Positive int boardId, + @RequestBody RequestBoardDetailDto requestBoardDetailDto, + @RequestParam(value = "userId", required = true) @Positive int userId + ){ + if(boardService.checkRegistration(userId, requestBoardDetailDto.getLectureId())){ + throw new RuntimeException(); + } + + boardService.createBoard(userId, requestBoardDetailDto); + + return new ResponseEntity<>(HttpStatus.OK); + } + + @DeleteMapping(value = "/{boardId}") + public ResponseEntity deleteBoard( + @PathVariable int boardId, + @RequestParam @Positive int userId + ){ + if(boardService.checkBoardOwner(userId, boardId)){ + throw new RuntimeException(); + } + + boardService.deleteBoard(boardId); + + return new ResponseEntity<>(HttpStatus.OK); + } + + @GetMapping(value = "/comment/{boardId}") + public ResponseEntity getComments( + @PathVariable @Positive int boardId, + @RequestParam @Positive int userId + ){ + List comments = boardService.findComments(userId, boardId); + + return ResponseEntity.ok(comments); + } + + @PostMapping(value = "/comment/{boardId}") + public ResponseEntity addComment( + @PathVariable @Positive int boardId, + @RequestParam int userId, + @RequestBody RequestCommentDto requestCommentDto + ){ + boardService.createComment(userId, boardId, requestCommentDto); + + return new ResponseEntity<>(HttpStatus.OK); + } + + @PutMapping(value = "/comment/{commentId}") + public ResponseEntity updateComment( + @RequestParam int userId, + @PathVariable @Positive int commentId, + @RequestBody RequestCommentDto requestCommentDto + ){ + boardService.checkCommentOwner(userId, commentId); + + boardService.updateComment(commentId, requestCommentDto); + + return new ResponseEntity<>(HttpStatus.OK); + } + + @DeleteMapping(value = "/comment/{commentId}") + public ResponseEntity deleteComment( + @PathVariable @Positive int commentId, + @RequestParam int userId + ){ + boardService.checkCommentOwner(userId, commentId); + + boardService.deleteComment(commentId); + + return new ResponseEntity<>(HttpStatus.OK); + } +} diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/RequestBoardDetailDto.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/RequestBoardDetailDto.java new file mode 100644 index 0000000..a88c1e0 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/RequestBoardDetailDto.java @@ -0,0 +1,2 @@ +package com.edufocus.edufocus.board.entity.dto;public class RequestBoartDetailDto { +} diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/RequestCommentDto.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/RequestCommentDto.java new file mode 100644 index 0000000..9a4ffcf --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/RequestCommentDto.java @@ -0,0 +1,2 @@ +package com.edufocus.edufocus.board.entity.dto;public class RequestCommentDto { +} diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardDetailDto.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardDetailDto.java new file mode 100644 index 0000000..383839a --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardDetailDto.java @@ -0,0 +1,2 @@ +package com.edufocus.edufocus.board.entity.dto;public class ResponseBoardDetailDto { +} diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardDto.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardDto.java new file mode 100644 index 0000000..cb700e9 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardDto.java @@ -0,0 +1,2 @@ +package com.edufocus.edufocus.board.entity.dto;public class ResponseBoardDto { +} diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java new file mode 100644 index 0000000..aca1d4d --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java @@ -0,0 +1,2 @@ +package com.edufocus.edufocus.board.entity.vo;public class Board { +} diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java new file mode 100644 index 0000000..92d3c3e --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java @@ -0,0 +1,2 @@ +package com.edufocus.edufocus.board.entity.vo;public class Comment { +} diff --git a/backend/src/main/java/com/edufocus/edufocus/board/service/BoardService.java b/backend/src/main/java/com/edufocus/edufocus/board/service/BoardService.java new file mode 100644 index 0000000..fad3c9d --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/board/service/BoardService.java @@ -0,0 +1,2 @@ +package com.edufocus.edufocus.board.service;public interface BoardService { +} diff --git a/backend/src/main/java/com/edufocus/edufocus/board/service/BoardServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/board/service/BoardServiceImpl.java new file mode 100644 index 0000000..7292811 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/board/service/BoardServiceImpl.java @@ -0,0 +1,2 @@ +package com.edufocus.edufocus.board.service;public class BoardServiceImpl { +} From 5e7d5fe67b96ed3a876bb32326a8db16172b1b42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Wed, 17 Jul 2024 17:30:04 +0900 Subject: [PATCH 006/197] Feat: qna --- .../edufocus/lecture/entity/Lecture.java | 9 +- .../qna/controller/QnaController.java | 83 +++++++++++++++++++ .../com/edufocus/edufocus/qna/entity/Qna.java | 58 +++++++++++++ .../qna/repository/QnaRepository.java | 18 ++++ .../edufocus/qna/service/QnaService.java | 19 +++++ .../edufocus/qna/service/QnaServiceImpl.java | 60 ++++++++++++++ .../user/controller/UserController.java | 2 +- .../edufocus/user/model/entity/User.java | 12 ++- 8 files changed, 258 insertions(+), 3 deletions(-) create mode 100644 backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/qna/repository/QnaRepository.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/qna/service/QnaService.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java index 5ae3972..b72e926 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java @@ -1,10 +1,13 @@ package com.edufocus.edufocus.lecture.entity; +import com.edufocus.edufocus.qna.entity.Qna; import jakarta.persistence.*; import lombok.Getter; import lombok.Setter; +import java.util.ArrayList; import java.util.Date; +import java.util.List; @Entity @Getter @@ -12,7 +15,8 @@ import java.util.Date; public class Lecture { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column + + @Column(name="lecture_id") private Long id; @Column(name = "teacher_id") @@ -38,5 +42,8 @@ public class Lecture { @Column private boolean online; +// +// @OneToMany(mappedBy = "lecture") +// private List qnas = new ArrayList<>(); } diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java b/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java new file mode 100644 index 0000000..fb3356f --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java @@ -0,0 +1,83 @@ +package com.edufocus.edufocus.qna.controller; + +import com.edufocus.edufocus.qna.entity.Qna; +import com.edufocus.edufocus.qna.service.QnaService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import okhttp3.Response; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.sql.SQLException; +import java.util.List; + +@RestController +@RequestMapping("/qna") +@Slf4j +@RequiredArgsConstructor +public class QnaController { + private final QnaService qnaService; + + + @PostMapping + public ResponseEntity createQna(@RequestBody Qna qna) { + try{ + qnaService.createQna(qna); + return new ResponseEntity<>(qna, HttpStatus.CREATED); + + }catch (Exception e){ + throw new RuntimeException(e); + } + } + @PutMapping("/{id}") + public ResponseEntity updateQna(@PathVariable Long id, @RequestBody Qna qna) { + + try{ + qnaService.updateQna(id,qna); + return new ResponseEntity<>(qna, HttpStatus.ACCEPTED); + + }catch (Exception e) + { + throw new RuntimeException(e); } + } + + @DeleteMapping("/{id}") + public ResponseEntity deleteQna(@PathVariable Long id) { + try { + qnaService.deleteQna(id); + return new ResponseEntity<>(HttpStatus.ACCEPTED); + + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + @GetMapping("/{id}") + public ResponseEntity getQna(@PathVariable Long id) { + try{ + Qna findQna= qnaService.getQna(id); + return new ResponseEntity<>(findQna, HttpStatus.ACCEPTED); + + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + @GetMapping("/all/{id}") + public ResponseEntity> getAllQna(@PathVariable Long id) { + try { + + System.out.print("@@@@@@@@@@@@@@@@@@@@@@@>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); + List qnaList= qnaService.getAllQnasByLecture(id); + for(Qna qna:qnaList) + { + System.out.print(qna.toString()); + } + return new ResponseEntity<>(qnaList, HttpStatus.ACCEPTED); + } catch (SQLException e) { + throw new RuntimeException(e); + + } + } +} diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java b/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java new file mode 100644 index 0000000..ddbc743 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java @@ -0,0 +1,58 @@ +package com.edufocus.edufocus.qna.entity; + +import com.edufocus.edufocus.lecture.entity.Lecture; +import com.edufocus.edufocus.user.model.entity.User; +import jakarta.persistence.*; +import lombok.Getter; +import lombok.Setter; +import org.checkerframework.checker.units.qual.C; + +import java.util.Date; + +@Entity +@Getter +@Setter +public class Qna { + + // 연관관계 주인 + + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name= "qna_id") + private Long id; + + // user_id + // lecture_id + + + + @Column + private String title; + + @Column + private String content; + + + @Column(name = "created_at") + @Temporal(TemporalType.DATE) + private Date createdAt; + + @Column(name = "modified_at") + @Temporal(TemporalType.DATE) + private Date modifiedAt; + + @Column + private String answer; + + + @ManyToOne + @JoinColumn(name= "id") + private User user; + + @ManyToOne + @JoinColumn(name= "lecture_id") + private Lecture lecture; + + +} diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/repository/QnaRepository.java b/backend/src/main/java/com/edufocus/edufocus/qna/repository/QnaRepository.java new file mode 100644 index 0000000..beeba54 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/qna/repository/QnaRepository.java @@ -0,0 +1,18 @@ +package com.edufocus.edufocus.qna.repository; + +import com.edufocus.edufocus.qna.entity.Qna; +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.util.List; + +@Repository +public interface QnaRepository extends JpaRepository { + + @Query(value = "SELECT * FROM qna WHERE lecture_id = :lectureId", nativeQuery = true) + List findLecture(@Param("lectureId") Long lectureId); + + +} diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaService.java b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaService.java new file mode 100644 index 0000000..a1b8d94 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaService.java @@ -0,0 +1,19 @@ +package com.edufocus.edufocus.qna.service; + +import com.edufocus.edufocus.lecture.entity.Lecture; +import com.edufocus.edufocus.qna.entity.Qna; +import jakarta.transaction.Transactional; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.sql.SQLException; +import java.util.List; +@Service +public interface QnaService { + + void createQna(Qna qna) throws SQLException; + void updateQna(Long id,Qna qna) throws SQLException; + void deleteQna(Long id) throws SQLException; + Qna getQna(Long id) throws SQLException; + List getAllQnasByLecture(Long lectureId) throws SQLException; +} diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java new file mode 100644 index 0000000..18a59c1 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java @@ -0,0 +1,60 @@ +package com.edufocus.edufocus.qna.service; + +import com.edufocus.edufocus.qna.entity.Qna; +import com.edufocus.edufocus.qna.repository.QnaRepository; +import jakarta.transaction.Transactional; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import org.springframework.stereotype.Service; + +import java.util.Date; +import java.util.List; +import java.util.Optional; + +@Service +@Transactional +@RequiredArgsConstructor +public class QnaServiceImpl implements QnaService{ + + private final QnaRepository qnaRepository; + + + @Override + public void createQna(Qna qna) { + + + qnaRepository.save(qna); + + } + + @Override + public void updateQna(Long id,Qna qna) { + + + Optional findQna = qnaRepository.findById(id); + + qna.setModifiedAt(new Date()); + qnaRepository.save(qna); + + + } + + @Override + public void deleteQna(Long id) { +qnaRepository.deleteById(id); + } + + @Override + public Qna getQna(Long id) { + return null; + } + + @Override + public List getAllQnasByLecture(Long lectureId) { + + + System.out.printf(lectureId+"!!!!!!!!!!!!!!!!!!!!!!"); + return qnaRepository.findLecture(lectureId); + + } +} diff --git a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java index 19b306d..ee15c64 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java @@ -22,7 +22,7 @@ public class UserController { @PostMapping("/join") public ResponseEntity join(@RequestBody User user) throws Exception { - System.out.println("!!!"); + userService.join(user); return ResponseEntity.ok("User registered successfully"); } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/User.java b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/User.java index 8914cd3..e8c64a9 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/User.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/User.java @@ -1,10 +1,15 @@ package com.edufocus.edufocus.user.model.entity; +import com.edufocus.edufocus.qna.entity.Qna; import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import org.checkerframework.checker.units.qual.A; + +import java.util.ArrayList; +import java.util.List; @Entity @Getter @@ -15,14 +20,19 @@ public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) // 자동 증가 설정 + @Column(name = "id") private Long id; - private String user_id; + + private String userId; private String email; private String password; @Enumerated(EnumType.STRING) // 혹은 EnumType.ORDINAL private UserRole role; +// +// @OneToMany(mappedBy = "user") +// private List qnas= new ArrayList<>(); } From 9757378bd70ee5ef3aac719fdc94f9660a4ae8af Mon Sep 17 00:00:00 2001 From: kgc9007 Date: Wed, 17 Jul 2024 17:37:49 +0900 Subject: [PATCH 007/197] =?UTF-8?q?feat:=20Lecture=20lecture=20=EB=93=B1?= =?UTF-8?q?=EB=A1=9D,=20=EC=82=AD=EC=A0=9C=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20Quiz=20=EC=97=94=ED=8B=B0=ED=8B=B0=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lecture/controller/LectureController.java | 23 ++++---- .../edufocus/lecture/entity/Lecture.java | 6 ++- .../lecture/entity/LectureRegist.java | 27 ++++++++++ .../lecture/repository/LectureRepository.java | 2 +- .../lecture/service/LectureService.java | 12 ++--- .../lecture/service/LectureServiceImpl.java | 44 ++++++++++----- .../quiz/controller/QuizController.java | 4 ++ .../edufocus/edufocus/quiz/entity/Quiz.java | 54 +++++++++++++++++++ .../edufocus/quiz/entity/QuizSet.java | 40 ++++++++++++++ .../quiz/repository/QuizRepository.java | 4 ++ .../quiz/repository/QuizSetRepository.java | 4 ++ .../edufocus/quiz/service/QuizService.java | 4 ++ .../quiz/service/QuizServiceImpl.java | 4 ++ .../edufocus/quiz/service/QuizSetService.java | 4 ++ .../quiz/service/QuizSetServiceImpl.java | 4 ++ .../edufocus/user/model/entity/User.java | 3 +- 16 files changed, 206 insertions(+), 33 deletions(-) create mode 100644 backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureRegist.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/quiz/entity/Quiz.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSet.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/quiz/repository/QuizRepository.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/quiz/repository/QuizSetRepository.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizService.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizServiceImpl.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetService.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java b/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java index ca8e1ff..8cc015c 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java @@ -1,6 +1,7 @@ package com.edufocus.edufocus.lecture.controller; import com.edufocus.edufocus.lecture.entity.Lecture; +import com.edufocus.edufocus.lecture.entity.LectureRegist; import com.edufocus.edufocus.lecture.service.LectureService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -19,26 +20,28 @@ public class LectureController { private final LectureService lectureService; @PostMapping - public ResponseEntity createLecture (@RequestBody Lecture lecture) { - lectureService.createLecture(lecture); + public ResponseEntity createLecture (@RequestBody long userId, @RequestBody LectureRegist lectureRegist) { + lectureService.createLecture(userId, lectureRegist); return new ResponseEntity<>(HttpStatus.CREATED); } @DeleteMapping("/{lectureId}") - public ResponseEntity deleteLecture (@PathVariable long lectureId) { - lectureService.deleteLecture(lectureId); + public ResponseEntity deleteLecture (@RequestBody long userId, @PathVariable long lectureId) { + if (!lectureService.deleteLecture(userId, lectureId)) { + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + } + return new ResponseEntity<>(HttpStatus.NO_CONTENT); } @GetMapping public ResponseEntity findAllLecture () { List lectures = lectureService.findAllLecture(); - return new ResponseEntity<>(lectures, HttpStatus.OK); - } - @GetMapping("/teacherId/{teacherId}") - public ResponseEntity findByTeacherId (@PathVariable String teacherId) { - List lectures = lectureService.findLectureByTeacherId(teacherId); + if (lectures.isEmpty()) { + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + return new ResponseEntity<>(lectures, HttpStatus.OK); } @@ -53,4 +56,6 @@ public class LectureController { return new ResponseEntity<>(lecture, HttpStatus.OK); } + + } diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java index 5ae3972..6df25fc 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java @@ -1,5 +1,6 @@ package com.edufocus.edufocus.lecture.entity; +import com.edufocus.edufocus.user.model.entity.User; import jakarta.persistence.*; import lombok.Getter; import lombok.Setter; @@ -15,8 +16,9 @@ public class Lecture { @Column private Long id; - @Column(name = "teacher_id") - private String teacherId; + @ManyToOne + @JoinColumn(name = "user_id") + private User user; @Column private String title; diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureRegist.java b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureRegist.java new file mode 100644 index 0000000..24790e3 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureRegist.java @@ -0,0 +1,27 @@ +package com.edufocus.edufocus.lecture.entity; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.Date; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class LectureRegist { + + private String title; + + private String description; + + @Temporal(TemporalType.DATE) + private Date startDate; + + @Temporal(TemporalType.DATE) + private Date endDate; + + private String plan; + +} diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/repository/LectureRepository.java b/backend/src/main/java/com/edufocus/edufocus/lecture/repository/LectureRepository.java index 032085b..6366507 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/repository/LectureRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/repository/LectureRepository.java @@ -2,6 +2,7 @@ package com.edufocus.edufocus.lecture.repository; import com.edufocus.edufocus.lecture.entity.Lecture; 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; @@ -11,5 +12,4 @@ import java.util.List; public interface LectureRepository extends JpaRepository { Lecture findByTitle(@Param("title") String title); - List findByTeacherId(@Param("teacherId") String teacherId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java index 777fd58..2731e5a 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java @@ -1,8 +1,7 @@ package com.edufocus.edufocus.lecture.service; import com.edufocus.edufocus.lecture.entity.Lecture; -import jakarta.transaction.Transactional; -import lombok.RequiredArgsConstructor; +import com.edufocus.edufocus.lecture.entity.LectureRegist; import org.springframework.stereotype.Service; import java.util.List; @@ -11,13 +10,12 @@ import java.util.List; @Service public interface LectureService { - void createLecture(Lecture lecture); + void createLecture(long userId, LectureRegist lectureRegist); - void deleteLecture(long lectureId); + boolean deleteLecture(long userId, long LectureId); + + List findAllLecture(); Lecture findLectureByTitle(String title); - List findLectureByTeacherId(String teacherId); - - List findAllLecture(); } diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java index 0431045..4f120d8 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java @@ -1,31 +1,57 @@ package com.edufocus.edufocus.lecture.service; import com.edufocus.edufocus.lecture.entity.Lecture; +import com.edufocus.edufocus.lecture.entity.LectureRegist; import com.edufocus.edufocus.lecture.repository.LectureRepository; +import com.edufocus.edufocus.user.model.entity.User; +import com.edufocus.edufocus.user.model.repository.UserRepository; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; -import java.util.Optional; @Service @Transactional @RequiredArgsConstructor public class LectureServiceImpl implements LectureService { - @Autowired private final LectureRepository lectureRepository; + private final UserRepository userRepository; + @Override - public void createLecture(Lecture lecture) { + public void createLecture(long userId, LectureRegist lectureRegist) { + + User user = userRepository.findById(userId).get(); + + Lecture lecture = new Lecture(); + lecture.setUser(user); + + lecture.setTitle(lectureRegist.getTitle()); + lecture.setDescription(lectureRegist.getDescription()); + lecture.setStartDate(lectureRegist.getStartDate()); + lecture.setEndDate(lectureRegist.getEndDate()); + lecture.setPlan(lectureRegist.getPlan()); + lectureRepository.save(lecture); } @Override - public void deleteLecture(long lectureId) { + public boolean deleteLecture(long userId, long lectureId) { + Lecture lecture = lectureRepository.findById(lectureId).get(); + + if (lecture.getUser().getId() != userId) { + return false; + } + lectureRepository.deleteById(lectureId); + return true; + } + + @Override + public List findAllLecture() { + return lectureRepository.findAll(); } @Override @@ -33,13 +59,5 @@ public class LectureServiceImpl implements LectureService { return lectureRepository.findByTitle(title); } - @Override - public List findLectureByTeacherId(String teacherId) { - return lectureRepository.findByTeacherId(teacherId); - } - @Override - public List findAllLecture() { - return lectureRepository.findAll(); - } } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java b/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java new file mode 100644 index 0000000..b77b3d4 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java @@ -0,0 +1,4 @@ +package com.edufocus.edufocus.quiz.controller; + +public class QuizController { +} diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Quiz.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Quiz.java new file mode 100644 index 0000000..b997e38 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Quiz.java @@ -0,0 +1,54 @@ +package com.edufocus.edufocus.quiz.entity; + +import jakarta.persistence.*; +import lombok.Getter; +import lombok.Setter; + +@Entity +@Getter +@Setter +public class Quiz { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private int id; + + @ManyToOne + @JoinColumn(name = "quizset_id") + private QuizSet quizSet; + + @Column + private String title; + + @Column + private String description; + + @Column + private String answer; + + @Column (name = "is_single") + private boolean isSingle; + + @Column + private String image; + + @Column + private String choice1; + + @Column + private String choice2; + + @Column + private String choice3; + + @Column + private String choice4; + + public void setQuizSet(QuizSet quizSet) { + this.quizSet = quizSet; + + if (!quizSet.getQuizzes().contains(this)) { + quizSet.getQuizzes().remove(this); + } + } +} diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSet.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSet.java new file mode 100644 index 0000000..7198a4c --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSet.java @@ -0,0 +1,40 @@ +package com.edufocus.edufocus.quiz.entity; + +import com.edufocus.edufocus.user.model.entity.User; +import jakarta.persistence.*; +import lombok.Getter; +import lombok.Setter; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Getter +@Setter +public class QuizSet { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private int id; + + @ManyToOne + @JoinColumn(name = "user_id") + private User user; + + @Column + private String title; + + @Column + private String image; + + @OneToMany(mappedBy = "quizSet") + private List quizzes = new ArrayList(); + + public void addQuiz(Quiz quiz) { + this.quizzes.add(quiz); + + if (quiz.getQuizSet() != this) { + quiz.setQuizSet(this); + } + } +} diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/repository/QuizRepository.java b/backend/src/main/java/com/edufocus/edufocus/quiz/repository/QuizRepository.java new file mode 100644 index 0000000..ba2085b --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/repository/QuizRepository.java @@ -0,0 +1,4 @@ +package com.edufocus.edufocus.quiz.repository; + +public interface QuizRepository { +} diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/repository/QuizSetRepository.java b/backend/src/main/java/com/edufocus/edufocus/quiz/repository/QuizSetRepository.java new file mode 100644 index 0000000..820dff9 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/repository/QuizSetRepository.java @@ -0,0 +1,4 @@ +package com.edufocus.edufocus.quiz.repository; + +public interface QuizSetRepository { +} diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizService.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizService.java new file mode 100644 index 0000000..3b84367 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizService.java @@ -0,0 +1,4 @@ +package com.edufocus.edufocus.quiz.service; + +public interface QuizService { +} diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizServiceImpl.java new file mode 100644 index 0000000..0a06913 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizServiceImpl.java @@ -0,0 +1,4 @@ +package com.edufocus.edufocus.quiz.service; + +public class QuizServiceImpl { +} diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetService.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetService.java new file mode 100644 index 0000000..bbf8570 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetService.java @@ -0,0 +1,4 @@ +package com.edufocus.edufocus.quiz.service; + +public interface QuizSetService { +} diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java new file mode 100644 index 0000000..d27c69b --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java @@ -0,0 +1,4 @@ +package com.edufocus.edufocus.quiz.service; + +public class QuizSetServiceImpl { +} diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/User.java b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/User.java index 8914cd3..78b62ea 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/User.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/User.java @@ -17,7 +17,8 @@ public class User { @GeneratedValue(strategy = GenerationType.IDENTITY) // 자동 증가 설정 private Long id; - private String user_id; + @Column(name = "user_id", unique = true, nullable = false) + private String userId; private String email; private String password; @Enumerated(EnumType.STRING) // 혹은 EnumType.ORDINAL From aceca6f458e7fdc6c42f93c8556e465429bae7d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Thu, 18 Jul 2024 13:10:49 +0900 Subject: [PATCH 008/197] feat: login --- backend/build.gradle | 6 +- .../lecture/controller/LectureController.java | 3 +- .../lecture/entity/LectureRegist.java | 2 + .../com/edufocus/edufocus/qna/entity/Qna.java | 4 - .../user/config/WebConfiguration.java | 41 +++++++++ .../user/controller/UserController.java | 50 ++++++++++- .../user/intercepter/JWTInterceptor.java | 40 +++++++++ .../edufocus/user/model/entity/User.java | 2 + .../exception/UnAuthorizedException.java | 11 +++ .../user/model/repository/UserRepository.java | 20 +++++ .../user/model/service/UserService.java | 4 + .../user/model/service/UserServiceImpl.java | 39 ++++++++- .../edufocus/edufocus/user/util/JWTUtil.java | 84 +++++++++++++++++++ .../src/main/resources/application.properties | 8 ++ 14 files changed, 302 insertions(+), 12 deletions(-) create mode 100644 backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/user/intercepter/JWTInterceptor.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/user/model/exception/UnAuthorizedException.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/user/util/JWTUtil.java diff --git a/backend/build.gradle b/backend/build.gradle index 68902bf..b21a1da 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -25,8 +25,12 @@ dependencies { implementation group: 'io.livekit', name: 'livekit-server', version: '0.6.1' implementation 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' - implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0' + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.4.0' + runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-jackson', version: '0.11.5' + runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-impl', version: '0.11.5' + implementation group: 'io.jsonwebtoken', name: 'jjwt-api', version: '0.11.5' + implementation group: 'org.glassfish.jaxb', name: 'jaxb-runtime', version: '4.0.5' } diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java b/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java index 8cc015c..bd013a4 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java @@ -20,7 +20,8 @@ public class LectureController { private final LectureService lectureService; @PostMapping - public ResponseEntity createLecture (@RequestBody long userId, @RequestBody LectureRegist lectureRegist) { + public ResponseEntity createLecture (@RequestBody long userId, LectureRegist lectureRegist) { + System.out.println("@@@@@@@@@@@@@@@@@@>>>>>>>>>>>>>>>>>>>>>> "+userId); lectureService.createLecture(userId, lectureRegist); return new ResponseEntity<>(HttpStatus.CREATED); } diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureRegist.java b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureRegist.java index 24790e3..4486854 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureRegist.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureRegist.java @@ -12,6 +12,8 @@ import java.util.Date; @AllArgsConstructor public class LectureRegist { + private Long userId; + private String title; private String description; diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java b/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java index ddbc743..4451568 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java @@ -22,10 +22,6 @@ public class Qna { @Column(name= "qna_id") private Long id; - // user_id - // lecture_id - - @Column private String title; diff --git a/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java b/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java new file mode 100644 index 0000000..362e689 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java @@ -0,0 +1,41 @@ +package com.edufocus.edufocus.user.config; + +import com.edufocus.edufocus.user.intercepter.JWTInterceptor; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + + +@Configuration +@EnableWebMvc +public class WebConfiguration implements WebMvcConfigurer { + + private JWTInterceptor jwtInterceptor; + + public WebConfiguration(JWTInterceptor jwtInterceptor) { + super(); + this.jwtInterceptor = jwtInterceptor; + } + + @Override + public void addCorsMappings(CorsRegistry registry) { + registry + .addMapping("/**") + .allowedOrigins("*") + .allowedMethods(HttpMethod.GET.name(), HttpMethod.POST.name(), HttpMethod.PUT.name(), + HttpMethod.DELETE.name(), HttpMethod.HEAD.name(), HttpMethod.OPTIONS.name(), + HttpMethod.PATCH.name()) + .maxAge(1800); // Pre-flight Caching + } + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("/img/**").addResourceLocations("classpath:/static/assets/img/"); + registry.addResourceHandler("/*.html**").addResourceLocations("classpath:/static/"); + } + +} \ No newline at end of file diff --git a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java index ee15c64..e96b6f4 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java @@ -2,15 +2,22 @@ package com.edufocus.edufocus.user.controller; import com.edufocus.edufocus.user.model.entity.User; import com.edufocus.edufocus.user.model.service.UserService; +import com.edufocus.edufocus.user.util.JWTUtil; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; 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; +import java.util.HashMap; +import java.util.Map; + @RestController @RequestMapping("/user") @Slf4j @@ -18,6 +25,7 @@ import org.springframework.web.bind.annotation.RestController; public class UserController { private final UserService userService; + private final JWTUtil jwtUtil; @PostMapping("/join") public ResponseEntity join(@RequestBody User user) throws Exception { @@ -27,15 +35,49 @@ public class UserController { return ResponseEntity.ok("User registered successfully"); } +// +// @PostMapping("/login") +// public ResponseEntity login(@RequestBody User user) { +// try { +// User loggedInUser = userService.login(user); +// return ResponseEntity.ok(loggedInUser); +// +// } catch (Exception e) { +// throw new RuntimeException(e); +// } + // } + @Operation(summary = "로그인", description = "아이디와 비밀번호를 이용하여 로그인 처리.") @PostMapping("/login") - public ResponseEntity login(@RequestBody User user) { + public ResponseEntity> login( + @RequestBody @Parameter(description = "로그인 시 필요한 회원정보(아이디, 비밀번호).", required = true) User user) { + Map resultMap = new HashMap<>(); + HttpStatus status = HttpStatus.ACCEPTED; try { - User loggedInUser = userService.login(user); - return ResponseEntity.ok(loggedInUser); + User loginUser = userService.login(user); + if (loginUser != null) { + String accessToken = jwtUtil.createAccessToken(String.valueOf(loginUser.getId())); + String refreshToken = jwtUtil.createRefreshToken(String.valueOf(loginUser.getId())); + // 발급받은 refresh token 을 DB에 저장. + userService.saveRefreshToken(loginUser.getId(), refreshToken); + + // JSON 으로 token 전달. + resultMap.put("access-token", accessToken); + resultMap.put("refresh-token", refreshToken); + + status = HttpStatus.CREATED; + } else { + resultMap.put("message", "아이디 또는 패스워드를 확인해 주세요."); + status = HttpStatus.UNAUTHORIZED; + } } catch (Exception e) { - throw new RuntimeException(e); + resultMap.put("message", e.getMessage()); + status = HttpStatus.INTERNAL_SERVER_ERROR; } + return new ResponseEntity<>(resultMap, status); } + + + } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/intercepter/JWTInterceptor.java b/backend/src/main/java/com/edufocus/edufocus/user/intercepter/JWTInterceptor.java new file mode 100644 index 0000000..fc741dc --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/user/intercepter/JWTInterceptor.java @@ -0,0 +1,40 @@ +package com.edufocus.edufocus.user.intercepter; + +import com.edufocus.edufocus.user.model.exception.UnAuthorizedException; +import com.edufocus.edufocus.user.util.JWTUtil; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; + + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; + +@Component +@Slf4j +public class JWTInterceptor implements HandlerInterceptor { + + private final String HEADER_AUTH = "Authorization"; + + private JWTUtil jwtUtil; + + public JWTInterceptor(JWTUtil jwtUtil) { + super(); + this.jwtUtil = jwtUtil; + } + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) + throws Exception { + final String token = request.getHeader(HEADER_AUTH); + + if (token != null && jwtUtil.checkToken(token)) { + log.info("토큰 사용 가능 : {}", token); + return true; + } else { + log.info("토큰 사용 불가능 : {}", token); + throw new UnAuthorizedException(); + } + + } +} \ No newline at end of file diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/User.java b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/User.java index 3eed888..69a8b96 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/User.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/User.java @@ -31,6 +31,8 @@ public class User { @Enumerated(EnumType.STRING) // 혹은 EnumType.ORDINAL private UserRole role; + private String refreshToken; + diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/exception/UnAuthorizedException.java b/backend/src/main/java/com/edufocus/edufocus/user/model/exception/UnAuthorizedException.java new file mode 100644 index 0000000..88bc30e --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/exception/UnAuthorizedException.java @@ -0,0 +1,11 @@ +package com.edufocus.edufocus.user.model.exception; + +public class UnAuthorizedException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public UnAuthorizedException() { + super("계정 권한이 유효하지 않습니다.\n다시 로그인을 하세요."); + } + +} \ No newline at end of file diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/repository/UserRepository.java b/backend/src/main/java/com/edufocus/edufocus/user/model/repository/UserRepository.java index d05e98e..53e6289 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/repository/UserRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/repository/UserRepository.java @@ -1,8 +1,28 @@ package com.edufocus.edufocus.user.model.repository; import com.edufocus.edufocus.user.model.entity.User; +import jakarta.transaction.Transactional; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.Optional; public interface UserRepository extends JpaRepository { + @Modifying + @Transactional + @Query("UPDATE User u SET u.refreshToken = :refreshToken WHERE u.id = :id") + void saveRefreshToken(@Param("id") Long id, @Param("refreshToken") String refreshToken); + + @Query("SELECT u.refreshToken FROM User u WHERE u.id = :id") + String getRefreshToken(@Param("id") Long id); + + @Modifying + @Transactional + @Query("UPDATE User u SET u.refreshToken = NULL WHERE u.id = :id") + void deleteRefreshToken(@Param("id") Long id); + + Optional findByUserId(String userId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java index ba32a4f..cf6353d 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java @@ -5,4 +5,8 @@ import com.edufocus.edufocus.user.model.entity.User; public interface UserService { void join(User user) throws Exception; User login(User user) throws Exception; + public void saveRefreshToken(Long id, String refreshToken) throws Exception; + public String getRefreshToken(Long id) throws Exception; + public void deleteRefreshToken(Long id) throws Exception; + } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java index e2719bf..50bb07e 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java @@ -10,6 +10,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; import java.util.Optional; @Service @@ -28,16 +30,49 @@ public class UserServiceImpl implements UserService{ public User login(User user) throws SQLException { - Optional findUser = userRepository.findById(user.getId()); + Optional findUser = userRepository.findByUserId(user.getUserId()); + if(findUser.isEmpty()) { throw new UserException("없는 유저"); } - return findUser.get(); + + + if(findUser.isPresent()) + { + + User find = findUser.get(); + if(find.getPassword().equals(user.getPassword())) + { + return find; + } + else{ + throw new UserException("비밀번호 틀림"); + + } + } + else{ + throw new UserException("없는 유저"); + + + } + + } + @Override + public void saveRefreshToken(Long id, String refreshToken) throws Exception { + userRepository.saveRefreshToken(id, refreshToken); } + @Override + public String getRefreshToken(Long id) throws Exception { + return userRepository.getRefreshToken(id); + } + @Override + public void deleteRefreshToken(Long id) throws Exception { + userRepository.deleteRefreshToken(id); + } } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/util/JWTUtil.java b/backend/src/main/java/com/edufocus/edufocus/user/util/JWTUtil.java new file mode 100644 index 0000000..1d0f98d --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/user/util/JWTUtil.java @@ -0,0 +1,84 @@ +package com.edufocus.edufocus.user.util; + +import java.nio.charset.StandardCharsets; +import java.util.Date; +import java.util.Map; + +import com.edufocus.edufocus.user.model.exception.UnAuthorizedException; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jws; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import lombok.extern.slf4j.Slf4j; + +@Component +@Slf4j +public class JWTUtil { + + @Value("${jwt.salt}") + private String salt; + + @Value("${jwt.access-token.expiretime}") + private long accessTokenExpireTime; + + @Value("${jwt.refresh-token.expiretime}") + private long refreshTokenExpireTime; + + public String createAccessToken(String id) { + return create(id, "access-token", accessTokenExpireTime); + } + + public String createRefreshToken(String id) { + return create(id, "refresh-token", refreshTokenExpireTime); + } + + private String create(String id, String subject, long expireTime) { + Claims claims = Jwts.claims() + .setSubject(subject) + .setIssuedAt(new Date()) + .setExpiration(new Date(System.currentTimeMillis() + expireTime)); + claims.put("id", id); + + return Jwts.builder() + .setHeaderParam("typ", "JWT") + .setClaims(claims) + .signWith(SignatureAlgorithm.HS256, generateKey()) + .compact(); + } + + private byte[] generateKey() { + return salt.getBytes(StandardCharsets.UTF_8); + } + + public boolean checkToken(String token) { + try { + Jws claims = Jwts.parserBuilder() + .setSigningKey(generateKey()) + .build() + .parseClaimsJws(token); + log.debug("claims: {}", claims); + return true; + } catch (Exception e) { + log.error("Token validation error: {}", e.getMessage()); + return false; + } + } + + public String getUserId(String authorization) { + try { + Jws claims = Jwts.parserBuilder() + .setSigningKey(generateKey()) + .build() + .parseClaimsJws(authorization); + Map value = claims.getBody(); + log.info("value : {}", value); + return (String) value.get("id"); + } catch (Exception e) { + log.error("Failed to get user ID from token: {}", e.getMessage()); + throw new UnAuthorizedException(); + } + } +} diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index b1eeab4..f06afe6 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -6,7 +6,15 @@ server.ssl.enabled=false # LiveKit configuration livekit.api.key=${LIVEKIT_API_KEY:devkey} livekit.api.secret=${LIVEKIT_API_SECRET:secret} +# JWT Salt (??? ?? ???? ???) +jwt.salt=ssafy-screte-key-20240404-ssafy-screte-key-20240404-ssafy-screte-key-20240404 + +# Access Token ?? ?? (??? ??) +jwt.access-token.expiretime=3600000 + +# Refresh Token ?? ?? (??? ??) +jwt.refresh-token.expiretime=86400000 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/edufocus?useSSL=false spring.datasource.username=root From f127eae148742bbcde88ba9ea7dc2183ba31bac2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Thu, 18 Jul 2024 14:27:11 +0900 Subject: [PATCH 009/197] feat: login --- .../user/controller/UserController.java | 110 +++++++++++++++++- .../user/model/service/UserService.java | 8 +- .../user/model/service/UserServiceImpl.java | 14 +++ .../edufocus/edufocus/user/util/JWTUtil.java | 11 +- 4 files changed, 130 insertions(+), 13 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java index e96b6f4..9689880 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java @@ -5,15 +5,13 @@ import com.edufocus.edufocus.user.model.service.UserService; import com.edufocus.edufocus.user.util.JWTUtil; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -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; +import org.springframework.web.bind.annotation.*; import java.util.HashMap; import java.util.Map; @@ -63,6 +61,7 @@ public class UserController { userService.saveRefreshToken(loginUser.getId(), refreshToken); // JSON 으로 token 전달. + System.out.println(accessToken); resultMap.put("access-token", accessToken); resultMap.put("refresh-token", refreshToken); @@ -78,6 +77,109 @@ public class UserController { return new ResponseEntity<>(resultMap, status); } + @Operation(summary = "회원인증", description = "회원 정보를 담은 Token 을 반환한다.") + @GetMapping("/info/{userId}") + public ResponseEntity> getInfo( + @PathVariable("userId") @Parameter(description = "인증할 회원의 아이디.", required = true) Long userId, + HttpServletRequest request) { + //logger.debug("userId : {} ", userId); + String id = String.valueOf(userId); + + System.out.println("!>>>>>>>>>>>>>>>>>>>>>>>>"); + System.out.println(id); + System.out.println(id.getClass().getName()); + Map resultMap = new HashMap<>(); + HttpStatus status = HttpStatus.ACCEPTED; + if (jwtUtil.checkToken(request.getHeader("Authorization"))) { + log.info("사용 가능한 토큰!!!"); + try { +// 로그인 사용자 정보. + User member = userService.userInfo(userId); + resultMap.put("userInfo", member); + status = HttpStatus.OK; + } catch (Exception e) { + log.error("정보조회 실패 : {}", e); + resultMap.put("message", e.getMessage()); + status = HttpStatus.INTERNAL_SERVER_ERROR; + } + } else { + System.out.println(jwtUtil.checkToken(request.getHeader("Authorization"))); + log.error("사용 불가능 토큰!!!"); + resultMap.put("message", "Unauthorized token"); + status = HttpStatus.UNAUTHORIZED; + } + return new ResponseEntity>(resultMap, status); + } + + @GetMapping("/logout/{userId}") + + public ResponseEntity removeToken(@PathVariable ("userId") @Parameter(description = "로그아웃 할 회원의 아이디.", required = true) Long userId) { + Map resultMap = new HashMap<>(); + HttpStatus status = HttpStatus.ACCEPTED; + try { + userService.deleteRefreshToken(userId); + status = HttpStatus.OK; + } catch (Exception e) { + log.error("로그아웃 실패 : {}", e); + resultMap.put("message", e.getMessage()); + status = HttpStatus.INTERNAL_SERVER_ERROR; + } + return new ResponseEntity>(resultMap, status); + } + + @Operation(summary = "Access Token 재발급", description = "만료된 access token 을 재발급 받는다.") + @PostMapping("/refresh") + public ResponseEntity refreshToken(@RequestBody User user, HttpServletRequest request) + throws Exception { + Map resultMap = new HashMap<>(); + HttpStatus status = HttpStatus.ACCEPTED; + String token = request.getHeader("refreshToken"); + log.debug("token : {}, memberDto : {}", token, user); + if (jwtUtil.checkToken(token)) { + if (token.equals(userService.getRefreshToken(user.getId()))) { + String accessToken = jwtUtil.createAccessToken(String.valueOf(user.getId())); + log.debug("token : {}", accessToken); + log.debug("정상적으로 access token 재발급!!!"); + resultMap.put("access-token", accessToken); + status = HttpStatus.CREATED; + } + } else { + log.debug("refresh token 도 사용 불가!!!!!!!"); + status = HttpStatus.UNAUTHORIZED; + } + return new ResponseEntity>(resultMap, status); + } + + @Operation(summary = "회원 정보 조회", description = "토큰을 이용하여 회원 정보를 조회한다.") + @GetMapping("/member") + public ResponseEntity> getMember(HttpServletRequest request) { + Map resultMap = new HashMap<>(); + HttpStatus status = HttpStatus.ACCEPTED; + String token = request.getHeader("Authorization"); + + if (jwtUtil.checkToken(token)) { + String userId = jwtUtil.getUserId(token); + log.info("사용 가능한 토큰!!! userId: {}", userId); + try { + User user = userService.userInfo(Long.parseLong(userId)); + resultMap.put("userInfo", user); + status = HttpStatus.OK; + + } catch (Exception e) { + log.error("정보조회 실패 : {}", e); + resultMap.put("message", e.getMessage()); + status = HttpStatus.INTERNAL_SERVER_ERROR; + } + } else { + log.error("사용 불가능 토큰!!!"); + status = HttpStatus.UNAUTHORIZED; + } + return new ResponseEntity>(resultMap, status); + } + + + + } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java index cf6353d..3ba4454 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java @@ -5,8 +5,8 @@ import com.edufocus.edufocus.user.model.entity.User; public interface UserService { void join(User user) throws Exception; User login(User user) throws Exception; - public void saveRefreshToken(Long id, String refreshToken) throws Exception; - public String getRefreshToken(Long id) throws Exception; - public void deleteRefreshToken(Long id) throws Exception; - + void saveRefreshToken(Long id, String refreshToken) throws Exception; + String getRefreshToken(Long id) throws Exception; + void deleteRefreshToken(Long id) throws Exception; + User userInfo(Long id) throws Exception; } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java index 50bb07e..0f70838 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java @@ -28,6 +28,7 @@ public class UserServiceImpl implements UserService{ userRepository.save(user); } + public User login(User user) throws SQLException { Optional findUser = userRepository.findByUserId(user.getUserId()); @@ -59,6 +60,19 @@ public class UserServiceImpl implements UserService{ } + } + + @Override + public User userInfo(Long id) + { + try{ + return userRepository.findById(id).get(); + } + catch (Exception e) + { + throw new UserException(e.getMessage()); + } + } @Override public void saveRefreshToken(Long id, String refreshToken) throws Exception { diff --git a/backend/src/main/java/com/edufocus/edufocus/user/util/JWTUtil.java b/backend/src/main/java/com/edufocus/edufocus/user/util/JWTUtil.java index 1d0f98d..ead01db 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/util/JWTUtil.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/util/JWTUtil.java @@ -5,13 +5,10 @@ import java.util.Date; import java.util.Map; import com.edufocus.edufocus.user.model.exception.UnAuthorizedException; +import io.jsonwebtoken.*; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.Jws; -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.SignatureAlgorithm; import lombok.extern.slf4j.Slf4j; @Component @@ -61,9 +58,13 @@ public class JWTUtil { .parseClaimsJws(token); log.debug("claims: {}", claims); return true; - } catch (Exception e) { + } catch (MalformedJwtException | UnsupportedJwtException | IllegalArgumentException | SignatureException | ExpiredJwtException e) { log.error("Token validation error: {}", e.getMessage()); return false; + } catch (Exception e) { + System.out.println(token); + log.error("Unexpected error while validating token: {}", e.getMessage()); + return false; } } From a02ee65a7eb0b940b983242abdd630085fd07673 Mon Sep 17 00:00:00 2001 From: yulmam Date: Thu, 18 Jul 2024 14:39:43 +0900 Subject: [PATCH 010/197] =?UTF-8?q?feat=20:=20=EA=B2=8C=EC=8B=9C=ED=8C=90?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../board/controller/BoardController.java | 78 +++++------ .../entity/dto/RequestBoardDetailDto.java | 2 - .../board/entity/dto/RequestBoardDto.java | 14 ++ .../entity/dto/RequestBoardUpdateDto.java | 12 ++ .../board/entity/dto/RequestCommentDto.java | 4 +- .../entity/dto/ResponseBoardDetailDto.java | 21 ++- .../board/entity/dto/ResponseBoardDto.java | 7 +- .../edufocus/board/entity/vo/Board.java | 52 +++++++- .../edufocus/board/entity/vo/Comment.java | 40 +++++- .../board/repository/BoardRepository.java | 13 ++ .../board/repository/CommentRepository.java | 11 ++ .../edufocus/board/service/BoardService.java | 23 +++- .../board/service/BoardServiceImpl.java | 122 +++++++++++++++++- 13 files changed, 347 insertions(+), 52 deletions(-) delete mode 100644 backend/src/main/java/com/edufocus/edufocus/board/entity/dto/RequestBoardDetailDto.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/board/entity/dto/RequestBoardDto.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/board/entity/dto/RequestBoardUpdateDto.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/board/repository/BoardRepository.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/board/repository/CommentRepository.java diff --git a/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java b/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java index 848335b..a8a4db6 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java @@ -1,13 +1,13 @@ package com.edufocus.edufocus.board.controller; -import com.edufocus.edufocus.board.entity.dto.RequestBoardDetailDto; +import com.edufocus.edufocus.board.entity.dto.RequestBoardDto; +import com.edufocus.edufocus.board.entity.dto.RequestBoardUpdateDto; import com.edufocus.edufocus.board.entity.dto.RequestCommentDto; -import com.edufocus.edufocus.board.entity.dto.ResponseBoardDetailDto; -import com.edufocus.edufocus.board.entity.dto.ResponseBoardDto; +import com.edufocus.edufocus.board.entity.vo.Board; import com.edufocus.edufocus.board.entity.vo.Comment; import com.edufocus.edufocus.board.service.BoardService; +import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.constraints.Positive; -import org.springframework.data.domain.Pageable; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -29,15 +29,11 @@ public class BoardController { @GetMapping() public ResponseEntity searchBoards( - Pageable pageable, - @RequestParam(value = "userId", required = true) int userId + @RequestParam(value = "category", required = false, defaultValue = "announcement") String category, + @RequestParam(value = "lectureId", required = true) long lectureId, + @RequestParam(value = "pageNo", required = false, defaultValue = "0") int pageNo ){ - - if(boardService.checkRegistration(userId, lectureId)){ - throw new RuntimeException(); - } - - List boards = boardService.findBoards(userId, category, lectureId); + List boards = boardService.findBoards(pageNo, category, lectureId); if(boards.isEmpty()){ return ResponseEntity.noContent().build(); @@ -48,39 +44,35 @@ public class BoardController { @GetMapping(value = "/{boardId}") public ResponseEntity getBoardDetail( - @PathVariable @Positive int boardId, - @RequestParam(value = "userId", required = true) @Positive int userId + @PathVariable @Positive int boardId ){ - ResponseBoardDetailDto responseBoardDetail = boardService.findBoardDetail(userId, boardId); + Board responseBoardDetail = boardService.findBoardDetail(boardId); return ResponseEntity.ok(responseBoardDetail); } @PostMapping public ResponseEntity addBoard( - @RequestBody RequestBoardDetailDto requestBoardDetailDto, - @RequestParam(value = "userId", required = true) @Positive int userId + @RequestBody RequestBoardDto requestBoardDto, + HttpServletRequest request ){ - if(boardService.checkRegistration(userId, requestBoardDetailDto.getLectureId())){ - throw new RuntimeException(); - } - boardService.createBoard(userId, requestBoardDetailDto); + long userId = Long.parseLong(request.getHeader("Authentication")); + + boardService.createBoard(userId, requestBoardDto); return new ResponseEntity<>(HttpStatus.OK); } @PutMapping(value = "/{boardId}") public ResponseEntity updateBoard( - @PathVariable @Positive int boardId, - @RequestBody RequestBoardDetailDto requestBoardDetailDto, - @RequestParam(value = "userId", required = true) @Positive int userId + @PathVariable @Positive long boardId, + @RequestBody RequestBoardUpdateDto requestBoardUpdateDto, + HttpServletRequest request ){ - if(boardService.checkRegistration(userId, requestBoardDetailDto.getLectureId())){ - throw new RuntimeException(); - } + long userId = Long.parseLong(request.getHeader("Authentication")); - boardService.createBoard(userId, requestBoardDetailDto); + boardService.updateBoard(boardId, requestBoardUpdateDto); return new ResponseEntity<>(HttpStatus.OK); } @@ -88,12 +80,8 @@ public class BoardController { @DeleteMapping(value = "/{boardId}") public ResponseEntity deleteBoard( @PathVariable int boardId, - @RequestParam @Positive int userId + HttpServletRequest request ){ - if(boardService.checkBoardOwner(userId, boardId)){ - throw new RuntimeException(); - } - boardService.deleteBoard(boardId); return new ResponseEntity<>(HttpStatus.OK); @@ -102,8 +90,10 @@ public class BoardController { @GetMapping(value = "/comment/{boardId}") public ResponseEntity getComments( @PathVariable @Positive int boardId, - @RequestParam @Positive int userId + HttpServletRequest request ){ + long userId = Long.parseLong(request.getHeader("Authentication")); + List comments = boardService.findComments(userId, boardId); return ResponseEntity.ok(comments); @@ -112,23 +102,25 @@ public class BoardController { @PostMapping(value = "/comment/{boardId}") public ResponseEntity addComment( @PathVariable @Positive int boardId, - @RequestParam int userId, - @RequestBody RequestCommentDto requestCommentDto + @RequestParam String content, + HttpServletRequest request ){ - boardService.createComment(userId, boardId, requestCommentDto); + long userId = Long.parseLong(request.getHeader("Authentication")); + + boardService.createComment(userId, boardId, content); return new ResponseEntity<>(HttpStatus.OK); } @PutMapping(value = "/comment/{commentId}") public ResponseEntity updateComment( - @RequestParam int userId, @PathVariable @Positive int commentId, - @RequestBody RequestCommentDto requestCommentDto + @RequestParam String content, + HttpServletRequest request ){ - boardService.checkCommentOwner(userId, commentId); + long userId = Long.parseLong(request.getHeader("Authentication")); - boardService.updateComment(commentId, requestCommentDto); + boardService.updateComment(commentId, content); return new ResponseEntity<>(HttpStatus.OK); } @@ -136,9 +128,9 @@ public class BoardController { @DeleteMapping(value = "/comment/{commentId}") public ResponseEntity deleteComment( @PathVariable @Positive int commentId, - @RequestParam int userId + HttpServletRequest request ){ - boardService.checkCommentOwner(userId, commentId); + long userId = Long.parseLong(request.getHeader("Authentication")); boardService.deleteComment(commentId); diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/RequestBoardDetailDto.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/RequestBoardDetailDto.java deleted file mode 100644 index a88c1e0..0000000 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/RequestBoardDetailDto.java +++ /dev/null @@ -1,2 +0,0 @@ -package com.edufocus.edufocus.board.entity.dto;public class RequestBoartDetailDto { -} diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/RequestBoardDto.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/RequestBoardDto.java new file mode 100644 index 0000000..ca59a75 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/RequestBoardDto.java @@ -0,0 +1,14 @@ +package com.edufocus.edufocus.board.entity.dto; + + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class RequestBoardDto { + private long lectureId; + private String title; + private String category; + private String content; +} diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/RequestBoardUpdateDto.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/RequestBoardUpdateDto.java new file mode 100644 index 0000000..58ff7a7 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/RequestBoardUpdateDto.java @@ -0,0 +1,12 @@ +package com.edufocus.edufocus.board.entity.dto; + + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class RequestBoardUpdateDto { + private String title; + private String content; +} diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/RequestCommentDto.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/RequestCommentDto.java index 9a4ffcf..6578cad 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/RequestCommentDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/RequestCommentDto.java @@ -1,2 +1,4 @@ -package com.edufocus.edufocus.board.entity.dto;public class RequestCommentDto { +package com.edufocus.edufocus.board.entity.dto; + +public class RequestCommentDto { } diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardDetailDto.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardDetailDto.java index 383839a..182a8cc 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardDetailDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardDetailDto.java @@ -1,2 +1,21 @@ -package com.edufocus.edufocus.board.entity.dto;public class ResponseBoardDetailDto { +package com.edufocus.edufocus.board.entity.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +import java.time.LocalTime; + +@Builder +@Getter +@Setter +@AllArgsConstructor +public class ResponseBoardDetailDto { + private int id; + private String name; + private String content; + private int viewCount; + private LocalTime createdAt; + private LocalTime modifiedAt; } diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardDto.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardDto.java index cb700e9..3d34b1a 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardDto.java @@ -1,2 +1,7 @@ -package com.edufocus.edufocus.board.entity.dto;public class ResponseBoardDto { +package com.edufocus.edufocus.board.entity.dto; + +public class ResponseBoardDto { + private int id; + private String name; + private String title; } diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java index aca1d4d..7f8de48 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java @@ -1,2 +1,52 @@ -package com.edufocus.edufocus.board.entity.vo;public class Board { +package com.edufocus.edufocus.board.entity.vo; + + +import com.edufocus.edufocus.lecture.entity.Lecture; +import com.edufocus.edufocus.user.model.entity.User; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.hibernate.annotations.CreationTimestamp; + +import java.time.LocalDate; +import java.util.Date; + +@Entity +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Setter +public class Board { + + @Id + @GeneratedValue + private long id; + + @Column(nullable = false) + private String title; + + @Column(nullable = false) + private String category; + + @Column(nullable = false) + private String content; + + @Column(nullable = true) + private int viewCount; + + @CreationTimestamp + LocalDate createdAt; + + @CreationTimestamp + LocalDate modifiedAt; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "lecture_id") + private Lecture lecture; } diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java index 92d3c3e..c3059c9 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java @@ -1,2 +1,40 @@ -package com.edufocus.edufocus.board.entity.vo;public class Comment { +package com.edufocus.edufocus.board.entity.vo; + + +import com.edufocus.edufocus.user.model.entity.User; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.time.LocalTime; + +@Entity +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Setter +public class Comment { + @Id + @GeneratedValue + private long id; + @Column + private String content; + + @Column + private LocalTime createdAt; + + @Column + private LocalTime updatedAt; + + @ManyToOne + @JoinColumn(name = "user_id") + User user; + + @ManyToOne + @JoinColumn(name = "board_id") + Board board; + + } diff --git a/backend/src/main/java/com/edufocus/edufocus/board/repository/BoardRepository.java b/backend/src/main/java/com/edufocus/edufocus/board/repository/BoardRepository.java new file mode 100644 index 0000000..2cdb7c1 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/board/repository/BoardRepository.java @@ -0,0 +1,13 @@ +package com.edufocus.edufocus.board.repository; + +import com.edufocus.edufocus.board.entity.vo.Board; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface BoardRepository extends JpaRepository { + Page findByLectureIdAndCategory(Long lectureId, String category, Pageable pageable); + +} diff --git a/backend/src/main/java/com/edufocus/edufocus/board/repository/CommentRepository.java b/backend/src/main/java/com/edufocus/edufocus/board/repository/CommentRepository.java new file mode 100644 index 0000000..9002ab8 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/board/repository/CommentRepository.java @@ -0,0 +1,11 @@ +package com.edufocus.edufocus.board.repository; + +import com.edufocus.edufocus.board.entity.vo.Comment; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface CommentRepository extends JpaRepository { + List findByBoardId(long boardId); + +} diff --git a/backend/src/main/java/com/edufocus/edufocus/board/service/BoardService.java b/backend/src/main/java/com/edufocus/edufocus/board/service/BoardService.java index fad3c9d..ac20175 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/service/BoardService.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/service/BoardService.java @@ -1,2 +1,23 @@ -package com.edufocus.edufocus.board.service;public interface BoardService { +package com.edufocus.edufocus.board.service; + +import com.edufocus.edufocus.board.entity.dto.RequestBoardDto; +import com.edufocus.edufocus.board.entity.dto.RequestBoardUpdateDto; +import com.edufocus.edufocus.board.entity.dto.RequestCommentDto; +import com.edufocus.edufocus.board.entity.vo.Board; +import com.edufocus.edufocus.board.entity.vo.Comment; + +import java.util.List; + +public interface BoardService { + + public List findBoards(int pageNo, String category, long lectureId); + public Board findBoardDetail(long boardId); + public void createBoard(long userId, RequestBoardDto requestBoardDto); + public void updateBoard(long boardId, RequestBoardUpdateDto requestBoardUpdateDto); + public void deleteBoard(long boardId); + public List findComments(long userId, long boardId); + public void createComment(long userId, long boardId, String content); + public void updateComment(long commentId, String content); + public void deleteComment(long commentId); + } diff --git a/backend/src/main/java/com/edufocus/edufocus/board/service/BoardServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/board/service/BoardServiceImpl.java index 7292811..308bd57 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/service/BoardServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/service/BoardServiceImpl.java @@ -1,2 +1,122 @@ -package com.edufocus.edufocus.board.service;public class BoardServiceImpl { +package com.edufocus.edufocus.board.service; + + +import com.edufocus.edufocus.board.entity.dto.RequestBoardDto; +import com.edufocus.edufocus.board.entity.dto.RequestBoardUpdateDto; +import com.edufocus.edufocus.board.entity.dto.RequestCommentDto; +import com.edufocus.edufocus.board.entity.vo.Board; +import com.edufocus.edufocus.board.entity.vo.Comment; +import com.edufocus.edufocus.board.repository.BoardRepository; +import com.edufocus.edufocus.board.repository.CommentRepository; +import com.edufocus.edufocus.lecture.entity.Lecture; +import com.edufocus.edufocus.lecture.repository.LectureRepository; +import com.edufocus.edufocus.user.model.entity.User; +import com.edufocus.edufocus.user.model.repository.UserRepository; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class BoardServiceImpl implements BoardService { + + private static final int PAGE_SIZE = 10; + + private final UserRepository userRepository; + private final LectureRepository lectureRepository; + private final BoardRepository boardRepository; + private final CommentRepository commentRepository; + + public BoardServiceImpl(BoardRepository boardRepository, CommentRepository commentRepository, UserRepository userRepository, LectureRepository lectureRepository){ + this.boardRepository = boardRepository; + this.commentRepository = commentRepository; + this.userRepository = userRepository; + this.lectureRepository = lectureRepository; + } + + + @Override + public List findBoards(int pageNo, String category, long lectureId) { + Pageable pageable = PageRequest.of(pageNo, PAGE_SIZE); + Page boards = boardRepository.findByLectureIdAndCategory(lectureId, category, pageable); + return boards.getContent(); + } + + @Override + public Board findBoardDetail(long boardId) { + Board board = boardRepository.findById(boardId).get(); + return board; + } + + @Override + public void createBoard(long userId, RequestBoardDto requestBoardDto) { + User user = userRepository.findById(userId).get(); + Lecture lecture = lectureRepository.findById(requestBoardDto.getLectureId()).get(); + + Board board = Board.builder() + .title(requestBoardDto.getTitle()) + .category(requestBoardDto.getCategory()) + .content(requestBoardDto.getCategory()) + .user(user) + .lecture(lecture) + .build(); + + boardRepository.save(board); + } + + @Override + public void updateBoard(long boardId, RequestBoardUpdateDto requestBoardUpdateDto) { + Board board = boardRepository.findById(boardId).get(); + + board.setTitle(requestBoardUpdateDto.getTitle()); + board.setContent(requestBoardUpdateDto.getContent()); + + boardRepository.save(board); + } + + + @Override + public void deleteBoard(long boardId) { + Board board = boardRepository.findById(boardId).get(); + + boardRepository.delete(board); + } + + @Override + public List findComments(long userId, long boardId) { + return commentRepository.findByBoardId(boardId); + } + + @Override + public void createComment(long userId, long boardId, String content) { + User user = userRepository.findById(userId).get(); + Board board = boardRepository.findById(boardId).get(); + + Comment comment = Comment.builder() + .content(content) + .board(board) + .user(user) + .build(); + + commentRepository.save(comment); + } + + + + @Override + public void updateComment(long commentId, String content) { + Comment comment = commentRepository.findById(commentId).get(); + comment.setContent(content); + commentRepository.save(comment); + } + + @Override + public void deleteComment(long commentId) { + Comment comment = commentRepository.findById(commentId).get(); + commentRepository.delete(comment); + } + + } From b9cd3de0432ab32700b1636058d0d8b5040b9d17 Mon Sep 17 00:00:00 2001 From: kgc9007 Date: Thu, 18 Jul 2024 14:55:54 +0900 Subject: [PATCH 011/197] =?UTF-8?q?feat:=20Quiz=20=ED=80=B4=EC=A6=88?= =?UTF-8?q?=EC=85=8B=20=EB=8B=A8=EC=9C=84=EB=A1=9C=20=ED=80=B4=EC=A6=88=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lecture/controller/LectureController.java | 6 +-- ...eRegist.java => LectureCreateRequest.java} | 2 +- .../lecture/service/LectureService.java | 4 +- .../lecture/service/LectureServiceImpl.java | 14 +++--- .../quiz/controller/QuizController.java | 42 +++++++++++++++++ .../quiz/entity/MutipleQuizCreateRequest.java | 20 ++++++++ .../edufocus/edufocus/quiz/entity/Quiz.java | 2 +- .../quiz/entity/QuizCreateRequest.java | 23 +++++++++ .../edufocus/quiz/entity/QuizSet.java | 2 +- .../quiz/entity/QuizSetCreateRequest.java | 22 +++++++++ .../quiz/entity/SetCreateRequest.java | 18 +++++++ .../quiz/repository/QuizRepository.java | 5 +- .../quiz/repository/QuizSetRepository.java | 6 ++- .../edufocus/quiz/service/QuizService.java | 10 ++++ .../quiz/service/QuizServiceImpl.java | 47 ++++++++++++++++++- .../edufocus/quiz/service/QuizSetService.java | 12 +++++ .../quiz/service/QuizSetServiceImpl.java | 43 ++++++++++++++++- 17 files changed, 259 insertions(+), 19 deletions(-) rename backend/src/main/java/com/edufocus/edufocus/lecture/entity/{LectureRegist.java => LectureCreateRequest.java} (92%) create mode 100644 backend/src/main/java/com/edufocus/edufocus/quiz/entity/MutipleQuizCreateRequest.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizCreateRequest.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSetCreateRequest.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/quiz/entity/SetCreateRequest.java diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java b/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java index 8cc015c..fd8471c 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java @@ -1,7 +1,7 @@ package com.edufocus.edufocus.lecture.controller; import com.edufocus.edufocus.lecture.entity.Lecture; -import com.edufocus.edufocus.lecture.entity.LectureRegist; +import com.edufocus.edufocus.lecture.entity.LectureCreateRequest; import com.edufocus.edufocus.lecture.service.LectureService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -20,8 +20,8 @@ public class LectureController { private final LectureService lectureService; @PostMapping - public ResponseEntity createLecture (@RequestBody long userId, @RequestBody LectureRegist lectureRegist) { - lectureService.createLecture(userId, lectureRegist); + public ResponseEntity createLecture (@RequestBody long userId, @RequestBody LectureCreateRequest lectureCreateRequest) { + lectureService.createLecture(userId, lectureCreateRequest); return new ResponseEntity<>(HttpStatus.CREATED); } diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureRegist.java b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureCreateRequest.java similarity index 92% rename from backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureRegist.java rename to backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureCreateRequest.java index 24790e3..7ce8bfb 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureRegist.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureCreateRequest.java @@ -10,7 +10,7 @@ import java.util.Date; @Getter @NoArgsConstructor @AllArgsConstructor -public class LectureRegist { +public class LectureCreateRequest { private String title; diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java index 2731e5a..cfd87e6 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java @@ -1,7 +1,7 @@ package com.edufocus.edufocus.lecture.service; import com.edufocus.edufocus.lecture.entity.Lecture; -import com.edufocus.edufocus.lecture.entity.LectureRegist; +import com.edufocus.edufocus.lecture.entity.LectureCreateRequest; import org.springframework.stereotype.Service; import java.util.List; @@ -10,7 +10,7 @@ import java.util.List; @Service public interface LectureService { - void createLecture(long userId, LectureRegist lectureRegist); + void createLecture(long userId, LectureCreateRequest lectureCreateRequest); boolean deleteLecture(long userId, long LectureId); diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java index 4f120d8..79b7093 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java @@ -1,7 +1,7 @@ package com.edufocus.edufocus.lecture.service; import com.edufocus.edufocus.lecture.entity.Lecture; -import com.edufocus.edufocus.lecture.entity.LectureRegist; +import com.edufocus.edufocus.lecture.entity.LectureCreateRequest; import com.edufocus.edufocus.lecture.repository.LectureRepository; import com.edufocus.edufocus.user.model.entity.User; import com.edufocus.edufocus.user.model.repository.UserRepository; @@ -21,18 +21,18 @@ public class LectureServiceImpl implements LectureService { private final UserRepository userRepository; @Override - public void createLecture(long userId, LectureRegist lectureRegist) { + public void createLecture(long userId, LectureCreateRequest lectureCreateRequest) { User user = userRepository.findById(userId).get(); Lecture lecture = new Lecture(); lecture.setUser(user); - lecture.setTitle(lectureRegist.getTitle()); - lecture.setDescription(lectureRegist.getDescription()); - lecture.setStartDate(lectureRegist.getStartDate()); - lecture.setEndDate(lectureRegist.getEndDate()); - lecture.setPlan(lectureRegist.getPlan()); + lecture.setTitle(lectureCreateRequest.getTitle()); + lecture.setDescription(lectureCreateRequest.getDescription()); + lecture.setStartDate(lectureCreateRequest.getStartDate()); + lecture.setEndDate(lectureCreateRequest.getEndDate()); + lecture.setPlan(lectureCreateRequest.getPlan()); lectureRepository.save(lecture); } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java b/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java index b77b3d4..3c18199 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java @@ -1,4 +1,46 @@ package com.edufocus.edufocus.quiz.controller; +import com.edufocus.edufocus.quiz.entity.*; +import com.edufocus.edufocus.quiz.service.QuizService; +import com.edufocus.edufocus.quiz.service.QuizSetService; +import com.edufocus.edufocus.user.model.service.UserService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +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 +@RequestMapping("/quiz") +@Slf4j +@RequiredArgsConstructor public class QuizController { + + private final QuizService quizService; + + private final QuizSetService quizSetService; + + private final UserService userService; + + @PostMapping + public ResponseEntity createQuizSet(@RequestBody QuizSetCreateRequest quizSetCreateRequest) { + + Long userId = 1L; + + String title = quizSetCreateRequest.getTitle(); + String image = quizSetCreateRequest.getImage(); + + SetCreateRequest setCreateRequest = new SetCreateRequest(userId, title, image); + + QuizSet quizSet = quizSetService.createQuizSet(setCreateRequest); + + for (QuizCreateRequest quizCreateRequest : quizSetCreateRequest.getQuizzes()) { + quizService.createQuiz(quizSet.getId(), quizCreateRequest); + } + + return new ResponseEntity<>(HttpStatus.CREATED); + } } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/MutipleQuizCreateRequest.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/MutipleQuizCreateRequest.java new file mode 100644 index 0000000..20dbf54 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/MutipleQuizCreateRequest.java @@ -0,0 +1,20 @@ +package com.edufocus.edufocus.quiz.entity; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.ToString; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class MutipleQuizCreateRequest extends QuizCreateRequest { + + private String choice1; + + private String choice2; + + private String choice3; + + private String choice4; +} diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Quiz.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Quiz.java index b997e38..4ea9b43 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Quiz.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Quiz.java @@ -11,7 +11,7 @@ public class Quiz { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - private int id; + private Long id; @ManyToOne @JoinColumn(name = "quizset_id") diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizCreateRequest.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizCreateRequest.java new file mode 100644 index 0000000..d5c38da --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizCreateRequest.java @@ -0,0 +1,23 @@ +package com.edufocus.edufocus.quiz.entity; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.ToString; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class QuizCreateRequest { + + private String title; + + private String description; + + private boolean isSingle; + + private String answer; + + private String image; + +} diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSet.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSet.java index 7198a4c..b067277 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSet.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSet.java @@ -15,7 +15,7 @@ public class QuizSet { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - private int id; + private Long id; @ManyToOne @JoinColumn(name = "user_id") diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSetCreateRequest.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSetCreateRequest.java new file mode 100644 index 0000000..20a0025 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSetCreateRequest.java @@ -0,0 +1,22 @@ +package com.edufocus.edufocus.quiz.entity; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class QuizSetCreateRequest { + + private Long UserId; + + private String title; + + private String image; + + private List quizzes; + +} \ No newline at end of file diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/SetCreateRequest.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/SetCreateRequest.java new file mode 100644 index 0000000..a391ceb --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/SetCreateRequest.java @@ -0,0 +1,18 @@ +package com.edufocus.edufocus.quiz.entity; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class SetCreateRequest { + + private Long UserId; + + private String title; + + private String image; + +} diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/repository/QuizRepository.java b/backend/src/main/java/com/edufocus/edufocus/quiz/repository/QuizRepository.java index ba2085b..7428689 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/repository/QuizRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/repository/QuizRepository.java @@ -1,4 +1,7 @@ package com.edufocus.edufocus.quiz.repository; -public interface QuizRepository { +import com.edufocus.edufocus.quiz.entity.Quiz; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface QuizRepository extends JpaRepository { } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/repository/QuizSetRepository.java b/backend/src/main/java/com/edufocus/edufocus/quiz/repository/QuizSetRepository.java index 820dff9..81883a6 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/repository/QuizSetRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/repository/QuizSetRepository.java @@ -1,4 +1,8 @@ package com.edufocus.edufocus.quiz.repository; -public interface QuizSetRepository { +import com.edufocus.edufocus.quiz.entity.QuizSet; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface QuizSetRepository extends JpaRepository { + } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizService.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizService.java index 3b84367..3174e89 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizService.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizService.java @@ -1,4 +1,14 @@ package com.edufocus.edufocus.quiz.service; +import com.edufocus.edufocus.quiz.entity.MutipleQuizCreateRequest; +import com.edufocus.edufocus.quiz.entity.QuizCreateRequest; +import org.springframework.stereotype.Service; + +@Service public interface QuizService { + + void createQuiz(long quizSetId, QuizCreateRequest + QuizCreateRequest); + + boolean deleteQuiz(long quizId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizServiceImpl.java index 0a06913..5f34010 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizServiceImpl.java @@ -1,4 +1,49 @@ package com.edufocus.edufocus.quiz.service; -public class QuizServiceImpl { +import com.edufocus.edufocus.quiz.entity.MutipleQuizCreateRequest; +import com.edufocus.edufocus.quiz.entity.Quiz; +import com.edufocus.edufocus.quiz.entity.QuizCreateRequest; +import com.edufocus.edufocus.quiz.entity.QuizSet; +import com.edufocus.edufocus.quiz.repository.QuizRepository; +import com.edufocus.edufocus.quiz.repository.QuizSetRepository; +import jakarta.transaction.Transactional; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@Transactional +@RequiredArgsConstructor +public class QuizServiceImpl implements QuizService { + + private final QuizRepository quizRepository; + + private final QuizSetRepository quizSetRepository; + + @Override + public void createQuiz(long quizSetId, QuizCreateRequest quizCreateRequest) { + QuizSet quizSet = quizSetRepository.findById(quizSetId).get(); + + Quiz quiz = new Quiz(); + + quiz.setTitle(quizCreateRequest.getTitle()); + quiz.setDescription(quizCreateRequest.getDescription()); + quiz.setAnswer(quizCreateRequest.getAnswer()); + quiz.setImage(quizCreateRequest.getImage()); + + + quiz.setQuizSet(quizSet); + + quizRepository.save(quiz); + } + + @Override + public boolean deleteQuiz(long quizId) { + // 유저 아이디 정보 조회 후 검증 로직 추가 예정 + // jwt -> 로그인 유저 정보 조회 + // quizId -> 퀴즈 정보 조회 -> 퀴즈셋 정보 조회 + // 퀴즈셋 생성자와 로그인 유저의 id값이 일치하는지 확인 -> 불일치시 삭제 실패 + + quizRepository.deleteById(quizId); + return true; + } } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetService.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetService.java index bbf8570..748283b 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetService.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetService.java @@ -1,4 +1,16 @@ package com.edufocus.edufocus.quiz.service; +import com.edufocus.edufocus.quiz.entity.QuizSet; +import com.edufocus.edufocus.quiz.entity.SetCreateRequest; +import org.springframework.stereotype.Service; + +@Service public interface QuizSetService { + + QuizSet createQuizSet(SetCreateRequest setCreateRequest); + + void updateQuizSet(QuizSet quizSet); + + void deleteQuizSet(long quizSetId); + } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java index d27c69b..a167cca 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java @@ -1,4 +1,45 @@ package com.edufocus.edufocus.quiz.service; -public class QuizSetServiceImpl { +import com.edufocus.edufocus.quiz.entity.QuizSet; +import com.edufocus.edufocus.quiz.entity.SetCreateRequest; +import com.edufocus.edufocus.quiz.repository.QuizSetRepository; +import com.edufocus.edufocus.user.model.entity.User; +import com.edufocus.edufocus.user.model.repository.UserRepository; +import jakarta.transaction.Transactional; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@Transactional +@RequiredArgsConstructor +public class QuizSetServiceImpl implements QuizSetService { + + private final QuizSetRepository quizSetRepository; + + private final UserRepository userRepository; + + + @Override + public QuizSet createQuizSet(SetCreateRequest setCreateRequest) { + QuizSet quizSet = new QuizSet(); + + User user = userRepository.findById(setCreateRequest.getUserId()).get(); + + quizSet.setUser(user); + + quizSet.setTitle(setCreateRequest.getTitle()); + quizSet.setImage(setCreateRequest.getImage()); + + return quizSetRepository.save(quizSet); + } + + @Override + public void updateQuizSet(QuizSet quizSet) { + + } + + @Override + public void deleteQuizSet(long quizSetId) { + quizSetRepository.deleteById(quizSetId); + } } From 83c4172c6216fa7f592a88f5b78739ee70adde90 Mon Sep 17 00:00:00 2001 From: kgc9007 Date: Thu, 18 Jul 2024 15:03:16 +0900 Subject: [PATCH 012/197] =?UTF-8?q?fix:=20conflict=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lecture/controller/LectureController.java | 6 +++--- ...ectureCreateRequest.java => LectureRegist.java} | 2 +- .../edufocus/lecture/service/LectureService.java | 4 ++-- .../lecture/service/LectureServiceImpl.java | 14 +++++++------- 4 files changed, 13 insertions(+), 13 deletions(-) rename backend/src/main/java/com/edufocus/edufocus/lecture/entity/{LectureCreateRequest.java => LectureRegist.java} (92%) diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java b/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java index fd8471c..8cc015c 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java @@ -1,7 +1,7 @@ package com.edufocus.edufocus.lecture.controller; import com.edufocus.edufocus.lecture.entity.Lecture; -import com.edufocus.edufocus.lecture.entity.LectureCreateRequest; +import com.edufocus.edufocus.lecture.entity.LectureRegist; import com.edufocus.edufocus.lecture.service.LectureService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -20,8 +20,8 @@ public class LectureController { private final LectureService lectureService; @PostMapping - public ResponseEntity createLecture (@RequestBody long userId, @RequestBody LectureCreateRequest lectureCreateRequest) { - lectureService.createLecture(userId, lectureCreateRequest); + public ResponseEntity createLecture (@RequestBody long userId, @RequestBody LectureRegist lectureRegist) { + lectureService.createLecture(userId, lectureRegist); return new ResponseEntity<>(HttpStatus.CREATED); } diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureCreateRequest.java b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureRegist.java similarity index 92% rename from backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureCreateRequest.java rename to backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureRegist.java index 7ce8bfb..24790e3 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureCreateRequest.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureRegist.java @@ -10,7 +10,7 @@ import java.util.Date; @Getter @NoArgsConstructor @AllArgsConstructor -public class LectureCreateRequest { +public class LectureRegist { private String title; diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java index cfd87e6..2731e5a 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java @@ -1,7 +1,7 @@ package com.edufocus.edufocus.lecture.service; import com.edufocus.edufocus.lecture.entity.Lecture; -import com.edufocus.edufocus.lecture.entity.LectureCreateRequest; +import com.edufocus.edufocus.lecture.entity.LectureRegist; import org.springframework.stereotype.Service; import java.util.List; @@ -10,7 +10,7 @@ import java.util.List; @Service public interface LectureService { - void createLecture(long userId, LectureCreateRequest lectureCreateRequest); + void createLecture(long userId, LectureRegist lectureRegist); boolean deleteLecture(long userId, long LectureId); diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java index 79b7093..4f120d8 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java @@ -1,7 +1,7 @@ package com.edufocus.edufocus.lecture.service; import com.edufocus.edufocus.lecture.entity.Lecture; -import com.edufocus.edufocus.lecture.entity.LectureCreateRequest; +import com.edufocus.edufocus.lecture.entity.LectureRegist; import com.edufocus.edufocus.lecture.repository.LectureRepository; import com.edufocus.edufocus.user.model.entity.User; import com.edufocus.edufocus.user.model.repository.UserRepository; @@ -21,18 +21,18 @@ public class LectureServiceImpl implements LectureService { private final UserRepository userRepository; @Override - public void createLecture(long userId, LectureCreateRequest lectureCreateRequest) { + public void createLecture(long userId, LectureRegist lectureRegist) { User user = userRepository.findById(userId).get(); Lecture lecture = new Lecture(); lecture.setUser(user); - lecture.setTitle(lectureCreateRequest.getTitle()); - lecture.setDescription(lectureCreateRequest.getDescription()); - lecture.setStartDate(lectureCreateRequest.getStartDate()); - lecture.setEndDate(lectureCreateRequest.getEndDate()); - lecture.setPlan(lectureCreateRequest.getPlan()); + lecture.setTitle(lectureRegist.getTitle()); + lecture.setDescription(lectureRegist.getDescription()); + lecture.setStartDate(lectureRegist.getStartDate()); + lecture.setEndDate(lectureRegist.getEndDate()); + lecture.setPlan(lectureRegist.getPlan()); lectureRepository.save(lecture); } From 56f3eaaa1e52e819b43949244052996761e4d874 Mon Sep 17 00:00:00 2001 From: kgc9007 Date: Thu, 18 Jul 2024 16:16:16 +0900 Subject: [PATCH 013/197] =?UTF-8?q?refactor:=20lecture=20lecture=20?= =?UTF-8?q?=EC=97=94=ED=8B=B0=ED=8B=B0=EC=9D=98=20=EC=BB=AC=EB=9F=BC?= =?UTF-8?q?=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/edufocus/edufocus/lecture/entity/Lecture.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java index 9c11337..8fd58e6 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java @@ -16,8 +16,7 @@ import java.util.List; public class Lecture { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - - @Column(name="lecture_id") + @Column private Long id; @ManyToOne From f6e601c9f96ce8e8f2216293581374b535c5bf3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Thu, 18 Jul 2024 16:33:54 +0900 Subject: [PATCH 014/197] feat: login --- .../lecture/controller/LectureController.java | 2 + .../user/controller/UserController.java | 73 ++++++++++++++++--- .../edufocus/user/model/entity/User.java | 1 - 3 files changed, 66 insertions(+), 10 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java b/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java index bd013a4..8d19901 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java @@ -22,6 +22,8 @@ public class LectureController { @PostMapping public ResponseEntity createLecture (@RequestBody long userId, LectureRegist lectureRegist) { System.out.println("@@@@@@@@@@@@@@@@@@>>>>>>>>>>>>>>>>>>>>>> "+userId); + + // 여기서 id 로직 lectureService.createLecture(userId, lectureRegist); return new ResponseEntity<>(HttpStatus.CREATED); } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java index 9689880..16e8b9f 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java @@ -5,7 +5,9 @@ import com.edufocus.edufocus.user.model.service.UserService; import com.edufocus.edufocus.user.util.JWTUtil; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; +import jakarta.servlet.http.Cookie; 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; @@ -48,7 +50,7 @@ public class UserController { @Operation(summary = "로그인", description = "아이디와 비밀번호를 이용하여 로그인 처리.") @PostMapping("/login") public ResponseEntity> login( - @RequestBody @Parameter(description = "로그인 시 필요한 회원정보(아이디, 비밀번호).", required = true) User user) { + @RequestBody @Parameter(description = "로그인 시 필요한 회원정보(아이디, 비밀번호).", required = true) User user, HttpServletResponse response) { Map resultMap = new HashMap<>(); HttpStatus status = HttpStatus.ACCEPTED; try { @@ -63,8 +65,18 @@ public class UserController { // JSON 으로 token 전달. System.out.println(accessToken); resultMap.put("access-token", accessToken); - resultMap.put("refresh-token", refreshToken); + // resultMap.put("refresh-token", refreshToken); + // 쿠키 저장 + Cookie refreshCookie = new Cookie("refresh-token", refreshToken); + refreshCookie.setPath("/"); + refreshCookie.setHttpOnly(true); + refreshCookie.setSecure(true); // HTTPS에서만 전송되도록 설정 + // refreshCookie.setSameSite(Cookie.SameSite.NONE); // Cross-Origin 요청에 대해 모두 전송 + + response.addCookie(refreshCookie); + + // 쿠키저장 status = HttpStatus.CREATED; } else { resultMap.put("message", "아이디 또는 패스워드를 확인해 주세요."); @@ -78,7 +90,7 @@ public class UserController { } @Operation(summary = "회원인증", description = "회원 정보를 담은 Token 을 반환한다.") - @GetMapping("/info/{userId}") + @GetMapping("/auth/{userId}") public ResponseEntity> getInfo( @PathVariable("userId") @Parameter(description = "인증할 회원의 아이디.", required = true) Long userId, HttpServletRequest request) { @@ -129,19 +141,62 @@ public class UserController { @Operation(summary = "Access Token 재발급", description = "만료된 access token 을 재발급 받는다.") @PostMapping("/refresh") - public ResponseEntity refreshToken(@RequestBody User user, HttpServletRequest request) + public ResponseEntity refreshToken(HttpServletRequest request,HttpServletResponse response) throws Exception { + + // System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@"); + // System.out.println(user.getUserId()); Map resultMap = new HashMap<>(); HttpStatus status = HttpStatus.ACCEPTED; - String token = request.getHeader("refreshToken"); - log.debug("token : {}, memberDto : {}", token, user); + + // String token = request.getHeader("refreshToken"); + + + Cookie[] cookies = request.getCookies(); + String token = null; + + if (cookies != null) { + for (Cookie cookie : cookies) { + if (cookie.getName().equals("refresh-token")) { + token = cookie.getValue(); + break; + } + } + } + Long userId = Long.parseLong(jwtUtil.getUserId(token)); + /// System.out.println(userId); + /// System.out.println("리프레쉬 토큰 (쿠키에서 받은거 "+token); + // log.debug("token : {}, memberDto : {}", token, user); + // System.out.println(jwtUtil.checkToken(token)); if (jwtUtil.checkToken(token)) { - if (token.equals(userService.getRefreshToken(user.getId()))) { - String accessToken = jwtUtil.createAccessToken(String.valueOf(user.getId())); + + // System.out.println(token); + // System.out.println(userService.getRefreshToken(userId)); + //System.out.println("쿠키 토큰 , 디비 토큰 비교"+token.equals(userService.getRefreshToken(userId))); + if (token.equals(userService.getRefreshToken(userId))) { + System.out.println("!!"); + String accessToken = jwtUtil.createAccessToken(String.valueOf(userId)); + String refreshToken = jwtUtil.createRefreshToken(String.valueOf(userId)); + log.debug("token : {}", accessToken); log.debug("정상적으로 access token 재발급!!!"); resultMap.put("access-token", accessToken); + + + // 바뀐 리프레시db저장 + userService.saveRefreshToken(userId,refreshToken); + // 쿠키 저장 + Cookie refreshCookie = new Cookie("refresh-token", refreshToken); + refreshCookie.setPath("/"); + refreshCookie.setHttpOnly(true); + refreshCookie.setSecure(true); // HTTPS에서만 전송되도록 설정 + // refreshCookie.setSameSite(Cookie.SameSite.NONE); // Cross-Origin 요청에 대해 모두 전송 + + response.addCookie(refreshCookie); + System.out.println("바뀐 리프레쉬랑 지금꺼 비교 "+ refreshToken.equals(token)); + resultMap.put("access-token", accessToken); status = HttpStatus.CREATED; + } } else { log.debug("refresh token 도 사용 불가!!!!!!!"); @@ -151,7 +206,7 @@ public class UserController { } @Operation(summary = "회원 정보 조회", description = "토큰을 이용하여 회원 정보를 조회한다.") - @GetMapping("/member") + @GetMapping("/userinfo") public ResponseEntity> getMember(HttpServletRequest request) { Map resultMap = new HashMap<>(); HttpStatus status = HttpStatus.ACCEPTED; diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/User.java b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/User.java index 69a8b96..74cff10 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/User.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/User.java @@ -30,7 +30,6 @@ public class User { private String password; @Enumerated(EnumType.STRING) // 혹은 EnumType.ORDINAL private UserRole role; - private String refreshToken; From ff9dad72f4b54a456874d1921cda8766bfe95325 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Fri, 19 Jul 2024 09:40:59 +0900 Subject: [PATCH 015/197] feat: user --- .../edufocus/qna/controller/QnaController.java | 13 ++++++++++--- .../edufocus/edufocus/qna/service/QnaService.java | 2 +- .../edufocus/qna/service/QnaServiceImpl.java | 3 ++- .../edufocus/edufocus/user/model/entity/User.java | 2 ++ 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java b/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java index fb3356f..0a4c1d2 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java @@ -2,6 +2,8 @@ package com.edufocus.edufocus.qna.controller; import com.edufocus.edufocus.qna.entity.Qna; import com.edufocus.edufocus.qna.service.QnaService; +import com.edufocus.edufocus.user.util.JWTUtil; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import okhttp3.Response; @@ -18,12 +20,17 @@ import java.util.List; @RequiredArgsConstructor public class QnaController { private final QnaService qnaService; - + private final JWTUtil jwtUtil; @PostMapping - public ResponseEntity createQna(@RequestBody Qna qna) { + public ResponseEntity createQna(@RequestBody Qna qna , HttpServletRequest request) { + + try{ - qnaService.createQna(qna); + String token = request.getHeader("Authorization"); + Long userId = Long.parseLong(jwtUtil.getUserId(token)); + + qnaService.createQna(userId,qna); return new ResponseEntity<>(qna, HttpStatus.CREATED); }catch (Exception e){ diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaService.java b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaService.java index a1b8d94..8acf0f5 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaService.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaService.java @@ -11,7 +11,7 @@ import java.util.List; @Service public interface QnaService { - void createQna(Qna qna) throws SQLException; + void createQna(Long id,Qna qna) throws SQLException; void updateQna(Long id,Qna qna) throws SQLException; void deleteQna(Long id) throws SQLException; Qna getQna(Long id) throws SQLException; diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java index 18a59c1..4e6cdc2 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java @@ -20,9 +20,10 @@ public class QnaServiceImpl implements QnaService{ @Override - public void createQna(Qna qna) { + public void createQna(Long id,Qna qna) { + qna.setId(id); qnaRepository.save(qna); } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/User.java b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/User.java index 74cff10..8bc7952 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/User.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/User.java @@ -32,6 +32,8 @@ public class User { private UserRole role; private String refreshToken; + private String name; + From afa5f494aa7d8d555fa68051a17eb4959ea88fbd Mon Sep 17 00:00:00 2001 From: kgc9007 Date: Fri, 19 Jul 2024 09:58:22 +0900 Subject: [PATCH 016/197] =?UTF-8?q?feat:=20Lecture=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80=20=EA=B0=95=EC=9D=98=20?= =?UTF-8?q?=EC=A0=84=EC=B2=B4=EC=A1=B0=ED=9A=8C,=20=EC=83=81=EC=84=B8?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C,=20=EB=82=B4=20=EA=B0=95=EC=9D=98=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lecture/controller/LectureController.java | 44 ++++++--- .../edufocus/lecture/entity/Lecture.java | 5 +- ...eRegist.java => LectureCreateRequest.java} | 9 +- .../lecture/entity/LectureDetailResponse.java | 33 +++++++ .../lecture/entity/LectureSearchResponse.java | 19 ++++ .../lecture/repository/LectureRepository.java | 2 + .../lecture/service/LectureService.java | 13 ++- .../lecture/service/LectureServiceImpl.java | 96 ++++++++++++++++--- .../repository/RegistrationRepository.java | 4 +- 9 files changed, 186 insertions(+), 39 deletions(-) rename backend/src/main/java/com/edufocus/edufocus/lecture/entity/{LectureRegist.java => LectureCreateRequest.java} (70%) create mode 100644 backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureDetailResponse.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureSearchResponse.java diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java b/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java index 8d19901..e532525 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java @@ -1,8 +1,13 @@ package com.edufocus.edufocus.lecture.controller; -import com.edufocus.edufocus.lecture.entity.Lecture; -import com.edufocus.edufocus.lecture.entity.LectureRegist; +import com.edufocus.edufocus.lecture.entity.LectureCreateRequest; +import com.edufocus.edufocus.lecture.entity.LectureSearchResponse; +import com.edufocus.edufocus.lecture.entity.LectureDetailResponse; import com.edufocus.edufocus.lecture.service.LectureService; +import com.edufocus.edufocus.user.model.entity.User; +import com.edufocus.edufocus.user.model.service.UserService; +import com.edufocus.edufocus.user.model.service.UserServiceImpl; +import com.edufocus.edufocus.user.util.JWTUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; @@ -18,18 +23,19 @@ import java.util.List; public class LectureController { private final LectureService lectureService; + private final JWTUtil jwtUtil; + private final UserService userService; @PostMapping - public ResponseEntity createLecture (@RequestBody long userId, LectureRegist lectureRegist) { - System.out.println("@@@@@@@@@@@@@@@@@@>>>>>>>>>>>>>>>>>>>>>> "+userId); + public ResponseEntity createLecture(@RequestHeader("Authorization") String accessToken, @RequestBody LectureCreateRequest lectureCreateRequest) { + Long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); - // 여기서 id 로직 - lectureService.createLecture(userId, lectureRegist); + lectureService.createLecture(userId, lectureCreateRequest); return new ResponseEntity<>(HttpStatus.CREATED); } @DeleteMapping("/{lectureId}") - public ResponseEntity deleteLecture (@RequestBody long userId, @PathVariable long lectureId) { + public ResponseEntity deleteLecture(@RequestBody long userId, @PathVariable long lectureId) { if (!lectureService.deleteLecture(userId, lectureId)) { return new ResponseEntity<>(HttpStatus.NOT_FOUND); } @@ -38,8 +44,8 @@ public class LectureController { } @GetMapping - public ResponseEntity findAllLecture () { - List lectures = lectureService.findAllLecture(); + public ResponseEntity findAllLecture() { + List lectures = lectureService.findAllLecture(); if (lectures.isEmpty()) { return new ResponseEntity<>(HttpStatus.NO_CONTENT); @@ -48,17 +54,27 @@ public class LectureController { return new ResponseEntity<>(lectures, HttpStatus.OK); } - @GetMapping("/title/{title}") - public ResponseEntity findByTitle (@PathVariable String title) { - Lecture lecture = lectureService.findLectureByTitle(title); + @GetMapping("/{lectureId}") + public ResponseEntity findById(@PathVariable long lectureId) { + LectureDetailResponse lectureDetailResponse = lectureService.findLectureById(lectureId); - if (lecture == null) { + if (lectureDetailResponse == null) { return new ResponseEntity<>(HttpStatus.NO_CONTENT); } - return new ResponseEntity<>(lecture, HttpStatus.OK); + return new ResponseEntity<>(lectureDetailResponse, HttpStatus.OK); } + @GetMapping("/mylecture") + public ResponseEntity findMyLecture(@RequestHeader("Authorization") String accessToken) { + Long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); + List myLectures = lectureService.findMyLecture(userId); + if (myLectures.isEmpty()) { + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + return new ResponseEntity<>(myLectures, HttpStatus.OK); + } } diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java index 8fd58e6..d2f220b 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java @@ -29,6 +29,9 @@ public class Lecture { @Lob private String description; + @Column + private String image; + @Column(name = "start_date") @Temporal(TemporalType.DATE) private Date startDate; @@ -43,6 +46,4 @@ public class Lecture { @Column private boolean online; - - } diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureRegist.java b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureCreateRequest.java similarity index 70% rename from backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureRegist.java rename to backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureCreateRequest.java index 4486854..84c2181 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureRegist.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureCreateRequest.java @@ -1,6 +1,5 @@ package com.edufocus.edufocus.lecture.entity; -import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; @@ -10,18 +9,16 @@ import java.util.Date; @Getter @NoArgsConstructor @AllArgsConstructor -public class LectureRegist { - - private Long userId; +public class LectureCreateRequest { private String title; private String description; - @Temporal(TemporalType.DATE) + private String image; + private Date startDate; - @Temporal(TemporalType.DATE) private Date endDate; private String plan; diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureDetailResponse.java b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureDetailResponse.java new file mode 100644 index 0000000..08f9558 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureDetailResponse.java @@ -0,0 +1,33 @@ +package com.edufocus.edufocus.lecture.entity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.Date; + +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class LectureDetailResponse { + + private Long id; + + private String teacherName; + + private String title; + + private String description; + + private String image; + + private Date startDate; + + private Date endDate; + + private String plan; + + private boolean online; +} diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureSearchResponse.java b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureSearchResponse.java new file mode 100644 index 0000000..08bf38d --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureSearchResponse.java @@ -0,0 +1,19 @@ +package com.edufocus.edufocus.lecture.entity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class LectureSearchResponse { + + private Long id; + + private String title; + + private String image; +} diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/repository/LectureRepository.java b/backend/src/main/java/com/edufocus/edufocus/lecture/repository/LectureRepository.java index 6366507..431b96a 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/repository/LectureRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/repository/LectureRepository.java @@ -12,4 +12,6 @@ import java.util.List; public interface LectureRepository extends JpaRepository { Lecture findByTitle(@Param("title") String title); + List findAllByUserId(@Param("userId") Long userId); + } diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java index 2731e5a..b359aa0 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java @@ -1,7 +1,8 @@ package com.edufocus.edufocus.lecture.service; -import com.edufocus.edufocus.lecture.entity.Lecture; -import com.edufocus.edufocus.lecture.entity.LectureRegist; +import com.edufocus.edufocus.lecture.entity.LectureCreateRequest; +import com.edufocus.edufocus.lecture.entity.LectureSearchResponse; +import com.edufocus.edufocus.lecture.entity.LectureDetailResponse; import org.springframework.stereotype.Service; import java.util.List; @@ -10,12 +11,14 @@ import java.util.List; @Service public interface LectureService { - void createLecture(long userId, LectureRegist lectureRegist); + void createLecture(long userId, LectureCreateRequest lectureCreateRequest); boolean deleteLecture(long userId, long LectureId); - List findAllLecture(); + List findAllLecture(); - Lecture findLectureByTitle(String title); + LectureDetailResponse findLectureById(long lectureId); + + List findMyLecture(long userId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java index 4f120d8..9f9eec8 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java @@ -1,16 +1,23 @@ package com.edufocus.edufocus.lecture.service; import com.edufocus.edufocus.lecture.entity.Lecture; -import com.edufocus.edufocus.lecture.entity.LectureRegist; +import com.edufocus.edufocus.lecture.entity.LectureCreateRequest; +import com.edufocus.edufocus.lecture.entity.LectureSearchResponse; +import com.edufocus.edufocus.lecture.entity.LectureDetailResponse; import com.edufocus.edufocus.lecture.repository.LectureRepository; +import com.edufocus.edufocus.registration.entity.Registration; +import com.edufocus.edufocus.registration.repository.RegistrationRepository; import com.edufocus.edufocus.user.model.entity.User; import com.edufocus.edufocus.user.model.repository.UserRepository; import jakarta.transaction.Transactional; +import lombok.Builder; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import java.util.ArrayList; import java.util.List; +@Builder @Service @Transactional @RequiredArgsConstructor @@ -20,19 +27,22 @@ public class LectureServiceImpl implements LectureService { private final UserRepository userRepository; + private final RegistrationRepository registrationRepository; + @Override - public void createLecture(long userId, LectureRegist lectureRegist) { + public void createLecture(long userId, LectureCreateRequest lectureCreateRequest) { User user = userRepository.findById(userId).get(); Lecture lecture = new Lecture(); lecture.setUser(user); - lecture.setTitle(lectureRegist.getTitle()); - lecture.setDescription(lectureRegist.getDescription()); - lecture.setStartDate(lectureRegist.getStartDate()); - lecture.setEndDate(lectureRegist.getEndDate()); - lecture.setPlan(lectureRegist.getPlan()); + lecture.setTitle(lectureCreateRequest.getTitle()); + lecture.setDescription(lectureCreateRequest.getDescription()); + lecture.setImage(lectureCreateRequest.getImage()); + lecture.setStartDate(lectureCreateRequest.getStartDate()); + lecture.setEndDate(lectureCreateRequest.getEndDate()); + lecture.setPlan(lectureCreateRequest.getPlan()); lectureRepository.save(lecture); } @@ -50,14 +60,78 @@ public class LectureServiceImpl implements LectureService { } @Override - public List findAllLecture() { - return lectureRepository.findAll(); + public List findAllLecture() { + List lectureList = lectureRepository.findAll(); + + List lectureSearchResponseList = new ArrayList<>(); + for (Lecture lecture : lectureList) { + LectureSearchResponse lectureSearchResponse = LectureSearchResponse.builder() + .id(lecture.getId()) + .title(lecture.getTitle()) + .image(lecture.getImage()).build(); + + lectureSearchResponseList.add(lectureSearchResponse); + } + + return lectureSearchResponseList; } @Override - public Lecture findLectureByTitle(String title) { - return lectureRepository.findByTitle(title); + public LectureDetailResponse findLectureById(long lectureId) { + + Lecture lecture = lectureRepository.findById(lectureId).get(); + + if (lecture == null) { + return null; + } + + LectureDetailResponse lectureDetailResponse = new LectureDetailResponse().builder() + .id(lecture.getId()) + .title(lecture.getTitle()) + .description(lecture.getDescription()) + .image(lecture.getImage()) + .startDate(lecture.getStartDate()) + .endDate(lecture.getEndDate()) + .plan(lecture.getPlan()) + .online(lecture.isOnline()) + .teacherName(lecture.getUser().getName()) + .build(); + + return lectureDetailResponse; } + public List findMyLecture(long userId) { + User user = userRepository.findById(userId).get(); + + List myLectureList = new ArrayList<>(); + + if (user.getRole().equals("ADMIN")) { + List lectureList = lectureRepository.findAllByUserId(userId); + + for (Lecture lecture : lectureList) { + LectureSearchResponse lectureSearchResponse = new LectureSearchResponse().builder() + .id(lecture.getId()) + .title(lecture.getTitle()) + .image(lecture.getImage()).build(); + + myLectureList.add(lectureSearchResponse); + } + } else { + List registrationList = registrationRepository.findAllByUserId(userId); + + for (Registration registration : registrationList) { + Lecture lecture = registration.getLecture(); + + LectureSearchResponse lectureSearchResponse = new LectureSearchResponse().builder() + .id(lecture.getId()) + .title(lecture.getTitle()) + .image(lecture.getImage()).build(); + + myLectureList.add(lectureSearchResponse); + } + } + + return myLectureList; + } } diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/repository/RegistrationRepository.java b/backend/src/main/java/com/edufocus/edufocus/registration/repository/RegistrationRepository.java index f8dc7db..34358a2 100644 --- a/backend/src/main/java/com/edufocus/edufocus/registration/repository/RegistrationRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/registration/repository/RegistrationRepository.java @@ -5,7 +5,9 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; +import java.util.List; + @Repository public interface RegistrationRepository extends JpaRepository { - + List findAllByUserId(@Param("userId") Long userId); } From 1549917d74bd612a1769b3e82977db41662d2b66 Mon Sep 17 00:00:00 2001 From: yulmam Date: Fri, 19 Jul 2024 12:58:12 +0900 Subject: [PATCH 017/197] =?UTF-8?q?feat=20:=20board=20=EA=B2=8C=EC=8B=9C?= =?UTF-8?q?=ED=8C=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/edufocus/board/entity/dto/RequestCommentDto.java | 4 +--- .../{ResponseBoardDto.java => ResponseBoardSummaryDto.java} | 0 .../edufocus/board/entity/dto/ResponseCommentDto.java | 2 ++ 3 files changed, 3 insertions(+), 3 deletions(-) rename backend/src/main/java/com/edufocus/edufocus/board/entity/dto/{ResponseBoardDto.java => ResponseBoardSummaryDto.java} (100%) create mode 100644 backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseCommentDto.java diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/RequestCommentDto.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/RequestCommentDto.java index 6578cad..9a4ffcf 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/RequestCommentDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/RequestCommentDto.java @@ -1,4 +1,2 @@ -package com.edufocus.edufocus.board.entity.dto; - -public class RequestCommentDto { +package com.edufocus.edufocus.board.entity.dto;public class RequestCommentDto { } diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardDto.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardSummaryDto.java similarity index 100% rename from backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardDto.java rename to backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardSummaryDto.java diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseCommentDto.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseCommentDto.java new file mode 100644 index 0000000..8726e1c --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseCommentDto.java @@ -0,0 +1,2 @@ +package com.edufocus.edufocus.board.entity.dto;public class ResponseCommentDto { +} From cebabf77c3d208bf9c6e8dabbcd661feea63fe37 Mon Sep 17 00:00:00 2001 From: yulmam Date: Fri, 19 Jul 2024 13:07:22 +0900 Subject: [PATCH 018/197] =?UTF-8?q?refactor=20:=20=EC=84=9C=EB=B9=84?= =?UTF-8?q?=EC=8A=A4=20=EB=A6=AC=ED=84=B4=EA=B0=92=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../board/controller/BoardController.java | 69 ++++++++----------- .../board/entity/dto/RequestBoardDto.java | 1 + .../board/entity/dto/RequestCommentDto.java | 10 ++- .../entity/dto/ResponseBoardDetailDto.java | 3 +- .../entity/dto/ResponseBoardSummaryDto.java | 12 +++- .../board/entity/dto/ResponseCommentDto.java | 18 ++++- .../edufocus/board/entity/vo/Board.java | 41 ++++++++--- .../edufocus/board/entity/vo/Comment.java | 14 +++- .../board/repository/BoardRepository.java | 4 +- .../board/repository/CommentRepository.java | 3 + .../edufocus/board/service/BoardService.java | 24 ++++--- .../board/service/BoardServiceImpl.java | 66 ++++++++++-------- 12 files changed, 172 insertions(+), 93 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java b/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java index a8a4db6..d25d940 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java @@ -1,11 +1,10 @@ package com.edufocus.edufocus.board.controller; -import com.edufocus.edufocus.board.entity.dto.RequestBoardDto; -import com.edufocus.edufocus.board.entity.dto.RequestBoardUpdateDto; -import com.edufocus.edufocus.board.entity.dto.RequestCommentDto; +import com.edufocus.edufocus.board.entity.dto.*; import com.edufocus.edufocus.board.entity.vo.Board; import com.edufocus.edufocus.board.entity.vo.Comment; import com.edufocus.edufocus.board.service.BoardService; +import com.edufocus.edufocus.user.util.JWTUtil; import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.constraints.Positive; import org.springframework.http.HttpStatus; @@ -18,13 +17,16 @@ import java.util.List; /** * @author Haneol Kim */ -@RestController("/board") +@RestController +@RequestMapping("/board") public class BoardController { + private final JWTUtil jwtUtil; private final BoardService boardService; - public BoardController(BoardService boardService){ + public BoardController(BoardService boardService, JWTUtil jwtUtil){ this.boardService = boardService; + this.jwtUtil = jwtUtil; } @GetMapping() @@ -33,22 +35,22 @@ public class BoardController { @RequestParam(value = "lectureId", required = true) long lectureId, @RequestParam(value = "pageNo", required = false, defaultValue = "0") int pageNo ){ - List boards = boardService.findBoards(pageNo, category, lectureId); + List boardSummaries = boardService.findBoards(pageNo, category, lectureId); - if(boards.isEmpty()){ - return ResponseEntity.noContent().build(); + if(boardSummaries.isEmpty()){ + return new ResponseEntity<>(HttpStatus.NO_CONTENT); } - return ResponseEntity.ok(boards); + return new ResponseEntity<>(boardSummaries, HttpStatus.OK); } @GetMapping(value = "/{boardId}") public ResponseEntity getBoardDetail( - @PathVariable @Positive int boardId + @PathVariable int boardId ){ - Board responseBoardDetail = boardService.findBoardDetail(boardId); + ResponseBoardDetailDto responseBoardDetailDto = boardService.findBoardDetail(boardId); - return ResponseEntity.ok(responseBoardDetail); + return new ResponseEntity<>(responseBoardDetailDto, HttpStatus.OK); } @PostMapping @@ -56,8 +58,8 @@ public class BoardController { @RequestBody RequestBoardDto requestBoardDto, HttpServletRequest request ){ - - long userId = Long.parseLong(request.getHeader("Authentication")); + String token = request.getHeader("Authorization"); + long userId = Long.parseLong(jwtUtil.getUserId(token)); boardService.createBoard(userId, requestBoardDto); @@ -66,12 +68,9 @@ public class BoardController { @PutMapping(value = "/{boardId}") public ResponseEntity updateBoard( - @PathVariable @Positive long boardId, - @RequestBody RequestBoardUpdateDto requestBoardUpdateDto, - HttpServletRequest request + @PathVariable long boardId, + @RequestBody RequestBoardUpdateDto requestBoardUpdateDto ){ - long userId = Long.parseLong(request.getHeader("Authentication")); - boardService.updateBoard(boardId, requestBoardUpdateDto); return new ResponseEntity<>(HttpStatus.OK); @@ -89,49 +88,41 @@ public class BoardController { @GetMapping(value = "/comment/{boardId}") public ResponseEntity getComments( - @PathVariable @Positive int boardId, - HttpServletRequest request + @PathVariable int boardId ){ - long userId = Long.parseLong(request.getHeader("Authentication")); + List comments = boardService.findComments(boardId); - List comments = boardService.findComments(userId, boardId); - - return ResponseEntity.ok(comments); + return new ResponseEntity<>(comments, HttpStatus.OK); } @PostMapping(value = "/comment/{boardId}") public ResponseEntity addComment( - @PathVariable @Positive int boardId, - @RequestParam String content, + @PathVariable int boardId, + @RequestBody RequestCommentDto requestCommentDto, HttpServletRequest request ){ - long userId = Long.parseLong(request.getHeader("Authentication")); + String token = request.getHeader("Authorization"); + long userId = Long.parseLong(jwtUtil.getUserId(token)); - boardService.createComment(userId, boardId, content); + boardService.createComment(userId, boardId, requestCommentDto); return new ResponseEntity<>(HttpStatus.OK); } @PutMapping(value = "/comment/{commentId}") public ResponseEntity updateComment( - @PathVariable @Positive int commentId, - @RequestParam String content, - HttpServletRequest request + @PathVariable int commentId, + @RequestBody RequestCommentDto requestCommentDto ){ - long userId = Long.parseLong(request.getHeader("Authentication")); - - boardService.updateComment(commentId, content); + boardService.updateComment(commentId, requestCommentDto); return new ResponseEntity<>(HttpStatus.OK); } @DeleteMapping(value = "/comment/{commentId}") public ResponseEntity deleteComment( - @PathVariable @Positive int commentId, - HttpServletRequest request + @PathVariable int commentId ){ - long userId = Long.parseLong(request.getHeader("Authentication")); - boardService.deleteComment(commentId); return new ResponseEntity<>(HttpStatus.OK); diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/RequestBoardDto.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/RequestBoardDto.java index ca59a75..478017a 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/RequestBoardDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/RequestBoardDto.java @@ -1,6 +1,7 @@ package com.edufocus.edufocus.board.entity.dto; +import com.edufocus.edufocus.board.entity.vo.Board; import lombok.Getter; import lombok.Setter; diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/RequestCommentDto.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/RequestCommentDto.java index 9a4ffcf..4dfbd0b 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/RequestCommentDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/RequestCommentDto.java @@ -1,2 +1,10 @@ -package com.edufocus.edufocus.board.entity.dto;public class RequestCommentDto { +package com.edufocus.edufocus.board.entity.dto; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class RequestCommentDto { + private String content; } diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardDetailDto.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardDetailDto.java index 182a8cc..8cf6bc7 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardDetailDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardDetailDto.java @@ -12,8 +12,9 @@ import java.time.LocalTime; @Setter @AllArgsConstructor public class ResponseBoardDetailDto { - private int id; + private long id; private String name; + private String title; private String content; private int viewCount; private LocalTime createdAt; diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardSummaryDto.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardSummaryDto.java index 3d34b1a..d3e72a5 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardSummaryDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardSummaryDto.java @@ -1,7 +1,15 @@ package com.edufocus.edufocus.board.entity.dto; -public class ResponseBoardDto { - private int id; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +@Builder +@Getter +@Setter +public class ResponseBoardSummaryDto { + private long id; private String name; private String title; } diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseCommentDto.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseCommentDto.java index 8726e1c..92156ce 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseCommentDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseCommentDto.java @@ -1,2 +1,18 @@ -package com.edufocus.edufocus.board.entity.dto;public class ResponseCommentDto { +package com.edufocus.edufocus.board.entity.dto; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +import java.time.LocalTime; + +@Builder +@Getter +@Setter +public class ResponseCommentDto { + private long id; + private String name; + private String content; + private LocalTime createAt; + private LocalTime modifiedAt; } diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java index 7f8de48..6272a17 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java @@ -1,23 +1,24 @@ package com.edufocus.edufocus.board.entity.vo; +import com.edufocus.edufocus.board.entity.dto.ResponseBoardDetailDto; +import com.edufocus.edufocus.board.entity.dto.ResponseBoardSummaryDto; import com.edufocus.edufocus.lecture.entity.Lecture; import com.edufocus.edufocus.user.model.entity.User; +import com.fasterxml.jackson.annotation.JsonAutoDetect; import jakarta.persistence.*; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.NoArgsConstructor; -import lombok.Setter; +import lombok.*; import org.hibernate.annotations.CreationTimestamp; -import java.time.LocalDate; -import java.util.Date; +import java.time.LocalTime; +import java.util.List; @Entity @Builder @NoArgsConstructor @AllArgsConstructor @Setter +@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) public class Board { @Id @@ -37,10 +38,10 @@ public class Board { private int viewCount; @CreationTimestamp - LocalDate createdAt; + LocalTime createdAt; @CreationTimestamp - LocalDate modifiedAt; + LocalTime modifiedAt; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") @@ -49,4 +50,28 @@ public class Board { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "lecture_id") private Lecture lecture; + + + @OneToMany(mappedBy = "board") + private List comments; + + public ResponseBoardSummaryDto makeSummaryDto(){ + return ResponseBoardSummaryDto.builder() + .id(id) + .title(title) + .name(user.getUserId()) + .build(); + } + + public ResponseBoardDetailDto makeDetailDto(){ + return ResponseBoardDetailDto.builder() + .id(id) + .name(user.getEmail()) + .title(title) + .content(content) + .viewCount(viewCount) + .createdAt(createdAt) + .modifiedAt(modifiedAt) + .build(); + } } diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java index c3059c9..90c7ebf 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java @@ -1,7 +1,9 @@ package com.edufocus.edufocus.board.entity.vo; +import com.edufocus.edufocus.board.entity.dto.ResponseCommentDto; import com.edufocus.edufocus.user.model.entity.User; +import com.fasterxml.jackson.annotation.JsonAutoDetect; import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Builder; @@ -15,6 +17,7 @@ import java.time.LocalTime; @NoArgsConstructor @AllArgsConstructor @Setter +@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) public class Comment { @Id @GeneratedValue @@ -26,7 +29,7 @@ public class Comment { private LocalTime createdAt; @Column - private LocalTime updatedAt; + private LocalTime modifiedAt; @ManyToOne @JoinColumn(name = "user_id") @@ -36,5 +39,14 @@ public class Comment { @JoinColumn(name = "board_id") Board board; + public ResponseCommentDto makeCommentDto() { + return ResponseCommentDto.builder() + .id(id) + .name(user.getEmail()) + .content(content) + .createAt(createdAt) + .modifiedAt(modifiedAt) + .build(); + } } diff --git a/backend/src/main/java/com/edufocus/edufocus/board/repository/BoardRepository.java b/backend/src/main/java/com/edufocus/edufocus/board/repository/BoardRepository.java index 2cdb7c1..beff8b3 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/repository/BoardRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/repository/BoardRepository.java @@ -4,10 +4,12 @@ import com.edufocus.edufocus.board.entity.vo.Board; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; -import java.util.List; public interface BoardRepository extends JpaRepository { + + @Query("select b from Board b join fetch b.user where b.category =:category and b.lecture.id=:lectureId") Page findByLectureIdAndCategory(Long lectureId, String category, Pageable pageable); } diff --git a/backend/src/main/java/com/edufocus/edufocus/board/repository/CommentRepository.java b/backend/src/main/java/com/edufocus/edufocus/board/repository/CommentRepository.java index 9002ab8..c877fd1 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/repository/CommentRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/repository/CommentRepository.java @@ -2,10 +2,13 @@ package com.edufocus.edufocus.board.repository; import com.edufocus.edufocus.board.entity.vo.Comment; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import java.util.List; public interface CommentRepository extends JpaRepository { + + @Query("select c from Comment c join fetch c.user where c.board.id =:boardId") List findByBoardId(long boardId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/board/service/BoardService.java b/backend/src/main/java/com/edufocus/edufocus/board/service/BoardService.java index ac20175..f0d25f8 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/service/BoardService.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/service/BoardService.java @@ -1,23 +1,27 @@ package com.edufocus.edufocus.board.service; -import com.edufocus.edufocus.board.entity.dto.RequestBoardDto; -import com.edufocus.edufocus.board.entity.dto.RequestBoardUpdateDto; -import com.edufocus.edufocus.board.entity.dto.RequestCommentDto; -import com.edufocus.edufocus.board.entity.vo.Board; -import com.edufocus.edufocus.board.entity.vo.Comment; +import com.edufocus.edufocus.board.entity.dto.*; import java.util.List; public interface BoardService { - public List findBoards(int pageNo, String category, long lectureId); - public Board findBoardDetail(long boardId); public void createBoard(long userId, RequestBoardDto requestBoardDto); + + public List findBoards(int pageNo, String category, long lectureId); + + public ResponseBoardDetailDto findBoardDetail(long boardId); + public void updateBoard(long boardId, RequestBoardUpdateDto requestBoardUpdateDto); + public void deleteBoard(long boardId); - public List findComments(long userId, long boardId); - public void createComment(long userId, long boardId, String content); - public void updateComment(long commentId, String content); + + public void createComment(long userId, long boardId, RequestCommentDto requestCommentDto); + + public List findComments(long boardId); + + public void updateComment(long commentId, RequestCommentDto requestCommentDto); + public void deleteComment(long commentId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/board/service/BoardServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/board/service/BoardServiceImpl.java index 308bd57..29c5006 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/service/BoardServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/service/BoardServiceImpl.java @@ -1,9 +1,7 @@ package com.edufocus.edufocus.board.service; -import com.edufocus.edufocus.board.entity.dto.RequestBoardDto; -import com.edufocus.edufocus.board.entity.dto.RequestBoardUpdateDto; -import com.edufocus.edufocus.board.entity.dto.RequestCommentDto; +import com.edufocus.edufocus.board.entity.dto.*; import com.edufocus.edufocus.board.entity.vo.Board; import com.edufocus.edufocus.board.entity.vo.Comment; import com.edufocus.edufocus.board.repository.BoardRepository; @@ -12,22 +10,23 @@ import com.edufocus.edufocus.lecture.entity.Lecture; import com.edufocus.edufocus.lecture.repository.LectureRepository; import com.edufocus.edufocus.user.model.entity.User; import com.edufocus.edufocus.user.model.repository.UserRepository; -import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.util.List; +import java.util.stream.Collectors; @Service public class BoardServiceImpl implements BoardService { private static final int PAGE_SIZE = 10; - private final UserRepository userRepository; - private final LectureRepository lectureRepository; private final BoardRepository boardRepository; private final CommentRepository commentRepository; + private final UserRepository userRepository; + private final LectureRepository lectureRepository; public BoardServiceImpl(BoardRepository boardRepository, CommentRepository commentRepository, UserRepository userRepository, LectureRepository lectureRepository){ this.boardRepository = boardRepository; @@ -37,28 +36,32 @@ public class BoardServiceImpl implements BoardService { } - @Override - public List findBoards(int pageNo, String category, long lectureId) { + @Transactional + public List findBoards(int pageNo, String category, long lectureId) { Pageable pageable = PageRequest.of(pageNo, PAGE_SIZE); - Page boards = boardRepository.findByLectureIdAndCategory(lectureId, category, pageable); - return boards.getContent(); + + List boards = boardRepository.findByLectureIdAndCategory(lectureId, category, pageable).getContent(); + + return boards.stream().map(Board::makeSummaryDto) + .collect(Collectors.toList()); } - @Override - public Board findBoardDetail(long boardId) { - Board board = boardRepository.findById(boardId).get(); - return board; + @Transactional + public ResponseBoardDetailDto findBoardDetail(long boardId) { + return boardRepository.findById(boardId) + .orElseThrow() + .makeDetailDto(); } - @Override + @Transactional public void createBoard(long userId, RequestBoardDto requestBoardDto) { - User user = userRepository.findById(userId).get(); + User user = userRepository.findById(userId).orElseThrow(); Lecture lecture = lectureRepository.findById(requestBoardDto.getLectureId()).get(); Board board = Board.builder() .title(requestBoardDto.getTitle()) .category(requestBoardDto.getCategory()) - .content(requestBoardDto.getCategory()) + .content(requestBoardDto.getContent()) .user(user) .lecture(lecture) .build(); @@ -66,7 +69,7 @@ public class BoardServiceImpl implements BoardService { boardRepository.save(board); } - @Override + @Transactional public void updateBoard(long boardId, RequestBoardUpdateDto requestBoardUpdateDto) { Board board = boardRepository.findById(boardId).get(); @@ -77,25 +80,27 @@ public class BoardServiceImpl implements BoardService { } - @Override + @Transactional public void deleteBoard(long boardId) { Board board = boardRepository.findById(boardId).get(); boardRepository.delete(board); } - @Override - public List findComments(long userId, long boardId) { - return commentRepository.findByBoardId(boardId); + @Transactional + public List findComments(long boardId) { + return commentRepository.findByBoardId(boardId).stream() + .map(Comment::makeCommentDto) + .collect(Collectors.toList()); } - @Override - public void createComment(long userId, long boardId, String content) { + @Transactional + public void createComment(long userId, long boardId, RequestCommentDto requestCommentDto) { User user = userRepository.findById(userId).get(); Board board = boardRepository.findById(boardId).get(); Comment comment = Comment.builder() - .content(content) + .content(requestCommentDto.getContent()) .board(board) .user(user) .build(); @@ -105,16 +110,19 @@ public class BoardServiceImpl implements BoardService { - @Override - public void updateComment(long commentId, String content) { + @Transactional + public void updateComment(long commentId, RequestCommentDto requestCommentDto) { Comment comment = commentRepository.findById(commentId).get(); - comment.setContent(content); + + comment.setContent(requestCommentDto.getContent()); + commentRepository.save(comment); } - @Override + @Transactional public void deleteComment(long commentId) { Comment comment = commentRepository.findById(commentId).get(); + commentRepository.delete(comment); } From 459bf9725e17d2e6c617352efebfe5d75e0a8f69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Fri, 19 Jul 2024 13:39:03 +0900 Subject: [PATCH 019/197] feat: q&a , answer --- .../qna/controller/QnaController.java | 70 ++++++++++++--- .../com/edufocus/edufocus/qna/entity/Qna.java | 8 +- .../edufocus/qna/entity/QnaRequestDto.java | 24 +++++ .../edufocus/qna/entity/QnaResponseDto.java | 38 ++++++++ .../qna/repository/QnaRepository.java | 7 +- .../edufocus/qna/service/QnaService.java | 13 ++- .../edufocus/qna/service/QnaServiceImpl.java | 89 ++++++++++++++++--- 7 files changed, 217 insertions(+), 32 deletions(-) create mode 100644 backend/src/main/java/com/edufocus/edufocus/qna/entity/QnaRequestDto.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/qna/entity/QnaResponseDto.java diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java b/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java index 0a4c1d2..48cc08a 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java @@ -1,6 +1,8 @@ package com.edufocus.edufocus.qna.controller; import com.edufocus.edufocus.qna.entity.Qna; +import com.edufocus.edufocus.qna.entity.QnaRequestDto; +import com.edufocus.edufocus.qna.entity.QnaResponseDto; import com.edufocus.edufocus.qna.service.QnaService; import com.edufocus.edufocus.user.util.JWTUtil; import jakarta.servlet.http.HttpServletRequest; @@ -21,28 +23,71 @@ import java.util.List; public class QnaController { private final QnaService qnaService; private final JWTUtil jwtUtil; + private static int PAGE_SIZE=10; - @PostMapping - public ResponseEntity createQna(@RequestBody Qna qna , HttpServletRequest request) { + + @PostMapping("/{lecture_id}") + public ResponseEntity createQna(@PathVariable("lecture_id") Long lecture_id, @RequestBody QnaRequestDto qnaRequestDto , HttpServletRequest request) { try{ String token = request.getHeader("Authorization"); Long userId = Long.parseLong(jwtUtil.getUserId(token)); - qnaService.createQna(userId,qna); - return new ResponseEntity<>(qna, HttpStatus.CREATED); + QnaResponseDto qnaResponseDto= qnaService.createQna(userId,qnaRequestDto,lecture_id); + return new ResponseEntity<>( qnaResponseDto,HttpStatus.CREATED); }catch (Exception e){ throw new RuntimeException(e); } } + + @PostMapping({"/answer/create/{qna_id}"}) + public ResponseEntity createAnswer(@PathVariable("qna_id") Long qna_id, @RequestBody QnaRequestDto qnaRequestDto) + { + try { + QnaResponseDto responseDto = qnaService.createAnswer(qna_id,qnaRequestDto); + return new ResponseEntity<>(responseDto,HttpStatus.ACCEPTED); + } + catch (Exception e) + { + throw new RuntimeException(e); + } + } + + @PutMapping({"/answer/update/{qna_id}"}) + public ResponseEntity updateAnswer(@PathVariable("qna_id") Long qna_id, @RequestBody QnaRequestDto qnaRequestDto) + { + try { + QnaResponseDto responseDto = qnaService.updateAnswer(qna_id,qnaRequestDto); + return new ResponseEntity<>(responseDto,HttpStatus.ACCEPTED); + } + catch (Exception e) + { + throw new RuntimeException(e); + } + } + + @DeleteMapping("/answer/delete/{qna_id}") + public ResponseEntity deleteAnswer(@PathVariable("qna_id") Long qna_id) + { + try { + qnaService.deleteAnswer(qna_id); + return new ResponseEntity<>(HttpStatus.ACCEPTED); + } + catch (Exception e) + { + throw new RuntimeException(e); + } + } + + @PutMapping("/{id}") - public ResponseEntity updateQna(@PathVariable Long id, @RequestBody Qna qna) { + public ResponseEntity updateQna(@PathVariable Long id, @RequestBody QnaRequestDto qnaRequestDto) { try{ - qnaService.updateQna(id,qna); - return new ResponseEntity<>(qna, HttpStatus.ACCEPTED); + QnaResponseDto qnaResponseDto= qnaService.updateQna(id,qnaRequestDto); + return new ResponseEntity<>(qnaResponseDto, HttpStatus.ACCEPTED); }catch (Exception e) { @@ -72,15 +117,12 @@ public class QnaController { } @GetMapping("/all/{id}") - public ResponseEntity> getAllQna(@PathVariable Long id) { + public ResponseEntity> getAllQna(@PathVariable Long id) { try { - System.out.print("@@@@@@@@@@@@@@@@@@@@@@@>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); - List qnaList= qnaService.getAllQnasByLecture(id); - for(Qna qna:qnaList) - { - System.out.print(qna.toString()); - } + + List qnaList= qnaService.getAllQnasByLecture(id,PAGE_SIZE); + return new ResponseEntity<>(qnaList, HttpStatus.ACCEPTED); } catch (SQLException e) { throw new RuntimeException(e); diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java b/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java index 4451568..993484e 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java @@ -3,8 +3,7 @@ package com.edufocus.edufocus.qna.entity; import com.edufocus.edufocus.lecture.entity.Lecture; import com.edufocus.edufocus.user.model.entity.User; import jakarta.persistence.*; -import lombok.Getter; -import lombok.Setter; +import lombok.*; import org.checkerframework.checker.units.qual.C; import java.util.Date; @@ -12,6 +11,9 @@ import java.util.Date; @Entity @Getter @Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor public class Qna { // 연관관계 주인 @@ -42,6 +44,7 @@ public class Qna { private String answer; + private String name; @ManyToOne @JoinColumn(name= "id") private User user; @@ -51,4 +54,5 @@ public class Qna { private Lecture lecture; + } diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/entity/QnaRequestDto.java b/backend/src/main/java/com/edufocus/edufocus/qna/entity/QnaRequestDto.java new file mode 100644 index 0000000..f73eeae --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/qna/entity/QnaRequestDto.java @@ -0,0 +1,24 @@ +package com.edufocus.edufocus.qna.entity; + +import jakarta.persistence.Column; +import lombok.*; + +@Getter +public class QnaRequestDto { + + + private String title; + private String content; + private String answer; + + public static Qna toEntity(QnaRequestDto qnaRequestDto) { + { + + return Qna.builder() + .content(qnaRequestDto.getContent()) + .title(qnaRequestDto.getTitle()) + .answer(qnaRequestDto.getAnswer()) + .build(); + } + } +} diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/entity/QnaResponseDto.java b/backend/src/main/java/com/edufocus/edufocus/qna/entity/QnaResponseDto.java new file mode 100644 index 0000000..3ef0b6a --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/qna/entity/QnaResponseDto.java @@ -0,0 +1,38 @@ +package com.edufocus.edufocus.qna.entity; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.Date; + +@Getter + +@NoArgsConstructor +@AllArgsConstructor +public class QnaResponseDto { + + + private String title; + private String username; + private String content; + private Date createtAt; + private String answer; + public static QnaResponseDto toEntity(Qna qna) + { + return new QnaResponseDto( + + qna.getTitle(), + qna.getUser().getName(), + qna.getContent(), + qna.getCreatedAt(), + qna.getAnswer() + ); + } + + +} + + + diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/repository/QnaRepository.java b/backend/src/main/java/com/edufocus/edufocus/qna/repository/QnaRepository.java index beeba54..d2cbf7f 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/repository/QnaRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/repository/QnaRepository.java @@ -1,6 +1,8 @@ package com.edufocus.edufocus.qna.repository; import com.edufocus.edufocus.qna.entity.Qna; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; @@ -11,8 +13,7 @@ import java.util.List; @Repository public interface QnaRepository extends JpaRepository { - @Query(value = "SELECT * FROM qna WHERE lecture_id = :lectureId", nativeQuery = true) - List findLecture(@Param("lectureId") Long lectureId); - + List findByLectureId(Long lecturerId); + Page findByLectureId(Long lectureId, Pageable pageable); } diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaService.java b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaService.java index 8acf0f5..2c84b6d 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaService.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaService.java @@ -2,6 +2,8 @@ package com.edufocus.edufocus.qna.service; import com.edufocus.edufocus.lecture.entity.Lecture; import com.edufocus.edufocus.qna.entity.Qna; +import com.edufocus.edufocus.qna.entity.QnaRequestDto; +import com.edufocus.edufocus.qna.entity.QnaResponseDto; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -11,9 +13,14 @@ import java.util.List; @Service public interface QnaService { - void createQna(Long id,Qna qna) throws SQLException; - void updateQna(Long id,Qna qna) throws SQLException; + QnaResponseDto createQna(Long id, QnaRequestDto qnaRequestDto, Long lecture_id) throws SQLException; + QnaResponseDto updateQna(Long id,QnaRequestDto qnaRequestDto) throws SQLException; void deleteQna(Long id) throws SQLException; Qna getQna(Long id) throws SQLException; - List getAllQnasByLecture(Long lectureId) throws SQLException; + + List getAllQnasByLecture(Long lectureId,int pageNumber) throws SQLException; + QnaResponseDto createAnswer(Long id,QnaRequestDto qnaRequestDto) throws SQLException; + QnaResponseDto updateAnswer(Long id,QnaRequestDto qnaRequestDto) throws SQLException; + void deleteAnswer(Long id) throws SQLException; + } diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java index 4e6cdc2..e53f585 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java @@ -1,15 +1,28 @@ package com.edufocus.edufocus.qna.service; +import com.edufocus.edufocus.lecture.entity.Lecture; +import com.edufocus.edufocus.lecture.repository.LectureRepository; import com.edufocus.edufocus.qna.entity.Qna; +import com.edufocus.edufocus.qna.entity.QnaRequestDto; +import com.edufocus.edufocus.qna.entity.QnaResponseDto; import com.edufocus.edufocus.qna.repository.QnaRepository; +import com.edufocus.edufocus.user.model.entity.User; +import com.edufocus.edufocus.user.model.repository.UserRepository; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import lombok.Setter; +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.stereotype.Service; +import java.sql.SQLException; +import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; @Service @Transactional @@ -17,25 +30,46 @@ import java.util.Optional; public class QnaServiceImpl implements QnaService{ private final QnaRepository qnaRepository; + private final LectureRepository lectureRepository; + private final UserRepository userRepository; + @Override - public void createQna(Long id,Qna qna) { + public QnaResponseDto createQna(Long id, QnaRequestDto qnaRequestDto, Long lecture_id) { - qna.setId(id); + Lecture lecture = lectureRepository.findById(lecture_id).orElse(null); + + User user = userRepository.findById(id).orElse(null); + + + + Qna qna = QnaRequestDto.toEntity(qnaRequestDto); + qna.setLecture(lecture); + qna.setUser(user); + + qna.setCreatedAt(new Date()); + qnaRepository.save(qna); - + return QnaResponseDto.toEntity(qna); } @Override - public void updateQna(Long id,Qna qna) { + public QnaResponseDto updateQna(Long id,QnaRequestDto qnaRequestDto) { - Optional findQna = qnaRepository.findById(id); + Qna findQna = qnaRepository.findById(id) + .orElseThrow(() -> new RuntimeException("QnA not found")); - qna.setModifiedAt(new Date()); - qnaRepository.save(qna); + findQna.setModifiedAt(new Date()); + findQna.setTitle(qnaRequestDto.getTitle()); + findQna.setContent(qnaRequestDto.getContent()); + + qnaRepository.save(findQna); + + + return QnaResponseDto.toEntity(findQna); } @@ -51,11 +85,46 @@ qnaRepository.deleteById(id); } @Override - public List getAllQnasByLecture(Long lectureId) { + public List getAllQnasByLecture(Long lectureId,int pageSize) + { + + Pageable pageable = PageRequest.of(0, pageSize); + + Page qnaPage = qnaRepository.findByLectureId(lectureId, pageable); - System.out.printf(lectureId+"!!!!!!!!!!!!!!!!!!!!!!"); - return qnaRepository.findLecture(lectureId); + return qnaPage.getContent().stream() + .map(QnaResponseDto::toEntity) + .collect(Collectors.toList()); } + + @Override + public QnaResponseDto createAnswer(Long id, QnaRequestDto qnaRequestDto) throws SQLException { + + Qna findQna = qnaRepository.findById(id).orElse(null); + findQna.setAnswer(qnaRequestDto.getAnswer()); + + qnaRepository.save(findQna); + + return QnaResponseDto.toEntity(findQna); + + } + + @Override + public QnaResponseDto updateAnswer(Long id, QnaRequestDto qnaRequestDto) throws SQLException { + + Qna findQna = qnaRepository.findById(id).orElse(null); + findQna.setAnswer(qnaRequestDto.getAnswer()); + + qnaRepository.save(findQna); + + return QnaResponseDto.toEntity(findQna); + } + + @Override + public void deleteAnswer(Long id) throws SQLException { + + qnaRepository.deleteById(id); + } } From c04142afd1e70f5d0ca99cfc0d2aae60de4363e8 Mon Sep 17 00:00:00 2001 From: kgc9007 Date: Fri, 19 Jul 2024 13:44:32 +0900 Subject: [PATCH 020/197] =?UTF-8?q?feat:=20Lecture=20=EA=B0=95=EC=9D=98=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EC=88=98=EC=A0=95,=20=EB=82=B4=20?= =?UTF-8?q?=EA=B0=95=EC=9D=98=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lecture/controller/LectureController.java | 14 ++++- .../edufocus/lecture/entity/Lecture.java | 8 +-- .../lecture/repository/LectureRepository.java | 6 +- .../lecture/service/LectureService.java | 2 + .../lecture/service/LectureServiceImpl.java | 58 ++++++++++++++----- 5 files changed, 68 insertions(+), 20 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java b/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java index e532525..ec71557 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java @@ -1,5 +1,6 @@ package com.edufocus.edufocus.lecture.controller; +import com.edufocus.edufocus.lecture.entity.Lecture; import com.edufocus.edufocus.lecture.entity.LectureCreateRequest; import com.edufocus.edufocus.lecture.entity.LectureSearchResponse; import com.edufocus.edufocus.lecture.entity.LectureDetailResponse; @@ -24,7 +25,6 @@ public class LectureController { private final LectureService lectureService; private final JWTUtil jwtUtil; - private final UserService userService; @PostMapping public ResponseEntity createLecture(@RequestHeader("Authorization") String accessToken, @RequestBody LectureCreateRequest lectureCreateRequest) { @@ -34,6 +34,18 @@ public class LectureController { return new ResponseEntity<>(HttpStatus.CREATED); } + @PutMapping("/{lectureId}") + public ResponseEntity updateLecture(@RequestHeader("Authorization") String accessToken, @PathVariable Long lectureId, @RequestBody LectureCreateRequest lectureCreateRequest) { + Long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); + + if (!lectureService.updateLecture(userId, lectureId, lectureCreateRequest)) { + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } + + return new ResponseEntity<>(HttpStatus.OK); + } + + @DeleteMapping("/{lectureId}") public ResponseEntity deleteLecture(@RequestBody long userId, @PathVariable long lectureId) { if (!lectureService.deleteLecture(userId, lectureId)) { diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java index d2f220b..24adc42 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java @@ -3,16 +3,16 @@ package com.edufocus.edufocus.lecture.entity; import com.edufocus.edufocus.user.model.entity.User; import jakarta.persistence.*; -import lombok.Getter; -import lombok.Setter; +import lombok.*; -import java.util.ArrayList; import java.util.Date; -import java.util.List; @Entity @Getter @Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor public class Lecture { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/repository/LectureRepository.java b/backend/src/main/java/com/edufocus/edufocus/lecture/repository/LectureRepository.java index 431b96a..a8615d2 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/repository/LectureRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/repository/LectureRepository.java @@ -10,8 +10,10 @@ import java.util.List; @Repository public interface LectureRepository extends JpaRepository { - Lecture findByTitle(@Param("title") String title); + Lecture findByTitle(String title); - List findAllByUserId(@Param("userId") Long userId); + List findAllByUserId(Long userId); + + List findLecturesByUserId(Long userId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java index b359aa0..29eb908 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java @@ -13,6 +13,8 @@ public interface LectureService { void createLecture(long userId, LectureCreateRequest lectureCreateRequest); + boolean updateLecture(long userId, long lectureId, LectureCreateRequest lectureCreateRequest); + boolean deleteLecture(long userId, long LectureId); List findAllLecture(); diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java index 9f9eec8..1e808ac 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java @@ -8,6 +8,7 @@ import com.edufocus.edufocus.lecture.repository.LectureRepository; import com.edufocus.edufocus.registration.entity.Registration; import com.edufocus.edufocus.registration.repository.RegistrationRepository; import com.edufocus.edufocus.user.model.entity.User; +import com.edufocus.edufocus.user.model.entity.UserRole; import com.edufocus.edufocus.user.model.repository.UserRepository; import jakarta.transaction.Transactional; import lombok.Builder; @@ -31,22 +32,54 @@ public class LectureServiceImpl implements LectureService { @Override public void createLecture(long userId, LectureCreateRequest lectureCreateRequest) { - User user = userRepository.findById(userId).get(); - Lecture lecture = new Lecture(); - lecture.setUser(user); - - lecture.setTitle(lectureCreateRequest.getTitle()); - lecture.setDescription(lectureCreateRequest.getDescription()); - lecture.setImage(lectureCreateRequest.getImage()); - lecture.setStartDate(lectureCreateRequest.getStartDate()); - lecture.setEndDate(lectureCreateRequest.getEndDate()); - lecture.setPlan(lectureCreateRequest.getPlan()); + Lecture lecture = new Lecture().builder() + .user(user) + .title(lectureCreateRequest.getTitle()) + .description(lectureCreateRequest.getDescription()) + .image(lectureCreateRequest.getImage()) + .startDate(lectureCreateRequest.getStartDate()) + .endDate(lectureCreateRequest.getEndDate()) + .plan(lectureCreateRequest.getPlan()) + .build(); lectureRepository.save(lecture); } + @Override + public boolean updateLecture(long userId, long lectureId, LectureCreateRequest lectureCreateRequest) { + User user = userRepository.findById(userId).get(); + + Lecture lecture = lectureRepository.findById(lectureId).get(); + + if (lecture.getUser().getId() != user.getId()) { + return false; + } + + if (lectureCreateRequest.getTitle() != null) { + lecture.setTitle(lectureCreateRequest.getTitle()); + } + if (lectureCreateRequest.getDescription() != null) { + lecture.setDescription(lectureCreateRequest.getDescription()); + } + if (lectureCreateRequest.getImage() != null) { + lecture.setImage(lectureCreateRequest.getImage()); + } + if (lectureCreateRequest.getStartDate() != null) { + lecture.setStartDate(lectureCreateRequest.getStartDate()); + } + if (lectureCreateRequest.getEndDate() != null) { + lecture.setEndDate(lectureCreateRequest.getEndDate()); + } + if (lectureCreateRequest.getPlan() != null) { + lecture.setPlan(lectureCreateRequest.getPlan()); + } + + lectureRepository.save(lecture); + return true; + } + @Override public boolean deleteLecture(long userId, long lectureId) { Lecture lecture = lectureRepository.findById(lectureId).get(); @@ -105,9 +138,8 @@ public class LectureServiceImpl implements LectureService { List myLectureList = new ArrayList<>(); - if (user.getRole().equals("ADMIN")) { - List lectureList = lectureRepository.findAllByUserId(userId); - + if (user.getRole() == UserRole.ADMIN) { + List lectureList = lectureRepository.findLecturesByUserId(userId); for (Lecture lecture : lectureList) { LectureSearchResponse lectureSearchResponse = new LectureSearchResponse().builder() .id(lecture.getId()) From 76b54ccf5d94536475151fde70460043d3d9e150 Mon Sep 17 00:00:00 2001 From: yulmam Date: Fri, 19 Jul 2024 14:28:26 +0900 Subject: [PATCH 021/197] =?UTF-8?q?feat=20:=20websocket=20=EC=9D=98?= =?UTF-8?q?=EC=A1=B4=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/build.gradle b/backend/build.gradle index b21a1da..f18f491 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -21,6 +21,7 @@ dependencies { implementation 'io.livekit:livekit-server:0.5.11' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'mysql:mysql-connector-java:8.0.33' + implementation 'org.springframework.boot:spring-boot-starter-websocket' testImplementation 'org.springframework.boot:spring-boot-starter-test' implementation group: 'io.livekit', name: 'livekit-server', version: '0.6.1' implementation 'org.projectlombok:lombok' From 1a556ff91fbc51645c7393891441b3a6514ed4aa Mon Sep 17 00:00:00 2001 From: yulmam Date: Fri, 19 Jul 2024 14:48:23 +0900 Subject: [PATCH 022/197] =?UTF-8?q?feat=20:=20websocket=20conifg=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ws/config/WebSocketConfigurer.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 backend/src/main/java/com/edufocus/edufocus/ws/config/WebSocketConfigurer.java diff --git a/backend/src/main/java/com/edufocus/edufocus/ws/config/WebSocketConfigurer.java b/backend/src/main/java/com/edufocus/edufocus/ws/config/WebSocketConfigurer.java new file mode 100644 index 0000000..eabc28d --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/ws/config/WebSocketConfigurer.java @@ -0,0 +1,25 @@ +package com.edufocus.edufocus.ws.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 WebSocketConfigurer implements WebSocketMessageBrokerConfigurer { + + @Override + public void configureMessageBroker(MessageBrokerRegistry registry) { + registry.enableSimpleBroker("/sub"); + registry.setApplicationDestinationPrefixes("/pub"); + } + + @Override + public void registerStompEndpoints(StompEndpointRegistry registry) { + registry + .addEndpoint("/ws") + .setAllowedOrigins("*"); + } +} \ No newline at end of file From d108709e4d0e53f86a67c77af685a2f7a134fe92 Mon Sep 17 00:00:00 2001 From: Jo Hyeonsoo Date: Fri, 19 Jul 2024 14:49:25 +0900 Subject: [PATCH 023/197] =?UTF-8?q?Revert=20"[Action]=20master=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=EC=82=AC=ED=95=AD=20backend=EC=97=90=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../.github/workflows/change-pr-target.yaml | 28 ------------------- 1 file changed, 28 deletions(-) delete mode 100644 frontend/.github/workflows/change-pr-target.yaml diff --git a/frontend/.github/workflows/change-pr-target.yaml b/frontend/.github/workflows/change-pr-target.yaml deleted file mode 100644 index b7e76f6..0000000 --- a/frontend/.github/workflows/change-pr-target.yaml +++ /dev/null @@ -1,28 +0,0 @@ -name: Change PR target if base branch is master - -on: - pull_request: - types: - - opened - - synchronize - - reopened - branches: - - master - -jobs: - change-pr-target: - runs-on: ubuntu-latest - steps: - - name: Set target environment variable - run: | - if [[ "${GITHUB_HEAD_REF}" == fe* || "${GITHUB_HEAD_REF}" == FE* ]]; then - echo "target=frontend" >> $GITHUB_ENV - elif [[ "${GITHUB_HEAD_REF}" == be* || "${GITHUB_HEAD_REF}" == BE* ]]; then - echo "target=backend" >> $GITHUB_ENV - fi - - - name: Change base branch for PR - if: env.target == 'frontend' || env.target == 'backend' - run: gh pr edit ${{ github.event.pull_request.number }} --base ${{ env.target }} --repo ${{ github.repository }} - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} From f3859e6a655adaad8e10e4ad1302014953319994 Mon Sep 17 00:00:00 2001 From: kgc9007 Date: Fri, 19 Jul 2024 15:57:48 +0900 Subject: [PATCH 024/197] =?UTF-8?q?feat:=20Lecture=20=EA=B0=95=EC=9D=98=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=EC=A1=B0=ED=9A=8C=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=EA=B0=95=EC=9D=98=20=EC=83=81=EC=84=B8=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=EC=8B=9C=20=EC=9C=A0=EC=A0=80=EC=A0=95=EB=B3=B4=EB=A5=BC=20?= =?UTF-8?q?=ED=99=95=EC=9D=B8=ED=95=B4=20=EC=88=98=EA=B0=95=EC=A4=91?= =?UTF-8?q?=EC=9D=B8=EC=A7=80=20=EC=97=AC=EB=B6=80=EB=A5=BC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=EB=A1=9C=20=EC=A0=84=EB=8B=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lecture/controller/LectureController.java | 12 +++++-- .../lecture/entity/LectureDetailResponse.java | 2 ++ .../edufocus/lecture/entity/UserStatus.java | 9 +++++ .../lecture/service/LectureService.java | 2 +- .../lecture/service/LectureServiceImpl.java | 35 +++++++++++++++---- .../repository/RegistrationRepository.java | 2 ++ 6 files changed, 53 insertions(+), 9 deletions(-) create mode 100644 backend/src/main/java/com/edufocus/edufocus/lecture/entity/UserStatus.java diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java b/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java index ec71557..6c4e0f8 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java @@ -67,13 +67,21 @@ public class LectureController { } @GetMapping("/{lectureId}") - public ResponseEntity findById(@PathVariable long lectureId) { - LectureDetailResponse lectureDetailResponse = lectureService.findLectureById(lectureId); + public ResponseEntity findById(@RequestHeader(value = "Authorization", required = false) String accessToken, @PathVariable long lectureId) { + Long userId = null; + + if (accessToken != null) { + userId = Long.parseLong(jwtUtil.getUserId(accessToken)); + } + + LectureDetailResponse lectureDetailResponse = lectureService.findLectureById(userId, lectureId); if (lectureDetailResponse == null) { return new ResponseEntity<>(HttpStatus.NO_CONTENT); } + + return new ResponseEntity<>(lectureDetailResponse, HttpStatus.OK); } diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureDetailResponse.java b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureDetailResponse.java index 08f9558..9c14a49 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureDetailResponse.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureDetailResponse.java @@ -30,4 +30,6 @@ public class LectureDetailResponse { private String plan; private boolean online; + + private String status; } diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/UserStatus.java b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/UserStatus.java new file mode 100644 index 0000000..3fbf6ba --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/UserStatus.java @@ -0,0 +1,9 @@ +package com.edufocus.edufocus.lecture.entity; + +public enum UserStatus { + MANAGED_BY_ME, // 내가 관리하는 강의 - 강사 + MANAGED_BY_OTHERS, // 내가 관리하지 않은 강의 - 강사 + ENROLLED, // 내가 수강 중인 강의 - 학생 + PENDING, // 내가 수강신청하고 승인 대기 중인 강의 - 학생 + NOT_ENROLLED // 내가 수강신청하지 않은 강의 - 학생/비로그인 +} diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java index 29eb908..e82bd25 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java @@ -19,7 +19,7 @@ public interface LectureService { List findAllLecture(); - LectureDetailResponse findLectureById(long lectureId); + LectureDetailResponse findLectureById(Long userId, long lectureId); List findMyLecture(long userId); diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java index 1e808ac..1971488 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java @@ -1,11 +1,9 @@ package com.edufocus.edufocus.lecture.service; -import com.edufocus.edufocus.lecture.entity.Lecture; -import com.edufocus.edufocus.lecture.entity.LectureCreateRequest; -import com.edufocus.edufocus.lecture.entity.LectureSearchResponse; -import com.edufocus.edufocus.lecture.entity.LectureDetailResponse; +import com.edufocus.edufocus.lecture.entity.*; import com.edufocus.edufocus.lecture.repository.LectureRepository; import com.edufocus.edufocus.registration.entity.Registration; +import com.edufocus.edufocus.registration.entity.RegistrationStatus; import com.edufocus.edufocus.registration.repository.RegistrationRepository; import com.edufocus.edufocus.user.model.entity.User; import com.edufocus.edufocus.user.model.entity.UserRole; @@ -110,14 +108,38 @@ public class LectureServiceImpl implements LectureService { } @Override - public LectureDetailResponse findLectureById(long lectureId) { - + public LectureDetailResponse findLectureById(Long userId, long lectureId) { Lecture lecture = lectureRepository.findById(lectureId).get(); if (lecture == null) { return null; } + String userStatus; + if (userId == null) { + userStatus = String.valueOf(UserStatus.NOT_ENROLLED); + } else { + User user = userRepository.findById(userId).get(); + + if (user.getRole() == UserRole.ADMIN) { + if (lecture.getUser().getId() == user.getId()) { + userStatus = String.valueOf(UserStatus.MANAGED_BY_ME); + } else{ + userStatus = String.valueOf(UserStatus.MANAGED_BY_OTHERS); + } + } else { + Registration registration = registrationRepository.findByUserIdAndLectureId(userId, lectureId); + + if (registration == null) { + userStatus = String.valueOf(UserStatus.NOT_ENROLLED); + } else if (registration.getStatus() == RegistrationStatus.ACCEPTED) { + userStatus = String.valueOf(UserStatus.ENROLLED); + } else { + userStatus = String.valueOf(UserStatus.PENDING); + } + } + } + LectureDetailResponse lectureDetailResponse = new LectureDetailResponse().builder() .id(lecture.getId()) .title(lecture.getTitle()) @@ -128,6 +150,7 @@ public class LectureServiceImpl implements LectureService { .plan(lecture.getPlan()) .online(lecture.isOnline()) .teacherName(lecture.getUser().getName()) + .status(userStatus) .build(); return lectureDetailResponse; diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/repository/RegistrationRepository.java b/backend/src/main/java/com/edufocus/edufocus/registration/repository/RegistrationRepository.java index 34358a2..251acaf 100644 --- a/backend/src/main/java/com/edufocus/edufocus/registration/repository/RegistrationRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/registration/repository/RegistrationRepository.java @@ -10,4 +10,6 @@ import java.util.List; @Repository public interface RegistrationRepository extends JpaRepository { List findAllByUserId(@Param("userId") Long userId); + + Registration findByUserIdAndLectureId(Long userId, Long lectureId); } From 65d43acb91c4330b2f185c9c951f99fe5670ccf4 Mon Sep 17 00:00:00 2001 From: kgc9007 Date: Mon, 22 Jul 2024 13:06:51 +0900 Subject: [PATCH 025/197] =?UTF-8?q?feat:=20Quiz=20=ED=80=B4=EC=A6=88=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D,=20=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../quiz/controller/QuizController.java | 25 +++++++++++++------ .../quiz/entity/MutipleQuizCreateRequest.java | 20 --------------- .../edufocus/edufocus/quiz/entity/Quiz.java | 9 +++++-- .../quiz/entity/QuizCreateRequest.java | 12 ++++++--- .../edufocus/quiz/entity/QuizSet.java | 4 +++ .../quiz/repository/QuizRepository.java | 2 ++ .../edufocus/quiz/service/QuizService.java | 3 ++- .../quiz/service/QuizServiceImpl.java | 25 ++++++++++++------- .../edufocus/quiz/service/QuizSetService.java | 1 + .../quiz/service/QuizSetServiceImpl.java | 10 ++++++-- 10 files changed, 67 insertions(+), 44 deletions(-) delete mode 100644 backend/src/main/java/com/edufocus/edufocus/quiz/entity/MutipleQuizCreateRequest.java diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java b/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java index 3c18199..57e22e0 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java @@ -1,17 +1,19 @@ package com.edufocus.edufocus.quiz.controller; import com.edufocus.edufocus.quiz.entity.*; +import com.edufocus.edufocus.quiz.repository.QuizRepository; import com.edufocus.edufocus.quiz.service.QuizService; import com.edufocus.edufocus.quiz.service.QuizSetService; import com.edufocus.edufocus.user.model.service.UserService; +import com.edufocus.edufocus.user.util.JWTUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -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; +import org.springframework.web.bind.annotation.*; + +import java.util.ArrayList; +import java.util.List; @RestController @RequestMapping("/quiz") @@ -25,10 +27,12 @@ public class QuizController { private final UserService userService; - @PostMapping - public ResponseEntity createQuizSet(@RequestBody QuizSetCreateRequest quizSetCreateRequest) { + private final JWTUtil jwtUtil; + private final QuizRepository quizRepository; - Long userId = 1L; + @PostMapping + public ResponseEntity createQuizSet(@RequestHeader("Authorization") String accessToken, @RequestBody QuizSetCreateRequest quizSetCreateRequest) { + Long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); String title = quizSetCreateRequest.getTitle(); String image = quizSetCreateRequest.getImage(); @@ -43,4 +47,11 @@ public class QuizController { return new ResponseEntity<>(HttpStatus.CREATED); } + + @GetMapping("/{quizsetId}") + public ResponseEntity getQuizzes(@PathVariable Long quizsetId) { + QuizSet quizSet = quizSetService.findQuizSet(quizsetId); + + return new ResponseEntity<>(quizSet, HttpStatus.OK); + } } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/MutipleQuizCreateRequest.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/MutipleQuizCreateRequest.java deleted file mode 100644 index 20dbf54..0000000 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/MutipleQuizCreateRequest.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.edufocus.edufocus.quiz.entity; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.ToString; - -@Getter -@NoArgsConstructor -@AllArgsConstructor -public class MutipleQuizCreateRequest extends QuizCreateRequest { - - private String choice1; - - private String choice2; - - private String choice3; - - private String choice4; -} diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Quiz.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Quiz.java index 4ea9b43..a113b12 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Quiz.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Quiz.java @@ -1,12 +1,16 @@ package com.edufocus.edufocus.quiz.entity; +import com.fasterxml.jackson.annotation.JsonBackReference; +import com.fasterxml.jackson.annotation.JsonManagedReference; import jakarta.persistence.*; -import lombok.Getter; -import lombok.Setter; +import lombok.*; @Entity @Getter @Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor public class Quiz { @Id @@ -15,6 +19,7 @@ public class Quiz { @ManyToOne @JoinColumn(name = "quizset_id") + @JsonBackReference private QuizSet quizSet; @Column diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizCreateRequest.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizCreateRequest.java index d5c38da..eb58041 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizCreateRequest.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizCreateRequest.java @@ -3,7 +3,6 @@ package com.edufocus.edufocus.quiz.entity; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; -import lombok.ToString; @Getter @NoArgsConstructor @@ -14,10 +13,17 @@ public class QuizCreateRequest { private String description; - private boolean isSingle; - private String answer; + private boolean isSingle; + private String image; + private String choice1; + + private String choice2; + + private String choice3; + + private String choice4; } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSet.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSet.java index b067277..89a2b4d 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSet.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSet.java @@ -1,6 +1,8 @@ package com.edufocus.edufocus.quiz.entity; import com.edufocus.edufocus.user.model.entity.User; +import com.fasterxml.jackson.annotation.JsonBackReference; +import com.fasterxml.jackson.annotation.JsonManagedReference; import jakarta.persistence.*; import lombok.Getter; import lombok.Setter; @@ -19,6 +21,7 @@ public class QuizSet { @ManyToOne @JoinColumn(name = "user_id") + @JsonBackReference private User user; @Column @@ -28,6 +31,7 @@ public class QuizSet { private String image; @OneToMany(mappedBy = "quizSet") + @JsonManagedReference private List quizzes = new ArrayList(); public void addQuiz(Quiz quiz) { diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/repository/QuizRepository.java b/backend/src/main/java/com/edufocus/edufocus/quiz/repository/QuizRepository.java index 7428689..9e7d345 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/repository/QuizRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/repository/QuizRepository.java @@ -3,5 +3,7 @@ package com.edufocus.edufocus.quiz.repository; import com.edufocus.edufocus.quiz.entity.Quiz; import org.springframework.data.jpa.repository.JpaRepository; + public interface QuizRepository extends JpaRepository { + } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizService.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizService.java index 3174e89..8b0725f 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizService.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizService.java @@ -1,9 +1,10 @@ package com.edufocus.edufocus.quiz.service; -import com.edufocus.edufocus.quiz.entity.MutipleQuizCreateRequest; import com.edufocus.edufocus.quiz.entity.QuizCreateRequest; import org.springframework.stereotype.Service; +import java.util.List; + @Service public interface QuizService { diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizServiceImpl.java index 5f34010..b4e0ac9 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizServiceImpl.java @@ -1,6 +1,5 @@ package com.edufocus.edufocus.quiz.service; -import com.edufocus.edufocus.quiz.entity.MutipleQuizCreateRequest; import com.edufocus.edufocus.quiz.entity.Quiz; import com.edufocus.edufocus.quiz.entity.QuizCreateRequest; import com.edufocus.edufocus.quiz.entity.QuizSet; @@ -10,6 +9,8 @@ import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import java.util.List; + @Service @Transactional @RequiredArgsConstructor @@ -23,15 +24,20 @@ public class QuizServiceImpl implements QuizService { public void createQuiz(long quizSetId, QuizCreateRequest quizCreateRequest) { QuizSet quizSet = quizSetRepository.findById(quizSetId).get(); - Quiz quiz = new Quiz(); + Quiz quiz = new Quiz().builder() + .title(quizCreateRequest.getTitle()) + .description(quizCreateRequest.getDescription()) + .answer(quizCreateRequest.getAnswer()) + .image(quizCreateRequest.getImage()) + .quizSet(quizSet) + .build(); - quiz.setTitle(quizCreateRequest.getTitle()); - quiz.setDescription(quizCreateRequest.getDescription()); - quiz.setAnswer(quizCreateRequest.getAnswer()); - quiz.setImage(quizCreateRequest.getImage()); - - - quiz.setQuizSet(quizSet); + if (!quiz.isSingle()) { + quiz.setChoice1(quizCreateRequest.getChoice1()); + quiz.setChoice2(quizCreateRequest.getChoice2()); + quiz.setChoice3(quizCreateRequest.getChoice3()); + quiz.setChoice4(quizCreateRequest.getChoice4()); + } quizRepository.save(quiz); } @@ -46,4 +52,5 @@ public class QuizServiceImpl implements QuizService { quizRepository.deleteById(quizId); return true; } + } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetService.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetService.java index 748283b..a62a979 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetService.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetService.java @@ -13,4 +13,5 @@ public interface QuizSetService { void deleteQuizSet(long quizSetId); + QuizSet findQuizSet(long quizSetId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java index a167cca..aefdd03 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java @@ -1,7 +1,7 @@ package com.edufocus.edufocus.quiz.service; -import com.edufocus.edufocus.quiz.entity.QuizSet; -import com.edufocus.edufocus.quiz.entity.SetCreateRequest; +import com.edufocus.edufocus.quiz.entity.*; +import com.edufocus.edufocus.quiz.repository.QuizRepository; import com.edufocus.edufocus.quiz.repository.QuizSetRepository; import com.edufocus.edufocus.user.model.entity.User; import com.edufocus.edufocus.user.model.repository.UserRepository; @@ -17,6 +17,7 @@ public class QuizSetServiceImpl implements QuizSetService { private final QuizSetRepository quizSetRepository; private final UserRepository userRepository; + private final QuizRepository quizRepository; @Override @@ -42,4 +43,9 @@ public class QuizSetServiceImpl implements QuizSetService { public void deleteQuizSet(long quizSetId) { quizSetRepository.deleteById(quizSetId); } + + @Override + public QuizSet findQuizSet(long quizSetId) { + return quizSetRepository.findById(quizSetId).get(); + } } From d4b7e5e14ceebccfc793b19ae57625f2b113edcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Mon, 22 Jul 2024 16:11:13 +0900 Subject: [PATCH 026/197] =?UTF-8?q?feat:=20user=20report,=20answer=20?= =?UTF-8?q?=EC=B1=84=EC=A0=90=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../report/controller/ReportController.java | 36 +++++++ .../edufocus/report/entity/Answer.java | 33 +++++++ .../edufocus/report/entity/AnswerInput.java | 11 +++ .../report/entity/QuizSubmissionDto.java | 6 ++ .../edufocus/report/entity/Report.java | 35 +++++++ .../edufocus/report/entity/ReportRequset.java | 25 +++++ .../report/repository/AnswerRepository.java | 7 ++ .../report/repository/ReportRepository.java | 9 ++ .../report/service/AnswerService.java | 8 ++ .../report/service/AnswerServiceImpl.java | 22 +++++ .../report/service/ReportService.java | 13 +++ .../report/service/ReportServiceImpl.java | 99 +++++++++++++++++++ 12 files changed, 304 insertions(+) create mode 100644 backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/report/entity/Answer.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/report/entity/AnswerInput.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/report/entity/QuizSubmissionDto.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/report/entity/Report.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/report/entity/ReportRequset.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/report/repository/AnswerRepository.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/report/repository/ReportRepository.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/report/service/AnswerService.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/report/service/AnswerServiceImpl.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/report/service/ReportService.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java diff --git a/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java b/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java new file mode 100644 index 0000000..20f82e1 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java @@ -0,0 +1,36 @@ +package com.edufocus.edufocus.report.controller; + +import com.edufocus.edufocus.report.entity.Report; +import com.edufocus.edufocus.report.entity.ReportRequset; +import com.edufocus.edufocus.report.service.ReportService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +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; + +import java.sql.SQLException; + +@RestController +@RequestMapping("/report") +@Slf4j +@RequiredArgsConstructor +public class ReportController{ + + + private final ReportService reportService; + + + + + @PostMapping("/submit") + public ResponseEntity submit(@RequestBody ReportRequset reportRequset) throws SQLException { + Report report = reportService.grading(reportRequset); + return new ResponseEntity<>(report,HttpStatus.CREATED); + + } + +} diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/Answer.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/Answer.java new file mode 100644 index 0000000..3204f24 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/Answer.java @@ -0,0 +1,33 @@ +package com.edufocus.edufocus.report.entity; + + +import com.edufocus.edufocus.quiz.entity.Quiz; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class Answer { + + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private long id; + + private String userAnswer; + private boolean isCorrect; + + @ManyToOne + @JoinColumn(name= "report_id") + private Report report; + + @ManyToOne + @JoinColumn(name= "quiz_id") + private Quiz quiz; + + +} diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/AnswerInput.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/AnswerInput.java new file mode 100644 index 0000000..c237616 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/AnswerInput.java @@ -0,0 +1,11 @@ +package com.edufocus.edufocus.report.entity; + +import lombok.Getter; + +@Getter +public class AnswerInput { + + Long answerinputID; + String answer; + +} diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/QuizSubmissionDto.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/QuizSubmissionDto.java new file mode 100644 index 0000000..489d896 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/QuizSubmissionDto.java @@ -0,0 +1,6 @@ +package com.edufocus.edufocus.report.entity; + +public class QuizSubmissionDto { + private Long quizSetId; + private Long userId; +} diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/Report.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/Report.java new file mode 100644 index 0000000..6a011d5 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/Report.java @@ -0,0 +1,35 @@ +package com.edufocus.edufocus.report.entity; + +import com.edufocus.edufocus.quiz.entity.QuizSet; +import com.edufocus.edufocus.user.model.entity.User; +import jakarta.persistence.*; +import lombok.*; + +import java.util.Date; + +@Entity +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class Report { + + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private int allCount; + private int correctCount; + private Date testAt; + + @ManyToOne + @JoinColumn(name= "user_id") + private User user; + + @ManyToOne + @JoinColumn(name= "quizset_id") + private QuizSet quizSet; + +} diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/ReportRequset.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/ReportRequset.java new file mode 100644 index 0000000..788f87f --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/ReportRequset.java @@ -0,0 +1,25 @@ +package com.edufocus.edufocus.report.entity; + +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +public class ReportRequset { + + + private Long userId; + private Long quizsetId; + List answerInputList; + + +// List a +// userID : +// quizSetId : +// answerList : [ +// { ans1 : 1}, +// {ans2 : 2} +// ] +} diff --git a/backend/src/main/java/com/edufocus/edufocus/report/repository/AnswerRepository.java b/backend/src/main/java/com/edufocus/edufocus/report/repository/AnswerRepository.java new file mode 100644 index 0000000..12f76ae --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/report/repository/AnswerRepository.java @@ -0,0 +1,7 @@ +package com.edufocus.edufocus.report.repository; + +import com.edufocus.edufocus.report.entity.Answer; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface AnswerRepository extends JpaRepository { +} diff --git a/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportRepository.java b/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportRepository.java new file mode 100644 index 0000000..dd5eca7 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportRepository.java @@ -0,0 +1,9 @@ +package com.edufocus.edufocus.report.repository; + +import com.edufocus.edufocus.report.entity.Report; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface ReportRepository extends JpaRepository { +} diff --git a/backend/src/main/java/com/edufocus/edufocus/report/service/AnswerService.java b/backend/src/main/java/com/edufocus/edufocus/report/service/AnswerService.java new file mode 100644 index 0000000..2c4c65a --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/report/service/AnswerService.java @@ -0,0 +1,8 @@ +package com.edufocus.edufocus.report.service; + +import com.edufocus.edufocus.report.entity.Answer; + +public interface AnswerService { + + void save(Answer answer); +} diff --git a/backend/src/main/java/com/edufocus/edufocus/report/service/AnswerServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/report/service/AnswerServiceImpl.java new file mode 100644 index 0000000..b838846 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/report/service/AnswerServiceImpl.java @@ -0,0 +1,22 @@ +package com.edufocus.edufocus.report.service; + +import com.edufocus.edufocus.report.entity.Answer; +import com.edufocus.edufocus.report.repository.AnswerRepository; +import jakarta.transaction.Transactional; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@Transactional +@RequiredArgsConstructor +public class AnswerServiceImpl implements AnswerService{ + + private final AnswerRepository answerRepository; + + @Override + public void save(Answer answer) { + + answerRepository.save(answer); + + } +} diff --git a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportService.java b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportService.java new file mode 100644 index 0000000..89de34f --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportService.java @@ -0,0 +1,13 @@ +package com.edufocus.edufocus.report.service; + +import com.edufocus.edufocus.report.entity.Report; +import com.edufocus.edufocus.report.entity.ReportRequset; +import org.springframework.stereotype.Service; + +import java.sql.SQLException; + +@Service +public interface ReportService { + Report grading(ReportRequset reportRequset) throws SQLException; + +} diff --git a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java new file mode 100644 index 0000000..87f0af0 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java @@ -0,0 +1,99 @@ +package com.edufocus.edufocus.report.service; + +import com.edufocus.edufocus.quiz.entity.Quiz; +import com.edufocus.edufocus.quiz.entity.QuizSet; +import com.edufocus.edufocus.quiz.repository.QuizRepository; +import com.edufocus.edufocus.quiz.service.QuizService; +import com.edufocus.edufocus.quiz.service.QuizSetService; +import com.edufocus.edufocus.report.entity.Answer; +import com.edufocus.edufocus.report.entity.AnswerInput; +import com.edufocus.edufocus.report.entity.Report; +import com.edufocus.edufocus.report.entity.ReportRequset; +import com.edufocus.edufocus.report.repository.ReportRepository; +import com.edufocus.edufocus.user.model.entity.User; +import com.edufocus.edufocus.user.model.repository.UserRepository; +import jakarta.transaction.Transactional; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.sql.SQLException; +import java.util.Date; +import java.util.List; + +@Service +@Transactional +@RequiredArgsConstructor +public class ReportServiceImpl implements ReportService { + + private final QuizSetService quizSetService; + private final QuizService quizService; + + private final ReportRepository reportRepository; + private final QuizRepository quizRepository; + + private final AnswerService answerService; + private final UserRepository userRepository; + + + @Override + public Report grading(ReportRequset reportRequset) throws SQLException { + + + QuizSet quizSet = quizSetService.findQuizSet(reportRequset.getQuizsetId()); + + List quizList = quizSet.getQuizzes(); + List answerInputList = reportRequset.getAnswerInputList(); + + Report report = new Report(); + + Long reportNum = report.getId(); + int allCount= quizList.size(); + int correctCount =0 ; + + User testuser= userRepository.findById(reportRequset.getUserId()).orElse(null); + + for (Quiz quiz : quizList) { + for (AnswerInput answerInput : answerInputList) { + if (quiz.getId().equals(answerInput.getAnswerinputID())) { + + if(quiz.getAnswer().equals(answerInput.getAnswer())) { + correctCount++; + + Answer answer = Answer.builder() + .userAnswer(answerInput.getAnswer()) + .isCorrect(true) + .report(report) + .quiz(quiz) + .build(); + + } + else{ + Answer answer = Answer.builder() + .userAnswer(answerInput.getAnswer()) + .isCorrect(false) + .report(report) + .quiz(quiz) + .build(); + + + + } + + } + + } + } + + report = Report.builder() + .user(testuser) + .quizSet(quizSet) + .allCount(allCount) + .correctCount(correctCount) + .testAt(new Date()).build(); + + reportRepository.save(report); + return report; + + + } +} From 588758c581ffd040ba9d4f3d237ebd1ba38888e3 Mon Sep 17 00:00:00 2001 From: kgc9007 Date: Mon, 22 Jul 2024 17:24:51 +0900 Subject: [PATCH 027/197] =?UTF-8?q?refactor:=20Lecture=20=EC=9D=BC?= =?UTF-8?q?=EB=B6=80=20=EC=BD=94=EB=93=9C=20=EB=A6=AC=ED=8C=A9=ED=86=A0?= =?UTF-8?q?=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lecture/controller/LectureController.java | 40 ++++++++++++----- .../lecture/service/LectureService.java | 2 + .../lecture/service/LectureServiceImpl.java | 45 +++++++++++-------- 3 files changed, 58 insertions(+), 29 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java b/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java index 6c4e0f8..5ba43cd 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java @@ -30,8 +30,15 @@ public class LectureController { public ResponseEntity createLecture(@RequestHeader("Authorization") String accessToken, @RequestBody LectureCreateRequest lectureCreateRequest) { Long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); + Lecture lecture = lectureService.findLectureByTitle(lectureCreateRequest.getTitle()); + if (lecture != null) { + String msg = new String("Duplicated Lecture"); + return new ResponseEntity<>(msg, HttpStatus.CONFLICT); + } + lectureService.createLecture(userId, lectureCreateRequest); - return new ResponseEntity<>(HttpStatus.CREATED); + String msg = new String("Lecture registered successfully"); + return new ResponseEntity<>(msg, HttpStatus.CREATED); } @PutMapping("/{lectureId}") @@ -39,17 +46,21 @@ public class LectureController { Long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); if (!lectureService.updateLecture(userId, lectureId, lectureCreateRequest)) { - return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + String msg = new String("Can't update Lecture"); + return new ResponseEntity<>(msg, HttpStatus.UNAUTHORIZED); } - - return new ResponseEntity<>(HttpStatus.OK); + String msg = new String("Lecture updated successfully"); + return new ResponseEntity<>(msg, HttpStatus.OK); } @DeleteMapping("/{lectureId}") - public ResponseEntity deleteLecture(@RequestBody long userId, @PathVariable long lectureId) { + public ResponseEntity deleteLecture(@RequestHeader("Authorization") String accessToken, @PathVariable long lectureId) { + Long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); + if (!lectureService.deleteLecture(userId, lectureId)) { - return new ResponseEntity<>(HttpStatus.NOT_FOUND); + String msg = new String("Can't delete Lecture"); + return new ResponseEntity<>(msg, HttpStatus.UNAUTHORIZED); } return new ResponseEntity<>(HttpStatus.NO_CONTENT); @@ -60,7 +71,8 @@ public class LectureController { List lectures = lectureService.findAllLecture(); if (lectures.isEmpty()) { - return new ResponseEntity<>(HttpStatus.NO_CONTENT); + String msg = new String("No lectures found"); + return new ResponseEntity<>(msg, HttpStatus.OK); } return new ResponseEntity<>(lectures, HttpStatus.OK); @@ -77,22 +89,28 @@ public class LectureController { LectureDetailResponse lectureDetailResponse = lectureService.findLectureById(userId, lectureId); if (lectureDetailResponse == null) { - return new ResponseEntity<>(HttpStatus.NO_CONTENT); + String msg = new String("Can't find Lecture"); + return new ResponseEntity<>(msg, HttpStatus.OK); } - return new ResponseEntity<>(lectureDetailResponse, HttpStatus.OK); } @GetMapping("/mylecture") - public ResponseEntity findMyLecture(@RequestHeader("Authorization") String accessToken) { + public ResponseEntity findMyLecture(@RequestHeader(value = "Authorization", required = false) String accessToken) { + if (accessToken == null) { + String msg = new String("Not logged in"); + return new ResponseEntity<>(msg, HttpStatus.OK); + } + Long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); List myLectures = lectureService.findMyLecture(userId); if (myLectures.isEmpty()) { - return new ResponseEntity<>(HttpStatus.NO_CONTENT); + String msg = new String("No lectures found"); + return new ResponseEntity<>(msg, HttpStatus.OK); } return new ResponseEntity<>(myLectures, HttpStatus.OK); diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java index e82bd25..88fc735 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java @@ -1,5 +1,6 @@ package com.edufocus.edufocus.lecture.service; +import com.edufocus.edufocus.lecture.entity.Lecture; import com.edufocus.edufocus.lecture.entity.LectureCreateRequest; import com.edufocus.edufocus.lecture.entity.LectureSearchResponse; import com.edufocus.edufocus.lecture.entity.LectureDetailResponse; @@ -23,4 +24,5 @@ public interface LectureService { List findMyLecture(long userId); + Lecture findLectureByTitle(String title); } diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java index 1971488..56b33cf 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java @@ -15,6 +15,7 @@ import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; +import java.util.Optional; @Builder @Service @@ -47,11 +48,9 @@ public class LectureServiceImpl implements LectureService { @Override public boolean updateLecture(long userId, long lectureId, LectureCreateRequest lectureCreateRequest) { - User user = userRepository.findById(userId).get(); - Lecture lecture = lectureRepository.findById(lectureId).get(); - if (lecture.getUser().getId() != user.getId()) { + if (lecture.getUser().getId() != userId) { return false; } @@ -80,9 +79,14 @@ public class LectureServiceImpl implements LectureService { @Override public boolean deleteLecture(long userId, long lectureId) { - Lecture lecture = lectureRepository.findById(lectureId).get(); + Optional lecture = lectureRepository.findById(lectureId); - if (lecture.getUser().getId() != userId) { + if (lecture.isEmpty()) { + return false; + } + lecture = Optional.of(lecture.get()); + + if (lecture.get().getUser().getId() != userId) { return false; } @@ -109,11 +113,12 @@ public class LectureServiceImpl implements LectureService { @Override public LectureDetailResponse findLectureById(Long userId, long lectureId) { - Lecture lecture = lectureRepository.findById(lectureId).get(); + Optional lecture = lectureRepository.findById(lectureId); - if (lecture == null) { + if (lecture.isEmpty()) { return null; } + lecture = Optional.of(lecture.get()); String userStatus; if (userId == null) { @@ -122,9 +127,9 @@ public class LectureServiceImpl implements LectureService { User user = userRepository.findById(userId).get(); if (user.getRole() == UserRole.ADMIN) { - if (lecture.getUser().getId() == user.getId()) { + if (lecture.get().getUser().getId() == user.getId()) { userStatus = String.valueOf(UserStatus.MANAGED_BY_ME); - } else{ + } else { userStatus = String.valueOf(UserStatus.MANAGED_BY_OTHERS); } } else { @@ -141,15 +146,15 @@ public class LectureServiceImpl implements LectureService { } LectureDetailResponse lectureDetailResponse = new LectureDetailResponse().builder() - .id(lecture.getId()) - .title(lecture.getTitle()) - .description(lecture.getDescription()) - .image(lecture.getImage()) - .startDate(lecture.getStartDate()) - .endDate(lecture.getEndDate()) - .plan(lecture.getPlan()) - .online(lecture.isOnline()) - .teacherName(lecture.getUser().getName()) + .id(lecture.get().getId()) + .title(lecture.get().getTitle()) + .description(lecture.get().getDescription()) + .image(lecture.get().getImage()) + .startDate(lecture.get().getStartDate()) + .endDate(lecture.get().getEndDate()) + .plan(lecture.get().getPlan()) + .online(lecture.get().isOnline()) + .teacherName(lecture.get().getUser().getName()) .status(userStatus) .build(); @@ -189,4 +194,8 @@ public class LectureServiceImpl implements LectureService { return myLectureList; } + @Override + public Lecture findLectureByTitle(String title) { + return lectureRepository.findByTitle(title); + } } From 4b483eea2df2adcd53fa8a5312d067bc65bda6f3 Mon Sep 17 00:00:00 2001 From: yulmam Date: Mon, 22 Jul 2024 17:32:23 +0900 Subject: [PATCH 028/197] =?UTF-8?q?feat=20:=20chatController=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../board/controller/BoardController.java | 18 +++-- .../board/service/BoardServiceImpl.java | 17 ++-- .../ws/controller/ChatController.java | 81 +++++++++++++++++++ .../edufocus/ws/entity/dto/HelloDto.java | 13 +++ .../edufocus/ws/entity/dto/MessageDto.java | 11 +++ .../edufocus/ws/entity/dto/QuizDto.java | 13 +++ .../ws/entity/dto/ResponseChatUserDto.java | 6 ++ .../edufocus/ws/entity/vo/ChatUser.java | 25 ++++++ .../edufocus/ws/service/ChatService.java | 10 +++ .../edufocus/ws/service/ChatServiceImpl.java | 9 +++ 10 files changed, 187 insertions(+), 16 deletions(-) create mode 100644 backend/src/main/java/com/edufocus/edufocus/ws/controller/ChatController.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/HelloDto.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/MessageDto.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/QuizDto.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/ResponseChatUserDto.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/ws/entity/vo/ChatUser.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/ws/service/ChatService.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/ws/service/ChatServiceImpl.java diff --git a/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java b/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java index d25d940..a1ead74 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java @@ -30,22 +30,18 @@ public class BoardController { } @GetMapping() - public ResponseEntity searchBoards( + public ResponseEntity> searchBoards( @RequestParam(value = "category", required = false, defaultValue = "announcement") String category, - @RequestParam(value = "lectureId", required = true) long lectureId, + @RequestParam(value = "lectureId") long lectureId, @RequestParam(value = "pageNo", required = false, defaultValue = "0") int pageNo ){ List boardSummaries = boardService.findBoards(pageNo, category, lectureId); - if(boardSummaries.isEmpty()){ - return new ResponseEntity<>(HttpStatus.NO_CONTENT); - } - return new ResponseEntity<>(boardSummaries, HttpStatus.OK); } @GetMapping(value = "/{boardId}") - public ResponseEntity getBoardDetail( + public ResponseEntity getBoardDetail( @PathVariable int boardId ){ ResponseBoardDetailDto responseBoardDetailDto = boardService.findBoardDetail(boardId); @@ -87,7 +83,7 @@ public class BoardController { } @GetMapping(value = "/comment/{boardId}") - public ResponseEntity getComments( + public ResponseEntity> getComments( @PathVariable int boardId ){ List comments = boardService.findComments(boardId); @@ -127,4 +123,10 @@ public class BoardController { return new ResponseEntity<>(HttpStatus.OK); } + + + @ExceptionHandler() + public ResponseEntity NoContentException(Exception exception){ + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } } diff --git a/backend/src/main/java/com/edufocus/edufocus/board/service/BoardServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/board/service/BoardServiceImpl.java index 29c5006..10426fb 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/service/BoardServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/service/BoardServiceImpl.java @@ -16,6 +16,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; +import java.util.NoSuchElementException; import java.util.stream.Collectors; @Service @@ -49,14 +50,14 @@ public class BoardServiceImpl implements BoardService { @Transactional public ResponseBoardDetailDto findBoardDetail(long boardId) { return boardRepository.findById(boardId) - .orElseThrow() + .orElseThrow(NoSuchElementException::new) .makeDetailDto(); } @Transactional public void createBoard(long userId, RequestBoardDto requestBoardDto) { User user = userRepository.findById(userId).orElseThrow(); - Lecture lecture = lectureRepository.findById(requestBoardDto.getLectureId()).get(); + Lecture lecture = lectureRepository.findById(requestBoardDto.getLectureId()).orElseThrow(IllegalArgumentException::new); Board board = Board.builder() .title(requestBoardDto.getTitle()) @@ -71,7 +72,7 @@ public class BoardServiceImpl implements BoardService { @Transactional public void updateBoard(long boardId, RequestBoardUpdateDto requestBoardUpdateDto) { - Board board = boardRepository.findById(boardId).get(); + Board board = boardRepository.findById(boardId).orElseThrow(IllegalArgumentException::new); board.setTitle(requestBoardUpdateDto.getTitle()); board.setContent(requestBoardUpdateDto.getContent()); @@ -82,7 +83,7 @@ public class BoardServiceImpl implements BoardService { @Transactional public void deleteBoard(long boardId) { - Board board = boardRepository.findById(boardId).get(); + Board board = boardRepository.findById(boardId).orElseThrow(IllegalArgumentException::new); boardRepository.delete(board); } @@ -96,8 +97,8 @@ public class BoardServiceImpl implements BoardService { @Transactional public void createComment(long userId, long boardId, RequestCommentDto requestCommentDto) { - User user = userRepository.findById(userId).get(); - Board board = boardRepository.findById(boardId).get(); + User user = userRepository.findById(userId).orElseThrow(IllegalArgumentException::new); + Board board = boardRepository.findById(boardId).orElseThrow(IllegalArgumentException::new); Comment comment = Comment.builder() .content(requestCommentDto.getContent()) @@ -112,7 +113,7 @@ public class BoardServiceImpl implements BoardService { @Transactional public void updateComment(long commentId, RequestCommentDto requestCommentDto) { - Comment comment = commentRepository.findById(commentId).get(); + Comment comment = commentRepository.findById(commentId).orElseThrow(IllegalArgumentException::new); comment.setContent(requestCommentDto.getContent()); @@ -121,7 +122,7 @@ public class BoardServiceImpl implements BoardService { @Transactional public void deleteComment(long commentId) { - Comment comment = commentRepository.findById(commentId).get(); + Comment comment = commentRepository.findById(commentId).orElseThrow(NoSuchElementException::new); commentRepository.delete(comment); } diff --git a/backend/src/main/java/com/edufocus/edufocus/ws/controller/ChatController.java b/backend/src/main/java/com/edufocus/edufocus/ws/controller/ChatController.java new file mode 100644 index 0000000..30af11a --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/ws/controller/ChatController.java @@ -0,0 +1,81 @@ +package com.edufocus.edufocus.ws.controller; + + +import com.edufocus.edufocus.user.util.JWTUtil; +import com.edufocus.edufocus.ws.entity.dto.HelloDto; +import com.edufocus.edufocus.ws.entity.dto.MessageDto; +import com.edufocus.edufocus.ws.entity.dto.QuizDto; +import com.edufocus.edufocus.ws.entity.dto.ResponseChatUserDto; +import com.edufocus.edufocus.ws.service.ChatService; +import jakarta.websocket.Session; +import org.springframework.context.event.EventListener; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.messaging.Message; +import org.springframework.messaging.handler.annotation.DestinationVariable; +import org.springframework.messaging.handler.annotation.Header; +import org.springframework.messaging.handler.annotation.MessageMapping; +import org.springframework.messaging.handler.annotation.SendTo; +import org.springframework.messaging.simp.SimpMessageHeaderAccessor; +import org.springframework.messaging.simp.SimpMessageSendingOperations; +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.RestController; +import org.springframework.web.socket.messaging.SessionDisconnectEvent; + +import java.util.List; + +@RestController +public class ChatController { + + private final SimpMessageSendingOperations simpMessageSendingOperations; + + private final ChatService chatService; + + private final JWTUtil jwtUtil; + + public ChatController(SimpMessageSendingOperations simpMessageSendingOperations, ChatService chatService, JWTUtil jwtUtil){ + this.simpMessageSendingOperations = simpMessageSendingOperations; + this.chatService = chatService; + this.jwtUtil = jwtUtil; + } + + @GetMapping("/chat/enter/{lectureId}") + public ResponseEntity enter(@PathVariable long lectureId){ + List chatUsers = chatService.findChatUsers(lectureId); + return new ResponseEntity<>(chatUsers, HttpStatus.OK); + } + + + @MessageMapping("/hello/{channelId}") + @SendTo("/sub/channel/{channelId}") + public ResponseChatUserDto hello(@DestinationVariable long channelId, SimpMessageHeaderAccessor simpMessageHeaderAccessor, @Header("Authorization") String token){ + String sessionId = simpMessageHeaderAccessor.getSessionId(); + + long userId = Long.parseLong(jwtUtil.getUserId(token)); + + chatService.saveChatUserInfo(userId, channelId, sessionId); + + return chatService.getChatUserInfo(userId); + } + + @MessageMapping("/message/{lectureId}") + @SendTo("/sub/channel/{lectureId}") + public MessageDto sendMessage(@DestinationVariable long lectureId, MessageDto messageDto){return messageDto;} + + @MessageMapping("/quiz/{lectureId}") + @SendTo("/sub/channel/{lectureId}") + public QuizDto quizStart(@DestinationVariable long lectureId, QuizDto quizDto){ + return quizDto; + } + + @EventListener + public void handleWebSocketDisconnectListener(SessionDisconnectEvent event){ + StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(event.getMessage()); + String sessionId = headerAccessor.getSessionId(); + long channelId = chatService.getChannelId(sessionId); + simpMessageSendingOperations.convertAndSend("/sub/channel/" + channelId); + } +} + diff --git a/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/HelloDto.java b/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/HelloDto.java new file mode 100644 index 0000000..55a6c4f --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/HelloDto.java @@ -0,0 +1,13 @@ +package com.edufocus.edufocus.ws.entity.dto; + + +import lombok.*; + +@Builder +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class HelloDto { + long channelId; + String name; +} diff --git a/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/MessageDto.java b/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/MessageDto.java new file mode 100644 index 0000000..17522a9 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/MessageDto.java @@ -0,0 +1,11 @@ +package com.edufocus.edufocus.ws.entity.dto; + + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class MessageDto { + int channelId; +} diff --git a/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/QuizDto.java b/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/QuizDto.java new file mode 100644 index 0000000..1900b3d --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/QuizDto.java @@ -0,0 +1,13 @@ +package com.edufocus.edufocus.ws.entity.dto; + + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class QuizDto { + int channelId; + int userId; + int quizSetId; +} diff --git a/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/ResponseChatUserDto.java b/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/ResponseChatUserDto.java new file mode 100644 index 0000000..f418b8f --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/ResponseChatUserDto.java @@ -0,0 +1,6 @@ +package com.edufocus.edufocus.ws.entity.dto; + +public class ResponseChatUserDto { + int userId; + int name; +} diff --git a/backend/src/main/java/com/edufocus/edufocus/ws/entity/vo/ChatUser.java b/backend/src/main/java/com/edufocus/edufocus/ws/entity/vo/ChatUser.java new file mode 100644 index 0000000..7a5422a --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/ws/entity/vo/ChatUser.java @@ -0,0 +1,25 @@ +package com.edufocus.edufocus.ws.entity.vo; + +import com.edufocus.edufocus.lecture.entity.Lecture; +import com.edufocus.edufocus.user.model.entity.User; +import jakarta.persistence.*; +import lombok.*; + + +@Entity +@Getter +@Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ChatUser { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) // 자동 증가 설정 + int id; + @Column + String sessionId; + @OneToOne + User user; + @ManyToOne + Lecture lecture; +} \ No newline at end of file diff --git a/backend/src/main/java/com/edufocus/edufocus/ws/service/ChatService.java b/backend/src/main/java/com/edufocus/edufocus/ws/service/ChatService.java new file mode 100644 index 0000000..765ddc1 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/ws/service/ChatService.java @@ -0,0 +1,10 @@ +package com.edufocus.edufocus.ws.service; + +import com.edufocus.edufocus.ws.entity.dto.ResponseChatUserDto; + +public interface ChatService { + public void saveChatUserInfo(long userId, long channelId, String sessionId); + public ResponseChatUserDto getChatUserInfo(long userId); + + +} diff --git a/backend/src/main/java/com/edufocus/edufocus/ws/service/ChatServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/ws/service/ChatServiceImpl.java new file mode 100644 index 0000000..8baccca --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/ws/service/ChatServiceImpl.java @@ -0,0 +1,9 @@ +package com.edufocus.edufocus.ws.service; + + +import org.springframework.stereotype.Service; + +@Service +public class ChatServiceImpl implements ChatService{ + +} From 6d09dc0cb5bdf687dfaa14118afe46e5b03b0d88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Mon, 22 Jul 2024 17:34:11 +0900 Subject: [PATCH 029/197] =?UTF-8?q?feat:=20report=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../report/controller/ReportController.java | 9 ++++--- .../report/entity/{ => dto}/AnswerInput.java | 2 +- .../entity/{ => dto}/QuizSubmissionDto.java | 2 +- .../entity/{ => dto}/ReportRequset.java | 2 +- .../report/entity/dto/ReportResponse.java | 26 +++++++++++++++++++ .../report/entity/{ => vo}/Answer.java | 2 +- .../report/entity/{ => vo}/Report.java | 2 +- .../report/repository/AnswerRepository.java | 2 +- .../report/repository/ReportRepository.java | 2 +- .../report/service/AnswerService.java | 2 +- .../report/service/AnswerServiceImpl.java | 2 +- .../report/service/ReportService.java | 7 ++--- .../report/service/ReportServiceImpl.java | 24 ++++++++++------- 13 files changed, 59 insertions(+), 25 deletions(-) rename backend/src/main/java/com/edufocus/edufocus/report/entity/{ => dto}/AnswerInput.java (68%) rename backend/src/main/java/com/edufocus/edufocus/report/entity/{ => dto}/QuizSubmissionDto.java (64%) rename backend/src/main/java/com/edufocus/edufocus/report/entity/{ => dto}/ReportRequset.java (87%) create mode 100644 backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportResponse.java rename backend/src/main/java/com/edufocus/edufocus/report/entity/{ => vo}/Answer.java (91%) rename backend/src/main/java/com/edufocus/edufocus/report/entity/{ => vo}/Report.java (92%) diff --git a/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java b/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java index 20f82e1..f07149f 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java @@ -1,7 +1,8 @@ package com.edufocus.edufocus.report.controller; -import com.edufocus.edufocus.report.entity.Report; -import com.edufocus.edufocus.report.entity.ReportRequset; +import com.edufocus.edufocus.report.entity.dto.ReportResponse; +import com.edufocus.edufocus.report.entity.vo.Report; +import com.edufocus.edufocus.report.entity.dto.ReportRequset; import com.edufocus.edufocus.report.service.ReportService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -27,8 +28,8 @@ public class ReportController{ @PostMapping("/submit") - public ResponseEntity submit(@RequestBody ReportRequset reportRequset) throws SQLException { - Report report = reportService.grading(reportRequset); + public ResponseEntity submit(@RequestBody ReportRequset reportRequset) throws SQLException { + ReportResponse report = reportService.grading(reportRequset); return new ResponseEntity<>(report,HttpStatus.CREATED); } diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/AnswerInput.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/AnswerInput.java similarity index 68% rename from backend/src/main/java/com/edufocus/edufocus/report/entity/AnswerInput.java rename to backend/src/main/java/com/edufocus/edufocus/report/entity/dto/AnswerInput.java index c237616..ba1ff2e 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/AnswerInput.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/AnswerInput.java @@ -1,4 +1,4 @@ -package com.edufocus.edufocus.report.entity; +package com.edufocus.edufocus.report.entity.dto; import lombok.Getter; diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/QuizSubmissionDto.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/QuizSubmissionDto.java similarity index 64% rename from backend/src/main/java/com/edufocus/edufocus/report/entity/QuizSubmissionDto.java rename to backend/src/main/java/com/edufocus/edufocus/report/entity/dto/QuizSubmissionDto.java index 489d896..24413b2 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/QuizSubmissionDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/QuizSubmissionDto.java @@ -1,4 +1,4 @@ -package com.edufocus.edufocus.report.entity; +package com.edufocus.edufocus.report.entity.dto; public class QuizSubmissionDto { private Long quizSetId; diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/ReportRequset.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportRequset.java similarity index 87% rename from backend/src/main/java/com/edufocus/edufocus/report/entity/ReportRequset.java rename to backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportRequset.java index 788f87f..ca20596 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/ReportRequset.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportRequset.java @@ -1,4 +1,4 @@ -package com.edufocus.edufocus.report.entity; +package com.edufocus.edufocus.report.entity.dto; import lombok.Getter; import lombok.Setter; diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportResponse.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportResponse.java new file mode 100644 index 0000000..7d6a439 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportResponse.java @@ -0,0 +1,26 @@ +package com.edufocus.edufocus.report.entity.dto; + +import com.edufocus.edufocus.report.entity.vo.Answer; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +import java.util.Date; +import java.util.List; + +@Getter +@Setter +@Builder +public class ReportResponse { + + private Long quizesetId; + private Long userId; + + private String title; + private int allCount; + private int correctCount; + private Date testAt; + + + +} diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/Answer.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Answer.java similarity index 91% rename from backend/src/main/java/com/edufocus/edufocus/report/entity/Answer.java rename to backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Answer.java index 3204f24..1437626 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/Answer.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Answer.java @@ -1,4 +1,4 @@ -package com.edufocus.edufocus.report.entity; +package com.edufocus.edufocus.report.entity.vo; import com.edufocus.edufocus.quiz.entity.Quiz; diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/Report.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java similarity index 92% rename from backend/src/main/java/com/edufocus/edufocus/report/entity/Report.java rename to backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java index 6a011d5..6165358 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/Report.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java @@ -1,4 +1,4 @@ -package com.edufocus.edufocus.report.entity; +package com.edufocus.edufocus.report.entity.vo; import com.edufocus.edufocus.quiz.entity.QuizSet; import com.edufocus.edufocus.user.model.entity.User; diff --git a/backend/src/main/java/com/edufocus/edufocus/report/repository/AnswerRepository.java b/backend/src/main/java/com/edufocus/edufocus/report/repository/AnswerRepository.java index 12f76ae..aa2ec9a 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/repository/AnswerRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/repository/AnswerRepository.java @@ -1,6 +1,6 @@ package com.edufocus.edufocus.report.repository; -import com.edufocus.edufocus.report.entity.Answer; +import com.edufocus.edufocus.report.entity.vo.Answer; import org.springframework.data.jpa.repository.JpaRepository; public interface AnswerRepository extends JpaRepository { diff --git a/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportRepository.java b/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportRepository.java index dd5eca7..954473e 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportRepository.java @@ -1,6 +1,6 @@ package com.edufocus.edufocus.report.repository; -import com.edufocus.edufocus.report.entity.Report; +import com.edufocus.edufocus.report.entity.vo.Report; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; diff --git a/backend/src/main/java/com/edufocus/edufocus/report/service/AnswerService.java b/backend/src/main/java/com/edufocus/edufocus/report/service/AnswerService.java index 2c4c65a..de98121 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/service/AnswerService.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/service/AnswerService.java @@ -1,6 +1,6 @@ package com.edufocus.edufocus.report.service; -import com.edufocus.edufocus.report.entity.Answer; +import com.edufocus.edufocus.report.entity.vo.Answer; public interface AnswerService { diff --git a/backend/src/main/java/com/edufocus/edufocus/report/service/AnswerServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/report/service/AnswerServiceImpl.java index b838846..e19f53e 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/service/AnswerServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/service/AnswerServiceImpl.java @@ -1,6 +1,6 @@ package com.edufocus.edufocus.report.service; -import com.edufocus.edufocus.report.entity.Answer; +import com.edufocus.edufocus.report.entity.vo.Answer; import com.edufocus.edufocus.report.repository.AnswerRepository; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; diff --git a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportService.java b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportService.java index 89de34f..bfead76 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportService.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportService.java @@ -1,13 +1,14 @@ package com.edufocus.edufocus.report.service; -import com.edufocus.edufocus.report.entity.Report; -import com.edufocus.edufocus.report.entity.ReportRequset; +import com.edufocus.edufocus.report.entity.dto.ReportResponse; +import com.edufocus.edufocus.report.entity.vo.Report; +import com.edufocus.edufocus.report.entity.dto.ReportRequset; import org.springframework.stereotype.Service; import java.sql.SQLException; @Service public interface ReportService { - Report grading(ReportRequset reportRequset) throws SQLException; + ReportResponse grading(ReportRequset reportRequset) throws SQLException; } diff --git a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java index 87f0af0..dd22a44 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java @@ -5,10 +5,11 @@ import com.edufocus.edufocus.quiz.entity.QuizSet; import com.edufocus.edufocus.quiz.repository.QuizRepository; import com.edufocus.edufocus.quiz.service.QuizService; import com.edufocus.edufocus.quiz.service.QuizSetService; -import com.edufocus.edufocus.report.entity.Answer; -import com.edufocus.edufocus.report.entity.AnswerInput; -import com.edufocus.edufocus.report.entity.Report; -import com.edufocus.edufocus.report.entity.ReportRequset; +import com.edufocus.edufocus.report.entity.dto.ReportResponse; +import com.edufocus.edufocus.report.entity.vo.Answer; +import com.edufocus.edufocus.report.entity.dto.AnswerInput; +import com.edufocus.edufocus.report.entity.vo.Report; +import com.edufocus.edufocus.report.entity.dto.ReportRequset; import com.edufocus.edufocus.report.repository.ReportRepository; import com.edufocus.edufocus.user.model.entity.User; import com.edufocus.edufocus.user.model.repository.UserRepository; @@ -36,7 +37,7 @@ public class ReportServiceImpl implements ReportService { @Override - public Report grading(ReportRequset reportRequset) throws SQLException { + public ReportResponse grading(ReportRequset reportRequset) throws SQLException { QuizSet quizSet = quizSetService.findQuizSet(reportRequset.getQuizsetId()); @@ -90,10 +91,15 @@ public class ReportServiceImpl implements ReportService { .allCount(allCount) .correctCount(correctCount) .testAt(new Date()).build(); + ReportResponse reportResponse = ReportResponse.builder() + .quizesetId(quizSet.getId()) + .userId(testuser.getId()) + .title(quizSet.getTitle()) + .allCount(allCount) + .correctCount(correctCount) + .testAt(new Date()) + .build(); - reportRepository.save(report); - return report; - - + return reportResponse; } } From 3eac0e45b215aaa0187edbccd02203913f6d124c Mon Sep 17 00:00:00 2001 From: kgc9007 Date: Mon, 22 Jul 2024 17:51:57 +0900 Subject: [PATCH 030/197] =?UTF-8?q?feat:=20Registration=20=EC=88=98?= =?UTF-8?q?=EA=B0=95=EC=8B=A0=EC=B2=AD,=20=EC=8A=B9=EC=9D=B8,=20=EA=B1=B0?= =?UTF-8?q?=EC=A0=88=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/RegistrationController.java | 17 +++++++------ .../registration/entity/Registration.java | 6 +++-- .../service/RegistrationService.java | 2 +- .../service/RegistrationServiceImpl.java | 25 ++++++++++++------- 4 files changed, 31 insertions(+), 19 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/controller/RegistrationController.java b/backend/src/main/java/com/edufocus/edufocus/registration/controller/RegistrationController.java index fc6e67d..2534d69 100644 --- a/backend/src/main/java/com/edufocus/edufocus/registration/controller/RegistrationController.java +++ b/backend/src/main/java/com/edufocus/edufocus/registration/controller/RegistrationController.java @@ -2,6 +2,8 @@ package com.edufocus.edufocus.registration.controller; import com.edufocus.edufocus.registration.entity.Registration; import com.edufocus.edufocus.registration.service.RegistrationService; +import com.edufocus.edufocus.user.util.JWTUtil; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -10,29 +12,30 @@ import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/registration") @Slf4j +@RequiredArgsConstructor public class RegistrationController { private final RegistrationService registrationServiceImpl; - public RegistrationController(RegistrationService registrationServiceImpl) { - this.registrationServiceImpl = registrationServiceImpl; - } + private final JWTUtil jwtUtil; @PostMapping - public ResponseEntity register(@RequestBody Registration registration) { - registrationServiceImpl.createRegistration(registration); + public ResponseEntity register(@RequestHeader("Authorization") String accessToken, @RequestBody long lectureId) { + Long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); + + registrationServiceImpl.createRegistration(userId, lectureId); return new ResponseEntity<>(HttpStatus.OK); } - @PatchMapping("/registrationId/{registrationId}") + @PutMapping("/{registrationId}") public ResponseEntity acceptRigistration(@PathVariable long registrationId) { registrationServiceImpl.acceptRegistration(registrationId); return new ResponseEntity<>(HttpStatus.OK); } - @DeleteMapping("/registrationId/{registrationId}") + @DeleteMapping("/{registrationId}") public ResponseEntity deleteRigistration(@PathVariable long registrationId) { registrationServiceImpl.deleteRegistration(registrationId); diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/entity/Registration.java b/backend/src/main/java/com/edufocus/edufocus/registration/entity/Registration.java index 7e1cce6..4a81aba 100644 --- a/backend/src/main/java/com/edufocus/edufocus/registration/entity/Registration.java +++ b/backend/src/main/java/com/edufocus/edufocus/registration/entity/Registration.java @@ -3,12 +3,14 @@ package com.edufocus.edufocus.registration.entity; import com.edufocus.edufocus.lecture.entity.Lecture; import com.edufocus.edufocus.user.model.entity.User; import jakarta.persistence.*; -import lombok.Getter; -import lombok.Setter; +import lombok.*; @Entity @Getter @Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor public class Registration { @Id diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationService.java b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationService.java index fcaac94..4553408 100644 --- a/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationService.java +++ b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationService.java @@ -6,7 +6,7 @@ import org.springframework.stereotype.Service; @Service public interface RegistrationService { - void createRegistration(Registration registration); + void createRegistration(long userId, long registrationId); void acceptRegistration(long RegistrationId); diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java index 6eadce6..507e084 100644 --- a/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java @@ -1,8 +1,10 @@ package com.edufocus.edufocus.registration.service; +import com.edufocus.edufocus.lecture.repository.LectureRepository; import com.edufocus.edufocus.registration.entity.Registration; import com.edufocus.edufocus.registration.entity.RegistrationStatus; import com.edufocus.edufocus.registration.repository.RegistrationRepository; +import com.edufocus.edufocus.user.model.repository.UserRepository; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -15,21 +17,26 @@ import java.util.Optional; public class RegistrationServiceImpl implements RegistrationService { private final RegistrationRepository registrationRepository; + private final UserRepository userRepository; + private final LectureRepository lectureRepository; @Override - public void createRegistration(Registration registration) { + public void createRegistration(long userId, long lectureId) { + Registration registration = new Registration().builder() + .user(userRepository.getReferenceById(userId)) + .lecture(lectureRepository.getReferenceById(lectureId)) + .status(RegistrationStatus.WAITING) + .build(); + registrationRepository.save(registration); } @Override public void acceptRegistration(long registrationId) { - Optional registration = registrationRepository.findById(registrationId); + Registration registration = registrationRepository.findById(registrationId).get(); - if (registration.isPresent()) { - Registration reg = registration.get(); - reg.setStatus(RegistrationStatus.valueOf("ACCEPTED")); - registrationRepository.save(reg); - } + registration.setStatus(RegistrationStatus.valueOf("ACCEPTED")); + registrationRepository.save(registration); } @Override @@ -39,8 +46,8 @@ public class RegistrationServiceImpl implements RegistrationService { @Override public boolean isAcceptedRegistration(long registrationId) { - Optional registration = registrationRepository.findById(registrationId); + Registration registration = registrationRepository.findById(registrationId).get(); - return registration.isPresent() && registration.get().getStatus().equals("ACCEPTED"); + return registration.getStatus().equals("ACCEPTED"); } } From 792a32711c21a58ae73e969cfe5c8fbce9c2084f Mon Sep 17 00:00:00 2001 From: kgc9007 Date: Tue, 23 Jul 2024 12:41:11 +0900 Subject: [PATCH 031/197] =?UTF-8?q?feat:=20Registration=20=EC=88=98?= =?UTF-8?q?=EA=B0=95=EC=8B=A0=EC=B2=AD=20=EC=8A=B9=EC=9D=B8/=EA=B1=B0?= =?UTF-8?q?=EC=A0=88=20=EA=B4=80=EB=A6=AC=EC=9E=90=20=ED=99=95=EC=9D=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/RegistrationController.java | 35 ++++++++++++++----- .../service/RegistrationService.java | 8 ++--- .../service/RegistrationServiceImpl.java | 30 +++++++++++----- 3 files changed, 50 insertions(+), 23 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/controller/RegistrationController.java b/backend/src/main/java/com/edufocus/edufocus/registration/controller/RegistrationController.java index 2534d69..1d28aaf 100644 --- a/backend/src/main/java/com/edufocus/edufocus/registration/controller/RegistrationController.java +++ b/backend/src/main/java/com/edufocus/edufocus/registration/controller/RegistrationController.java @@ -1,6 +1,5 @@ package com.edufocus.edufocus.registration.controller; -import com.edufocus.edufocus.registration.entity.Registration; import com.edufocus.edufocus.registration.service.RegistrationService; import com.edufocus.edufocus.user.util.JWTUtil; import lombok.RequiredArgsConstructor; @@ -9,6 +8,8 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import java.util.Map; + @RestController @RequestMapping("/registration") @Slf4j @@ -20,26 +21,42 @@ public class RegistrationController { private final JWTUtil jwtUtil; @PostMapping - public ResponseEntity register(@RequestHeader("Authorization") String accessToken, @RequestBody long lectureId) { + public ResponseEntity register(@RequestHeader("Authorization") String accessToken, @RequestBody Map map) { Long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); + Long lectureId = map.get("lectureId"); - registrationServiceImpl.createRegistration(userId, lectureId); + if (!registrationServiceImpl.createRegistration(userId, lectureId)) { + String msg = new String("Duplicated Registration"); + return new ResponseEntity<>(msg, HttpStatus.CONFLICT); + } - return new ResponseEntity<>(HttpStatus.OK); + String msg = new String("registration successful"); + return new ResponseEntity<>(HttpStatus.CREATED); } @PutMapping("/{registrationId}") - public ResponseEntity acceptRigistration(@PathVariable long registrationId) { - registrationServiceImpl.acceptRegistration(registrationId); + public ResponseEntity acceptRigistration(@RequestHeader("Authorization") String accessToken, @PathVariable long registrationId) { + Long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); + if (!registrationServiceImpl.acceptRegistration(userId, registrationId)) { + String msg = new String("Not Acceptable"); + return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); + } + + String msg = new String("registration accepted"); return new ResponseEntity<>(HttpStatus.OK); } @DeleteMapping("/{registrationId}") - public ResponseEntity deleteRigistration(@PathVariable long registrationId) { - registrationServiceImpl.deleteRegistration(registrationId); + public ResponseEntity deleteRigistration(@RequestHeader("Authorization") String accessToken, @PathVariable long registrationId) { + Long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); - return new ResponseEntity<>(HttpStatus.OK); + if (!registrationServiceImpl.deleteRegistration(userId, registrationId)) { + String msg = new String("Not Acceptable"); + return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); + } + + return new ResponseEntity<>(HttpStatus.NO_CONTENT); } } diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationService.java b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationService.java index 4553408..96d89f6 100644 --- a/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationService.java +++ b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationService.java @@ -6,12 +6,10 @@ import org.springframework.stereotype.Service; @Service public interface RegistrationService { - void createRegistration(long userId, long registrationId); + boolean createRegistration(long userId, long registrationId); - void acceptRegistration(long RegistrationId); + boolean acceptRegistration(long userId, long RegistrationId); - void deleteRegistration(long registrationId); - - boolean isAcceptedRegistration(long registrationId); + boolean deleteRegistration(long userId, long registrationId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java index 507e084..7c156bf 100644 --- a/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java @@ -21,7 +21,11 @@ public class RegistrationServiceImpl implements RegistrationService { private final LectureRepository lectureRepository; @Override - public void createRegistration(long userId, long lectureId) { + public boolean createRegistration(long userId, long lectureId) { + if (registrationRepository.findByUserIdAndLectureId(userId, lectureId) != null) { + return false; + } + Registration registration = new Registration().builder() .user(userRepository.getReferenceById(userId)) .lecture(lectureRepository.getReferenceById(lectureId)) @@ -29,25 +33,33 @@ public class RegistrationServiceImpl implements RegistrationService { .build(); registrationRepository.save(registration); + return true; } @Override - public void acceptRegistration(long registrationId) { + public boolean acceptRegistration(long userId, long registrationId) { Registration registration = registrationRepository.findById(registrationId).get(); + if (registration.getLecture().getUser().getId() != userId) { + return false; + } + registration.setStatus(RegistrationStatus.valueOf("ACCEPTED")); registrationRepository.save(registration); + + return true; } @Override - public void deleteRegistration(long registrationId) { - registrationRepository.deleteById(registrationId); - } - - @Override - public boolean isAcceptedRegistration(long registrationId) { + public boolean deleteRegistration(long userId, long registrationId) { Registration registration = registrationRepository.findById(registrationId).get(); - return registration.getStatus().equals("ACCEPTED"); + if (registration.getLecture().getUser().getId() != userId) { + return false; + } + + registrationRepository.deleteById(registrationId); + return true; } + } From 5f678beccca1f193b6d1bdb97d4fe2c93de8d30d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Tue, 23 Jul 2024 12:58:49 +0900 Subject: [PATCH 032/197] =?UTF-8?q?feat:=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85=20=EC=9C=A0=ED=9A=A8=EC=84=B1=EA=B2=80=EC=82=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/build.gradle | 4 + .../user/controller/UserController.java | 6 ++ .../edufocus/user/model/entity/MailDto.java | 20 +++++ .../user/model/entity/MemberChangeDto.java | 19 +++++ .../edufocus/user/model/entity/User.java | 7 ++ .../user/model/repository/UserRepository.java | 6 ++ .../user/model/service/UserService.java | 3 + .../user/model/service/UserServiceImpl.java | 76 ++++++++++++++++++- .../src/main/resources/application.properties | 13 +++- 9 files changed, 152 insertions(+), 2 deletions(-) create mode 100644 backend/src/main/java/com/edufocus/edufocus/user/model/entity/MailDto.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/user/model/entity/MemberChangeDto.java diff --git a/backend/build.gradle b/backend/build.gradle index f18f491..62702e7 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -30,6 +30,10 @@ dependencies { runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-jackson', version: '0.11.5' runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-impl', version: '0.11.5' implementation group: 'io.jsonwebtoken', name: 'jjwt-api', version: '0.11.5' + implementation group: 'org.springframework.boot', name: 'spring-boot-starter-mail', version: '3.2.5' + implementation 'org.springframework.boot:spring-boot-starter-mail' + + implementation group: 'org.glassfish.jaxb', name: 'jaxb-runtime', version: '4.0.5' diff --git a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java index 16e8b9f..e185b6c 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java @@ -34,7 +34,13 @@ public class UserController { userService.join(user); return ResponseEntity.ok("User registered successfully"); } + @PostMapping("/findpassword/{user_id}") + public ResponseEntity findpassword(@PathVariable("user_id") Long user_id) throws Exception { + userService.userCheck(user_id); + return ResponseEntity.ok("임시 비밀번호가 이메일로 전송되었습니다."); + + } // // @PostMapping("/login") // public ResponseEntity login(@RequestBody User user) { diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/MailDto.java b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/MailDto.java new file mode 100644 index 0000000..b2e1e51 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/MailDto.java @@ -0,0 +1,20 @@ +package com.edufocus.edufocus.user.model.entity; + +import lombok.Data; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +@Getter +@Setter +@NoArgsConstructor +@ToString +@Data +public class MailDto { + + private String address; + private String title; + private String message; + +} \ No newline at end of file diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/MemberChangeDto.java b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/MemberChangeDto.java new file mode 100644 index 0000000..5576813 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/MemberChangeDto.java @@ -0,0 +1,19 @@ +package com.edufocus.edufocus.user.model.entity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@ToString +@Data +public class MemberChangeDto { + Long id; + String password; +} \ No newline at end of file diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/User.java b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/User.java index 8bc7952..f0403f8 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/User.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/User.java @@ -2,6 +2,8 @@ package com.edufocus.edufocus.user.model.entity; import com.edufocus.edufocus.qna.entity.Qna; import jakarta.persistence.*; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Pattern; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; @@ -25,7 +27,12 @@ public class User { @Column(name = "user_id", unique = true, nullable = false) + @Pattern(regexp = "(?=.*[0-9])(?=.*[a-zA-Z])(?=.*\\W)(?=\\S+$).{8,16}", message = "비밀번호는 8~16자 영문 대 소문자, 숫자, 특수문자를 사용하세요.") + @NotBlank(message = "아이디는 필수 입력 값입니다.") + private String userId; + + @Pattern(regexp = "^(?:\\w+\\.?)*\\w+@(?:\\w+\\.)+\\w+$", message = "이메일 형식이 올바르지 않습니다.") private String email; private String password; @Enumerated(EnumType.STRING) // 혹은 EnumType.ORDINAL diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/repository/UserRepository.java b/backend/src/main/java/com/edufocus/edufocus/user/model/repository/UserRepository.java index 53e6289..026c4aa 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/repository/UserRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/repository/UserRepository.java @@ -23,6 +23,12 @@ public interface UserRepository extends JpaRepository { @Query("UPDATE User u SET u.refreshToken = NULL WHERE u.id = :id") void deleteRefreshToken(@Param("id") Long id); + @Transactional + @Modifying + @Query("UPDATE User u set u.password = :password where u.id= :id") + void updatePassword(@Param("id") Long id , @Param("password") String password); + + Optional findByUserId(String userId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java index 3ba4454..4f3733a 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java @@ -9,4 +9,7 @@ public interface UserService { String getRefreshToken(Long id) throws Exception; void deleteRefreshToken(Long id) throws Exception; User userInfo(Long id) throws Exception; + void sendEamail(User user) throws Exception; + void userCheck(Long id) throws Exception; + } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java index 0f70838..2c39b06 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java @@ -1,12 +1,16 @@ package com.edufocus.edufocus.user.model.service; +import com.edufocus.edufocus.user.model.entity.MailDto; +import com.edufocus.edufocus.user.model.entity.MemberChangeDto; import com.edufocus.edufocus.user.model.entity.User; import com.edufocus.edufocus.user.model.exception.UserException; import com.edufocus.edufocus.user.model.repository.UserRepository; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.mail.javamail.JavaMailSender; import org.springframework.stereotype.Service; import java.sql.SQLException; @@ -19,8 +23,10 @@ import java.util.Optional; @RequiredArgsConstructor public class UserServiceImpl implements UserService{ - @Autowired + private final UserRepository userRepository; + private final JavaMailSender mailSender; + public void join(User user) @@ -74,6 +80,74 @@ public class UserServiceImpl implements UserService{ } } + + @Override + public void sendEamail(User user) throws Exception { + MailDto mailDto = createMailAndChargePassword(user); + + System.out.println("이메일 전송 완료"); + SimpleMailMessage message = new SimpleMailMessage(); + + + + message.setTo(mailDto.getAddress()); + message.setFrom("passfinder111@gmail.com"); + message.setSubject(mailDto.getTitle()); + message.setText(mailDto.getMessage()); + System.out.println("!!!!!!!!!!!!!!!!!!"+ message); + + mailSender.send(message); + + + } + + public MailDto createMailAndChargePassword(User user) throws SQLException { + String str = getTempPassword(); + MailDto dto = new MailDto(); + dto.setAddress(user.getEmail()); + dto.setTitle(user.getUserId()+"님의 임시비밀번호 안내 이메일 입니다."); + dto.setMessage("안녕하세요. EduFoucs 입니다. "+ "\n"+ "임시비밀번호 안내 관련 메일 입니다." + "\n[" + user.getName() + "]" + "님의 임시 비밀번호는 " + + str + " 입니다."); + + System.out.println(dto); + + MemberChangeDto memberChangeDto = new MemberChangeDto(user.getId(),str); + System.out.println(memberChangeDto); + userRepository.updatePassword(memberChangeDto.getId(),memberChangeDto.getPassword()); + System.out.println(); + + return dto; + } + + @Override + public void userCheck(Long id) throws Exception { + + User user = userRepository.findById(id).orElse(null); + + + if(user == null) + { + System.out.println("불가"); + throw new RuntimeException("유효하지 않은 아이디입니다. 다시 입력하세요"); + + } + else { + + sendEamail(user); + } + } + public String getTempPassword() { + char[] charSet = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', + 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}; + String str = ""; + + int idx = 0; + for (int i=0; i<10; i++) { + idx = (int) (charSet.length * Math.random()); + str += charSet[idx]; + } + return str; + } @Override public void saveRefreshToken(Long id, String refreshToken) throws Exception { userRepository.saveRefreshToken(id, refreshToken); diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index f06afe6..d24fac6 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -23,4 +23,15 @@ spring.mvc.pathmatch.matching-strategy=ant_path_matcher spring.jpa.database=mysql spring.jpa.hibernate.ddl-auto=create -spring.jpa.show-sql=true \ No newline at end of file +spring.jpa.show-sql=true + + +spring.mail.host=smtp.gmail.com +spring.mail.port=587 +#spring.mail.username=ssafytestpjt +#spring.mail.password=trpjbxqialufuzih +spring.mail.username=passfinder111@gmail.com +spring.mail.password=mnlyfkiprltjlsmw + +spring.mail.properties.mail.smtp.auth=true +spring.mail.properties.mail.smtp.starttls.enable=true From 7e32f9ac39191b28140c8b9a09c9dc31cf2ff303 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Wed, 24 Jul 2024 10:17:21 +0900 Subject: [PATCH 033/197] =?UTF-8?q?feat:=20cors=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/edufocus/user/config/WebConfiguration.java | 7 ++++++- .../com/edufocus/edufocus/video/controller/Controller.java | 7 +++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java b/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java index 362e689..da85d88 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java @@ -37,5 +37,10 @@ public class WebConfiguration implements WebMvcConfigurer { registry.addResourceHandler("/img/**").addResourceLocations("classpath:/static/assets/img/"); registry.addResourceHandler("/*.html**").addResourceLocations("classpath:/static/"); } - + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(jwtInterceptor) + .addPathPatterns("/**") // 모든 경로에 대해 인터셉터 적용 + .excludePathPatterns("/auth/**", "/board/**", "/user/**","/lecture/**","/qna/**"); // 인증 없이 접근 가능한 경로 설정 + } } \ No newline at end of file diff --git a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java index ab3a751..ed35745 100644 --- a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java +++ b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java @@ -30,6 +30,13 @@ public class Controller { String roomName = params.get("roomName"); String participantName = params.get("participantName"); + // + // + // + // + // + // + if (roomName == null || participantName == null) { return ResponseEntity.badRequest().body(Map.of("errorMessage", "roomName and participantName are required")); } From 45a7e780149a16abb7ab7e7cca3fd18bff8cb29c Mon Sep 17 00:00:00 2001 From: yulmam Date: Wed, 24 Jul 2024 10:21:51 +0900 Subject: [PATCH 034/197] =?UTF-8?q?feat=20:=20chat=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../entity/dto/{ResponseChatUserDto.java => ChatUserDto.java} | 0 .../com/edufocus/edufocus/ws/repository/ChatUserRepository.java | 2 ++ 2 files changed, 2 insertions(+) rename backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/{ResponseChatUserDto.java => ChatUserDto.java} (100%) create mode 100644 backend/src/main/java/com/edufocus/edufocus/ws/repository/ChatUserRepository.java diff --git a/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/ResponseChatUserDto.java b/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/ChatUserDto.java similarity index 100% rename from backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/ResponseChatUserDto.java rename to backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/ChatUserDto.java diff --git a/backend/src/main/java/com/edufocus/edufocus/ws/repository/ChatUserRepository.java b/backend/src/main/java/com/edufocus/edufocus/ws/repository/ChatUserRepository.java new file mode 100644 index 0000000..02408c5 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/ws/repository/ChatUserRepository.java @@ -0,0 +1,2 @@ +package com.edufocus.edufocus.ws.repository;public interface ChatUserRepository { +} From 9cfa34ed002f23afe2c719b8f1501548963704f7 Mon Sep 17 00:00:00 2001 From: yulmam Date: Wed, 24 Jul 2024 10:22:47 +0900 Subject: [PATCH 035/197] =?UTF-8?q?refactor=20:=20header=20=ED=95=84?= =?UTF-8?q?=EC=9A=94=20=EA=B8=B0=EB=8A=A5=20=EC=A3=BC=EC=84=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../board/controller/BoardController.java | 1 + .../board/service/BoardServiceImpl.java | 12 +-- .../lecture/repository/LectureRepository.java | 1 + .../ws/controller/ChatController.java | 65 +++++++++------- .../edufocus/ws/entity/dto/ChatUserDto.java | 14 +++- .../edufocus/ws/entity/dto/HelloDto.java | 2 +- .../edufocus/ws/entity/dto/MessageDto.java | 5 +- .../edufocus/ws/entity/dto/QuizDto.java | 2 +- .../edufocus/ws/entity/vo/ChatUser.java | 12 ++- .../ws/repository/ChatUserRepository.java | 15 +++- .../edufocus/ws/service/ChatService.java | 13 +++- .../edufocus/ws/service/ChatServiceImpl.java | 74 +++++++++++++++++++ 12 files changed, 170 insertions(+), 46 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java b/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java index a1ead74..dd45f9b 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java @@ -19,6 +19,7 @@ import java.util.List; */ @RestController @RequestMapping("/board") +@CrossOrigin("*") public class BoardController { private final JWTUtil jwtUtil; diff --git a/backend/src/main/java/com/edufocus/edufocus/board/service/BoardServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/board/service/BoardServiceImpl.java index 10426fb..4e047f9 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/service/BoardServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/service/BoardServiceImpl.java @@ -56,8 +56,8 @@ public class BoardServiceImpl implements BoardService { @Transactional public void createBoard(long userId, RequestBoardDto requestBoardDto) { - User user = userRepository.findById(userId).orElseThrow(); - Lecture lecture = lectureRepository.findById(requestBoardDto.getLectureId()).orElseThrow(IllegalArgumentException::new); + User user = userRepository.getReferenceById(userId); + Lecture lecture = lectureRepository.getReferenceById(requestBoardDto.getLectureId()); Board board = Board.builder() .title(requestBoardDto.getTitle()) @@ -83,7 +83,7 @@ public class BoardServiceImpl implements BoardService { @Transactional public void deleteBoard(long boardId) { - Board board = boardRepository.findById(boardId).orElseThrow(IllegalArgumentException::new); + Board board = boardRepository.getReferenceById(boardId); boardRepository.delete(board); } @@ -97,8 +97,8 @@ public class BoardServiceImpl implements BoardService { @Transactional public void createComment(long userId, long boardId, RequestCommentDto requestCommentDto) { - User user = userRepository.findById(userId).orElseThrow(IllegalArgumentException::new); - Board board = boardRepository.findById(boardId).orElseThrow(IllegalArgumentException::new); + User user = userRepository.getReferenceById(userId); + Board board = boardRepository.getReferenceById(boardId); Comment comment = Comment.builder() .content(requestCommentDto.getContent()) @@ -122,7 +122,7 @@ public class BoardServiceImpl implements BoardService { @Transactional public void deleteComment(long commentId) { - Comment comment = commentRepository.findById(commentId).orElseThrow(NoSuchElementException::new); + Comment comment = commentRepository.getReferenceById(commentId); commentRepository.delete(comment); } diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/repository/LectureRepository.java b/backend/src/main/java/com/edufocus/edufocus/lecture/repository/LectureRepository.java index a8615d2..eb708fd 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/repository/LectureRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/repository/LectureRepository.java @@ -16,4 +16,5 @@ public interface LectureRepository extends JpaRepository { List findLecturesByUserId(Long userId); + Lecture findByIdAndUserId(long id, long userId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/ws/controller/ChatController.java b/backend/src/main/java/com/edufocus/edufocus/ws/controller/ChatController.java index 30af11a..a5a0e58 100644 --- a/backend/src/main/java/com/edufocus/edufocus/ws/controller/ChatController.java +++ b/backend/src/main/java/com/edufocus/edufocus/ws/controller/ChatController.java @@ -2,16 +2,13 @@ package com.edufocus.edufocus.ws.controller; import com.edufocus.edufocus.user.util.JWTUtil; -import com.edufocus.edufocus.ws.entity.dto.HelloDto; import com.edufocus.edufocus.ws.entity.dto.MessageDto; import com.edufocus.edufocus.ws.entity.dto.QuizDto; -import com.edufocus.edufocus.ws.entity.dto.ResponseChatUserDto; +import com.edufocus.edufocus.ws.entity.dto.ChatUserDto; import com.edufocus.edufocus.ws.service.ChatService; -import jakarta.websocket.Session; import org.springframework.context.event.EventListener; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.messaging.Message; import org.springframework.messaging.handler.annotation.DestinationVariable; import org.springframework.messaging.handler.annotation.Header; import org.springframework.messaging.handler.annotation.MessageMapping; @@ -41,24 +38,27 @@ public class ChatController { this.jwtUtil = jwtUtil; } - @GetMapping("/chat/enter/{lectureId}") - public ResponseEntity enter(@PathVariable long lectureId){ - List chatUsers = chatService.findChatUsers(lectureId); - return new ResponseEntity<>(chatUsers, HttpStatus.OK); - } +// @GetMapping("/chat/enter/{lectureId}") +// public ResponseEntity enter(@PathVariable long lectureId){ +// List chatUsers = chatService.findChatUsers(lectureId); +// +// return new ResponseEntity<>(chatUsers, HttpStatus.OK); +// } - @MessageMapping("/hello/{channelId}") - @SendTo("/sub/channel/{channelId}") - public ResponseChatUserDto hello(@DestinationVariable long channelId, SimpMessageHeaderAccessor simpMessageHeaderAccessor, @Header("Authorization") String token){ - String sessionId = simpMessageHeaderAccessor.getSessionId(); - - long userId = Long.parseLong(jwtUtil.getUserId(token)); - - chatService.saveChatUserInfo(userId, channelId, sessionId); - - return chatService.getChatUserInfo(userId); - } +// @MessageMapping("/hello/{channelId}") +// @SendTo("/sub/channel/{channelId}") +// public ChatUserDto hello(@DestinationVariable long channelId, SimpMessageHeaderAccessor simpMessageHeaderAccessor, @Header("Authorization") String token){ +// String sessionId = simpMessageHeaderAccessor.getSessionId(); +// +// System.out.println("session" + sessionId); +// +// long userId = Long.parseLong(jwtUtil.getUserId(token)); +// +// chatService.saveChatUserInfo(userId, channelId, sessionId); +// +// return chatService.getChatUserInfo(userId); +// } @MessageMapping("/message/{lectureId}") @SendTo("/sub/channel/{lectureId}") @@ -70,12 +70,23 @@ public class ChatController { return quizDto; } - @EventListener - public void handleWebSocketDisconnectListener(SessionDisconnectEvent event){ - StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(event.getMessage()); - String sessionId = headerAccessor.getSessionId(); - long channelId = chatService.getChannelId(sessionId); - simpMessageSendingOperations.convertAndSend("/sub/channel/" + channelId); - } +// @EventListener +// public void handleWebSocketDisconnectListener(SessionDisconnectEvent event){ +// StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(event.getMessage()); +// String sessionId = headerAccessor.getSessionId(); +// +// +// ChatUserDto chatUserDto = chatService.getChatUserInfo(sessionId); +// +// +// if(chatService.checkTeacher(chatUserDto)){ +// chatService.closeChatRoom(chatUserDto.getLectureId()); +// simpMessageSendingOperations.convertAndSend("/sub/channel/" + chatUserDto.getLectureId(), "강의가 종료 됐습니다."); +// return; +// } +// +// chatService.deleteChatUserInfo(chatUserDto.getUserId()); +// simpMessageSendingOperations.convertAndSend("/sub/channel/" + chatUserDto.getLectureId(), chatUserDto); +// } } diff --git a/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/ChatUserDto.java b/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/ChatUserDto.java index f418b8f..3830c35 100644 --- a/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/ChatUserDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/ChatUserDto.java @@ -1,6 +1,14 @@ package com.edufocus.edufocus.ws.entity.dto; -public class ResponseChatUserDto { - int userId; - int name; + +import lombok.*; + +@Builder +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ChatUserDto { + long userId; + long lectureId; + String name; } diff --git a/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/HelloDto.java b/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/HelloDto.java index 55a6c4f..6d1eb41 100644 --- a/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/HelloDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/HelloDto.java @@ -8,6 +8,6 @@ import lombok.*; @NoArgsConstructor @AllArgsConstructor public class HelloDto { - long channelId; + long lectureId; String name; } diff --git a/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/MessageDto.java b/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/MessageDto.java index 17522a9..27fea4d 100644 --- a/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/MessageDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/MessageDto.java @@ -7,5 +7,8 @@ import lombok.Setter; @Getter @Setter public class MessageDto { - int channelId; + long lectureId; + long userId; + String name; + String content; } diff --git a/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/QuizDto.java b/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/QuizDto.java index 1900b3d..57dacb6 100644 --- a/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/QuizDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/QuizDto.java @@ -7,7 +7,7 @@ import lombok.Setter; @Getter @Setter public class QuizDto { - int channelId; + int lectureId; int userId; int quizSetId; } diff --git a/backend/src/main/java/com/edufocus/edufocus/ws/entity/vo/ChatUser.java b/backend/src/main/java/com/edufocus/edufocus/ws/entity/vo/ChatUser.java index 7a5422a..7a1d8d6 100644 --- a/backend/src/main/java/com/edufocus/edufocus/ws/entity/vo/ChatUser.java +++ b/backend/src/main/java/com/edufocus/edufocus/ws/entity/vo/ChatUser.java @@ -2,19 +2,19 @@ package com.edufocus.edufocus.ws.entity.vo; import com.edufocus.edufocus.lecture.entity.Lecture; import com.edufocus.edufocus.user.model.entity.User; +import com.edufocus.edufocus.ws.entity.dto.ChatUserDto; import jakarta.persistence.*; import lombok.*; @Entity @Getter -@Setter @Builder @NoArgsConstructor @AllArgsConstructor public class ChatUser { @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) // 자동 증가 설정 + @GeneratedValue(strategy = GenerationType.IDENTITY) int id; @Column String sessionId; @@ -22,4 +22,12 @@ public class ChatUser { User user; @ManyToOne Lecture lecture; + + public ChatUserDto makeChatUserDto(){ + return ChatUserDto.builder() + .userId(user.getId()) + .name(user.getName()) + .lectureId(lecture.getId()) + .build(); + } } \ No newline at end of file diff --git a/backend/src/main/java/com/edufocus/edufocus/ws/repository/ChatUserRepository.java b/backend/src/main/java/com/edufocus/edufocus/ws/repository/ChatUserRepository.java index 02408c5..a59fd9e 100644 --- a/backend/src/main/java/com/edufocus/edufocus/ws/repository/ChatUserRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/ws/repository/ChatUserRepository.java @@ -1,2 +1,15 @@ -package com.edufocus.edufocus.ws.repository;public interface ChatUserRepository { +package com.edufocus.edufocus.ws.repository; + +import com.edufocus.edufocus.ws.entity.vo.ChatUser; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +import java.util.List; + +public interface ChatUserRepository extends JpaRepository { + public ChatUser findBySessionId(String sessionId); + public List findByLectureId(long lectureId); + + @Query("delete from ChatUser c where c.lecture.id=:lectureId") + public void deleteByLectureId(long lectureId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/ws/service/ChatService.java b/backend/src/main/java/com/edufocus/edufocus/ws/service/ChatService.java index 765ddc1..5399bb9 100644 --- a/backend/src/main/java/com/edufocus/edufocus/ws/service/ChatService.java +++ b/backend/src/main/java/com/edufocus/edufocus/ws/service/ChatService.java @@ -1,10 +1,15 @@ package com.edufocus.edufocus.ws.service; -import com.edufocus.edufocus.ws.entity.dto.ResponseChatUserDto; +import com.edufocus.edufocus.ws.entity.dto.ChatUserDto; + +import java.util.List; public interface ChatService { public void saveChatUserInfo(long userId, long channelId, String sessionId); - public ResponseChatUserDto getChatUserInfo(long userId); - - + public ChatUserDto getChatUserInfo(long userId); + public ChatUserDto getChatUserInfo(String sessionId); + public List findChatUsers(long lectureId); + public boolean checkTeacher(ChatUserDto chatUser); + public void closeChatRoom(long chatRoomId); + public void deleteChatUserInfo(long userId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/ws/service/ChatServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/ws/service/ChatServiceImpl.java index 8baccca..7cc7866 100644 --- a/backend/src/main/java/com/edufocus/edufocus/ws/service/ChatServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/ws/service/ChatServiceImpl.java @@ -1,9 +1,83 @@ package com.edufocus.edufocus.ws.service; +import com.edufocus.edufocus.lecture.entity.Lecture; +import com.edufocus.edufocus.lecture.repository.LectureRepository; +import com.edufocus.edufocus.user.model.entity.User; +import com.edufocus.edufocus.user.model.repository.UserRepository; +import com.edufocus.edufocus.ws.entity.dto.ChatUserDto; +import com.edufocus.edufocus.ws.entity.vo.ChatUser; +import com.edufocus.edufocus.ws.repository.ChatUserRepository; import org.springframework.stereotype.Service; +import java.util.List; +import java.util.stream.Collectors; + @Service public class ChatServiceImpl implements ChatService{ + private final ChatUserRepository chatUserRepository; + private final UserRepository userRepository; + private final LectureRepository lectureRepository; + + public ChatServiceImpl(ChatUserRepository chatUserRepository, UserRepository userRepository, LectureRepository lectureRepository) { + this.chatUserRepository = chatUserRepository; + this.userRepository = userRepository; + this.lectureRepository = lectureRepository; + } + + + @Override + public void saveChatUserInfo(long userId, long lectureId, String sessionId) { + User user = userRepository.getReferenceById(userId); + Lecture lecture = lectureRepository.getReferenceById(lectureId); + + ChatUser chatUser = ChatUser.builder() + .user(user) + .lecture(lecture) + .sessionId(sessionId) + .build(); + + chatUserRepository.save(chatUser); + } + + @Override + public ChatUserDto getChatUserInfo(long userId) { + ChatUser chatUser = chatUserRepository.findById(userId).orElseThrow(IllegalArgumentException::new); + + return chatUser.makeChatUserDto(); + } + + @Override + public ChatUserDto getChatUserInfo(String sessionId) { + ChatUser chatUser = chatUserRepository.findBySessionId(sessionId); + + return chatUser.makeChatUserDto(); + } + + @Override + public List findChatUsers(long lectureId) { + return chatUserRepository.findByLectureId(lectureId) + .stream() + .map(ChatUser::makeChatUserDto) + .collect(Collectors.toList()); + } + + @Override + public boolean checkTeacher(ChatUserDto chatUser) { + Lecture lecture = lectureRepository.findByIdAndUserId(chatUser.getLectureId(), chatUser.getUserId()); + return lecture != null; + } + + @Override + public void closeChatRoom(long lectureId) { + chatUserRepository.deleteByLectureId(lectureId); + } + + @Override + public void deleteChatUserInfo(long userId) { + ChatUser chatUser = chatUserRepository.getReferenceById(userId); + + chatUserRepository.delete(chatUser); + } } From 8d5ddae6eab34f165a5de8d56d101682edbec249 Mon Sep 17 00:00:00 2001 From: yulmam Date: Wed, 24 Jul 2024 10:43:53 +0900 Subject: [PATCH 036/197] =?UTF-8?q?feat=20:=20cors=20=EC=A0=95=EC=B1=85=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/edufocus/edufocus/user/config/WebConfiguration.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java b/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java index 362e689..98007f4 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java @@ -25,10 +25,12 @@ public class WebConfiguration implements WebMvcConfigurer { public void addCorsMappings(CorsRegistry registry) { registry .addMapping("/**") - .allowedOrigins("*") + .allowedOrigins("http://i11a701.p.ssafy.io/", "http://localhost:5173", "http://localhost:4173") .allowedMethods(HttpMethod.GET.name(), HttpMethod.POST.name(), HttpMethod.PUT.name(), HttpMethod.DELETE.name(), HttpMethod.HEAD.name(), HttpMethod.OPTIONS.name(), HttpMethod.PATCH.name()) + .allowCredentials(true) + .allowedHeaders("*") .maxAge(1800); // Pre-flight Caching } From 7aa0ddf184ffe1a64a49e1cd12d6a1e4c472cc98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Wed, 24 Jul 2024 10:53:42 +0900 Subject: [PATCH 037/197] =?UTF-8?q?feat:=20application.properties=20local?= =?UTF-8?q?=20variables=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/main/resources/application.properties | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index d24fac6..71bd62a 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -2,13 +2,15 @@ spring.application.name=edufocus server.port=8080 server.ssl.enabled=false +server.servlet.context-path=${CONTEXT_PATH} + # LiveKit configuration livekit.api.key=${LIVEKIT_API_KEY:devkey} livekit.api.secret=${LIVEKIT_API_SECRET:secret} # JWT Salt (??? ?? ???? ???) -jwt.salt=ssafy-screte-key-20240404-ssafy-screte-key-20240404-ssafy-screte-key-20240404 +jwt.salt=${SALT} # Access Token ?? ?? (??? ??) jwt.access-token.expiretime=3600000 @@ -16,9 +18,9 @@ jwt.access-token.expiretime=3600000 # Refresh Token ?? ?? (??? ??) jwt.refresh-token.expiretime=86400000 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver -spring.datasource.url=jdbc:mysql://localhost:3306/edufocus?useSSL=false -spring.datasource.username=root -spring.datasource.password=root +spring.datasource.url=${DATA_SOURCE_URL} +spring.datasource.username=${USER_NAME} +spring.datasource.password=${USER_PASSWORD} spring.mvc.pathmatch.matching-strategy=ant_path_matcher spring.jpa.database=mysql From 61d5e22ed9f89b16137fa453c1b7edf22578306c Mon Sep 17 00:00:00 2001 From: yulmam Date: Wed, 24 Jul 2024 12:57:18 +0900 Subject: [PATCH 038/197] =?UTF-8?q?feat=20:=20board=20cors=EC=A0=95?= =?UTF-8?q?=EC=B1=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/edufocus/edufocus/board/controller/BoardController.java | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java b/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java index dd45f9b..a1ead74 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java @@ -19,7 +19,6 @@ import java.util.List; */ @RestController @RequestMapping("/board") -@CrossOrigin("*") public class BoardController { private final JWTUtil jwtUtil; From cc935974e71bc65b77156ea1d7e60a0c497258fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Wed, 24 Jul 2024 13:17:44 +0900 Subject: [PATCH 039/197] =?UTF-8?q?feat:=20swagger=20context-path=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/edufocus/edufocus/swagger/SwaggerConfig.java | 1 + backend/src/main/resources/application.properties | 3 +++ 2 files changed, 4 insertions(+) diff --git a/backend/src/main/java/com/edufocus/edufocus/swagger/SwaggerConfig.java b/backend/src/main/java/com/edufocus/edufocus/swagger/SwaggerConfig.java index 7d71ef7..970f7ba 100644 --- a/backend/src/main/java/com/edufocus/edufocus/swagger/SwaggerConfig.java +++ b/backend/src/main/java/com/edufocus/edufocus/swagger/SwaggerConfig.java @@ -15,6 +15,7 @@ public class SwaggerConfig { .info(new Info() .title("에듀포커스 API") .description("") + .version("1.0.0")); } } \ No newline at end of file diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 71bd62a..76ad644 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -28,6 +28,9 @@ spring.jpa.hibernate.ddl-auto=create spring.jpa.show-sql=true +springdoc.api-docs.path=/api/v3/api-docs +springdoc.swagger-ui.path=/api/swagger-ui.html + spring.mail.host=smtp.gmail.com spring.mail.port=587 #spring.mail.username=ssafytestpjt From 5fb3dfc452d75fd0eee6a813a372e6762079c7a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Wed, 24 Jul 2024 13:26:14 +0900 Subject: [PATCH 040/197] =?UTF-8?q?feat:=20swagger-ui=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/edufocus/edufocus/user/config/WebConfiguration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java b/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java index bed956a..70e3cec 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java @@ -43,6 +43,6 @@ public class WebConfiguration implements WebMvcConfigurer { public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(jwtInterceptor) .addPathPatterns("/**") // 모든 경로에 대해 인터셉터 적용 - .excludePathPatterns("/auth/**", "/board/**", "/user/**","/lecture/**","/qna/**"); // 인증 없이 접근 가능한 경로 설정 + .excludePathPatterns("swagger-ui/**","/auth/**", "/board/**", "/user/**","/lecture/**","/qna/**"); // 인증 없이 접근 가능한 경로 설정 } } \ No newline at end of file From 6d03363a0e71f88829e8ef6ee963ef84e083ecb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Wed, 24 Jul 2024 13:52:31 +0900 Subject: [PATCH 041/197] feat: swagger --- .../com/edufocus/edufocus/user/config/WebConfiguration.java | 6 +++++- backend/src/main/resources/application.properties | 3 +-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java b/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java index 70e3cec..8a1f979 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java @@ -18,6 +18,7 @@ public class WebConfiguration implements WebMvcConfigurer { public WebConfiguration(JWTInterceptor jwtInterceptor) { super(); + this.jwtInterceptor = jwtInterceptor; } @@ -42,7 +43,10 @@ public class WebConfiguration implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(jwtInterceptor) + .addPathPatterns("/**") // 모든 경로에 대해 인터셉터 적용 - .excludePathPatterns("swagger-ui/**","/auth/**", "/board/**", "/user/**","/lecture/**","/qna/**"); // 인증 없이 접근 가능한 경로 설정 + .excludePathPatterns("/v3/api-docs/**","/swagger-resources/**","/webjars/**","/swagger-ui/**","/auth/**", "/board/**", "/user/**","/lecture/**","/qna/**"); // 인증 없이 접근 가능한 경로 설정 + + ///v3/api-docs/**, /swagger-resources/**, /webjars/** } } \ No newline at end of file diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 76ad644..37b4488 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -28,8 +28,7 @@ spring.jpa.hibernate.ddl-auto=create spring.jpa.show-sql=true -springdoc.api-docs.path=/api/v3/api-docs -springdoc.swagger-ui.path=/api/swagger-ui.html + spring.mail.host=smtp.gmail.com spring.mail.port=587 From 2f7e8431451cd7463d8e65a5eedb342586c2b1d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Wed, 24 Jul 2024 15:36:42 +0900 Subject: [PATCH 042/197] =?UTF-8?q?feat:=20refreshToken=20cookie=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/edufocus/edufocus/user/controller/UserController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java index e185b6c..f27e42d 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java @@ -77,7 +77,7 @@ public class UserController { Cookie refreshCookie = new Cookie("refresh-token", refreshToken); refreshCookie.setPath("/"); refreshCookie.setHttpOnly(true); - refreshCookie.setSecure(true); // HTTPS에서만 전송되도록 설정 + // refreshCookie.setSecure(true); // HTTPS에서만 전송되도록 설정 // refreshCookie.setSameSite(Cookie.SameSite.NONE); // Cross-Origin 요청에 대해 모두 전송 response.addCookie(refreshCookie); From f6e94fd4d310c1c12b9cbf11aeed40aebe7a9bcd Mon Sep 17 00:00:00 2001 From: kgc9007 Date: Wed, 24 Jul 2024 16:08:28 +0900 Subject: [PATCH 043/197] =?UTF-8?q?feat:=20Lecture=20=EC=9D=B4=EB=AF=B8?= =?UTF-8?q?=EC=A7=80=20=EB=93=B1=EB=A1=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lecture/controller/LectureController.java | 16 +++++++---- .../lecture/entity/LectureCreateRequest.java | 2 -- .../lecture/service/LectureService.java | 3 +- .../lecture/service/LectureServiceImpl.java | 28 +++++++++++++++---- 4 files changed, 35 insertions(+), 14 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java b/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java index 5ba43cd..b1895d5 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java @@ -5,17 +5,19 @@ import com.edufocus.edufocus.lecture.entity.LectureCreateRequest; import com.edufocus.edufocus.lecture.entity.LectureSearchResponse; import com.edufocus.edufocus.lecture.entity.LectureDetailResponse; import com.edufocus.edufocus.lecture.service.LectureService; -import com.edufocus.edufocus.user.model.entity.User; -import com.edufocus.edufocus.user.model.service.UserService; -import com.edufocus.edufocus.user.model.service.UserServiceImpl; import com.edufocus.edufocus.user.util.JWTUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import java.io.File; +import java.io.IOException; import java.util.List; +import java.util.UUID; @RestController @RequestMapping("/lecture") @@ -26,8 +28,9 @@ public class LectureController { private final LectureService lectureService; private final JWTUtil jwtUtil; - @PostMapping - public ResponseEntity createLecture(@RequestHeader("Authorization") String accessToken, @RequestBody LectureCreateRequest lectureCreateRequest) { + @PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + public ResponseEntity createLecture(@RequestHeader("Authorization") String accessToken, @RequestPart LectureCreateRequest lectureCreateRequest + , @RequestPart(value = "image", required = false) MultipartFile image) throws Exception { Long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); Lecture lecture = lectureService.findLectureByTitle(lectureCreateRequest.getTitle()); @@ -36,7 +39,8 @@ public class LectureController { return new ResponseEntity<>(msg, HttpStatus.CONFLICT); } - lectureService.createLecture(userId, lectureCreateRequest); + lectureService.createLecture(userId, lectureCreateRequest, image); + String msg = new String("Lecture registered successfully"); return new ResponseEntity<>(msg, HttpStatus.CREATED); } diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureCreateRequest.java b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureCreateRequest.java index 84c2181..d76afbe 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureCreateRequest.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureCreateRequest.java @@ -15,8 +15,6 @@ public class LectureCreateRequest { private String description; - private String image; - private Date startDate; private Date endDate; diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java index 88fc735..962ed5d 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java @@ -5,6 +5,7 @@ import com.edufocus.edufocus.lecture.entity.LectureCreateRequest; import com.edufocus.edufocus.lecture.entity.LectureSearchResponse; import com.edufocus.edufocus.lecture.entity.LectureDetailResponse; import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; import java.util.List; @@ -12,7 +13,7 @@ import java.util.List; @Service public interface LectureService { - void createLecture(long userId, LectureCreateRequest lectureCreateRequest); + void createLecture(long userId, LectureCreateRequest lectureCreateRequest, MultipartFile image) throws Exception; boolean updateLecture(long userId, long lectureId, LectureCreateRequest lectureCreateRequest); diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java index 56b33cf..73267b9 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java @@ -11,11 +11,17 @@ import com.edufocus.edufocus.user.model.repository.UserRepository; import jakarta.transaction.Transactional; import lombok.Builder; import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; +import java.io.File; +import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.UUID; @Builder @Service @@ -30,19 +36,34 @@ public class LectureServiceImpl implements LectureService { private final RegistrationRepository registrationRepository; @Override - public void createLecture(long userId, LectureCreateRequest lectureCreateRequest) { + public void createLecture(long userId, LectureCreateRequest lectureCreateRequest, MultipartFile image) throws IOException { User user = userRepository.findById(userId).get(); Lecture lecture = new Lecture().builder() .user(user) .title(lectureCreateRequest.getTitle()) .description(lectureCreateRequest.getDescription()) - .image(lectureCreateRequest.getImage()) .startDate(lectureCreateRequest.getStartDate()) .endDate(lectureCreateRequest.getEndDate()) .plan(lectureCreateRequest.getPlan()) .build(); + if (image != null && !image.isEmpty()) { + String uid = UUID.randomUUID().toString(); + + String currentPath = "backend/src/main/resources/images/"; + File checkPathFile = new File(currentPath); + if (!checkPathFile.exists()) { + checkPathFile.mkdirs(); + } + + File savingImage = new File(currentPath + uid + "_" + image.getOriginalFilename()); + image.transferTo(savingImage.toPath()); + String savePath = savingImage.toPath().toString(); + + lecture.setImage(savePath); + } + lectureRepository.save(lecture); } @@ -60,9 +81,6 @@ public class LectureServiceImpl implements LectureService { if (lectureCreateRequest.getDescription() != null) { lecture.setDescription(lectureCreateRequest.getDescription()); } - if (lectureCreateRequest.getImage() != null) { - lecture.setImage(lectureCreateRequest.getImage()); - } if (lectureCreateRequest.getStartDate() != null) { lecture.setStartDate(lectureCreateRequest.getStartDate()); } From d94a09eea635c59164c744c7febc385e055ef53e Mon Sep 17 00:00:00 2001 From: yulmam Date: Thu, 25 Jul 2024 10:07:50 +0900 Subject: [PATCH 044/197] =?UTF-8?q?feat=20:=20ws=20dto=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/edufocus/edufocus/ws/entity/dto/MessageDto.java | 1 - .../java/com/edufocus/edufocus/ws/entity/dto/QuizDto.java | 5 ++--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/MessageDto.java b/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/MessageDto.java index 27fea4d..0e12619 100644 --- a/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/MessageDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/MessageDto.java @@ -7,7 +7,6 @@ import lombok.Setter; @Getter @Setter public class MessageDto { - long lectureId; long userId; String name; String content; diff --git a/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/QuizDto.java b/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/QuizDto.java index 57dacb6..bd97f35 100644 --- a/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/QuizDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/QuizDto.java @@ -7,7 +7,6 @@ import lombok.Setter; @Getter @Setter public class QuizDto { - int lectureId; - int userId; - int quizSetId; + long userId; + long quizSetId; } From 60b875bb3e2b0dae1331fbe4b36a21c6afae5bb9 Mon Sep 17 00:00:00 2001 From: kgc9007 Date: Thu, 25 Jul 2024 13:13:28 +0900 Subject: [PATCH 045/197] =?UTF-8?q?feat:=20quiz=20=EC=82=AC=EC=A7=84=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D=20=EC=B6=94=EA=B0=80,=20=ED=80=B4=EC=A6=88?= =?UTF-8?q?=20=ED=83=80=EC=9E=85=20=EC=BD=94=EB=93=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...72-6b2b-4fa8-9982-f0b7e87daf95_testimg.jpg | Bin 0 -> 8567 bytes ...1b-5e2d-44bf-af27-4afa52212ae3_testimg.jpg | Bin 0 -> 8567 bytes ...d7-716f-4157-985c-bcfeee6087b3_testimg.jpg | Bin 0 -> 8567 bytes ...0b-2918-416e-9309-f24836a02b5b_testimg.jpg | Bin 0 -> 8567 bytes ...eb-0d6e-4979-8b76-a4f72ca59b9a_testimg.jpg | Bin 0 -> 8567 bytes ...3d-0b4d-4348-b9bf-77d7ef2ee39c_testimg.jpg | Bin 0 -> 8567 bytes ...76-5ec0-47e5-80f4-27d03ce9c825_testimg.jpg | Bin 0 -> 8567 bytes ...c8-a836-4e5a-9e81-877186d6e1a8_testimg.jpg | Bin 0 -> 8567 bytes ...46-a05e-4298-94c3-a8be8cc772d7_testimg.jpg | Bin 0 -> 8567 bytes ...bb-6a27-4cf0-91b6-1d16f75e92a3_testimg.jpg | Bin 0 -> 8567 bytes ...0d-4bbd-4d86-b5ea-5ef2b5bfbc43_testimg.jpg | Bin 0 -> 8567 bytes .../quiz/controller/QuizController.java | 36 ++++++++++++------ .../edufocus/edufocus/quiz/entity/Quiz.java | 5 ++- .../quiz/entity/QuizCreateRequest.java | 4 +- .../edufocus/quiz/entity/QuizType.java | 5 +++ .../quiz/entity/SetCreateRequest.java | 2 - .../quiz/service/QuizServiceImpl.java | 7 ++-- .../quiz/service/QuizSetServiceImpl.java | 2 - .../user/config/WebConfiguration.java | 2 +- 19 files changed, 37 insertions(+), 26 deletions(-) create mode 100644 backend/backend/src/main/resources/images/2030c172-6b2b-4fa8-9982-f0b7e87daf95_testimg.jpg create mode 100644 backend/backend/src/main/resources/images/24cdf21b-5e2d-44bf-af27-4afa52212ae3_testimg.jpg create mode 100644 backend/backend/src/main/resources/images/54d7ded7-716f-4157-985c-bcfeee6087b3_testimg.jpg create mode 100644 backend/backend/src/main/resources/images/6128e50b-2918-416e-9309-f24836a02b5b_testimg.jpg create mode 100644 backend/backend/src/main/resources/images/6e41fdeb-0d6e-4979-8b76-a4f72ca59b9a_testimg.jpg create mode 100644 backend/backend/src/main/resources/images/74f3623d-0b4d-4348-b9bf-77d7ef2ee39c_testimg.jpg create mode 100644 backend/backend/src/main/resources/images/79e7db76-5ec0-47e5-80f4-27d03ce9c825_testimg.jpg create mode 100644 backend/backend/src/main/resources/images/84a572c8-a836-4e5a-9e81-877186d6e1a8_testimg.jpg create mode 100644 backend/backend/src/main/resources/images/ce0a9b46-a05e-4298-94c3-a8be8cc772d7_testimg.jpg create mode 100644 backend/backend/src/main/resources/images/dc007fbb-6a27-4cf0-91b6-1d16f75e92a3_testimg.jpg create mode 100644 backend/backend/src/main/resources/images/f98b230d-4bbd-4d86-b5ea-5ef2b5bfbc43_testimg.jpg create mode 100644 backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizType.java diff --git a/backend/backend/src/main/resources/images/2030c172-6b2b-4fa8-9982-f0b7e87daf95_testimg.jpg b/backend/backend/src/main/resources/images/2030c172-6b2b-4fa8-9982-f0b7e87daf95_testimg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c53ac5e358df846b8d20f1928bd0860aa4302f24 GIT binary patch literal 8567 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 createQuizSet(@RequestHeader("Authorization") String accessToken, @RequestBody QuizSetCreateRequest quizSetCreateRequest) { + @PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + public ResponseEntity createQuizSet(@RequestHeader("Authorization") String accessToken, @RequestPart QuizSetCreateRequest quizSetCreateRequest + , @RequestPart(value = "image", required = false) MultipartFile image) throws IOException { Long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); String title = quizSetCreateRequest.getTitle(); - String image = quizSetCreateRequest.getImage(); - - SetCreateRequest setCreateRequest = new SetCreateRequest(userId, title, image); + SetCreateRequest setCreateRequest = new SetCreateRequest(userId, title); QuizSet quizSet = quizSetService.createQuizSet(setCreateRequest); + if (image != null && !image.isEmpty()) { + String uid = UUID.randomUUID().toString(); + + String currentPath = "backend/src/main/resources/images/"; + File checkPathFile = new File(currentPath); + if (!checkPathFile.exists()) { + checkPathFile.mkdirs(); + } + + File savingImage = new File(currentPath + uid + "_" + image.getOriginalFilename()); + image.transferTo(savingImage.toPath()); + String savePath = savingImage.toPath().toString(); + + quizSet.setImage(savePath); + } for (QuizCreateRequest quizCreateRequest : quizSetCreateRequest.getQuizzes()) { quizService.createQuiz(quizSet.getId(), quizCreateRequest); diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Quiz.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Quiz.java index a113b12..ad429ac 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Quiz.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Quiz.java @@ -1,5 +1,6 @@ package com.edufocus.edufocus.quiz.entity; +import com.edufocus.edufocus.user.model.entity.UserRole; import com.fasterxml.jackson.annotation.JsonBackReference; import com.fasterxml.jackson.annotation.JsonManagedReference; import jakarta.persistence.*; @@ -31,8 +32,8 @@ public class Quiz { @Column private String answer; - @Column (name = "is_single") - private boolean isSingle; + @Enumerated(EnumType.STRING) + private QuizType quizType; @Column private String image; diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizCreateRequest.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizCreateRequest.java index eb58041..c140c79 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizCreateRequest.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizCreateRequest.java @@ -15,9 +15,7 @@ public class QuizCreateRequest { private String answer; - private boolean isSingle; - - private String image; + private String quizType; private String choice1; diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizType.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizType.java new file mode 100644 index 0000000..b58f56c --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizType.java @@ -0,0 +1,5 @@ +package com.edufocus.edufocus.quiz.entity; + +public enum QuizType { + SINGLE, MULTIPLE +} diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/SetCreateRequest.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/SetCreateRequest.java index a391ceb..83caff8 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/SetCreateRequest.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/SetCreateRequest.java @@ -13,6 +13,4 @@ public class SetCreateRequest { private String title; - private String image; - } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizServiceImpl.java index b4e0ac9..0412f68 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizServiceImpl.java @@ -3,14 +3,13 @@ package com.edufocus.edufocus.quiz.service; import com.edufocus.edufocus.quiz.entity.Quiz; import com.edufocus.edufocus.quiz.entity.QuizCreateRequest; import com.edufocus.edufocus.quiz.entity.QuizSet; +import com.edufocus.edufocus.quiz.entity.QuizType; import com.edufocus.edufocus.quiz.repository.QuizRepository; import com.edufocus.edufocus.quiz.repository.QuizSetRepository; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; -import java.util.List; - @Service @Transactional @RequiredArgsConstructor @@ -28,11 +27,11 @@ public class QuizServiceImpl implements QuizService { .title(quizCreateRequest.getTitle()) .description(quizCreateRequest.getDescription()) .answer(quizCreateRequest.getAnswer()) - .image(quizCreateRequest.getImage()) + .quizType(QuizType.valueOf(quizCreateRequest.getQuizType())) .quizSet(quizSet) .build(); - if (!quiz.isSingle()) { + if (!quiz.getQuizType().equals(QuizType.MULTIPLE)) { quiz.setChoice1(quizCreateRequest.getChoice1()); quiz.setChoice2(quizCreateRequest.getChoice2()); quiz.setChoice3(quizCreateRequest.getChoice3()); diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java index aefdd03..1836ce5 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java @@ -17,7 +17,6 @@ public class QuizSetServiceImpl implements QuizSetService { private final QuizSetRepository quizSetRepository; private final UserRepository userRepository; - private final QuizRepository quizRepository; @Override @@ -29,7 +28,6 @@ public class QuizSetServiceImpl implements QuizSetService { quizSet.setUser(user); quizSet.setTitle(setCreateRequest.getTitle()); - quizSet.setImage(setCreateRequest.getImage()); return quizSetRepository.save(quizSet); } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java b/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java index 8a1f979..4bc3d83 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java @@ -45,7 +45,7 @@ public class WebConfiguration implements WebMvcConfigurer { registry.addInterceptor(jwtInterceptor) .addPathPatterns("/**") // 모든 경로에 대해 인터셉터 적용 - .excludePathPatterns("/v3/api-docs/**","/swagger-resources/**","/webjars/**","/swagger-ui/**","/auth/**", "/board/**", "/user/**","/lecture/**","/qna/**"); // 인증 없이 접근 가능한 경로 설정 + .excludePathPatterns("/v3/api-docs/**","/swagger-resources/**","/webjars/**","/swagger-ui/**","/auth/**", "/board/**", "/user/**","/lecture/**","/qna/**", "/quiz/**"); // 인증 없이 접근 가능한 경로 설정 ///v3/api-docs/**, /swagger-resources/**, /webjars/** } From 1b709325b7e3340bd384b1a752e42988bdf38b06 Mon Sep 17 00:00:00 2001 From: kgc9007 Date: Thu, 25 Jul 2024 13:17:34 +0900 Subject: [PATCH 046/197] =?UTF-8?q?remove:=20=EC=9D=B4=EB=AF=B8=EC=A7=80?= =?UTF-8?q?=20=ED=8C=8C=EC=9D=BC=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...0c172-6b2b-4fa8-9982-f0b7e87daf95_testimg.jpg | Bin 8567 -> 0 bytes ...df21b-5e2d-44bf-af27-4afa52212ae3_testimg.jpg | Bin 8567 -> 0 bytes ...7ded7-716f-4157-985c-bcfeee6087b3_testimg.jpg | Bin 8567 -> 0 bytes ...8e50b-2918-416e-9309-f24836a02b5b_testimg.jpg | Bin 8567 -> 0 bytes ...1fdeb-0d6e-4979-8b76-a4f72ca59b9a_testimg.jpg | Bin 8567 -> 0 bytes ...3623d-0b4d-4348-b9bf-77d7ef2ee39c_testimg.jpg | Bin 8567 -> 0 bytes ...7db76-5ec0-47e5-80f4-27d03ce9c825_testimg.jpg | Bin 8567 -> 0 bytes ...572c8-a836-4e5a-9e81-877186d6e1a8_testimg.jpg | Bin 8567 -> 0 bytes ...a9b46-a05e-4298-94c3-a8be8cc772d7_testimg.jpg | Bin 8567 -> 0 bytes ...07fbb-6a27-4cf0-91b6-1d16f75e92a3_testimg.jpg | Bin 8567 -> 0 bytes ...b230d-4bbd-4d86-b5ea-5ef2b5bfbc43_testimg.jpg | Bin 8567 -> 0 bytes 11 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 backend/backend/src/main/resources/images/2030c172-6b2b-4fa8-9982-f0b7e87daf95_testimg.jpg delete mode 100644 backend/backend/src/main/resources/images/24cdf21b-5e2d-44bf-af27-4afa52212ae3_testimg.jpg delete mode 100644 backend/backend/src/main/resources/images/54d7ded7-716f-4157-985c-bcfeee6087b3_testimg.jpg delete mode 100644 backend/backend/src/main/resources/images/6128e50b-2918-416e-9309-f24836a02b5b_testimg.jpg delete mode 100644 backend/backend/src/main/resources/images/6e41fdeb-0d6e-4979-8b76-a4f72ca59b9a_testimg.jpg delete mode 100644 backend/backend/src/main/resources/images/74f3623d-0b4d-4348-b9bf-77d7ef2ee39c_testimg.jpg delete mode 100644 backend/backend/src/main/resources/images/79e7db76-5ec0-47e5-80f4-27d03ce9c825_testimg.jpg delete mode 100644 backend/backend/src/main/resources/images/84a572c8-a836-4e5a-9e81-877186d6e1a8_testimg.jpg delete mode 100644 backend/backend/src/main/resources/images/ce0a9b46-a05e-4298-94c3-a8be8cc772d7_testimg.jpg delete mode 100644 backend/backend/src/main/resources/images/dc007fbb-6a27-4cf0-91b6-1d16f75e92a3_testimg.jpg delete mode 100644 backend/backend/src/main/resources/images/f98b230d-4bbd-4d86-b5ea-5ef2b5bfbc43_testimg.jpg diff --git a/backend/backend/src/main/resources/images/2030c172-6b2b-4fa8-9982-f0b7e87daf95_testimg.jpg b/backend/backend/src/main/resources/images/2030c172-6b2b-4fa8-9982-f0b7e87daf95_testimg.jpg deleted file mode 100644 index c53ac5e358df846b8d20f1928bd0860aa4302f24..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8567 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 Date: Thu, 25 Jul 2024 16:56:31 +0900 Subject: [PATCH 047/197] =?UTF-8?q?feat=20:=20=EC=9E=90=EB=8F=99=ED=99=94?= =?UTF-8?q?=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/edufocus/edufocus/user/controller/UserController.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java index f27e42d..9f5e6d7 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java @@ -65,10 +65,8 @@ public class UserController { String accessToken = jwtUtil.createAccessToken(String.valueOf(loginUser.getId())); String refreshToken = jwtUtil.createRefreshToken(String.valueOf(loginUser.getId())); - // 발급받은 refresh token 을 DB에 저장. userService.saveRefreshToken(loginUser.getId(), refreshToken); - // JSON 으로 token 전달. System.out.println(accessToken); resultMap.put("access-token", accessToken); // resultMap.put("refresh-token", refreshToken); @@ -82,7 +80,7 @@ public class UserController { response.addCookie(refreshCookie); - // 쿠키저장 + // 쿠키저장f status = HttpStatus.CREATED; } else { resultMap.put("message", "아이디 또는 패스워드를 확인해 주세요."); From 491573592b9fce71e9ae1ab973ea0b114f90f337 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Fri, 26 Jul 2024 12:36:05 +0900 Subject: [PATCH 048/197] =?UTF-8?q?feat:=20user=20login=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/controller/UserController.java | 26 ++++++------------- 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java index 9f5e6d7..12e4b56 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java @@ -41,17 +41,7 @@ public class UserController { return ResponseEntity.ok("임시 비밀번호가 이메일로 전송되었습니다."); } -// -// @PostMapping("/login") -// public ResponseEntity login(@RequestBody User user) { -// try { -// User loggedInUser = userService.login(user); -// return ResponseEntity.ok(loggedInUser); -// -// } catch (Exception e) { -// throw new RuntimeException(e); -// } - // } + @Operation(summary = "로그인", description = "아이디와 비밀번호를 이용하여 로그인 처리.") @PostMapping("/login") @@ -59,6 +49,9 @@ public class UserController { @RequestBody @Parameter(description = "로그인 시 필요한 회원정보(아이디, 비밀번호).", required = true) User user, HttpServletResponse response) { Map resultMap = new HashMap<>(); HttpStatus status = HttpStatus.ACCEPTED; + + String name= user.getName(); + resultMap.put("name",name); try { User loginUser = userService.login(user); if (loginUser != null) { @@ -69,9 +62,9 @@ public class UserController { System.out.println(accessToken); resultMap.put("access-token", accessToken); - // resultMap.put("refresh-token", refreshToken); - // 쿠키 저장 + + Cookie refreshCookie = new Cookie("refresh-token", refreshToken); refreshCookie.setPath("/"); refreshCookie.setHttpOnly(true); @@ -80,7 +73,7 @@ public class UserController { response.addCookie(refreshCookie); - // 쿠키저장f + status = HttpStatus.CREATED; } else { resultMap.put("message", "아이디 또는 패스워드를 확인해 주세요."); @@ -98,12 +91,9 @@ public class UserController { public ResponseEntity> getInfo( @PathVariable("userId") @Parameter(description = "인증할 회원의 아이디.", required = true) Long userId, HttpServletRequest request) { - //logger.debug("userId : {} ", userId); String id = String.valueOf(userId); - System.out.println("!>>>>>>>>>>>>>>>>>>>>>>>>"); - System.out.println(id); - System.out.println(id.getClass().getName()); + Map resultMap = new HashMap<>(); HttpStatus status = HttpStatus.ACCEPTED; if (jwtUtil.checkToken(request.getHeader("Authorization"))) { From c4373a24af38750ca7a31904ab2d7ccd63341227 Mon Sep 17 00:00:00 2001 From: kgc9007 Date: Fri, 26 Jul 2024 12:51:02 +0900 Subject: [PATCH 049/197] =?UTF-8?q?feat:=20Lecture=20=EA=B0=95=EC=9D=98=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=EB=B3=B4=EA=B8=B0=EC=8B=9C=20=EA=B0=95?= =?UTF-8?q?=EC=9D=98=20=EC=8B=9C=EA=B0=84=20=EC=A1=B0=ED=9A=8C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/edufocus/lecture/entity/Lecture.java | 10 +++++++--- .../lecture/entity/LectureCreateRequest.java | 4 +++- .../lecture/entity/LectureDetailResponse.java | 4 +++- .../lecture/service/LectureServiceImpl.java | 13 +++++++++---- 4 files changed, 22 insertions(+), 9 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java index 24adc42..0a9168a 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java @@ -15,7 +15,8 @@ import java.util.Date; @AllArgsConstructor public class Lecture { - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) @Column private Long id; @@ -29,6 +30,9 @@ public class Lecture { @Lob private String description; + @Lob + private String plan; + @Column private String image; @@ -40,8 +44,8 @@ public class Lecture { @Temporal(TemporalType.DATE) private Date endDate; - @Lob - private String plan; + @Column + private String time; @Column private boolean online; diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureCreateRequest.java b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureCreateRequest.java index d76afbe..dfd02fd 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureCreateRequest.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureCreateRequest.java @@ -15,10 +15,12 @@ public class LectureCreateRequest { private String description; + private String plan; + private Date startDate; private Date endDate; - private String plan; + private String time; } diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureDetailResponse.java b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureDetailResponse.java index 9c14a49..0a5629a 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureDetailResponse.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/LectureDetailResponse.java @@ -21,13 +21,15 @@ public class LectureDetailResponse { private String description; + private String plan; + private String image; private Date startDate; private Date endDate; - private String plan; + private String time; private boolean online; diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java index 73267b9..52a8824 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java @@ -43,9 +43,10 @@ public class LectureServiceImpl implements LectureService { .user(user) .title(lectureCreateRequest.getTitle()) .description(lectureCreateRequest.getDescription()) + .plan(lectureCreateRequest.getPlan()) .startDate(lectureCreateRequest.getStartDate()) .endDate(lectureCreateRequest.getEndDate()) - .plan(lectureCreateRequest.getPlan()) + .time(lectureCreateRequest.getTime()) .build(); if (image != null && !image.isEmpty()) { @@ -81,14 +82,17 @@ public class LectureServiceImpl implements LectureService { if (lectureCreateRequest.getDescription() != null) { lecture.setDescription(lectureCreateRequest.getDescription()); } + if (lectureCreateRequest.getPlan() != null) { + lecture.setPlan(lectureCreateRequest.getPlan()); + } if (lectureCreateRequest.getStartDate() != null) { lecture.setStartDate(lectureCreateRequest.getStartDate()); } if (lectureCreateRequest.getEndDate() != null) { lecture.setEndDate(lectureCreateRequest.getEndDate()); } - if (lectureCreateRequest.getPlan() != null) { - lecture.setPlan(lectureCreateRequest.getPlan()); + if (lectureCreateRequest.getTime() != null) { + lecture.setTime(lectureCreateRequest.getTime()); } lectureRepository.save(lecture); @@ -167,10 +171,11 @@ public class LectureServiceImpl implements LectureService { .id(lecture.get().getId()) .title(lecture.get().getTitle()) .description(lecture.get().getDescription()) + .plan(lecture.get().getPlan()) .image(lecture.get().getImage()) .startDate(lecture.get().getStartDate()) .endDate(lecture.get().getEndDate()) - .plan(lecture.get().getPlan()) + .time(lecture.get().getTime()) .online(lecture.get().isOnline()) .teacherName(lecture.get().getUser().getName()) .status(userStatus) From 37fd8cea68dedc8609bfd5d61c5c737ebfda3ad9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Fri, 26 Jul 2024 13:22:41 +0900 Subject: [PATCH 050/197] =?UTF-8?q?feat:=20user=20login,=20qna=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/edufocus/edufocus/qna/entity/QnaResponseDto.java | 3 ++- .../edufocus/edufocus/user/controller/UserController.java | 7 +++++-- .../edufocus/edufocus/user/model/service/UserService.java | 2 +- .../edufocus/user/model/service/UserServiceImpl.java | 7 +++++++ 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/entity/QnaResponseDto.java b/backend/src/main/java/com/edufocus/edufocus/qna/entity/QnaResponseDto.java index 3ef0b6a..ee7c768 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/entity/QnaResponseDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/entity/QnaResponseDto.java @@ -14,6 +14,7 @@ import java.util.Date; public class QnaResponseDto { + private Long id; private String title; private String username; private String content; @@ -22,7 +23,7 @@ public class QnaResponseDto { public static QnaResponseDto toEntity(Qna qna) { return new QnaResponseDto( - + qna.getId(), qna.getTitle(), qna.getUser().getName(), qna.getContent(), diff --git a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java index 12e4b56..5b36459 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java @@ -50,11 +50,14 @@ public class UserController { Map resultMap = new HashMap<>(); HttpStatus status = HttpStatus.ACCEPTED; - String name= user.getName(); - resultMap.put("name",name); + + try { User loginUser = userService.login(user); if (loginUser != null) { + + String name = loginUser.getName(); + resultMap.put("name",name); String accessToken = jwtUtil.createAccessToken(String.valueOf(loginUser.getId())); String refreshToken = jwtUtil.createRefreshToken(String.valueOf(loginUser.getId())); diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java index 4f3733a..f661fd1 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java @@ -11,5 +11,5 @@ public interface UserService { User userInfo(Long id) throws Exception; void sendEamail(User user) throws Exception; void userCheck(Long id) throws Exception; - + String getUserName(Long id) throws Exception; } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java index 2c39b06..554d971 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java @@ -136,6 +136,13 @@ public class UserServiceImpl implements UserService{ sendEamail(user); } } + + @Override + public String getUserName(Long id) throws Exception { + + return userRepository.findById(id).get().getName(); + } + public String getTempPassword() { char[] charSet = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}; From ec0331e2634a6c88308cc952097d8c0386af000e Mon Sep 17 00:00:00 2001 From: yulmam Date: Fri, 26 Jul 2024 15:50:00 +0900 Subject: [PATCH 051/197] =?UTF-8?q?feat=20:=20rabbitmq=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/build.gradle | 3 + .../board/controller/BoardController.java | 3 + .../user/config/WebConfiguration.java | 66 ++++++++++--------- .../ws/config/WebSocketConfigurer.java | 9 ++- .../ws/controller/ChatController.java | 49 ++++++++------ 5 files changed, 76 insertions(+), 54 deletions(-) diff --git a/backend/build.gradle b/backend/build.gradle index 62702e7..71dea75 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -22,6 +22,9 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'mysql:mysql-connector-java:8.0.33' implementation 'org.springframework.boot:spring-boot-starter-websocket' + implementation 'org.springframework.boot:spring-boot-starter-amqp' + implementation 'org.springframework.boot:spring-boot-starter-reactor-netty' + testImplementation 'org.springframework.amqp:spring-rabbit-test' testImplementation 'org.springframework.boot:spring-boot-starter-test' implementation group: 'io.livekit', name: 'livekit-server', version: '0.6.1' implementation 'org.projectlombok:lombok' diff --git a/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java b/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java index dd45f9b..97cee9e 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java @@ -38,6 +38,9 @@ public class BoardController { ){ List boardSummaries = boardService.findBoards(pageNo, category, lectureId); + if(boardSummaries.isEmpty()) + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + return new ResponseEntity<>(boardSummaries, HttpStatus.OK); } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java b/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java index bed956a..38dff9d 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java @@ -14,35 +14,39 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @EnableWebMvc public class WebConfiguration implements WebMvcConfigurer { - private JWTInterceptor jwtInterceptor; - - public WebConfiguration(JWTInterceptor jwtInterceptor) { - super(); - this.jwtInterceptor = jwtInterceptor; - } - - @Override - public void addCorsMappings(CorsRegistry registry) { - registry - .addMapping("/**") - .allowedOrigins("http://i11a701.p.ssafy.io/", "http://localhost:5173", "http://localhost:4173") - .allowedMethods(HttpMethod.GET.name(), HttpMethod.POST.name(), HttpMethod.PUT.name(), - HttpMethod.DELETE.name(), HttpMethod.HEAD.name(), HttpMethod.OPTIONS.name(), - HttpMethod.PATCH.name()) - .allowCredentials(true) - .allowedHeaders("*") - .maxAge(1800); // Pre-flight Caching - } - - @Override - public void addResourceHandlers(ResourceHandlerRegistry registry) { - registry.addResourceHandler("/img/**").addResourceLocations("classpath:/static/assets/img/"); - registry.addResourceHandler("/*.html**").addResourceLocations("classpath:/static/"); - } - @Override - public void addInterceptors(InterceptorRegistry registry) { - registry.addInterceptor(jwtInterceptor) - .addPathPatterns("/**") // 모든 경로에 대해 인터셉터 적용 - .excludePathPatterns("/auth/**", "/board/**", "/user/**","/lecture/**","/qna/**"); // 인증 없이 접근 가능한 경로 설정 - } +// private JWTInterceptor jwtInterceptor; +// +// public WebConfiguration(JWTInterceptor jwtInterceptor) { +// super(); +// +// this.jwtInterceptor = jwtInterceptor; +// } +// +// @Override +// public void addCorsMappings(CorsRegistry registry) { +// registry +// .addMapping("/**") +// .allowedOrigins("http://i11a701.p.ssafy.io/", "http://localhost:5173", "http://localhost:4173") +// .allowedMethods(HttpMethod.GET.name(), HttpMethod.POST.name(), HttpMethod.PUT.name(), +// HttpMethod.DELETE.name(), HttpMethod.HEAD.name(), HttpMethod.OPTIONS.name(), +// HttpMethod.PATCH.name()) +// .allowCredentials(true) +// .allowedHeaders("*") +// .maxAge(1800); // Pre-flight Caching +// } +// +// @Override +// public void addResourceHandlers(ResourceHandlerRegistry registry) { +// registry.addResourceHandler("/img/**").addResourceLocations("classpath:/static/assets/img/"); +// registry.addResourceHandler("/*.html**").addResourceLocations("classpath:/static/"); +// } +// @Override +// public void addInterceptors(InterceptorRegistry registry) { +// registry.addInterceptor(jwtInterceptor) +// +// .addPathPatterns("/**") // 모든 경로에 대해 인터셉터 적용 +// .excludePathPatterns("/v3/api-docs/**","/swagger-resources/**","/webjars/**","/swagger-ui/**","/auth/**", "/board/**", "/user/**","/lecture/**","/qna/**", "/quiz/**"); // 인증 없이 접근 가능한 경로 설정 +// +// ///v3/api-docs/**, /swagger-resources/**, /webjars/** +// } } \ No newline at end of file diff --git a/backend/src/main/java/com/edufocus/edufocus/ws/config/WebSocketConfigurer.java b/backend/src/main/java/com/edufocus/edufocus/ws/config/WebSocketConfigurer.java index eabc28d..f99bf50 100644 --- a/backend/src/main/java/com/edufocus/edufocus/ws/config/WebSocketConfigurer.java +++ b/backend/src/main/java/com/edufocus/edufocus/ws/config/WebSocketConfigurer.java @@ -12,8 +12,13 @@ public class WebSocketConfigurer implements WebSocketMessageBrokerConfigurer { @Override public void configureMessageBroker(MessageBrokerRegistry registry) { - registry.enableSimpleBroker("/sub"); - registry.setApplicationDestinationPrefixes("/pub"); + registry.setApplicationDestinationPrefixes("/pub") + .enableStompBrokerRelay("/topic") + .setRelayHost("localhost") + .setVirtualHost("/") + .setRelayPort(61613) + .setClientLogin("guest") + .setClientPasscode("guest"); } @Override diff --git a/backend/src/main/java/com/edufocus/edufocus/ws/controller/ChatController.java b/backend/src/main/java/com/edufocus/edufocus/ws/controller/ChatController.java index a5a0e58..5623b66 100644 --- a/backend/src/main/java/com/edufocus/edufocus/ws/controller/ChatController.java +++ b/backend/src/main/java/com/edufocus/edufocus/ws/controller/ChatController.java @@ -16,10 +16,14 @@ import org.springframework.messaging.handler.annotation.SendTo; import org.springframework.messaging.simp.SimpMessageHeaderAccessor; import org.springframework.messaging.simp.SimpMessageSendingOperations; import org.springframework.messaging.simp.stomp.StompHeaderAccessor; +import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.socket.messaging.SessionConnectedEvent; import org.springframework.web.socket.messaging.SessionDisconnectEvent; +import org.springframework.web.socket.messaging.SessionSubscribeEvent; +import org.springframework.web.socket.messaging.SessionUnsubscribeEvent; import java.util.List; @@ -38,34 +42,36 @@ public class ChatController { this.jwtUtil = jwtUtil; } -// @GetMapping("/chat/enter/{lectureId}") -// public ResponseEntity enter(@PathVariable long lectureId){ -// List chatUsers = chatService.findChatUsers(lectureId); -// -// return new ResponseEntity<>(chatUsers, HttpStatus.OK); -// } + @GetMapping("/chat/enter/{lectureId}") + public ResponseEntity enter(@PathVariable long lectureId){ + List chatUsers = chatService.findChatUsers(lectureId); + + return new ResponseEntity<>(chatUsers, HttpStatus.OK); + } -// @MessageMapping("/hello/{channelId}") -// @SendTo("/sub/channel/{channelId}") -// public ChatUserDto hello(@DestinationVariable long channelId, SimpMessageHeaderAccessor simpMessageHeaderAccessor, @Header("Authorization") String token){ -// String sessionId = simpMessageHeaderAccessor.getSessionId(); -// -// System.out.println("session" + sessionId); -// -// long userId = Long.parseLong(jwtUtil.getUserId(token)); -// -// chatService.saveChatUserInfo(userId, channelId, sessionId); -// -// return chatService.getChatUserInfo(userId); -// } + @MessageMapping("/hello/{channelId}") + @SendTo("/topic/{channelId}") + public ChatUserDto hello(@DestinationVariable long channelId, SimpMessageHeaderAccessor simpMessageHeaderAccessor, @Header("Authorization") String token){ + String sessionId = simpMessageHeaderAccessor.getSessionId(); + + System.out.println("session" + sessionId); + + System.out.println("가냐?????"+token); + + long userId = Long.parseLong(jwtUtil.getUserId(token)); + + chatService.saveChatUserInfo(userId, channelId, sessionId); + + return chatService.getChatUserInfo(userId); + } @MessageMapping("/message/{lectureId}") - @SendTo("/sub/channel/{lectureId}") + @SendTo("/topic/{lectureId}") public MessageDto sendMessage(@DestinationVariable long lectureId, MessageDto messageDto){return messageDto;} @MessageMapping("/quiz/{lectureId}") - @SendTo("/sub/channel/{lectureId}") + @SendTo("/topic/{lectureId}") public QuizDto quizStart(@DestinationVariable long lectureId, QuizDto quizDto){ return quizDto; } @@ -88,5 +94,6 @@ public class ChatController { // chatService.deleteChatUserInfo(chatUserDto.getUserId()); // simpMessageSendingOperations.convertAndSend("/sub/channel/" + chatUserDto.getLectureId(), chatUserDto); // } + } From 9c2abc6d6d651c0c0ce9db406f96534b6dc6bec9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Fri, 26 Jul 2024 16:03:30 +0900 Subject: [PATCH 052/197] =?UTF-8?q?feat:=20qna=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/qna/controller/QnaController.java | 4 ++-- .../edufocus/qna/repository/QnaRepository.java | 1 - .../edufocus/qna/service/QnaService.java | 2 +- .../edufocus/qna/service/QnaServiceImpl.java | 18 ++++++++++++++++-- 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java b/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java index 48cc08a..6ba7628 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java @@ -106,9 +106,9 @@ public class QnaController { } @GetMapping("/{id}") - public ResponseEntity getQna(@PathVariable Long id) { + public ResponseEntity getQna(@PathVariable Long id) { try{ - Qna findQna= qnaService.getQna(id); + QnaResponseDto findQna= qnaService.getQna(id); return new ResponseEntity<>(findQna, HttpStatus.ACCEPTED); } catch (SQLException e) { diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/repository/QnaRepository.java b/backend/src/main/java/com/edufocus/edufocus/qna/repository/QnaRepository.java index d2cbf7f..9d1c71e 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/repository/QnaRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/repository/QnaRepository.java @@ -13,7 +13,6 @@ import java.util.List; @Repository public interface QnaRepository extends JpaRepository { - List findByLectureId(Long lecturerId); Page findByLectureId(Long lectureId, Pageable pageable); } diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaService.java b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaService.java index 2c84b6d..de97f93 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaService.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaService.java @@ -16,7 +16,7 @@ public interface QnaService { QnaResponseDto createQna(Long id, QnaRequestDto qnaRequestDto, Long lecture_id) throws SQLException; QnaResponseDto updateQna(Long id,QnaRequestDto qnaRequestDto) throws SQLException; void deleteQna(Long id) throws SQLException; - Qna getQna(Long id) throws SQLException; + QnaResponseDto getQna(Long id) throws SQLException; List getAllQnasByLecture(Long lectureId,int pageNumber) throws SQLException; QnaResponseDto createAnswer(Long id,QnaRequestDto qnaRequestDto) throws SQLException; diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java index e53f585..bed4103 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java @@ -80,8 +80,22 @@ qnaRepository.deleteById(id); } @Override - public Qna getQna(Long id) { - return null; + public QnaResponseDto getQna(Long id) { + Optional qna; + try { + + qna= qnaRepository.findById(id); + + + } catch (Exception e) { + + throw new RuntimeException("Qna 없음 " + id, e); + } + + + + return QnaResponseDto.toEntity(qna.get()); + } @Override From 97a69ae3af6908dc0850c14b2852d0d21fc3f245 Mon Sep 17 00:00:00 2001 From: yulmam Date: Fri, 26 Jul 2024 16:29:58 +0900 Subject: [PATCH 053/197] =?UTF-8?q?feat=20:=20BoardSummaryDto=20create=20t?= =?UTF-8?q?ime=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/EdufocusApplication.java | 2 ++ .../entity/dto/ResponseBoardDetailDto.java | 6 ++--- .../entity/dto/ResponseBoardSummaryDto.java | 3 +++ .../board/entity/dto/ResponseCommentDto.java | 5 ++-- .../edufocus/board/entity/vo/Board.java | 15 +++++++---- .../edufocus/board/entity/vo/Comment.java | 6 ++--- .../src/main/resources/application.properties | 25 +++++++++++++++---- 7 files changed, 44 insertions(+), 18 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/EdufocusApplication.java b/backend/src/main/java/com/edufocus/edufocus/EdufocusApplication.java index 556bff0..e80c9fd 100644 --- a/backend/src/main/java/com/edufocus/edufocus/EdufocusApplication.java +++ b/backend/src/main/java/com/edufocus/edufocus/EdufocusApplication.java @@ -2,7 +2,9 @@ package com.edufocus.edufocus; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +@EnableJpaAuditing @SpringBootApplication public class EdufocusApplication { diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardDetailDto.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardDetailDto.java index 8cf6bc7..e050da7 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardDetailDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardDetailDto.java @@ -5,7 +5,7 @@ import lombok.Builder; import lombok.Getter; import lombok.Setter; -import java.time.LocalTime; +import java.time.LocalDateTime; @Builder @Getter @@ -17,6 +17,6 @@ public class ResponseBoardDetailDto { private String title; private String content; private int viewCount; - private LocalTime createdAt; - private LocalTime modifiedAt; + private LocalDateTime createdAt; + private LocalDateTime modifiedAt; } diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardSummaryDto.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardSummaryDto.java index d3e72a5..bcd1f11 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardSummaryDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardSummaryDto.java @@ -5,6 +5,8 @@ import lombok.Builder; import lombok.Getter; import lombok.Setter; +import java.time.LocalDateTime; + @Builder @Getter @Setter @@ -12,4 +14,5 @@ public class ResponseBoardSummaryDto { private long id; private String name; private String title; + private LocalDateTime createdAt; } diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseCommentDto.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseCommentDto.java index 92156ce..180c6b1 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseCommentDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseCommentDto.java @@ -4,6 +4,7 @@ import lombok.Builder; import lombok.Getter; import lombok.Setter; +import java.time.LocalDateTime; import java.time.LocalTime; @Builder @@ -13,6 +14,6 @@ public class ResponseCommentDto { private long id; private String name; private String content; - private LocalTime createAt; - private LocalTime modifiedAt; + private LocalDateTime createAt; + private LocalDateTime modifiedAt; } diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java index 6272a17..6b283ec 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java @@ -8,8 +8,11 @@ import com.edufocus.edufocus.user.model.entity.User; import com.fasterxml.jackson.annotation.JsonAutoDetect; import jakarta.persistence.*; import lombok.*; -import org.hibernate.annotations.CreationTimestamp; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; +import java.time.LocalDateTime; import java.time.LocalTime; import java.util.List; @@ -18,6 +21,7 @@ import java.util.List; @NoArgsConstructor @AllArgsConstructor @Setter +@EntityListeners(AuditingEntityListener.class) @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) public class Board { @@ -37,11 +41,11 @@ public class Board { @Column(nullable = true) private int viewCount; - @CreationTimestamp - LocalTime createdAt; + @CreatedDate + LocalDateTime createdAt; - @CreationTimestamp - LocalTime modifiedAt; + @LastModifiedDate + LocalDateTime modifiedAt; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") @@ -60,6 +64,7 @@ public class Board { .id(id) .title(title) .name(user.getUserId()) + .createdAt(createdAt) .build(); } diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java index 90c7ebf..667f678 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java @@ -10,7 +10,7 @@ import lombok.Builder; import lombok.NoArgsConstructor; import lombok.Setter; -import java.time.LocalTime; +import java.time.LocalDateTime; @Entity @Builder @@ -26,10 +26,10 @@ public class Comment { private String content; @Column - private LocalTime createdAt; + private LocalDateTime createdAt; @Column - private LocalTime modifiedAt; + private LocalDateTime modifiedAt; @ManyToOne @JoinColumn(name = "user_id") diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index f06afe6..e67341c 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -2,13 +2,15 @@ spring.application.name=edufocus server.port=8080 server.ssl.enabled=false +server.servlet.context-path=${CONTEXT_PATH} + # LiveKit configuration livekit.api.key=${LIVEKIT_API_KEY:devkey} livekit.api.secret=${LIVEKIT_API_SECRET:secret} # JWT Salt (??? ?? ???? ???) -jwt.salt=ssafy-screte-key-20240404-ssafy-screte-key-20240404-ssafy-screte-key-20240404 +jwt.salt=${SALT} # Access Token ?? ?? (??? ??) jwt.access-token.expiretime=3600000 @@ -16,11 +18,24 @@ jwt.access-token.expiretime=3600000 # Refresh Token ?? ?? (??? ??) jwt.refresh-token.expiretime=86400000 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver -spring.datasource.url=jdbc:mysql://localhost:3306/edufocus?useSSL=false -spring.datasource.username=root -spring.datasource.password=root +spring.datasource.url=${DATA_SOURCE_URL} +spring.datasource.username=${USER_NAME} +spring.datasource.password=${USER_PASSWORD} spring.mvc.pathmatch.matching-strategy=ant_path_matcher spring.jpa.database=mysql spring.jpa.hibernate.ddl-auto=create -spring.jpa.show-sql=true \ No newline at end of file +spring.jpa.show-sql=true + + + + +spring.mail.host=smtp.gmail.com +spring.mail.port=587 +#spring.mail.username=ssafytestpjt +#spring.mail.password=trpjbxqialufuzih +spring.mail.username=passfinder111@gmail.com +spring.mail.password=mnlyfkiprltjlsmw + +spring.mail.properties.mail.smtp.auth=true +spring.mail.properties.mail.smtp.starttls.enable=true \ No newline at end of file From 2d88ceed347104d8f4e7af6d019de2659ea03423 Mon Sep 17 00:00:00 2001 From: kgc9007 Date: Mon, 29 Jul 2024 10:55:07 +0900 Subject: [PATCH 054/197] =?UTF-8?q?fix:=20lecture=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=EA=B2=B0=EA=B3=BC=20=EB=B0=98=ED=99=98=EA=B0=92=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lecture/controller/LectureController.java | 27 +++++++------------ .../lecture/service/LectureServiceImpl.java | 1 + 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java b/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java index b1895d5..e97cb07 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java @@ -35,14 +35,12 @@ public class LectureController { Lecture lecture = lectureService.findLectureByTitle(lectureCreateRequest.getTitle()); if (lecture != null) { - String msg = new String("Duplicated Lecture"); - return new ResponseEntity<>(msg, HttpStatus.CONFLICT); + return new ResponseEntity<>(HttpStatus.CONFLICT); } lectureService.createLecture(userId, lectureCreateRequest, image); - String msg = new String("Lecture registered successfully"); - return new ResponseEntity<>(msg, HttpStatus.CREATED); + return new ResponseEntity<>(HttpStatus.CREATED); } @PutMapping("/{lectureId}") @@ -50,11 +48,9 @@ public class LectureController { Long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); if (!lectureService.updateLecture(userId, lectureId, lectureCreateRequest)) { - String msg = new String("Can't update Lecture"); - return new ResponseEntity<>(msg, HttpStatus.UNAUTHORIZED); + return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); } - String msg = new String("Lecture updated successfully"); - return new ResponseEntity<>(msg, HttpStatus.OK); + return new ResponseEntity<>(HttpStatus.OK); } @@ -63,8 +59,7 @@ public class LectureController { Long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); if (!lectureService.deleteLecture(userId, lectureId)) { - String msg = new String("Can't delete Lecture"); - return new ResponseEntity<>(msg, HttpStatus.UNAUTHORIZED); + return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); } return new ResponseEntity<>(HttpStatus.NO_CONTENT); @@ -75,8 +70,7 @@ public class LectureController { List lectures = lectureService.findAllLecture(); if (lectures.isEmpty()) { - String msg = new String("No lectures found"); - return new ResponseEntity<>(msg, HttpStatus.OK); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); } return new ResponseEntity<>(lectures, HttpStatus.OK); @@ -93,8 +87,7 @@ public class LectureController { LectureDetailResponse lectureDetailResponse = lectureService.findLectureById(userId, lectureId); if (lectureDetailResponse == null) { - String msg = new String("Can't find Lecture"); - return new ResponseEntity<>(msg, HttpStatus.OK); + return new ResponseEntity<>(HttpStatus.OK); } @@ -104,8 +97,7 @@ public class LectureController { @GetMapping("/mylecture") public ResponseEntity findMyLecture(@RequestHeader(value = "Authorization", required = false) String accessToken) { if (accessToken == null) { - String msg = new String("Not logged in"); - return new ResponseEntity<>(msg, HttpStatus.OK); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); } Long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); @@ -113,8 +105,7 @@ public class LectureController { List myLectures = lectureService.findMyLecture(userId); if (myLectures.isEmpty()) { - String msg = new String("No lectures found"); - return new ResponseEntity<>(msg, HttpStatus.OK); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); } return new ResponseEntity<>(myLectures, HttpStatus.OK); diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java index 52a8824..e644018 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java @@ -119,6 +119,7 @@ public class LectureServiceImpl implements LectureService { @Override public List findAllLecture() { List lectureList = lectureRepository.findAll(); + System.out.println(lectureList.size()); List lectureSearchResponseList = new ArrayList<>(); for (Lecture lecture : lectureList) { From dc9a6ac3b846748da3ee7138546f7fb5657e4ce2 Mon Sep 17 00:00:00 2001 From: kgc9007 Date: Mon, 29 Jul 2024 11:35:21 +0900 Subject: [PATCH 055/197] =?UTF-8?q?fix:=20Lecture=20=EB=B9=88=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=EC=8B=9C=20=EB=B0=98=ED=99=98=20?= =?UTF-8?q?=ED=83=80=EC=9E=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lecture/controller/LectureController.java | 17 ----------------- .../lecture/service/LectureServiceImpl.java | 8 +------- 2 files changed, 1 insertion(+), 24 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java b/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java index e97cb07..6e04639 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java @@ -14,10 +14,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; -import java.io.File; -import java.io.IOException; import java.util.List; -import java.util.UUID; @RestController @RequestMapping("/lecture") @@ -69,10 +66,6 @@ public class LectureController { public ResponseEntity findAllLecture() { List lectures = lectureService.findAllLecture(); - if (lectures.isEmpty()) { - return new ResponseEntity<>(HttpStatus.NO_CONTENT); - } - return new ResponseEntity<>(lectures, HttpStatus.OK); } @@ -83,14 +76,8 @@ public class LectureController { if (accessToken != null) { userId = Long.parseLong(jwtUtil.getUserId(accessToken)); } - LectureDetailResponse lectureDetailResponse = lectureService.findLectureById(userId, lectureId); - if (lectureDetailResponse == null) { - return new ResponseEntity<>(HttpStatus.OK); - } - - return new ResponseEntity<>(lectureDetailResponse, HttpStatus.OK); } @@ -104,10 +91,6 @@ public class LectureController { List myLectures = lectureService.findMyLecture(userId); - if (myLectures.isEmpty()) { - return new ResponseEntity<>(HttpStatus.NO_CONTENT); - } - return new ResponseEntity<>(myLectures, HttpStatus.OK); } } diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java index e644018..babbea5 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java @@ -18,10 +18,7 @@ import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.UUID; +import java.util.*; @Builder @Service @@ -119,7 +116,6 @@ public class LectureServiceImpl implements LectureService { @Override public List findAllLecture() { List lectureList = lectureRepository.findAll(); - System.out.println(lectureList.size()); List lectureSearchResponseList = new ArrayList<>(); for (Lecture lecture : lectureList) { @@ -137,11 +133,9 @@ public class LectureServiceImpl implements LectureService { @Override public LectureDetailResponse findLectureById(Long userId, long lectureId) { Optional lecture = lectureRepository.findById(lectureId); - if (lecture.isEmpty()) { return null; } - lecture = Optional.of(lecture.get()); String userStatus; if (userId == null) { From 32a176b679c5acd02e0439897ce9aa458600a519 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Mon, 29 Jul 2024 14:08:44 +0900 Subject: [PATCH 056/197] =?UTF-8?q?feat:=20=EA=B0=95=EC=9D=98=20=EC=8B=9C?= =?UTF-8?q?=EC=9E=91,=20=EA=B0=95=EC=9D=98=20=EC=B0=B8=EC=97=AC=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/lecture/entity/Lecture.java | 2 +- .../lecture/service/LectureService.java | 2 + .../lecture/service/LectureServiceImpl.java | 24 +++ .../service/RegistrationService.java | 2 + .../service/RegistrationServiceImpl.java | 7 + .../user/config/WebConfiguration.java | 4 +- .../edufocus/video/controller/Controller.java | 150 +++++++++++++----- .../edufocus/video/service/VideoSertvice.java | 8 + .../video/service/VideoServiceImpl.java | 21 +++ .../src/main/resources/application.properties | 3 + 10 files changed, 179 insertions(+), 44 deletions(-) create mode 100644 backend/src/main/java/com/edufocus/edufocus/video/service/VideoSertvice.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/video/service/VideoServiceImpl.java diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java index 0a9168a..f74d97f 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java @@ -47,7 +47,7 @@ public class Lecture { @Column private String time; - @Column + @Column(columnDefinition = "boolean default false") private boolean online; } diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java index 962ed5d..65153a0 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java @@ -26,4 +26,6 @@ public interface LectureService { List findMyLecture(long userId); Lecture findLectureByTitle(String title); + + void changeState(Long lectureId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java index 52a8824..0f841ad 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java @@ -221,4 +221,28 @@ public class LectureServiceImpl implements LectureService { public Lecture findLectureByTitle(String title) { return lectureRepository.findByTitle(title); } + + @Override + public void changeState(Long id) { + + Optional lecture = lectureRepository.findById(id); + + Lecture l; + if(lecture.isPresent()) + { + l = lecture.get(); + + System.out.println(l.isOnline()); + l.setOnline(true); + System.out.println(l.isOnline()); + + + }else { + + throw new RuntimeException("Lecture not found with id: " + id); + } + lectureRepository.save(l); + } + + } diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationService.java b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationService.java index 96d89f6..bc27b37 100644 --- a/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationService.java +++ b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationService.java @@ -1,6 +1,7 @@ package com.edufocus.edufocus.registration.service; import com.edufocus.edufocus.registration.entity.Registration; +import com.edufocus.edufocus.registration.entity.RegistrationStatus; import org.springframework.stereotype.Service; @Service @@ -12,4 +13,5 @@ public interface RegistrationService { boolean deleteRegistration(long userId, long registrationId); + RegistrationStatus isOnline(Long userId , Long lectureId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java index 7c156bf..0eca5b5 100644 --- a/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java @@ -62,4 +62,11 @@ public class RegistrationServiceImpl implements RegistrationService { return true; } + @Override + public RegistrationStatus isOnline(Long userId, Long lectureId) { + + Registration registration = registrationRepository.findByUserIdAndLectureId(userId,lectureId); + return registration.getStatus(); + } + } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java b/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java index 4bc3d83..58213a3 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java @@ -26,7 +26,7 @@ public class WebConfiguration implements WebMvcConfigurer { public void addCorsMappings(CorsRegistry registry) { registry .addMapping("/**") - .allowedOrigins("http://i11a701.p.ssafy.io/", "http://localhost:5173", "http://localhost:4173") + .allowedOrigins("http://i11a701.p.ssafy.io/", "http://localhost:5173", "http://localhost:4173","http://localhost:5080") .allowedMethods(HttpMethod.GET.name(), HttpMethod.POST.name(), HttpMethod.PUT.name(), HttpMethod.DELETE.name(), HttpMethod.HEAD.name(), HttpMethod.OPTIONS.name(), HttpMethod.PATCH.name()) @@ -45,7 +45,7 @@ public class WebConfiguration implements WebMvcConfigurer { registry.addInterceptor(jwtInterceptor) .addPathPatterns("/**") // 모든 경로에 대해 인터셉터 적용 - .excludePathPatterns("/v3/api-docs/**","/swagger-resources/**","/webjars/**","/swagger-ui/**","/auth/**", "/board/**", "/user/**","/lecture/**","/qna/**", "/quiz/**"); // 인증 없이 접근 가능한 경로 설정 + .excludePathPatterns("/v3/api-docs/**","/swagger-resources/**","/webjars/**","/swagger-ui/**","/auth/**", "/board/**", "/user/**","/lecture/**","/qna/**", "/quiz/**","/video/**"); // 인증 없이 접근 가능한 경로 설정 ///v3/api-docs/**, /swagger-resources/**, /webjars/** } diff --git a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java index ed35745..36cadb8 100644 --- a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java +++ b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java @@ -1,20 +1,37 @@ package com.edufocus.edufocus.video.controller; -import io.livekit.server.AccessToken; -import io.livekit.server.RoomJoin; -import io.livekit.server.RoomName; -import io.livekit.server.WebhookReceiver; -import livekit.LivekitWebhook.WebhookEvent; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - import java.util.Map; -@CrossOrigin(origins = "*") -@RestController -public class Controller { +import com.edufocus.edufocus.lecture.entity.Lecture; +import com.edufocus.edufocus.lecture.entity.LectureDetailResponse; +import com.edufocus.edufocus.lecture.service.LectureService; +import com.edufocus.edufocus.registration.entity.RegistrationStatus; +import com.edufocus.edufocus.registration.service.RegistrationService; +import com.edufocus.edufocus.user.model.service.UserService; +import com.edufocus.edufocus.user.util.JWTUtil; +import com.edufocus.edufocus.video.service.VideoSertvice; +import io.livekit.server.*; +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import livekit.LivekitWebhook.WebhookEvent; + +//@CrossOrigin(origins = "*") +@RestController +@RequestMapping("/video") +@Slf4j +@RequiredArgsConstructor +public class Controller { + private final JWTUtil jwtUtil; + private final UserService userService; + private final LectureService lectureService; + private final VideoSertvice videoSertvice; + private final RegistrationService registrationService; @Value("${livekit.api.key}") private String LIVEKIT_API_KEY; @@ -25,47 +42,98 @@ public class Controller { * @param params JSON object with roomName and participantName * @return JSON object with the JWT token */ - @PostMapping(value = "/token") - public ResponseEntity> createToken(@RequestBody Map params) { - String roomName = params.get("roomName"); - String participantName = params.get("participantName"); +// @PostMapping(value = "/token") +// public ResponseEntity> createToken(@RequestBody Map params) { +// String roomName = params.get("roomName"); +// String participantName = params.get("participantName"); +// +// if (roomName == null || participantName == null) { +// return ResponseEntity.badRequest().body(Map.of("errorMessage", "roomName and participantName are required")); +// } +// +// AccessToken token = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); +// token.setName(participantName); +// token.setIdentity(participantName); +// token.addGrants(new RoomJoin(true), new RoomName(roomName)); +// +// +// +// return ResponseEntity.ok(Map.of("token", token.toJwt())); +// } - // - // - // - // - // - // + @PostMapping(value = "/makeroom/{lecture_id}") + public ResponseEntity> startLecture(@PathVariable("lecture_id") Long id, HttpServletRequest request) throws Exception { + + String userToken = request.getHeader("Authorization"); + + Long userId = Long.parseLong(jwtUtil.getUserId(userToken)); + LectureDetailResponse lecture= lectureService.findLectureById(userId,id); + + String roomName = lecture.getTitle(); + String participantName = userService.getUserName(userId); - if (roomName == null || participantName == null) { - return ResponseEntity.badRequest().body(Map.of("errorMessage", "roomName and participantName are required")); - } AccessToken token = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); - - token.setName(participantName); token.setIdentity(participantName); - token.addGrants(new RoomJoin(true), new RoomName(roomName)); + token.addGrants(new RoomJoin(true), new RoomName(roomName),new RoomCreate(true)); + + videoSertvice.startOnline(userId,id); + - // 방이름으로 입장하는건데 - // 만약 수강생에 DB에 신청한 강의명이 없다면 들어갈수 없음 - // 검증 로직만 추가하면 될듯? return ResponseEntity.ok(Map.of("token", token.toJwt())); } - @PostMapping(value = "/webhook", consumes = "application/webhook+json") - public ResponseEntity receiveWebhook(@RequestHeader("Authorization") String authHeader, @RequestBody String body) { - WebhookReceiver webhookReceiver = new WebhookReceiver(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); - try { - WebhookEvent event = webhookReceiver.receive(body, authHeader); - System.out.println("LiveKit Webhook: " + event.toString()); - } catch (Exception e) { - System.err.println("Error validating webhook event: " + e.getMessage()); - } - return ResponseEntity.ok("ok"); + + @PostMapping(value = "/joinroom/{lecture_id}") + public ResponseEntity> joinRoom(@PathVariable("lecture_id") Long id, HttpServletRequest request) throws Exception { + + String userToken = request.getHeader("Authorization"); + + Long userId = Long.parseLong(jwtUtil.getUserId(userToken)); + LectureDetailResponse lecture= lectureService.findLectureById(userId,id); + + + RegistrationStatus registrationStatus = registrationService.isOnline(userId,id); + + if(registrationStatus==RegistrationStatus.ACCEPTED) + { + String roomName = lecture.getTitle(); + String participantName = userService.getUserName(userId); + + + AccessToken token = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); + token.setName(participantName); + token.setIdentity(participantName); + token.addGrants(new RoomJoin(true), new RoomName(roomName)); + + videoSertvice.startOnline(userId,id); + + + + return ResponseEntity.ok(Map.of("token", token.toJwt())); + } + else{ + return ResponseEntity.status(HttpStatus.FORBIDDEN).body(Map.of("errorMessage", "Not accepted")); + + } + + + + } + + @PostMapping(value = "/livekit/webhook", consumes = "application/webhook+json") + public ResponseEntity receiveWebhook(@RequestHeader("Authorization") String authHeader, @RequestBody String body) { + WebhookReceiver webhookReceiver = new WebhookReceiver(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); + try { + WebhookEvent event = webhookReceiver.receive(body, authHeader); + System.out.println("LiveKit Webhook: " + event.toString()); + } catch (Exception e) { + System.err.println("Error validating webhook event: " + e.getMessage()); + } + return ResponseEntity.ok("ok"); } } diff --git a/backend/src/main/java/com/edufocus/edufocus/video/service/VideoSertvice.java b/backend/src/main/java/com/edufocus/edufocus/video/service/VideoSertvice.java new file mode 100644 index 0000000..981c5c4 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/video/service/VideoSertvice.java @@ -0,0 +1,8 @@ +package com.edufocus.edufocus.video.service; + +import java.sql.SQLException; + +public interface VideoSertvice { + + void startOnline(Long userId,Long lectureId) throws SQLException; +} diff --git a/backend/src/main/java/com/edufocus/edufocus/video/service/VideoServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/video/service/VideoServiceImpl.java new file mode 100644 index 0000000..af82559 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/video/service/VideoServiceImpl.java @@ -0,0 +1,21 @@ +package com.edufocus.edufocus.video.service; + +import com.edufocus.edufocus.lecture.entity.Lecture; +import com.edufocus.edufocus.lecture.service.LectureService; +import jakarta.transaction.Transactional; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.sql.SQLException; +@Service +@Transactional +@RequiredArgsConstructor +public class VideoServiceImpl implements VideoSertvice{ + + private final LectureService lectureService; + @Override + public void startOnline(Long userId,Long lectureId) throws SQLException { + + lectureService.changeState(lectureId); + } +} diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 37b4488..b188226 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -4,6 +4,9 @@ server.port=8080 server.ssl.enabled=false server.servlet.context-path=${CONTEXT_PATH} +# openvidu +#server.port=${SERVER_PORT:6080} + # LiveKit configuration livekit.api.key=${LIVEKIT_API_KEY:devkey} From 16fd51641a126b1613be0850aef00da29ef533d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Mon, 29 Jul 2024 14:33:27 +0900 Subject: [PATCH 057/197] =?UTF-8?q?feat:=20regisration=20cors=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/edufocus/edufocus/user/config/WebConfiguration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java b/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java index 58213a3..9b421ef 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java @@ -45,7 +45,7 @@ public class WebConfiguration implements WebMvcConfigurer { registry.addInterceptor(jwtInterceptor) .addPathPatterns("/**") // 모든 경로에 대해 인터셉터 적용 - .excludePathPatterns("/v3/api-docs/**","/swagger-resources/**","/webjars/**","/swagger-ui/**","/auth/**", "/board/**", "/user/**","/lecture/**","/qna/**", "/quiz/**","/video/**"); // 인증 없이 접근 가능한 경로 설정 + .excludePathPatterns("/v3/api-docs/**","/swagger-resources/**","/webjars/**","/swagger-ui/**","/auth/**", "/board/**", "/user/**","/lecture/**","/qna/**", "/quiz/**","/video/**","/registration/**"); // 인증 없이 접근 가능한 경로 설정 ///v3/api-docs/**, /swagger-resources/**, /webjars/** } From 32d2592841c32eb65e9259383aa4232c803bfb06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Mon, 29 Jul 2024 14:58:44 +0900 Subject: [PATCH 058/197] feat: cors --- .../edufocus/edufocus/user/model/entity/InfoDto.java | 8 ++++++++ .../edufocus/user/model/service/UserService.java | 3 +++ .../edufocus/user/model/service/UserServiceImpl.java | 10 ++++++++++ .../edufocus/edufocus/video/controller/Controller.java | 3 ++- 4 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 backend/src/main/java/com/edufocus/edufocus/user/model/entity/InfoDto.java diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/InfoDto.java b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/InfoDto.java new file mode 100644 index 0000000..ed96b9c --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/InfoDto.java @@ -0,0 +1,8 @@ +package com.edufocus.edufocus.user.model.entity; + +public class InfoDto { + + String name; + String email; + +} diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java index f661fd1..2f63135 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java @@ -12,4 +12,7 @@ public interface UserService { void sendEamail(User user) throws Exception; void userCheck(Long id) throws Exception; String getUserName(Long id) throws Exception; + void changeuInfo(Long id) throws Exception; + void changePassword(Long id) throws Exception; + } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java index 554d971..66bb873 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java @@ -143,6 +143,16 @@ public class UserServiceImpl implements UserService{ return userRepository.findById(id).get().getName(); } + @Override + public void changeuInfo(Long id) throws Exception { + + } + + @Override + public void changePassword(Long id) throws Exception { + + } + public String getTempPassword() { char[] charSet = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}; diff --git a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java index 36cadb8..b6c1493 100644 --- a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java +++ b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java @@ -21,11 +21,12 @@ import org.springframework.web.bind.annotation.*; import livekit.LivekitWebhook.WebhookEvent; -//@CrossOrigin(origins = "*") +@CrossOrigin(origins = "*") @RestController @RequestMapping("/video") @Slf4j @RequiredArgsConstructor + public class Controller { private final JWTUtil jwtUtil; private final UserService userService; From bcf36665f9eeaa85e8c40c5a34139f05aab1d42d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Mon, 29 Jul 2024 15:11:25 +0900 Subject: [PATCH 059/197] =?UTF-8?q?feat:=20cors=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/edufocus/edufocus/video/controller/Controller.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java index b6c1493..b36b4d2 100644 --- a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java +++ b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java @@ -21,7 +21,7 @@ import org.springframework.web.bind.annotation.*; import livekit.LivekitWebhook.WebhookEvent; -@CrossOrigin(origins = "*") + @RestController @RequestMapping("/video") @Slf4j @@ -66,6 +66,8 @@ public class Controller { public ResponseEntity> startLecture(@PathVariable("lecture_id") Long id, HttpServletRequest request) throws Exception { String userToken = request.getHeader("Authorization"); + log.info("userToekn : ", userToken); + Long userId = Long.parseLong(jwtUtil.getUserId(userToken)); LectureDetailResponse lecture= lectureService.findLectureById(userId,id); From 764f5bd30db768bf0818a6daf3c89df0d122f763 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Mon, 29 Jul 2024 15:18:37 +0900 Subject: [PATCH 060/197] feat: video --- .../edufocus/video/controller/Controller.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java index b36b4d2..6ad9ef3 100644 --- a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java +++ b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java @@ -99,10 +99,10 @@ public class Controller { LectureDetailResponse lecture= lectureService.findLectureById(userId,id); - RegistrationStatus registrationStatus = registrationService.isOnline(userId,id); + //RegistrationStatus registrationStatus = registrationService.isOnline(userId,id); - if(registrationStatus==RegistrationStatus.ACCEPTED) - { +// if(registrationStatus==RegistrationStatus.ACCEPTED) +// { String roomName = lecture.getTitle(); String participantName = userService.getUserName(userId); @@ -112,16 +112,16 @@ public class Controller { token.setIdentity(participantName); token.addGrants(new RoomJoin(true), new RoomName(roomName)); - videoSertvice.startOnline(userId,id); + //videoSertvice.startOnline(userId,id); return ResponseEntity.ok(Map.of("token", token.toJwt())); - } - else{ - return ResponseEntity.status(HttpStatus.FORBIDDEN).body(Map.of("errorMessage", "Not accepted")); - - } +// } +// else{ +// return ResponseEntity.status(HttpStatus.FORBIDDEN).body(Map.of("errorMessage", "Not accepted")); +// +// } From c94827259f0d141ecbf0fe51294259ec9c70cb94 Mon Sep 17 00:00:00 2001 From: yulmam Date: Mon, 29 Jul 2024 17:53:55 +0900 Subject: [PATCH 061/197] =?UTF-8?q?feat=20:=20rabbitmq=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/edufocus/edufocus/ws/config/RabbitConfig.java | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 backend/src/main/java/com/edufocus/edufocus/ws/config/RabbitConfig.java diff --git a/backend/src/main/java/com/edufocus/edufocus/ws/config/RabbitConfig.java b/backend/src/main/java/com/edufocus/edufocus/ws/config/RabbitConfig.java new file mode 100644 index 0000000..783000a --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/ws/config/RabbitConfig.java @@ -0,0 +1,2 @@ +package com.edufocus.edufocus.ws.config;public class RabbitConfig { +} From 8dd5676a265c5c7aba2ec24c446181defed77cbd Mon Sep 17 00:00:00 2001 From: kgc9007 Date: Mon, 29 Jul 2024 17:54:27 +0900 Subject: [PATCH 062/197] =?UTF-8?q?feat:=20Quiz=20=EB=93=B1=EB=A1=9D,=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EC=9A=94=EC=B2=AD=20=ED=98=95=EC=8B=9D=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../quiz/controller/QuizController.java | 24 ++---------- .../edufocus/edufocus/quiz/entity/Choice.java | 29 ++++++++++++++ ...eRequest.java => ChoiceCreateRequest.java} | 7 ++-- .../edufocus/edufocus/quiz/entity/Quiz.java | 35 +++++++---------- .../quiz/entity/QuizCreateRequest.java | 16 ++------ .../edufocus/quiz/entity/QuizResponse.java | 21 ++++++++++ .../quiz/entity/QuizSetCreateRequest.java | 4 -- .../edufocus/quiz/entity/QuizSetResponse.java | 20 ++++++++++ .../edufocus/quiz/entity/QuizType.java | 5 --- .../quiz/repository/ChoiceRepository.java | 8 ++++ .../quiz/repository/QuizRepository.java | 1 - .../edufocus/quiz/service/ChoiceService.java | 7 ++++ .../quiz/service/ChoiceServiceImpl.java | 25 ++++++++++++ .../edufocus/quiz/service/QuizService.java | 4 +- .../quiz/service/QuizServiceImpl.java | 39 +++++++++++-------- .../edufocus/quiz/service/QuizSetService.java | 7 +++- .../quiz/service/QuizSetServiceImpl.java | 36 ++++++++++++++--- .../controller/RegistrationController.java | 4 +- 18 files changed, 196 insertions(+), 96 deletions(-) create mode 100644 backend/src/main/java/com/edufocus/edufocus/quiz/entity/Choice.java rename backend/src/main/java/com/edufocus/edufocus/quiz/entity/{SetCreateRequest.java => ChoiceCreateRequest.java} (68%) create mode 100644 backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizResponse.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSetResponse.java delete mode 100644 backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizType.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/quiz/repository/ChoiceRepository.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/quiz/service/ChoiceService.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/quiz/service/ChoiceServiceImpl.java diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java b/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java index fc3abcd..ac58dd2 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java @@ -33,28 +33,10 @@ public class QuizController { , @RequestPart(value = "image", required = false) MultipartFile image) throws IOException { Long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); - String title = quizSetCreateRequest.getTitle(); - SetCreateRequest setCreateRequest = new SetCreateRequest(userId, title); - - QuizSet quizSet = quizSetService.createQuizSet(setCreateRequest); - if (image != null && !image.isEmpty()) { - String uid = UUID.randomUUID().toString(); - - String currentPath = "backend/src/main/resources/images/"; - File checkPathFile = new File(currentPath); - if (!checkPathFile.exists()) { - checkPathFile.mkdirs(); - } - - File savingImage = new File(currentPath + uid + "_" + image.getOriginalFilename()); - image.transferTo(savingImage.toPath()); - String savePath = savingImage.toPath().toString(); - - quizSet.setImage(savePath); - } + QuizSet quizSet = quizSetService.createQuizSet(userId, quizSetCreateRequest.getTitle()); for (QuizCreateRequest quizCreateRequest : quizSetCreateRequest.getQuizzes()) { - quizService.createQuiz(quizSet.getId(), quizCreateRequest); + quizService.createQuiz(quizSet, quizCreateRequest); } return new ResponseEntity<>(HttpStatus.CREATED); @@ -62,7 +44,7 @@ public class QuizController { @GetMapping("/{quizsetId}") public ResponseEntity getQuizzes(@PathVariable Long quizsetId) { - QuizSet quizSet = quizSetService.findQuizSet(quizsetId); + QuizSetResponse quizSet = quizSetService.findQuizSetResponse(quizsetId); return new ResponseEntity<>(quizSet, HttpStatus.OK); } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Choice.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Choice.java new file mode 100644 index 0000000..d31f8a1 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Choice.java @@ -0,0 +1,29 @@ +package com.edufocus.edufocus.quiz.entity; + +import com.fasterxml.jackson.annotation.JsonBackReference; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Getter +@Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class Choice { + + @Id + @GeneratedValue + private Long id; + + @ManyToOne + @JoinColumn(name = "QuizId") + @JsonBackReference + private Quiz quiz; + + @Column + private int num; + + @Column + private String content; +} diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/SetCreateRequest.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/ChoiceCreateRequest.java similarity index 68% rename from backend/src/main/java/com/edufocus/edufocus/quiz/entity/SetCreateRequest.java rename to backend/src/main/java/com/edufocus/edufocus/quiz/entity/ChoiceCreateRequest.java index 83caff8..80f8fc4 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/SetCreateRequest.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/ChoiceCreateRequest.java @@ -7,10 +7,9 @@ import lombok.NoArgsConstructor; @Getter @NoArgsConstructor @AllArgsConstructor -public class SetCreateRequest { +public class ChoiceCreateRequest { - private Long UserId; - - private String title; + private int num; + private String content; } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Quiz.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Quiz.java index ad429ac..f9a3cc7 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Quiz.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Quiz.java @@ -1,11 +1,12 @@ package com.edufocus.edufocus.quiz.entity; -import com.edufocus.edufocus.user.model.entity.UserRole; import com.fasterxml.jackson.annotation.JsonBackReference; import com.fasterxml.jackson.annotation.JsonManagedReference; import jakarta.persistence.*; import lombok.*; +import java.util.List; + @Entity @Getter @Setter @@ -24,31 +25,17 @@ public class Quiz { private QuizSet quizSet; @Column - private String title; - - @Column - private String description; - - @Column - private String answer; - - @Enumerated(EnumType.STRING) - private QuizType quizType; + private String question; @Column private String image; @Column - private String choice1; + private String answer; - @Column - private String choice2; - - @Column - private String choice3; - - @Column - private String choice4; + @OneToMany(mappedBy = "quiz") + @JsonManagedReference + private List choices; public void setQuizSet(QuizSet quizSet) { this.quizSet = quizSet; @@ -57,4 +44,12 @@ public class Quiz { quizSet.getQuizzes().remove(this); } } + + public void addChoice(Choice choice) { + this.choices.add(choice); + + if (choice.getQuiz() != this) { + choice.setQuiz(this); + } + } } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizCreateRequest.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizCreateRequest.java index c140c79..9ac60bd 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizCreateRequest.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizCreateRequest.java @@ -4,24 +4,16 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; +import java.util.List; + @Getter @NoArgsConstructor @AllArgsConstructor public class QuizCreateRequest { - private String title; - - private String description; + private String question; private String answer; - private String quizType; - - private String choice1; - - private String choice2; - - private String choice3; - - private String choice4; + private List choices; } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizResponse.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizResponse.java new file mode 100644 index 0000000..0b0be9f --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizResponse.java @@ -0,0 +1,21 @@ +package com.edufocus.edufocus.quiz.entity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class QuizResponse { + + private String question; + + private String image; + + private List choices; +} diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSetCreateRequest.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSetCreateRequest.java index 20a0025..0a137a3 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSetCreateRequest.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSetCreateRequest.java @@ -11,12 +11,8 @@ import java.util.List; @AllArgsConstructor public class QuizSetCreateRequest { - private Long UserId; - private String title; - private String image; - private List quizzes; } \ No newline at end of file diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSetResponse.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSetResponse.java new file mode 100644 index 0000000..9fdaf5e --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSetResponse.java @@ -0,0 +1,20 @@ +package com.edufocus.edufocus.quiz.entity; + +import lombok.*; + +import java.util.ArrayList; +import java.util.List; + +@Getter +@Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class QuizSetResponse { + + private String title; + + private String image; + + private List quizzes; +} diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizType.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizType.java deleted file mode 100644 index b58f56c..0000000 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizType.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.edufocus.edufocus.quiz.entity; - -public enum QuizType { - SINGLE, MULTIPLE -} diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/repository/ChoiceRepository.java b/backend/src/main/java/com/edufocus/edufocus/quiz/repository/ChoiceRepository.java new file mode 100644 index 0000000..740dda2 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/repository/ChoiceRepository.java @@ -0,0 +1,8 @@ +package com.edufocus.edufocus.quiz.repository; + +import com.edufocus.edufocus.quiz.entity.Choice; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ChoiceRepository extends JpaRepository { + +} diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/repository/QuizRepository.java b/backend/src/main/java/com/edufocus/edufocus/quiz/repository/QuizRepository.java index 9e7d345..c271ee2 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/repository/QuizRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/repository/QuizRepository.java @@ -3,7 +3,6 @@ package com.edufocus.edufocus.quiz.repository; import com.edufocus.edufocus.quiz.entity.Quiz; import org.springframework.data.jpa.repository.JpaRepository; - public interface QuizRepository extends JpaRepository { } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/ChoiceService.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/ChoiceService.java new file mode 100644 index 0000000..22b81d1 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/service/ChoiceService.java @@ -0,0 +1,7 @@ +package com.edufocus.edufocus.quiz.service; + +import org.springframework.stereotype.Service; + +@Service +public interface ChoiceService { +} diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/ChoiceServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/ChoiceServiceImpl.java new file mode 100644 index 0000000..8f1b2c0 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/service/ChoiceServiceImpl.java @@ -0,0 +1,25 @@ +package com.edufocus.edufocus.quiz.service; + +import com.edufocus.edufocus.quiz.entity.Choice; +import com.edufocus.edufocus.quiz.entity.ChoiceCreateRequest; +import com.edufocus.edufocus.quiz.repository.ChoiceRepository; +import jakarta.transaction.Transactional; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@Transactional +@RequiredArgsConstructor +public class ChoiceServiceImpl implements ChoiceService { + + private final ChoiceRepository choiceRepository; + + public void createChoice(ChoiceCreateRequest choiceCreateRequest) { + Choice choice = new Choice().builder() + .num(choiceCreateRequest.getNum()) + .content(choiceCreateRequest.getContent()) + .build(); + + choiceRepository.save(choice); + } +} diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizService.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizService.java index 8b0725f..60c81a5 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizService.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizService.java @@ -1,6 +1,7 @@ package com.edufocus.edufocus.quiz.service; import com.edufocus.edufocus.quiz.entity.QuizCreateRequest; +import com.edufocus.edufocus.quiz.entity.QuizSet; import org.springframework.stereotype.Service; import java.util.List; @@ -8,8 +9,7 @@ import java.util.List; @Service public interface QuizService { - void createQuiz(long quizSetId, QuizCreateRequest - QuizCreateRequest); + void createQuiz(QuizSet quizSet, QuizCreateRequest quizCreateRequest); boolean deleteQuiz(long quizId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizServiceImpl.java index 0412f68..12c9543 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizServiceImpl.java @@ -1,43 +1,50 @@ package com.edufocus.edufocus.quiz.service; -import com.edufocus.edufocus.quiz.entity.Quiz; -import com.edufocus.edufocus.quiz.entity.QuizCreateRequest; -import com.edufocus.edufocus.quiz.entity.QuizSet; -import com.edufocus.edufocus.quiz.entity.QuizType; +import com.edufocus.edufocus.quiz.entity.*; +import com.edufocus.edufocus.quiz.repository.ChoiceRepository; import com.edufocus.edufocus.quiz.repository.QuizRepository; import com.edufocus.edufocus.quiz.repository.QuizSetRepository; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import java.util.ArrayList; +import java.util.List; + + @Service @Transactional @RequiredArgsConstructor public class QuizServiceImpl implements QuizService { + private final ChoiceRepository choiceRepository; + private final QuizRepository quizRepository; private final QuizSetRepository quizSetRepository; @Override - public void createQuiz(long quizSetId, QuizCreateRequest quizCreateRequest) { - QuizSet quizSet = quizSetRepository.findById(quizSetId).get(); - + public void createQuiz(QuizSet quizSet, QuizCreateRequest quizCreateRequest) { Quiz quiz = new Quiz().builder() - .title(quizCreateRequest.getTitle()) - .description(quizCreateRequest.getDescription()) - .answer(quizCreateRequest.getAnswer()) - .quizType(QuizType.valueOf(quizCreateRequest.getQuizType())) .quizSet(quizSet) + .question(quizCreateRequest.getQuestion()) + .answer(quizCreateRequest.getAnswer()) .build(); - if (!quiz.getQuizType().equals(QuizType.MULTIPLE)) { - quiz.setChoice1(quizCreateRequest.getChoice1()); - quiz.setChoice2(quizCreateRequest.getChoice2()); - quiz.setChoice3(quizCreateRequest.getChoice3()); - quiz.setChoice4(quizCreateRequest.getChoice4()); + List choices = new ArrayList<>(); + + for (ChoiceCreateRequest choiceCreateRequest : quizCreateRequest.getChoices()) { + Choice choice = new Choice().builder() + .quiz(quiz) + .num(choiceCreateRequest.getNum()) + .content(choiceCreateRequest.getContent()) + .build(); + choices.add(choice); + choiceRepository.save(choice); } + quiz.setChoices(choices); + quizRepository.save(quiz); } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetService.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetService.java index a62a979..14f3e2b 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetService.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetService.java @@ -1,17 +1,20 @@ package com.edufocus.edufocus.quiz.service; import com.edufocus.edufocus.quiz.entity.QuizSet; -import com.edufocus.edufocus.quiz.entity.SetCreateRequest; +import com.edufocus.edufocus.quiz.entity.QuizSetResponse; import org.springframework.stereotype.Service; @Service public interface QuizSetService { - QuizSet createQuizSet(SetCreateRequest setCreateRequest); + QuizSet createQuizSet(Long userId, String title); void updateQuizSet(QuizSet quizSet); void deleteQuizSet(long quizSetId); QuizSet findQuizSet(long quizSetId); + + QuizSetResponse findQuizSetResponse(long quizSetId); + } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java index 1836ce5..ee582ee 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java @@ -9,6 +9,9 @@ import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import java.util.ArrayList; +import java.util.List; + @Service @Transactional @RequiredArgsConstructor @@ -18,16 +21,13 @@ public class QuizSetServiceImpl implements QuizSetService { private final UserRepository userRepository; - @Override - public QuizSet createQuizSet(SetCreateRequest setCreateRequest) { + public QuizSet createQuizSet(Long userId, String title) { QuizSet quizSet = new QuizSet(); - User user = userRepository.findById(setCreateRequest.getUserId()).get(); - + User user = userRepository.findById(userId).get(); quizSet.setUser(user); - - quizSet.setTitle(setCreateRequest.getTitle()); + quizSet.setTitle(title); return quizSetRepository.save(quizSet); } @@ -46,4 +46,28 @@ public class QuizSetServiceImpl implements QuizSetService { public QuizSet findQuizSet(long quizSetId) { return quizSetRepository.findById(quizSetId).get(); } + + @Override + public QuizSetResponse findQuizSetResponse(long quizSetId) { + QuizSet quizSet = findQuizSet(quizSetId); + + List quizResponses = new ArrayList<>(); + for (Quiz quiz : quizSet.getQuizzes()) { + QuizResponse quizResponse = new QuizResponse().builder() + .question(quiz.getQuestion()) + .choices(quiz.getChoices()) + .build(); + quizResponses.add(quizResponse); + } + + QuizSetResponse quizSetResponse = new QuizSetResponse().builder() + .title(quizSet.getTitle()) + .image(quizSet.getImage()) + .quizzes(quizResponses) + .build(); + + return quizSetResponse; + } + + } diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/controller/RegistrationController.java b/backend/src/main/java/com/edufocus/edufocus/registration/controller/RegistrationController.java index 1d28aaf..ee36efb 100644 --- a/backend/src/main/java/com/edufocus/edufocus/registration/controller/RegistrationController.java +++ b/backend/src/main/java/com/edufocus/edufocus/registration/controller/RegistrationController.java @@ -26,11 +26,9 @@ public class RegistrationController { Long lectureId = map.get("lectureId"); if (!registrationServiceImpl.createRegistration(userId, lectureId)) { - String msg = new String("Duplicated Registration"); - return new ResponseEntity<>(msg, HttpStatus.CONFLICT); + return new ResponseEntity<>(HttpStatus.CONFLICT); } - String msg = new String("registration successful"); return new ResponseEntity<>(HttpStatus.CREATED); } From 78b37baf9f57b01a5e3bf94e4920efd3fd860af8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Tue, 30 Jul 2024 09:32:37 +0900 Subject: [PATCH 063/197] =?UTF-8?q?feat:=20openvidu=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/edufocus/edufocus/video/controller/Controller.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java index 6ad9ef3..c4fa32c 100644 --- a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java +++ b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java @@ -139,4 +139,6 @@ public class Controller { return ResponseEntity.ok("ok"); } + + } From bfa6387a726c1c171871084fbd5eb41cf96ecaac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Tue, 30 Jul 2024 13:04:45 +0900 Subject: [PATCH 064/197] =?UTF-8?q?feat:=20=EC=9C=A0=EC=A0=80=20=ED=9A=8C?= =?UTF-8?q?=EC=9B=90=EC=A0=95=EB=B3=B4=20=EC=88=98=EC=A0=95=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/controller/UserController.java | 25 +++++ .../edufocus/user/model/entity/InfoDto.java | 7 ++ .../user/model/entity/PasswordDto.java | 14 +++ .../user/model/service/UserService.java | 6 +- .../user/model/service/UserServiceImpl.java | 98 +++++++++++-------- 5 files changed, 107 insertions(+), 43 deletions(-) create mode 100644 backend/src/main/java/com/edufocus/edufocus/user/model/entity/PasswordDto.java diff --git a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java index 5b36459..7ca0bf4 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java @@ -1,5 +1,7 @@ package com.edufocus.edufocus.user.controller; +import com.edufocus.edufocus.user.model.entity.InfoDto; +import com.edufocus.edufocus.user.model.entity.PasswordDto; import com.edufocus.edufocus.user.model.entity.User; import com.edufocus.edufocus.user.model.service.UserService; import com.edufocus.edufocus.user.util.JWTUtil; @@ -42,7 +44,30 @@ public class UserController { } + @PutMapping("/updateinfo/{id}") + public ResponseEntity updateUserInfo( + @PathVariable("id") Long id, + @RequestBody InfoDto infoDto) { + try { + userService.changeuInfo(infoDto, id); + return ResponseEntity.ok("User info updated successfully"); + } catch (Exception e) { + return ResponseEntity.badRequest().body(e.getMessage()); + } + } + // 비밀번호 변경 + @PutMapping("/updatepassword/{id}") + public ResponseEntity updatePassword( + @PathVariable("id") Long id, + @RequestBody PasswordDto passwordDto) { + try { + userService.changePassword(passwordDto, id); + return ResponseEntity.ok("Password changed successfully"); + } catch (Exception e) { + return ResponseEntity.badRequest().body(e.getMessage()); + } + } @Operation(summary = "로그인", description = "아이디와 비밀번호를 이용하여 로그인 처리.") @PostMapping("/login") public ResponseEntity> login( diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/InfoDto.java b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/InfoDto.java index ed96b9c..52b1f08 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/InfoDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/InfoDto.java @@ -1,8 +1,15 @@ package com.edufocus.edufocus.user.model.entity; +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter + public class InfoDto { String name; String email; + } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/PasswordDto.java b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/PasswordDto.java new file mode 100644 index 0000000..a77f73e --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/PasswordDto.java @@ -0,0 +1,14 @@ +package com.edufocus.edufocus.user.model.entity; + +import lombok.Generated; +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class PasswordDto { + + String currentPassword; + String newPassword; + String newPasswordCheck; +} diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java index 2f63135..5e1ba53 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java @@ -1,5 +1,7 @@ package com.edufocus.edufocus.user.model.service; +import com.edufocus.edufocus.user.model.entity.InfoDto; +import com.edufocus.edufocus.user.model.entity.PasswordDto; import com.edufocus.edufocus.user.model.entity.User; public interface UserService { @@ -12,7 +14,7 @@ public interface UserService { void sendEamail(User user) throws Exception; void userCheck(Long id) throws Exception; String getUserName(Long id) throws Exception; - void changeuInfo(Long id) throws Exception; - void changePassword(Long id) throws Exception; + void changeuInfo(InfoDto infoDto,Long id) throws Exception; + void changePassword(PasswordDto passwordDto,Long id) throws Exception; } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java index 66bb873..ed0f07d 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java @@ -1,9 +1,7 @@ package com.edufocus.edufocus.user.model.service; -import com.edufocus.edufocus.user.model.entity.MailDto; -import com.edufocus.edufocus.user.model.entity.MemberChangeDto; -import com.edufocus.edufocus.user.model.entity.User; +import com.edufocus.edufocus.user.model.entity.*; import com.edufocus.edufocus.user.model.exception.UserException; import com.edufocus.edufocus.user.model.repository.UserRepository; import jakarta.transaction.Transactional; @@ -21,46 +19,38 @@ import java.util.Optional; @Service @Transactional @RequiredArgsConstructor -public class UserServiceImpl implements UserService{ +public class UserServiceImpl implements UserService { private final UserRepository userRepository; private final JavaMailSender mailSender; - - public void join(User user) - { + public void join(User user) { userRepository.save(user); } - public User login(User user) throws SQLException - { + public User login(User user) throws SQLException { Optional findUser = userRepository.findByUserId(user.getUserId()); - if(findUser.isEmpty()) - { + if (findUser.isEmpty()) { throw new UserException("없는 유저"); } - if(findUser.isPresent()) - { + if (findUser.isPresent()) { User find = findUser.get(); - if(find.getPassword().equals(user.getPassword())) - { + if (find.getPassword().equals(user.getPassword())) { return find; - } - else{ + } else { throw new UserException("비밀번호 틀림"); } - } - else{ + } else { throw new UserException("없는 유저"); @@ -69,13 +59,10 @@ public class UserServiceImpl implements UserService{ } @Override - public User userInfo(Long id) - { - try{ + public User userInfo(Long id) { + try { return userRepository.findById(id).get(); - } - catch (Exception e) - { + } catch (Exception e) { throw new UserException(e.getMessage()); } @@ -89,12 +76,11 @@ public class UserServiceImpl implements UserService{ SimpleMailMessage message = new SimpleMailMessage(); - message.setTo(mailDto.getAddress()); message.setFrom("passfinder111@gmail.com"); message.setSubject(mailDto.getTitle()); message.setText(mailDto.getMessage()); - System.out.println("!!!!!!!!!!!!!!!!!!"+ message); + System.out.println("!!!!!!!!!!!!!!!!!!" + message); mailSender.send(message); @@ -105,15 +91,15 @@ public class UserServiceImpl implements UserService{ String str = getTempPassword(); MailDto dto = new MailDto(); dto.setAddress(user.getEmail()); - dto.setTitle(user.getUserId()+"님의 임시비밀번호 안내 이메일 입니다."); - dto.setMessage("안녕하세요. EduFoucs 입니다. "+ "\n"+ "임시비밀번호 안내 관련 메일 입니다." + "\n[" + user.getName() + "]" + "님의 임시 비밀번호는 " + dto.setTitle(user.getUserId() + "님의 임시비밀번호 안내 이메일 입니다."); + dto.setMessage("안녕하세요. EduFoucs 입니다. " + "\n" + "임시비밀번호 안내 관련 메일 입니다." + "\n[" + user.getName() + "]" + "님의 임시 비밀번호는 " + str + " 입니다."); System.out.println(dto); - MemberChangeDto memberChangeDto = new MemberChangeDto(user.getId(),str); + MemberChangeDto memberChangeDto = new MemberChangeDto(user.getId(), str); System.out.println(memberChangeDto); - userRepository.updatePassword(memberChangeDto.getId(),memberChangeDto.getPassword()); + userRepository.updatePassword(memberChangeDto.getId(), memberChangeDto.getPassword()); System.out.println(); return dto; @@ -125,13 +111,11 @@ public class UserServiceImpl implements UserService{ User user = userRepository.findById(id).orElse(null); - if(user == null) - { + if (user == null) { System.out.println("불가"); throw new RuntimeException("유효하지 않은 아이디입니다. 다시 입력하세요"); - } - else { + } else { sendEamail(user); } @@ -143,16 +127,48 @@ public class UserServiceImpl implements UserService{ return userRepository.findById(id).get().getName(); } - @Override - public void changeuInfo(Long id) throws Exception { - - } @Override - public void changePassword(Long id) throws Exception { + public void changeuInfo(InfoDto infoDto, Long id) throws Exception { + User user = userRepository.findById(id).orElse(null); + + if (user == null) { + throw new Exception("User not found"); + } + + if (infoDto.getName() != null) + { + user.setName(infoDto.getName()); + } + + if(infoDto.getEmail()!=null) + { + user.setEmail(infoDto.getEmail()); + } + userRepository.save(user); +} + + + @Override + public void changePassword(PasswordDto passwordDto, Long id) throws Exception { + User user = userRepository.findById(id).orElse(null); + + if (user == null) { + throw new Exception("User not found"); + } + + if (!user.getPassword().equals(passwordDto.getCurrentPassword())) { + throw new Exception("Current password is incorrect"); + } else { + if (!passwordDto.getNewPassword().equals(passwordDto.getNewPasswordCheck())) { + throw new Exception("New password confirmation does not match"); + } + } + + user.setPassword(passwordDto.getNewPassword()); + userRepository.save(user); } - public String getTempPassword() { char[] charSet = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}; From 97c25fff13f8c6c465303028ea12b3f2b2d0d843 Mon Sep 17 00:00:00 2001 From: kgc9007 Date: Tue, 30 Jul 2024 14:23:41 +0900 Subject: [PATCH 065/197] =?UTF-8?q?feat:=20Quiz=20=EC=82=AC=EC=A7=84=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D,=20=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../quiz/controller/QuizController.java | 30 +++++++++++-- .../quiz/entity/MyQuizSetResponse.java | 14 ++++++ .../edufocus/edufocus/quiz/entity/Quiz.java | 2 +- .../edufocus/quiz/entity/QuizSet.java | 7 +-- .../edufocus/quiz/entity/QuizSetResponse.java | 3 -- .../quiz/repository/ChoiceRepository.java | 8 ---- .../quiz/repository/QuizSetRepository.java | 3 ++ .../edufocus/quiz/service/ChoiceService.java | 7 --- .../quiz/service/ChoiceServiceImpl.java | 25 ----------- .../edufocus/quiz/service/QuizService.java | 5 ++- .../quiz/service/QuizServiceImpl.java | 39 ++++++++-------- .../edufocus/quiz/service/QuizSetService.java | 10 +++-- .../quiz/service/QuizSetServiceImpl.java | 45 +++++++++++++++---- 13 files changed, 114 insertions(+), 84 deletions(-) create mode 100644 backend/src/main/java/com/edufocus/edufocus/quiz/entity/MyQuizSetResponse.java delete mode 100644 backend/src/main/java/com/edufocus/edufocus/quiz/repository/ChoiceRepository.java delete mode 100644 backend/src/main/java/com/edufocus/edufocus/quiz/service/ChoiceService.java delete mode 100644 backend/src/main/java/com/edufocus/edufocus/quiz/service/ChoiceServiceImpl.java diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java b/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java index ac58dd2..cf0ecc8 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java @@ -12,9 +12,8 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; -import java.io.File; import java.io.IOException; -import java.util.UUID; +import java.util.List; @RestController @RequestMapping("/quiz") @@ -30,13 +29,14 @@ public class QuizController { @PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public ResponseEntity createQuizSet(@RequestHeader("Authorization") String accessToken, @RequestPart QuizSetCreateRequest quizSetCreateRequest - , @RequestPart(value = "image", required = false) MultipartFile image) throws IOException { + , @RequestPart(value = "images", required = false) List images) throws IOException { Long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); QuizSet quizSet = quizSetService.createQuizSet(userId, quizSetCreateRequest.getTitle()); + int imageIdx = 0; for (QuizCreateRequest quizCreateRequest : quizSetCreateRequest.getQuizzes()) { - quizService.createQuiz(quizSet, quizCreateRequest); + quizService.createQuiz(quizSet, quizCreateRequest, images.get(imageIdx++)); } return new ResponseEntity<>(HttpStatus.CREATED); @@ -46,6 +46,28 @@ public class QuizController { public ResponseEntity getQuizzes(@PathVariable Long quizsetId) { QuizSetResponse quizSet = quizSetService.findQuizSetResponse(quizsetId); + if (quizSet == null) { + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + } + return new ResponseEntity<>(quizSet, HttpStatus.OK); } + + @DeleteMapping("/{quizsetId}") + public ResponseEntity deleteQuizSet(@RequestHeader("Authorization") String accessToken, @PathVariable Long quizsetId) { + Long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); + + if (!quizSetService.deleteQuizSet(userId, quizsetId)) { + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + } + + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + @GetMapping + public ResponseEntity getQuizSets(@RequestHeader("Authorization") String accessToken) { + Long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); + + return new ResponseEntity<>(quizSetService.findMyQuizSetResponses(userId), HttpStatus.OK); + } } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/MyQuizSetResponse.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/MyQuizSetResponse.java new file mode 100644 index 0000000..da8947f --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/MyQuizSetResponse.java @@ -0,0 +1,14 @@ +package com.edufocus.edufocus.quiz.entity; + +import lombok.*; + +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MyQuizSetResponse { + + private Long quizSetId; + + private String title; +} diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Quiz.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Quiz.java index f9a3cc7..7eed889 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Quiz.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Quiz.java @@ -33,7 +33,7 @@ public class Quiz { @Column private String answer; - @OneToMany(mappedBy = "quiz") + @OneToMany(mappedBy = "quiz", orphanRemoval = true, cascade = CascadeType.ALL) @JsonManagedReference private List choices; diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSet.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSet.java index 89a2b4d..8357279 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSet.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSet.java @@ -27,12 +27,9 @@ public class QuizSet { @Column private String title; - @Column - private String image; - - @OneToMany(mappedBy = "quizSet") + @OneToMany(mappedBy = "quizSet", orphanRemoval = true) @JsonManagedReference - private List quizzes = new ArrayList(); + private List quizzes = new ArrayList(); public void addQuiz(Quiz quiz) { this.quizzes.add(quiz); diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSetResponse.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSetResponse.java index 9fdaf5e..1d4098d 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSetResponse.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSetResponse.java @@ -2,7 +2,6 @@ package com.edufocus.edufocus.quiz.entity; import lombok.*; -import java.util.ArrayList; import java.util.List; @Getter @@ -14,7 +13,5 @@ public class QuizSetResponse { private String title; - private String image; - private List quizzes; } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/repository/ChoiceRepository.java b/backend/src/main/java/com/edufocus/edufocus/quiz/repository/ChoiceRepository.java deleted file mode 100644 index 740dda2..0000000 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/repository/ChoiceRepository.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.edufocus.edufocus.quiz.repository; - -import com.edufocus.edufocus.quiz.entity.Choice; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface ChoiceRepository extends JpaRepository { - -} diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/repository/QuizSetRepository.java b/backend/src/main/java/com/edufocus/edufocus/quiz/repository/QuizSetRepository.java index 81883a6..89bc7bc 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/repository/QuizSetRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/repository/QuizSetRepository.java @@ -3,6 +3,9 @@ package com.edufocus.edufocus.quiz.repository; import com.edufocus.edufocus.quiz.entity.QuizSet; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.List; + public interface QuizSetRepository extends JpaRepository { + List findQuizSetsByUserId(Long userId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/ChoiceService.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/ChoiceService.java deleted file mode 100644 index 22b81d1..0000000 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/service/ChoiceService.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.edufocus.edufocus.quiz.service; - -import org.springframework.stereotype.Service; - -@Service -public interface ChoiceService { -} diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/ChoiceServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/ChoiceServiceImpl.java deleted file mode 100644 index 8f1b2c0..0000000 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/service/ChoiceServiceImpl.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.edufocus.edufocus.quiz.service; - -import com.edufocus.edufocus.quiz.entity.Choice; -import com.edufocus.edufocus.quiz.entity.ChoiceCreateRequest; -import com.edufocus.edufocus.quiz.repository.ChoiceRepository; -import jakarta.transaction.Transactional; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -@Service -@Transactional -@RequiredArgsConstructor -public class ChoiceServiceImpl implements ChoiceService { - - private final ChoiceRepository choiceRepository; - - public void createChoice(ChoiceCreateRequest choiceCreateRequest) { - Choice choice = new Choice().builder() - .num(choiceCreateRequest.getNum()) - .content(choiceCreateRequest.getContent()) - .build(); - - choiceRepository.save(choice); - } -} diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizService.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizService.java index 60c81a5..92014a2 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizService.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizService.java @@ -3,13 +3,14 @@ package com.edufocus.edufocus.quiz.service; import com.edufocus.edufocus.quiz.entity.QuizCreateRequest; import com.edufocus.edufocus.quiz.entity.QuizSet; import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; +import java.io.IOException; import java.util.List; @Service public interface QuizService { - void createQuiz(QuizSet quizSet, QuizCreateRequest quizCreateRequest); + void createQuiz(QuizSet quizSet, QuizCreateRequest quizCreateRequest, MultipartFile quizImage) throws IOException; - boolean deleteQuiz(long quizId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizServiceImpl.java index 12c9543..b25adfb 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizServiceImpl.java @@ -1,15 +1,17 @@ package com.edufocus.edufocus.quiz.service; import com.edufocus.edufocus.quiz.entity.*; -import com.edufocus.edufocus.quiz.repository.ChoiceRepository; import com.edufocus.edufocus.quiz.repository.QuizRepository; -import com.edufocus.edufocus.quiz.repository.QuizSetRepository; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; +import java.io.File; +import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.UUID; @Service @@ -17,14 +19,10 @@ import java.util.List; @RequiredArgsConstructor public class QuizServiceImpl implements QuizService { - private final ChoiceRepository choiceRepository; - private final QuizRepository quizRepository; - private final QuizSetRepository quizSetRepository; - @Override - public void createQuiz(QuizSet quizSet, QuizCreateRequest quizCreateRequest) { + public void createQuiz(QuizSet quizSet, QuizCreateRequest quizCreateRequest, MultipartFile quizImage) throws IOException { Quiz quiz = new Quiz().builder() .quizSet(quizSet) .question(quizCreateRequest.getQuestion()) @@ -40,23 +38,28 @@ public class QuizServiceImpl implements QuizService { .content(choiceCreateRequest.getContent()) .build(); choices.add(choice); - choiceRepository.save(choice); } quiz.setChoices(choices); + if (quizImage != null && !quizImage.isEmpty()) { + String uid = UUID.randomUUID().toString(); + + String currentPath = "backend/src/main/resources/images/quizzes/"; + File checkPathFile = new File(currentPath); + if (!checkPathFile.exists()) { + checkPathFile.mkdirs(); + } + + File savingImage = new File(currentPath + uid + "_" + quizImage.getOriginalFilename()); + quizImage.transferTo(savingImage.toPath()); + String savePath = savingImage.toPath().toString(); + + quiz.setImage(savePath); + } + quizRepository.save(quiz); } - @Override - public boolean deleteQuiz(long quizId) { - // 유저 아이디 정보 조회 후 검증 로직 추가 예정 - // jwt -> 로그인 유저 정보 조회 - // quizId -> 퀴즈 정보 조회 -> 퀴즈셋 정보 조회 - // 퀴즈셋 생성자와 로그인 유저의 id값이 일치하는지 확인 -> 불일치시 삭제 실패 - - quizRepository.deleteById(quizId); - return true; - } } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetService.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetService.java index 14f3e2b..1f8e4d7 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetService.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetService.java @@ -1,9 +1,12 @@ package com.edufocus.edufocus.quiz.service; +import com.edufocus.edufocus.quiz.entity.MyQuizSetResponse; import com.edufocus.edufocus.quiz.entity.QuizSet; import com.edufocus.edufocus.quiz.entity.QuizSetResponse; import org.springframework.stereotype.Service; +import java.util.List; + @Service public interface QuizSetService { @@ -11,10 +14,11 @@ public interface QuizSetService { void updateQuizSet(QuizSet quizSet); - void deleteQuizSet(long quizSetId); + boolean deleteQuizSet(Long userId, Long quizSetId); - QuizSet findQuizSet(long quizSetId); + QuizSet findQuizSet(Long quizSetId); - QuizSetResponse findQuizSetResponse(long quizSetId); + QuizSetResponse findQuizSetResponse(Long quizSetId); + List findMyQuizSetResponses(Long userId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java index ee582ee..c65a071 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java @@ -1,7 +1,6 @@ package com.edufocus.edufocus.quiz.service; import com.edufocus.edufocus.quiz.entity.*; -import com.edufocus.edufocus.quiz.repository.QuizRepository; import com.edufocus.edufocus.quiz.repository.QuizSetRepository; import com.edufocus.edufocus.user.model.entity.User; import com.edufocus.edufocus.user.model.repository.UserRepository; @@ -11,6 +10,7 @@ import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; +import java.util.Optional; @Service @Transactional @@ -38,36 +38,65 @@ public class QuizSetServiceImpl implements QuizSetService { } @Override - public void deleteQuizSet(long quizSetId) { + public boolean deleteQuizSet(Long userId, Long quizSetId) { + Optional quizSet = quizSetRepository.findById(quizSetId); + + if (quizSet.isEmpty() || userId != quizSet.get().getUser().getId()) { + return false; + } + quizSetRepository.deleteById(quizSetId); + return true; } @Override - public QuizSet findQuizSet(long quizSetId) { + public QuizSet findQuizSet(Long quizSetId) { return quizSetRepository.findById(quizSetId).get(); } @Override - public QuizSetResponse findQuizSetResponse(long quizSetId) { - QuizSet quizSet = findQuizSet(quizSetId); + public QuizSetResponse findQuizSetResponse(Long quizSetId) { + Optional quizSet = quizSetRepository.findById(quizSetId); + + if (quizSet.isEmpty()) { + return null; + } + List quizResponses = new ArrayList<>(); - for (Quiz quiz : quizSet.getQuizzes()) { + for (Quiz quiz : quizSet.get().getQuizzes()) { QuizResponse quizResponse = new QuizResponse().builder() .question(quiz.getQuestion()) + .image(quiz.getImage()) .choices(quiz.getChoices()) .build(); quizResponses.add(quizResponse); } QuizSetResponse quizSetResponse = new QuizSetResponse().builder() - .title(quizSet.getTitle()) - .image(quizSet.getImage()) + .title(quizSet.get().getTitle()) .quizzes(quizResponses) .build(); return quizSetResponse; } + @Override + public List findMyQuizSetResponses(Long userId) { + List quizSetList = quizSetRepository.findQuizSetsByUserId(userId); + + List myQuizSetResponses = new ArrayList<>(); + for (QuizSet quizSet : quizSetList) { + MyQuizSetResponse myQuizSetResponse = new MyQuizSetResponse().builder() + .quizSetId(quizSet.getId()) + .title(quizSet.getTitle()) + .build(); + + myQuizSetResponses.add(myQuizSetResponse); + } + + return myQuizSetResponses; + + } } From 96a124a82200b84ba9c82b89ca02de24023ede13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Tue, 30 Jul 2024 15:00:31 +0900 Subject: [PATCH 066/197] =?UTF-8?q?feat:=20user=20login=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/controller/UserController.java | 5 +- .../user/model/service/UserServiceImpl.java | 5 +- .../edufocus/user/UserControllerTest.java | 79 +++++ .../model/service/UserServiceImplTest.java | 298 ++++++++++++++++++ 4 files changed, 385 insertions(+), 2 deletions(-) create mode 100644 backend/src/test/java/com/edufocus/edufocus/user/UserControllerTest.java create mode 100644 backend/src/test/java/com/edufocus/edufocus/user/model/service/UserServiceImplTest.java diff --git a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java index 7ca0bf4..b4bff53 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java @@ -86,9 +86,12 @@ public class UserController { String accessToken = jwtUtil.createAccessToken(String.valueOf(loginUser.getId())); String refreshToken = jwtUtil.createRefreshToken(String.valueOf(loginUser.getId())); + userService.saveRefreshToken(loginUser.getId(), refreshToken); - System.out.println(accessToken); + + + resultMap.put("role",loginUser.getRole()); resultMap.put("access-token", accessToken); diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java index ed0f07d..716c4f0 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java @@ -26,7 +26,10 @@ public class UserServiceImpl implements UserService { private final JavaMailSender mailSender; - public void join(User user) { + public void join(User user) + { + System.out.println(user.getRole().getClass()); + userRepository.save(user); } diff --git a/backend/src/test/java/com/edufocus/edufocus/user/UserControllerTest.java b/backend/src/test/java/com/edufocus/edufocus/user/UserControllerTest.java new file mode 100644 index 0000000..eef3a64 --- /dev/null +++ b/backend/src/test/java/com/edufocus/edufocus/user/UserControllerTest.java @@ -0,0 +1,79 @@ +//package com.edufocus.edufocus.user; +// +//import com.edufocus.edufocus.user.controller.UserController; +//import com.edufocus.edufocus.user.model.entity.InfoDto; +//import com.edufocus.edufocus.user.model.entity.PasswordDto; +//import com.edufocus.edufocus.user.model.entity.User; +//import com.edufocus.edufocus.user.model.entity.UserRole; +//import com.edufocus.edufocus.user.model.service.UserService; +//import com.edufocus.edufocus.user.util.JWTUtil; +//import com.fasterxml.jackson.databind.ObjectMapper; +//import org.junit.jupiter.api.BeforeEach; +//import org.junit.jupiter.api.Test; +//import org.junit.jupiter.api.extension.ExtendWith; +//import org.mockito.InjectMocks; +//import org.mockito.Mock; +//import org.mockito.MockitoAnnotations; +//import org.mockito.junit.jupiter.MockitoExtension; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +//import org.springframework.http.HttpStatus; +//import org.springframework.http.MediaType; +//import org.springframework.http.ResponseEntity; +//import org.springframework.test.web.servlet.MockMvc; +// +//import static org.mockito.ArgumentMatchers.any; +//import static org.mockito.Mockito.*; +//import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +// +//@WebMvcTest(UserController.class) +//public class UserControllerTest { +// +// @Mock +// private MockMvc mockMvc; +// +// @Autowired +// ObjectMapper mapper; +// @Mock +// private UserService userService; +// +// @Mock +// private JWTUtil jwtUtil; +// +// @InjectMocks +// private UserController userController; +// +// private User testUser; +// private InfoDto testInfo; +// private PasswordDto passwordDto; +// private UserRole userRole; +// @BeforeEach +// void setUp() +// { +// MockitoAnnotations.openMocks(this); +// +// } +//// @Test +//// void testjoin() throws Exception +//// { +//// +//// User user = new User(); +//// user.setId(1L); +//// user.setName("jungmin"); +//// user.setUserId("v_v"); +//// user.setRole(userRole.STUDENT); +//// user.setPassword("pwd"); +//// user.setEmail("wjdals231@naver.com"); +//// +//// String body= mapper.writeValueAsString( +//// UserRe +//// ) +//// +//// mockMvc.perform(post("/api/user/join") +//// .contentType(MediaType.APPLICATION_JSON) +//// . +//// +//// // +//// +//// } +//} diff --git a/backend/src/test/java/com/edufocus/edufocus/user/model/service/UserServiceImplTest.java b/backend/src/test/java/com/edufocus/edufocus/user/model/service/UserServiceImplTest.java new file mode 100644 index 0000000..9fb092b --- /dev/null +++ b/backend/src/test/java/com/edufocus/edufocus/user/model/service/UserServiceImplTest.java @@ -0,0 +1,298 @@ +package com.edufocus.edufocus.user.model.service; + +import static org.junit.jupiter.api.Assertions.*; + + +import com.edufocus.edufocus.user.model.entity.*; +import com.edufocus.edufocus.user.model.exception.UserException; +import com.edufocus.edufocus.user.model.repository.UserRepository; +import jakarta.transaction.Transactional; +import lombok.RequiredArgsConstructor; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.*; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.mail.javamail.JavaMailSender; + +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +public class UserServiceImplTest { + + @InjectMocks + private UserServiceImpl userService; + + @Mock + private UserRepository userRepository; + + @Mock + private JavaMailSender mailSender; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + } + + @Test + void testJoin() { + User user = new User(); + user.setId(1L); + user.setName("John Doe"); + + userService.join(user); + + verify(userRepository, times(1)).save(user); + } + + @Test + void testLoginSuccess() throws Exception { + User user = new User(); + user.setUserId("john"); + user.setPassword("password"); + + User returnedUser = new User(); + returnedUser.setUserId("john"); + returnedUser.setPassword("password"); + + when(userRepository.findByUserId(user.getUserId())).thenReturn(Optional.of(returnedUser)); + + User result = userService.login(user); + + assertNotNull(result); + assertEquals("john", result.getUserId()); + assertEquals("password", result.getPassword()); + } + + @Test + void testLoginUserNotFound() { + User user = new User(); + user.setUserId("john"); + user.setPassword("password"); + + when(userRepository.findByUserId(user.getUserId())).thenReturn(Optional.empty()); + + UserException exception = assertThrows(UserException.class, () -> userService.login(user)); + + assertEquals("없는 유저", exception.getMessage()); + } + + @Test + void testLoginIncorrectPassword() { + User user = new User(); + user.setUserId("john"); + user.setPassword("password"); + + User returnedUser = new User(); + returnedUser.setUserId("john"); + returnedUser.setPassword("wrongPassword"); + + when(userRepository.findByUserId(user.getUserId())).thenReturn(Optional.of(returnedUser)); + + UserException exception = assertThrows(UserException.class, () -> userService.login(user)); + + assertEquals("비밀번호 틀림", exception.getMessage()); + } + + @Test + void testUserInfo() { + User user = new User(); + user.setId(1L); + user.setName("John Doe"); + + when(userRepository.findById(1L)).thenReturn(Optional.of(user)); + + User result = userService.userInfo(1L); + + assertNotNull(result); + assertEquals("John Doe", result.getName()); + } + + @Test + void testSendEmail() throws Exception { + User user = new User(); + user.setEmail("test@example.com"); + user.setUserId("testUser"); + user.setName("Test User"); + + MailDto mailDto = new MailDto(); + mailDto.setAddress("test@example.com"); + mailDto.setTitle("Test Title"); + mailDto.setMessage("Test Message"); + + doNothing().when(mailSender).send(any(SimpleMailMessage.class)); + doReturn(mailDto).when(userService).createMailAndChargePassword(user); + + userService.sendEamail(user); + + verify(mailSender, times(1)).send(any(SimpleMailMessage.class)); + } + + @Test + void testUserCheck() throws Exception { + User user = new User(); + user.setId(1L); + user.setUserId("testUser"); + user.setEmail("test@example.com"); + user.setName("Test User"); + + when(userRepository.findById(1L)).thenReturn(Optional.of(user)); + + userService.userCheck(1L); + + verify(userRepository, times(1)).findById(1L); + verify(userService, times(1)).sendEamail(user); + } + + @Test + void testUserCheckInvalidId() { + when(userRepository.findById(1L)).thenReturn(Optional.empty()); + + RuntimeException exception = assertThrows(RuntimeException.class, () -> userService.userCheck(1L)); + + assertEquals("유효하지 않은 아이디입니다. 다시 입력하세요", exception.getMessage()); + } + + @Test + void testChangeUserInfo() throws Exception { + Long userId = 1L; + InfoDto infoDto = new InfoDto(); + infoDto.setName("New Name"); + infoDto.setEmail("new.email@example.com"); + + User user = new User(); + user.setId(userId); + user.setName("Old Name"); + user.setEmail("old.email@example.com"); + + when(userRepository.findById(userId)).thenReturn(Optional.of(user)); + + userService.changeuInfo(infoDto, userId); + + assertEquals("New Name", user.getName()); + assertEquals("new.email@example.com", user.getEmail()); + verify(userRepository, times(1)).save(user); + } + + @Test + void testChangeUserInfoUserNotFound() { + Long userId = 1L; + InfoDto infoDto = new InfoDto(); + infoDto.setName("New Name"); + infoDto.setEmail("new.email@example.com"); + + when(userRepository.findById(userId)).thenReturn(Optional.empty()); + + Exception exception = assertThrows(Exception.class, () -> userService.changeuInfo(infoDto, userId)); + + assertEquals("User not found", exception.getMessage()); + } + + @Test + void testChangePasswordSuccess() throws Exception { + Long userId = 1L; + PasswordDto passwordDto = new PasswordDto(); + passwordDto.setCurrentPassword("oldPassword"); + passwordDto.setNewPassword("newPassword"); + passwordDto.setNewPasswordCheck("newPassword"); + + User user = new User(); + user.setId(userId); + user.setPassword("oldPassword"); + + when(userRepository.findById(userId)).thenReturn(Optional.of(user)); + + userService.changePassword(passwordDto, userId); + + assertEquals("newPassword", user.getPassword()); + verify(userRepository, times(1)).save(user); + } + + @Test + void testChangePasswordUserNotFound() { + Long userId = 1L; + PasswordDto passwordDto = new PasswordDto(); + passwordDto.setCurrentPassword("oldPassword"); + passwordDto.setNewPassword("newPassword"); + passwordDto.setNewPasswordCheck("newPassword"); + + when(userRepository.findById(userId)).thenReturn(Optional.empty()); + + Exception exception = assertThrows(Exception.class, () -> userService.changePassword(passwordDto, userId)); + + assertEquals("User not found", exception.getMessage()); + } + + @Test + void testChangePasswordIncorrectCurrentPassword() { + Long userId = 1L; + PasswordDto passwordDto = new PasswordDto(); + passwordDto.setCurrentPassword("wrongPassword"); + passwordDto.setNewPassword("newPassword"); + passwordDto.setNewPasswordCheck("newPassword"); + + User user = new User(); + user.setId(userId); + user.setPassword("oldPassword"); + + when(userRepository.findById(userId)).thenReturn(Optional.of(user)); + + Exception exception = assertThrows(Exception.class, () -> userService.changePassword(passwordDto, userId)); + + assertEquals("Current password is incorrect", exception.getMessage()); + } + + @Test + void testChangePasswordNewPasswordMismatch() { + Long userId = 1L; + PasswordDto passwordDto = new PasswordDto(); + passwordDto.setCurrentPassword("oldPassword"); + passwordDto.setNewPassword("newPassword"); + passwordDto.setNewPasswordCheck("differentNewPassword"); + + User user = new User(); + user.setId(userId); + user.setPassword("oldPassword"); + + when(userRepository.findById(userId)).thenReturn(Optional.of(user)); + + Exception exception = assertThrows(Exception.class, () -> userService.changePassword(passwordDto, userId)); + + assertEquals("New password confirmation does not match", exception.getMessage()); + } + + @Test + void testSaveRefreshToken() throws Exception { + Long userId = 1L; + String refreshToken = "refresh-token"; + + doNothing().when(userRepository).saveRefreshToken(userId, refreshToken); + + userService.saveRefreshToken(userId, refreshToken); + + verify(userRepository, times(1)).saveRefreshToken(userId, refreshToken); + } + + @Test + void testGetRefreshToken() throws Exception { + Long userId = 1L; + String refreshToken = "refresh-token"; + + when(userRepository.getRefreshToken(userId)).thenReturn(refreshToken); + + String result = userService.getRefreshToken(userId); + + assertEquals(refreshToken, result); + } + +// @Test +// void testDeleteRefreshToken() throws Exception { +// Long userId = 1L; +// +// doNothing().when(userRepository).delete +// } +} \ No newline at end of file From 4573f4335563ab79cd47e7f95f7252099cd5178a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Tue, 30 Jul 2024 15:38:42 +0900 Subject: [PATCH 067/197] =?UTF-8?q?feat:=20user=20test=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/model/service/UserServiceImpl.java | 9 +- .../edufocus/user/UserControllerTest.java | 79 ---- .../model/service/UserServiceImplTest.java | 361 ++++++------------ 3 files changed, 127 insertions(+), 322 deletions(-) delete mode 100644 backend/src/test/java/com/edufocus/edufocus/user/UserControllerTest.java diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java index 716c4f0..06ee58a 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java @@ -75,7 +75,7 @@ public class UserServiceImpl implements UserService { public void sendEamail(User user) throws Exception { MailDto mailDto = createMailAndChargePassword(user); - System.out.println("이메일 전송 완료"); + SimpleMailMessage message = new SimpleMailMessage(); @@ -83,7 +83,7 @@ public class UserServiceImpl implements UserService { message.setFrom("passfinder111@gmail.com"); message.setSubject(mailDto.getTitle()); message.setText(mailDto.getMessage()); - System.out.println("!!!!!!!!!!!!!!!!!!" + message); + mailSender.send(message); @@ -101,9 +101,7 @@ public class UserServiceImpl implements UserService { System.out.println(dto); MemberChangeDto memberChangeDto = new MemberChangeDto(user.getId(), str); - System.out.println(memberChangeDto); userRepository.updatePassword(memberChangeDto.getId(), memberChangeDto.getPassword()); - System.out.println(); return dto; } @@ -115,8 +113,7 @@ public class UserServiceImpl implements UserService { if (user == null) { - System.out.println("불가"); - throw new RuntimeException("유효하지 않은 아이디입니다. 다시 입력하세요"); + throw new UserException("유효하지 않은 아이디입니다. 다시 입력하세요"); } else { diff --git a/backend/src/test/java/com/edufocus/edufocus/user/UserControllerTest.java b/backend/src/test/java/com/edufocus/edufocus/user/UserControllerTest.java deleted file mode 100644 index eef3a64..0000000 --- a/backend/src/test/java/com/edufocus/edufocus/user/UserControllerTest.java +++ /dev/null @@ -1,79 +0,0 @@ -//package com.edufocus.edufocus.user; -// -//import com.edufocus.edufocus.user.controller.UserController; -//import com.edufocus.edufocus.user.model.entity.InfoDto; -//import com.edufocus.edufocus.user.model.entity.PasswordDto; -//import com.edufocus.edufocus.user.model.entity.User; -//import com.edufocus.edufocus.user.model.entity.UserRole; -//import com.edufocus.edufocus.user.model.service.UserService; -//import com.edufocus.edufocus.user.util.JWTUtil; -//import com.fasterxml.jackson.databind.ObjectMapper; -//import org.junit.jupiter.api.BeforeEach; -//import org.junit.jupiter.api.Test; -//import org.junit.jupiter.api.extension.ExtendWith; -//import org.mockito.InjectMocks; -//import org.mockito.Mock; -//import org.mockito.MockitoAnnotations; -//import org.mockito.junit.jupiter.MockitoExtension; -//import org.springframework.beans.factory.annotation.Autowired; -//import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -//import org.springframework.http.HttpStatus; -//import org.springframework.http.MediaType; -//import org.springframework.http.ResponseEntity; -//import org.springframework.test.web.servlet.MockMvc; -// -//import static org.mockito.ArgumentMatchers.any; -//import static org.mockito.Mockito.*; -//import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -// -//@WebMvcTest(UserController.class) -//public class UserControllerTest { -// -// @Mock -// private MockMvc mockMvc; -// -// @Autowired -// ObjectMapper mapper; -// @Mock -// private UserService userService; -// -// @Mock -// private JWTUtil jwtUtil; -// -// @InjectMocks -// private UserController userController; -// -// private User testUser; -// private InfoDto testInfo; -// private PasswordDto passwordDto; -// private UserRole userRole; -// @BeforeEach -// void setUp() -// { -// MockitoAnnotations.openMocks(this); -// -// } -//// @Test -//// void testjoin() throws Exception -//// { -//// -//// User user = new User(); -//// user.setId(1L); -//// user.setName("jungmin"); -//// user.setUserId("v_v"); -//// user.setRole(userRole.STUDENT); -//// user.setPassword("pwd"); -//// user.setEmail("wjdals231@naver.com"); -//// -//// String body= mapper.writeValueAsString( -//// UserRe -//// ) -//// -//// mockMvc.perform(post("/api/user/join") -//// .contentType(MediaType.APPLICATION_JSON) -//// . -//// -//// // -//// -//// } -//} diff --git a/backend/src/test/java/com/edufocus/edufocus/user/model/service/UserServiceImplTest.java b/backend/src/test/java/com/edufocus/edufocus/user/model/service/UserServiceImplTest.java index 9fb092b..5cf213f 100644 --- a/backend/src/test/java/com/edufocus/edufocus/user/model/service/UserServiceImplTest.java +++ b/backend/src/test/java/com/edufocus/edufocus/user/model/service/UserServiceImplTest.java @@ -1,19 +1,15 @@ package com.edufocus.edufocus.user.model.service; -import static org.junit.jupiter.api.Assertions.*; - - -import com.edufocus.edufocus.user.model.entity.*; +import com.edufocus.edufocus.user.model.entity.PasswordDto; +import com.edufocus.edufocus.user.model.entity.User; +import com.edufocus.edufocus.user.model.entity.UserRole; import com.edufocus.edufocus.user.model.exception.UserException; import com.edufocus.edufocus.user.model.repository.UserRepository; -import jakarta.transaction.Transactional; -import lombok.RequiredArgsConstructor; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.*; -import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.mail.SimpleMailMessage; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; import org.springframework.mail.javamail.JavaMailSender; import java.util.Optional; @@ -21,7 +17,6 @@ import java.util.Optional; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; -@ExtendWith(MockitoExtension.class) public class UserServiceImplTest { @InjectMocks @@ -30,19 +25,22 @@ public class UserServiceImplTest { @Mock private UserRepository userRepository; - @Mock - private JavaMailSender mailSender; + @BeforeEach - void setUp() { + public void setup() { MockitoAnnotations.openMocks(this); } @Test - void testJoin() { + public void testJoin() { User user = new User(); + user.setUserId("testUser"); + user.setPassword("password"); + user.setEmail("test@example.com"); + user.setRole(UserRole.STUDENT); user.setId(1L); - user.setName("John Doe"); + userService.join(user); @@ -50,249 +48,138 @@ public class UserServiceImplTest { } @Test - void testLoginSuccess() throws Exception { + public void testLogin_Success() throws Exception { User user = new User(); - user.setUserId("john"); - user.setPassword("password"); - - User returnedUser = new User(); - returnedUser.setUserId("john"); - returnedUser.setPassword("password"); - - when(userRepository.findByUserId(user.getUserId())).thenReturn(Optional.of(returnedUser)); - - User result = userService.login(user); - - assertNotNull(result); - assertEquals("john", result.getUserId()); - assertEquals("password", result.getPassword()); - } - - @Test - void testLoginUserNotFound() { - User user = new User(); - user.setUserId("john"); - user.setPassword("password"); - - when(userRepository.findByUserId(user.getUserId())).thenReturn(Optional.empty()); - - UserException exception = assertThrows(UserException.class, () -> userService.login(user)); - - assertEquals("없는 유저", exception.getMessage()); - } - - @Test - void testLoginIncorrectPassword() { - User user = new User(); - user.setUserId("john"); - user.setPassword("password"); - - User returnedUser = new User(); - returnedUser.setUserId("john"); - returnedUser.setPassword("wrongPassword"); - - when(userRepository.findByUserId(user.getUserId())).thenReturn(Optional.of(returnedUser)); - - UserException exception = assertThrows(UserException.class, () -> userService.login(user)); - - assertEquals("비밀번호 틀림", exception.getMessage()); - } - - @Test - void testUserInfo() { - User user = new User(); - user.setId(1L); - user.setName("John Doe"); - - when(userRepository.findById(1L)).thenReturn(Optional.of(user)); - - User result = userService.userInfo(1L); - - assertNotNull(result); - assertEquals("John Doe", result.getName()); - } - - @Test - void testSendEmail() throws Exception { - User user = new User(); - user.setEmail("test@example.com"); user.setUserId("testUser"); - user.setName("Test User"); + user.setPassword("password"); - MailDto mailDto = new MailDto(); - mailDto.setAddress("test@example.com"); - mailDto.setTitle("Test Title"); - mailDto.setMessage("Test Message"); + when(userRepository.findByUserId("testUser")).thenReturn(Optional.of(user)); - doNothing().when(mailSender).send(any(SimpleMailMessage.class)); - doReturn(mailDto).when(userService).createMailAndChargePassword(user); + User loggedInUser = userService.login(user); - userService.sendEamail(user); - - verify(mailSender, times(1)).send(any(SimpleMailMessage.class)); + assertNotNull(loggedInUser); + assertEquals("testUser", loggedInUser.getUserId()); } @Test - void testUserCheck() throws Exception { + public void testLogin_UserNotFound() { User user = new User(); - user.setId(1L); user.setUserId("testUser"); - user.setEmail("test@example.com"); - user.setName("Test User"); + user.setPassword("password"); - when(userRepository.findById(1L)).thenReturn(Optional.of(user)); + when(userRepository.findByUserId("testUser")).thenReturn(Optional.empty()); - userService.userCheck(1L); - - verify(userRepository, times(1)).findById(1L); - verify(userService, times(1)).sendEamail(user); + assertThrows(UserException.class, () -> { + userService.login(user); + }); } @Test - void testUserCheckInvalidId() { - when(userRepository.findById(1L)).thenReturn(Optional.empty()); - - RuntimeException exception = assertThrows(RuntimeException.class, () -> userService.userCheck(1L)); - - assertEquals("유효하지 않은 아이디입니다. 다시 입력하세요", exception.getMessage()); - } - - @Test - void testChangeUserInfo() throws Exception { - Long userId = 1L; - InfoDto infoDto = new InfoDto(); - infoDto.setName("New Name"); - infoDto.setEmail("new.email@example.com"); - + public void testLogin_InvalidPassword() { User user = new User(); - user.setId(userId); - user.setName("Old Name"); - user.setEmail("old.email@example.com"); + user.setUserId("testUser"); + user.setPassword("password"); - when(userRepository.findById(userId)).thenReturn(Optional.of(user)); + User storedUser = new User(); + storedUser.setUserId("testUser"); + storedUser.setPassword("wrongPassword"); - userService.changeuInfo(infoDto, userId); + when(userRepository.findByUserId("testUser")).thenReturn(Optional.of(storedUser)); - assertEquals("New Name", user.getName()); - assertEquals("new.email@example.com", user.getEmail()); - verify(userRepository, times(1)).save(user); - } - - @Test - void testChangeUserInfoUserNotFound() { - Long userId = 1L; - InfoDto infoDto = new InfoDto(); - infoDto.setName("New Name"); - infoDto.setEmail("new.email@example.com"); - - when(userRepository.findById(userId)).thenReturn(Optional.empty()); - - Exception exception = assertThrows(Exception.class, () -> userService.changeuInfo(infoDto, userId)); - - assertEquals("User not found", exception.getMessage()); - } - - @Test - void testChangePasswordSuccess() throws Exception { - Long userId = 1L; - PasswordDto passwordDto = new PasswordDto(); - passwordDto.setCurrentPassword("oldPassword"); - passwordDto.setNewPassword("newPassword"); - passwordDto.setNewPasswordCheck("newPassword"); - - User user = new User(); - user.setId(userId); - user.setPassword("oldPassword"); - - when(userRepository.findById(userId)).thenReturn(Optional.of(user)); - - userService.changePassword(passwordDto, userId); - - assertEquals("newPassword", user.getPassword()); - verify(userRepository, times(1)).save(user); - } - - @Test - void testChangePasswordUserNotFound() { - Long userId = 1L; - PasswordDto passwordDto = new PasswordDto(); - passwordDto.setCurrentPassword("oldPassword"); - passwordDto.setNewPassword("newPassword"); - passwordDto.setNewPasswordCheck("newPassword"); - - when(userRepository.findById(userId)).thenReturn(Optional.empty()); - - Exception exception = assertThrows(Exception.class, () -> userService.changePassword(passwordDto, userId)); - - assertEquals("User not found", exception.getMessage()); - } - - @Test - void testChangePasswordIncorrectCurrentPassword() { - Long userId = 1L; - PasswordDto passwordDto = new PasswordDto(); - passwordDto.setCurrentPassword("wrongPassword"); - passwordDto.setNewPassword("newPassword"); - passwordDto.setNewPasswordCheck("newPassword"); - - User user = new User(); - user.setId(userId); - user.setPassword("oldPassword"); - - when(userRepository.findById(userId)).thenReturn(Optional.of(user)); - - Exception exception = assertThrows(Exception.class, () -> userService.changePassword(passwordDto, userId)); - - assertEquals("Current password is incorrect", exception.getMessage()); - } - - @Test - void testChangePasswordNewPasswordMismatch() { - Long userId = 1L; - PasswordDto passwordDto = new PasswordDto(); - passwordDto.setCurrentPassword("oldPassword"); - passwordDto.setNewPassword("newPassword"); - passwordDto.setNewPasswordCheck("differentNewPassword"); - - User user = new User(); - user.setId(userId); - user.setPassword("oldPassword"); - - when(userRepository.findById(userId)).thenReturn(Optional.of(user)); - - Exception exception = assertThrows(Exception.class, () -> userService.changePassword(passwordDto, userId)); - - assertEquals("New password confirmation does not match", exception.getMessage()); - } - - @Test - void testSaveRefreshToken() throws Exception { - Long userId = 1L; - String refreshToken = "refresh-token"; - - doNothing().when(userRepository).saveRefreshToken(userId, refreshToken); - - userService.saveRefreshToken(userId, refreshToken); - - verify(userRepository, times(1)).saveRefreshToken(userId, refreshToken); - } - - @Test - void testGetRefreshToken() throws Exception { - Long userId = 1L; - String refreshToken = "refresh-token"; - - when(userRepository.getRefreshToken(userId)).thenReturn(refreshToken); - - String result = userService.getRefreshToken(userId); - - assertEquals(refreshToken, result); + assertThrows(UserException.class, () -> { + userService.login(user); + }); } // @Test -// void testDeleteRefreshToken() throws Exception { -// Long userId = 1L; +// public void testUserInfo_Success() { +// User user = new User(); +// user.setId(1L); +// user.setName("testUser"); // -// doNothing().when(userRepository).delete +// when(userRepository.findById(1L)).thenReturn(Optional.of(user)); +// +// User userInfo = userService.userInfo(1L); +// +// assertNotNull(userInfo); +// assertEquals("testUser", userInfo.getName()); +// } +// +// @Test +// public void testUserInfo_UserNotFound() { +// when(userRepository.findById(1L)).thenReturn(Optional.empty()); +// +// assertThrows(UserException.class, () -> { +// userService.userInfo(1L); +// }); +// } +// +// @Test +// public void testChangePassword_Success() throws Exception { +// User user = new User(); +// user.setId(1L); +// user.setPassword("currentPassword"); +// +// when(userRepository.findById(1L)).thenReturn(Optional.of(user)); +// +// PasswordDto passwordDto = new PasswordDto(); +// passwordDto.setCurrentPassword("currentPassword"); +// passwordDto.setNewPassword("newPassword"); +// passwordDto.setNewPasswordCheck("newPassword"); +// +// userService.changePassword(passwordDto, 1L); +// +// verify(userRepository, times(1)).save(user); +// assertEquals("newPassword", user.getPassword()); +// } +// +// @Test +// public void testChangePassword_UserNotFound() { +// when(userRepository.findById(1L)).thenReturn(Optional.empty()); +// +// PasswordDto passwordDto = new PasswordDto(); +// passwordDto.setCurrentPassword("currentPassword"); +// passwordDto.setNewPassword("newPassword"); +// passwordDto.setNewPasswordCheck("newPassword"); +// +// assertThrows(Exception.class, () -> { +// userService.changePassword(passwordDto, 1L); +// }); +// } +// +// @Test +// public void testChangePassword_InvalidCurrentPassword() { +// User user = new User(); +// user.setId(1L); +// user.setPassword("currentPassword"); +// +// when(userRepository.findById(1L)).thenReturn(Optional.of(user)); +// +// PasswordDto passwordDto = new PasswordDto(); +// passwordDto.setCurrentPassword("wrongPassword"); +// passwordDto.setNewPassword("newPassword"); +// passwordDto.setNewPasswordCheck("newPassword"); +// +// assertThrows(Exception.class, () -> { +// userService.changePassword(passwordDto, 1L); +// }); +// } +// +// @Test +// public void testChangePassword_NewPasswordMismatch() { +// User user = new User(); +// user.setId(1L); +// user.setPassword("currentPassword"); +// +// when(userRepository.findById(1L)).thenReturn(Optional.of(user)); +// +// PasswordDto passwordDto = new PasswordDto(); +// passwordDto.setCurrentPassword("currentPassword"); +// passwordDto.setNewPassword("newPassword"); +// passwordDto.setNewPasswordCheck("mismatchNewPassword"); +// +// assertThrows(Exception.class, () -> { +// userService.changePassword(passwordDto, 1L); +// }); // } } \ No newline at end of file From ce4c6a1c8da137d09ec700f02864c404a4cf0a4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Tue, 30 Jul 2024 17:35:37 +0900 Subject: [PATCH 068/197] =?UTF-8?q?feat:=20refresh=20token=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/controller/UserController.java | 10 ++ .../exception/ExpriedTokenException.java | 11 ++ .../exception/GlobalExceptionHandler.java | 27 +++++ .../exception/InvalidTokenException.java | 7 ++ .../edufocus/edufocus/user/util/JWTUtil.java | 44 ++++--- .../edufocus/video/controller/Controller.java | 108 ++++++++++++------ 6 files changed, 156 insertions(+), 51 deletions(-) create mode 100644 backend/src/main/java/com/edufocus/edufocus/user/model/exception/ExpriedTokenException.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/user/model/exception/GlobalExceptionHandler.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/user/model/exception/InvalidTokenException.java diff --git a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java index b4bff53..6526a03 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java @@ -3,6 +3,8 @@ package com.edufocus.edufocus.user.controller; import com.edufocus.edufocus.user.model.entity.InfoDto; import com.edufocus.edufocus.user.model.entity.PasswordDto; import com.edufocus.edufocus.user.model.entity.User; +import com.edufocus.edufocus.user.model.exception.ExpriedTokenException; +import com.edufocus.edufocus.user.model.exception.UnAuthorizedException; import com.edufocus.edufocus.user.model.service.UserService; import com.edufocus.edufocus.user.util.JWTUtil; import io.swagger.v3.oas.annotations.Operation; @@ -258,7 +260,15 @@ public class UserController { } + @ExceptionHandler(ExpriedTokenException.class) + public ResponseEntity handleExpiredTokenException(){ + return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); + } + @ExceptionHandler(UnAuthorizedException.class) + public ResponseEntity handleUnauthorizedException(){ + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/exception/ExpriedTokenException.java b/backend/src/main/java/com/edufocus/edufocus/user/model/exception/ExpriedTokenException.java new file mode 100644 index 0000000..e816b32 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/exception/ExpriedTokenException.java @@ -0,0 +1,11 @@ +package com.edufocus.edufocus.user.model.exception; + +public class ExpriedTokenException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public ExpriedTokenException() { + super("계정 권한이 유효하지 않습니다.\n다시 로그인을 하세요."); + } + +} diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/exception/GlobalExceptionHandler.java b/backend/src/main/java/com/edufocus/edufocus/user/model/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..526e6ae --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/exception/GlobalExceptionHandler.java @@ -0,0 +1,27 @@ +package com.edufocus.edufocus.user.model.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; + +@ControllerAdvice +public class GlobalExceptionHandler { + + @ExceptionHandler(UnAuthorizedException.class) + public ResponseEntity handleUnAuthorizedException(UnAuthorizedException e) { + + + + return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST); + } + + + @ExceptionHandler(ExpriedTokenException.class) + public ResponseEntity handleInvalidTokenException(ExpriedTokenException e) { + // 로그 남기기 (선택 사항) + // log.error("Invalid token", e); + + return new ResponseEntity<>(e.getMessage(), HttpStatus.UNAUTHORIZED); + } +} diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/exception/InvalidTokenException.java b/backend/src/main/java/com/edufocus/edufocus/user/model/exception/InvalidTokenException.java new file mode 100644 index 0000000..74969f3 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/exception/InvalidTokenException.java @@ -0,0 +1,7 @@ +package com.edufocus.edufocus.user.model.exception; + +public class InvalidTokenException extends RuntimeException { + public InvalidTokenException() { + super("Token is invalid"); + } +} \ No newline at end of file diff --git a/backend/src/main/java/com/edufocus/edufocus/user/util/JWTUtil.java b/backend/src/main/java/com/edufocus/edufocus/user/util/JWTUtil.java index ead01db..ffce34c 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/util/JWTUtil.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/util/JWTUtil.java @@ -4,6 +4,8 @@ import java.nio.charset.StandardCharsets; import java.util.Date; import java.util.Map; +import com.edufocus.edufocus.user.model.exception.ExpriedTokenException; +import com.edufocus.edufocus.user.model.exception.InvalidTokenException; import com.edufocus.edufocus.user.model.exception.UnAuthorizedException; import io.jsonwebtoken.*; import org.springframework.beans.factory.annotation.Value; @@ -52,19 +54,27 @@ public class JWTUtil { public boolean checkToken(String token) { try { - Jws claims = Jwts.parserBuilder() - .setSigningKey(generateKey()) - .build() - .parseClaimsJws(token); - log.debug("claims: {}", claims); - return true; - } catch (MalformedJwtException | UnsupportedJwtException | IllegalArgumentException | SignatureException | ExpiredJwtException e) { - log.error("Token validation error: {}", e.getMessage()); - return false; - } catch (Exception e) { - System.out.println(token); - log.error("Unexpected error while validating token: {}", e.getMessage()); - return false; + Jws claims = Jwts.parserBuilder() + .setSigningKey(generateKey()) + .build() + .parseClaimsJws(token); + log.debug("claims: {}", claims); + return true; + } catch (MalformedJwtException | UnsupportedJwtException | IllegalArgumentException | SignatureException e) { + log.error("Token validation error: {}", e.getMessage()); + + return false; + } + catch ( ExpiredJwtException e) + { + throw new ExpriedTokenException(); + + } + catch (Exception e) { + System.out.println(token); + System.out.println(e.getMessage()); + log.error("Unexpected error while validating token: {}", e.getMessage()); + return false; } } @@ -77,7 +87,13 @@ public class JWTUtil { Map value = claims.getBody(); log.info("value : {}", value); return (String) value.get("id"); - } catch (Exception e) { + }catch ( ExpiredJwtException e) + { + System.out.println("expired token"); + throw new ExpriedTokenException(); + + } + catch (Exception e) { log.error("Failed to get user ID from token: {}", e.getMessage()); throw new UnAuthorizedException(); } diff --git a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java index c4fa32c..40b206a 100644 --- a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java +++ b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java @@ -7,6 +7,9 @@ import com.edufocus.edufocus.lecture.entity.LectureDetailResponse; import com.edufocus.edufocus.lecture.service.LectureService; import com.edufocus.edufocus.registration.entity.RegistrationStatus; import com.edufocus.edufocus.registration.service.RegistrationService; +import com.edufocus.edufocus.user.model.entity.User; +import com.edufocus.edufocus.user.model.entity.UserRole; +import com.edufocus.edufocus.user.model.repository.UserRepository; import com.edufocus.edufocus.user.model.service.UserService; import com.edufocus.edufocus.user.util.JWTUtil; import com.edufocus.edufocus.video.service.VideoSertvice; @@ -33,6 +36,7 @@ public class Controller { private final LectureService lectureService; private final VideoSertvice videoSertvice; private final RegistrationService registrationService; + private final UserRepository userRepository; @Value("${livekit.api.key}") private String LIVEKIT_API_KEY; @@ -70,39 +74,13 @@ public class Controller { Long userId = Long.parseLong(jwtUtil.getUserId(userToken)); - LectureDetailResponse lecture= lectureService.findLectureById(userId,id); - - String roomName = lecture.getTitle(); - String participantName = userService.getUserName(userId); + User findUser= userRepository.findById(userId).orElse(null); - AccessToken token = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); - token.setName(participantName); - token.setIdentity(participantName); - token.addGrants(new RoomJoin(true), new RoomName(roomName),new RoomCreate(true)); - - videoSertvice.startOnline(userId,id); + if(findUser.getRole()==UserRole.ADMIN) { + LectureDetailResponse lecture = lectureService.findLectureById(userId, id); - - - return ResponseEntity.ok(Map.of("token", token.toJwt())); - } - - - @PostMapping(value = "/joinroom/{lecture_id}") - public ResponseEntity> joinRoom(@PathVariable("lecture_id") Long id, HttpServletRequest request) throws Exception { - - String userToken = request.getHeader("Authorization"); - - Long userId = Long.parseLong(jwtUtil.getUserId(userToken)); - LectureDetailResponse lecture= lectureService.findLectureById(userId,id); - - - //RegistrationStatus registrationStatus = registrationService.isOnline(userId,id); - -// if(registrationStatus==RegistrationStatus.ACCEPTED) -// { String roomName = lecture.getTitle(); String participantName = userService.getUserName(userId); @@ -110,23 +88,79 @@ public class Controller { AccessToken token = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); token.setName(participantName); token.setIdentity(participantName); - token.addGrants(new RoomJoin(true), new RoomName(roomName)); - - //videoSertvice.startOnline(userId,id); + token.addGrants(new RoomJoin(true), new RoomName(roomName), new RoomCreate(true)); + videoSertvice.startOnline(userId, id); return ResponseEntity.ok(Map.of("token", token.toJwt())); -// } -// else{ -// return ResponseEntity.status(HttpStatus.FORBIDDEN).body(Map.of("errorMessage", "Not accepted")); -// -// } + + } + else if(findUser.getRole()==UserRole.STUDENT) + { + LectureDetailResponse lecture = lectureService.findLectureById(userId, id); + + + String roomName = lecture.getTitle(); + String participantName = userService.getUserName(userId); + + + AccessToken token = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); + token.setName(participantName); + token.setIdentity(participantName); + token.addGrants(new RoomJoin(true), new RoomName(roomName), new RoomCreate(true)); + + videoSertvice.startOnline(userId, id); + + + return ResponseEntity.ok(Map.of("token", token.toJwt())); + } + + + return ResponseEntity.ok(Map.of("token", null)); } + +// @PostMapping(value = "/joinroom/{lecture_id}") +// public ResponseEntity> joinRoom(@PathVariable("lecture_id") Long id, HttpServletRequest request) throws Exception { +// +//// String userToken = request.getHeader("Authorization"); +//// +//// Long userId = Long.parseLong(jwtUtil.getUserId(userToken)); +//// LectureDetailResponse lecture= lectureService.findLectureById(userId,id); +//// +//// +//// //RegistrationStatus registrationStatus = registrationService.isOnline(userId,id); +//// +////// if(registrationStatus==RegistrationStatus.ACCEPTED) +////// { +//// String roomName = lecture.getTitle(); +//// String participantName = userService.getUserName(userId); +//// +//// +//// AccessToken token = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); +//// token.setName(participantName); +//// token.setIdentity(participantName); +//// token.addGrants(new RoomJoin(true), new RoomName(roomName)); +//// +//// //videoSertvice.startOnline(userId,id); +//// +//// +//// +//// return ResponseEntity.ok(Map.of("token", token.toJwt())); +////// } +////// else{ +////// return ResponseEntity.status(HttpStatus.FORBIDDEN).body(Map.of("errorMessage", "Not accepted")); +////// +////// } +//// +// +// +// } + @PostMapping(value = "/livekit/webhook", consumes = "application/webhook+json") public ResponseEntity receiveWebhook(@RequestHeader("Authorization") String authHeader, @RequestBody String body) { WebhookReceiver webhookReceiver = new WebhookReceiver(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); From f813e55733486d0617470d3be51afe8af2173eb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Wed, 31 Jul 2024 10:37:40 +0900 Subject: [PATCH 069/197] BE/userinfo --- .../lecture/service/LectureService.java | 1 + .../lecture/service/LectureServiceImpl.java | 8 ++ .../exception/GlobalExceptionHandler.java | 2 - .../edufocus/video/controller/Controller.java | 103 ++++++++++-------- 4 files changed, 67 insertions(+), 47 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java index 65153a0..e8483d4 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java @@ -28,4 +28,5 @@ public interface LectureService { Lecture findLectureByTitle(String title); void changeState(Long lectureId); + boolean getState(Long lectureId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java index 90da51c..e770f55 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java @@ -239,5 +239,13 @@ public class LectureServiceImpl implements LectureService { lectureRepository.save(l); } + @Override + public boolean getState(Long lectureId) { + + Lecture lecture= lectureRepository.findById(lectureId).orElse(null); + return lecture.isOnline(); + + } + } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/exception/GlobalExceptionHandler.java b/backend/src/main/java/com/edufocus/edufocus/user/model/exception/GlobalExceptionHandler.java index 526e6ae..81042dc 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/exception/GlobalExceptionHandler.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/exception/GlobalExceptionHandler.java @@ -19,8 +19,6 @@ public class GlobalExceptionHandler { @ExceptionHandler(ExpriedTokenException.class) public ResponseEntity handleInvalidTokenException(ExpriedTokenException e) { - // 로그 남기기 (선택 사항) - // log.error("Invalid token", e); return new ResponseEntity<>(e.getMessage(), HttpStatus.UNAUTHORIZED); } diff --git a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java index 40b206a..1fe7492 100644 --- a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java +++ b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java @@ -4,6 +4,7 @@ import java.util.Map; import com.edufocus.edufocus.lecture.entity.Lecture; import com.edufocus.edufocus.lecture.entity.LectureDetailResponse; +import com.edufocus.edufocus.lecture.repository.LectureRepository; import com.edufocus.edufocus.lecture.service.LectureService; import com.edufocus.edufocus.registration.entity.RegistrationStatus; import com.edufocus.edufocus.registration.service.RegistrationService; @@ -37,6 +38,7 @@ public class Controller { private final VideoSertvice videoSertvice; private final RegistrationService registrationService; private final UserRepository userRepository; + private final LectureRepository lectureRepository; @Value("${livekit.api.key}") private String LIVEKIT_API_KEY; @@ -67,18 +69,37 @@ public class Controller { // } @PostMapping(value = "/makeroom/{lecture_id}") - public ResponseEntity> startLecture(@PathVariable("lecture_id") Long id, HttpServletRequest request) throws Exception { + public ResponseEntity startLecture(@PathVariable("lecture_id") Long id, HttpServletRequest request) throws Exception { + + + String userToken = request.getHeader("Authorization"); + Long userId = Long.parseLong(jwtUtil.getUserId(userToken)); + + + videoSertvice.startOnline(userId, id); + + return new ResponseEntity<>("방만들기 성공",HttpStatus.OK); + + } + + + @PostMapping(value = "/joinroom/{lecture_id}") + public ResponseEntity> joinRoom(@PathVariable("lecture_id") Long id, HttpServletRequest request) throws Exception + { String userToken = request.getHeader("Authorization"); - log.info("userToekn : ", userToken); Long userId = Long.parseLong(jwtUtil.getUserId(userToken)); User findUser= userRepository.findById(userId).orElse(null); + Lecture lecture= lectureRepository.findById(id).orElse(null); - if(findUser.getRole()==UserRole.ADMIN) { - LectureDetailResponse lecture = lectureService.findLectureById(userId, id); + + + + if(findUser.getRole()==UserRole.ADMIN && lecture.isOnline() ) { + String roomName = lecture.getTitle(); @@ -96,9 +117,8 @@ public class Controller { return ResponseEntity.ok(Map.of("token", token.toJwt())); } - else if(findUser.getRole()==UserRole.STUDENT) + else if(findUser.getRole()==UserRole.STUDENT && lecture.isOnline() ) { - LectureDetailResponse lecture = lectureService.findLectureById(userId, id); String roomName = lecture.getTitle(); @@ -108,7 +128,8 @@ public class Controller { AccessToken token = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); token.setName(participantName); token.setIdentity(participantName); - token.addGrants(new RoomJoin(true), new RoomName(roomName), new RoomCreate(true)); + token.addGrants(new RoomJoin(true), new RoomName(roomName)); + videoSertvice.startOnline(userId, id); @@ -119,48 +140,40 @@ public class Controller { return ResponseEntity.ok(Map.of("token", null)); +// String userToken = request.getHeader("Authorization"); +// +// Long userId = Long.parseLong(jwtUtil.getUserId(userToken)); +// LectureDetailResponse lecture= lectureService.findLectureById(userId,id); +// +// +// //RegistrationStatus registrationStatus = registrationService.isOnline(userId,id); +// +// if(registrationStatus==RegistrationStatus.ACCEPTED) +// { +// String roomName = lecture.getTitle(); +// String participantName = userService.getUserName(userId); +// +// +// AccessToken token = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); +// token.setName(participantName); +// token.setIdentity(participantName); +// token.addGrants(new RoomJoin(true), new RoomName(roomName)); +// +// //videoSertvice.startOnline(userId,id); +// +// +// +// return ResponseEntity.ok(Map.of("token", token.toJwt())); +// } +// else{ +// return ResponseEntity.status(HttpStatus.FORBIDDEN).body(Map.of("errorMessage", "Not accepted")); +// +// } + } - -// @PostMapping(value = "/joinroom/{lecture_id}") -// public ResponseEntity> joinRoom(@PathVariable("lecture_id") Long id, HttpServletRequest request) throws Exception { -// -//// String userToken = request.getHeader("Authorization"); -//// -//// Long userId = Long.parseLong(jwtUtil.getUserId(userToken)); -//// LectureDetailResponse lecture= lectureService.findLectureById(userId,id); -//// -//// -//// //RegistrationStatus registrationStatus = registrationService.isOnline(userId,id); -//// -////// if(registrationStatus==RegistrationStatus.ACCEPTED) -////// { -//// String roomName = lecture.getTitle(); -//// String participantName = userService.getUserName(userId); -//// -//// -//// AccessToken token = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); -//// token.setName(participantName); -//// token.setIdentity(participantName); -//// token.addGrants(new RoomJoin(true), new RoomName(roomName)); -//// -//// //videoSertvice.startOnline(userId,id); -//// -//// -//// -//// return ResponseEntity.ok(Map.of("token", token.toJwt())); -////// } -////// else{ -////// return ResponseEntity.status(HttpStatus.FORBIDDEN).body(Map.of("errorMessage", "Not accepted")); -////// -////// } -//// -// -// -// } - @PostMapping(value = "/livekit/webhook", consumes = "application/webhook+json") public ResponseEntity receiveWebhook(@RequestHeader("Authorization") String authHeader, @RequestBody String body) { WebhookReceiver webhookReceiver = new WebhookReceiver(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); From 62dde35a66e1287426f69bf91f20fce4a6a34ccc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Wed, 31 Jul 2024 11:07:11 +0900 Subject: [PATCH 070/197] =?UTF-8?q?feat:=20global=20exception=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/user/model/exception/GlobalExceptionHandler.java | 4 ++-- .../main/java/com/edufocus/edufocus/user/util/JWTUtil.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/exception/GlobalExceptionHandler.java b/backend/src/main/java/com/edufocus/edufocus/user/model/exception/GlobalExceptionHandler.java index 81042dc..63355d3 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/exception/GlobalExceptionHandler.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/exception/GlobalExceptionHandler.java @@ -8,8 +8,8 @@ import org.springframework.web.bind.annotation.ExceptionHandler; @ControllerAdvice public class GlobalExceptionHandler { - @ExceptionHandler(UnAuthorizedException.class) - public ResponseEntity handleUnAuthorizedException(UnAuthorizedException e) { + @ExceptionHandler(InvalidTokenException.class) + public ResponseEntity handleUnAuthorizedException(InvalidTokenException e) { diff --git a/backend/src/main/java/com/edufocus/edufocus/user/util/JWTUtil.java b/backend/src/main/java/com/edufocus/edufocus/user/util/JWTUtil.java index ffce34c..89f068f 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/util/JWTUtil.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/util/JWTUtil.java @@ -95,7 +95,7 @@ public class JWTUtil { } catch (Exception e) { log.error("Failed to get user ID from token: {}", e.getMessage()); - throw new UnAuthorizedException(); + throw new InvalidTokenException(); } } } From 34050e912d986a5a8059b2bb61fad9b7da40684c Mon Sep 17 00:00:00 2001 From: kgc9007 Date: Wed, 31 Jul 2024 11:17:46 +0900 Subject: [PATCH 071/197] =?UTF-8?q?feat:=20Registration=20=EA=B0=95?= =?UTF-8?q?=EC=9D=98=EB=B3=84=20=EC=88=98=EA=B0=95=EC=8B=A0=EC=B2=AD=20?= =?UTF-8?q?=ED=98=84=ED=99=A9=20=EC=A1=B0=ED=9A=8C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lecture/service/LectureService.java | 2 + .../lecture/service/LectureServiceImpl.java | 11 ++-- .../controller/RegistrationController.java | 29 +++++++---- .../registration/entity/Registration.java | 2 +- .../entity/RegistrationSearchResponse.java | 18 +++++++ .../repository/RegistrationRepository.java | 3 ++ .../service/RegistrationService.java | 13 +++-- .../service/RegistrationServiceImpl.java | 51 ++++++++++++++----- 8 files changed, 99 insertions(+), 30 deletions(-) create mode 100644 backend/src/main/java/com/edufocus/edufocus/registration/entity/RegistrationSearchResponse.java diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java index 65153a0..50e3b3c 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java @@ -28,4 +28,6 @@ public interface LectureService { Lecture findLectureByTitle(String title); void changeState(Long lectureId); + + boolean checkTeacher(Long userId, Long lectureId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java index 90da51c..2ba7032 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java @@ -223,8 +223,7 @@ public class LectureServiceImpl implements LectureService { Optional lecture = lectureRepository.findById(id); Lecture l; - if(lecture.isPresent()) - { + if (lecture.isPresent()) { l = lecture.get(); System.out.println(l.isOnline()); @@ -232,12 +231,18 @@ public class LectureServiceImpl implements LectureService { System.out.println(l.isOnline()); - }else { + } else { throw new RuntimeException("Lecture not found with id: " + id); } lectureRepository.save(l); } + @Override + public boolean checkTeacher(Long userId, Long lectureId) { + Optional lecture = lectureRepository.findById(lectureId); + + return lecture.isPresent() && lecture.get().getUser().getId() == userId; + } } diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/controller/RegistrationController.java b/backend/src/main/java/com/edufocus/edufocus/registration/controller/RegistrationController.java index ee36efb..6e008fe 100644 --- a/backend/src/main/java/com/edufocus/edufocus/registration/controller/RegistrationController.java +++ b/backend/src/main/java/com/edufocus/edufocus/registration/controller/RegistrationController.java @@ -1,5 +1,6 @@ package com.edufocus.edufocus.registration.controller; +import com.edufocus.edufocus.lecture.service.LectureService; import com.edufocus.edufocus.registration.service.RegistrationService; import com.edufocus.edufocus.user.util.JWTUtil; import lombok.RequiredArgsConstructor; @@ -16,7 +17,9 @@ import java.util.Map; @RequiredArgsConstructor public class RegistrationController { - private final RegistrationService registrationServiceImpl; + private final RegistrationService registrationService; + + private final LectureService lectureService; private final JWTUtil jwtUtil; @@ -25,7 +28,7 @@ public class RegistrationController { Long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); Long lectureId = map.get("lectureId"); - if (!registrationServiceImpl.createRegistration(userId, lectureId)) { + if (!registrationService.createRegistration(userId, lectureId)) { return new ResponseEntity<>(HttpStatus.CONFLICT); } @@ -36,12 +39,10 @@ public class RegistrationController { public ResponseEntity acceptRigistration(@RequestHeader("Authorization") String accessToken, @PathVariable long registrationId) { Long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); - if (!registrationServiceImpl.acceptRegistration(userId, registrationId)) { - String msg = new String("Not Acceptable"); - return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); + if (!registrationService.acceptRegistration(userId, registrationId)) { + return new ResponseEntity<>(HttpStatus.NOT_FOUND); } - String msg = new String("registration accepted"); return new ResponseEntity<>(HttpStatus.OK); } @@ -49,12 +50,22 @@ public class RegistrationController { public ResponseEntity deleteRigistration(@RequestHeader("Authorization") String accessToken, @PathVariable long registrationId) { Long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); - if (!registrationServiceImpl.deleteRegistration(userId, registrationId)) { - String msg = new String("Not Acceptable"); - return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); + if (!registrationService.deleteRegistration(userId, registrationId)) { + return new ResponseEntity<>(HttpStatus.NOT_FOUND); } return new ResponseEntity<>(HttpStatus.NO_CONTENT); } + @GetMapping("/{lectureId}") + public ResponseEntity getRegistrations(@RequestHeader("Authorization") String accessToken, @PathVariable long lectureId) { + Long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); + + if (!lectureService.checkTeacher(userId, lectureId)) { + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + } + + return new ResponseEntity<>(registrationService.searchRegistrations(lectureId), HttpStatus.OK); + } + } diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/entity/Registration.java b/backend/src/main/java/com/edufocus/edufocus/registration/entity/Registration.java index 4a81aba..38cfe35 100644 --- a/backend/src/main/java/com/edufocus/edufocus/registration/entity/Registration.java +++ b/backend/src/main/java/com/edufocus/edufocus/registration/entity/Registration.java @@ -26,5 +26,5 @@ public class Registration { private Lecture lecture; @Enumerated(EnumType.STRING) - private RegistrationStatus status ; + private RegistrationStatus status; } diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/entity/RegistrationSearchResponse.java b/backend/src/main/java/com/edufocus/edufocus/registration/entity/RegistrationSearchResponse.java new file mode 100644 index 0000000..e9c1b46 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/registration/entity/RegistrationSearchResponse.java @@ -0,0 +1,18 @@ +package com.edufocus.edufocus.registration.entity; + +import com.edufocus.edufocus.lecture.entity.Lecture; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class RegistrationSearchResponse { + + private Long id; + + private String userName; +} diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/repository/RegistrationRepository.java b/backend/src/main/java/com/edufocus/edufocus/registration/repository/RegistrationRepository.java index 251acaf..f8c31b7 100644 --- a/backend/src/main/java/com/edufocus/edufocus/registration/repository/RegistrationRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/registration/repository/RegistrationRepository.java @@ -2,6 +2,7 @@ package com.edufocus.edufocus.registration.repository; import com.edufocus.edufocus.registration.entity.Registration; 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; @@ -11,5 +12,7 @@ import java.util.List; public interface RegistrationRepository extends JpaRepository { List findAllByUserId(@Param("userId") Long userId); + List findAllNotAcceptedByLectureId(@Param("lectureId") Long lectureId); + Registration findByUserIdAndLectureId(Long userId, Long lectureId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationService.java b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationService.java index bc27b37..3c7d477 100644 --- a/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationService.java +++ b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationService.java @@ -1,17 +1,22 @@ package com.edufocus.edufocus.registration.service; import com.edufocus.edufocus.registration.entity.Registration; +import com.edufocus.edufocus.registration.entity.RegistrationSearchResponse; import com.edufocus.edufocus.registration.entity.RegistrationStatus; import org.springframework.stereotype.Service; +import java.util.List; + @Service public interface RegistrationService { - boolean createRegistration(long userId, long registrationId); + boolean createRegistration(Long userId, Long registrationId); - boolean acceptRegistration(long userId, long RegistrationId); + boolean acceptRegistration(Long userId, Long RegistrationId); - boolean deleteRegistration(long userId, long registrationId); + boolean deleteRegistration(Long userId, Long registrationId); - RegistrationStatus isOnline(Long userId , Long lectureId); + List searchRegistrations(Long LectureId); + + RegistrationStatus isOnline(Long userId, Long lectureId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java index 0eca5b5..e36c9a1 100644 --- a/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java @@ -1,14 +1,20 @@ package com.edufocus.edufocus.registration.service; +import com.edufocus.edufocus.lecture.entity.Lecture; import com.edufocus.edufocus.lecture.repository.LectureRepository; import com.edufocus.edufocus.registration.entity.Registration; +import com.edufocus.edufocus.registration.entity.RegistrationSearchResponse; import com.edufocus.edufocus.registration.entity.RegistrationStatus; import com.edufocus.edufocus.registration.repository.RegistrationRepository; +import com.edufocus.edufocus.user.model.entity.User; +import com.edufocus.edufocus.user.model.entity.UserRole; import com.edufocus.edufocus.user.model.repository.UserRepository; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; @Service @@ -21,14 +27,16 @@ public class RegistrationServiceImpl implements RegistrationService { private final LectureRepository lectureRepository; @Override - public boolean createRegistration(long userId, long lectureId) { - if (registrationRepository.findByUserIdAndLectureId(userId, lectureId) != null) { + public boolean createRegistration(Long userId, Long lectureId) { + Optional user = userRepository.findById(userId); + + if (user.isEmpty() || user.get().getRole().equals(UserRole.ADMIN)) { return false; } Registration registration = new Registration().builder() - .user(userRepository.getReferenceById(userId)) - .lecture(lectureRepository.getReferenceById(lectureId)) + .user(userRepository.findById(userId).get()) + .lecture(lectureRepository.findById(lectureId).get()) .status(RegistrationStatus.WAITING) .build(); @@ -37,24 +45,24 @@ public class RegistrationServiceImpl implements RegistrationService { } @Override - public boolean acceptRegistration(long userId, long registrationId) { - Registration registration = registrationRepository.findById(registrationId).get(); + public boolean acceptRegistration(Long userId, Long registrationId) { + Optional registration = registrationRepository.findById(registrationId); - if (registration.getLecture().getUser().getId() != userId) { + if (registration.isEmpty() || registration.get().getLecture().getUser().getId() != userId) { return false; } - registration.setStatus(RegistrationStatus.valueOf("ACCEPTED")); - registrationRepository.save(registration); + registration.get().setStatus(RegistrationStatus.valueOf("ACCEPTED")); + registrationRepository.save(registration.get()); return true; } @Override - public boolean deleteRegistration(long userId, long registrationId) { - Registration registration = registrationRepository.findById(registrationId).get(); + public boolean deleteRegistration(Long userId, Long registrationId) { + Optional registration = registrationRepository.findById(registrationId); - if (registration.getLecture().getUser().getId() != userId) { + if (registration.isEmpty() || registration.get().getLecture().getUser().getId() != userId) { return false; } @@ -62,10 +70,27 @@ public class RegistrationServiceImpl implements RegistrationService { return true; } + @Override + public List searchRegistrations(Long lectureId) { + List registrations = registrationRepository.findAllNotAcceptedByLectureId(lectureId); + + List responses = new ArrayList<>(); + for (Registration registration : registrations) { + RegistrationSearchResponse response = new RegistrationSearchResponse().builder() + .id(registration.getId()) + .userName(registration.getUser().getName()) + .build(); + + responses.add(response); + } + + return responses; + } + @Override public RegistrationStatus isOnline(Long userId, Long lectureId) { - Registration registration = registrationRepository.findByUserIdAndLectureId(userId,lectureId); + Registration registration = registrationRepository.findByUserIdAndLectureId(userId, lectureId); return registration.getStatus(); } From 60baa59027bc31c4bd5126da143796f73ac0bf48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Wed, 31 Jul 2024 12:37:37 +0900 Subject: [PATCH 072/197] =?UTF-8?q?feat:=20openvidu=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/edufocus/edufocus/video/controller/Controller.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java index 1fe7492..4c470ed 100644 --- a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java +++ b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java @@ -98,7 +98,7 @@ public class Controller { - if(findUser.getRole()==UserRole.ADMIN && lecture.isOnline() ) { + if(findUser.getRole()==UserRole.ADMIN ){//&& lecture.isOnline() ) { @@ -117,7 +117,7 @@ public class Controller { return ResponseEntity.ok(Map.of("token", token.toJwt())); } - else if(findUser.getRole()==UserRole.STUDENT && lecture.isOnline() ) + else if(findUser.getRole()==UserRole.STUDENT )// && lecture.isOnline() ) { From b9cc9b8a5063ac4e7c4ac3b349d15587cf1ea2a3 Mon Sep 17 00:00:00 2001 From: yulmam Date: Wed, 31 Jul 2024 12:52:40 +0900 Subject: [PATCH 073/197] =?UTF-8?q?feat=20:=20rabbitmq=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/config/PropertiesConfig.java | 13 ++++ .../global/constant/RabbitMQConstant.java | 15 ++++ .../global/properties/RabbitMQProperties.java | 16 ++++ .../user/config/WebConfiguration.java | 69 +++++++++-------- .../edufocus/ws/config/RabbitConfig.java | 75 ++++++++++++++++++- .../ws/config/WebSocketConfigurer.java | 18 ++++- .../ws/controller/ChatController.java | 72 ++++-------------- .../src/main/resources/application.properties | 6 ++ 8 files changed, 186 insertions(+), 98 deletions(-) create mode 100644 backend/src/main/java/com/edufocus/edufocus/global/config/PropertiesConfig.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/global/constant/RabbitMQConstant.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/global/properties/RabbitMQProperties.java diff --git a/backend/src/main/java/com/edufocus/edufocus/global/config/PropertiesConfig.java b/backend/src/main/java/com/edufocus/edufocus/global/config/PropertiesConfig.java new file mode 100644 index 0000000..4c3323e --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/global/config/PropertiesConfig.java @@ -0,0 +1,13 @@ +package com.edufocus.edufocus.global.config; + + +import com.edufocus.edufocus.global.properties.RabbitMQProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +@Configuration +@EnableConfigurationProperties({ + RabbitMQProperties.class +}) +public class PropertiesConfig { +} diff --git a/backend/src/main/java/com/edufocus/edufocus/global/constant/RabbitMQConstant.java b/backend/src/main/java/com/edufocus/edufocus/global/constant/RabbitMQConstant.java new file mode 100644 index 0000000..4ccd8fc --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/global/constant/RabbitMQConstant.java @@ -0,0 +1,15 @@ +package com.edufocus.edufocus.global.constant; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum RabbitMQConstant { + + CHAT_QUEUE_NAME("chat.queue"), + CHAT_EXCHANGE("chat.exchange"), + ROUTING_KEY("*.room.*"), + ROUTING_KEY_PREFIX("*.room.");; + private final String constant; +} diff --git a/backend/src/main/java/com/edufocus/edufocus/global/properties/RabbitMQProperties.java b/backend/src/main/java/com/edufocus/edufocus/global/properties/RabbitMQProperties.java new file mode 100644 index 0000000..461022c --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/global/properties/RabbitMQProperties.java @@ -0,0 +1,16 @@ +package com.edufocus.edufocus.global.properties; + + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.boot.context.properties.ConfigurationProperties; + +@Getter +@RequiredArgsConstructor +@ConfigurationProperties(prefix = "spring.rabbitmq") +public class RabbitMQProperties { + private final String host; + private final Integer port; + private final String username; + private final String password; +} diff --git a/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java b/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java index 38dff9d..9e7859f 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java @@ -14,39 +14,38 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @EnableWebMvc public class WebConfiguration implements WebMvcConfigurer { -// private JWTInterceptor jwtInterceptor; -// -// public WebConfiguration(JWTInterceptor jwtInterceptor) { -// super(); -// -// this.jwtInterceptor = jwtInterceptor; -// } -// -// @Override -// public void addCorsMappings(CorsRegistry registry) { -// registry -// .addMapping("/**") -// .allowedOrigins("http://i11a701.p.ssafy.io/", "http://localhost:5173", "http://localhost:4173") -// .allowedMethods(HttpMethod.GET.name(), HttpMethod.POST.name(), HttpMethod.PUT.name(), -// HttpMethod.DELETE.name(), HttpMethod.HEAD.name(), HttpMethod.OPTIONS.name(), -// HttpMethod.PATCH.name()) -// .allowCredentials(true) -// .allowedHeaders("*") -// .maxAge(1800); // Pre-flight Caching -// } -// -// @Override -// public void addResourceHandlers(ResourceHandlerRegistry registry) { -// registry.addResourceHandler("/img/**").addResourceLocations("classpath:/static/assets/img/"); -// registry.addResourceHandler("/*.html**").addResourceLocations("classpath:/static/"); -// } -// @Override -// public void addInterceptors(InterceptorRegistry registry) { -// registry.addInterceptor(jwtInterceptor) -// -// .addPathPatterns("/**") // 모든 경로에 대해 인터셉터 적용 -// .excludePathPatterns("/v3/api-docs/**","/swagger-resources/**","/webjars/**","/swagger-ui/**","/auth/**", "/board/**", "/user/**","/lecture/**","/qna/**", "/quiz/**"); // 인증 없이 접근 가능한 경로 설정 -// -// ///v3/api-docs/**, /swagger-resources/**, /webjars/** -// } + private JWTInterceptor jwtInterceptor; + + public WebConfiguration(JWTInterceptor jwtInterceptor) { + super(); + + this.jwtInterceptor = jwtInterceptor; + } + + @Override + public void addCorsMappings(CorsRegistry registry) { + registry + .addMapping("/**") + .allowedOrigins("http://i11a701.p.ssafy.io/", "http://localhost:5173", "http://localhost:4173") + .allowedMethods(HttpMethod.GET.name(), HttpMethod.POST.name(), HttpMethod.PUT.name(), + HttpMethod.DELETE.name(), HttpMethod.HEAD.name(), HttpMethod.OPTIONS.name(), + HttpMethod.PATCH.name()) + .allowCredentials(true) + .allowedHeaders("*") + .maxAge(1800); // Pre-flight Caching + } + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("/img/**").addResourceLocations("classpath:/static/assets/img/"); + registry.addResourceHandler("/*.html**").addResourceLocations("classpath:/static/"); + } + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(jwtInterceptor) + .addPathPatterns("/**") // 모든 경로에 대해 인터셉터 적용 + .excludePathPatterns("/v3/api-docs/**","/swagger-resources/**","/webjars/**","/swagger-ui/**","/auth/**", "/board/**", "/user/**","/lecture/**","/qna/**", "/quiz/**"); // 인증 없이 접근 가능한 경로 설정 + + ///v3/api-docs/**, /swagger-resources/**, /webjars/** + } } \ No newline at end of file diff --git a/backend/src/main/java/com/edufocus/edufocus/ws/config/RabbitConfig.java b/backend/src/main/java/com/edufocus/edufocus/ws/config/RabbitConfig.java index 783000a..349316a 100644 --- a/backend/src/main/java/com/edufocus/edufocus/ws/config/RabbitConfig.java +++ b/backend/src/main/java/com/edufocus/edufocus/ws/config/RabbitConfig.java @@ -1,2 +1,73 @@ -package com.edufocus.edufocus.ws.config;public class RabbitConfig { -} +package com.edufocus.edufocus.ws.config; + + +import com.edufocus.edufocus.global.constant.RabbitMQConstant; +import com.edufocus.edufocus.global.properties.RabbitMQProperties; +import org.springframework.amqp.core.*; +import org.springframework.amqp.rabbit.connection.CachingConnectionFactory; +import org.springframework.amqp.rabbit.connection.ConnectionFactory; +import org.springframework.amqp.rabbit.core.RabbitAdmin; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; +import org.springframework.amqp.support.converter.MessageConverter; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class RabbitConfig { + + private final RabbitMQProperties rabbitMQProperties; + + public RabbitConfig(RabbitMQProperties rabbitMQProperties) { + this.rabbitMQProperties = rabbitMQProperties; + } + + @Bean + public Queue queue() { + + return new Queue(RabbitMQConstant.CHAT_QUEUE_NAME.getConstant(), true); + } + + @Bean + public TopicExchange exchange() { + return new TopicExchange(RabbitMQConstant.CHAT_EXCHANGE.getConstant()); + } + + @Bean + Binding binding(TopicExchange topicExchange, Queue queue) { + return BindingBuilder.bind(queue).to(topicExchange).with(RabbitMQConstant.ROUTING_KEY.getConstant()); + } + + @Bean + ConnectionFactory connectionFactory() { + CachingConnectionFactory connectionFactory = new CachingConnectionFactory(); + connectionFactory.setHost(rabbitMQProperties.getHost()); + connectionFactory.setPort(rabbitMQProperties.getPort()); + connectionFactory.setUsername(rabbitMQProperties.getUsername()); + connectionFactory.setPassword(rabbitMQProperties.getPassword()); + return connectionFactory; + } + + @Bean + public AmqpAdmin amqpAdmin() { + RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory()); + rabbitAdmin.declareQueue(queue()); + return rabbitAdmin; + } + + + @Bean + MessageConverter messageConverter() { + return new Jackson2JsonMessageConverter(); + } + + + + @Bean + RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory, MessageConverter messageConverter) { + RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory); + rabbitTemplate.setMessageConverter(messageConverter); + return rabbitTemplate; + } +} \ No newline at end of file diff --git a/backend/src/main/java/com/edufocus/edufocus/ws/config/WebSocketConfigurer.java b/backend/src/main/java/com/edufocus/edufocus/ws/config/WebSocketConfigurer.java index f99bf50..30a6441 100644 --- a/backend/src/main/java/com/edufocus/edufocus/ws/config/WebSocketConfigurer.java +++ b/backend/src/main/java/com/edufocus/edufocus/ws/config/WebSocketConfigurer.java @@ -1,7 +1,9 @@ package com.edufocus.edufocus.ws.config; +import com.edufocus.edufocus.global.properties.RabbitMQProperties; import org.springframework.context.annotation.Configuration; import org.springframework.messaging.simp.config.MessageBrokerRegistry; +import org.springframework.util.AntPathMatcher; import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; import org.springframework.web.socket.config.annotation.StompEndpointRegistry; import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; @@ -10,15 +12,23 @@ import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerCo @EnableWebSocketMessageBroker public class WebSocketConfigurer implements WebSocketMessageBrokerConfigurer { + private final RabbitMQProperties rabbitMQProperties; + + public WebSocketConfigurer(RabbitMQProperties rabbitMQProperties) { + this.rabbitMQProperties = rabbitMQProperties; + } + @Override public void configureMessageBroker(MessageBrokerRegistry registry) { + registry.setPathMatcher(new AntPathMatcher(".")); + registry.setApplicationDestinationPrefixes("/pub") - .enableStompBrokerRelay("/topic") - .setRelayHost("localhost") + .enableStompBrokerRelay("/topic", "/queue", "/exchange") + .setRelayHost(rabbitMQProperties.getHost()) .setVirtualHost("/") .setRelayPort(61613) - .setClientLogin("guest") - .setClientPasscode("guest"); + .setClientLogin(rabbitMQProperties.getUsername()) + .setClientPasscode(rabbitMQProperties.getPassword()); } @Override diff --git a/backend/src/main/java/com/edufocus/edufocus/ws/controller/ChatController.java b/backend/src/main/java/com/edufocus/edufocus/ws/controller/ChatController.java index 5623b66..dbf5d8e 100644 --- a/backend/src/main/java/com/edufocus/edufocus/ws/controller/ChatController.java +++ b/backend/src/main/java/com/edufocus/edufocus/ws/controller/ChatController.java @@ -1,11 +1,13 @@ package com.edufocus.edufocus.ws.controller; +import com.edufocus.edufocus.global.constant.RabbitMQConstant; import com.edufocus.edufocus.user.util.JWTUtil; import com.edufocus.edufocus.ws.entity.dto.MessageDto; import com.edufocus.edufocus.ws.entity.dto.QuizDto; import com.edufocus.edufocus.ws.entity.dto.ChatUserDto; import com.edufocus.edufocus.ws.service.ChatService; +import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.context.event.EventListener; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -30,70 +32,26 @@ import java.util.List; @RestController public class ChatController { - private final SimpMessageSendingOperations simpMessageSendingOperations; + RabbitTemplate rabbitTemplate; - private final ChatService chatService; - - private final JWTUtil jwtUtil; - - public ChatController(SimpMessageSendingOperations simpMessageSendingOperations, ChatService chatService, JWTUtil jwtUtil){ - this.simpMessageSendingOperations = simpMessageSendingOperations; - this.chatService = chatService; - this.jwtUtil = jwtUtil; + public ChatController(RabbitTemplate rabbitTemplate){ + this.rabbitTemplate = rabbitTemplate; } - @GetMapping("/chat/enter/{lectureId}") - public ResponseEntity enter(@PathVariable long lectureId){ - List chatUsers = chatService.findChatUsers(lectureId); - - return new ResponseEntity<>(chatUsers, HttpStatus.OK); + @MessageMapping("chat.message.{lectureId}") + public void sendMessage(@DestinationVariable long lectureId, MessageDto messageDto){ + rabbitTemplate.convertAndSend(RabbitMQConstant.CHAT_EXCHANGE.getConstant(), + RabbitMQConstant.ROUTING_KEY_PREFIX.getConstant() + lectureId, + messageDto); } - - @MessageMapping("/hello/{channelId}") - @SendTo("/topic/{channelId}") - public ChatUserDto hello(@DestinationVariable long channelId, SimpMessageHeaderAccessor simpMessageHeaderAccessor, @Header("Authorization") String token){ - String sessionId = simpMessageHeaderAccessor.getSessionId(); - - System.out.println("session" + sessionId); - - System.out.println("가냐?????"+token); - - long userId = Long.parseLong(jwtUtil.getUserId(token)); - - chatService.saveChatUserInfo(userId, channelId, sessionId); - - return chatService.getChatUserInfo(userId); + @MessageMapping("chat.quiz.{lectureId}") + public void quizStart(@DestinationVariable long lectureId, QuizDto quizDto){ + rabbitTemplate.convertAndSend(RabbitMQConstant.CHAT_EXCHANGE.getConstant(), + RabbitMQConstant.ROUTING_KEY_PREFIX.getConstant() + lectureId, + quizDto); } - @MessageMapping("/message/{lectureId}") - @SendTo("/topic/{lectureId}") - public MessageDto sendMessage(@DestinationVariable long lectureId, MessageDto messageDto){return messageDto;} - - @MessageMapping("/quiz/{lectureId}") - @SendTo("/topic/{lectureId}") - public QuizDto quizStart(@DestinationVariable long lectureId, QuizDto quizDto){ - return quizDto; - } - -// @EventListener -// public void handleWebSocketDisconnectListener(SessionDisconnectEvent event){ -// StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(event.getMessage()); -// String sessionId = headerAccessor.getSessionId(); -// -// -// ChatUserDto chatUserDto = chatService.getChatUserInfo(sessionId); -// -// -// if(chatService.checkTeacher(chatUserDto)){ -// chatService.closeChatRoom(chatUserDto.getLectureId()); -// simpMessageSendingOperations.convertAndSend("/sub/channel/" + chatUserDto.getLectureId(), "강의가 종료 됐습니다."); -// return; -// } -// -// chatService.deleteChatUserInfo(chatUserDto.getUserId()); -// simpMessageSendingOperations.convertAndSend("/sub/channel/" + chatUserDto.getLectureId(), chatUserDto); -// } } diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 71bd62a..9427387 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -37,3 +37,9 @@ spring.mail.password=mnlyfkiprltjlsmw spring.mail.properties.mail.smtp.auth=true spring.mail.properties.mail.smtp.starttls.enable=true + + +spring.rabbitmq.host=${RABBITMQ_HOST} +spring.rabbitmq.port=${RABBITMQ_PORT} +spring.rabbitmq.username=${RABBITMQ_USERNAME} +spring.rabbitmq.password=${RABBITMQ_PASSWORD} \ No newline at end of file From 47d8649057494288b623323fba28bf9ce1adeb1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Wed, 31 Jul 2024 13:02:33 +0900 Subject: [PATCH 074/197] =?UTF-8?q?feat:=20sameorigin=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/edufocus/edufocus/qna/service/QnaServiceImpl.java | 3 +-- .../edufocus/edufocus/user/controller/UserController.java | 6 +++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java index bed4103..5ab58f9 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java @@ -66,8 +66,7 @@ public class QnaServiceImpl implements QnaService{ findQna.setTitle(qnaRequestDto.getTitle()); findQna.setContent(qnaRequestDto.getContent()); - qnaRepository.save(findQna); - + qnaRepository.save(findQna); return QnaResponseDto.toEntity(findQna); diff --git a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java index 6526a03..464020f 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java @@ -102,8 +102,12 @@ public class UserController { refreshCookie.setPath("/"); refreshCookie.setHttpOnly(true); // refreshCookie.setSecure(true); // HTTPS에서만 전송되도록 설정 - // refreshCookie.setSameSite(Cookie.SameSite.NONE); // Cross-Origin 요청에 대해 모두 전송 + //r/efreshCookie.setSameSite(Cookie.SameSite.NONE); // Cross-Origin 요청에 대해 모두 전송 + //refreshCookie.setSameSite("None"); // Cross-Origin 요청에 대해 모두 전송 + String cookieHeader = String.format("refresh-token=%s; Path=/; HttpOnly; Secure; SameSite=None", refreshToken); + response.setHeader("Set-Cookie", cookieHeader); + // refreshCookie.setSameSite("None"); // Cross-Origin 요청에 대해 모두 전송 response.addCookie(refreshCookie); From 9934fef06ca43a0265559743beae6e433870cc78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Wed, 31 Jul 2024 13:50:34 +0900 Subject: [PATCH 075/197] faet: cookie --- .../com/edufocus/edufocus/user/controller/UserController.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java index 464020f..2f3abf4 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java @@ -101,9 +101,10 @@ public class UserController { Cookie refreshCookie = new Cookie("refresh-token", refreshToken); refreshCookie.setPath("/"); refreshCookie.setHttpOnly(true); - // refreshCookie.setSecure(true); // HTTPS에서만 전송되도록 설정 + refreshCookie.setSecure(true); // HTTPS에서만 전송되도록 설정 //r/efreshCookie.setSameSite(Cookie.SameSite.NONE); // Cross-Origin 요청에 대해 모두 전송 //refreshCookie.setSameSite("None"); // Cross-Origin 요청에 대해 모두 전송 + String cookieHeader = String.format("refresh-token=%s; Path=/; HttpOnly; Secure; SameSite=None", refreshToken); response.setHeader("Set-Cookie", cookieHeader); From 051ea7cad4a5d7c36dcb7c4c86f59841b1a4bbc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Wed, 31 Jul 2024 14:11:54 +0900 Subject: [PATCH 076/197] =?UTF-8?q?feat:=20cors=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/edufocus/edufocus/user/config/WebConfiguration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java b/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java index 61dd3ae..6eed008 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java @@ -26,7 +26,7 @@ public class WebConfiguration implements WebMvcConfigurer { public void addCorsMappings(CorsRegistry registry) { registry .addMapping("/**") - .allowedOrigins("http://i11a701.p.ssafy.io/", "http://localhost:5173", "http://localhost:4173","http://localhost:5080") + .allowedOrigins("https://i11a701.p.ssafy.io/", "http://localhost:5173", "http://localhost:4173","http://localhost:5080") .allowedMethods(HttpMethod.GET.name(), HttpMethod.POST.name(), HttpMethod.PUT.name(), HttpMethod.DELETE.name(), HttpMethod.HEAD.name(), HttpMethod.OPTIONS.name(), HttpMethod.PATCH.name()) From c854debbe746074d6ec00dcf2abb072fa26cb46e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Wed, 31 Jul 2024 15:11:49 +0900 Subject: [PATCH 077/197] feat: cors --- .../com/edufocus/edufocus/user/config/WebConfiguration.java | 3 ++- .../com/edufocus/edufocus/user/controller/UserController.java | 2 ++ .../edufocus/edufocus/user/model/service/UserServiceImpl.java | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java b/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java index 6eed008..b95ccb1 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java @@ -26,7 +26,7 @@ public class WebConfiguration implements WebMvcConfigurer { public void addCorsMappings(CorsRegistry registry) { registry .addMapping("/**") - .allowedOrigins("https://i11a701.p.ssafy.io/", "http://localhost:5173", "http://localhost:4173","http://localhost:5080") + .allowedOrigins("https://i11a701.p.ssafy.io/", "http://localhost:5173", "http://localhost:4173","http://localhost:5080","http://192.168.*:5173") .allowedMethods(HttpMethod.GET.name(), HttpMethod.POST.name(), HttpMethod.PUT.name(), HttpMethod.DELETE.name(), HttpMethod.HEAD.name(), HttpMethod.OPTIONS.name(), HttpMethod.PATCH.name()) @@ -35,6 +35,7 @@ public class WebConfiguration implements WebMvcConfigurer { .maxAge(1800); // Pre-flight Caching } + @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/img/**").addResourceLocations("classpath:/static/assets/img/"); diff --git a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java index 2f3abf4..77d1774 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java @@ -35,6 +35,8 @@ public class UserController { public ResponseEntity join(@RequestBody User user) throws Exception { + System.out.println("@@@@@"); + log.info("@@@@@@@@@@@@@@@@"); userService.join(user); return ResponseEntity.ok("User registered successfully"); } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java index 06ee58a..dd8667a 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java @@ -23,7 +23,7 @@ public class UserServiceImpl implements UserService { private final UserRepository userRepository; - private final JavaMailSender mailSender; + private final JavaMailSender mailSender;//private final PasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); public void join(User user) From b28b6b76373ae7b790842d49150ef726c1676d98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Wed, 31 Jul 2024 15:20:25 +0900 Subject: [PATCH 078/197] feat: cors --- backend/build.gradle | 1 + .../user/config/WebConfiguration.java | 2 +- .../user/model/entity/PasswordUtils.java | 15 +++++++++++ .../user/model/service/UserServiceImpl.java | 27 +++++++------------ 4 files changed, 26 insertions(+), 19 deletions(-) create mode 100644 backend/src/main/java/com/edufocus/edufocus/user/model/entity/PasswordUtils.java diff --git a/backend/build.gradle b/backend/build.gradle index 71dea75..8fddcd1 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -35,6 +35,7 @@ dependencies { implementation group: 'io.jsonwebtoken', name: 'jjwt-api', version: '0.11.5' implementation group: 'org.springframework.boot', name: 'spring-boot-starter-mail', version: '3.2.5' implementation 'org.springframework.boot:spring-boot-starter-mail' + implementation 'org.mindrot:jbcrypt:0.4' diff --git a/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java b/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java index b95ccb1..3ac277c 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java @@ -26,7 +26,7 @@ public class WebConfiguration implements WebMvcConfigurer { public void addCorsMappings(CorsRegistry registry) { registry .addMapping("/**") - .allowedOrigins("https://i11a701.p.ssafy.io/", "http://localhost:5173", "http://localhost:4173","http://localhost:5080","http://192.168.*:5173") + .allowedOriginPatterns("https://i11a701.p.ssafy.io/", "http://localhost:5173", "http://localhost:4173","http://localhost:5080","http://192.168.*.*:5173") .allowedMethods(HttpMethod.GET.name(), HttpMethod.POST.name(), HttpMethod.PUT.name(), HttpMethod.DELETE.name(), HttpMethod.HEAD.name(), HttpMethod.OPTIONS.name(), HttpMethod.PATCH.name()) diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/PasswordUtils.java b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/PasswordUtils.java new file mode 100644 index 0000000..aa61d1f --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/PasswordUtils.java @@ -0,0 +1,15 @@ +package com.edufocus.edufocus.user.model.entity; +import org.mindrot.jbcrypt.BCrypt; + +public class PasswordUtils { + + // Hash a password + public static String hashPassword(String plainPassword) { + return BCrypt.hashpw(plainPassword, BCrypt.gensalt()); + } + + // Verify a password + public static boolean checkPassword(String plainPassword, String hashedPassword) { + return BCrypt.checkpw(plainPassword, hashedPassword); + } +} \ No newline at end of file diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java index dd8667a..019c1d2 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java @@ -29,6 +29,7 @@ public class UserServiceImpl implements UserService { public void join(User user) { System.out.println(user.getRole().getClass()); + user.setPassword(PasswordUtils.hashPassword(user.getPassword())); userRepository.save(user); } @@ -37,26 +38,15 @@ public class UserServiceImpl implements UserService { public User login(User user) throws SQLException { Optional findUser = userRepository.findByUserId(user.getUserId()); - if (findUser.isEmpty()) { - throw new UserException("없는 유저"); - + throw new UserException("User does not exist"); } - - if (findUser.isPresent()) { - - User find = findUser.get(); - if (find.getPassword().equals(user.getPassword())) { - return find; - } else { - throw new UserException("비밀번호 틀림"); - - } + User find = findUser.get(); + if (PasswordUtils.checkPassword(user.getPassword(), find.getPassword())) { + return find; } else { - throw new UserException("없는 유저"); - - + throw new UserException("Incorrect password"); } } @@ -158,7 +148,7 @@ public class UserServiceImpl implements UserService { throw new Exception("User not found"); } - if (!user.getPassword().equals(passwordDto.getCurrentPassword())) { + if (!PasswordUtils.checkPassword(passwordDto.getCurrentPassword(), user.getPassword())) { throw new Exception("Current password is incorrect"); } else { if (!passwordDto.getNewPassword().equals(passwordDto.getNewPasswordCheck())) { @@ -166,7 +156,8 @@ public class UserServiceImpl implements UserService { } } - user.setPassword(passwordDto.getNewPassword()); + // Hash the new password before saving + user.setPassword(PasswordUtils.hashPassword(passwordDto.getNewPassword())); userRepository.save(user); } public String getTempPassword() { From a117b8ef869c6dd1aac3cfa8a7c2937fc117deb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Wed, 31 Jul 2024 15:28:00 +0900 Subject: [PATCH 079/197] =?UTF-8?q?feat:=20=EB=B9=84=EB=B0=80=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=95=94=ED=98=B8=ED=99=94=20,=20=ED=9A=8C?= =?UTF-8?q?=EC=9B=90=EC=A0=95=EB=B3=B4=20=EB=B3=80=EA=B2=BD=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/controller/UserController.java | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java index 77d1774..97eed14 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java @@ -48,12 +48,14 @@ public class UserController { } - @PutMapping("/updateinfo/{id}") + @PutMapping("/updateinfo") public ResponseEntity updateUserInfo( - @PathVariable("id") Long id, - @RequestBody InfoDto infoDto) { + + @RequestBody InfoDto infoDto, HttpServletRequest request) { try { - userService.changeuInfo(infoDto, id); + String token = request.getHeader("Authorization"); + Long userId = Long.parseLong(jwtUtil.getUserId(token)); + userService.changeuInfo(infoDto, userId); return ResponseEntity.ok("User info updated successfully"); } catch (Exception e) { return ResponseEntity.badRequest().body(e.getMessage()); @@ -61,12 +63,15 @@ public class UserController { } // 비밀번호 변경 - @PutMapping("/updatepassword/{id}") + @PutMapping("/updatepassword") public ResponseEntity updatePassword( - @PathVariable("id") Long id, - @RequestBody PasswordDto passwordDto) { + + @RequestBody PasswordDto passwordDto, HttpServletRequest request) { try { - userService.changePassword(passwordDto, id); + String token = request.getHeader("Authorization"); + Long userId = Long.parseLong(jwtUtil.getUserId(token)); + + userService.changePassword(passwordDto, userId); return ResponseEntity.ok("Password changed successfully"); } catch (Exception e) { return ResponseEntity.badRequest().body(e.getMessage()); From a8df7b39ad6ddc5cca74d951ca4c69cce0c2c5ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Wed, 31 Jul 2024 16:04:27 +0900 Subject: [PATCH 080/197] feat: video --- .../edufocus/video/controller/Controller.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java index 4c470ed..99a9494 100644 --- a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java +++ b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java @@ -1,6 +1,7 @@ package com.edufocus.edufocus.video.controller; import java.util.Map; +import java.util.Random; import com.edufocus.edufocus.lecture.entity.Lecture; import com.edufocus.edufocus.lecture.entity.LectureDetailResponse; @@ -95,8 +96,13 @@ public class Controller { Lecture lecture= lectureRepository.findById(id).orElse(null); + Random random = new Random(); + int randomNumber = 100 + random.nextInt(9000); + + String randStr = String.valueOf(randomNumber); + if(findUser.getRole()==UserRole.ADMIN ){//&& lecture.isOnline() ) { @@ -107,8 +113,8 @@ public class Controller { AccessToken token = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); - token.setName(participantName); - token.setIdentity(participantName); + token.setName(participantName+randStr); + token.setIdentity(participantName+randStr); token.addGrants(new RoomJoin(true), new RoomName(roomName), new RoomCreate(true)); videoSertvice.startOnline(userId, id); @@ -126,8 +132,8 @@ public class Controller { AccessToken token = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); - token.setName(participantName); - token.setIdentity(participantName); + token.setName(participantName+randStr); + token.setIdentity(participantName+randStr); token.addGrants(new RoomJoin(true), new RoomName(roomName)); From 1fc4ec876e841fe2cf4fcb308fb4c1acdfe88740 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Thu, 1 Aug 2024 09:35:52 +0900 Subject: [PATCH 081/197] gitlab runner test --- backend/.gitlab-ci.yml | 23 +++++++++++++++++++ .../user/config/WebConfiguration.java | 2 +- .../edufocus/video/controller/Controller.java | 7 +++--- 3 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 backend/.gitlab-ci.yml diff --git a/backend/.gitlab-ci.yml b/backend/.gitlab-ci.yml new file mode 100644 index 0000000..9761a6c --- /dev/null +++ b/backend/.gitlab-ci.yml @@ -0,0 +1,23 @@ +deploy-to-server: + stage: deploy + only: + - backend + before_script: + - echo 'start deployment' + - whoami + script: + - cd /home/ubuntu/gitlab_runner/ + - git pull origin backend + - cd backend +# - kill $(lsof -t -i:8000) + - ./gradlew build + # - cd /home/ubuntu/s03p12a112/backend/target/ +# - setsid nohup java -jar backend-0.0.1-SNAPSHOT.jar > /dev/null 2>&1 & +# - cd /home/ubuntu/s03p12a112/frontend/ +# - sudo npm install +# - sudo npm run build +# - sudo service nginx restart + after_script: + - echo 'deployment is done' + tags: + - edu \ No newline at end of file diff --git a/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java b/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java index 3ac277c..f9f5977 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java @@ -21,7 +21,7 @@ public class WebConfiguration implements WebMvcConfigurer { this.jwtInterceptor = jwtInterceptor; } - +// @Override public void addCorsMappings(CorsRegistry registry) { registry diff --git a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java index 99a9494..68d1cb1 100644 --- a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java +++ b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java @@ -98,7 +98,7 @@ public class Controller { Random random = new Random(); - + System.out.println(); int randomNumber = 100 + random.nextInt(9000); String randStr = String.valueOf(randomNumber); @@ -110,8 +110,9 @@ public class Controller { String roomName = lecture.getTitle(); String participantName = userService.getUserName(userId); + System.out.println(participantName); - + System.out.println(participantName+randStr); AccessToken token = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); token.setName(participantName+randStr); token.setIdentity(participantName+randStr); @@ -129,7 +130,7 @@ public class Controller { String roomName = lecture.getTitle(); String participantName = userService.getUserName(userId); - + System.out.println(participantName); AccessToken token = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); token.setName(participantName+randStr); From 555df4106cb0f38fd8f6c09deb89dc36fa5bce65 Mon Sep 17 00:00:00 2001 From: yulmam <70622601+yulmam@users.noreply.github.com> Date: Thu, 1 Aug 2024 10:26:47 +0900 Subject: [PATCH 082/197] =?UTF-8?q?feat:=20user=EC=A4=91=EB=B3=B5=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8=20=EC=B2=B4=ED=81=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/controller/UserController.java | 35 +++++++------------ .../user/model/service/UserService.java | 2 +- .../user/model/service/UserServiceImpl.java | 13 ++----- 3 files changed, 17 insertions(+), 33 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java index 97eed14..3ad1737 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java @@ -33,29 +33,22 @@ public class UserController { @PostMapping("/join") public ResponseEntity join(@RequestBody User user) throws Exception { - - - System.out.println("@@@@@"); - log.info("@@@@@@@@@@@@@@@@"); userService.join(user); return ResponseEntity.ok("User registered successfully"); } @PostMapping("/findpassword/{user_id}") public ResponseEntity findpassword(@PathVariable("user_id") Long user_id) throws Exception { - userService.userCheck(user_id); return ResponseEntity.ok("임시 비밀번호가 이메일로 전송되었습니다."); - } @PutMapping("/updateinfo") public ResponseEntity updateUserInfo( - @RequestBody InfoDto infoDto, HttpServletRequest request) { try { String token = request.getHeader("Authorization"); Long userId = Long.parseLong(jwtUtil.getUserId(token)); - userService.changeuInfo(infoDto, userId); + userService.changeUserInfo(infoDto, userId); return ResponseEntity.ok("User info updated successfully"); } catch (Exception e) { return ResponseEntity.badRequest().body(e.getMessage()); @@ -80,45 +73,43 @@ public class UserController { @Operation(summary = "로그인", description = "아이디와 비밀번호를 이용하여 로그인 처리.") @PostMapping("/login") public ResponseEntity> login( - @RequestBody @Parameter(description = "로그인 시 필요한 회원정보(아이디, 비밀번호).", required = true) User user, HttpServletResponse response) { + @RequestBody @Parameter(description = "로그인 시 필요한 회원정보(아이디, 비밀번호).", required = true) User user, HttpServletRequest request, HttpServletResponse response) { + + String token = request.getHeader("Authorization"); + if(jwtUtil.checkToken(token)){ + return new ResponseEntity<>(HttpStatus.FORBIDDEN); + } + Map resultMap = new HashMap<>(); HttpStatus status = HttpStatus.ACCEPTED; - - try { User loginUser = userService.login(user); if (loginUser != null) { - String name = loginUser.getName(); - resultMap.put("name",name); + String accessToken = jwtUtil.createAccessToken(String.valueOf(loginUser.getId())); String refreshToken = jwtUtil.createRefreshToken(String.valueOf(loginUser.getId())); - userService.saveRefreshToken(loginUser.getId(), refreshToken); - - + resultMap.put("name",loginUser.getName()); resultMap.put("role",loginUser.getRole()); resultMap.put("access-token", accessToken); - - Cookie refreshCookie = new Cookie("refresh-token", refreshToken); refreshCookie.setPath("/"); refreshCookie.setHttpOnly(true); - refreshCookie.setSecure(true); // HTTPS에서만 전송되도록 설정 - //r/efreshCookie.setSameSite(Cookie.SameSite.NONE); // Cross-Origin 요청에 대해 모두 전송 + refreshCookie.setSecure(true); // HTTPS에서만 전송되도록 설정 + //refreshCookie.setSameSite(Cookie.SameSite.NONE); // Cross-Origin 요청에 대해 모두 전송 //refreshCookie.setSameSite("None"); // Cross-Origin 요청에 대해 모두 전송 String cookieHeader = String.format("refresh-token=%s; Path=/; HttpOnly; Secure; SameSite=None", refreshToken); response.setHeader("Set-Cookie", cookieHeader); - // refreshCookie.setSameSite("None"); // Cross-Origin 요청에 대해 모두 전송 + // refreshCookie.setSameSite("None"); // Cross-Origin 요청에 대해 모두 전송 response.addCookie(refreshCookie); - status = HttpStatus.CREATED; } else { resultMap.put("message", "아이디 또는 패스워드를 확인해 주세요."); diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java index 5e1ba53..e8ea468 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java @@ -14,7 +14,7 @@ public interface UserService { void sendEamail(User user) throws Exception; void userCheck(Long id) throws Exception; String getUserName(Long id) throws Exception; - void changeuInfo(InfoDto infoDto,Long id) throws Exception; + void changeUserInfo(InfoDto infoDto,Long id) throws Exception; void changePassword(PasswordDto passwordDto,Long id) throws Exception; } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java index 019c1d2..6c3feec 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java @@ -119,23 +119,16 @@ public class UserServiceImpl implements UserService { @Override - public void changeuInfo(InfoDto infoDto, Long id) throws Exception { + public void changeUserInfo(InfoDto infoDto, Long id) throws Exception { - User user = userRepository.findById(id).orElse(null); - - if (user == null) { - throw new Exception("User not found"); - } + User user = userRepository.findById(id).orElseThrow(IllegalArgumentException::new); if (infoDto.getName() != null) - { user.setName(infoDto.getName()); - } if(infoDto.getEmail()!=null) - { user.setEmail(infoDto.getEmail()); - } + userRepository.save(user); } From 9f1ccf8b2e4fffe050bb33ac61f08ea87216484e Mon Sep 17 00:00:00 2001 From: kgc91747 Date: Thu, 1 Aug 2024 10:29:22 +0900 Subject: [PATCH 083/197] =?UTF-8?q?feat:=20Lecture,=20Quiz=20=EC=9D=B4?= =?UTF-8?q?=EB=AF=B8=EC=A7=80=20=EC=A0=80=EC=9E=A5=20=EC=9C=84=EC=B9=98=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/config/PropertiesConfig.java | 4 +- .../properties/ImagePathProperties.java | 12 ++++++ .../lecture/service/LectureServiceImpl.java | 42 ++++++++++--------- .../quiz/service/QuizServiceImpl.java | 14 ++++--- .../src/main/resources/application.properties | 5 ++- 5 files changed, 50 insertions(+), 27 deletions(-) create mode 100644 backend/src/main/java/com/edufocus/edufocus/global/properties/ImagePathProperties.java diff --git a/backend/src/main/java/com/edufocus/edufocus/global/config/PropertiesConfig.java b/backend/src/main/java/com/edufocus/edufocus/global/config/PropertiesConfig.java index 4c3323e..eb01984 100644 --- a/backend/src/main/java/com/edufocus/edufocus/global/config/PropertiesConfig.java +++ b/backend/src/main/java/com/edufocus/edufocus/global/config/PropertiesConfig.java @@ -1,13 +1,15 @@ package com.edufocus.edufocus.global.config; +import com.edufocus.edufocus.global.properties.ImagePathProperties; import com.edufocus.edufocus.global.properties.RabbitMQProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Configuration; @Configuration @EnableConfigurationProperties({ - RabbitMQProperties.class + RabbitMQProperties.class, + ImagePathProperties.class }) public class PropertiesConfig { } diff --git a/backend/src/main/java/com/edufocus/edufocus/global/properties/ImagePathProperties.java b/backend/src/main/java/com/edufocus/edufocus/global/properties/ImagePathProperties.java new file mode 100644 index 0000000..77d3672 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/global/properties/ImagePathProperties.java @@ -0,0 +1,12 @@ +package com.edufocus.edufocus.global.properties; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.boot.context.properties.ConfigurationProperties; + +@Getter +@RequiredArgsConstructor +@ConfigurationProperties(prefix = "image") +public class ImagePathProperties { + private final String path; +} diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java index d3d15e9..4c1bc84 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java @@ -1,5 +1,6 @@ package com.edufocus.edufocus.lecture.service; +import com.edufocus.edufocus.global.properties.ImagePathProperties; import com.edufocus.edufocus.lecture.entity.*; import com.edufocus.edufocus.lecture.repository.LectureRepository; import com.edufocus.edufocus.registration.entity.Registration; @@ -9,23 +10,22 @@ import com.edufocus.edufocus.user.model.entity.User; import com.edufocus.edufocus.user.model.entity.UserRole; import com.edufocus.edufocus.user.model.repository.UserRepository; import jakarta.transaction.Transactional; -import lombok.Builder; import lombok.RequiredArgsConstructor; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.IOException; import java.util.*; +import java.util.List; -@Builder @Service @Transactional @RequiredArgsConstructor public class LectureServiceImpl implements LectureService { + private final ImagePathProperties imagePathProperties; + private final LectureRepository lectureRepository; private final UserRepository userRepository; @@ -34,9 +34,9 @@ public class LectureServiceImpl implements LectureService { @Override public void createLecture(long userId, LectureCreateRequest lectureCreateRequest, MultipartFile image) throws IOException { - User user = userRepository.findById(userId).get(); + User user = userRepository.findById(userId).orElse(null); - Lecture lecture = new Lecture().builder() + Lecture lecture = Lecture.builder() .user(user) .title(lectureCreateRequest.getTitle()) .description(lectureCreateRequest.getDescription()) @@ -49,13 +49,14 @@ public class LectureServiceImpl implements LectureService { if (image != null && !image.isEmpty()) { String uid = UUID.randomUUID().toString(); - String currentPath = "backend/src/main/resources/images/"; - File checkPathFile = new File(currentPath); + String imagePath = imagePathProperties.getPath(); + + File checkPathFile = new File(imagePath); if (!checkPathFile.exists()) { checkPathFile.mkdirs(); } - File savingImage = new File(currentPath + uid + "_" + image.getOriginalFilename()); + File savingImage = new File(imagePath + "/" + uid + "_" + image.getOriginalFilename()); image.transferTo(savingImage.toPath()); String savePath = savingImage.toPath().toString(); @@ -67,12 +68,14 @@ public class LectureServiceImpl implements LectureService { @Override public boolean updateLecture(long userId, long lectureId, LectureCreateRequest lectureCreateRequest) { - Lecture lecture = lectureRepository.findById(lectureId).get(); + Optional findLecture = lectureRepository.findById(lectureId); - if (lecture.getUser().getId() != userId) { + if (findLecture.isEmpty() || findLecture.get().getUser().getId() != userId) { return false; } + Lecture lecture = findLecture.get(); + if (lectureCreateRequest.getTitle() != null) { lecture.setTitle(lectureCreateRequest.getTitle()); } @@ -98,14 +101,14 @@ public class LectureServiceImpl implements LectureService { @Override public boolean deleteLecture(long userId, long lectureId) { - Optional lecture = lectureRepository.findById(lectureId); + Optional findLecture = lectureRepository.findById(lectureId); - if (lecture.isEmpty()) { + if (findLecture.isEmpty()) { return false; } - lecture = Optional.of(lecture.get()); + Lecture lecture = findLecture.get(); - if (lecture.get().getUser().getId() != userId) { + if (lecture.getUser().getId() != userId) { return false; } @@ -162,7 +165,7 @@ public class LectureServiceImpl implements LectureService { } } - LectureDetailResponse lectureDetailResponse = new LectureDetailResponse().builder() + return LectureDetailResponse.builder() .id(lecture.get().getId()) .title(lecture.get().getTitle()) .description(lecture.get().getDescription()) @@ -176,7 +179,6 @@ public class LectureServiceImpl implements LectureService { .status(userStatus) .build(); - return lectureDetailResponse; } public List findMyLecture(long userId) { @@ -187,7 +189,7 @@ public class LectureServiceImpl implements LectureService { if (user.getRole() == UserRole.ADMIN) { List lectureList = lectureRepository.findLecturesByUserId(userId); for (Lecture lecture : lectureList) { - LectureSearchResponse lectureSearchResponse = new LectureSearchResponse().builder() + LectureSearchResponse lectureSearchResponse = LectureSearchResponse.builder() .id(lecture.getId()) .title(lecture.getTitle()) .image(lecture.getImage()).build(); @@ -200,7 +202,7 @@ public class LectureServiceImpl implements LectureService { for (Registration registration : registrationList) { Lecture lecture = registration.getLecture(); - LectureSearchResponse lectureSearchResponse = new LectureSearchResponse().builder() + LectureSearchResponse lectureSearchResponse = LectureSearchResponse.builder() .id(lecture.getId()) .title(lecture.getTitle()) .image(lecture.getImage()).build(); @@ -241,7 +243,7 @@ public class LectureServiceImpl implements LectureService { @Override public boolean getState(Long lectureId) { - Lecture lecture= lectureRepository.findById(lectureId).orElse(null); + Lecture lecture = lectureRepository.findById(lectureId).orElse(null); return lecture.isOnline(); } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizServiceImpl.java index b25adfb..fbb42e5 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizServiceImpl.java @@ -1,5 +1,6 @@ package com.edufocus.edufocus.quiz.service; +import com.edufocus.edufocus.global.properties.ImagePathProperties; import com.edufocus.edufocus.quiz.entity.*; import com.edufocus.edufocus.quiz.repository.QuizRepository; import jakarta.transaction.Transactional; @@ -19,11 +20,13 @@ import java.util.UUID; @RequiredArgsConstructor public class QuizServiceImpl implements QuizService { + private final ImagePathProperties imagePathProperties; + private final QuizRepository quizRepository; @Override public void createQuiz(QuizSet quizSet, QuizCreateRequest quizCreateRequest, MultipartFile quizImage) throws IOException { - Quiz quiz = new Quiz().builder() + Quiz quiz = Quiz.builder() .quizSet(quizSet) .question(quizCreateRequest.getQuestion()) .answer(quizCreateRequest.getAnswer()) @@ -32,7 +35,7 @@ public class QuizServiceImpl implements QuizService { List choices = new ArrayList<>(); for (ChoiceCreateRequest choiceCreateRequest : quizCreateRequest.getChoices()) { - Choice choice = new Choice().builder() + Choice choice = Choice.builder() .quiz(quiz) .num(choiceCreateRequest.getNum()) .content(choiceCreateRequest.getContent()) @@ -45,13 +48,14 @@ public class QuizServiceImpl implements QuizService { if (quizImage != null && !quizImage.isEmpty()) { String uid = UUID.randomUUID().toString(); - String currentPath = "backend/src/main/resources/images/quizzes/"; - File checkPathFile = new File(currentPath); + String imagePath = imagePathProperties.getPath(); + + File checkPathFile = new File(imagePath); if (!checkPathFile.exists()) { checkPathFile.mkdirs(); } - File savingImage = new File(currentPath + uid + "_" + quizImage.getOriginalFilename()); + File savingImage = new File(imagePath + "/" + uid + "_" + quizImage.getOriginalFilename()); quizImage.transferTo(savingImage.toPath()); String savePath = savingImage.toPath().toString(); diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 62d7538..9cc111a 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -47,4 +47,7 @@ spring.mail.properties.mail.smtp.starttls.enable=true spring.rabbitmq.host=${RABBITMQ_HOST} spring.rabbitmq.port=${RABBITMQ_PORT} spring.rabbitmq.username=${RABBITMQ_USERNAME} -spring.rabbitmq.password=${RABBITMQ_PASSWORD} \ No newline at end of file +spring.rabbitmq.password=${RABBITMQ_PASSWORD} + + +image.path=${IMAGE_PATH} \ No newline at end of file From 430543bf1801deb4a7d3fbe7cdbbba46350b5f6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Thu, 1 Aug 2024 10:45:07 +0900 Subject: [PATCH 084/197] gitlab jenkins test --- .../model/service/UserServiceImplTest.java | 312 +++++++++--------- 1 file changed, 156 insertions(+), 156 deletions(-) diff --git a/backend/src/test/java/com/edufocus/edufocus/user/model/service/UserServiceImplTest.java b/backend/src/test/java/com/edufocus/edufocus/user/model/service/UserServiceImplTest.java index 5cf213f..2986703 100644 --- a/backend/src/test/java/com/edufocus/edufocus/user/model/service/UserServiceImplTest.java +++ b/backend/src/test/java/com/edufocus/edufocus/user/model/service/UserServiceImplTest.java @@ -1,185 +1,185 @@ -package com.edufocus.edufocus.user.model.service; - -import com.edufocus.edufocus.user.model.entity.PasswordDto; -import com.edufocus.edufocus.user.model.entity.User; -import com.edufocus.edufocus.user.model.entity.UserRole; -import com.edufocus.edufocus.user.model.exception.UserException; -import com.edufocus.edufocus.user.model.repository.UserRepository; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.springframework.mail.javamail.JavaMailSender; - -import java.util.Optional; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; - -public class UserServiceImplTest { - - @InjectMocks - private UserServiceImpl userService; - - @Mock - private UserRepository userRepository; - - - - @BeforeEach - public void setup() { - MockitoAnnotations.openMocks(this); - } - - @Test - public void testJoin() { - User user = new User(); - user.setUserId("testUser"); - user.setPassword("password"); - user.setEmail("test@example.com"); - user.setRole(UserRole.STUDENT); - user.setId(1L); - - - userService.join(user); - - verify(userRepository, times(1)).save(user); - } - - @Test - public void testLogin_Success() throws Exception { - User user = new User(); - user.setUserId("testUser"); - user.setPassword("password"); - - when(userRepository.findByUserId("testUser")).thenReturn(Optional.of(user)); - - User loggedInUser = userService.login(user); - - assertNotNull(loggedInUser); - assertEquals("testUser", loggedInUser.getUserId()); - } - - @Test - public void testLogin_UserNotFound() { - User user = new User(); - user.setUserId("testUser"); - user.setPassword("password"); - - when(userRepository.findByUserId("testUser")).thenReturn(Optional.empty()); - - assertThrows(UserException.class, () -> { - userService.login(user); - }); - } - - @Test - public void testLogin_InvalidPassword() { - User user = new User(); - user.setUserId("testUser"); - user.setPassword("password"); - - User storedUser = new User(); - storedUser.setUserId("testUser"); - storedUser.setPassword("wrongPassword"); - - when(userRepository.findByUserId("testUser")).thenReturn(Optional.of(storedUser)); - - assertThrows(UserException.class, () -> { - userService.login(user); - }); - } - -// @Test -// public void testUserInfo_Success() { -// User user = new User(); -// user.setId(1L); -// user.setName("testUser"); +//package com.edufocus.edufocus.user.model.service; // -// when(userRepository.findById(1L)).thenReturn(Optional.of(user)); +//import com.edufocus.edufocus.user.model.entity.PasswordDto; +//import com.edufocus.edufocus.user.model.entity.User; +//import com.edufocus.edufocus.user.model.entity.UserRole; +//import com.edufocus.edufocus.user.model.exception.UserException; +//import com.edufocus.edufocus.user.model.repository.UserRepository; +//import org.junit.jupiter.api.BeforeEach; +//import org.junit.jupiter.api.Test; +//import org.mockito.InjectMocks; +//import org.mockito.Mock; +//import org.mockito.MockitoAnnotations; +//import org.springframework.mail.javamail.JavaMailSender; // -// User userInfo = userService.userInfo(1L); +//import java.util.Optional; // -// assertNotNull(userInfo); -// assertEquals("testUser", userInfo.getName()); +//import static org.junit.jupiter.api.Assertions.*; +//import static org.mockito.Mockito.*; +// +//public class UserServiceImplTest { +// +// @InjectMocks +// private UserServiceImpl userService; +// +// @Mock +// private UserRepository userRepository; +// +// +// +// @BeforeEach +// public void setup() { +// MockitoAnnotations.openMocks(this); // } // // @Test -// public void testUserInfo_UserNotFound() { -// when(userRepository.findById(1L)).thenReturn(Optional.empty()); -// -// assertThrows(UserException.class, () -> { -// userService.userInfo(1L); -// }); -// } -// -// @Test -// public void testChangePassword_Success() throws Exception { +// public void testJoin() { // User user = new User(); +// user.setUserId("testUser"); +// user.setPassword("password"); +// user.setEmail("test@example.com"); +// user.setRole(UserRole.STUDENT); // user.setId(1L); -// user.setPassword("currentPassword"); // -// when(userRepository.findById(1L)).thenReturn(Optional.of(user)); // -// PasswordDto passwordDto = new PasswordDto(); -// passwordDto.setCurrentPassword("currentPassword"); -// passwordDto.setNewPassword("newPassword"); -// passwordDto.setNewPasswordCheck("newPassword"); -// -// userService.changePassword(passwordDto, 1L); +// userService.join(user); // // verify(userRepository, times(1)).save(user); -// assertEquals("newPassword", user.getPassword()); // } // // @Test -// public void testChangePassword_UserNotFound() { -// when(userRepository.findById(1L)).thenReturn(Optional.empty()); -// -// PasswordDto passwordDto = new PasswordDto(); -// passwordDto.setCurrentPassword("currentPassword"); -// passwordDto.setNewPassword("newPassword"); -// passwordDto.setNewPasswordCheck("newPassword"); -// -// assertThrows(Exception.class, () -> { -// userService.changePassword(passwordDto, 1L); -// }); -// } -// -// @Test -// public void testChangePassword_InvalidCurrentPassword() { +// public void testLogin_Success() throws Exception { // User user = new User(); -// user.setId(1L); -// user.setPassword("currentPassword"); +// user.setUserId("testUser"); +// user.setPassword("password"); // -// when(userRepository.findById(1L)).thenReturn(Optional.of(user)); +// when(userRepository.findByUserId("testUser")).thenReturn(Optional.of(user)); // -// PasswordDto passwordDto = new PasswordDto(); -// passwordDto.setCurrentPassword("wrongPassword"); -// passwordDto.setNewPassword("newPassword"); -// passwordDto.setNewPasswordCheck("newPassword"); +// User loggedInUser = userService.login(user); // -// assertThrows(Exception.class, () -> { -// userService.changePassword(passwordDto, 1L); +// assertNotNull(loggedInUser); +// assertEquals("testUser", loggedInUser.getUserId()); +// } +// +// @Test +// public void testLogin_UserNotFound() { +// User user = new User(); +// user.setUserId("testUser"); +// user.setPassword("password"); +// +// when(userRepository.findByUserId("testUser")).thenReturn(Optional.empty()); +// +// assertThrows(UserException.class, () -> { +// userService.login(user); // }); // } // // @Test -// public void testChangePassword_NewPasswordMismatch() { +// public void testLogin_InvalidPassword() { // User user = new User(); -// user.setId(1L); -// user.setPassword("currentPassword"); +// user.setUserId("testUser"); +// user.setPassword("password"); // -// when(userRepository.findById(1L)).thenReturn(Optional.of(user)); +// User storedUser = new User(); +// storedUser.setUserId("testUser"); +// storedUser.setPassword("wrongPassword"); // -// PasswordDto passwordDto = new PasswordDto(); -// passwordDto.setCurrentPassword("currentPassword"); -// passwordDto.setNewPassword("newPassword"); -// passwordDto.setNewPasswordCheck("mismatchNewPassword"); +// when(userRepository.findByUserId("testUser")).thenReturn(Optional.of(storedUser)); // -// assertThrows(Exception.class, () -> { -// userService.changePassword(passwordDto, 1L); +// assertThrows(UserException.class, () -> { +// userService.login(user); // }); // } -} \ No newline at end of file +// +//// @Test +//// public void testUserInfo_Success() { +//// User user = new User(); +//// user.setId(1L); +//// user.setName("testUser"); +//// +//// when(userRepository.findById(1L)).thenReturn(Optional.of(user)); +//// +//// User userInfo = userService.userInfo(1L); +//// +//// assertNotNull(userInfo); +//// assertEquals("testUser", userInfo.getName()); +//// } +//// +//// @Test +//// public void testUserInfo_UserNotFound() { +//// when(userRepository.findById(1L)).thenReturn(Optional.empty()); +//// +//// assertThrows(UserException.class, () -> { +//// userService.userInfo(1L); +//// }); +//// } +//// +//// @Test +//// public void testChangePassword_Success() throws Exception { +//// User user = new User(); +//// user.setId(1L); +//// user.setPassword("currentPassword"); +//// +//// when(userRepository.findById(1L)).thenReturn(Optional.of(user)); +//// +//// PasswordDto passwordDto = new PasswordDto(); +//// passwordDto.setCurrentPassword("currentPassword"); +//// passwordDto.setNewPassword("newPassword"); +//// passwordDto.setNewPasswordCheck("newPassword"); +//// +//// userService.changePassword(passwordDto, 1L); +//// +//// verify(userRepository, times(1)).save(user); +//// assertEquals("newPassword", user.getPassword()); +//// } +//// +//// @Test +//// public void testChangePassword_UserNotFound() { +//// when(userRepository.findById(1L)).thenReturn(Optional.empty()); +//// +//// PasswordDto passwordDto = new PasswordDto(); +//// passwordDto.setCurrentPassword("currentPassword"); +//// passwordDto.setNewPassword("newPassword"); +//// passwordDto.setNewPasswordCheck("newPassword"); +//// +//// assertThrows(Exception.class, () -> { +//// userService.changePassword(passwordDto, 1L); +//// }); +//// } +//// +//// @Test +//// public void testChangePassword_InvalidCurrentPassword() { +//// User user = new User(); +//// user.setId(1L); +//// user.setPassword("currentPassword"); +//// +//// when(userRepository.findById(1L)).thenReturn(Optional.of(user)); +//// +//// PasswordDto passwordDto = new PasswordDto(); +//// passwordDto.setCurrentPassword("wrongPassword"); +//// passwordDto.setNewPassword("newPassword"); +//// passwordDto.setNewPasswordCheck("newPassword"); +//// +//// assertThrows(Exception.class, () -> { +//// userService.changePassword(passwordDto, 1L); +//// }); +//// } +//// +//// @Test +//// public void testChangePassword_NewPasswordMismatch() { +//// User user = new User(); +//// user.setId(1L); +//// user.setPassword("currentPassword"); +//// +//// when(userRepository.findById(1L)).thenReturn(Optional.of(user)); +//// +//// PasswordDto passwordDto = new PasswordDto(); +//// passwordDto.setCurrentPassword("currentPassword"); +//// passwordDto.setNewPassword("newPassword"); +//// passwordDto.setNewPasswordCheck("mismatchNewPassword"); +//// +//// assertThrows(Exception.class, () -> { +//// userService.changePassword(passwordDto, 1L); +//// }); +//// } +//} \ No newline at end of file From 6c36715a257ee6d55c0bd29833589bfd78ef2c6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Thu, 1 Aug 2024 13:18:42 +0900 Subject: [PATCH 085/197] =?UTF-8?q?feat:=20=EC=88=98=EA=B0=95=EC=A4=91=20?= =?UTF-8?q?=ED=99=95=EC=9D=B8=20=EA=B8=B0=EB=8A=A5=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/registration/service/RegistrationService.java | 2 +- .../edufocus/registration/service/RegistrationServiceImpl.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationService.java b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationService.java index 3c7d477..b01c410 100644 --- a/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationService.java +++ b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationService.java @@ -18,5 +18,5 @@ public interface RegistrationService { List searchRegistrations(Long LectureId); - RegistrationStatus isOnline(Long userId, Long lectureId); + RegistrationStatus getStatus(Long userId, Long lectureId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java index e36c9a1..9f89fdb 100644 --- a/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java @@ -88,7 +88,7 @@ public class RegistrationServiceImpl implements RegistrationService { } @Override - public RegistrationStatus isOnline(Long userId, Long lectureId) { + public RegistrationStatus getStatus(Long userId, Long lectureId) { Registration registration = registrationRepository.findByUserIdAndLectureId(userId, lectureId); return registration.getStatus(); From 3a7204cfba812f1f49bbfe67ae6be21e6c78dea9 Mon Sep 17 00:00:00 2001 From: kgc91747 Date: Thu, 1 Aug 2024 15:02:44 +0900 Subject: [PATCH 086/197] =?UTF-8?q?refactor:=20Quiz=20=EB=A6=AC=ED=8C=A9?= =?UTF-8?q?=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lecture/service/LectureServiceImpl.java | 2 +- .../quiz/controller/QuizController.java | 12 ++--- .../edufocus/edufocus/quiz/entity/Choice.java | 2 +- .../quiz/entity/MyQuizSetResponse.java | 2 +- .../edufocus/edufocus/quiz/entity/Quiz.java | 2 +- .../edufocus/quiz/entity/QuizSet.java | 10 +++-- .../quiz/repository/QuizSetRepository.java | 2 +- .../edufocus/quiz/service/QuizSetService.java | 10 ++--- .../quiz/service/QuizSetServiceImpl.java | 45 +++++++++---------- .../report/service/ReportServiceImpl.java | 2 +- 10 files changed, 41 insertions(+), 48 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java index 4c1bc84..7c202eb 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java @@ -46,7 +46,7 @@ public class LectureServiceImpl implements LectureService { .time(lectureCreateRequest.getTime()) .build(); - if (image != null && !image.isEmpty()) { + if (image != null) { String uid = UUID.randomUUID().toString(); String imagePath = imagePathProperties.getPath(); diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java b/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java index cf0ecc8..3a27228 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java @@ -30,7 +30,7 @@ public class QuizController { @PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public ResponseEntity createQuizSet(@RequestHeader("Authorization") String accessToken, @RequestPart QuizSetCreateRequest quizSetCreateRequest , @RequestPart(value = "images", required = false) List images) throws IOException { - Long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); + long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); QuizSet quizSet = quizSetService.createQuizSet(userId, quizSetCreateRequest.getTitle()); @@ -46,16 +46,12 @@ public class QuizController { public ResponseEntity getQuizzes(@PathVariable Long quizsetId) { QuizSetResponse quizSet = quizSetService.findQuizSetResponse(quizsetId); - if (quizSet == null) { - return new ResponseEntity<>(HttpStatus.NOT_FOUND); - } - return new ResponseEntity<>(quizSet, HttpStatus.OK); } @DeleteMapping("/{quizsetId}") - public ResponseEntity deleteQuizSet(@RequestHeader("Authorization") String accessToken, @PathVariable Long quizsetId) { - Long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); + public ResponseEntity deleteQuizSet(@RequestHeader("Authorization") String accessToken, @PathVariable long quizsetId) { + long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); if (!quizSetService.deleteQuizSet(userId, quizsetId)) { return new ResponseEntity<>(HttpStatus.NOT_FOUND); @@ -66,7 +62,7 @@ public class QuizController { @GetMapping public ResponseEntity getQuizSets(@RequestHeader("Authorization") String accessToken) { - Long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); + long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); return new ResponseEntity<>(quizSetService.findMyQuizSetResponses(userId), HttpStatus.OK); } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Choice.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Choice.java index d31f8a1..8078db1 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Choice.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Choice.java @@ -14,7 +14,7 @@ public class Choice { @Id @GeneratedValue - private Long id; + private long id; @ManyToOne @JoinColumn(name = "QuizId") diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/MyQuizSetResponse.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/MyQuizSetResponse.java index da8947f..9bf177c 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/MyQuizSetResponse.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/MyQuizSetResponse.java @@ -8,7 +8,7 @@ import lombok.*; @AllArgsConstructor public class MyQuizSetResponse { - private Long quizSetId; + private long quizSetId; private String title; } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Quiz.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Quiz.java index 7eed889..d0737b6 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Quiz.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Quiz.java @@ -17,7 +17,7 @@ public class Quiz { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; + private long id; @ManyToOne @JoinColumn(name = "quizset_id") diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSet.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSet.java index 8357279..816638c 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSet.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSet.java @@ -4,8 +4,7 @@ import com.edufocus.edufocus.user.model.entity.User; import com.fasterxml.jackson.annotation.JsonBackReference; import com.fasterxml.jackson.annotation.JsonManagedReference; import jakarta.persistence.*; -import lombok.Getter; -import lombok.Setter; +import lombok.*; import java.util.ArrayList; import java.util.List; @@ -13,11 +12,14 @@ import java.util.List; @Entity @Getter @Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor public class QuizSet { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; + private long id; @ManyToOne @JoinColumn(name = "user_id") @@ -29,7 +31,7 @@ public class QuizSet { @OneToMany(mappedBy = "quizSet", orphanRemoval = true) @JsonManagedReference - private List quizzes = new ArrayList(); + private List quizzes; public void addQuiz(Quiz quiz) { this.quizzes.add(quiz); diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/repository/QuizSetRepository.java b/backend/src/main/java/com/edufocus/edufocus/quiz/repository/QuizSetRepository.java index 89bc7bc..c3282c7 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/repository/QuizSetRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/repository/QuizSetRepository.java @@ -7,5 +7,5 @@ import java.util.List; public interface QuizSetRepository extends JpaRepository { - List findQuizSetsByUserId(Long userId); + List findQuizSetsByUserId(long userId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetService.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetService.java index 1f8e4d7..4b25ebc 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetService.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetService.java @@ -10,15 +10,15 @@ import java.util.List; @Service public interface QuizSetService { - QuizSet createQuizSet(Long userId, String title); + QuizSet createQuizSet(long userId, String title); void updateQuizSet(QuizSet quizSet); - boolean deleteQuizSet(Long userId, Long quizSetId); + boolean deleteQuizSet(long userId, long quizSetId); - QuizSet findQuizSet(Long quizSetId); + QuizSet findQuizSet(long quizSetId); - QuizSetResponse findQuizSetResponse(Long quizSetId); + QuizSetResponse findQuizSetResponse(long quizSetId); - List findMyQuizSetResponses(Long userId); + List findMyQuizSetResponses(long userId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java index c65a071..c5c68c8 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java @@ -10,7 +10,7 @@ import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; -import java.util.Optional; +import java.util.NoSuchElementException; @Service @Transactional @@ -22,12 +22,13 @@ public class QuizSetServiceImpl implements QuizSetService { private final UserRepository userRepository; @Override - public QuizSet createQuizSet(Long userId, String title) { - QuizSet quizSet = new QuizSet(); + public QuizSet createQuizSet(long userId, String title) { + User user = userRepository.findById(userId).orElseThrow(NoSuchElementException::new); - User user = userRepository.findById(userId).get(); - quizSet.setUser(user); - quizSet.setTitle(title); + QuizSet quizSet = QuizSet.builder() + .user(user) + .title(title) + .build(); return quizSetRepository.save(quizSet); } @@ -38,10 +39,10 @@ public class QuizSetServiceImpl implements QuizSetService { } @Override - public boolean deleteQuizSet(Long userId, Long quizSetId) { - Optional quizSet = quizSetRepository.findById(quizSetId); + public boolean deleteQuizSet(long userId, long quizSetId) { + QuizSet quizSet = quizSetRepository.findById(quizSetId).orElseThrow(NoSuchElementException::new); - if (quizSet.isEmpty() || userId != quizSet.get().getUser().getId()) { + if (userId != quizSet.getUser().getId()) { return false; } @@ -50,22 +51,17 @@ public class QuizSetServiceImpl implements QuizSetService { } @Override - public QuizSet findQuizSet(Long quizSetId) { - return quizSetRepository.findById(quizSetId).get(); + public QuizSet findQuizSet(long quizSetId) { + return quizSetRepository.findById(quizSetId).orElseThrow(NoSuchElementException::new); } @Override - public QuizSetResponse findQuizSetResponse(Long quizSetId) { - Optional quizSet = quizSetRepository.findById(quizSetId); - - if (quizSet.isEmpty()) { - return null; - } - + public QuizSetResponse findQuizSetResponse(long quizSetId) { + QuizSet quizSet = quizSetRepository.findById(quizSetId).orElseThrow(NoSuchElementException::new); List quizResponses = new ArrayList<>(); - for (Quiz quiz : quizSet.get().getQuizzes()) { - QuizResponse quizResponse = new QuizResponse().builder() + for (Quiz quiz : quizSet.getQuizzes()) { + QuizResponse quizResponse = QuizResponse.builder() .question(quiz.getQuestion()) .image(quiz.getImage()) .choices(quiz.getChoices()) @@ -73,21 +69,20 @@ public class QuizSetServiceImpl implements QuizSetService { quizResponses.add(quizResponse); } - QuizSetResponse quizSetResponse = new QuizSetResponse().builder() - .title(quizSet.get().getTitle()) + return QuizSetResponse.builder() + .title(quizSet.getTitle()) .quizzes(quizResponses) .build(); - return quizSetResponse; } @Override - public List findMyQuizSetResponses(Long userId) { + public List findMyQuizSetResponses(long userId) { List quizSetList = quizSetRepository.findQuizSetsByUserId(userId); List myQuizSetResponses = new ArrayList<>(); for (QuizSet quizSet : quizSetList) { - MyQuizSetResponse myQuizSetResponse = new MyQuizSetResponse().builder() + MyQuizSetResponse myQuizSetResponse = MyQuizSetResponse.builder() .quizSetId(quizSet.getId()) .title(quizSet.getTitle()) .build(); diff --git a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java index dd22a44..1d6449d 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java @@ -55,7 +55,7 @@ public class ReportServiceImpl implements ReportService { for (Quiz quiz : quizList) { for (AnswerInput answerInput : answerInputList) { - if (quiz.getId().equals(answerInput.getAnswerinputID())) { + if (quiz.getId() == answerInput.getAnswerinputID()) { if(quiz.getAnswer().equals(answerInput.getAnswer())) { correctCount++; From 15399f1e6bc0e5436fdf07dda96ebac30a1a1628 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Thu, 1 Aug 2024 15:14:00 +0900 Subject: [PATCH 087/197] =?UTF-8?q?feat:=20user=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/controller/UserController.java | 30 ++++++++----------- .../edufocus/edufocus/user/util/JWTUtil.java | 2 +- .../edufocus/video/controller/Controller.java | 3 -- 3 files changed, 13 insertions(+), 22 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java index 3ad1737..3a06abc 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java @@ -135,7 +135,6 @@ public class UserController { if (jwtUtil.checkToken(request.getHeader("Authorization"))) { log.info("사용 가능한 토큰!!!"); try { -// 로그인 사용자 정보. User member = userService.userInfo(userId); resultMap.put("userInfo", member); status = HttpStatus.OK; @@ -153,12 +152,16 @@ public class UserController { return new ResponseEntity>(resultMap, status); } - @GetMapping("/logout/{userId}") + @GetMapping("/logout") - public ResponseEntity removeToken(@PathVariable ("userId") @Parameter(description = "로그아웃 할 회원의 아이디.", required = true) Long userId) { + public ResponseEntity removeToken(HttpServletRequest request) { Map resultMap = new HashMap<>(); HttpStatus status = HttpStatus.ACCEPTED; try { + + String token = request.getHeader("Authorization"); + Long userId = Long.parseLong(jwtUtil.getUserId(token)); + userService.deleteRefreshToken(userId); status = HttpStatus.OK; } catch (Exception e) { @@ -174,14 +177,10 @@ public class UserController { public ResponseEntity refreshToken(HttpServletRequest request,HttpServletResponse response) throws Exception { - // System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@"); - // System.out.println(user.getUserId()); + Map resultMap = new HashMap<>(); HttpStatus status = HttpStatus.ACCEPTED; - // String token = request.getHeader("refreshToken"); - - Cookie[] cookies = request.getCookies(); String token = null; @@ -194,17 +193,12 @@ public class UserController { } } Long userId = Long.parseLong(jwtUtil.getUserId(token)); - /// System.out.println(userId); - /// System.out.println("리프레쉬 토큰 (쿠키에서 받은거 "+token); - // log.debug("token : {}, memberDto : {}", token, user); - // System.out.println(jwtUtil.checkToken(token)); + if (jwtUtil.checkToken(token)) { - // System.out.println(token); - // System.out.println(userService.getRefreshToken(userId)); - //System.out.println("쿠키 토큰 , 디비 토큰 비교"+token.equals(userService.getRefreshToken(userId))); + if (token.equals(userService.getRefreshToken(userId))) { - System.out.println("!!"); + String accessToken = jwtUtil.createAccessToken(String.valueOf(userId)); String refreshToken = jwtUtil.createRefreshToken(String.valueOf(userId)); @@ -213,9 +207,9 @@ public class UserController { resultMap.put("access-token", accessToken); - // 바뀐 리프레시db저장 + userService.saveRefreshToken(userId,refreshToken); - // 쿠키 저장 + Cookie refreshCookie = new Cookie("refresh-token", refreshToken); refreshCookie.setPath("/"); refreshCookie.setHttpOnly(true); diff --git a/backend/src/main/java/com/edufocus/edufocus/user/util/JWTUtil.java b/backend/src/main/java/com/edufocus/edufocus/user/util/JWTUtil.java index 89f068f..a5e4964 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/util/JWTUtil.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/util/JWTUtil.java @@ -74,7 +74,7 @@ public class JWTUtil { System.out.println(token); System.out.println(e.getMessage()); log.error("Unexpected error while validating token: {}", e.getMessage()); - return false; + throw new InvalidTokenException(); } } diff --git a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java index 68d1cb1..204e1bc 100644 --- a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java +++ b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java @@ -110,9 +110,6 @@ public class Controller { String roomName = lecture.getTitle(); String participantName = userService.getUserName(userId); - System.out.println(participantName); - - System.out.println(participantName+randStr); AccessToken token = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); token.setName(participantName+randStr); token.setIdentity(participantName+randStr); From 3cc05cb9613e77724d3ea3c71639979a0f191ea1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Thu, 1 Aug 2024 15:21:52 +0900 Subject: [PATCH 088/197] =?UTF-8?q?feat:=20=EC=98=A4=EB=A5=98=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../registration/service/RegistrationService.java | 2 +- .../service/RegistrationServiceImpl.java | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationService.java b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationService.java index b01c410..d1cc462 100644 --- a/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationService.java +++ b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationService.java @@ -18,5 +18,5 @@ public interface RegistrationService { List searchRegistrations(Long LectureId); - RegistrationStatus getStatus(Long userId, Long lectureId); + //RegistrationStatus getStatus(Long userId, Long lectureId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java index 9f89fdb..0225f44 100644 --- a/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java @@ -87,11 +87,11 @@ public class RegistrationServiceImpl implements RegistrationService { return responses; } - @Override - public RegistrationStatus getStatus(Long userId, Long lectureId) { - - Registration registration = registrationRepository.findByUserIdAndLectureId(userId, lectureId); - return registration.getStatus(); - } +// @Override +// public RegistrationStatus getStatus(Long userId, Long lectureId) { +// +// Registration registration = registrationRepository.findByUserIdAndLectureId(userId, lectureId); +// return registration.getStatus(); +// } } From 88693ac9b537dc63964bf4d415002a0f84af9368 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Thu, 1 Aug 2024 16:33:41 +0900 Subject: [PATCH 089/197] jenkins setting --- backend/build.gradle | 2 ++ backend/src/main/resources/application.properties | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/backend/build.gradle b/backend/build.gradle index 8fddcd1..1daa388 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -36,6 +36,8 @@ dependencies { implementation group: 'org.springframework.boot', name: 'spring-boot-starter-mail', version: '3.2.5' implementation 'org.springframework.boot:spring-boot-starter-mail' implementation 'org.mindrot:jbcrypt:0.4' + implementation 'org.springframework.boot:spring-boot-starter-actuator' + diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 9cc111a..58d6582 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -31,7 +31,8 @@ spring.jpa.hibernate.ddl-auto=create spring.jpa.show-sql=true - +management.endpoints.web.exposure.include=health,info +management.endpoint.health.show-details=always spring.mail.host=smtp.gmail.com spring.mail.port=587 From 48d08f0816ca1f902b97fffc4758b91f5b36b536 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Thu, 1 Aug 2024 16:50:42 +0900 Subject: [PATCH 090/197] feat: lecetureServiceImpl Refactoring --- .../lecture/service/LectureServiceImpl.java | 19 +++++++++---------- .../user/controller/UserController.java | 7 +++---- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java index 7c202eb..617a43b 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java @@ -224,19 +224,18 @@ public class LectureServiceImpl implements LectureService { Optional lecture = lectureRepository.findById(id); - Lecture l; - if (lecture.isPresent()) { - l = lecture.get(); - - System.out.println(l.isOnline()); - l.setOnline(true); - System.out.println(l.isOnline()); - - - } else { + if (!lecture.isPresent()) { throw new RuntimeException("Lecture not found with id: " + id); + } + + Lecture l; + l = lecture.get(); + l.setOnline(true); + + + lectureRepository.save(l); } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java index 3a06abc..f57de58 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java @@ -57,10 +57,9 @@ public class UserController { // 비밀번호 변경 @PutMapping("/updatepassword") - public ResponseEntity updatePassword( - - @RequestBody PasswordDto passwordDto, HttpServletRequest request) { - try { + public ResponseEntity updatePassword(@RequestBody PasswordDto passwordDto, HttpServletRequest request) { + try + { String token = request.getHeader("Authorization"); Long userId = Long.parseLong(jwtUtil.getUserId(token)); From c36e444d9c548ad835f008738f876f9666fd0d7f Mon Sep 17 00:00:00 2001 From: kgc91747 Date: Thu, 1 Aug 2024 17:01:00 +0900 Subject: [PATCH 091/197] =?UTF-8?q?refactor:=20Lecture=20=EA=B0=95?= =?UTF-8?q?=EC=9D=98=20=EC=83=81=EC=84=B8=EC=A1=B0=ED=9A=8C=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lecture/service/LectureService.java | 2 + .../lecture/service/LectureServiceImpl.java | 81 ++++++++++--------- 2 files changed, 44 insertions(+), 39 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java index 54d0d3e..fac837d 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java @@ -21,6 +21,8 @@ public interface LectureService { List findAllLecture(); + String getUserStatus(Long userId, Lecture lecture); + LectureDetailResponse findLectureById(Long userId, long lectureId); List findMyLecture(long userId); diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java index 7c202eb..58958f9 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java @@ -134,55 +134,58 @@ public class LectureServiceImpl implements LectureService { } @Override - public LectureDetailResponse findLectureById(Long userId, long lectureId) { - Optional lecture = lectureRepository.findById(lectureId); - if (lecture.isEmpty()) { - return null; - } - - String userStatus; + public String getUserStatus(Long userId, Lecture lecture) { if (userId == null) { - userStatus = String.valueOf(UserStatus.NOT_ENROLLED); - } else { - User user = userRepository.findById(userId).get(); - - if (user.getRole() == UserRole.ADMIN) { - if (lecture.get().getUser().getId() == user.getId()) { - userStatus = String.valueOf(UserStatus.MANAGED_BY_ME); - } else { - userStatus = String.valueOf(UserStatus.MANAGED_BY_OTHERS); - } - } else { - Registration registration = registrationRepository.findByUserIdAndLectureId(userId, lectureId); - - if (registration == null) { - userStatus = String.valueOf(UserStatus.NOT_ENROLLED); - } else if (registration.getStatus() == RegistrationStatus.ACCEPTED) { - userStatus = String.valueOf(UserStatus.ENROLLED); - } else { - userStatus = String.valueOf(UserStatus.PENDING); - } - } + return String.valueOf(UserStatus.NOT_ENROLLED); } + User user = userRepository.findById(userId).orElseThrow(NoSuchElementException::new); + UserRole userRole = user.getRole(); + + if (userRole == UserRole.ADMIN) { + if (lecture.getUser() == user) { + return String.valueOf(UserStatus.MANAGED_BY_ME); + } + return String.valueOf(UserStatus.MANAGED_BY_OTHERS); + } + + Registration registration = registrationRepository.findByUserIdAndLectureId(userId, lecture.getId()); + + if (registration == null) { + return String.valueOf(UserStatus.NOT_ENROLLED); + } + + if (registration.getStatus() == RegistrationStatus.ACCEPTED) { + return String.valueOf(UserStatus.ENROLLED); + } + + return String.valueOf(UserStatus.PENDING); + } + + @Override + public LectureDetailResponse findLectureById(Long userId, long lectureId) { + Lecture lecture = lectureRepository.findById(lectureId).orElseThrow(NoSuchElementException::new); + + String userStatus = getUserStatus(userId, lecture); + return LectureDetailResponse.builder() - .id(lecture.get().getId()) - .title(lecture.get().getTitle()) - .description(lecture.get().getDescription()) - .plan(lecture.get().getPlan()) - .image(lecture.get().getImage()) - .startDate(lecture.get().getStartDate()) - .endDate(lecture.get().getEndDate()) - .time(lecture.get().getTime()) - .online(lecture.get().isOnline()) - .teacherName(lecture.get().getUser().getName()) + .id(lecture.getId()) + .title(lecture.getTitle()) + .description(lecture.getDescription()) + .plan(lecture.getPlan()) + .image(lecture.getImage()) + .startDate(lecture.getStartDate()) + .endDate(lecture.getEndDate()) + .time(lecture.getTime()) + .online(lecture.isOnline()) + .teacherName(lecture.getUser().getName()) .status(userStatus) .build(); } public List findMyLecture(long userId) { - User user = userRepository.findById(userId).get(); + User user = userRepository.findById(userId).orElseThrow(NoSuchElementException::new); List myLectureList = new ArrayList<>(); From 8fdda0f6af5384dce4b289fc52c53bf9a5558605 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Fri, 2 Aug 2024 11:14:41 +0900 Subject: [PATCH 092/197] BE/userinfo --- .../com/edufocus/edufocus/user/config/WebConfiguration.java | 2 +- .../com/edufocus/edufocus/user/controller/UserController.java | 2 +- .../com/edufocus/edufocus/video/controller/Controller.java | 3 +++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java b/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java index f9f5977..8cc0809 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java @@ -27,7 +27,7 @@ public class WebConfiguration implements WebMvcConfigurer { registry .addMapping("/**") .allowedOriginPatterns("https://i11a701.p.ssafy.io/", "http://localhost:5173", "http://localhost:4173","http://localhost:5080","http://192.168.*.*:5173") - .allowedMethods(HttpMethod.GET.name(), HttpMethod.POST.name(), HttpMethod.PUT.name(), + .allowedMethods("GET","POST",HttpMethod.GET.name(), HttpMethod.POST.name(), HttpMethod.PUT.name(), HttpMethod.DELETE.name(), HttpMethod.HEAD.name(), HttpMethod.OPTIONS.name(), HttpMethod.PATCH.name()) .allowCredentials(true) diff --git a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java index f57de58..19f0d89 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java @@ -26,6 +26,7 @@ import java.util.Map; @RequestMapping("/user") @Slf4j @RequiredArgsConstructor + public class UserController { private final UserService userService; @@ -152,7 +153,6 @@ public class UserController { } @GetMapping("/logout") - public ResponseEntity removeToken(HttpServletRequest request) { Map resultMap = new HashMap<>(); HttpStatus status = HttpStatus.ACCEPTED; diff --git a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java index 204e1bc..83356e6 100644 --- a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java +++ b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java @@ -88,6 +88,9 @@ public class Controller { public ResponseEntity> joinRoom(@PathVariable("lecture_id") Long id, HttpServletRequest request) throws Exception { + // 방 조인할떄 고려해야할점 + // 1. 신청됀 강의인지 + // 2. 그 강의기 On인지 String userToken = request.getHeader("Authorization"); From b798f04dfcf351087cc21d37b588ee647ad6be27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Fri, 2 Aug 2024 11:18:19 +0900 Subject: [PATCH 093/197] =?UTF-8?q?feat:=20video=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/edufocus/video/controller/Controller.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java index 83356e6..29fe56d 100644 --- a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java +++ b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java @@ -114,8 +114,8 @@ public class Controller { String roomName = lecture.getTitle(); String participantName = userService.getUserName(userId); AccessToken token = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); - token.setName(participantName+randStr); - token.setIdentity(participantName+randStr); + token.setName(participantName); + token.setIdentity("강사"+randStr); token.addGrants(new RoomJoin(true), new RoomName(roomName), new RoomCreate(true)); videoSertvice.startOnline(userId, id); @@ -133,8 +133,8 @@ public class Controller { System.out.println(participantName); AccessToken token = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); - token.setName(participantName+randStr); - token.setIdentity(participantName+randStr); + token.setName(participantName); + token.setIdentity("학생"+participantName+randStr); token.addGrants(new RoomJoin(true), new RoomName(roomName)); From b05f555d9ad2e38b0f9c787d8105318b1ac9324c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Fri, 2 Aug 2024 11:24:45 +0900 Subject: [PATCH 094/197] =?UTF-8?q?feat:=20user=20cors=EC=97=90=EB=9F=AC?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/edufocus/edufocus/user/config/WebConfiguration.java | 2 +- .../com/edufocus/edufocus/user/controller/UserController.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java b/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java index 8cc0809..0d8851c 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java @@ -26,7 +26,7 @@ public class WebConfiguration implements WebMvcConfigurer { public void addCorsMappings(CorsRegistry registry) { registry .addMapping("/**") - .allowedOriginPatterns("https://i11a701.p.ssafy.io/", "http://localhost:5173", "http://localhost:4173","http://localhost:5080","http://192.168.*.*:5173") + .allowedOriginPatterns("https://i11a701.p.ssafy.io/","https://localhost:5173", "http://localhost:5173", "http://localhost:4173","http://localhost:5080","http://192.168.*.*:5173") .allowedMethods("GET","POST",HttpMethod.GET.name(), HttpMethod.POST.name(), HttpMethod.PUT.name(), HttpMethod.DELETE.name(), HttpMethod.HEAD.name(), HttpMethod.OPTIONS.name(), HttpMethod.PATCH.name()) diff --git a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java index 19f0d89..91fae7e 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java @@ -26,7 +26,7 @@ import java.util.Map; @RequestMapping("/user") @Slf4j @RequiredArgsConstructor - +@CrossOrigin(origins = "http://localhost:5173", allowedHeaders = "*", allowCredentials = "true") public class UserController { private final UserService userService; From 679a885919a91beb34d0fad447d6826a65c575d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Fri, 2 Aug 2024 12:56:05 +0900 Subject: [PATCH 095/197] BE/uesrinfo --- .../com/edufocus/edufocus/user/controller/UserController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java index 91fae7e..03566ed 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java @@ -152,7 +152,7 @@ public class UserController { return new ResponseEntity>(resultMap, status); } - @GetMapping("/logout") + @PostMapping("/logout") public ResponseEntity removeToken(HttpServletRequest request) { Map resultMap = new HashMap<>(); HttpStatus status = HttpStatus.ACCEPTED; From f0ef0a397d973676367f92d87518ccb2b15b3784 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Fri, 2 Aug 2024 13:15:52 +0900 Subject: [PATCH 096/197] =?UTF-8?q?feat:=20video=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/video/controller/Controller.java | 21 +++++++++++++++---- .../edufocus/video/dto/IdentityData.java | 17 +++++++++++++++ 2 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 backend/src/main/java/com/edufocus/edufocus/video/dto/IdentityData.java diff --git a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java index 29fe56d..e0af090 100644 --- a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java +++ b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java @@ -14,7 +14,10 @@ import com.edufocus.edufocus.user.model.entity.UserRole; import com.edufocus.edufocus.user.model.repository.UserRepository; import com.edufocus.edufocus.user.model.service.UserService; import com.edufocus.edufocus.user.util.JWTUtil; +import com.edufocus.edufocus.video.dto.IdentityData; import com.edufocus.edufocus.video.service.VideoSertvice; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import io.livekit.server.*; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; @@ -45,6 +48,7 @@ public class Controller { @Value("${livekit.api.secret}") private String LIVEKIT_API_SECRET; + private static final ObjectMapper objectMapper = new ObjectMapper(); /** * @param params JSON object with roomName and participantName @@ -82,7 +86,9 @@ public class Controller { return new ResponseEntity<>("방만들기 성공",HttpStatus.OK); } - + public static String serializeIdentityData(IdentityData identityData) throws JsonProcessingException, JsonProcessingException { + return objectMapper.writeValueAsString(identityData); + } @PostMapping(value = "/joinroom/{lecture_id}") public ResponseEntity> joinRoom(@PathVariable("lecture_id") Long id, HttpServletRequest request) throws Exception @@ -114,14 +120,20 @@ public class Controller { String roomName = lecture.getTitle(); String participantName = userService.getUserName(userId); AccessToken token = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); + IdentityData identityData = new IdentityData(participantName, "강사"); + String jsonIdentity = serializeIdentityData(identityData); + + + + token.setIdentity(jsonIdentity); token.setName(participantName); - token.setIdentity("강사"+randStr); + token.addGrants(new RoomJoin(true), new RoomName(roomName), new RoomCreate(true)); videoSertvice.startOnline(userId, id); - return ResponseEntity.ok(Map.of("token", token.toJwt())); + return ResponseEntity.ok(Map.of("joinroom token", token.toJwt())); } else if(findUser.getRole()==UserRole.STUDENT )// && lecture.isOnline() ) @@ -133,8 +145,9 @@ public class Controller { System.out.println(participantName); AccessToken token = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); - token.setName(participantName); token.setIdentity("학생"+participantName+randStr); + token.setName(participantName); + token.addGrants(new RoomJoin(true), new RoomName(roomName)); diff --git a/backend/src/main/java/com/edufocus/edufocus/video/dto/IdentityData.java b/backend/src/main/java/com/edufocus/edufocus/video/dto/IdentityData.java new file mode 100644 index 0000000..e9fd7dd --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/video/dto/IdentityData.java @@ -0,0 +1,17 @@ +package com.edufocus.edufocus.video.dto; + +public class IdentityData { + private String name; + private String role; + + public IdentityData(String name, String role) { + this.name = name; + this.role = role; + } + + // Getters and setters + public String getName() { return name; } + public void setName(String name) { this.name = name; } + public String getRole() { return role; } + public void setRole(String role) { this.role = role; } +} From 2db6511a19a98f09e7c1e208ef2209994f31c047 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Fri, 2 Aug 2024 13:20:02 +0900 Subject: [PATCH 097/197] =?UTF-8?q?feat:=20qna=20delete=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/edufocus/edufocus/qna/service/QnaServiceImpl.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java index 5ab58f9..c9e537f 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java @@ -138,6 +138,9 @@ qnaRepository.deleteById(id); @Override public void deleteAnswer(Long id) throws SQLException { - qnaRepository.deleteById(id); + Qna findQna = qnaRepository.findById(id).orElse(null); + findQna.setAnswer(null); + qnaRepository.save(findQna); + } } From b22009ef75a05a6c8a7ca399bafa3da306735ed8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Fri, 2 Aug 2024 13:41:07 +0900 Subject: [PATCH 098/197] =?UTF-8?q?feat:=20qna=20=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/edufocus/edufocus/qna/controller/QnaController.java | 2 +- .../java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java b/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java index 6ba7628..fe50454 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java @@ -68,7 +68,7 @@ public class QnaController { } } - @DeleteMapping("/answer/delete/{qna_id}") + @PostMapping("/answer/delete/{qna_id}") public ResponseEntity deleteAnswer(@PathVariable("qna_id") Long qna_id) { try { diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java index c9e537f..d583346 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java @@ -141,6 +141,6 @@ qnaRepository.deleteById(id); Qna findQna = qnaRepository.findById(id).orElse(null); findQna.setAnswer(null); qnaRepository.save(findQna); - + } } From 156955d84704bd6aed3f1e3942d47fb76f837ea5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Fri, 2 Aug 2024 13:48:23 +0900 Subject: [PATCH 099/197] =?UTF-8?q?feat:=20openvidu=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/edufocus/edufocus/video/controller/Controller.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java index e0af090..d11f2b4 100644 --- a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java +++ b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java @@ -132,8 +132,9 @@ public class Controller { videoSertvice.startOnline(userId, id); + System.out.println(); - return ResponseEntity.ok(Map.of("joinroom token", token.toJwt())); + return ResponseEntity.ok(Map.of("token", token.toJwt())); } else if(findUser.getRole()==UserRole.STUDENT )// && lecture.isOnline() ) From 3a8b244f141f96128e7e49a2e867be3842316900 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Fri, 2 Aug 2024 13:50:35 +0900 Subject: [PATCH 100/197] feat: video controller --- .../edufocus/edufocus/video/controller/Controller.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java index d11f2b4..363f9f1 100644 --- a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java +++ b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java @@ -146,7 +146,13 @@ public class Controller { System.out.println(participantName); AccessToken token = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); - token.setIdentity("학생"+participantName+randStr); + + IdentityData identityData = new IdentityData(participantName, "강사"); + String jsonIdentity = serializeIdentityData(identityData); + + + + token.setIdentity(jsonIdentity); token.setName(participantName); token.addGrants(new RoomJoin(true), new RoomName(roomName)); From 75a4baf7828f1c172cc1371b5d05fddf8b44b149 Mon Sep 17 00:00:00 2001 From: kgc91747 Date: Fri, 2 Aug 2024 15:41:42 +0900 Subject: [PATCH 101/197] =?UTF-8?q?feat:=20Registration=20=EB=AF=B8?= =?UTF-8?q?=EC=8A=B9=EC=9D=B8=20=EC=88=98=EA=B0=95=EC=8B=A0=EC=B2=AD=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C,=20=EC=A4=91=EB=B3=B5=EC=8B=A0=EC=B2=AD=20?= =?UTF-8?q?=ED=99=95=EC=9D=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/RegistrationController.java | 2 +- .../repository/RegistrationRepository.java | 1 + .../service/RegistrationService.java | 2 +- .../service/RegistrationServiceImpl.java | 20 +++++++++++-------- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/controller/RegistrationController.java b/backend/src/main/java/com/edufocus/edufocus/registration/controller/RegistrationController.java index 6e008fe..4b8bba3 100644 --- a/backend/src/main/java/com/edufocus/edufocus/registration/controller/RegistrationController.java +++ b/backend/src/main/java/com/edufocus/edufocus/registration/controller/RegistrationController.java @@ -29,7 +29,7 @@ public class RegistrationController { Long lectureId = map.get("lectureId"); if (!registrationService.createRegistration(userId, lectureId)) { - return new ResponseEntity<>(HttpStatus.CONFLICT); + return new ResponseEntity<>(HttpStatus.NOT_FOUND); } return new ResponseEntity<>(HttpStatus.CREATED); diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/repository/RegistrationRepository.java b/backend/src/main/java/com/edufocus/edufocus/registration/repository/RegistrationRepository.java index f8c31b7..ef2c721 100644 --- a/backend/src/main/java/com/edufocus/edufocus/registration/repository/RegistrationRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/registration/repository/RegistrationRepository.java @@ -12,6 +12,7 @@ import java.util.List; public interface RegistrationRepository extends JpaRepository { List findAllByUserId(@Param("userId") Long userId); + @Query("SELECT r FROM Registration r WHERE r.lecture.id = :lectureId AND r.status = 'WAITING'") List findAllNotAcceptedByLectureId(@Param("lectureId") Long lectureId); Registration findByUserIdAndLectureId(Long userId, Long lectureId); diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationService.java b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationService.java index d1cc462..b01c410 100644 --- a/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationService.java +++ b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationService.java @@ -18,5 +18,5 @@ public interface RegistrationService { List searchRegistrations(Long LectureId); - //RegistrationStatus getStatus(Long userId, Long lectureId); + RegistrationStatus getStatus(Long userId, Long lectureId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java index 0225f44..4e69660 100644 --- a/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java @@ -34,7 +34,11 @@ public class RegistrationServiceImpl implements RegistrationService { return false; } - Registration registration = new Registration().builder() + if (registrationRepository.findByUserIdAndLectureId(userId, lectureId) != null) { + return false; + } + + Registration registration = Registration.builder() .user(userRepository.findById(userId).get()) .lecture(lectureRepository.findById(lectureId).get()) .status(RegistrationStatus.WAITING) @@ -76,7 +80,7 @@ public class RegistrationServiceImpl implements RegistrationService { List responses = new ArrayList<>(); for (Registration registration : registrations) { - RegistrationSearchResponse response = new RegistrationSearchResponse().builder() + RegistrationSearchResponse response = RegistrationSearchResponse.builder() .id(registration.getId()) .userName(registration.getUser().getName()) .build(); @@ -87,11 +91,11 @@ public class RegistrationServiceImpl implements RegistrationService { return responses; } -// @Override -// public RegistrationStatus getStatus(Long userId, Long lectureId) { -// -// Registration registration = registrationRepository.findByUserIdAndLectureId(userId, lectureId); -// return registration.getStatus(); -// } + @Override + public RegistrationStatus getStatus(Long userId, Long lectureId) { + + Registration registration = registrationRepository.findByUserIdAndLectureId(userId, lectureId); + return registration.getStatus(); + } } From d280424d557e95bcd04e9b5d283529172cfcda0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Fri, 2 Aug 2024 16:07:27 +0900 Subject: [PATCH 102/197] =?UTF-8?q?feat:=20token=20exception=20(=EC=9E=91?= =?UTF-8?q?=EC=97=85=EC=A4=91)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/controller/UserController.java | 28 +++++++++++-------- .../exception/GlobalExceptionHandler.java | 8 +++++- .../RefreshTokenExpiredException.java | 9 ++++++ .../edufocus/edufocus/user/util/JWTUtil.java | 22 +++++++++++---- .../src/main/resources/application.properties | 6 ++-- 5 files changed, 52 insertions(+), 21 deletions(-) create mode 100644 backend/src/main/java/com/edufocus/edufocus/user/model/exception/RefreshTokenExpiredException.java diff --git a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java index 03566ed..9feb6a0 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java @@ -4,6 +4,7 @@ import com.edufocus.edufocus.user.model.entity.InfoDto; import com.edufocus.edufocus.user.model.entity.PasswordDto; import com.edufocus.edufocus.user.model.entity.User; import com.edufocus.edufocus.user.model.exception.ExpriedTokenException; +import com.edufocus.edufocus.user.model.exception.RefreshTokenExpiredException; import com.edufocus.edufocus.user.model.exception.UnAuthorizedException; import com.edufocus.edufocus.user.model.service.UserService; import com.edufocus.edufocus.user.util.JWTUtil; @@ -76,7 +77,7 @@ public class UserController { @RequestBody @Parameter(description = "로그인 시 필요한 회원정보(아이디, 비밀번호).", required = true) User user, HttpServletRequest request, HttpServletResponse response) { String token = request.getHeader("Authorization"); - if(jwtUtil.checkToken(token)){ + if(jwtUtil.checkToken(token, false)){ return new ResponseEntity<>(HttpStatus.FORBIDDEN); } @@ -132,7 +133,7 @@ public class UserController { Map resultMap = new HashMap<>(); HttpStatus status = HttpStatus.ACCEPTED; - if (jwtUtil.checkToken(request.getHeader("Authorization"))) { + if (jwtUtil.checkToken(request.getHeader("Authorization"), false)) { log.info("사용 가능한 토큰!!!"); try { User member = userService.userInfo(userId); @@ -144,7 +145,7 @@ public class UserController { status = HttpStatus.INTERNAL_SERVER_ERROR; } } else { - System.out.println(jwtUtil.checkToken(request.getHeader("Authorization"))); + System.out.println(jwtUtil.checkToken(request.getHeader("Authorization"), false)); log.error("사용 불가능 토큰!!!"); resultMap.put("message", "Unauthorized token"); status = HttpStatus.UNAUTHORIZED; @@ -166,7 +167,7 @@ public class UserController { } catch (Exception e) { log.error("로그아웃 실패 : {}", e); resultMap.put("message", e.getMessage()); - status = HttpStatus.INTERNAL_SERVER_ERROR; + status = HttpStatus.UNAUTHORIZED; } return new ResponseEntity>(resultMap, status); } @@ -192,12 +193,16 @@ public class UserController { } } Long userId = Long.parseLong(jwtUtil.getUserId(token)); - - if (jwtUtil.checkToken(token)) { + if(jwtUtil.isExpired(token)){ + throw new RefreshTokenExpiredException(); + } - if (token.equals(userService.getRefreshToken(userId))) { + try { + if (token == null || jwtUtil.checkToken(token, true) || !token.equals(userService.getRefreshToken(userId))) { + throw new RefreshTokenExpiredException(); + } String accessToken = jwtUtil.createAccessToken(String.valueOf(userId)); String refreshToken = jwtUtil.createRefreshToken(String.valueOf(userId)); @@ -219,11 +224,10 @@ public class UserController { System.out.println("바뀐 리프레쉬랑 지금꺼 비교 "+ refreshToken.equals(token)); resultMap.put("access-token", accessToken); status = HttpStatus.CREATED; - - } - } else { + } catch (Exception e) { log.debug("refresh token 도 사용 불가!!!!!!!"); - status = HttpStatus.UNAUTHORIZED; + System.out.println("refresh token 도 사용 불가!!!!!!!"); + status = HttpStatus.FORBIDDEN; } return new ResponseEntity>(resultMap, status); } @@ -235,7 +239,7 @@ public class UserController { HttpStatus status = HttpStatus.ACCEPTED; String token = request.getHeader("Authorization"); - if (jwtUtil.checkToken(token)) { + if (jwtUtil.checkToken(token, false)) { String userId = jwtUtil.getUserId(token); log.info("사용 가능한 토큰!!! userId: {}", userId); try { diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/exception/GlobalExceptionHandler.java b/backend/src/main/java/com/edufocus/edufocus/user/model/exception/GlobalExceptionHandler.java index 63355d3..e4b08fc 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/exception/GlobalExceptionHandler.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/exception/GlobalExceptionHandler.java @@ -16,10 +16,16 @@ public class GlobalExceptionHandler { return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST); } - + // @ExceptionHandler(ExpriedTokenException.class) public ResponseEntity handleInvalidTokenException(ExpriedTokenException e) { return new ResponseEntity<>(e.getMessage(), HttpStatus.UNAUTHORIZED); } + + @ExceptionHandler(RefreshTokenExpiredException.class) + public ResponseEntity handleInvalidTokenException(RefreshTokenExpiredException e) { + + return new ResponseEntity<>(e.getMessage(), HttpStatus.FORBIDDEN); + } } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/exception/RefreshTokenExpiredException.java b/backend/src/main/java/com/edufocus/edufocus/user/model/exception/RefreshTokenExpiredException.java new file mode 100644 index 0000000..8a1dd14 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/exception/RefreshTokenExpiredException.java @@ -0,0 +1,9 @@ +package com.edufocus.edufocus.user.model.exception; + +public class RefreshTokenExpiredException extends RuntimeException { + private static final long serialVersionUID = 1L; + + public RefreshTokenExpiredException() { + super("REFRESH TOKEN 만료\n다시 로그인을 하세요."); + } +} diff --git a/backend/src/main/java/com/edufocus/edufocus/user/util/JWTUtil.java b/backend/src/main/java/com/edufocus/edufocus/user/util/JWTUtil.java index a5e4964..1df2eca 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/util/JWTUtil.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/util/JWTUtil.java @@ -6,6 +6,7 @@ import java.util.Map; import com.edufocus.edufocus.user.model.exception.ExpriedTokenException; import com.edufocus.edufocus.user.model.exception.InvalidTokenException; +import com.edufocus.edufocus.user.model.exception.RefreshTokenExpiredException; import com.edufocus.edufocus.user.model.exception.UnAuthorizedException; import io.jsonwebtoken.*; import org.springframework.beans.factory.annotation.Value; @@ -64,12 +65,7 @@ public class JWTUtil { log.error("Token validation error: {}", e.getMessage()); return false; - } - catch ( ExpiredJwtException e) - { - throw new ExpriedTokenException(); - - } + } catch (Exception e) { System.out.println(token); System.out.println(e.getMessage()); @@ -78,6 +74,20 @@ public class JWTUtil { } } + public boolean isExpired(String token) { + try { + Jws claims = Jwts.parserBuilder() + .setSigningKey(generateKey()) + .build() + .parseClaimsJws(token); + return false; + }catch(ExpiredJwtException e){ + return true; + }catch(Exception e){ + throw new InvalidTokenException(); + } + } + public String getUserId(String authorization) { try { Jws claims = Jwts.parserBuilder() diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 58d6582..0f03472 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -16,10 +16,12 @@ livekit.api.secret=${LIVEKIT_API_SECRET:secret} jwt.salt=${SALT} # Access Token ?? ?? (??? ??) -jwt.access-token.expiretime=3600000 +#jwt.access-token.expiretime=3600000 +jwt.access-token.expiretime=3000 # Refresh Token ?? ?? (??? ??) -jwt.refresh-token.expiretime=86400000 +jwt.refresh-token.expiretime=50400000 +#jwt.refresh-token.expiretime=4000 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=${DATA_SOURCE_URL} spring.datasource.username=${USER_NAME} From 44e9308927ae95ce5890e1c35edf351459611a12 Mon Sep 17 00:00:00 2001 From: kgc91747 Date: Fri, 2 Aug 2024 16:18:17 +0900 Subject: [PATCH 103/197] =?UTF-8?q?feat:=20Quiz=20=EA=B0=95=EC=82=AC/?= =?UTF-8?q?=ED=95=99=EC=83=9D=20=ED=83=80=EC=9E=85=EB=B3=84=20=ED=80=B4?= =?UTF-8?q?=EC=A6=88=20=EC=A1=B0=ED=9A=8C=20=EA=B2=B0=EA=B3=BC=20=EA=B5=AC?= =?UTF-8?q?=EB=B6=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/quiz/controller/QuizController.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java b/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java index 3a27228..c85822a 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java @@ -42,13 +42,25 @@ public class QuizController { return new ResponseEntity<>(HttpStatus.CREATED); } - @GetMapping("/{quizsetId}") + @GetMapping("/student/{quizsetId}") public ResponseEntity getQuizzes(@PathVariable Long quizsetId) { QuizSetResponse quizSet = quizSetService.findQuizSetResponse(quizsetId); return new ResponseEntity<>(quizSet, HttpStatus.OK); } + @GetMapping("/teacher/{quizsetId}") + public ResponseEntity getQuizzesIncludeAnswer(@RequestHeader("Authorization") String accessToken, @PathVariable Long quizsetId) { + long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); + + QuizSet quizSet = quizSetService.findQuizSet(quizsetId); + if (quizSet.getUser().getId() != userId) { + return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); + } + + return new ResponseEntity<>(quizSet, HttpStatus.OK); + } + @DeleteMapping("/{quizsetId}") public ResponseEntity deleteQuizSet(@RequestHeader("Authorization") String accessToken, @PathVariable long quizsetId) { long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); From 746197715634ff77051f5ebd75f1d855100deb27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Fri, 2 Aug 2024 17:02:00 +0900 Subject: [PATCH 104/197] =?UTF-8?q?feat:=20openvidu=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/video/controller/Controller.java | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java index 363f9f1..a94758e 100644 --- a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java +++ b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java @@ -108,18 +108,21 @@ public class Controller { Random random = new Random(); System.out.println(); - int randomNumber = 100 + random.nextInt(9000); + int randomNumber = 10000 + random.nextInt(80000); String randStr = String.valueOf(randomNumber); + String roomName = lecture.getTitle(); + String participantName = userService.getUserName(userId); + System.out.println(participantName); + + AccessToken token = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); + if(findUser.getRole()==UserRole.ADMIN ){//&& lecture.isOnline() ) { - String roomName = lecture.getTitle(); - String participantName = userService.getUserName(userId); - AccessToken token = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); IdentityData identityData = new IdentityData(participantName, "강사"); String jsonIdentity = serializeIdentityData(identityData); @@ -141,13 +144,7 @@ public class Controller { { - String roomName = lecture.getTitle(); - String participantName = userService.getUserName(userId); - System.out.println(participantName); - - AccessToken token = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); - - IdentityData identityData = new IdentityData(participantName, "강사"); + IdentityData identityData = new IdentityData(participantName, "학생"); String jsonIdentity = serializeIdentityData(identityData); From 3302c8b51e6437f9ed1aa583a2ef6e7c022ffe78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Fri, 2 Aug 2024 17:19:17 +0900 Subject: [PATCH 105/197] =?UTF-8?q?feat:=20token=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/controller/UserController.java | 92 +++++-------------- .../user/intercepter/JWTInterceptor.java | 12 +-- .../exception/GlobalExceptionHandler.java | 15 +-- .../edufocus/edufocus/user/util/JWTUtil.java | 32 ++----- 4 files changed, 38 insertions(+), 113 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java index 9feb6a0..9e1ebe5 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java @@ -4,6 +4,7 @@ import com.edufocus.edufocus.user.model.entity.InfoDto; import com.edufocus.edufocus.user.model.entity.PasswordDto; import com.edufocus.edufocus.user.model.entity.User; import com.edufocus.edufocus.user.model.exception.ExpriedTokenException; +import com.edufocus.edufocus.user.model.exception.InvalidTokenException; import com.edufocus.edufocus.user.model.exception.RefreshTokenExpiredException; import com.edufocus.edufocus.user.model.exception.UnAuthorizedException; import com.edufocus.edufocus.user.model.service.UserService; @@ -77,7 +78,7 @@ public class UserController { @RequestBody @Parameter(description = "로그인 시 필요한 회원정보(아이디, 비밀번호).", required = true) User user, HttpServletRequest request, HttpServletResponse response) { String token = request.getHeader("Authorization"); - if(jwtUtil.checkToken(token, false)){ + if(jwtUtil.checkToken(token)){ return new ResponseEntity<>(HttpStatus.FORBIDDEN); } @@ -123,35 +124,6 @@ public class UserController { return new ResponseEntity<>(resultMap, status); } - @Operation(summary = "회원인증", description = "회원 정보를 담은 Token 을 반환한다.") - @GetMapping("/auth/{userId}") - public ResponseEntity> getInfo( - @PathVariable("userId") @Parameter(description = "인증할 회원의 아이디.", required = true) Long userId, - HttpServletRequest request) { - String id = String.valueOf(userId); - - - Map resultMap = new HashMap<>(); - HttpStatus status = HttpStatus.ACCEPTED; - if (jwtUtil.checkToken(request.getHeader("Authorization"), false)) { - log.info("사용 가능한 토큰!!!"); - try { - User member = userService.userInfo(userId); - resultMap.put("userInfo", member); - status = HttpStatus.OK; - } catch (Exception e) { - log.error("정보조회 실패 : {}", e); - resultMap.put("message", e.getMessage()); - status = HttpStatus.INTERNAL_SERVER_ERROR; - } - } else { - System.out.println(jwtUtil.checkToken(request.getHeader("Authorization"), false)); - log.error("사용 불가능 토큰!!!"); - resultMap.put("message", "Unauthorized token"); - status = HttpStatus.UNAUTHORIZED; - } - return new ResponseEntity>(resultMap, status); - } @PostMapping("/logout") public ResponseEntity removeToken(HttpServletRequest request) { @@ -176,14 +148,8 @@ public class UserController { @PostMapping("/refresh") public ResponseEntity refreshToken(HttpServletRequest request,HttpServletResponse response) throws Exception { - - - Map resultMap = new HashMap<>(); - HttpStatus status = HttpStatus.ACCEPTED; - Cookie[] cookies = request.getCookies(); String token = null; - if (cookies != null) { for (Cookie cookie : cookies) { if (cookie.getName().equals("refresh-token")) { @@ -192,44 +158,36 @@ public class UserController { } } } + + try{ + jwtUtil.checkToken(token); + }catch (Exception e){ + throw new InvalidTokenException(); + } + Long userId = Long.parseLong(jwtUtil.getUserId(token)); - if(jwtUtil.isExpired(token)){ - throw new RefreshTokenExpiredException(); + + if (!token.equals(userService.getRefreshToken(userId))) { + throw new InvalidTokenException(); } - try { - if (token == null || jwtUtil.checkToken(token, true) || !token.equals(userService.getRefreshToken(userId))) { - throw new RefreshTokenExpiredException(); - - } - String accessToken = jwtUtil.createAccessToken(String.valueOf(userId)); - String refreshToken = jwtUtil.createRefreshToken(String.valueOf(userId)); - - log.debug("token : {}", accessToken); - log.debug("정상적으로 access token 재발급!!!"); - resultMap.put("access-token", accessToken); + String accessToken = jwtUtil.createAccessToken(String.valueOf(userId)); + String refreshToken = jwtUtil.createRefreshToken(String.valueOf(userId)); + Map resultMap = new HashMap<>(); + resultMap.put("access-token", accessToken); - userService.saveRefreshToken(userId,refreshToken); + userService.saveRefreshToken(userId,refreshToken); - Cookie refreshCookie = new Cookie("refresh-token", refreshToken); - refreshCookie.setPath("/"); - refreshCookie.setHttpOnly(true); - refreshCookie.setSecure(true); // HTTPS에서만 전송되도록 설정 - // refreshCookie.setSameSite(Cookie.SameSite.NONE); // Cross-Origin 요청에 대해 모두 전송 + Cookie refreshCookie = new Cookie("refresh-token", refreshToken); + refreshCookie.setPath("/"); + refreshCookie.setHttpOnly(true); + refreshCookie.setSecure(true); + response.addCookie(refreshCookie); - response.addCookie(refreshCookie); - System.out.println("바뀐 리프레쉬랑 지금꺼 비교 "+ refreshToken.equals(token)); - resultMap.put("access-token", accessToken); - status = HttpStatus.CREATED; - } catch (Exception e) { - log.debug("refresh token 도 사용 불가!!!!!!!"); - System.out.println("refresh token 도 사용 불가!!!!!!!"); - status = HttpStatus.FORBIDDEN; - } - return new ResponseEntity>(resultMap, status); + return new ResponseEntity>(resultMap, HttpStatus.CREATED); } @Operation(summary = "회원 정보 조회", description = "토큰을 이용하여 회원 정보를 조회한다.") @@ -239,7 +197,7 @@ public class UserController { HttpStatus status = HttpStatus.ACCEPTED; String token = request.getHeader("Authorization"); - if (jwtUtil.checkToken(token, false)) { + if (jwtUtil.checkToken(token)) { String userId = jwtUtil.getUserId(token); log.info("사용 가능한 토큰!!! userId: {}", userId); try { @@ -272,4 +230,4 @@ public class UserController { -} +} \ No newline at end of file diff --git a/backend/src/main/java/com/edufocus/edufocus/user/intercepter/JWTInterceptor.java b/backend/src/main/java/com/edufocus/edufocus/user/intercepter/JWTInterceptor.java index fc741dc..c1c6003 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/intercepter/JWTInterceptor.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/intercepter/JWTInterceptor.java @@ -24,17 +24,11 @@ public class JWTInterceptor implements HandlerInterceptor { } @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) - throws Exception { + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler){ final String token = request.getHeader(HEADER_AUTH); - if (token != null && jwtUtil.checkToken(token)) { - log.info("토큰 사용 가능 : {}", token); - return true; - } else { - log.info("토큰 사용 불가능 : {}", token); - throw new UnAuthorizedException(); - } + jwtUtil.checkToken(token); + return true; } } \ No newline at end of file diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/exception/GlobalExceptionHandler.java b/backend/src/main/java/com/edufocus/edufocus/user/model/exception/GlobalExceptionHandler.java index e4b08fc..21c3a22 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/exception/GlobalExceptionHandler.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/exception/GlobalExceptionHandler.java @@ -9,23 +9,14 @@ import org.springframework.web.bind.annotation.ExceptionHandler; public class GlobalExceptionHandler { @ExceptionHandler(InvalidTokenException.class) - public ResponseEntity handleUnAuthorizedException(InvalidTokenException e) { - - - + public ResponseEntity handleInvalidTokenException(InvalidTokenException e) { return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST); } // @ExceptionHandler(ExpriedTokenException.class) - public ResponseEntity handleInvalidTokenException(ExpriedTokenException e) { - + public ResponseEntity handleExpiredTokenException(ExpriedTokenException e) { return new ResponseEntity<>(e.getMessage(), HttpStatus.UNAUTHORIZED); } - @ExceptionHandler(RefreshTokenExpiredException.class) - public ResponseEntity handleInvalidTokenException(RefreshTokenExpiredException e) { - - return new ResponseEntity<>(e.getMessage(), HttpStatus.FORBIDDEN); - } -} +} \ No newline at end of file diff --git a/backend/src/main/java/com/edufocus/edufocus/user/util/JWTUtil.java b/backend/src/main/java/com/edufocus/edufocus/user/util/JWTUtil.java index 1df2eca..e7d4f8c 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/util/JWTUtil.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/util/JWTUtil.java @@ -54,40 +54,22 @@ public class JWTUtil { } public boolean checkToken(String token) { - try { - Jws claims = Jwts.parserBuilder() - .setSigningKey(generateKey()) - .build() - .parseClaimsJws(token); - log.debug("claims: {}", claims); - return true; - } catch (MalformedJwtException | UnsupportedJwtException | IllegalArgumentException | SignatureException e) { - log.error("Token validation error: {}", e.getMessage()); - - return false; - } - catch (Exception e) { - System.out.println(token); - System.out.println(e.getMessage()); - log.error("Unexpected error while validating token: {}", e.getMessage()); - throw new InvalidTokenException(); - } - } - - public boolean isExpired(String token) { try { Jws claims = Jwts.parserBuilder() .setSigningKey(generateKey()) .build() .parseClaimsJws(token); - return false; - }catch(ExpiredJwtException e){ + log.debug("claims: {}", claims); return true; - }catch(Exception e){ + } + catch (ExpriedTokenException e) { + throw new ExpriedTokenException(); + }catch (Exception e){ throw new InvalidTokenException(); } } + public String getUserId(String authorization) { try { Jws claims = Jwts.parserBuilder() @@ -108,4 +90,4 @@ public class JWTUtil { throw new InvalidTokenException(); } } -} +} \ No newline at end of file From 874b8773996a082d0489db1251818ac1c633ef8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Fri, 2 Aug 2024 17:24:50 +0900 Subject: [PATCH 106/197] reafactoring: mailsender --- .../user/controller/UserController.java | 10 ++-- .../edufocus/user/model/entity/MailDto.java | 20 -------- .../user/model/service/UserService.java | 4 +- .../user/model/service/UserServiceImpl.java | 47 ------------------- .../src/main/resources/application.properties | 9 ---- 5 files changed, 6 insertions(+), 84 deletions(-) delete mode 100644 backend/src/main/java/com/edufocus/edufocus/user/model/entity/MailDto.java diff --git a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java index 9e1ebe5..828f717 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java @@ -39,11 +39,11 @@ public class UserController { userService.join(user); return ResponseEntity.ok("User registered successfully"); } - @PostMapping("/findpassword/{user_id}") - public ResponseEntity findpassword(@PathVariable("user_id") Long user_id) throws Exception { - userService.userCheck(user_id); - return ResponseEntity.ok("임시 비밀번호가 이메일로 전송되었습니다."); - } +// @PostMapping("/findpassword/{user_id}") +// public ResponseEntity findpassword(@PathVariable("user_id") Long user_id) throws Exception { +// userService.userCheck(user_id); +// return ResponseEntity.ok("임시 비밀번호가 이메일로 전송되었습니다."); +// } @PutMapping("/updateinfo") public ResponseEntity updateUserInfo( diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/MailDto.java b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/MailDto.java deleted file mode 100644 index b2e1e51..0000000 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/MailDto.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.edufocus.edufocus.user.model.entity; - -import lombok.Data; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -@Getter -@Setter -@NoArgsConstructor -@ToString -@Data -public class MailDto { - - private String address; - private String title; - private String message; - -} \ No newline at end of file diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java index e8ea468..9252869 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java @@ -11,9 +11,7 @@ public interface UserService { String getRefreshToken(Long id) throws Exception; void deleteRefreshToken(Long id) throws Exception; User userInfo(Long id) throws Exception; - void sendEamail(User user) throws Exception; - void userCheck(Long id) throws Exception; - String getUserName(Long id) throws Exception; + String getUserName(Long id) throws Exception; void changeUserInfo(InfoDto infoDto,Long id) throws Exception; void changePassword(PasswordDto passwordDto,Long id) throws Exception; diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java index 6c3feec..c6301c0 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java @@ -23,7 +23,6 @@ public class UserServiceImpl implements UserService { private final UserRepository userRepository; - private final JavaMailSender mailSender;//private final PasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); public void join(User user) @@ -61,56 +60,10 @@ public class UserServiceImpl implements UserService { } - @Override - public void sendEamail(User user) throws Exception { - MailDto mailDto = createMailAndChargePassword(user); - SimpleMailMessage message = new SimpleMailMessage(); - message.setTo(mailDto.getAddress()); - message.setFrom("passfinder111@gmail.com"); - message.setSubject(mailDto.getTitle()); - message.setText(mailDto.getMessage()); - - - mailSender.send(message); - - - } - - public MailDto createMailAndChargePassword(User user) throws SQLException { - String str = getTempPassword(); - MailDto dto = new MailDto(); - dto.setAddress(user.getEmail()); - dto.setTitle(user.getUserId() + "님의 임시비밀번호 안내 이메일 입니다."); - dto.setMessage("안녕하세요. EduFoucs 입니다. " + "\n" + "임시비밀번호 안내 관련 메일 입니다." + "\n[" + user.getName() + "]" + "님의 임시 비밀번호는 " - + str + " 입니다."); - - System.out.println(dto); - - MemberChangeDto memberChangeDto = new MemberChangeDto(user.getId(), str); - userRepository.updatePassword(memberChangeDto.getId(), memberChangeDto.getPassword()); - - return dto; - } - - @Override - public void userCheck(Long id) throws Exception { - - User user = userRepository.findById(id).orElse(null); - - - if (user == null) { - throw new UserException("유효하지 않은 아이디입니다. 다시 입력하세요"); - - } else { - - sendEamail(user); - } - } - @Override public String getUserName(Long id) throws Exception { diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 0f03472..4b851bd 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -36,15 +36,6 @@ spring.jpa.show-sql=true management.endpoints.web.exposure.include=health,info management.endpoint.health.show-details=always -spring.mail.host=smtp.gmail.com -spring.mail.port=587 -#spring.mail.username=ssafytestpjt -#spring.mail.password=trpjbxqialufuzih -spring.mail.username=passfinder111@gmail.com -spring.mail.password=mnlyfkiprltjlsmw - -spring.mail.properties.mail.smtp.auth=true -spring.mail.properties.mail.smtp.starttls.enable=true spring.rabbitmq.host=${RABBITMQ_HOST} From a44d29ee1eacba928925c1ae2c6c38d7711830b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Fri, 2 Aug 2024 17:39:51 +0900 Subject: [PATCH 107/197] feat: user token exception --- .../edufocus/user/controller/UserController.java | 12 ------------ .../user/model/exception/GlobalExceptionHandler.java | 2 +- backend/src/main/resources/application.properties | 2 +- 3 files changed, 2 insertions(+), 14 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java index 828f717..55306a5 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java @@ -78,9 +78,6 @@ public class UserController { @RequestBody @Parameter(description = "로그인 시 필요한 회원정보(아이디, 비밀번호).", required = true) User user, HttpServletRequest request, HttpServletResponse response) { String token = request.getHeader("Authorization"); - if(jwtUtil.checkToken(token)){ - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } Map resultMap = new HashMap<>(); HttpStatus status = HttpStatus.ACCEPTED; @@ -218,15 +215,6 @@ public class UserController { } - @ExceptionHandler(ExpriedTokenException.class) - public ResponseEntity handleExpiredTokenException(){ - return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); - - } - @ExceptionHandler(UnAuthorizedException.class) - public ResponseEntity handleUnauthorizedException(){ - return new ResponseEntity<>(HttpStatus.BAD_REQUEST); - } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/exception/GlobalExceptionHandler.java b/backend/src/main/java/com/edufocus/edufocus/user/model/exception/GlobalExceptionHandler.java index 21c3a22..b3b2608 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/exception/GlobalExceptionHandler.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/exception/GlobalExceptionHandler.java @@ -10,7 +10,7 @@ public class GlobalExceptionHandler { @ExceptionHandler(InvalidTokenException.class) public ResponseEntity handleInvalidTokenException(InvalidTokenException e) { - return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST); + return new ResponseEntity<>(e.getMessage(), HttpStatus.FORBIDDEN); } // diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 4b851bd..714d1c9 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -17,7 +17,7 @@ jwt.salt=${SALT} # Access Token ?? ?? (??? ??) #jwt.access-token.expiretime=3600000 -jwt.access-token.expiretime=3000 +jwt.access-token.expiretime=300 # Refresh Token ?? ?? (??? ??) jwt.refresh-token.expiretime=50400000 From 4c019a6fb0e3f710160db1d35fa8eaea591e6aec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Mon, 5 Aug 2024 09:18:21 +0900 Subject: [PATCH 108/197] =?UTF-8?q?feat:=20access-token=20=EC=9E=AC?= =?UTF-8?q?=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/main/resources/application.properties | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 714d1c9..6b6aae7 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -17,7 +17,8 @@ jwt.salt=${SALT} # Access Token ?? ?? (??? ??) #jwt.access-token.expiretime=3600000 -jwt.access-token.expiretime=300 + +jwt.access-token.expiretime=3000000 # Refresh Token ?? ?? (??? ??) jwt.refresh-token.expiretime=50400000 From 2636833458da49c9b4d33a139acc703637d929b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Mon, 5 Aug 2024 10:19:53 +0900 Subject: [PATCH 109/197] =?UTF-8?q?feat:=20=EA=B0=95=EC=9D=98=20=EB=A7=8C?= =?UTF-8?q?=EB=93=A4=EA=B8=B0/=EC=9E=85=EC=9E=A5=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lecture/service/LectureServiceImpl.java | 10 +- .../edufocus/video/controller/Controller.java | 227 +++++++----------- .../edufocus/video/service/VideoSertvice.java | 3 + .../video/service/VideoServiceImpl.java | 25 ++ .../src/main/resources/application.properties | 2 +- 5 files changed, 124 insertions(+), 143 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java index b97246c..b2fc5fd 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java @@ -235,8 +235,14 @@ public class LectureServiceImpl implements LectureService { Lecture l; l = lecture.get(); - l.setOnline(true); - + if(l.isOnline()) + { + l.setOnline(false); + } + else + { + l.setOnline(true); + } lectureRepository.save(l); diff --git a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java index a94758e..c4b06e5 100644 --- a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java +++ b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java @@ -36,180 +36,127 @@ import livekit.LivekitWebhook.WebhookEvent; @RequiredArgsConstructor public class Controller { - private final JWTUtil jwtUtil; - private final UserService userService; - private final LectureService lectureService; - private final VideoSertvice videoSertvice; - private final RegistrationService registrationService; - private final UserRepository userRepository; - private final LectureRepository lectureRepository; - @Value("${livekit.api.key}") - private String LIVEKIT_API_KEY; + private final JWTUtil jwtUtil; + private final UserService userService; + private final LectureService lectureService; + private final VideoSertvice videoSertvice; + private final RegistrationService registrationService; + private final UserRepository userRepository; + private final LectureRepository lectureRepository; - @Value("${livekit.api.secret}") - private String LIVEKIT_API_SECRET; - private static final ObjectMapper objectMapper = new ObjectMapper(); + @Value("${livekit.api.key}") + private String LIVEKIT_API_KEY; - /** - * @param params JSON object with roomName and participantName - * @return JSON object with the JWT token - */ -// @PostMapping(value = "/token") -// public ResponseEntity> createToken(@RequestBody Map params) { -// String roomName = params.get("roomName"); -// String participantName = params.get("participantName"); -// -// if (roomName == null || participantName == null) { -// return ResponseEntity.badRequest().body(Map.of("errorMessage", "roomName and participantName are required")); -// } -// -// AccessToken token = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); -// token.setName(participantName); -// token.setIdentity(participantName); -// token.addGrants(new RoomJoin(true), new RoomName(roomName)); -// -// -// -// return ResponseEntity.ok(Map.of("token", token.toJwt())); -// } - - @PostMapping(value = "/makeroom/{lecture_id}") - public ResponseEntity startLecture(@PathVariable("lecture_id") Long id, HttpServletRequest request) throws Exception { + @Value("${livekit.api.secret}") + private String LIVEKIT_API_SECRET; + private static final ObjectMapper objectMapper = new ObjectMapper(); - String userToken = request.getHeader("Authorization"); - Long userId = Long.parseLong(jwtUtil.getUserId(userToken)); + public static String serializeIdentityData(IdentityData identityData) throws JsonProcessingException, JsonProcessingException { + return objectMapper.writeValueAsString(identityData); + } + + @PostMapping(value = "/joinroom/{lecture_id}") + public ResponseEntity> joinRoom(@PathVariable("lecture_id") Long id, HttpServletRequest request) throws Exception { - videoSertvice.startOnline(userId, id); - - return new ResponseEntity<>("방만들기 성공",HttpStatus.OK); - - } - public static String serializeIdentityData(IdentityData identityData) throws JsonProcessingException, JsonProcessingException { - return objectMapper.writeValueAsString(identityData); - } - - @PostMapping(value = "/joinroom/{lecture_id}") - public ResponseEntity> joinRoom(@PathVariable("lecture_id") Long id, HttpServletRequest request) throws Exception - { - - // 방 조인할떄 고려해야할점 - // 1. 신청됀 강의인지 - // 2. 그 강의기 On인지 - String userToken = request.getHeader("Authorization"); + String userToken = request.getHeader("Authorization"); - Long userId = Long.parseLong(jwtUtil.getUserId(userToken)); - User findUser= userRepository.findById(userId).orElse(null); - Lecture lecture= lectureRepository.findById(id).orElse(null); + Long userId = Long.parseLong(jwtUtil.getUserId(userToken)); + User findUser = userRepository.findById(userId).orElse(null); + Lecture lecture = lectureRepository.findById(id).orElse(null); - Random random = new Random(); + String roomName = lecture.getTitle(); + String participantName = userService.getUserName(userId); + System.out.println(participantName); - System.out.println(); - int randomNumber = 10000 + random.nextInt(80000); - - String randStr = String.valueOf(randomNumber); - - String roomName = lecture.getTitle(); - String participantName = userService.getUserName(userId); - System.out.println(participantName); - - AccessToken token = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); + AccessToken token = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); - if(findUser.getRole()==UserRole.ADMIN ){//&& lecture.isOnline() ) { + if (findUser.getRole() == UserRole.STUDENT) { + + if (videoSertvice.isRoomAccessible(id, userId)) { + IdentityData identityData = new IdentityData(participantName, "학생"); + String jsonIdentity = serializeIdentityData(identityData); + token.setIdentity(jsonIdentity); + token.setName(participantName); - IdentityData identityData = new IdentityData(participantName, "강사"); - String jsonIdentity = serializeIdentityData(identityData); + token.addGrants(new RoomJoin(true), new RoomName(roomName)); - - token.setIdentity(jsonIdentity); - token.setName(participantName); - - token.addGrants(new RoomJoin(true), new RoomName(roomName), new RoomCreate(true)); - - videoSertvice.startOnline(userId, id); - - System.out.println(); - - return ResponseEntity.ok(Map.of("token", token.toJwt())); - - } - else if(findUser.getRole()==UserRole.STUDENT )// && lecture.isOnline() ) - { + return ResponseEntity.ok(Map.of("token", token.toJwt())); + } else { + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(Map.of("error", "방에 들어갈 수 없습니다.")); + } - IdentityData identityData = new IdentityData(participantName, "학생"); - String jsonIdentity = serializeIdentityData(identityData); + } + return ResponseEntity.ok(Map.of("token", null)); - token.setIdentity(jsonIdentity); - token.setName(participantName); - - token.addGrants(new RoomJoin(true), new RoomName(roomName)); + } - videoSertvice.startOnline(userId, id); + @PostMapping(value = "/makeroom/{lecture_id}") + public ResponseEntity> makeRoom(@PathVariable("lecture_id") Long id, HttpServletRequest request) throws Exception { + String userToken = request.getHeader("Authorization"); - return ResponseEntity.ok(Map.of("token", token.toJwt())); - } + Long userId = Long.parseLong(jwtUtil.getUserId(userToken)); + User findUser = userRepository.findById(userId).orElse(null); + Lecture lecture = lectureRepository.findById(id).orElse(null); - return ResponseEntity.ok(Map.of("token", null)); + String roomName = lecture.getTitle(); + String participantName = userService.getUserName(userId); + System.out.println(participantName); -// String userToken = request.getHeader("Authorization"); -// -// Long userId = Long.parseLong(jwtUtil.getUserId(userToken)); -// LectureDetailResponse lecture= lectureService.findLectureById(userId,id); -// -// -// //RegistrationStatus registrationStatus = registrationService.isOnline(userId,id); -// -// if(registrationStatus==RegistrationStatus.ACCEPTED) -// { -// String roomName = lecture.getTitle(); -// String participantName = userService.getUserName(userId); -// -// -// AccessToken token = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); -// token.setName(participantName); -// token.setIdentity(participantName); -// token.addGrants(new RoomJoin(true), new RoomName(roomName)); -// -// //videoSertvice.startOnline(userId,id); -// -// -// -// return ResponseEntity.ok(Map.of("token", token.toJwt())); -// } -// else{ -// return ResponseEntity.status(HttpStatus.FORBIDDEN).body(Map.of("errorMessage", "Not accepted")); -// -// } + AccessToken token = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); + if (findUser.getRole() == UserRole.ADMIN) {//&& lecture.isOnline() ) { - } - @PostMapping(value = "/livekit/webhook", consumes = "application/webhook+json") - public ResponseEntity receiveWebhook(@RequestHeader("Authorization") String authHeader, @RequestBody String body) { - WebhookReceiver webhookReceiver = new WebhookReceiver(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); - try { - WebhookEvent event = webhookReceiver.receive(body, authHeader); - System.out.println("LiveKit Webhook: " + event.toString()); - } catch (Exception e) { - System.err.println("Error validating webhook event: " + e.getMessage()); - } - return ResponseEntity.ok("ok"); - } + videoSertvice.startOnline(userId, id); + + IdentityData identityData = new IdentityData(participantName, "강사"); + String jsonIdentity = serializeIdentityData(identityData); + + + token.setIdentity(jsonIdentity); + token.setName(participantName); + + token.addGrants(new RoomJoin(true), new RoomName(roomName), new RoomCreate(true)); + + + return ResponseEntity.ok(Map.of("token", token.toJwt())); + + } + + + return ResponseEntity.ok(Map.of("token", null)); + + } + + @PostMapping(value = "/livekit/webhook", consumes = "application/webhook+json") + public ResponseEntity receiveWebhook(@RequestHeader("Authorization") String authHeader, @RequestBody String body) { + WebhookReceiver webhookReceiver = new WebhookReceiver(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); + try { + WebhookEvent event = webhookReceiver.receive(body, authHeader); + System.out.println("LiveKit Webhook: " + event.toString()); + } catch (Exception e) { + System.err.println("Error validating webhook event: " + e.getMessage()); + } + + + return ResponseEntity.ok("ok"); + } - } diff --git a/backend/src/main/java/com/edufocus/edufocus/video/service/VideoSertvice.java b/backend/src/main/java/com/edufocus/edufocus/video/service/VideoSertvice.java index 981c5c4..53428f9 100644 --- a/backend/src/main/java/com/edufocus/edufocus/video/service/VideoSertvice.java +++ b/backend/src/main/java/com/edufocus/edufocus/video/service/VideoSertvice.java @@ -5,4 +5,7 @@ import java.sql.SQLException; public interface VideoSertvice { void startOnline(Long userId,Long lectureId) throws SQLException; + + boolean isRoomAccessible(Long lectureId,Long userId); + } diff --git a/backend/src/main/java/com/edufocus/edufocus/video/service/VideoServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/video/service/VideoServiceImpl.java index af82559..c6328e2 100644 --- a/backend/src/main/java/com/edufocus/edufocus/video/service/VideoServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/video/service/VideoServiceImpl.java @@ -1,7 +1,10 @@ package com.edufocus.edufocus.video.service; import com.edufocus.edufocus.lecture.entity.Lecture; +import com.edufocus.edufocus.lecture.entity.LectureDetailResponse; import com.edufocus.edufocus.lecture.service.LectureService; +import com.edufocus.edufocus.registration.entity.RegistrationStatus; +import com.edufocus.edufocus.registration.service.RegistrationService; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -13,9 +16,31 @@ import java.sql.SQLException; public class VideoServiceImpl implements VideoSertvice{ private final LectureService lectureService; + private final RegistrationService registrationService; @Override public void startOnline(Long userId,Long lectureId) throws SQLException { lectureService.changeState(lectureId); } + + @Override + public boolean isRoomAccessible(Long lectureId, Long userId) { + + + + LectureDetailResponse lecture= lectureService.findLectureById(userId,userId); + + + RegistrationStatus registrationStatus = registrationService.getStatus(userId,lectureId); + + + if(registrationStatus==RegistrationStatus.ACCEPTED && lecture.isOnline()) + { + return true; + } + else + { + return false; + } + } } diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 6b6aae7..b774bfc 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -21,7 +21,7 @@ jwt.salt=${SALT} jwt.access-token.expiretime=3000000 # Refresh Token ?? ?? (??? ??) -jwt.refresh-token.expiretime=50400000 +jwt.refresh-token.expiretime=504000000 #jwt.refresh-token.expiretime=4000 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=${DATA_SOURCE_URL} From 772fb038c7c5e4be9a8c3f0d3dd98fee3032b98b Mon Sep 17 00:00:00 2001 From: yulmam <70622601+yulmam@users.noreply.github.com> Date: Mon, 5 Aug 2024 10:22:16 +0900 Subject: [PATCH 110/197] =?UTF-8?q?refactor=20:=20user=20=EC=84=9C?= =?UTF-8?q?=EB=B9=84=EC=8A=A4=20=EB=A6=AC=ED=8E=99=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../board/controller/BoardController.java | 2 +- .../edufocus/board/entity/vo/Board.java | 3 +- .../edufocus/board/entity/vo/Comment.java | 2 +- .../board/service/BoardServiceImpl.java | 6 +- .../edufocus/lecture/entity/Lecture.java | 2 +- .../lecture/service/LectureServiceImpl.java | 4 +- .../com/edufocus/edufocus/qna/entity/Qna.java | 3 +- .../edufocus/qna/service/QnaServiceImpl.java | 5 +- .../edufocus/quiz/entity/QuizSet.java | 3 +- .../quiz/service/QuizSetServiceImpl.java | 2 +- .../registration/entity/Registration.java | 2 +- .../service/RegistrationServiceImpl.java | 5 +- .../edufocus/report/entity/vo/Report.java | 2 +- .../report/service/ReportServiceImpl.java | 2 +- .../user/controller/UserController.java | 132 +++++++----------- .../user/intercepter/JWTInterceptor.java | 2 - .../edufocus/user/model/entity/UserRole.java | 5 - .../user/model/entity/{ => dto}/InfoDto.java | 2 +- .../entity/{ => dto}/MemberChangeDto.java | 2 +- .../model/entity/{ => dto}/PasswordDto.java | 4 +- .../model/entity/dto/RefreshTokenDto.java | 11 ++ .../user/model/entity/dto/RequestJoinDto.java | 17 +++ .../user/model/entity/{ => vo}/User.java | 13 +- .../user/model/entity/vo/UserRole.java | 5 + .../exception/GlobalExceptionHandler.java | 4 + .../user/model/repository/UserRepository.java | 2 +- .../user/model/service/UserService.java | 34 +++-- .../user/model/service/UserServiceImpl.java | 51 ++++--- .../edufocus/edufocus/user/util/JWTUtil.java | 2 +- .../{model/entity => util}/PasswordUtils.java | 2 +- .../edufocus/video/controller/Controller.java | 6 +- .../edufocus/ws/entity/vo/ChatUser.java | 2 +- .../edufocus/ws/service/ChatServiceImpl.java | 2 +- .../model/service/UserServiceImplTest.java | 6 +- 34 files changed, 171 insertions(+), 176 deletions(-) delete mode 100644 backend/src/main/java/com/edufocus/edufocus/user/model/entity/UserRole.java rename backend/src/main/java/com/edufocus/edufocus/user/model/entity/{ => dto}/InfoDto.java (70%) rename backend/src/main/java/com/edufocus/edufocus/user/model/entity/{ => dto}/MemberChangeDto.java (84%) rename backend/src/main/java/com/edufocus/edufocus/user/model/entity/{ => dto}/PasswordDto.java (69%) create mode 100644 backend/src/main/java/com/edufocus/edufocus/user/model/entity/dto/RefreshTokenDto.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/user/model/entity/dto/RequestJoinDto.java rename backend/src/main/java/com/edufocus/edufocus/user/model/entity/{ => vo}/User.java (76%) create mode 100644 backend/src/main/java/com/edufocus/edufocus/user/model/entity/vo/UserRole.java rename backend/src/main/java/com/edufocus/edufocus/user/{model/entity => util}/PasswordUtils.java (89%) diff --git a/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java b/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java index ef8abb7..5bd154d 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java @@ -129,7 +129,7 @@ public class BoardController { @ExceptionHandler() - public ResponseEntity NoContentException(Exception exception){ + public ResponseEntity NoContentException(Exception e){ return new ResponseEntity<>(HttpStatus.NO_CONTENT); } } diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java index 6b283ec..0277c7c 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java @@ -4,7 +4,7 @@ package com.edufocus.edufocus.board.entity.vo; import com.edufocus.edufocus.board.entity.dto.ResponseBoardDetailDto; import com.edufocus.edufocus.board.entity.dto.ResponseBoardSummaryDto; import com.edufocus.edufocus.lecture.entity.Lecture; -import com.edufocus.edufocus.user.model.entity.User; +import com.edufocus.edufocus.user.model.entity.vo.User; import com.fasterxml.jackson.annotation.JsonAutoDetect; import jakarta.persistence.*; import lombok.*; @@ -13,7 +13,6 @@ import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; import java.time.LocalDateTime; -import java.time.LocalTime; import java.util.List; @Entity diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java index 667f678..ef311a0 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java @@ -2,7 +2,7 @@ package com.edufocus.edufocus.board.entity.vo; import com.edufocus.edufocus.board.entity.dto.ResponseCommentDto; -import com.edufocus.edufocus.user.model.entity.User; +import com.edufocus.edufocus.user.model.entity.vo.User; import com.fasterxml.jackson.annotation.JsonAutoDetect; import jakarta.persistence.*; import lombok.AllArgsConstructor; diff --git a/backend/src/main/java/com/edufocus/edufocus/board/service/BoardServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/board/service/BoardServiceImpl.java index 4e047f9..f471fed 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/service/BoardServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/service/BoardServiceImpl.java @@ -8,7 +8,7 @@ import com.edufocus.edufocus.board.repository.BoardRepository; import com.edufocus.edufocus.board.repository.CommentRepository; import com.edufocus.edufocus.lecture.entity.Lecture; import com.edufocus.edufocus.lecture.repository.LectureRepository; -import com.edufocus.edufocus.user.model.entity.User; +import com.edufocus.edufocus.user.model.entity.vo.User; import com.edufocus.edufocus.user.model.repository.UserRepository; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; @@ -72,7 +72,7 @@ public class BoardServiceImpl implements BoardService { @Transactional public void updateBoard(long boardId, RequestBoardUpdateDto requestBoardUpdateDto) { - Board board = boardRepository.findById(boardId).orElseThrow(IllegalArgumentException::new); + Board board = boardRepository.getReferenceById(boardId); board.setTitle(requestBoardUpdateDto.getTitle()); board.setContent(requestBoardUpdateDto.getContent()); @@ -113,7 +113,7 @@ public class BoardServiceImpl implements BoardService { @Transactional public void updateComment(long commentId, RequestCommentDto requestCommentDto) { - Comment comment = commentRepository.findById(commentId).orElseThrow(IllegalArgumentException::new); + Comment comment = commentRepository.getReferenceById(commentId); comment.setContent(requestCommentDto.getContent()); diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java index f74d97f..5db4488 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java @@ -1,7 +1,7 @@ package com.edufocus.edufocus.lecture.entity; -import com.edufocus.edufocus.user.model.entity.User; +import com.edufocus.edufocus.user.model.entity.vo.User; import jakarta.persistence.*; import lombok.*; diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java index b97246c..2fd8dd0 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java @@ -6,8 +6,8 @@ import com.edufocus.edufocus.lecture.repository.LectureRepository; import com.edufocus.edufocus.registration.entity.Registration; import com.edufocus.edufocus.registration.entity.RegistrationStatus; import com.edufocus.edufocus.registration.repository.RegistrationRepository; -import com.edufocus.edufocus.user.model.entity.User; -import com.edufocus.edufocus.user.model.entity.UserRole; +import com.edufocus.edufocus.user.model.entity.vo.User; +import com.edufocus.edufocus.user.model.entity.vo.UserRole; import com.edufocus.edufocus.user.model.repository.UserRepository; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java b/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java index 993484e..901afd3 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java @@ -1,10 +1,9 @@ package com.edufocus.edufocus.qna.entity; import com.edufocus.edufocus.lecture.entity.Lecture; -import com.edufocus.edufocus.user.model.entity.User; +import com.edufocus.edufocus.user.model.entity.vo.User; import jakarta.persistence.*; import lombok.*; -import org.checkerframework.checker.units.qual.C; import java.util.Date; diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java index d583346..80ea7ae 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java @@ -6,19 +6,16 @@ import com.edufocus.edufocus.qna.entity.Qna; import com.edufocus.edufocus.qna.entity.QnaRequestDto; import com.edufocus.edufocus.qna.entity.QnaResponseDto; import com.edufocus.edufocus.qna.repository.QnaRepository; -import com.edufocus.edufocus.user.model.entity.User; +import com.edufocus.edufocus.user.model.entity.vo.User; import com.edufocus.edufocus.user.model.repository.UserRepository; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; -import lombok.Setter; 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.stereotype.Service; import java.sql.SQLException; -import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Optional; diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSet.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSet.java index 816638c..90d13ac 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSet.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSet.java @@ -1,12 +1,11 @@ package com.edufocus.edufocus.quiz.entity; -import com.edufocus.edufocus.user.model.entity.User; +import com.edufocus.edufocus.user.model.entity.vo.User; import com.fasterxml.jackson.annotation.JsonBackReference; import com.fasterxml.jackson.annotation.JsonManagedReference; import jakarta.persistence.*; import lombok.*; -import java.util.ArrayList; import java.util.List; @Entity diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java index c5c68c8..0c76d30 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java @@ -2,7 +2,7 @@ package com.edufocus.edufocus.quiz.service; import com.edufocus.edufocus.quiz.entity.*; import com.edufocus.edufocus.quiz.repository.QuizSetRepository; -import com.edufocus.edufocus.user.model.entity.User; +import com.edufocus.edufocus.user.model.entity.vo.User; import com.edufocus.edufocus.user.model.repository.UserRepository; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/entity/Registration.java b/backend/src/main/java/com/edufocus/edufocus/registration/entity/Registration.java index 38cfe35..88af158 100644 --- a/backend/src/main/java/com/edufocus/edufocus/registration/entity/Registration.java +++ b/backend/src/main/java/com/edufocus/edufocus/registration/entity/Registration.java @@ -1,7 +1,7 @@ package com.edufocus.edufocus.registration.entity; import com.edufocus.edufocus.lecture.entity.Lecture; -import com.edufocus.edufocus.user.model.entity.User; +import com.edufocus.edufocus.user.model.entity.vo.User; import jakarta.persistence.*; import lombok.*; diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java index 4e69660..26ac48d 100644 --- a/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java @@ -1,13 +1,12 @@ package com.edufocus.edufocus.registration.service; -import com.edufocus.edufocus.lecture.entity.Lecture; import com.edufocus.edufocus.lecture.repository.LectureRepository; import com.edufocus.edufocus.registration.entity.Registration; import com.edufocus.edufocus.registration.entity.RegistrationSearchResponse; import com.edufocus.edufocus.registration.entity.RegistrationStatus; import com.edufocus.edufocus.registration.repository.RegistrationRepository; -import com.edufocus.edufocus.user.model.entity.User; -import com.edufocus.edufocus.user.model.entity.UserRole; +import com.edufocus.edufocus.user.model.entity.vo.User; +import com.edufocus.edufocus.user.model.entity.vo.UserRole; import com.edufocus.edufocus.user.model.repository.UserRepository; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java index 6165358..a9e2222 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java @@ -1,7 +1,7 @@ package com.edufocus.edufocus.report.entity.vo; import com.edufocus.edufocus.quiz.entity.QuizSet; -import com.edufocus.edufocus.user.model.entity.User; +import com.edufocus.edufocus.user.model.entity.vo.User; import jakarta.persistence.*; import lombok.*; diff --git a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java index 1d6449d..104e626 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java @@ -11,7 +11,7 @@ import com.edufocus.edufocus.report.entity.dto.AnswerInput; import com.edufocus.edufocus.report.entity.vo.Report; import com.edufocus.edufocus.report.entity.dto.ReportRequset; import com.edufocus.edufocus.report.repository.ReportRepository; -import com.edufocus.edufocus.user.model.entity.User; +import com.edufocus.edufocus.user.model.entity.vo.User; import com.edufocus.edufocus.user.model.repository.UserRepository; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; diff --git a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java index 55306a5..c077839 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java @@ -1,12 +1,10 @@ package com.edufocus.edufocus.user.controller; -import com.edufocus.edufocus.user.model.entity.InfoDto; -import com.edufocus.edufocus.user.model.entity.PasswordDto; -import com.edufocus.edufocus.user.model.entity.User; -import com.edufocus.edufocus.user.model.exception.ExpriedTokenException; +import com.edufocus.edufocus.user.model.entity.dto.InfoDto; +import com.edufocus.edufocus.user.model.entity.dto.PasswordDto; +import com.edufocus.edufocus.user.model.entity.dto.RequestJoinDto; +import com.edufocus.edufocus.user.model.entity.vo.User; import com.edufocus.edufocus.user.model.exception.InvalidTokenException; -import com.edufocus.edufocus.user.model.exception.RefreshTokenExpiredException; -import com.edufocus.edufocus.user.model.exception.UnAuthorizedException; import com.edufocus.edufocus.user.model.service.UserService; import com.edufocus.edufocus.user.util.JWTUtil; import io.swagger.v3.oas.annotations.Operation; @@ -16,7 +14,6 @@ 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.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -35,34 +32,30 @@ public class UserController { private final JWTUtil jwtUtil; @PostMapping("/join") - public ResponseEntity join(@RequestBody User user) throws Exception { - userService.join(user); + public ResponseEntity join(@RequestBody RequestJoinDto requestJoinDto){ + + if(userService.isUserIdExist(requestJoinDto.getUserId())) + return new ResponseEntity<>("아이디가 중복 됐습니다.", HttpStatus.CONFLICT); + + userService.join(requestJoinDto); + return ResponseEntity.ok("User registered successfully"); } -// @PostMapping("/findpassword/{user_id}") -// public ResponseEntity findpassword(@PathVariable("user_id") Long user_id) throws Exception { -// userService.userCheck(user_id); -// return ResponseEntity.ok("임시 비밀번호가 이메일로 전송되었습니다."); -// } @PutMapping("/updateinfo") - public ResponseEntity updateUserInfo( - @RequestBody InfoDto infoDto, HttpServletRequest request) { - try { - String token = request.getHeader("Authorization"); - Long userId = Long.parseLong(jwtUtil.getUserId(token)); - userService.changeUserInfo(infoDto, userId); - return ResponseEntity.ok("User info updated successfully"); - } catch (Exception e) { - return ResponseEntity.badRequest().body(e.getMessage()); - } + public ResponseEntity updateUserInfo(@RequestBody InfoDto infoDto, HttpServletRequest request) { + String token = request.getHeader("Authorization"); + Long userId = Long.parseLong(jwtUtil.getUserId(token)); + + userService.changeUserInfo(infoDto, userId); + + return new ResponseEntity<>(HttpStatus.OK); } // 비밀번호 변경 @PutMapping("/updatepassword") public ResponseEntity updatePassword(@RequestBody PasswordDto passwordDto, HttpServletRequest request) { - try - { + try { String token = request.getHeader("Authorization"); Long userId = Long.parseLong(jwtUtil.getUserId(token)); @@ -72,79 +65,50 @@ public class UserController { return ResponseEntity.badRequest().body(e.getMessage()); } } + @Operation(summary = "로그인", description = "아이디와 비밀번호를 이용하여 로그인 처리.") @PostMapping("/login") public ResponseEntity> login( @RequestBody @Parameter(description = "로그인 시 필요한 회원정보(아이디, 비밀번호).", required = true) User user, HttpServletRequest request, HttpServletResponse response) { - String token = request.getHeader("Authorization"); - Map resultMap = new HashMap<>(); HttpStatus status = HttpStatus.ACCEPTED; - try { - User loginUser = userService.login(user); - if (loginUser != null) { + User loginUser = userService.login(user); + if (loginUser == null) + return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); + + String accessToken = jwtUtil.createAccessToken(String.valueOf(loginUser.getId())); + String refreshToken = jwtUtil.createRefreshToken(String.valueOf(loginUser.getId())); + + userService.saveRefreshToken(loginUser.getId(), refreshToken); + + resultMap.put("name",loginUser.getName()); + resultMap.put("role",loginUser.getRole()); + resultMap.put("access-token", accessToken); + + setCookies(response, refreshToken); + + status = HttpStatus.CREATED; - String accessToken = jwtUtil.createAccessToken(String.valueOf(loginUser.getId())); - String refreshToken = jwtUtil.createRefreshToken(String.valueOf(loginUser.getId())); - - userService.saveRefreshToken(loginUser.getId(), refreshToken); - - resultMap.put("name",loginUser.getName()); - resultMap.put("role",loginUser.getRole()); - resultMap.put("access-token", accessToken); - - Cookie refreshCookie = new Cookie("refresh-token", refreshToken); - refreshCookie.setPath("/"); - refreshCookie.setHttpOnly(true); - refreshCookie.setSecure(true); // HTTPS에서만 전송되도록 설정 - //refreshCookie.setSameSite(Cookie.SameSite.NONE); // Cross-Origin 요청에 대해 모두 전송 - //refreshCookie.setSameSite("None"); // Cross-Origin 요청에 대해 모두 전송 - - String cookieHeader = String.format("refresh-token=%s; Path=/; HttpOnly; Secure; SameSite=None", refreshToken); - response.setHeader("Set-Cookie", cookieHeader); - - // refreshCookie.setSameSite("None"); // Cross-Origin 요청에 대해 모두 전송 - response.addCookie(refreshCookie); - - status = HttpStatus.CREATED; - } else { - resultMap.put("message", "아이디 또는 패스워드를 확인해 주세요."); - status = HttpStatus.UNAUTHORIZED; - } - } catch (Exception e) { - resultMap.put("message", e.getMessage()); - status = HttpStatus.INTERNAL_SERVER_ERROR; - } return new ResponseEntity<>(resultMap, status); } @PostMapping("/logout") public ResponseEntity removeToken(HttpServletRequest request) { - Map resultMap = new HashMap<>(); - HttpStatus status = HttpStatus.ACCEPTED; - try { + String token = request.getHeader("Authorization"); + Long userId = Long.parseLong(jwtUtil.getUserId(token)); - String token = request.getHeader("Authorization"); - Long userId = Long.parseLong(jwtUtil.getUserId(token)); + userService.deleteRefreshToken(userId); - userService.deleteRefreshToken(userId); - status = HttpStatus.OK; - } catch (Exception e) { - log.error("로그아웃 실패 : {}", e); - resultMap.put("message", e.getMessage()); - status = HttpStatus.UNAUTHORIZED; - } - return new ResponseEntity>(resultMap, status); + return new ResponseEntity>(HttpStatus.ACCEPTED); } @Operation(summary = "Access Token 재발급", description = "만료된 access token 을 재발급 받는다.") @PostMapping("/refresh") - public ResponseEntity refreshToken(HttpServletRequest request,HttpServletResponse response) - throws Exception { + public ResponseEntity refreshToken(HttpServletRequest request,HttpServletResponse response) { Cookie[] cookies = request.getCookies(); String token = null; if (cookies != null) { @@ -178,11 +142,7 @@ public class UserController { userService.saveRefreshToken(userId,refreshToken); - Cookie refreshCookie = new Cookie("refresh-token", refreshToken); - refreshCookie.setPath("/"); - refreshCookie.setHttpOnly(true); - refreshCookie.setSecure(true); - response.addCookie(refreshCookie); + setCookies(response, refreshToken); return new ResponseEntity>(resultMap, HttpStatus.CREATED); } @@ -215,7 +175,13 @@ public class UserController { } - + private void setCookies(HttpServletResponse response, String refreshToken){ + Cookie refreshCookie = new Cookie("refresh-token", refreshToken); + refreshCookie.setPath("/"); + refreshCookie.setHttpOnly(true); + refreshCookie.setSecure(true); + response.addCookie(refreshCookie); + } } \ No newline at end of file diff --git a/backend/src/main/java/com/edufocus/edufocus/user/intercepter/JWTInterceptor.java b/backend/src/main/java/com/edufocus/edufocus/user/intercepter/JWTInterceptor.java index c1c6003..55ec605 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/intercepter/JWTInterceptor.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/intercepter/JWTInterceptor.java @@ -26,9 +26,7 @@ public class JWTInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler){ final String token = request.getHeader(HEADER_AUTH); - jwtUtil.checkToken(token); - return true; } } \ No newline at end of file diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/UserRole.java b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/UserRole.java deleted file mode 100644 index 48f8cc1..0000000 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/UserRole.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.edufocus.edufocus.user.model.entity; - -public enum UserRole { - STUDENT,ADMIN -} diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/InfoDto.java b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/dto/InfoDto.java similarity index 70% rename from backend/src/main/java/com/edufocus/edufocus/user/model/entity/InfoDto.java rename to backend/src/main/java/com/edufocus/edufocus/user/model/entity/dto/InfoDto.java index 52b1f08..6c67119 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/InfoDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/dto/InfoDto.java @@ -1,4 +1,4 @@ -package com.edufocus.edufocus.user.model.entity; +package com.edufocus.edufocus.user.model.entity.dto; import lombok.Getter; import lombok.Setter; diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/MemberChangeDto.java b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/dto/MemberChangeDto.java similarity index 84% rename from backend/src/main/java/com/edufocus/edufocus/user/model/entity/MemberChangeDto.java rename to backend/src/main/java/com/edufocus/edufocus/user/model/entity/dto/MemberChangeDto.java index 5576813..3f965c6 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/MemberChangeDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/dto/MemberChangeDto.java @@ -1,4 +1,4 @@ -package com.edufocus.edufocus.user.model.entity; +package com.edufocus.edufocus.user.model.entity.dto; import lombok.AllArgsConstructor; import lombok.Data; diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/PasswordDto.java b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/dto/PasswordDto.java similarity index 69% rename from backend/src/main/java/com/edufocus/edufocus/user/model/entity/PasswordDto.java rename to backend/src/main/java/com/edufocus/edufocus/user/model/entity/dto/PasswordDto.java index a77f73e..c2f6790 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/PasswordDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/dto/PasswordDto.java @@ -1,13 +1,11 @@ -package com.edufocus.edufocus.user.model.entity; +package com.edufocus.edufocus.user.model.entity.dto; -import lombok.Generated; import lombok.Getter; import lombok.Setter; @Setter @Getter public class PasswordDto { - String currentPassword; String newPassword; String newPasswordCheck; diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/dto/RefreshTokenDto.java b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/dto/RefreshTokenDto.java new file mode 100644 index 0000000..8f22764 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/dto/RefreshTokenDto.java @@ -0,0 +1,11 @@ +package com.edufocus.edufocus.user.model.entity.dto; + + +import lombok.AllArgsConstructor; +import lombok.Setter; + +@Setter +@AllArgsConstructor +public class RefreshTokenDto { + private String Token; +} diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/dto/RequestJoinDto.java b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/dto/RequestJoinDto.java new file mode 100644 index 0000000..6983d90 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/dto/RequestJoinDto.java @@ -0,0 +1,17 @@ +package com.edufocus.edufocus.user.model.entity.dto; + +import com.edufocus.edufocus.user.model.entity.vo.UserRole; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +@AllArgsConstructor +public class RequestJoinDto { + private String userId; + private String email; + private String password; + private UserRole role; + private String name; +} diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/User.java b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/vo/User.java similarity index 76% rename from backend/src/main/java/com/edufocus/edufocus/user/model/entity/User.java rename to backend/src/main/java/com/edufocus/edufocus/user/model/entity/vo/User.java index f0403f8..02e409e 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/User.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/vo/User.java @@ -1,21 +1,14 @@ -package com.edufocus.edufocus.user.model.entity; +package com.edufocus.edufocus.user.model.entity.vo; -import com.edufocus.edufocus.qna.entity.Qna; import jakarta.persistence.*; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Pattern; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import org.checkerframework.checker.units.qual.A; - -import java.util.ArrayList; -import java.util.List; +import lombok.*; @Entity @Getter @Setter +@Builder @NoArgsConstructor @AllArgsConstructor public class User { diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/vo/UserRole.java b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/vo/UserRole.java new file mode 100644 index 0000000..41602af --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/entity/vo/UserRole.java @@ -0,0 +1,5 @@ +package com.edufocus.edufocus.user.model.entity.vo; + +public enum UserRole { + STUDENT,ADMIN +} diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/exception/GlobalExceptionHandler.java b/backend/src/main/java/com/edufocus/edufocus/user/model/exception/GlobalExceptionHandler.java index b3b2608..fed4131 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/exception/GlobalExceptionHandler.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/exception/GlobalExceptionHandler.java @@ -19,4 +19,8 @@ public class GlobalExceptionHandler { return new ResponseEntity<>(e.getMessage(), HttpStatus.UNAUTHORIZED); } + @ExceptionHandler(UserException.class) + public ResponseEntity handleUserException(UserException e) { + return new ResponseEntity<>(e.getMessage(), HttpStatus.FORBIDDEN);//수정해야함 + } } \ No newline at end of file diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/repository/UserRepository.java b/backend/src/main/java/com/edufocus/edufocus/user/model/repository/UserRepository.java index 026c4aa..10e9f87 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/repository/UserRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/repository/UserRepository.java @@ -1,6 +1,6 @@ package com.edufocus.edufocus.user.model.repository; -import com.edufocus.edufocus.user.model.entity.User; +import com.edufocus.edufocus.user.model.entity.vo.User; import jakarta.transaction.Transactional; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java index 9252869..7b2d101 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java @@ -1,18 +1,28 @@ package com.edufocus.edufocus.user.model.service; -import com.edufocus.edufocus.user.model.entity.InfoDto; -import com.edufocus.edufocus.user.model.entity.PasswordDto; -import com.edufocus.edufocus.user.model.entity.User; +import com.edufocus.edufocus.user.model.entity.dto.InfoDto; +import com.edufocus.edufocus.user.model.entity.dto.PasswordDto; +import com.edufocus.edufocus.user.model.entity.dto.RequestJoinDto; +import com.edufocus.edufocus.user.model.entity.vo.User; public interface UserService { - void join(User user) throws Exception; - User login(User user) throws Exception; - void saveRefreshToken(Long id, String refreshToken) throws Exception; - String getRefreshToken(Long id) throws Exception; - void deleteRefreshToken(Long id) throws Exception; - User userInfo(Long id) throws Exception; - String getUserName(Long id) throws Exception; - void changeUserInfo(InfoDto infoDto,Long id) throws Exception; - void changePassword(PasswordDto passwordDto,Long id) throws Exception; + void join(RequestJoinDto requestJoinDto); + User login(User user); + + void saveRefreshToken(Long id, String refreshToken); + + String getRefreshToken(Long id); + + void deleteRefreshToken(Long id); + + User userInfo(Long id); + + String getUserName(Long id); + + void changeUserInfo(InfoDto infoDto,Long id); + + void changePassword(PasswordDto passwordDto,Long id); + + boolean isUserIdExist(String userId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java index c6301c0..77fd4ca 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java @@ -1,19 +1,17 @@ package com.edufocus.edufocus.user.model.service; -import com.edufocus.edufocus.user.model.entity.*; +import com.edufocus.edufocus.user.model.entity.dto.InfoDto; +import com.edufocus.edufocus.user.model.entity.dto.PasswordDto; +import com.edufocus.edufocus.user.util.PasswordUtils; +import com.edufocus.edufocus.user.model.entity.dto.RequestJoinDto; +import com.edufocus.edufocus.user.model.entity.vo.User; import com.edufocus.edufocus.user.model.exception.UserException; import com.edufocus.edufocus.user.model.repository.UserRepository; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.mail.SimpleMailMessage; -import org.springframework.mail.javamail.JavaMailSender; import org.springframework.stereotype.Service; -import java.sql.SQLException; -import java.util.HashMap; -import java.util.Map; import java.util.Optional; @Service @@ -25,16 +23,20 @@ public class UserServiceImpl implements UserService { private final UserRepository userRepository; - public void join(User user) + public void join(RequestJoinDto requestJoinDto) { - System.out.println(user.getRole().getClass()); - user.setPassword(PasswordUtils.hashPassword(user.getPassword())); - + User user = User.builder() + .userId(requestJoinDto.getUserId()) + .email(requestJoinDto.getEmail()) + .password(PasswordUtils.hashPassword(requestJoinDto.getPassword())) + .role(requestJoinDto.getRole()) + .name(requestJoinDto.getName()) + .build(); userRepository.save(user); } - public User login(User user) throws SQLException { + public User login(User user){ Optional findUser = userRepository.findByUserId(user.getUserId()); if (findUser.isEmpty()) { @@ -65,14 +67,13 @@ public class UserServiceImpl implements UserService { @Override - public String getUserName(Long id) throws Exception { - + public String getUserName(Long id){ return userRepository.findById(id).get().getName(); } @Override - public void changeUserInfo(InfoDto infoDto, Long id) throws Exception { + public void changeUserInfo(InfoDto infoDto, Long id){ User user = userRepository.findById(id).orElseThrow(IllegalArgumentException::new); @@ -87,18 +88,18 @@ public class UserServiceImpl implements UserService { @Override - public void changePassword(PasswordDto passwordDto, Long id) throws Exception { + public void changePassword(PasswordDto passwordDto, Long id){ User user = userRepository.findById(id).orElse(null); if (user == null) { - throw new Exception("User not found"); + throw new UserException("User not found"); } if (!PasswordUtils.checkPassword(passwordDto.getCurrentPassword(), user.getPassword())) { - throw new Exception("Current password is incorrect"); + throw new UserException("Current password is incorrect"); } else { if (!passwordDto.getNewPassword().equals(passwordDto.getNewPasswordCheck())) { - throw new Exception("New password confirmation does not match"); + throw new UserException("New password confirmation does not match"); } } @@ -106,6 +107,12 @@ public class UserServiceImpl implements UserService { user.setPassword(PasswordUtils.hashPassword(passwordDto.getNewPassword())); userRepository.save(user); } + + @Override + public boolean isUserIdExist(String userId) { + return userRepository.findByUserId(userId).isPresent(); + } + public String getTempPassword() { char[] charSet = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}; @@ -119,17 +126,17 @@ public class UserServiceImpl implements UserService { return str; } @Override - public void saveRefreshToken(Long id, String refreshToken) throws Exception { + public void saveRefreshToken(Long id, String refreshToken){ userRepository.saveRefreshToken(id, refreshToken); } @Override - public String getRefreshToken(Long id) throws Exception { + public String getRefreshToken(Long id){ return userRepository.getRefreshToken(id); } @Override - public void deleteRefreshToken(Long id) throws Exception { + public void deleteRefreshToken(Long id){ userRepository.deleteRefreshToken(id); } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/util/JWTUtil.java b/backend/src/main/java/com/edufocus/edufocus/user/util/JWTUtil.java index e7d4f8c..c6630d9 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/util/JWTUtil.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/util/JWTUtil.java @@ -79,7 +79,7 @@ public class JWTUtil { Map value = claims.getBody(); log.info("value : {}", value); return (String) value.get("id"); - }catch ( ExpiredJwtException e) + }catch (ExpiredJwtException e) { System.out.println("expired token"); throw new ExpriedTokenException(); diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/PasswordUtils.java b/backend/src/main/java/com/edufocus/edufocus/user/util/PasswordUtils.java similarity index 89% rename from backend/src/main/java/com/edufocus/edufocus/user/model/entity/PasswordUtils.java rename to backend/src/main/java/com/edufocus/edufocus/user/util/PasswordUtils.java index aa61d1f..1abbd98 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/entity/PasswordUtils.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/util/PasswordUtils.java @@ -1,4 +1,4 @@ -package com.edufocus.edufocus.user.model.entity; +package com.edufocus.edufocus.user.util; import org.mindrot.jbcrypt.BCrypt; public class PasswordUtils { diff --git a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java index a94758e..83c19f8 100644 --- a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java +++ b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java @@ -4,13 +4,11 @@ import java.util.Map; import java.util.Random; import com.edufocus.edufocus.lecture.entity.Lecture; -import com.edufocus.edufocus.lecture.entity.LectureDetailResponse; import com.edufocus.edufocus.lecture.repository.LectureRepository; import com.edufocus.edufocus.lecture.service.LectureService; -import com.edufocus.edufocus.registration.entity.RegistrationStatus; import com.edufocus.edufocus.registration.service.RegistrationService; -import com.edufocus.edufocus.user.model.entity.User; -import com.edufocus.edufocus.user.model.entity.UserRole; +import com.edufocus.edufocus.user.model.entity.vo.User; +import com.edufocus.edufocus.user.model.entity.vo.UserRole; import com.edufocus.edufocus.user.model.repository.UserRepository; import com.edufocus.edufocus.user.model.service.UserService; import com.edufocus.edufocus.user.util.JWTUtil; diff --git a/backend/src/main/java/com/edufocus/edufocus/ws/entity/vo/ChatUser.java b/backend/src/main/java/com/edufocus/edufocus/ws/entity/vo/ChatUser.java index 7a1d8d6..1a2a06a 100644 --- a/backend/src/main/java/com/edufocus/edufocus/ws/entity/vo/ChatUser.java +++ b/backend/src/main/java/com/edufocus/edufocus/ws/entity/vo/ChatUser.java @@ -1,7 +1,7 @@ package com.edufocus.edufocus.ws.entity.vo; import com.edufocus.edufocus.lecture.entity.Lecture; -import com.edufocus.edufocus.user.model.entity.User; +import com.edufocus.edufocus.user.model.entity.vo.User; import com.edufocus.edufocus.ws.entity.dto.ChatUserDto; import jakarta.persistence.*; import lombok.*; diff --git a/backend/src/main/java/com/edufocus/edufocus/ws/service/ChatServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/ws/service/ChatServiceImpl.java index 7cc7866..29071cf 100644 --- a/backend/src/main/java/com/edufocus/edufocus/ws/service/ChatServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/ws/service/ChatServiceImpl.java @@ -3,7 +3,7 @@ package com.edufocus.edufocus.ws.service; import com.edufocus.edufocus.lecture.entity.Lecture; import com.edufocus.edufocus.lecture.repository.LectureRepository; -import com.edufocus.edufocus.user.model.entity.User; +import com.edufocus.edufocus.user.model.entity.vo.User; import com.edufocus.edufocus.user.model.repository.UserRepository; import com.edufocus.edufocus.ws.entity.dto.ChatUserDto; import com.edufocus.edufocus.ws.entity.vo.ChatUser; diff --git a/backend/src/test/java/com/edufocus/edufocus/user/model/service/UserServiceImplTest.java b/backend/src/test/java/com/edufocus/edufocus/user/model/service/UserServiceImplTest.java index 2986703..a399bd8 100644 --- a/backend/src/test/java/com/edufocus/edufocus/user/model/service/UserServiceImplTest.java +++ b/backend/src/test/java/com/edufocus/edufocus/user/model/service/UserServiceImplTest.java @@ -1,8 +1,8 @@ //package com.edufocus.edufocus.user.model.service; // -//import com.edufocus.edufocus.user.model.entity.PasswordDto; -//import com.edufocus.edufocus.user.model.entity.User; -//import com.edufocus.edufocus.user.model.entity.UserRole; +//import com.edufocus.edufocus.user.model.entity.dto.PasswordDto; +//import com.edufocus.edufocus.user.model.entity.vo.User; +//import com.edufocus.edufocus.user.model.entity.vo.UserRole; //import com.edufocus.edufocus.user.model.exception.UserException; //import com.edufocus.edufocus.user.model.repository.UserRepository; //import org.junit.jupiter.api.BeforeEach; From f29ca87ee740f132753252b87d020e3e397a3e24 Mon Sep 17 00:00:00 2001 From: kgc91747 Date: Mon, 5 Aug 2024 14:35:13 +0900 Subject: [PATCH 111/197] =?UTF-8?q?feat:=20Quiz=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../quiz/controller/QuizController.java | 48 ++++++++++++- .../quiz/entity/QuizSetUpdateRequest.java | 20 ++++++ .../quiz/entity/QuizUpdateRequest.java | 21 ++++++ .../quiz/repository/ChoiceRepository.java | 7 ++ .../edufocus/quiz/service/QuizService.java | 7 ++ .../quiz/service/QuizServiceImpl.java | 67 +++++++++++++++++++ .../edufocus/quiz/service/QuizSetService.java | 2 +- .../quiz/service/QuizSetServiceImpl.java | 5 +- .../src/main/resources/application.properties | 2 +- 9 files changed, 175 insertions(+), 4 deletions(-) create mode 100644 backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSetUpdateRequest.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizUpdateRequest.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/quiz/repository/ChoiceRepository.java diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java b/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java index 3a27228..8109765 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java @@ -13,7 +13,9 @@ import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; +import java.util.HashMap; import java.util.List; +import java.util.Map; @RestController @RequestMapping("/quiz") @@ -42,13 +44,57 @@ public class QuizController { return new ResponseEntity<>(HttpStatus.CREATED); } - @GetMapping("/{quizsetId}") + @GetMapping("/student/{quizsetId}") public ResponseEntity getQuizzes(@PathVariable Long quizsetId) { QuizSetResponse quizSet = quizSetService.findQuizSetResponse(quizsetId); return new ResponseEntity<>(quizSet, HttpStatus.OK); } + @GetMapping("/teacher/{quizsetId}") + public ResponseEntity getQuizzesIncludeAnswer(@RequestHeader("Authorization") String accessToken, @PathVariable Long quizsetId) { + long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); + + QuizSet quizSet = quizSetService.findQuizSet(quizsetId); + if (quizSet.getUser().getId() != userId) { + return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); + } + + return new ResponseEntity<>(quizSet, HttpStatus.OK); + } + + @PutMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + public ResponseEntity updateQuizSet(@RequestHeader("Authorization") String accessToken, @RequestPart QuizSetUpdateRequest quizSetUpdateRequest + , @RequestPart(value = "images", required = false) List images) throws IOException { + long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); + + QuizSet quizset = quizSetService.findQuizSet(quizSetUpdateRequest.getId()); + if (userId != quizset.getUser().getId()) { + return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); + } + + quizSetService.updateQuizSet(quizSetUpdateRequest.getId(), quizSetUpdateRequest.getTitle()); + + Map quizUpdatedCheckMap = new HashMap<>(); + for (Quiz quiz : quizset.getQuizzes()) { + quizUpdatedCheckMap.put(quiz.getId(), false); + } + int imageIdx = 0; + for (QuizUpdateRequest quizUpdateRequest : quizSetUpdateRequest.getQuizzes()) { + quizService.updateQuiz(quizUpdateRequest, images.get(imageIdx++)); + + quizUpdatedCheckMap.put(quizUpdateRequest.getId(), true); + } + + for (Long quizId : quizUpdatedCheckMap.keySet()) { + if (!quizUpdatedCheckMap.get(quizId)) { + quizService.removeQuiz(quizId); + } + } + + return new ResponseEntity<>(HttpStatus.OK); + } + @DeleteMapping("/{quizsetId}") public ResponseEntity deleteQuizSet(@RequestHeader("Authorization") String accessToken, @PathVariable long quizsetId) { long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSetUpdateRequest.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSetUpdateRequest.java new file mode 100644 index 0000000..da4c5f9 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSetUpdateRequest.java @@ -0,0 +1,20 @@ +package com.edufocus.edufocus.quiz.entity; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class QuizSetUpdateRequest { + + private long id; + + private String title; + + private List quizzes; + +} diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizUpdateRequest.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizUpdateRequest.java new file mode 100644 index 0000000..f4cdc4f --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizUpdateRequest.java @@ -0,0 +1,21 @@ +package com.edufocus.edufocus.quiz.entity; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class QuizUpdateRequest { + + private long id; + + private String question; + + private String answer; + + private List choices; +} diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/repository/ChoiceRepository.java b/backend/src/main/java/com/edufocus/edufocus/quiz/repository/ChoiceRepository.java new file mode 100644 index 0000000..b32ec5f --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/repository/ChoiceRepository.java @@ -0,0 +1,7 @@ +package com.edufocus.edufocus.quiz.repository; + +import com.edufocus.edufocus.quiz.entity.Choice; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ChoiceRepository extends JpaRepository { +} diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizService.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizService.java index 92014a2..adda12f 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizService.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizService.java @@ -1,7 +1,9 @@ package com.edufocus.edufocus.quiz.service; +import com.edufocus.edufocus.quiz.entity.Quiz; import com.edufocus.edufocus.quiz.entity.QuizCreateRequest; import com.edufocus.edufocus.quiz.entity.QuizSet; +import com.edufocus.edufocus.quiz.entity.QuizUpdateRequest; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; @@ -13,4 +15,9 @@ public interface QuizService { void createQuiz(QuizSet quizSet, QuizCreateRequest quizCreateRequest, MultipartFile quizImage) throws IOException; + void updateQuiz(QuizUpdateRequest quizUpdateRequest, MultipartFile quizImage) throws IOException; + + Quiz findQuiz(long quizId); + + void removeQuiz(long quizId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizServiceImpl.java index fbb42e5..0225c8b 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizServiceImpl.java @@ -2,6 +2,7 @@ package com.edufocus.edufocus.quiz.service; import com.edufocus.edufocus.global.properties.ImagePathProperties; import com.edufocus.edufocus.quiz.entity.*; +import com.edufocus.edufocus.quiz.repository.ChoiceRepository; import com.edufocus.edufocus.quiz.repository.QuizRepository; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; @@ -12,6 +13,7 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.NoSuchElementException; import java.util.UUID; @@ -24,6 +26,8 @@ public class QuizServiceImpl implements QuizService { private final QuizRepository quizRepository; + private final ChoiceRepository choiceRepository; + @Override public void createQuiz(QuizSet quizSet, QuizCreateRequest quizCreateRequest, MultipartFile quizImage) throws IOException { Quiz quiz = Quiz.builder() @@ -66,4 +70,67 @@ public class QuizServiceImpl implements QuizService { } + @Override + public void updateQuiz(QuizUpdateRequest quizUpdateRequest, MultipartFile quizImage) throws IOException { + Quiz quiz = quizRepository.findById(quizUpdateRequest.getId()).orElseThrow(NoSuchElementException::new); + + quiz.setQuestion(quizUpdateRequest.getQuestion()); + quiz.setAnswer(quizUpdateRequest.getAnswer()); + + quiz.getChoices().clear(); + quizRepository.save(quiz); + + for (ChoiceCreateRequest choiceCreateRequest : quizUpdateRequest.getChoices()) { + Choice choice = Choice.builder() + .quiz(quiz) + .num(choiceCreateRequest.getNum()) + .content(choiceCreateRequest.getContent()) + .build(); + + quiz.addChoice(choice); + } + + if (quizImage != null && !quizImage.isEmpty()) { + if (quiz.getImage() != null) { + File file = new File(quiz.getImage()); + file.delete(); + } + + String uid = UUID.randomUUID().toString(); + + String imagePath = imagePathProperties.getPath(); + + File checkPathFile = new File(imagePath); + if (!checkPathFile.exists()) { + checkPathFile.mkdirs(); + } + + File savingImage = new File(imagePath + "/" + uid + "_" + quizImage.getOriginalFilename()); + quizImage.transferTo(savingImage.toPath()); + String savePath = savingImage.toPath().toString(); + + quiz.setImage(savePath); + } + + quizRepository.save(quiz); + } + + @Override + public Quiz findQuiz(long quizId) { + return quizRepository.findById(quizId).orElseThrow(NoSuchElementException::new); + } + + @Override + public void removeQuiz(long quizId) { + Quiz quiz = quizRepository.findById(quizId).orElseThrow(NoSuchElementException::new); + + String image = quiz.getImage(); + if (image != null) { + File file = new File(quiz.getImage()); + file.delete(); + quiz.setImage(null); + } + + quizRepository.delete(quiz); + } } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetService.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetService.java index 4b25ebc..a8c3fa0 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetService.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetService.java @@ -12,7 +12,7 @@ public interface QuizSetService { QuizSet createQuizSet(long userId, String title); - void updateQuizSet(QuizSet quizSet); + void updateQuizSet(long quizSetId, String title); boolean deleteQuizSet(long userId, long quizSetId); diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java index c5c68c8..419c0c6 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java @@ -34,8 +34,11 @@ public class QuizSetServiceImpl implements QuizSetService { } @Override - public void updateQuizSet(QuizSet quizSet) { + public void updateQuizSet(long quizSetId, String title) { + QuizSet quizSet = quizSetRepository.findById(quizSetId).orElseThrow(NoSuchElementException::new); + quizSet.setTitle(title); + quizSetRepository.save(quizSet); } @Override diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 714d1c9..a888094 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -17,7 +17,7 @@ jwt.salt=${SALT} # Access Token ?? ?? (??? ??) #jwt.access-token.expiretime=3600000 -jwt.access-token.expiretime=300 +jwt.access-token.expiretime=360000 # Refresh Token ?? ?? (??? ??) jwt.refresh-token.expiretime=50400000 From 09d86ebcdf2a6cc146c8e003bdf32f27f5165ebf Mon Sep 17 00:00:00 2001 From: kgc91747 Date: Mon, 5 Aug 2024 15:35:11 +0900 Subject: [PATCH 112/197] =?UTF-8?q?feat:=20Lecture=20=EB=82=B4=20=EA=B0=95?= =?UTF-8?q?=EC=9D=98=20=EC=A1=B0=ED=9A=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lecture/service/LectureServiceImpl.java | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java index 125bad0..98f6535 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java @@ -205,12 +205,14 @@ public class LectureServiceImpl implements LectureService { for (Registration registration : registrationList) { Lecture lecture = registration.getLecture(); - LectureSearchResponse lectureSearchResponse = LectureSearchResponse.builder() - .id(lecture.getId()) - .title(lecture.getTitle()) - .image(lecture.getImage()).build(); + if (registration.getStatus() == RegistrationStatus.ACCEPTED) { + LectureSearchResponse lectureSearchResponse = LectureSearchResponse.builder() + .id(lecture.getId()) + .title(lecture.getTitle()) + .image(lecture.getImage()).build(); - myLectureList.add(lectureSearchResponse); + myLectureList.add(lectureSearchResponse); + } } } @@ -233,16 +235,13 @@ public class LectureServiceImpl implements LectureService { } - Lecture l; - l = lecture.get(); - if(l.isOnline()) - { - l.setOnline(false); - } - else - { - l.setOnline(true); - } + Lecture l; + l = lecture.get(); + if (l.isOnline()) { + l.setOnline(false); + } else { + l.setOnline(true); + } lectureRepository.save(l); From 6a6852b4f53aad184080ecd3756f6f129c8e337a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Mon, 5 Aug 2024 16:07:37 +0900 Subject: [PATCH 113/197] =?UTF-8?q?feat:=20=EC=96=B4=EB=93=9C=EB=AF=BC,?= =?UTF-8?q?=ED=95=99=EC=83=9D=20=EB=B0=A9=20=EC=9E=85=EC=9E=A5=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../quiz/controller/QuizController.java | 2 +- .../report/service/ReportServiceImpl.java | 26 +++++------ .../user/config/WebConfiguration.java | 10 ++-- .../edufocus/video/controller/Controller.java | 46 +++++++------------ 4 files changed, 36 insertions(+), 48 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java b/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java index c85822a..8edb05e 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java @@ -28,7 +28,7 @@ public class QuizController { private final JWTUtil jwtUtil; @PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE) - public ResponseEntity createQuizSet(@RequestHeader("Authorization") String accessToken, @RequestPart QuizSetCreateRequest quizSetCreateRequest + public ResponseEntity createQuizSet(@RequestHeader("Authzation") String accessToken, @RequestPart QuizSetCreateRequest quizSetCreateRequest , @RequestPart(value = "images", required = false) List images) throws IOException { long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); diff --git a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java index 104e626..a9e119e 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java @@ -41,34 +41,33 @@ public class ReportServiceImpl implements ReportService { QuizSet quizSet = quizSetService.findQuizSet(reportRequset.getQuizsetId()); - + System.out.println(quizSet.toString()); List quizList = quizSet.getQuizzes(); List answerInputList = reportRequset.getAnswerInputList(); Report report = new Report(); Long reportNum = report.getId(); - int allCount= quizList.size(); - int correctCount =0 ; + int allCount = quizList.size(); + int correctCount = 0; - User testuser= userRepository.findById(reportRequset.getUserId()).orElse(null); + User testuser = userRepository.findById(reportRequset.getUserId()).orElse(null); for (Quiz quiz : quizList) { for (AnswerInput answerInput : answerInputList) { if (quiz.getId() == answerInput.getAnswerinputID()) { - if(quiz.getAnswer().equals(answerInput.getAnswer())) { + if (quiz.getAnswer().equals(answerInput.getAnswer())) { correctCount++; Answer answer = Answer.builder() - .userAnswer(answerInput.getAnswer()) + .userAnswer(answerInput.getAnswer()) .isCorrect(true) .report(report) .quiz(quiz) .build(); - } - else{ + } else { Answer answer = Answer.builder() .userAnswer(answerInput.getAnswer()) .isCorrect(false) @@ -77,7 +76,6 @@ public class ReportServiceImpl implements ReportService { .build(); - } } @@ -86,11 +84,11 @@ public class ReportServiceImpl implements ReportService { } report = Report.builder() - .user(testuser) - .quizSet(quizSet) - .allCount(allCount) - .correctCount(correctCount) - .testAt(new Date()).build(); + .user(testuser) + .quizSet(quizSet) + .allCount(allCount) + .correctCount(correctCount) + .testAt(new Date()).build(); ReportResponse reportResponse = ReportResponse.builder() .quizesetId(quizSet.getId()) .userId(testuser.getId()) diff --git a/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java b/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java index 0d8851c..0972d21 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java @@ -21,13 +21,14 @@ public class WebConfiguration implements WebMvcConfigurer { this.jwtInterceptor = jwtInterceptor; } -// + + // @Override public void addCorsMappings(CorsRegistry registry) { registry .addMapping("/**") - .allowedOriginPatterns("https://i11a701.p.ssafy.io/","https://localhost:5173", "http://localhost:5173", "http://localhost:4173","http://localhost:5080","http://192.168.*.*:5173") - .allowedMethods("GET","POST",HttpMethod.GET.name(), HttpMethod.POST.name(), HttpMethod.PUT.name(), + .allowedOriginPatterns("https://i11a701.p.ssafy.io/", "https://localhost:5173", "http://localhost:5173", "http://localhost:4173", "http://localhost:5080", "http://192.168.*.*:5173") + .allowedMethods("GET", "POST", HttpMethod.GET.name(), HttpMethod.POST.name(), HttpMethod.PUT.name(), HttpMethod.DELETE.name(), HttpMethod.HEAD.name(), HttpMethod.OPTIONS.name(), HttpMethod.PATCH.name()) .allowCredentials(true) @@ -41,10 +42,11 @@ public class WebConfiguration implements WebMvcConfigurer { registry.addResourceHandler("/img/**").addResourceLocations("classpath:/static/assets/img/"); registry.addResourceHandler("/*.html**").addResourceLocations("classpath:/static/"); } + @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(jwtInterceptor) .addPathPatterns("/**") // 모든 경로에 대해 인터셉터 적용 - .excludePathPatterns("/v3/api-docs/**","/swagger-resources/**","/webjars/**","/swagger-ui/**","/auth/**", "/board/**", "/user/**","/lecture/**","/qna/**", "/quiz/**","/video/**","/registration/**"); // 인증 없이 접근 가능한 경로 설정 + .excludePathPatterns("/v3/api-docs/**", "/swagger-resources/**", "/webjars/**", "/swagger-ui/**", "/auth/**", "/board/**", "/user/**", "/lecture/**", "/qna/**", "/quiz/**", "/video/**", "/registration/**", "/report/**"); // 인증 없이 접근 가능한 경로 설정 } } \ No newline at end of file diff --git a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java index 6bfa21a..6dbba66 100644 --- a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java +++ b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java @@ -93,36 +93,9 @@ public class Controller { } - } + } else if (findUser.getRole() == UserRole.ADMIN) {//&& lecture.isOnline() ) { - return ResponseEntity.ok(Map.of("token", null)); - - } - - - @PostMapping(value = "/makeroom/{lecture_id}") - public ResponseEntity> makeRoom(@PathVariable("lecture_id") Long id, HttpServletRequest request) throws Exception { - String userToken = request.getHeader("Authorization"); - - - Long userId = Long.parseLong(jwtUtil.getUserId(userToken)); - User findUser = userRepository.findById(userId).orElse(null); - Lecture lecture = lectureRepository.findById(id).orElse(null); - - - String roomName = lecture.getTitle(); - String participantName = userService.getUserName(userId); - System.out.println(participantName); - - AccessToken token = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); - - - if (findUser.getRole() == UserRole.ADMIN) {//&& lecture.isOnline() ) { - - - videoSertvice.startOnline(userId, id); - IdentityData identityData = new IdentityData(participantName, "강사"); String jsonIdentity = serializeIdentityData(identityData); @@ -137,11 +110,26 @@ public class Controller { } - return ResponseEntity.ok(Map.of("token", null)); } + + @PostMapping(value = "/makeroom/{lecture_id}") + public ResponseEntity> makeRoom(@PathVariable("lecture_id") Long id, HttpServletRequest request) throws Exception { + String userToken = request.getHeader("Authorization"); + + + Long userId = Long.parseLong(jwtUtil.getUserId(userToken)); + + + videoSertvice.startOnline(userId, id); + + + return ResponseEntity.ok(Map.of("token", " ")); + + } + @PostMapping(value = "/livekit/webhook", consumes = "application/webhook+json") public ResponseEntity receiveWebhook(@RequestHeader("Authorization") String authHeader, @RequestBody String body) { WebhookReceiver webhookReceiver = new WebhookReceiver(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); From 77a5aed6ece8c810e0bf64eb913614339d441085 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Mon, 5 Aug 2024 16:16:14 +0900 Subject: [PATCH 114/197] =?UTF-8?q?feat:=20joinromm=20=EC=88=98=EC=A0=95:?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/video/controller/Controller.java | 17 ++++++++++------- .../edufocus/video/service/VideoSertvice.java | 2 ++ .../video/service/VideoServiceImpl.java | 15 +++++++++++++++ 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java index 6dbba66..0996fa4 100644 --- a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java +++ b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java @@ -95,18 +95,21 @@ public class Controller { } else if (findUser.getRole() == UserRole.ADMIN) {//&& lecture.isOnline() ) { - - IdentityData identityData = new IdentityData(participantName, "강사"); - String jsonIdentity = serializeIdentityData(identityData); + // 자신의 강의인지 확인하기 + if (videoSertvice.checkAdmin(userId, id)) { + IdentityData identityData = new IdentityData(participantName, "강사"); + String jsonIdentity = serializeIdentityData(identityData); - token.setIdentity(jsonIdentity); - token.setName(participantName); + token.setIdentity(jsonIdentity); + token.setName(participantName); - token.addGrants(new RoomJoin(true), new RoomName(roomName), new RoomCreate(true)); + token.addGrants(new RoomJoin(true), new RoomName(roomName), new RoomCreate(true)); - return ResponseEntity.ok(Map.of("token", token.toJwt())); + return ResponseEntity.ok(Map.of("token", token.toJwt())); + } + } diff --git a/backend/src/main/java/com/edufocus/edufocus/video/service/VideoSertvice.java b/backend/src/main/java/com/edufocus/edufocus/video/service/VideoSertvice.java index 71b34d9..f45cdc4 100644 --- a/backend/src/main/java/com/edufocus/edufocus/video/service/VideoSertvice.java +++ b/backend/src/main/java/com/edufocus/edufocus/video/service/VideoSertvice.java @@ -10,4 +10,6 @@ public interface VideoSertvice { boolean isRoomAccessible(Long lectureId, Long userId); + boolean checkAdmin(Long userId, Long lectureId); + } diff --git a/backend/src/main/java/com/edufocus/edufocus/video/service/VideoServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/video/service/VideoServiceImpl.java index cf9714e..055e133 100644 --- a/backend/src/main/java/com/edufocus/edufocus/video/service/VideoServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/video/service/VideoServiceImpl.java @@ -2,6 +2,7 @@ package com.edufocus.edufocus.video.service; import com.edufocus.edufocus.lecture.entity.Lecture; import com.edufocus.edufocus.lecture.entity.LectureDetailResponse; +import com.edufocus.edufocus.lecture.entity.LectureSearchResponse; import com.edufocus.edufocus.lecture.service.LectureService; import com.edufocus.edufocus.registration.entity.RegistrationStatus; import com.edufocus.edufocus.registration.service.RegistrationService; @@ -10,6 +11,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import java.sql.SQLException; +import java.util.List; @Service @Transactional @@ -46,4 +48,17 @@ public class VideoServiceImpl implements VideoSertvice { return false; } } + + @Override + public boolean checkAdmin(Long userId, Long lectureId) { + // 강의가 내 강의인지 확인 + List lecture = lectureService.findMyLecture(userId); + + for (LectureSearchResponse l : lecture) { + if (l.getId() == lectureId) { + return true; + } + } + return false; + } } From 1a7e6c1bba7785d7ac2c1a9be218c3ecba73e485 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Mon, 5 Aug 2024 16:33:53 +0900 Subject: [PATCH 115/197] =?UTF-8?q?feat:=20joinroom=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/lecture/service/LectureServiceImpl.java | 4 +--- .../edufocus/edufocus/video/controller/Controller.java | 9 ++++++--- .../edufocus/video/service/VideoServiceImpl.java | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java index 98f6535..29e26ad 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java @@ -237,9 +237,7 @@ public class LectureServiceImpl implements LectureService { Lecture l; l = lecture.get(); - if (l.isOnline()) { - l.setOnline(false); - } else { + if (l.isOnline() == false) { l.setOnline(true); } diff --git a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java index 0996fa4..cc7bb6c 100644 --- a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java +++ b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java @@ -121,13 +121,16 @@ public class Controller { @PostMapping(value = "/makeroom/{lecture_id}") public ResponseEntity> makeRoom(@PathVariable("lecture_id") Long id, HttpServletRequest request) throws Exception { String userToken = request.getHeader("Authorization"); - - Long userId = Long.parseLong(jwtUtil.getUserId(userToken)); + User findUser = userRepository.findById(userId).orElse(null); + if (findUser.getRole() == UserRole.ADMIN) { - videoSertvice.startOnline(userId, id); + videoSertvice.startOnline(userId, id); + + + } return ResponseEntity.ok(Map.of("token", " ")); diff --git a/backend/src/main/java/com/edufocus/edufocus/video/service/VideoServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/video/service/VideoServiceImpl.java index 055e133..110de11 100644 --- a/backend/src/main/java/com/edufocus/edufocus/video/service/VideoServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/video/service/VideoServiceImpl.java @@ -36,7 +36,7 @@ public class VideoServiceImpl implements VideoSertvice { public boolean isRoomAccessible(Long lectureId, Long userId) { - LectureDetailResponse lecture = lectureService.findLectureById(userId, userId); + LectureDetailResponse lecture = lectureService.findLectureById(userId, lectureId); RegistrationStatus registrationStatus = registrationService.getStatus(userId, lectureId); From 38c747e7d49059da0843c9acb1fd9ae6bd489aa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Mon, 5 Aug 2024 16:45:56 +0900 Subject: [PATCH 116/197] =?UTF-8?q?feat:=20=EB=B0=A9=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lecture/service/LectureService.java | 6 +++-- .../lecture/service/LectureServiceImpl.java | 22 ++++++++++++++++++- .../edufocus/video/controller/Controller.java | 20 +++++++++++++++++ .../video/service/VideoServiceImpl.java | 4 ++-- 4 files changed, 47 insertions(+), 5 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java index fac837d..fded3dc 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureService.java @@ -22,14 +22,16 @@ public interface LectureService { List findAllLecture(); String getUserStatus(Long userId, Lecture lecture); - + LectureDetailResponse findLectureById(Long userId, long lectureId); List findMyLecture(long userId); Lecture findLectureByTitle(String title); - void changeState(Long lectureId); + void startClass(Long lectureId); + + void stopClass(Long lectureId); boolean getState(Long lectureId); diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java index 29e26ad..c434f54 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java @@ -225,7 +225,7 @@ public class LectureServiceImpl implements LectureService { } @Override - public void changeState(Long id) { + public void startClass(Long id) { Optional lecture = lectureRepository.findById(id); @@ -245,6 +245,26 @@ public class LectureServiceImpl implements LectureService { lectureRepository.save(l); } + @Override + public void stopClass(Long id) { + Optional lecture = lectureRepository.findById(id); + + + if (!lecture.isPresent()) { + throw new RuntimeException("Lecture not found with id: " + id); + + } + + Lecture l; + l = lecture.get(); + if (l.isOnline()) { + l.setOnline(false); + } + + + lectureRepository.save(l); + } + @Override public boolean getState(Long lectureId) { diff --git a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java index cc7bb6c..efb4a64 100644 --- a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java +++ b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java @@ -136,6 +136,26 @@ public class Controller { } + + @PostMapping(value = "/deleteroom/{lecture_id}") + public ResponseEntity> deleteRooom(@PathVariable("lecture_id") Long id, HttpServletRequest request) throws Exception { + String userToken = request.getHeader("Authorization"); + Long userId = Long.parseLong(jwtUtil.getUserId(userToken)); + + User findUser = userRepository.findById(userId).orElse(null); + if (findUser.getRole() == UserRole.ADMIN) { + + + videoSertvice.startOnline(userId, id); + + + } + + return ResponseEntity.ok(Map.of("token", " ")); + + } + + @PostMapping(value = "/livekit/webhook", consumes = "application/webhook+json") public ResponseEntity receiveWebhook(@RequestHeader("Authorization") String authHeader, @RequestBody String body) { WebhookReceiver webhookReceiver = new WebhookReceiver(LIVEKIT_API_KEY, LIVEKIT_API_SECRET); diff --git a/backend/src/main/java/com/edufocus/edufocus/video/service/VideoServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/video/service/VideoServiceImpl.java index 110de11..ce948a3 100644 --- a/backend/src/main/java/com/edufocus/edufocus/video/service/VideoServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/video/service/VideoServiceImpl.java @@ -24,12 +24,12 @@ public class VideoServiceImpl implements VideoSertvice { @Override public void startOnline(Long userId, Long lectureId) throws SQLException { - lectureService.changeState(lectureId); + lectureService.startClass(lectureId); } @Override public void stopOnline(Long userId, Long lectureId) throws SQLException { - lectureService.changeState(lectureId); + lectureService.startClass(lectureId); } @Override From 3c5909926b8f924f983a9e3a9a47e90136ee9ccf Mon Sep 17 00:00:00 2001 From: kgc91747 Date: Mon, 5 Aug 2024 16:59:14 +0900 Subject: [PATCH 117/197] =?UTF-8?q?feat:=20Quiz=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=EC=8B=9C=20=EB=AC=B8=EC=A0=9C=20=EC=B6=94=EA=B0=80=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...b76-54cb-42ad-a53e-04691c6401ba_testimg3.jpg | Bin 0 -> 8567 bytes ...d22e-43a3-8fde-69bace73ee6a_lectureImage.jpg | Bin 0 -> 8567 bytes ...a03-017a-4d3c-9c5c-aa0a2ada53f9_testimg1.jpg | Bin 0 -> 8567 bytes ...af1a-4f48-885c-30bf45d63778_lectureImage.jpg | Bin 0 -> 8567 bytes ...5108-41ad-96b9-9d25d5353c73_lectureImage.jpg | Bin 0 -> 8567 bytes .../quiz/controller/QuizController.java | 16 +++++++++++++--- .../edufocus/quiz/entity/QuizCreateRequest.java | 2 ++ .../edufocus/quiz/entity/QuizUpdateRequest.java | 2 +- 8 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 backend/backend/src/main/resources/images/30d65b76-54cb-42ad-a53e-04691c6401ba_testimg3.jpg create mode 100644 backend/backend/src/main/resources/images/427dc7fc-d22e-43a3-8fde-69bace73ee6a_lectureImage.jpg create mode 100644 backend/backend/src/main/resources/images/45b6ea03-017a-4d3c-9c5c-aa0a2ada53f9_testimg1.jpg create mode 100644 backend/backend/src/main/resources/images/7fd1090b-af1a-4f48-885c-30bf45d63778_lectureImage.jpg create mode 100644 backend/backend/src/main/resources/images/a69e91c4-5108-41ad-96b9-9d25d5353c73_lectureImage.jpg diff --git a/backend/backend/src/main/resources/images/30d65b76-54cb-42ad-a53e-04691c6401ba_testimg3.jpg b/backend/backend/src/main/resources/images/30d65b76-54cb-42ad-a53e-04691c6401ba_testimg3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c53ac5e358df846b8d20f1928bd0860aa4302f24 GIT binary patch literal 8567 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 createQuizSet(@RequestHeader("Authzation") String accessToken, @RequestPart QuizSetCreateRequest quizSetCreateRequest + public ResponseEntity createQuizSet(@RequestHeader("Authorization") String accessToken, @RequestPart QuizSetCreateRequest quizSetCreateRequest , @RequestPart(value = "images", required = false) List images) throws IOException { long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); @@ -81,9 +81,19 @@ public class QuizController { } int imageIdx = 0; for (QuizUpdateRequest quizUpdateRequest : quizSetUpdateRequest.getQuizzes()) { - quizService.updateQuiz(quizUpdateRequest, images.get(imageIdx++)); + if (quizUpdateRequest.getId() == null) { + QuizCreateRequest quizCreateRequest = QuizCreateRequest.builder() + .question(quizUpdateRequest.getQuestion()) + .answer(quizUpdateRequest.getAnswer()) + .choices(quizUpdateRequest.getChoices()) + .build(); - quizUpdatedCheckMap.put(quizUpdateRequest.getId(), true); + quizService.createQuiz(quizset, quizCreateRequest, images.get(imageIdx++)); + } else { + quizService.updateQuiz(quizUpdateRequest, images.get(imageIdx++)); + + quizUpdatedCheckMap.put(quizUpdateRequest.getId(), true); + } } for (Long quizId : quizUpdatedCheckMap.keySet()) { diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizCreateRequest.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizCreateRequest.java index 9ac60bd..d2a254d 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizCreateRequest.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizCreateRequest.java @@ -1,11 +1,13 @@ package com.edufocus.edufocus.quiz.entity; import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; import java.util.List; +@Builder @Getter @NoArgsConstructor @AllArgsConstructor diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizUpdateRequest.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizUpdateRequest.java index f4cdc4f..7fa153d 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizUpdateRequest.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizUpdateRequest.java @@ -11,7 +11,7 @@ import java.util.List; @AllArgsConstructor public class QuizUpdateRequest { - private long id; + private Long id; private String question; From cb28eb2cd230b943e6637adcd95f1803170808b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Mon, 5 Aug 2024 17:12:11 +0900 Subject: [PATCH 118/197] =?UTF-8?q?feat:=20joinroom,makeroom,deleteroom=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/video/controller/Controller.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java index efb4a64..88ff332 100644 --- a/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java +++ b/backend/src/main/java/com/edufocus/edufocus/video/controller/Controller.java @@ -88,7 +88,7 @@ public class Controller { return ResponseEntity.ok(Map.of("token", token.toJwt())); } else { - return ResponseEntity.status(HttpStatus.BAD_REQUEST) + return ResponseEntity.status(HttpStatus.NOT_FOUND) .body(Map.of("error", "방에 들어갈 수 없습니다.")); } @@ -108,6 +108,8 @@ public class Controller { return ResponseEntity.ok(Map.of("token", token.toJwt())); + } else { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(Map.of("error", "자신의 강의가 아닙니다.")); } @@ -124,12 +126,15 @@ public class Controller { Long userId = Long.parseLong(jwtUtil.getUserId(userToken)); User findUser = userRepository.findById(userId).orElse(null); - if (findUser.getRole() == UserRole.ADMIN) { + if (findUser.getRole() == UserRole.ADMIN && videoSertvice.checkAdmin(userId, id)) { videoSertvice.startOnline(userId, id); + } else { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(Map.of("error", "들어갈수없는 계정입니다")); + } return ResponseEntity.ok(Map.of("token", " ")); @@ -146,7 +151,7 @@ public class Controller { if (findUser.getRole() == UserRole.ADMIN) { - videoSertvice.startOnline(userId, id); + videoSertvice.stopOnline(userId, id); } From 31faa12d83935b693890da9f7e5a1bfac39c0f2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Tue, 6 Aug 2024 13:18:26 +0900 Subject: [PATCH 119/197] =?UTF-8?q?feat:=20=ED=80=B4=EC=A6=88=20=EC=B1=84?= =?UTF-8?q?=EC=A0=90=20=EA=B8=B0=EB=8A=A5=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...1dfad-83fc-4665-b2d6-5edeada95134_bono.jpg | Bin 0 -> 18333 bytes ...84650-3544-45e3-9677-f8187b8ceb34_bono.jpg | Bin 0 -> 18333 bytes .../edufocus/report/entity/vo/Answer.java | 5 +- .../report/service/ReportServiceImpl.java | 73 ++++++++++-------- .../src/main/resources/application.properties | 2 +- 5 files changed, 43 insertions(+), 37 deletions(-) create mode 100644 backend/${IMAGE_PATH}/5871dfad-83fc-4665-b2d6-5edeada95134_bono.jpg create mode 100644 backend/${IMAGE_PATH}/7da84650-3544-45e3-9677-f8187b8ceb34_bono.jpg diff --git a/backend/${IMAGE_PATH}/5871dfad-83fc-4665-b2d6-5edeada95134_bono.jpg b/backend/${IMAGE_PATH}/5871dfad-83fc-4665-b2d6-5edeada95134_bono.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c936434d25b4e01743eb3516d58e920c82857cdc GIT binary patch literal 18333 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 literal 0 HcmV?d00001 diff --git a/backend/${IMAGE_PATH}/7da84650-3544-45e3-9677-f8187b8ceb34_bono.jpg b/backend/${IMAGE_PATH}/7da84650-3544-45e3-9677-f8187b8ceb34_bono.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c936434d25b4e01743eb3516d58e920c82857cdc GIT binary patch literal 18333 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 literal 0 HcmV?d00001 diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Answer.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Answer.java index 1437626..929adb0 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Answer.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Answer.java @@ -17,16 +17,15 @@ public class Answer { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; - private String userAnswer; private boolean isCorrect; @ManyToOne - @JoinColumn(name= "report_id") + @JoinColumn(name = "report_id") private Report report; @ManyToOne - @JoinColumn(name= "quiz_id") + @JoinColumn(name = "quiz_id") private Quiz quiz; diff --git a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java index a9e119e..cb5dd56 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java @@ -10,6 +10,7 @@ import com.edufocus.edufocus.report.entity.vo.Answer; import com.edufocus.edufocus.report.entity.dto.AnswerInput; import com.edufocus.edufocus.report.entity.vo.Report; import com.edufocus.edufocus.report.entity.dto.ReportRequset; +import com.edufocus.edufocus.report.repository.AnswerRepository; import com.edufocus.edufocus.report.repository.ReportRepository; import com.edufocus.edufocus.user.model.entity.vo.User; import com.edufocus.edufocus.user.model.repository.UserRepository; @@ -18,6 +19,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import java.sql.SQLException; +import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -32,6 +34,7 @@ public class ReportServiceImpl implements ReportService { private final ReportRepository reportRepository; private final QuizRepository quizRepository; + private final AnswerRepository answerRepository; private final AnswerService answerService; private final UserRepository userRepository; @@ -39,56 +42,59 @@ public class ReportServiceImpl implements ReportService { @Override public ReportResponse grading(ReportRequset reportRequset) throws SQLException { - QuizSet quizSet = quizSetService.findQuizSet(reportRequset.getQuizsetId()); - System.out.println(quizSet.toString()); List quizList = quizSet.getQuizzes(); List answerInputList = reportRequset.getAnswerInputList(); - Report report = new Report(); + List answerList = new ArrayList<>(); - Long reportNum = report.getId(); int allCount = quizList.size(); int correctCount = 0; User testuser = userRepository.findById(reportRequset.getUserId()).orElse(null); - for (Quiz quiz : quizList) { - for (AnswerInput answerInput : answerInputList) { - if (quiz.getId() == answerInput.getAnswerinputID()) { - - if (quiz.getAnswer().equals(answerInput.getAnswer())) { - correctCount++; - - Answer answer = Answer.builder() - .userAnswer(answerInput.getAnswer()) - .isCorrect(true) - .report(report) - .quiz(quiz) - .build(); - - } else { - Answer answer = Answer.builder() - .userAnswer(answerInput.getAnswer()) - .isCorrect(false) - .report(report) - .quiz(quiz) - .build(); - - - } - - } - + for (int idx = 0; idx < answerInputList.size(); idx++) { + Quiz quiz = quizList.get(idx); + AnswerInput inputAnswer = answerInputList.get(idx); + Answer answer; + if (quiz.getAnswer().equals(inputAnswer.getAnswer())) { + correctCount++; + answer = Answer.builder() + .userAnswer(inputAnswer.getAnswer()) + .isCorrect(true) + .report(null) + .quiz(quiz) + .build(); + } else { + answer = Answer.builder() + .userAnswer(inputAnswer.getAnswer()) + .isCorrect(false) + .report(null) + .quiz(quiz) + .build(); } + answerList.add(answer); } - report = Report.builder() + + Report report = Report.builder() .user(testuser) .quizSet(quizSet) .allCount(allCount) .correctCount(correctCount) - .testAt(new Date()).build(); + .testAt(new Date()) + .build(); + + + reportRepository.save(report); + + + for (Answer answer : answerList) { + answer.setReport(report); + answerRepository.save(answer); + } + + ReportResponse reportResponse = ReportResponse.builder() .quizesetId(quizSet.getId()) .userId(testuser.getId()) @@ -100,4 +106,5 @@ public class ReportServiceImpl implements ReportService { return reportResponse; } + } diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index aa22dc0..68e5d54 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -21,7 +21,7 @@ spring.datasource.username=${USER_NAME} spring.datasource.password=${USER_PASSWORD} spring.mvc.pathmatch.matching-strategy=ant_path_matcher spring.jpa.database=mysql -spring.jpa.hibernate.ddl-auto=update +spring.jpa.hibernate.ddl-auto=create spring.jpa.show-sql=true management.endpoints.web.exposure.include=health,info management.endpoint.health.show-details=always From 62b690b2051b1f2bbb94084db8a45554a4644aa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Tue, 6 Aug 2024 13:24:31 +0900 Subject: [PATCH 120/197] feat: update -> create --- backend/src/main/resources/application.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 68e5d54..aa22dc0 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -21,7 +21,7 @@ spring.datasource.username=${USER_NAME} spring.datasource.password=${USER_PASSWORD} spring.mvc.pathmatch.matching-strategy=ant_path_matcher spring.jpa.database=mysql -spring.jpa.hibernate.ddl-auto=create +spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true management.endpoints.web.exposure.include=health,info management.endpoint.health.show-details=always From 57acdf06d61beb394e724dcca6427285906f1c1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Tue, 6 Aug 2024 13:38:27 +0900 Subject: [PATCH 121/197] =?UTF-8?q?db=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/main/resources/application.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index aa22dc0..2a34560 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -22,7 +22,7 @@ spring.datasource.password=${USER_PASSWORD} spring.mvc.pathmatch.matching-strategy=ant_path_matcher spring.jpa.database=mysql spring.jpa.hibernate.ddl-auto=update -spring.jpa.show-sql=true +spring.jpa.show-sql=true management.endpoints.web.exposure.include=health,info management.endpoint.health.show-details=always spring.rabbitmq.host=${RABBITMQ_HOST} From 6925c50349089be9f99a4f87fbef85a016b3a19d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Tue, 6 Aug 2024 14:01:22 +0900 Subject: [PATCH 122/197] =?UTF-8?q?feat:=20deleteroom=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/edufocus/edufocus/video/service/VideoServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/video/service/VideoServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/video/service/VideoServiceImpl.java index ce948a3..81c604c 100644 --- a/backend/src/main/java/com/edufocus/edufocus/video/service/VideoServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/video/service/VideoServiceImpl.java @@ -29,7 +29,7 @@ public class VideoServiceImpl implements VideoSertvice { @Override public void stopOnline(Long userId, Long lectureId) throws SQLException { - lectureService.startClass(lectureId); + lectureService.stopClass(lectureId); } @Override From a14ba8b04b12f35246c5f80a93c0313d0cd57abc Mon Sep 17 00:00:00 2001 From: yulmam <70622601+yulmam@users.noreply.github.com> Date: Tue, 6 Aug 2024 14:40:54 +0900 Subject: [PATCH 123/197] =?UTF-8?q?refactor=20:=20summary=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/edufocus/edufocus/board/entity/vo/Board.java | 2 +- .../edufocus/edufocus/board/controller/BoardControllerTest.java | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 backend/src/test/java/com/edufocus/edufocus/board/controller/BoardControllerTest.java diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java index 0277c7c..98df363 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java @@ -70,7 +70,7 @@ public class Board { public ResponseBoardDetailDto makeDetailDto(){ return ResponseBoardDetailDto.builder() .id(id) - .name(user.getEmail()) + .name(user.getName()) .title(title) .content(content) .viewCount(viewCount) diff --git a/backend/src/test/java/com/edufocus/edufocus/board/controller/BoardControllerTest.java b/backend/src/test/java/com/edufocus/edufocus/board/controller/BoardControllerTest.java new file mode 100644 index 0000000..e531369 --- /dev/null +++ b/backend/src/test/java/com/edufocus/edufocus/board/controller/BoardControllerTest.java @@ -0,0 +1,2 @@ +package com.edufocus.edufocus.board.controller;public class BoardControllerTest { +} From d8b236960faefd44ef8b9cff07ab10707bc5ce1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Tue, 6 Aug 2024 16:32:45 +0900 Subject: [PATCH 124/197] =?UTF-8?q?feat:=20report=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../report/controller/ReportController.java | 45 +++++-- .../report/entity/dto/AnswerInput.java | 3 +- .../entity/dto/ReportDetailResponseDto.java | 21 ++++ .../entity/dto/ReportListResponseDto.java | 14 +++ .../report/entity/dto/ReportRequset.java | 4 +- .../report/repository/AnswerRepository.java | 6 +- .../report/repository/ReportRepository.java | 4 + .../report/service/ReportService.java | 10 +- .../report/service/ReportServiceImpl.java | 114 +++++++++++++++++- .../user/controller/UserController.java | 18 +-- 10 files changed, 207 insertions(+), 32 deletions(-) create mode 100644 backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportDetailResponseDto.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportListResponseDto.java diff --git a/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java b/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java index f07149f..bbae94c 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java @@ -1,37 +1,62 @@ package com.edufocus.edufocus.report.controller; +import com.edufocus.edufocus.report.entity.dto.ReportDetailResponseDto; +import com.edufocus.edufocus.report.entity.dto.ReportListResponseDto; import com.edufocus.edufocus.report.entity.dto.ReportResponse; import com.edufocus.edufocus.report.entity.vo.Report; import com.edufocus.edufocus.report.entity.dto.ReportRequset; import com.edufocus.edufocus.report.service.ReportService; +import com.edufocus.edufocus.user.util.JWTUtil; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -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; +import org.springframework.web.bind.annotation.*; import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; @RestController @RequestMapping("/report") @Slf4j @RequiredArgsConstructor -public class ReportController{ +public class ReportController { private final ReportService reportService; + private final JWTUtil jwtUtil; + @PostMapping("/submit/{quizsetId}") + public ResponseEntity submit(@PathVariable("quizsetId") Long quizestId, @RequestBody ReportRequset reportRequset, HttpServletRequest request) throws SQLException { + String token = request.getHeader("Authorization"); + Long userId = Long.parseLong(jwtUtil.getUserId(token)); - - @PostMapping("/submit") - public ResponseEntity submit(@RequestBody ReportRequset reportRequset) throws SQLException { - ReportResponse report = reportService.grading(reportRequset); - return new ResponseEntity<>(report,HttpStatus.CREATED); + ReportResponse report = reportService.grading(userId, quizestId, reportRequset); + return new ResponseEntity<>(report, HttpStatus.CREATED); } + @GetMapping("/myreport/{id}") + public ResponseEntity> reportList(@PathVariable Long id, HttpServletRequest request) throws SQLException { + String token = request.getHeader("Authorization"); + Long userId = Long.parseLong(jwtUtil.getUserId(token)); + List reportList = reportService.resultList(userId); + + return new ResponseEntity<>(reportList, HttpStatus.CREATED); + + } + + @GetMapping("/detailreport/{id}") + public ResponseEntity myReport(@PathVariable("id") Long reportId) throws SQLException { + + ReportDetailResponseDto detailReport = reportService.reportDetail(reportId); + return new ResponseEntity<>(detailReport, HttpStatus.CREATED); + + } + + } diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/AnswerInput.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/AnswerInput.java index ba1ff2e..b979e52 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/AnswerInput.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/AnswerInput.java @@ -5,7 +5,8 @@ import lombok.Getter; @Getter public class AnswerInput { - Long answerinputID; + String answer; + } diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportDetailResponseDto.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportDetailResponseDto.java new file mode 100644 index 0000000..20458df --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportDetailResponseDto.java @@ -0,0 +1,21 @@ +package com.edufocus.edufocus.report.entity.dto; + +import com.edufocus.edufocus.quiz.entity.Quiz; +import lombok.Builder; +import lombok.Data; + +import java.util.Date; +import java.util.List; + +@Data +@Builder +public class ReportDetailResponseDto { + private int allCount; + private String title; + private int correctCount; + private Date testAt; + private List correctQuizzes; + private List incorrectQuizzes; + + +} \ No newline at end of file diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportListResponseDto.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportListResponseDto.java new file mode 100644 index 0000000..02536d7 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportListResponseDto.java @@ -0,0 +1,14 @@ +package com.edufocus.edufocus.report.entity.dto; + +import lombok.Builder; +import lombok.Data; + +import java.util.Date; + +@Data +@Builder +public class ReportListResponseDto { + private String title; + private Date date; + private Long reportId; +} \ No newline at end of file diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportRequset.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportRequset.java index ca20596..e88a821 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportRequset.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportRequset.java @@ -10,11 +10,9 @@ import java.util.List; public class ReportRequset { - private Long userId; - private Long quizsetId; List answerInputList; - +// [1,2,,3] // List a // userID : // quizSetId : diff --git a/backend/src/main/java/com/edufocus/edufocus/report/repository/AnswerRepository.java b/backend/src/main/java/com/edufocus/edufocus/report/repository/AnswerRepository.java index aa2ec9a..2a9787f 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/repository/AnswerRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/repository/AnswerRepository.java @@ -3,5 +3,9 @@ package com.edufocus.edufocus.report.repository; import com.edufocus.edufocus.report.entity.vo.Answer; import org.springframework.data.jpa.repository.JpaRepository; -public interface AnswerRepository extends JpaRepository { +import java.util.List; + +public interface AnswerRepository extends JpaRepository { + List findByReport_Id(Long reportId); + } diff --git a/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportRepository.java b/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportRepository.java index 954473e..fd69fb5 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportRepository.java @@ -4,6 +4,10 @@ import com.edufocus.edufocus.report.entity.vo.Report; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.List; + @Repository public interface ReportRepository extends JpaRepository { + List findByUser_Id(Long userId); + } diff --git a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportService.java b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportService.java index bfead76..10c08d7 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportService.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportService.java @@ -1,14 +1,20 @@ package com.edufocus.edufocus.report.service; +import com.edufocus.edufocus.report.entity.dto.ReportDetailResponseDto; +import com.edufocus.edufocus.report.entity.dto.ReportListResponseDto; import com.edufocus.edufocus.report.entity.dto.ReportResponse; -import com.edufocus.edufocus.report.entity.vo.Report; import com.edufocus.edufocus.report.entity.dto.ReportRequset; import org.springframework.stereotype.Service; import java.sql.SQLException; +import java.util.List; @Service public interface ReportService { - ReportResponse grading(ReportRequset reportRequset) throws SQLException; + ReportResponse grading(Long userId, Long quizesetId, ReportRequset reportRequset) throws SQLException; + + ReportDetailResponseDto reportDetail(Long userId) throws SQLException; + + List resultList(Long userId) throws SQLException; } diff --git a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java index cb5dd56..bbbc8aa 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java @@ -3,13 +3,12 @@ package com.edufocus.edufocus.report.service; import com.edufocus.edufocus.quiz.entity.Quiz; import com.edufocus.edufocus.quiz.entity.QuizSet; import com.edufocus.edufocus.quiz.repository.QuizRepository; +import com.edufocus.edufocus.quiz.repository.QuizSetRepository; import com.edufocus.edufocus.quiz.service.QuizService; import com.edufocus.edufocus.quiz.service.QuizSetService; -import com.edufocus.edufocus.report.entity.dto.ReportResponse; +import com.edufocus.edufocus.report.entity.dto.*; import com.edufocus.edufocus.report.entity.vo.Answer; -import com.edufocus.edufocus.report.entity.dto.AnswerInput; import com.edufocus.edufocus.report.entity.vo.Report; -import com.edufocus.edufocus.report.entity.dto.ReportRequset; import com.edufocus.edufocus.report.repository.AnswerRepository; import com.edufocus.edufocus.report.repository.ReportRepository; import com.edufocus.edufocus.user.model.entity.vo.User; @@ -34,15 +33,17 @@ public class ReportServiceImpl implements ReportService { private final ReportRepository reportRepository; private final QuizRepository quizRepository; + private final AnswerRepository answerRepository; private final AnswerService answerService; private final UserRepository userRepository; + private final QuizSetRepository quizSetRepository; @Override - public ReportResponse grading(ReportRequset reportRequset) throws SQLException { + public ReportResponse grading(Long userId, Long quizsetId, ReportRequset reportRequset) throws SQLException { - QuizSet quizSet = quizSetService.findQuizSet(reportRequset.getQuizsetId()); + QuizSet quizSet = quizSetService.findQuizSet(quizsetId); List quizList = quizSet.getQuizzes(); List answerInputList = reportRequset.getAnswerInputList(); @@ -51,7 +52,7 @@ public class ReportServiceImpl implements ReportService { int allCount = quizList.size(); int correctCount = 0; - User testuser = userRepository.findById(reportRequset.getUserId()).orElse(null); + User testuser = userRepository.findById(userId).orElse(null); for (int idx = 0; idx < answerInputList.size(); idx++) { Quiz quiz = quizList.get(idx); @@ -107,4 +108,105 @@ public class ReportServiceImpl implements ReportService { return reportResponse; } + @Override + public ReportDetailResponseDto reportDetail(Long repordId) { + + Report report = reportRepository.findById(repordId).orElse(null); + + QuizSet quizSet = quizSetService.findQuizSet(report.getQuizSet().getId()); + + List correctQuiz = new ArrayList<>(); + List incorrectQuiz = new ArrayList<>(); + + List myAnswer = answerRepository.findByReport_Id(report.getId()); + + for (Answer answer : myAnswer) { + if (answer.isCorrect()) { + correctQuiz.add(quizRepository.findById(answer.getQuiz().getId()).orElse(null)); + } else { + incorrectQuiz.add(quizRepository.findById(answer.getQuiz().getId()).orElse(null)); + + } + } + ReportDetailResponseDto dto = ReportDetailResponseDto.builder() + .title(quizSet.getTitle()) + .testAt(report.getTestAt()) + .allCount(report.getAllCount()) + .correctCount(report.getCorrectCount()) + .correctQuizzes(correctQuiz) + .incorrectQuizzes(incorrectQuiz) + .build(); + + return dto; + } + +// @Override +// public List result(Long userId) throws SQLException { +// List myReport = reportRepository.findByUser_Id(userId); +// +// +// List responseDtos = new ArrayList<>(); +// +// for (Report report : myReport) { +// int all = report.getAllCount(); +// int correctCount = report.getCorrectCount(); +// Long quizsetId = report.getQuizSet().getId(); +// Date testAt = report.getTestAt(); +// +// List correctQuiz = new ArrayList<>(); +// List incorrectQuiz = new ArrayList<>(); +// +// List myAnswer = answerRepository.findByReport_Id(report.getId()); +// +// for (Answer answer : myAnswer) { +// if (answer.isCorrect()) { +// correctQuiz.add(quizRepository.findById(answer.getQuiz().getId()).orElse(null)); +// } else { +// incorrectQuiz.add(quizRepository.findById(answer.getQuiz().getId()).orElse(null)); +// +// } +// } +// +// +// ReportResultResponseDto dto = ReportResultResponseDto.builder() +// .reportId(report.getId()) +// .allCount(all) +// .correctCount(correctCount) +// .quizSetId(quizSetId) +// .testAt(testAt) +// .correctQuizzes(correctQuiz) +// .incorrectQuizzes(incorrectQuiz) +// .build(); +// +// responseDtos.add(dto); +// } +// // 틀린문제 +// // 내가 체크한 번호 +// // 정답 번호 +// } + + @Override + public List resultList(Long userId) throws SQLException { + + List reportList = reportRepository.findByUser_Id(userId); + + List reportListResponseDtoList = new ArrayList<>(); + + + for (Report report : reportList) { + + QuizSet quizSet = quizSetService.findQuizSet(report.getQuizSet().getId()); + ReportListResponseDto dto = ReportListResponseDto.builder() + .title(quizSet.getTitle()) // Assuming QuizSet has a method getTitle() + .date(report.getTestAt()) + .reportId(report.getId())// Assuming QuizSet has a method getDate() + .build(); + reportListResponseDtoList.add(dto); + + } + + return reportListResponseDtoList; + + } + } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java index c077839..2efa0e7 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java @@ -32,9 +32,9 @@ public class UserController { private final JWTUtil jwtUtil; @PostMapping("/join") - public ResponseEntity join(@RequestBody RequestJoinDto requestJoinDto){ + public ResponseEntity join(@RequestBody RequestJoinDto requestJoinDto) { - if(userService.isUserIdExist(requestJoinDto.getUserId())) + if (userService.isUserIdExist(requestJoinDto.getUserId())) return new ResponseEntity<>("아이디가 중복 됐습니다.", HttpStatus.CONFLICT); userService.join(requestJoinDto); @@ -83,8 +83,8 @@ public class UserController { userService.saveRefreshToken(loginUser.getId(), refreshToken); - resultMap.put("name",loginUser.getName()); - resultMap.put("role",loginUser.getRole()); + resultMap.put("name", loginUser.getName()); + resultMap.put("role", loginUser.getRole()); resultMap.put("access-token", accessToken); setCookies(response, refreshToken); @@ -108,7 +108,7 @@ public class UserController { @Operation(summary = "Access Token 재발급", description = "만료된 access token 을 재발급 받는다.") @PostMapping("/refresh") - public ResponseEntity refreshToken(HttpServletRequest request,HttpServletResponse response) { + public ResponseEntity refreshToken(HttpServletRequest request, HttpServletResponse response) { Cookie[] cookies = request.getCookies(); String token = null; if (cookies != null) { @@ -120,9 +120,9 @@ public class UserController { } } - try{ + try { jwtUtil.checkToken(token); - }catch (Exception e){ + } catch (Exception e) { throw new InvalidTokenException(); } @@ -140,7 +140,7 @@ public class UserController { Map resultMap = new HashMap<>(); resultMap.put("access-token", accessToken); - userService.saveRefreshToken(userId,refreshToken); + userService.saveRefreshToken(userId, refreshToken); setCookies(response, refreshToken); @@ -175,7 +175,7 @@ public class UserController { } - private void setCookies(HttpServletResponse response, String refreshToken){ + private void setCookies(HttpServletResponse response, String refreshToken) { Cookie refreshCookie = new Cookie("refresh-token", refreshToken); refreshCookie.setPath("/"); refreshCookie.setHttpOnly(true); From a4b3bab290b6fbcf426452072ddcba261233a83a Mon Sep 17 00:00:00 2001 From: yulmam <70622601+yulmam@users.noreply.github.com> Date: Tue, 6 Aug 2024 16:47:01 +0900 Subject: [PATCH 125/197] =?UTF-8?q?refactor=20:=20board=20name=20=EC=B6=9C?= =?UTF-8?q?=EB=A0=A5=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/edufocus/edufocus/board/entity/vo/Board.java | 2 +- .../java/com/edufocus/edufocus/board/entity/vo/Comment.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java index 98df363..ff8d039 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java @@ -62,7 +62,7 @@ public class Board { return ResponseBoardSummaryDto.builder() .id(id) .title(title) - .name(user.getUserId()) + .name(user.getName()) .createdAt(createdAt) .build(); } diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java index ef311a0..d7c97c2 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java @@ -42,7 +42,7 @@ public class Comment { public ResponseCommentDto makeCommentDto() { return ResponseCommentDto.builder() .id(id) - .name(user.getEmail()) + .name(user.getName()) .content(content) .createAt(createdAt) .modifiedAt(modifiedAt) From 84e56206dcd194e1a2e9cb5ab3c1dd109c1d870d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Tue, 6 Aug 2024 17:08:00 +0900 Subject: [PATCH 126/197] =?UTF-8?q?feat:=20report=20=EC=A0=9C=EC=B6=9C=20?= =?UTF-8?q?=EB=B0=8F=20=EC=B1=84=EC=A0=90=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/report/entity/dto/ReportRequset.java | 2 +- .../edufocus/edufocus/report/entity/vo/Report.java | 6 +++--- .../edufocus/report/service/ReportServiceImpl.java | 11 ++++++----- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportRequset.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportRequset.java index e88a821..84e3e74 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportRequset.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportRequset.java @@ -10,7 +10,7 @@ import java.util.List; public class ReportRequset { - List answerInputList; + List answer; // [1,2,,3] // List a diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java index a9e2222..1b81e78 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java @@ -23,13 +23,13 @@ public class Report { private int allCount; private int correctCount; private Date testAt; - + private Long lectureId; @ManyToOne - @JoinColumn(name= "user_id") + @JoinColumn(name = "user_id") private User user; @ManyToOne - @JoinColumn(name= "quizset_id") + @JoinColumn(name = "quizset_id") private QuizSet quizSet; } diff --git a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java index bbbc8aa..f2666bc 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java @@ -45,7 +45,7 @@ public class ReportServiceImpl implements ReportService { QuizSet quizSet = quizSetService.findQuizSet(quizsetId); List quizList = quizSet.getQuizzes(); - List answerInputList = reportRequset.getAnswerInputList(); + List answerInputList = reportRequset.getAnswer(); List answerList = new ArrayList<>(); @@ -56,19 +56,20 @@ public class ReportServiceImpl implements ReportService { for (int idx = 0; idx < answerInputList.size(); idx++) { Quiz quiz = quizList.get(idx); - AnswerInput inputAnswer = answerInputList.get(idx); + String inputAnswer = answerInputList.get(idx); Answer answer; - if (quiz.getAnswer().equals(inputAnswer.getAnswer())) { + // + if (quiz.getAnswer().equals(inputAnswer)) { correctCount++; answer = Answer.builder() - .userAnswer(inputAnswer.getAnswer()) + .userAnswer(inputAnswer) .isCorrect(true) .report(null) .quiz(quiz) .build(); } else { answer = Answer.builder() - .userAnswer(inputAnswer.getAnswer()) + .userAnswer(inputAnswer) .isCorrect(false) .report(null) .quiz(quiz) From 747af409fa0cc715e0b7b4a1f5be421165d32297 Mon Sep 17 00:00:00 2001 From: yulmam <70622601+yulmam@users.noreply.github.com> Date: Wed, 7 Aug 2024 09:09:40 +0900 Subject: [PATCH 127/197] =?UTF-8?q?feat=20:=20onlinestate=20=EC=B2=B4?= =?UTF-8?q?=ED=81=AC=20=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/lecture/controller/LectureController.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java b/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java index 6e04639..90c9416 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java @@ -93,4 +93,9 @@ public class LectureController { return new ResponseEntity<>(myLectures, HttpStatus.OK); } + + @GetMapping("/isLive/{lectureId}") + public ResponseEntity checkIsLive(@PathVariable long lectureId) { + return new ResponseEntity<>(lectureService.getState(lectureId), HttpStatus.OK); + } } From 96e3949700d2c63d99aa7493ac7e04beaf92b151 Mon Sep 17 00:00:00 2001 From: yulmam <70622601+yulmam@users.noreply.github.com> Date: Wed, 7 Aug 2024 09:48:35 +0900 Subject: [PATCH 128/197] =?UTF-8?q?feat=20:=20=EC=9D=B4=EB=A9=94=EC=9D=BC?= =?UTF-8?q?=20=EC=A4=91=EB=B3=B5=20=EC=B2=B4=ED=81=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/edufocus/user/controller/UserController.java | 3 +++ .../edufocus/user/model/repository/UserRepository.java | 1 + .../edufocus/edufocus/user/model/service/UserService.java | 2 ++ .../edufocus/user/model/service/UserServiceImpl.java | 5 +++++ 4 files changed, 11 insertions(+) diff --git a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java index c077839..fec5f10 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java @@ -37,6 +37,9 @@ public class UserController { if(userService.isUserIdExist(requestJoinDto.getUserId())) return new ResponseEntity<>("아이디가 중복 됐습니다.", HttpStatus.CONFLICT); + if(userService.isEmailExist(requestJoinDto.getEmail())) + return new ResponseEntity<>("이메일이 중복 됐습니다.", HttpStatus.CONFLICT); + userService.join(requestJoinDto); return ResponseEntity.ok("User registered successfully"); diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/repository/UserRepository.java b/backend/src/main/java/com/edufocus/edufocus/user/model/repository/UserRepository.java index 10e9f87..cd8e74c 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/repository/UserRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/repository/UserRepository.java @@ -31,4 +31,5 @@ public interface UserRepository extends JpaRepository { Optional findByUserId(String userId); + Optional findByEmail(String email); } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java index 7b2d101..29578c0 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java @@ -25,4 +25,6 @@ public interface UserService { void changePassword(PasswordDto passwordDto,Long id); boolean isUserIdExist(String userId); + + boolean isEmailExist(String email); } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java index 77fd4ca..547b37f 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java @@ -113,6 +113,11 @@ public class UserServiceImpl implements UserService { return userRepository.findByUserId(userId).isPresent(); } + @Override + public boolean isEmailExist(String email) { + return userRepository.findByEmail(email).isPresent(); + } + public String getTempPassword() { char[] charSet = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}; From e8c88f9b1bd4b87310c6921b65e740f759a917fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Wed, 7 Aug 2024 10:15:12 +0900 Subject: [PATCH 129/197] =?UTF-8?q?feat:=20report=20=ED=95=99=EC=83=9D,?= =?UTF-8?q?=EA=B0=95=EC=82=AC=20=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lecture/controller/LectureController.java | 4 +- .../report/controller/ReportController.java | 58 +++++++-- .../edufocus/report/entity/dto/ChoiceDto.java | 12 ++ .../edufocus/report/entity/dto/QuizDto.java | 28 +++++ .../entity/dto/ReportDetailResponseDto.java | 4 +- .../entity/dto/ReportListResponseDto.java | 3 + .../report/repository/ReportRepository.java | 2 + .../report/service/ReportService.java | 3 +- .../report/service/ReportServiceImpl.java | 116 ++++++++++-------- 9 files changed, 170 insertions(+), 60 deletions(-) create mode 100644 backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ChoiceDto.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/report/entity/dto/QuizDto.java diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java b/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java index 6e04639..90e8e0b 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java @@ -14,6 +14,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; +import java.util.ArrayList; import java.util.List; @RestController @@ -83,8 +84,9 @@ public class LectureController { @GetMapping("/mylecture") public ResponseEntity findMyLecture(@RequestHeader(value = "Authorization", required = false) String accessToken) { + if (accessToken == null) { - return new ResponseEntity<>(HttpStatus.NO_CONTENT); + return new ResponseEntity<>(new ArrayList<>(), HttpStatus.OK); } Long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); diff --git a/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java b/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java index bbae94c..9c789bf 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java @@ -6,6 +6,11 @@ import com.edufocus.edufocus.report.entity.dto.ReportResponse; import com.edufocus.edufocus.report.entity.vo.Report; import com.edufocus.edufocus.report.entity.dto.ReportRequset; import com.edufocus.edufocus.report.service.ReportService; +import com.edufocus.edufocus.user.model.entity.vo.User; +import com.edufocus.edufocus.user.model.entity.vo.UserRole; +import com.edufocus.edufocus.user.model.repository.UserRepository; +import com.edufocus.edufocus.user.model.service.UserService; +import com.edufocus.edufocus.user.model.service.UserServiceImpl; import com.edufocus.edufocus.user.util.JWTUtil; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @@ -28,35 +33,74 @@ public class ReportController { private final ReportService reportService; private final JWTUtil jwtUtil; + private final UserService userService; + private final UserRepository userRepository; + //SUBMIT 할떄 LECTURE ID 저장해놓기 - @PostMapping("/submit/{quizsetId}") - public ResponseEntity submit(@PathVariable("quizsetId") Long quizestId, @RequestBody ReportRequset reportRequset, HttpServletRequest request) throws SQLException { + @PostMapping("/submit/{lectreId}/quizset/{quizsetId}") + public ResponseEntity submit(@PathVariable("lectreId") Long lectureId, @PathVariable("quizsetId") Long quizestId, @RequestBody ReportRequset reportRequset, HttpServletRequest request) throws SQLException { String token = request.getHeader("Authorization"); Long userId = Long.parseLong(jwtUtil.getUserId(token)); + User findUser = userRepository.findById(userId).orElse(null); + if (findUser.getRole() == UserRole.ADMIN) { + + return new ResponseEntity<>("강사는 퀴즈제출을 할수 없습니다", HttpStatus.FORBIDDEN); + + } + ReportResponse report = reportService.grading(userId, quizestId, reportRequset, lectureId); - ReportResponse report = reportService.grading(userId, quizestId, reportRequset); return new ResponseEntity<>(report, HttpStatus.CREATED); } - @GetMapping("/myreport/{id}") - public ResponseEntity> reportList(@PathVariable Long id, HttpServletRequest request) throws SQLException { + + @GetMapping("/myreport") + public ResponseEntity> myreport(HttpServletRequest request) throws SQLException { String token = request.getHeader("Authorization"); Long userId = Long.parseLong(jwtUtil.getUserId(token)); + + List reportList = reportService.resultList(userId); return new ResponseEntity<>(reportList, HttpStatus.CREATED); } - @GetMapping("/detailreport/{id}") - public ResponseEntity myReport(@PathVariable("id") Long reportId) throws SQLException { + @GetMapping("/myreportdetail/{id}") + public ResponseEntity myreportdetail(@PathVariable("id") Long reportId) throws SQLException { ReportDetailResponseDto detailReport = reportService.reportDetail(reportId); return new ResponseEntity<>(detailReport, HttpStatus.CREATED); } + @GetMapping("/studentreport/{lecturid}") + public ResponseEntity> studentreport(@PathVariable("lecturid") Long lectureId) throws SQLException { + + + List reportList = reportService.studentResultList(lectureId); + + return new ResponseEntity<>(reportList, HttpStatus.CREATED); + + } + + @GetMapping("/studentreportdetail/{id}") + public ResponseEntity studentdetailreport(@PathVariable("id") Long reportId) throws SQLException { + + ReportDetailResponseDto detailReport = reportService.reportDetail(reportId); + return new ResponseEntity<>(detailReport, HttpStatus.CREATED); + + } + + // 강좌에 대한 퀴즈셋 +// lecture id가 똑같은 report들 제목 + 작성자 + 맞틀 개수 미리 보여주기 +// @GetMapping("/detailreport/{id}") +// public ResponseEntity (@PathVariable("id") Long reportId) throws SQLException { +// +// ReportDetailResponseDto detailReport = reportService.reportDetail(reportId); +// return new ResponseEntity<>(detailReport, HttpStatus.CREATED); +// +// } v 9 } diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ChoiceDto.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ChoiceDto.java new file mode 100644 index 0000000..c28bbc2 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ChoiceDto.java @@ -0,0 +1,12 @@ +package com.edufocus.edufocus.report.entity.dto; + +import lombok.Builder; +import lombok.Data; +import lombok.Setter; + +@Data +@Builder +public class ChoiceDto { + int num; + String content; +} diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/QuizDto.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/QuizDto.java new file mode 100644 index 0000000..350e906 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/QuizDto.java @@ -0,0 +1,28 @@ +package com.edufocus.edufocus.report.entity.dto; + +import com.edufocus.edufocus.quiz.entity.Choice; +import com.edufocus.edufocus.quiz.entity.QuizSet; +import com.fasterxml.jackson.annotation.JsonBackReference; +import com.fasterxml.jackson.annotation.JsonManagedReference; +import jakarta.persistence.*; +import lombok.Builder; +import lombok.Data; + +import java.util.List; + +@Data +@Builder +public class QuizDto { + + + private long id; + + + private String question; + + private String image; + + private String answer; + private String userAnswer; + private List choices; +} diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportDetailResponseDto.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportDetailResponseDto.java index 20458df..a86b4e7 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportDetailResponseDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportDetailResponseDto.java @@ -14,8 +14,8 @@ public class ReportDetailResponseDto { private String title; private int correctCount; private Date testAt; - private List correctQuizzes; - private List incorrectQuizzes; + private List correctQuizzes; + private List incorrectQuizzes; } \ No newline at end of file diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportListResponseDto.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportListResponseDto.java index 02536d7..94fc3e2 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportListResponseDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportListResponseDto.java @@ -11,4 +11,7 @@ public class ReportListResponseDto { private String title; private Date date; private Long reportId; + private String name; + private int allCount; + private int correctCount; } \ No newline at end of file diff --git a/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportRepository.java b/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportRepository.java index fd69fb5..66d2fb9 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportRepository.java @@ -10,4 +10,6 @@ import java.util.List; public interface ReportRepository extends JpaRepository { List findByUser_Id(Long userId); + List findByLectureId(Long lectureId); + } diff --git a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportService.java b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportService.java index 10c08d7..7edcc4a 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportService.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportService.java @@ -11,10 +11,11 @@ import java.util.List; @Service public interface ReportService { - ReportResponse grading(Long userId, Long quizesetId, ReportRequset reportRequset) throws SQLException; + ReportResponse grading(Long userId, Long quizesetId, ReportRequset reportRequset, Long lectureId) throws SQLException; ReportDetailResponseDto reportDetail(Long userId) throws SQLException; List resultList(Long userId) throws SQLException; + List studentResultList(Long lectureId) throws SQLException; } diff --git a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java index f2666bc..5543795 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java @@ -1,5 +1,6 @@ package com.edufocus.edufocus.report.service; +import com.edufocus.edufocus.quiz.entity.Choice; import com.edufocus.edufocus.quiz.entity.Quiz; import com.edufocus.edufocus.quiz.entity.QuizSet; import com.edufocus.edufocus.quiz.repository.QuizRepository; @@ -15,6 +16,7 @@ import com.edufocus.edufocus.user.model.entity.vo.User; import com.edufocus.edufocus.user.model.repository.UserRepository; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; +import org.checkerframework.checker.units.qual.C; import org.springframework.stereotype.Service; import java.sql.SQLException; @@ -41,7 +43,7 @@ public class ReportServiceImpl implements ReportService { @Override - public ReportResponse grading(Long userId, Long quizsetId, ReportRequset reportRequset) throws SQLException { + public ReportResponse grading(Long userId, Long quizsetId, ReportRequset reportRequset, Long lectureId) throws SQLException { QuizSet quizSet = quizSetService.findQuizSet(quizsetId); List quizList = quizSet.getQuizzes(); @@ -85,6 +87,7 @@ public class ReportServiceImpl implements ReportService { .allCount(allCount) .correctCount(correctCount) .testAt(new Date()) + .lectureId(lectureId) .build(); @@ -116,16 +119,49 @@ public class ReportServiceImpl implements ReportService { QuizSet quizSet = quizSetService.findQuizSet(report.getQuizSet().getId()); - List correctQuiz = new ArrayList<>(); - List incorrectQuiz = new ArrayList<>(); + List correctQuiz = new ArrayList<>(); + List incorrectQuiz = new ArrayList<>(); List myAnswer = answerRepository.findByReport_Id(report.getId()); for (Answer answer : myAnswer) { + QuizDto quizDto; + Quiz quiz = quizRepository.findById(answer.getQuiz().getId()).orElse(null); + + ArrayList choiceDtos = new ArrayList<>(); + + for (Choice c : quiz.getChoices()) { + ChoiceDto choiceDto = null; + choiceDto = choiceDto.builder() + .num(c.getNum()) + .content(c.getContent()) + .build(); + choiceDtos.add(choiceDto); + + } if (answer.isCorrect()) { - correctQuiz.add(quizRepository.findById(answer.getQuiz().getId()).orElse(null)); + + quizDto = QuizDto.builder() + .id(quiz.getId()) + .question(quiz.getQuestion()) + .image(quiz.getImage()) + .question(quiz.getQuestion()) + .answer(quiz.getAnswer()) + .userAnswer(answer.getUserAnswer()) + .choices(choiceDtos) + .build(); + correctQuiz.add(quizDto); } else { - incorrectQuiz.add(quizRepository.findById(answer.getQuiz().getId()).orElse(null)); + quizDto = QuizDto.builder() + .id(quiz.getId()) + .question(quiz.getQuestion()) + .image(quiz.getImage()) + .question(quiz.getQuestion()) + .answer(quiz.getAnswer()) + .userAnswer(answer.getUserAnswer()) + .choices(choiceDtos) + .build(); + incorrectQuiz.add(quizDto); } } @@ -141,50 +177,6 @@ public class ReportServiceImpl implements ReportService { return dto; } -// @Override -// public List result(Long userId) throws SQLException { -// List myReport = reportRepository.findByUser_Id(userId); -// -// -// List responseDtos = new ArrayList<>(); -// -// for (Report report : myReport) { -// int all = report.getAllCount(); -// int correctCount = report.getCorrectCount(); -// Long quizsetId = report.getQuizSet().getId(); -// Date testAt = report.getTestAt(); -// -// List correctQuiz = new ArrayList<>(); -// List incorrectQuiz = new ArrayList<>(); -// -// List myAnswer = answerRepository.findByReport_Id(report.getId()); -// -// for (Answer answer : myAnswer) { -// if (answer.isCorrect()) { -// correctQuiz.add(quizRepository.findById(answer.getQuiz().getId()).orElse(null)); -// } else { -// incorrectQuiz.add(quizRepository.findById(answer.getQuiz().getId()).orElse(null)); -// -// } -// } -// -// -// ReportResultResponseDto dto = ReportResultResponseDto.builder() -// .reportId(report.getId()) -// .allCount(all) -// .correctCount(correctCount) -// .quizSetId(quizSetId) -// .testAt(testAt) -// .correctQuizzes(correctQuiz) -// .incorrectQuizzes(incorrectQuiz) -// .build(); -// -// responseDtos.add(dto); -// } -// // 틀린문제 -// // 내가 체크한 번호 -// // 정답 번호 -// } @Override public List resultList(Long userId) throws SQLException { @@ -210,4 +202,30 @@ public class ReportServiceImpl implements ReportService { } + @Override + public List studentResultList(Long lectureId) throws SQLException { + + List reportList = reportRepository.findByLectureId(lectureId); + + List reportListResponseDtoList = new ArrayList<>(); + + + for (Report report : reportList) { + + System.out.println(report.toString()); + QuizSet quizSet = quizSetService.findQuizSet(report.getQuizSet().getId()); + ReportListResponseDto dto = ReportListResponseDto.builder() + .title(quizSet.getTitle()) + .date(report.getTestAt()) + .reportId(report.getId()) + .allCount(report.getAllCount()) + .correctCount(report.getCorrectCount()) + .build(); + reportListResponseDtoList.add(dto); + + } + + return reportListResponseDtoList; + + } } From 509a41fd0a73d62b6fe393afabd9f7e115261fa6 Mon Sep 17 00:00:00 2001 From: kgc91747 Date: Wed, 7 Aug 2024 10:39:16 +0900 Subject: [PATCH 130/197] =?UTF-8?q?feat:=20email=20=EB=B9=84=EB=B0=80?= =?UTF-8?q?=EB=B2=88=ED=98=B8=20=EC=B0=BE=EA=B8=B0=20=EC=9D=B4=EB=A9=94?= =?UTF-8?q?=EC=9D=BC=20=EC=9D=B8=EC=A6=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...-2922-4057-81cd-756e62ddd13c_testimg1.jpg} | Bin ...-11a6-4026-82fb-5a1d0beb9130_testImg2.jpg} | Bin ...3-017a-4d3c-9c5c-aa0a2ada53f9_testimg1.jpg | Bin 8567 -> 0 bytes ...1a-4f48-885c-30bf45d63778_lectureImage.jpg | Bin 8567 -> 0 bytes ...08-41ad-96b9-9d25d5353c73_lectureImage.jpg | Bin 8567 -> 0 bytes backend/build.gradle | 2 +- .../global/config/PropertiesConfig.java | 4 +- .../edufocus/global/config/RedisConfig.java | 22 ++++++ .../global/properties/MailProperties.java | 15 ++++ .../mail/controller/MailController.java | 39 ++++++++++ .../edufocus/mail/service/MailService.java | 13 ++++ .../mail/service/MailServiceImpl.java | 69 ++++++++++++++++++ .../edufocus/redis/util/RedisUtil.java | 36 +++++++++ .../user/config/WebConfiguration.java | 2 +- .../user/controller/UserController.java | 26 ++++--- .../user/model/repository/UserRepository.java | 2 + .../user/model/service/UserService.java | 24 +++--- .../user/model/service/UserServiceImpl.java | 52 ++++++++----- .../src/main/resources/application.properties | 11 ++- 19 files changed, 277 insertions(+), 40 deletions(-) rename backend/backend/src/main/resources/images/{30d65b76-54cb-42ad-a53e-04691c6401ba_testimg3.jpg => 0a51d4af-2922-4057-81cd-756e62ddd13c_testimg1.jpg} (100%) rename backend/backend/src/main/resources/images/{427dc7fc-d22e-43a3-8fde-69bace73ee6a_lectureImage.jpg => 0bef3f29-11a6-4026-82fb-5a1d0beb9130_testImg2.jpg} (100%) delete mode 100644 backend/backend/src/main/resources/images/45b6ea03-017a-4d3c-9c5c-aa0a2ada53f9_testimg1.jpg delete mode 100644 backend/backend/src/main/resources/images/7fd1090b-af1a-4f48-885c-30bf45d63778_lectureImage.jpg delete mode 100644 backend/backend/src/main/resources/images/a69e91c4-5108-41ad-96b9-9d25d5353c73_lectureImage.jpg create mode 100644 backend/src/main/java/com/edufocus/edufocus/global/config/RedisConfig.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/global/properties/MailProperties.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/mail/controller/MailController.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/mail/service/MailService.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/mail/service/MailServiceImpl.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/redis/util/RedisUtil.java diff --git a/backend/backend/src/main/resources/images/30d65b76-54cb-42ad-a53e-04691c6401ba_testimg3.jpg b/backend/backend/src/main/resources/images/0a51d4af-2922-4057-81cd-756e62ddd13c_testimg1.jpg similarity index 100% rename from backend/backend/src/main/resources/images/30d65b76-54cb-42ad-a53e-04691c6401ba_testimg3.jpg rename to backend/backend/src/main/resources/images/0a51d4af-2922-4057-81cd-756e62ddd13c_testimg1.jpg diff --git a/backend/backend/src/main/resources/images/427dc7fc-d22e-43a3-8fde-69bace73ee6a_lectureImage.jpg b/backend/backend/src/main/resources/images/0bef3f29-11a6-4026-82fb-5a1d0beb9130_testImg2.jpg similarity index 100% rename from backend/backend/src/main/resources/images/427dc7fc-d22e-43a3-8fde-69bace73ee6a_lectureImage.jpg rename to backend/backend/src/main/resources/images/0bef3f29-11a6-4026-82fb-5a1d0beb9130_testImg2.jpg diff --git a/backend/backend/src/main/resources/images/45b6ea03-017a-4d3c-9c5c-aa0a2ada53f9_testimg1.jpg b/backend/backend/src/main/resources/images/45b6ea03-017a-4d3c-9c5c-aa0a2ada53f9_testimg1.jpg deleted file mode 100644 index c53ac5e358df846b8d20f1928bd0860aa4302f24..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8567 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 sendMail(@RequestParam String email) { + if (!userService.isEmailExist(email)) { + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + } + + mailService.sendMail(email); + return new ResponseEntity<>(HttpStatus.OK); + } + + @GetMapping("/verify") + public ResponseEntity verifyCode(@RequestParam String code, @RequestParam String email) { + if (!mailService.verifyCode(code, email)) { + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } + return new ResponseEntity<>(HttpStatus.OK); + } + +} diff --git a/backend/src/main/java/com/edufocus/edufocus/mail/service/MailService.java b/backend/src/main/java/com/edufocus/edufocus/mail/service/MailService.java new file mode 100644 index 0000000..1799126 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/mail/service/MailService.java @@ -0,0 +1,13 @@ +package com.edufocus.edufocus.mail.service; + +import org.springframework.stereotype.Service; + +@Service +public interface MailService { + + void sendMail(String to); + + String createRandomCode(); + + boolean verifyCode(String code, String email); +} diff --git a/backend/src/main/java/com/edufocus/edufocus/mail/service/MailServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/mail/service/MailServiceImpl.java new file mode 100644 index 0000000..20859de --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/mail/service/MailServiceImpl.java @@ -0,0 +1,69 @@ +package com.edufocus.edufocus.mail.service; + +import com.edufocus.edufocus.redis.util.RedisUtil; +import com.edufocus.edufocus.user.model.entity.vo.User; +import com.edufocus.edufocus.user.model.repository.UserRepository; +import com.edufocus.edufocus.user.model.service.UserService; +import lombok.RequiredArgsConstructor; +import lombok.ToString; +import lombok.extern.slf4j.Slf4j; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.stereotype.Service; + +import java.util.NoSuchElementException; +import java.util.Random; + +@Service +@Slf4j +@ToString +@RequiredArgsConstructor +public class MailServiceImpl implements MailService { + + private final JavaMailSender mailSender; + + private final UserRepository userRepository; + + private final UserService userService; + + private final RedisUtil redisUtil; + + @Override + public void sendMail(String email) { + String code = createRandomCode(); + redisUtil.setDataExpire(code, email, 60 * 5L); + + SimpleMailMessage mail = createEmail(email, "[EDUFOCUS] 비밀번호 찾기 안내", code); + mailSender.send(mail); + } + + @Override + public boolean verifyCode(String code, String email) { + String registedEmail = redisUtil.getData(code); + + return registedEmail != null && registedEmail.equals(email); + } + + private SimpleMailMessage createEmail(String to, String title, String code) { + SimpleMailMessage message = new SimpleMailMessage(); + message.setTo(to); + message.setSubject(title); + message.setText("인증번호 6자리입니다 : " + code); + + return message; + } + + @Override + public String createRandomCode() { + StringBuilder sb = new StringBuilder(); + Random random = new Random(); + for (int i = 0; i < 3; i++) { + sb.append((char) (random.nextInt(26) + 65)); + } + for (int i = 0; i < 3; i++) { + sb.append(random.nextInt(10)); + } + return sb.toString(); + } + +} diff --git a/backend/src/main/java/com/edufocus/edufocus/redis/util/RedisUtil.java b/backend/src/main/java/com/edufocus/edufocus/redis/util/RedisUtil.java new file mode 100644 index 0000000..ad9bf09 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/redis/util/RedisUtil.java @@ -0,0 +1,36 @@ +package com.edufocus.edufocus.redis.util; + +import lombok.RequiredArgsConstructor; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.data.redis.core.ValueOperations; +import org.springframework.stereotype.Component; + +import java.time.Duration; + +@Component +@RequiredArgsConstructor +public class RedisUtil { + + private final StringRedisTemplate stringRedisTemplate; + + public String getData(String key) { + ValueOperations valueOperations = stringRedisTemplate.opsForValue(); + return valueOperations.get(key); + } + + public void setData(String key, String value) { + ValueOperations valueOperations = stringRedisTemplate.opsForValue(); + valueOperations.set(key, value); + } + + public void setDataExpire(String key, String value, long duration) { + ValueOperations valueOperations = stringRedisTemplate.opsForValue(); + Duration expireDuration = Duration.ofSeconds(duration); + valueOperations.set(key, value, expireDuration); + } + + public void deleteData(String key) { + stringRedisTemplate.delete(key); + } + +} \ No newline at end of file diff --git a/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java b/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java index 0972d21..5899062 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/config/WebConfiguration.java @@ -47,6 +47,6 @@ public class WebConfiguration implements WebMvcConfigurer { public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(jwtInterceptor) .addPathPatterns("/**") // 모든 경로에 대해 인터셉터 적용 - .excludePathPatterns("/v3/api-docs/**", "/swagger-resources/**", "/webjars/**", "/swagger-ui/**", "/auth/**", "/board/**", "/user/**", "/lecture/**", "/qna/**", "/quiz/**", "/video/**", "/registration/**", "/report/**"); // 인증 없이 접근 가능한 경로 설정 + .excludePathPatterns("/v3/api-docs/**", "/swagger-resources/**", "/webjars/**", "/swagger-ui/**", "/auth/**", "/board/**", "/user/**", "/lecture/**", "/qna/**", "/quiz/**", "/video/**", "/registration/**", "/report/**", "/mail/**"); // 인증 없이 접근 가능한 경로 설정 } } \ No newline at end of file diff --git a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java index c077839..2aecbb3 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java @@ -32,9 +32,9 @@ public class UserController { private final JWTUtil jwtUtil; @PostMapping("/join") - public ResponseEntity join(@RequestBody RequestJoinDto requestJoinDto){ + public ResponseEntity join(@RequestBody RequestJoinDto requestJoinDto) { - if(userService.isUserIdExist(requestJoinDto.getUserId())) + if (userService.isUserIdExist(requestJoinDto.getUserId())) return new ResponseEntity<>("아이디가 중복 됐습니다.", HttpStatus.CONFLICT); userService.join(requestJoinDto); @@ -66,6 +66,14 @@ public class UserController { } } + // 비밀번호 찾기를 통한 변경 + @PutMapping("/updateforgottenpassword") + public ResponseEntity updatePassword(@RequestParam long userId, + @RequestParam String newPassword) { + userService.changeForgottenPassword(userId, newPassword); + return new ResponseEntity<>(HttpStatus.OK); + } + @Operation(summary = "로그인", description = "아이디와 비밀번호를 이용하여 로그인 처리.") @PostMapping("/login") public ResponseEntity> login( @@ -83,8 +91,8 @@ public class UserController { userService.saveRefreshToken(loginUser.getId(), refreshToken); - resultMap.put("name",loginUser.getName()); - resultMap.put("role",loginUser.getRole()); + resultMap.put("name", loginUser.getName()); + resultMap.put("role", loginUser.getRole()); resultMap.put("access-token", accessToken); setCookies(response, refreshToken); @@ -108,7 +116,7 @@ public class UserController { @Operation(summary = "Access Token 재발급", description = "만료된 access token 을 재발급 받는다.") @PostMapping("/refresh") - public ResponseEntity refreshToken(HttpServletRequest request,HttpServletResponse response) { + public ResponseEntity refreshToken(HttpServletRequest request, HttpServletResponse response) { Cookie[] cookies = request.getCookies(); String token = null; if (cookies != null) { @@ -120,9 +128,9 @@ public class UserController { } } - try{ + try { jwtUtil.checkToken(token); - }catch (Exception e){ + } catch (Exception e) { throw new InvalidTokenException(); } @@ -140,7 +148,7 @@ public class UserController { Map resultMap = new HashMap<>(); resultMap.put("access-token", accessToken); - userService.saveRefreshToken(userId,refreshToken); + userService.saveRefreshToken(userId, refreshToken); setCookies(response, refreshToken); @@ -175,7 +183,7 @@ public class UserController { } - private void setCookies(HttpServletResponse response, String refreshToken){ + private void setCookies(HttpServletResponse response, String refreshToken) { Cookie refreshCookie = new Cookie("refresh-token", refreshToken); refreshCookie.setPath("/"); refreshCookie.setHttpOnly(true); diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/repository/UserRepository.java b/backend/src/main/java/com/edufocus/edufocus/user/model/repository/UserRepository.java index 10e9f87..6aea378 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/repository/UserRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/repository/UserRepository.java @@ -31,4 +31,6 @@ public interface UserRepository extends JpaRepository { Optional findByUserId(String userId); + Optional findByEmail(String email); + } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java index 7b2d101..0737045 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java @@ -6,23 +6,27 @@ import com.edufocus.edufocus.user.model.entity.dto.RequestJoinDto; import com.edufocus.edufocus.user.model.entity.vo.User; public interface UserService { - void join(RequestJoinDto requestJoinDto); + void join(RequestJoinDto requestJoinDto); - User login(User user); + User login(User user); - void saveRefreshToken(Long id, String refreshToken); + void saveRefreshToken(Long id, String refreshToken); - String getRefreshToken(Long id); + String getRefreshToken(Long id); - void deleteRefreshToken(Long id); + void deleteRefreshToken(Long id); - User userInfo(Long id); + User userInfo(Long id); - String getUserName(Long id); + String getUserName(Long id); - void changeUserInfo(InfoDto infoDto,Long id); + void changeUserInfo(InfoDto infoDto, Long id); - void changePassword(PasswordDto passwordDto,Long id); + void changePassword(PasswordDto passwordDto, Long id); - boolean isUserIdExist(String userId); + boolean isUserIdExist(String userId); + + boolean isEmailExist(String email); + + void changeForgottenPassword(Long id, String newPassword); } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java index 77fd4ca..9cd9705 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java @@ -3,11 +3,11 @@ package com.edufocus.edufocus.user.model.service; import com.edufocus.edufocus.user.model.entity.dto.InfoDto; import com.edufocus.edufocus.user.model.entity.dto.PasswordDto; -import com.edufocus.edufocus.user.util.PasswordUtils; import com.edufocus.edufocus.user.model.entity.dto.RequestJoinDto; import com.edufocus.edufocus.user.model.entity.vo.User; import com.edufocus.edufocus.user.model.exception.UserException; import com.edufocus.edufocus.user.model.repository.UserRepository; +import com.edufocus.edufocus.user.util.PasswordUtils; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -23,8 +23,7 @@ public class UserServiceImpl implements UserService { private final UserRepository userRepository; - public void join(RequestJoinDto requestJoinDto) - { + public void join(RequestJoinDto requestJoinDto) { User user = User.builder() .userId(requestJoinDto.getUserId()) .email(requestJoinDto.getEmail()) @@ -36,7 +35,7 @@ public class UserServiceImpl implements UserService { } - public User login(User user){ + public User login(User user) { Optional findUser = userRepository.findByUserId(user.getUserId()); if (findUser.isEmpty()) { @@ -63,32 +62,29 @@ public class UserServiceImpl implements UserService { } - - - @Override - public String getUserName(Long id){ + public String getUserName(Long id) { return userRepository.findById(id).get().getName(); } @Override - public void changeUserInfo(InfoDto infoDto, Long id){ + public void changeUserInfo(InfoDto infoDto, Long id) { User user = userRepository.findById(id).orElseThrow(IllegalArgumentException::new); if (infoDto.getName() != null) user.setName(infoDto.getName()); - if(infoDto.getEmail()!=null) + if (infoDto.getEmail() != null) user.setEmail(infoDto.getEmail()); userRepository.save(user); -} + } @Override - public void changePassword(PasswordDto passwordDto, Long id){ + public void changePassword(PasswordDto passwordDto, Long id) { User user = userRepository.findById(id).orElse(null); if (user == null) { @@ -114,30 +110,52 @@ public class UserServiceImpl implements UserService { } public String getTempPassword() { - char[] charSet = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', + char[] charSet = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}; String str = ""; int idx = 0; - for (int i=0; i<10; i++) { + for (int i = 0; i < 10; i++) { idx = (int) (charSet.length * Math.random()); str += charSet[idx]; } return str; } + @Override - public void saveRefreshToken(Long id, String refreshToken){ + public void saveRefreshToken(Long id, String refreshToken) { userRepository.saveRefreshToken(id, refreshToken); } @Override - public String getRefreshToken(Long id){ + public String getRefreshToken(Long id) { return userRepository.getRefreshToken(id); } @Override - public void deleteRefreshToken(Long id){ + public void deleteRefreshToken(Long id) { userRepository.deleteRefreshToken(id); } + @Override + public boolean isEmailExist(String email) { + Optional user = userRepository.findByEmail(email); + + return user.isPresent(); + } + + @Override + public void changeForgottenPassword(Long id, String newPassword) { + User user = userRepository.findById(id).orElse(null); + + if (user == null) { + throw new UserException("User not found"); + } + + // Hash the new password before saving + user.setPassword(PasswordUtils.hashPassword(newPassword)); + userRepository.save(user); + } + + } diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index aa22dc0..479d1de 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -29,4 +29,13 @@ spring.rabbitmq.host=${RABBITMQ_HOST} spring.rabbitmq.port=${RABBITMQ_PORT} spring.rabbitmq.username=${RABBITMQ_USERNAME} spring.rabbitmq.password=${RABBITMQ_PASSWORD} -image.path=${IMAGE_PATH} \ No newline at end of file +image.path=${IMAGE_PATH} +spring.mail.host=smtp.gmail.com +spring.mail.port=${MAIL_PORT} +spring.mail.username=${MAIL_NAME} +spring.mail.password=${MAIL_PASSWORD} +spring.mail.properties.mail.smtp.auth=true +spring.mail.properties.mail.smtp.timeout=5000 +spring.mail.properties.mail.smtp.starttls.enable=true +spring.data.redis.host=${REDIS_HOST} +spring.data.redis.port=${REDIS_PORT} \ No newline at end of file From d9adb66800d2fe85fe55d7b808389c6214fb7a9d Mon Sep 17 00:00:00 2001 From: kgc91747 Date: Wed, 7 Aug 2024 10:45:35 +0900 Subject: [PATCH 131/197] fix: conflict solve --- .../edufocus/user/model/service/UserServiceImpl.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java index ea2d0a5..c50e1c9 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java @@ -142,13 +142,6 @@ public class UserServiceImpl implements UserService { userRepository.deleteRefreshToken(id); } - @Override - public boolean isEmailExist(String email) { - Optional user = userRepository.findByEmail(email); - - return user.isPresent(); - } - @Override public void changeForgottenPassword(Long id, String newPassword) { User user = userRepository.findById(id).orElse(null); From 208bd69d5bcf16a99049fa6204a1179c758cd83e Mon Sep 17 00:00:00 2001 From: yulmam <70622601+yulmam@users.noreply.github.com> Date: Wed, 7 Aug 2024 11:08:26 +0900 Subject: [PATCH 132/197] =?UTF-8?q?feat=20:=20=EA=B2=8C=EC=8B=9C=ED=8C=90?= =?UTF-8?q?=20=EB=8C=93=EA=B8=80=20=EC=9E=91=EC=84=B1=EC=9E=90=20=EC=B2=B4?= =?UTF-8?q?=ED=81=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../board/controller/BoardController.java | 19 +++++++++++++------ .../entity/dto/ResponseBoardDetailDto.java | 2 +- .../board/entity/dto/ResponseCommentDto.java | 1 + .../edufocus/board/entity/vo/Board.java | 4 ++-- .../edufocus/board/entity/vo/Comment.java | 3 ++- .../edufocus/board/service/BoardService.java | 4 ++-- .../board/service/BoardServiceImpl.java | 8 ++++---- 7 files changed, 25 insertions(+), 16 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java b/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java index 5bd154d..309acb6 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java @@ -45,9 +45,13 @@ public class BoardController { @GetMapping(value = "/{boardId}") public ResponseEntity getBoardDetail( - @PathVariable int boardId + @PathVariable int boardId, + HttpServletRequest request ){ - ResponseBoardDetailDto responseBoardDetailDto = boardService.findBoardDetail(boardId); + String token = request.getHeader("Authorization"); + long userId = Long.parseLong(jwtUtil.getUserId(token)); + + ResponseBoardDetailDto responseBoardDetailDto = boardService.findBoardDetail(userId, boardId); return new ResponseEntity<>(responseBoardDetailDto, HttpStatus.OK); } @@ -77,8 +81,7 @@ public class BoardController { @DeleteMapping(value = "/{boardId}") public ResponseEntity deleteBoard( - @PathVariable int boardId, - HttpServletRequest request + @PathVariable int boardId ){ boardService.deleteBoard(boardId); @@ -87,9 +90,13 @@ public class BoardController { @GetMapping(value = "/comment/{boardId}") public ResponseEntity> getComments( - @PathVariable int boardId + @PathVariable int boardId, + HttpServletRequest request ){ - List comments = boardService.findComments(boardId); + String token = request.getHeader("Authorization"); + long userId = Long.parseLong(jwtUtil.getUserId(token)); + + List comments = boardService.findComments(userId, boardId); return new ResponseEntity<>(comments, HttpStatus.OK); } diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardDetailDto.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardDetailDto.java index e050da7..7a6e8fe 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardDetailDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardDetailDto.java @@ -16,7 +16,7 @@ public class ResponseBoardDetailDto { private String name; private String title; private String content; - private int viewCount; + private boolean isMine; private LocalDateTime createdAt; private LocalDateTime modifiedAt; } diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseCommentDto.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseCommentDto.java index 180c6b1..2e0ec6e 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseCommentDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseCommentDto.java @@ -14,6 +14,7 @@ public class ResponseCommentDto { private long id; private String name; private String content; + private boolean isMine; private LocalDateTime createAt; private LocalDateTime modifiedAt; } diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java index ff8d039..e1e4ac6 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java @@ -67,13 +67,13 @@ public class Board { .build(); } - public ResponseBoardDetailDto makeDetailDto(){ + public ResponseBoardDetailDto makeDetailDto(long userId){ return ResponseBoardDetailDto.builder() .id(id) .name(user.getName()) .title(title) .content(content) - .viewCount(viewCount) + .isMine(user.getId() == userId) .createdAt(createdAt) .modifiedAt(modifiedAt) .build(); diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java index d7c97c2..aa05c5b 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java @@ -39,11 +39,12 @@ public class Comment { @JoinColumn(name = "board_id") Board board; - public ResponseCommentDto makeCommentDto() { + public ResponseCommentDto makeCommentDto(long userId) { return ResponseCommentDto.builder() .id(id) .name(user.getName()) .content(content) + .isMine(user.getId() == userId) .createAt(createdAt) .modifiedAt(modifiedAt) .build(); diff --git a/backend/src/main/java/com/edufocus/edufocus/board/service/BoardService.java b/backend/src/main/java/com/edufocus/edufocus/board/service/BoardService.java index f0d25f8..d5c646d 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/service/BoardService.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/service/BoardService.java @@ -10,7 +10,7 @@ public interface BoardService { public List findBoards(int pageNo, String category, long lectureId); - public ResponseBoardDetailDto findBoardDetail(long boardId); + public ResponseBoardDetailDto findBoardDetail(long userId, long boardId); public void updateBoard(long boardId, RequestBoardUpdateDto requestBoardUpdateDto); @@ -18,7 +18,7 @@ public interface BoardService { public void createComment(long userId, long boardId, RequestCommentDto requestCommentDto); - public List findComments(long boardId); + public List findComments(long userId, long boardId); public void updateComment(long commentId, RequestCommentDto requestCommentDto); diff --git a/backend/src/main/java/com/edufocus/edufocus/board/service/BoardServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/board/service/BoardServiceImpl.java index f471fed..3fc7250 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/service/BoardServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/service/BoardServiceImpl.java @@ -48,10 +48,10 @@ public class BoardServiceImpl implements BoardService { } @Transactional - public ResponseBoardDetailDto findBoardDetail(long boardId) { + public ResponseBoardDetailDto findBoardDetail(long userId, long boardId) { return boardRepository.findById(boardId) .orElseThrow(NoSuchElementException::new) - .makeDetailDto(); + .makeDetailDto(userId); } @Transactional @@ -89,9 +89,9 @@ public class BoardServiceImpl implements BoardService { } @Transactional - public List findComments(long boardId) { + public List findComments(long userId, long boardId) { return commentRepository.findByBoardId(boardId).stream() - .map(Comment::makeCommentDto) + .map((Comment c) -> c.makeCommentDto(userId)) .collect(Collectors.toList()); } From 919b61c47c47d52fda56f9acd76f81424999ba8e Mon Sep 17 00:00:00 2001 From: kgc91747 Date: Wed, 7 Aug 2024 13:42:17 +0900 Subject: [PATCH 133/197] =?UTF-8?q?refactor:=20email=20API=20=EA=B2=BD?= =?UTF-8?q?=EB=A1=9C=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/edufocus/edufocus/mail/controller/MailController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/mail/controller/MailController.java b/backend/src/main/java/com/edufocus/edufocus/mail/controller/MailController.java index a6df23d..ee2c38d 100644 --- a/backend/src/main/java/com/edufocus/edufocus/mail/controller/MailController.java +++ b/backend/src/main/java/com/edufocus/edufocus/mail/controller/MailController.java @@ -18,7 +18,7 @@ public class MailController { private final UserService userService; - @PostMapping("/sendCode") + @PostMapping("/sendcode") public ResponseEntity sendMail(@RequestParam String email) { if (!userService.isEmailExist(email)) { return new ResponseEntity<>(HttpStatus.NOT_FOUND); From 9032a156c4553ff7571cd80d713722eb194e8c1f Mon Sep 17 00:00:00 2001 From: kgc91747 Date: Wed, 7 Aug 2024 14:23:44 +0900 Subject: [PATCH 134/197] =?UTF-8?q?feat:=20redis=20password=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/main/resources/application.properties | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 483ec8b..d46f4df 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -38,4 +38,5 @@ spring.mail.properties.mail.smtp.auth=true spring.mail.properties.mail.smtp.timeout=5000 spring.mail.properties.mail.smtp.starttls.enable=true spring.data.redis.host=${REDIS_HOST} -spring.data.redis.port=${REDIS_PORT} \ No newline at end of file +spring.data.redis.port=${REDIS_PORT} +spring.data.redis.password=${REDIS_PASSWORD} \ No newline at end of file From c3c574baf31c9112c95370dd94a91f0666fd6665 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Wed, 7 Aug 2024 15:30:54 +0900 Subject: [PATCH 135/197] =?UTF-8?q?feat:=20qna=20=EB=8B=B5=EB=B3=80=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/qna/service/QnaServiceImpl.java | 24 +++++++------- .../report/service/ReportServiceImpl.java | 2 +- .../user/model/service/UserServiceImpl.java | 31 +++++++++---------- 3 files changed, 28 insertions(+), 29 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java index 80ea7ae..dbc6d84 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java @@ -7,6 +7,7 @@ import com.edufocus.edufocus.qna.entity.QnaRequestDto; import com.edufocus.edufocus.qna.entity.QnaResponseDto; import com.edufocus.edufocus.qna.repository.QnaRepository; import com.edufocus.edufocus.user.model.entity.vo.User; +import com.edufocus.edufocus.user.model.entity.vo.UserRole; import com.edufocus.edufocus.user.model.repository.UserRepository; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; @@ -24,14 +25,13 @@ import java.util.stream.Collectors; @Service @Transactional @RequiredArgsConstructor -public class QnaServiceImpl implements QnaService{ +public class QnaServiceImpl implements QnaService { private final QnaRepository qnaRepository; private final LectureRepository lectureRepository; private final UserRepository userRepository; - @Override public QnaResponseDto createQna(Long id, QnaRequestDto qnaRequestDto, Long lecture_id) { @@ -41,19 +41,21 @@ public class QnaServiceImpl implements QnaService{ User user = userRepository.findById(id).orElse(null); - Qna qna = QnaRequestDto.toEntity(qnaRequestDto); + if (qna.getAnswer() != null || user.getRole() != UserRole.ADMIN) { + throw new RuntimeException(); + } qna.setLecture(lecture); qna.setUser(user); qna.setCreatedAt(new Date()); qnaRepository.save(qna); - return QnaResponseDto.toEntity(qna); + return QnaResponseDto.toEntity(qna); } @Override - public QnaResponseDto updateQna(Long id,QnaRequestDto qnaRequestDto) { + public QnaResponseDto updateQna(Long id, QnaRequestDto qnaRequestDto) { Qna findQna = qnaRepository.findById(id) @@ -65,14 +67,14 @@ public class QnaServiceImpl implements QnaService{ qnaRepository.save(findQna); - return QnaResponseDto.toEntity(findQna); + return QnaResponseDto.toEntity(findQna); } @Override public void deleteQna(Long id) { -qnaRepository.deleteById(id); + qnaRepository.deleteById(id); } @Override @@ -80,7 +82,7 @@ qnaRepository.deleteById(id); Optional qna; try { - qna= qnaRepository.findById(id); + qna = qnaRepository.findById(id); } catch (Exception e) { @@ -89,14 +91,12 @@ qnaRepository.deleteById(id); } - - return QnaResponseDto.toEntity(qna.get()); + return QnaResponseDto.toEntity(qna.get()); } @Override - public List getAllQnasByLecture(Long lectureId,int pageSize) - { + public List getAllQnasByLecture(Long lectureId, int pageSize) { Pageable pageable = PageRequest.of(0, pageSize); diff --git a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java index 5543795..d6c2cbc 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java @@ -60,7 +60,6 @@ public class ReportServiceImpl implements ReportService { Quiz quiz = quizList.get(idx); String inputAnswer = answerInputList.get(idx); Answer answer; - // if (quiz.getAnswer().equals(inputAnswer)) { correctCount++; answer = Answer.builder() @@ -183,6 +182,7 @@ public class ReportServiceImpl implements ReportService { List reportList = reportRepository.findByUser_Id(userId); + List reportListResponseDtoList = new ArrayList<>(); diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java index 77fd4ca..93ef8c5 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java @@ -23,8 +23,7 @@ public class UserServiceImpl implements UserService { private final UserRepository userRepository; - public void join(RequestJoinDto requestJoinDto) - { + public void join(RequestJoinDto requestJoinDto) { User user = User.builder() .userId(requestJoinDto.getUserId()) .email(requestJoinDto.getEmail()) @@ -36,7 +35,7 @@ public class UserServiceImpl implements UserService { } - public User login(User user){ + public User login(User user) { Optional findUser = userRepository.findByUserId(user.getUserId()); if (findUser.isEmpty()) { @@ -63,32 +62,29 @@ public class UserServiceImpl implements UserService { } - - - @Override - public String getUserName(Long id){ + public String getUserName(Long id) { return userRepository.findById(id).get().getName(); } @Override - public void changeUserInfo(InfoDto infoDto, Long id){ + public void changeUserInfo(InfoDto infoDto, Long id) { User user = userRepository.findById(id).orElseThrow(IllegalArgumentException::new); if (infoDto.getName() != null) user.setName(infoDto.getName()); - if(infoDto.getEmail()!=null) + if (infoDto.getEmail() != null) user.setEmail(infoDto.getEmail()); userRepository.save(user); -} + } @Override - public void changePassword(PasswordDto passwordDto, Long id){ + public void changePassword(PasswordDto passwordDto, Long id) { User user = userRepository.findById(id).orElse(null); if (user == null) { @@ -97,6 +93,8 @@ public class UserServiceImpl implements UserService { if (!PasswordUtils.checkPassword(passwordDto.getCurrentPassword(), user.getPassword())) { throw new UserException("Current password is incorrect"); + } else if (passwordDto.getCurrentPassword().equals(passwordDto.getNewPassword())) { + throw new UserException("New password cannot be the same as the current password"); } else { if (!passwordDto.getNewPassword().equals(passwordDto.getNewPasswordCheck())) { throw new UserException("New password confirmation does not match"); @@ -114,29 +112,30 @@ public class UserServiceImpl implements UserService { } public String getTempPassword() { - char[] charSet = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', + char[] charSet = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}; String str = ""; int idx = 0; - for (int i=0; i<10; i++) { + for (int i = 0; i < 10; i++) { idx = (int) (charSet.length * Math.random()); str += charSet[idx]; } return str; } + @Override - public void saveRefreshToken(Long id, String refreshToken){ + public void saveRefreshToken(Long id, String refreshToken) { userRepository.saveRefreshToken(id, refreshToken); } @Override - public String getRefreshToken(Long id){ + public String getRefreshToken(Long id) { return userRepository.getRefreshToken(id); } @Override - public void deleteRefreshToken(Long id){ + public void deleteRefreshToken(Long id) { userRepository.deleteRefreshToken(id); } From 8d4d9e02272f5ba6784b37f1f6033bd438dd031a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Wed, 7 Aug 2024 16:57:38 +0900 Subject: [PATCH 136/197] =?UTF-8?q?feat:=20qna=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../qna/controller/QnaController.java | 98 +++++++++++-------- .../edufocus/qna/service/QnaService.java | 17 +++- .../edufocus/qna/service/QnaServiceImpl.java | 30 ++++-- 3 files changed, 95 insertions(+), 50 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java b/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java index fe50454..90f33c6 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java @@ -4,6 +4,9 @@ import com.edufocus.edufocus.qna.entity.Qna; import com.edufocus.edufocus.qna.entity.QnaRequestDto; import com.edufocus.edufocus.qna.entity.QnaResponseDto; import com.edufocus.edufocus.qna.service.QnaService; +import com.edufocus.edufocus.user.model.entity.vo.User; +import com.edufocus.edufocus.user.model.entity.vo.UserRole; +import com.edufocus.edufocus.user.model.repository.UserRepository; import com.edufocus.edufocus.user.util.JWTUtil; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; @@ -23,81 +26,98 @@ import java.util.List; public class QnaController { private final QnaService qnaService; private final JWTUtil jwtUtil; - private static int PAGE_SIZE=10; - + private static int PAGE_SIZE = 10; + private final UserRepository userRepository; @PostMapping("/{lecture_id}") - public ResponseEntity createQna(@PathVariable("lecture_id") Long lecture_id, @RequestBody QnaRequestDto qnaRequestDto , HttpServletRequest request) { + public ResponseEntity createQna(@PathVariable("lecture_id") Long lecture_id, @RequestBody QnaRequestDto qnaRequestDto, HttpServletRequest request) { - try{ + try { String token = request.getHeader("Authorization"); Long userId = Long.parseLong(jwtUtil.getUserId(token)); - QnaResponseDto qnaResponseDto= qnaService.createQna(userId,qnaRequestDto,lecture_id); - return new ResponseEntity<>( qnaResponseDto,HttpStatus.CREATED); + QnaResponseDto qnaResponseDto = qnaService.createQna(userId, qnaRequestDto, lecture_id); + return new ResponseEntity<>(qnaResponseDto, HttpStatus.CREATED); - }catch (Exception e){ + } catch (Exception e) { throw new RuntimeException(e); } } @PostMapping({"/answer/create/{qna_id}"}) - public ResponseEntity createAnswer(@PathVariable("qna_id") Long qna_id, @RequestBody QnaRequestDto qnaRequestDto) - { + public ResponseEntity createAnswer(@PathVariable("qna_id") Long qna_id, @RequestBody QnaRequestDto qnaRequestDto, HttpServletRequest request) { try { - QnaResponseDto responseDto = qnaService.createAnswer(qna_id,qnaRequestDto); - return new ResponseEntity<>(responseDto,HttpStatus.ACCEPTED); - } - catch (Exception e) - { + String token = request.getHeader("Authorization"); + Long userId = Long.parseLong(jwtUtil.getUserId(token)); + User findUser = userRepository.findById(userId).orElse(null); + + if (findUser.getRole() != UserRole.ADMIN) { + throw new RuntimeException(); + } + + QnaResponseDto responseDto = qnaService.createAnswer(qna_id, qnaRequestDto); + return new ResponseEntity<>(responseDto, HttpStatus.ACCEPTED); + } catch (Exception e) { throw new RuntimeException(e); } } @PutMapping({"/answer/update/{qna_id}"}) - public ResponseEntity updateAnswer(@PathVariable("qna_id") Long qna_id, @RequestBody QnaRequestDto qnaRequestDto) - { + public ResponseEntity updateAnswer(@PathVariable("qna_id") Long qna_id, @RequestBody QnaRequestDto qnaRequestDto, HttpServletRequest request) { try { - QnaResponseDto responseDto = qnaService.updateAnswer(qna_id,qnaRequestDto); - return new ResponseEntity<>(responseDto,HttpStatus.ACCEPTED); - } - catch (Exception e) - { + String token = request.getHeader("Authorization"); + Long userId = Long.parseLong(jwtUtil.getUserId(token)); + User findUser = userRepository.findById(userId).orElse(null); + + if (findUser.getRole() != UserRole.ADMIN) { + throw new RuntimeException(); + } + + QnaResponseDto responseDto = qnaService.updateAnswer(qna_id, qnaRequestDto); + return new ResponseEntity<>(responseDto, HttpStatus.ACCEPTED); + } catch (Exception e) { throw new RuntimeException(e); } } @PostMapping("/answer/delete/{qna_id}") - public ResponseEntity deleteAnswer(@PathVariable("qna_id") Long qna_id) - { + public ResponseEntity deleteAnswer(@PathVariable("qna_id") Long qna_id, HttpServletRequest request) { try { - qnaService.deleteAnswer(qna_id); + String token = request.getHeader("Authorization"); + Long userId = Long.parseLong(jwtUtil.getUserId(token)); + User findUser = userRepository.findById(userId).orElse(null); + + if (findUser.getRole() != UserRole.ADMIN) { + throw new RuntimeException(); + } + qnaService.deleteAnswer(qna_id); return new ResponseEntity<>(HttpStatus.ACCEPTED); - } - catch (Exception e) - { + } catch (Exception e) { throw new RuntimeException(e); } } @PutMapping("/{id}") - public ResponseEntity updateQna(@PathVariable Long id, @RequestBody QnaRequestDto qnaRequestDto) { - - try{ - QnaResponseDto qnaResponseDto= qnaService.updateQna(id,qnaRequestDto); + public ResponseEntity updateQna(@PathVariable Long id, @RequestBody QnaRequestDto qnaRequestDto, HttpServletRequest request) { + String token = request.getHeader("Authorization"); + Long userId = Long.parseLong(jwtUtil.getUserId(token)); + try { + QnaResponseDto qnaResponseDto = qnaService.updateQna(id, qnaRequestDto, userId); return new ResponseEntity<>(qnaResponseDto, HttpStatus.ACCEPTED); - }catch (Exception e) - { - throw new RuntimeException(e); } + } catch (Exception e) { + throw new RuntimeException(e); + } } @DeleteMapping("/{id}") - public ResponseEntity deleteQna(@PathVariable Long id) { + public ResponseEntity deleteQna(@PathVariable Long id, HttpServletRequest request) { try { - qnaService.deleteQna(id); + String token = request.getHeader("Authorization"); + Long userId = Long.parseLong(jwtUtil.getUserId(token)); + qnaService.deleteQna(id, userId); return new ResponseEntity<>(HttpStatus.ACCEPTED); } catch (SQLException e) { @@ -107,8 +127,8 @@ public class QnaController { @GetMapping("/{id}") public ResponseEntity getQna(@PathVariable Long id) { - try{ - QnaResponseDto findQna= qnaService.getQna(id); + try { + QnaResponseDto findQna = qnaService.getQna(id); return new ResponseEntity<>(findQna, HttpStatus.ACCEPTED); } catch (SQLException e) { @@ -121,7 +141,7 @@ public class QnaController { try { - List qnaList= qnaService.getAllQnasByLecture(id,PAGE_SIZE); + List qnaList = qnaService.getAllQnasByLecture(id, PAGE_SIZE); return new ResponseEntity<>(qnaList, HttpStatus.ACCEPTED); } catch (SQLException e) { diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaService.java b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaService.java index de97f93..912ed9e 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaService.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaService.java @@ -10,17 +10,24 @@ import org.springframework.stereotype.Service; import java.sql.SQLException; import java.util.List; + @Service public interface QnaService { QnaResponseDto createQna(Long id, QnaRequestDto qnaRequestDto, Long lecture_id) throws SQLException; - QnaResponseDto updateQna(Long id,QnaRequestDto qnaRequestDto) throws SQLException; - void deleteQna(Long id) throws SQLException; + + QnaResponseDto updateQna(Long id, QnaRequestDto qnaRequestDto, Long userId) throws SQLException; + + void deleteQna(Long id, Long userId) throws SQLException; + QnaResponseDto getQna(Long id) throws SQLException; - List getAllQnasByLecture(Long lectureId,int pageNumber) throws SQLException; - QnaResponseDto createAnswer(Long id,QnaRequestDto qnaRequestDto) throws SQLException; - QnaResponseDto updateAnswer(Long id,QnaRequestDto qnaRequestDto) throws SQLException; + List getAllQnasByLecture(Long lectureId, int pageNumber) throws SQLException; + + QnaResponseDto createAnswer(Long id, QnaRequestDto qnaRequestDto) throws SQLException; + + QnaResponseDto updateAnswer(Long id, QnaRequestDto qnaRequestDto) throws SQLException; + void deleteAnswer(Long id) throws SQLException; } diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java index dbc6d84..637239c 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java @@ -42,9 +42,7 @@ public class QnaServiceImpl implements QnaService { Qna qna = QnaRequestDto.toEntity(qnaRequestDto); - if (qna.getAnswer() != null || user.getRole() != UserRole.ADMIN) { - throw new RuntimeException(); - } + qna.setLecture(lecture); qna.setUser(user); @@ -55,7 +53,15 @@ public class QnaServiceImpl implements QnaService { } @Override - public QnaResponseDto updateQna(Long id, QnaRequestDto qnaRequestDto) { + public QnaResponseDto updateQna(Long id, QnaRequestDto qnaRequestDto, Long userId) { + + Qna qna = qnaRepository.findById(id).orElse(null); + User user = userRepository.findById(userId).orElse(null); + if (qna.getUser().getId() == userId) { + qnaRepository.delete(qna); + } else { + throw new RuntimeException(); + } Qna findQna = qnaRepository.findById(id) @@ -73,8 +79,16 @@ public class QnaServiceImpl implements QnaService { } @Override - public void deleteQna(Long id) { - qnaRepository.deleteById(id); + public void deleteQna(Long id, Long userId) { + + Qna qna = qnaRepository.findById(id).orElse(null); + User user = userRepository.findById(userId).orElse(null); + if (qna.getUser().getId() == userId || user.getRole() == UserRole.ADMIN) { + qnaRepository.delete(qna); + } else { + throw new RuntimeException(); + } + } @Override @@ -115,6 +129,9 @@ public class QnaServiceImpl implements QnaService { Qna findQna = qnaRepository.findById(id).orElse(null); findQna.setAnswer(qnaRequestDto.getAnswer()); + if (findQna.getAnswer() != null) { + throw new RuntimeException(); + } qnaRepository.save(findQna); return QnaResponseDto.toEntity(findQna); @@ -127,6 +144,7 @@ public class QnaServiceImpl implements QnaService { Qna findQna = qnaRepository.findById(id).orElse(null); findQna.setAnswer(qnaRequestDto.getAnswer()); + qnaRepository.save(findQna); return QnaResponseDto.toEntity(findQna); From 25f7343b0430e9a8e7f072f0e584bdb7a8c27f9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Wed, 7 Aug 2024 17:04:19 +0900 Subject: [PATCH 137/197] =?UTF-8?q?feat:qna=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/edufocus/edufocus/qna/controller/QnaController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java b/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java index 90f33c6..64b2e73 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java @@ -71,7 +71,7 @@ public class QnaController { User findUser = userRepository.findById(userId).orElse(null); if (findUser.getRole() != UserRole.ADMIN) { - throw new RuntimeException(); + throw new RuntimeException("update 실패"); } QnaResponseDto responseDto = qnaService.updateAnswer(qna_id, qnaRequestDto); From e9d0db30e52e03863a7ef2140c9e8dd2f5801101 Mon Sep 17 00:00:00 2001 From: kgc91747 Date: Wed, 7 Aug 2024 17:19:07 +0900 Subject: [PATCH 138/197] =?UTF-8?q?feat:=20=EC=9D=B4=EB=A9=94=EC=9D=BC=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20=EC=BD=94=EB=93=9C=20=EC=9E=AC=EC=9A=94?= =?UTF-8?q?=EC=B2=AD=EC=8B=9C=20=EA=B8=B0=EC=A1=B4=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/mail/service/MailServiceImpl.java | 15 ++++++++++----- .../edufocus/edufocus/redis/util/RedisUtil.java | 4 ++++ .../edufocus/user/controller/UserController.java | 4 ++-- .../edufocus/user/model/service/UserService.java | 2 +- .../user/model/service/UserServiceImpl.java | 4 ++-- 5 files changed, 19 insertions(+), 10 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/mail/service/MailServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/mail/service/MailServiceImpl.java index 20859de..f5c08b6 100644 --- a/backend/src/main/java/com/edufocus/edufocus/mail/service/MailServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/mail/service/MailServiceImpl.java @@ -1,7 +1,6 @@ package com.edufocus.edufocus.mail.service; import com.edufocus.edufocus.redis.util.RedisUtil; -import com.edufocus.edufocus.user.model.entity.vo.User; import com.edufocus.edufocus.user.model.repository.UserRepository; import com.edufocus.edufocus.user.model.service.UserService; import lombok.RequiredArgsConstructor; @@ -11,7 +10,6 @@ import org.springframework.mail.SimpleMailMessage; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.stereotype.Service; -import java.util.NoSuchElementException; import java.util.Random; @Service @@ -31,10 +29,16 @@ public class MailServiceImpl implements MailService { @Override public void sendMail(String email) { String code = createRandomCode(); - redisUtil.setDataExpire(code, email, 60 * 5L); - SimpleMailMessage mail = createEmail(email, "[EDUFOCUS] 비밀번호 찾기 안내", code); - mailSender.send(mail); + if (redisUtil.exists(email)) { + redisUtil.deleteData(redisUtil.getData(email)); + } + + redisUtil.setDataExpire(code, email, 60 * 5L); + redisUtil.setDataExpire(email, code, 60 * 5L); + +// SimpleMailMessage mail = createEmail(email, "[EDUFOCUS] 비밀번호 찾기 안내", code); +// mailSender.send(mail); } @Override @@ -46,6 +50,7 @@ public class MailServiceImpl implements MailService { private SimpleMailMessage createEmail(String to, String title, String code) { SimpleMailMessage message = new SimpleMailMessage(); + message.setFrom("EDUFOCUS"); message.setTo(to); message.setSubject(title); message.setText("인증번호 6자리입니다 : " + code); diff --git a/backend/src/main/java/com/edufocus/edufocus/redis/util/RedisUtil.java b/backend/src/main/java/com/edufocus/edufocus/redis/util/RedisUtil.java index ad9bf09..d13b40f 100644 --- a/backend/src/main/java/com/edufocus/edufocus/redis/util/RedisUtil.java +++ b/backend/src/main/java/com/edufocus/edufocus/redis/util/RedisUtil.java @@ -33,4 +33,8 @@ public class RedisUtil { stringRedisTemplate.delete(key); } + public boolean exists(String key) { + return stringRedisTemplate.hasKey(key); + } + } \ No newline at end of file diff --git a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java index 791fa4b..bb3818f 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java @@ -71,9 +71,9 @@ public class UserController { // 비밀번호 찾기를 통한 변경 @PutMapping("/updateforgottenpassword") - public ResponseEntity updatePassword(@RequestParam long userId, + public ResponseEntity updatePassword(@RequestParam String email, @RequestParam String newPassword) { - userService.changeForgottenPassword(userId, newPassword); + userService.changeForgottenPassword(email, newPassword); return new ResponseEntity<>(HttpStatus.OK); } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java index 0737045..9a4b9ef 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java @@ -28,5 +28,5 @@ public interface UserService { boolean isEmailExist(String email); - void changeForgottenPassword(Long id, String newPassword); + void changeForgottenPassword(String email, String newPassword); } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java index c50e1c9..d211644 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java @@ -143,8 +143,8 @@ public class UserServiceImpl implements UserService { } @Override - public void changeForgottenPassword(Long id, String newPassword) { - User user = userRepository.findById(id).orElse(null); + public void changeForgottenPassword(String email, String newPassword) { + User user = userRepository.findByEmail(email).orElse(null); if (user == null) { throw new UserException("User not found"); From 78cfed17e7e62b88a5254310fbf6c361231e1adc Mon Sep 17 00:00:00 2001 From: kgc91747 Date: Wed, 7 Aug 2024 17:27:46 +0900 Subject: [PATCH 139/197] =?UTF-8?q?feat:=20=EC=9D=B4=EB=A9=94=EC=9D=BC=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20=EC=8B=A4=ED=8C=A8=EC=8B=9C=20=EB=B0=98?= =?UTF-8?q?=ED=99=98=EA=B0=92=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/edufocus/edufocus/mail/controller/MailController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/mail/controller/MailController.java b/backend/src/main/java/com/edufocus/edufocus/mail/controller/MailController.java index ee2c38d..bc6be99 100644 --- a/backend/src/main/java/com/edufocus/edufocus/mail/controller/MailController.java +++ b/backend/src/main/java/com/edufocus/edufocus/mail/controller/MailController.java @@ -31,7 +31,7 @@ public class MailController { @GetMapping("/verify") public ResponseEntity verifyCode(@RequestParam String code, @RequestParam String email) { if (!mailService.verifyCode(code, email)) { - return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + return new ResponseEntity<>(HttpStatus.NOT_FOUND); } return new ResponseEntity<>(HttpStatus.OK); } From 25fb49a4ba3555b70b59baaace565274f0196feb Mon Sep 17 00:00:00 2001 From: kgc91747 Date: Wed, 7 Aug 2024 17:37:19 +0900 Subject: [PATCH 140/197] =?UTF-8?q?feat:=20=EC=9D=B4=EB=A9=94=EC=9D=BC=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...d4af-2922-4057-81cd-756e62ddd13c_testimg1.jpg | Bin 8567 -> 0 bytes ...3f29-11a6-4026-82fb-5a1d0beb9130_testImg2.jpg | Bin 8567 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 backend/backend/src/main/resources/images/0a51d4af-2922-4057-81cd-756e62ddd13c_testimg1.jpg delete mode 100644 backend/backend/src/main/resources/images/0bef3f29-11a6-4026-82fb-5a1d0beb9130_testImg2.jpg diff --git a/backend/backend/src/main/resources/images/0a51d4af-2922-4057-81cd-756e62ddd13c_testimg1.jpg b/backend/backend/src/main/resources/images/0a51d4af-2922-4057-81cd-756e62ddd13c_testimg1.jpg deleted file mode 100644 index c53ac5e358df846b8d20f1928bd0860aa4302f24..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8567 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 Date: Wed, 7 Aug 2024 17:37:59 +0900 Subject: [PATCH 141/197] =?UTF-8?q?feat:=20=EC=9D=B4=EB=A9=94=EC=9D=BC=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/edufocus/edufocus/mail/service/MailServiceImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/mail/service/MailServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/mail/service/MailServiceImpl.java index f5c08b6..201c99d 100644 --- a/backend/src/main/java/com/edufocus/edufocus/mail/service/MailServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/mail/service/MailServiceImpl.java @@ -37,8 +37,8 @@ public class MailServiceImpl implements MailService { redisUtil.setDataExpire(code, email, 60 * 5L); redisUtil.setDataExpire(email, code, 60 * 5L); -// SimpleMailMessage mail = createEmail(email, "[EDUFOCUS] 비밀번호 찾기 안내", code); -// mailSender.send(mail); + SimpleMailMessage mail = createEmail(email, "[EDUFOCUS] 비밀번호 찾기 안내", code); + mailSender.send(mail); } @Override From a732cb78c66f161d5df43de1ac143e448db2b9c8 Mon Sep 17 00:00:00 2001 From: kgc91747 Date: Wed, 7 Aug 2024 17:42:13 +0900 Subject: [PATCH 142/197] =?UTF-8?q?feat:=20=EC=9D=B4=EB=A9=94=EC=9D=BC=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...d4af-2922-4057-81cd-756e62ddd13c_testimg1.jpg | Bin 8567 -> 0 bytes ...3f29-11a6-4026-82fb-5a1d0beb9130_testImg2.jpg | Bin 8567 -> 0 bytes .../edufocus/mail/service/MailServiceImpl.java | 4 ++-- 3 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 backend/backend/src/main/resources/images/0a51d4af-2922-4057-81cd-756e62ddd13c_testimg1.jpg delete mode 100644 backend/backend/src/main/resources/images/0bef3f29-11a6-4026-82fb-5a1d0beb9130_testImg2.jpg diff --git a/backend/backend/src/main/resources/images/0a51d4af-2922-4057-81cd-756e62ddd13c_testimg1.jpg b/backend/backend/src/main/resources/images/0a51d4af-2922-4057-81cd-756e62ddd13c_testimg1.jpg deleted file mode 100644 index c53ac5e358df846b8d20f1928bd0860aa4302f24..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8567 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 Date: Wed, 7 Aug 2024 17:44:27 +0900 Subject: [PATCH 143/197] =?UTF-8?q?feat:=20qna=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/edufocus/mail/service/MailServiceImpl.java | 2 +- .../edufocus/edufocus/qna/controller/QnaController.java | 2 ++ .../com/edufocus/edufocus/qna/service/QnaServiceImpl.java | 8 +++++--- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/mail/service/MailServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/mail/service/MailServiceImpl.java index 20859de..e6f02ac 100644 --- a/backend/src/main/java/com/edufocus/edufocus/mail/service/MailServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/mail/service/MailServiceImpl.java @@ -34,7 +34,7 @@ public class MailServiceImpl implements MailService { redisUtil.setDataExpire(code, email, 60 * 5L); SimpleMailMessage mail = createEmail(email, "[EDUFOCUS] 비밀번호 찾기 안내", code); - mailSender.send(mail); + //mailSender.send(mail); } @Override diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java b/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java index 64b2e73..c4c2a0a 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java @@ -71,6 +71,7 @@ public class QnaController { User findUser = userRepository.findById(userId).orElse(null); if (findUser.getRole() != UserRole.ADMIN) { + System.out.println("role 안맞음"); throw new RuntimeException("update 실패"); } @@ -88,6 +89,7 @@ public class QnaController { Long userId = Long.parseLong(jwtUtil.getUserId(token)); User findUser = userRepository.findById(userId).orElse(null); + System.out.println("delete answer"); if (findUser.getRole() != UserRole.ADMIN) { throw new RuntimeException(); } diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java index 637239c..3454e27 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java @@ -55,11 +55,13 @@ public class QnaServiceImpl implements QnaService { @Override public QnaResponseDto updateQna(Long id, QnaRequestDto qnaRequestDto, Long userId) { + System.out.println("userId:" + userId); + Qna qna = qnaRepository.findById(id).orElse(null); + System.out.println("quesiton에 있는거: " + qna.getUser().getId()); User user = userRepository.findById(userId).orElse(null); - if (qna.getUser().getId() == userId) { - qnaRepository.delete(qna); - } else { + + if (qna.getUser().getId() != userId) { throw new RuntimeException(); } From ccc2b998dac1e9b268ffe3d969d741226e1f89a6 Mon Sep 17 00:00:00 2001 From: yulmam <70622601+yulmam@users.noreply.github.com> Date: Wed, 7 Aug 2024 23:24:52 +0900 Subject: [PATCH 144/197] =?UTF-8?q?feat=20:=20reportSet=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/board/entity/vo/Board.java | 2 +- .../edufocus/quiz/entity/QuizSet.java | 2 +- .../registration/entity/Registration.java | 19 ++ .../repository/RegistrationRepository.java | 3 + .../report/controller/ReportController.java | 91 ++++------ .../report/entity/dto/AnswerInput.java | 12 -- .../edufocus/report/entity/dto/QuizDto.java | 6 - .../report/entity/dto/QuizSubmissionDto.java | 6 - .../entity/dto/ReportDetailResponseDto.java | 3 +- .../entity/dto/ReportListResponseDto.java | 17 -- ...{ReportRequset.java => ReportRequest.java} | 2 +- .../report/entity/dto/ReportResponse.java | 14 +- .../report/entity/dto/ReportSetResponse.java | 18 ++ .../edufocus/report/entity/vo/Answer.java | 1 - .../edufocus/report/entity/vo/Report.java | 30 +++- .../edufocus/report/entity/vo/ReportSet.java | 54 ++++++ .../report/repository/ReportRepository.java | 10 +- .../repository/ReportSetRepository.java | 13 ++ .../report/service/ReportService.java | 18 +- .../report/service/ReportServiceImpl.java | 168 ++++++++---------- .../user/model/service/UserService.java | 2 + .../user/model/service/UserServiceImpl.java | 6 +- .../ws/controller/ChatController.java | 29 +-- .../edufocus/ws/entity/dto/QuizDto.java | 3 + .../edufocus/ws/service/ChatService.java | 15 -- .../edufocus/ws/service/ChatServiceImpl.java | 83 --------- 26 files changed, 285 insertions(+), 342 deletions(-) delete mode 100644 backend/src/main/java/com/edufocus/edufocus/report/entity/dto/AnswerInput.java delete mode 100644 backend/src/main/java/com/edufocus/edufocus/report/entity/dto/QuizSubmissionDto.java delete mode 100644 backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportListResponseDto.java rename backend/src/main/java/com/edufocus/edufocus/report/entity/dto/{ReportRequset.java => ReportRequest.java} (91%) create mode 100644 backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportSetResponse.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java create mode 100644 backend/src/main/java/com/edufocus/edufocus/report/repository/ReportSetRepository.java delete mode 100644 backend/src/main/java/com/edufocus/edufocus/ws/service/ChatService.java delete mode 100644 backend/src/main/java/com/edufocus/edufocus/ws/service/ChatServiceImpl.java diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java index e1e4ac6..c2a2519 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java @@ -55,7 +55,7 @@ public class Board { private Lecture lecture; - @OneToMany(mappedBy = "board") + @OneToMany(mappedBy = "board", cascade = CascadeType.ALL) private List comments; public ResponseBoardSummaryDto makeSummaryDto(){ diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSet.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSet.java index 90d13ac..557dc57 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSet.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSet.java @@ -28,7 +28,7 @@ public class QuizSet { @Column private String title; - @OneToMany(mappedBy = "quizSet", orphanRemoval = true) + @OneToMany(mappedBy = "quizSet", orphanRemoval = true, fetch = FetchType.EAGER) @JsonManagedReference private List quizzes; diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/entity/Registration.java b/backend/src/main/java/com/edufocus/edufocus/registration/entity/Registration.java index 88af158..0b01d55 100644 --- a/backend/src/main/java/com/edufocus/edufocus/registration/entity/Registration.java +++ b/backend/src/main/java/com/edufocus/edufocus/registration/entity/Registration.java @@ -1,10 +1,15 @@ package com.edufocus.edufocus.registration.entity; import com.edufocus.edufocus.lecture.entity.Lecture; +import com.edufocus.edufocus.quiz.entity.QuizSet; +import com.edufocus.edufocus.report.entity.vo.Report; +import com.edufocus.edufocus.report.entity.vo.ReportSet; import com.edufocus.edufocus.user.model.entity.vo.User; import jakarta.persistence.*; import lombok.*; +import java.util.UUID; + @Entity @Getter @Setter @@ -27,4 +32,18 @@ public class Registration { @Enumerated(EnumType.STRING) private RegistrationStatus status; + + public boolean isAccepted(){ + return status == RegistrationStatus.ACCEPTED; + } + + public Report makeReport(ReportSet reportSet, QuizSet quizSet, long lectureId){ + return Report.builder() + .allCount(0) + .correctCount(-1) + .lectureId(lectureId) + .user(user) + .build(); + + } } diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/repository/RegistrationRepository.java b/backend/src/main/java/com/edufocus/edufocus/registration/repository/RegistrationRepository.java index ef2c721..327893d 100644 --- a/backend/src/main/java/com/edufocus/edufocus/registration/repository/RegistrationRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/registration/repository/RegistrationRepository.java @@ -1,6 +1,7 @@ package com.edufocus.edufocus.registration.repository; import com.edufocus.edufocus.registration.entity.Registration; +import com.edufocus.edufocus.registration.entity.RegistrationStatus; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; @@ -16,4 +17,6 @@ public interface RegistrationRepository extends JpaRepository findAllNotAcceptedByLectureId(@Param("lectureId") Long lectureId); Registration findByUserIdAndLectureId(Long userId, Long lectureId); + + List findByLectureIdAndStatus(Long lectureId, RegistrationStatus status); } diff --git a/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java b/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java index 9c789bf..bc9b5f2 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java @@ -1,19 +1,10 @@ package com.edufocus.edufocus.report.controller; -import com.edufocus.edufocus.report.entity.dto.ReportDetailResponseDto; -import com.edufocus.edufocus.report.entity.dto.ReportListResponseDto; -import com.edufocus.edufocus.report.entity.dto.ReportResponse; -import com.edufocus.edufocus.report.entity.vo.Report; -import com.edufocus.edufocus.report.entity.dto.ReportRequset; +import com.edufocus.edufocus.report.entity.dto.*; import com.edufocus.edufocus.report.service.ReportService; -import com.edufocus.edufocus.user.model.entity.vo.User; -import com.edufocus.edufocus.user.model.entity.vo.UserRole; -import com.edufocus.edufocus.user.model.repository.UserRepository; import com.edufocus.edufocus.user.model.service.UserService; -import com.edufocus.edufocus.user.model.service.UserServiceImpl; import com.edufocus.edufocus.user.util.JWTUtil; import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; @@ -21,8 +12,8 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.sql.SQLException; -import java.util.ArrayList; import java.util.List; +import java.util.UUID; @RestController @RequestMapping("/report") @@ -34,73 +25,61 @@ public class ReportController { private final ReportService reportService; private final JWTUtil jwtUtil; private final UserService userService; - private final UserRepository userRepository; - //SUBMIT 할떄 LECTURE ID 저장해놓기 - @PostMapping("/submit/{lectreId}/quizset/{quizsetId}") - public ResponseEntity submit(@PathVariable("lectreId") Long lectureId, @PathVariable("quizsetId") Long quizestId, @RequestBody ReportRequset reportRequset, HttpServletRequest request) throws SQLException { + @PostMapping("/submit/quizSet/{reportSetId}") + public ResponseEntity submit(@PathVariable("reportSetId") UUID reportSetId, @RequestBody ReportRequest reportRequest, HttpServletRequest request) { String token = request.getHeader("Authorization"); - Long userId = Long.parseLong(jwtUtil.getUserId(token)); - User findUser = userRepository.findById(userId).orElse(null); - if (findUser.getRole() == UserRole.ADMIN) { + long userId = Long.parseLong(jwtUtil.getUserId(token)); + if (userService.isTeacher(userId)) return new ResponseEntity<>("강사는 퀴즈제출을 할수 없습니다", HttpStatus.FORBIDDEN); - } - ReportResponse report = reportService.grading(userId, quizestId, reportRequset, lectureId); + reportService.grade(userId, reportSetId, reportRequest); - return new ResponseEntity<>(report, HttpStatus.CREATED); + return new ResponseEntity<>(HttpStatus.OK); } - @GetMapping("/myreport") - public ResponseEntity> myreport(HttpServletRequest request) throws SQLException { + @GetMapping("/student/{lectureId}") + public ResponseEntity> searchMyReport(@PathVariable long lectureId, HttpServletRequest request) { String token = request.getHeader("Authorization"); - Long userId = Long.parseLong(jwtUtil.getUserId(token)); + long userId = Long.parseLong(jwtUtil.getUserId(token)); + List reportResponses = reportService.findReports(lectureId, userId); - List reportList = reportService.resultList(userId); - - return new ResponseEntity<>(reportList, HttpStatus.CREATED); + if(reportResponses.isEmpty()) + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + return new ResponseEntity<>(reportResponses, HttpStatus.OK); } - @GetMapping("/myreportdetail/{id}") - public ResponseEntity myreportdetail(@PathVariable("id") Long reportId) throws SQLException { - + @GetMapping("/reportDetail/{reportId}") + public ResponseEntity searchDetailReport(@PathVariable("reportId") long reportId){ ReportDetailResponseDto detailReport = reportService.reportDetail(reportId); - return new ResponseEntity<>(detailReport, HttpStatus.CREATED); + return new ResponseEntity<>(detailReport, HttpStatus.OK); } - @GetMapping("/studentreport/{lecturid}") - public ResponseEntity> studentreport(@PathVariable("lecturid") Long lectureId) throws SQLException { - - - List reportList = reportService.studentResultList(lectureId); - - return new ResponseEntity<>(reportList, HttpStatus.CREATED); - + @GetMapping("/teacher/reportSet/{lectureId}") + public ResponseEntity> searchReportSets(@PathVariable("lectureId") long lectureId){ + List reportSetResponses = reportService.findReportSets(lectureId); + + if(reportSetResponses.isEmpty()) + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + + return new ResponseEntity<>(reportSetResponses, HttpStatus.OK); } - - @GetMapping("/studentreportdetail/{id}") - public ResponseEntity studentdetailreport(@PathVariable("id") Long reportId) throws SQLException { - - ReportDetailResponseDto detailReport = reportService.reportDetail(reportId); - return new ResponseEntity<>(detailReport, HttpStatus.CREATED); - + + @GetMapping("/teacher/report/{reportSetId}") + public ResponseEntity searchReports(@PathVariable("reportSetId") UUID reportSetId){ + List reportResponses = reportService.findReports(reportSetId); + + if(reportResponses.isEmpty()) + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + + return new ResponseEntity<>(reportResponses, HttpStatus.OK); } - // 강좌에 대한 퀴즈셋 -// lecture id가 똑같은 report들 제목 + 작성자 + 맞틀 개수 미리 보여주기 -// @GetMapping("/detailreport/{id}") -// public ResponseEntity (@PathVariable("id") Long reportId) throws SQLException { -// -// ReportDetailResponseDto detailReport = reportService.reportDetail(reportId); -// return new ResponseEntity<>(detailReport, HttpStatus.CREATED); -// -// } v 9 - } diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/AnswerInput.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/AnswerInput.java deleted file mode 100644 index b979e52..0000000 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/AnswerInput.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.edufocus.edufocus.report.entity.dto; - -import lombok.Getter; - -@Getter -public class AnswerInput { - - - String answer; - - -} diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/QuizDto.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/QuizDto.java index 350e906..d73d6fb 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/QuizDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/QuizDto.java @@ -13,15 +13,9 @@ import java.util.List; @Data @Builder public class QuizDto { - - private long id; - - private String question; - private String image; - private String answer; private String userAnswer; private List choices; diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/QuizSubmissionDto.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/QuizSubmissionDto.java deleted file mode 100644 index 24413b2..0000000 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/QuizSubmissionDto.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.edufocus.edufocus.report.entity.dto; - -public class QuizSubmissionDto { - private Long quizSetId; - private Long userId; -} diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportDetailResponseDto.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportDetailResponseDto.java index a86b4e7..4dc0f76 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportDetailResponseDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportDetailResponseDto.java @@ -4,6 +4,7 @@ import com.edufocus.edufocus.quiz.entity.Quiz; import lombok.Builder; import lombok.Data; +import java.time.LocalDateTime; import java.util.Date; import java.util.List; @@ -13,7 +14,7 @@ public class ReportDetailResponseDto { private int allCount; private String title; private int correctCount; - private Date testAt; + private LocalDateTime testAt; private List correctQuizzes; private List incorrectQuizzes; diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportListResponseDto.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportListResponseDto.java deleted file mode 100644 index 94fc3e2..0000000 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportListResponseDto.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.edufocus.edufocus.report.entity.dto; - -import lombok.Builder; -import lombok.Data; - -import java.util.Date; - -@Data -@Builder -public class ReportListResponseDto { - private String title; - private Date date; - private Long reportId; - private String name; - private int allCount; - private int correctCount; -} \ No newline at end of file diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportRequset.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportRequest.java similarity index 91% rename from backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportRequset.java rename to backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportRequest.java index 84e3e74..4f2c0bf 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportRequset.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportRequest.java @@ -7,7 +7,7 @@ import java.util.List; @Getter @Setter -public class ReportRequset { +public class ReportRequest { List answer; diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportResponse.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportResponse.java index 7d6a439..0740a0b 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportResponse.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportResponse.java @@ -1,26 +1,20 @@ package com.edufocus.edufocus.report.entity.dto; -import com.edufocus.edufocus.report.entity.vo.Answer; import lombok.Builder; import lombok.Getter; import lombok.Setter; +import java.time.LocalDateTime; import java.util.Date; -import java.util.List; @Getter @Setter @Builder public class ReportResponse { - - private Long quizesetId; - private Long userId; - + private long reportId; + private String name; private String title; private int allCount; private int correctCount; - private Date testAt; - - - + private LocalDateTime date; } diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportSetResponse.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportSetResponse.java new file mode 100644 index 0000000..ad300bf --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportSetResponse.java @@ -0,0 +1,18 @@ +package com.edufocus.edufocus.report.entity.dto; + + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; +import java.util.UUID; + +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ReportSetResponse { + private UUID reportSetId; + private String quizSetTitle; + private LocalDateTime testAt; +} diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Answer.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Answer.java index 929adb0..53d0d35 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Answer.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Answer.java @@ -28,5 +28,4 @@ public class Answer { @JoinColumn(name = "quiz_id") private Quiz quiz; - } diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java index 1b81e78..dcc4b95 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java @@ -1,11 +1,15 @@ package com.edufocus.edufocus.report.entity.vo; import com.edufocus.edufocus.quiz.entity.QuizSet; +import com.edufocus.edufocus.report.entity.dto.ReportResponse; import com.edufocus.edufocus.user.model.entity.vo.User; import jakarta.persistence.*; import lombok.*; +import org.springframework.data.annotation.CreatedDate; +import java.time.LocalDateTime; import java.util.Date; +import java.util.List; @Entity @Getter @@ -14,16 +18,19 @@ import java.util.Date; @AllArgsConstructor @Builder public class Report { - - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private int allCount; + private int correctCount; - private Date testAt; + + @CreatedDate + private LocalDateTime testAt; + private Long lectureId; + @ManyToOne @JoinColumn(name = "user_id") private User user; @@ -32,4 +39,21 @@ public class Report { @JoinColumn(name = "quizset_id") private QuizSet quizSet; + @ManyToOne + @JoinColumn(name = "reportset_id") + private ReportSet reportSet; + + @OneToMany(mappedBy = "report", cascade = CascadeType.ALL) + private List answers; + + public ReportResponse makeReportResponse(){ + return ReportResponse.builder() + .reportId(id) + .name(user.getName()) + .title(quizSet.getTitle()) + .allCount(allCount) + .correctCount(correctCount) + .date(testAt) + .build(); + } } diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java new file mode 100644 index 0000000..2dedc12 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java @@ -0,0 +1,54 @@ +package com.edufocus.edufocus.report.entity.vo; + +import com.edufocus.edufocus.lecture.entity.Lecture; +import com.edufocus.edufocus.quiz.entity.QuizSet; +import com.edufocus.edufocus.report.entity.dto.ReportSetResponse; +import jakarta.persistence.*; +import lombok.*; +import org.hibernate.annotations.ColumnDefault; +import org.hibernate.annotations.GenericGenerator; +import org.springframework.data.annotation.CreatedDate; + + +import java.time.LocalDateTime; +import java.util.List; +import java.util.UUID; + + + +@Entity +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ReportSet { + @Id + @GeneratedValue(generator = "UUID") + @GenericGenerator( + name = "UUID", + strategy = "org.hibernate.id.UUIDGenerator" + ) + private UUID id; + + @CreatedDate + private LocalDateTime createAt; + + @OneToMany(mappedBy = "reportSet", cascade = CascadeType.ALL) + private List reports; + + @ManyToOne + @JoinColumn(name = "lecture_id") + private Lecture lecture; + + @ManyToOne + @JoinColumn(name = "quizSet_id") + private QuizSet quizSet; + + public ReportSetResponse makeReportSetResponse() { + return ReportSetResponse.builder() + .reportSetId(id) + .quizSetTitle(quizSet.getTitle()) + .testAt(createAt) + .build(); + } +} diff --git a/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportRepository.java b/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportRepository.java index 66d2fb9..7665f28 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportRepository.java @@ -5,11 +5,17 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; import java.util.List; +import java.util.UUID; @Repository public interface ReportRepository extends JpaRepository { - List findByUser_Id(Long userId); + List findByUserId(long userId); - List findByLectureId(Long lectureId); + List findByLectureId(long lectureId); + Report findByReportSetIdAndUserId(UUID reportSetId, long userId); + + List findByReportSetId(UUID reportSetId); + + List findByLectureIdAndUserId(long lectureId, long userId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportSetRepository.java b/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportSetRepository.java new file mode 100644 index 0000000..f1b484c --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportSetRepository.java @@ -0,0 +1,13 @@ +package com.edufocus.edufocus.report.repository; + +import com.edufocus.edufocus.report.entity.vo.ReportSet; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.UUID; + +@Repository +public interface ReportSetRepository extends JpaRepository { + List findByLectureId(long userId); +} diff --git a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportService.java b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportService.java index 7edcc4a..1e1b2b2 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportService.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportService.java @@ -1,21 +1,23 @@ package com.edufocus.edufocus.report.service; -import com.edufocus.edufocus.report.entity.dto.ReportDetailResponseDto; -import com.edufocus.edufocus.report.entity.dto.ReportListResponseDto; -import com.edufocus.edufocus.report.entity.dto.ReportResponse; -import com.edufocus.edufocus.report.entity.dto.ReportRequset; +import com.edufocus.edufocus.report.entity.dto.*; import org.springframework.stereotype.Service; import java.sql.SQLException; import java.util.List; +import java.util.UUID; @Service public interface ReportService { - ReportResponse grading(Long userId, Long quizesetId, ReportRequset reportRequset, Long lectureId) throws SQLException; + void grade(long userId, UUID reportSetId, ReportRequest reportRequest); - ReportDetailResponseDto reportDetail(Long userId) throws SQLException; + ReportDetailResponseDto reportDetail(long userId); - List resultList(Long userId) throws SQLException; + List findReportSets(long lectureId); - List studentResultList(Long lectureId) throws SQLException; + List findReports(UUID reportSetId); + + List findReports(long lectureId, long userid); + + UUID initReportSet(long lectureId, long quizSetId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java index 5543795..016bb34 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java @@ -1,123 +1,96 @@ package com.edufocus.edufocus.report.service; +import com.edufocus.edufocus.lecture.repository.LectureRepository; import com.edufocus.edufocus.quiz.entity.Choice; import com.edufocus.edufocus.quiz.entity.Quiz; import com.edufocus.edufocus.quiz.entity.QuizSet; import com.edufocus.edufocus.quiz.repository.QuizRepository; import com.edufocus.edufocus.quiz.repository.QuizSetRepository; -import com.edufocus.edufocus.quiz.service.QuizService; import com.edufocus.edufocus.quiz.service.QuizSetService; +import com.edufocus.edufocus.registration.entity.Registration; +import com.edufocus.edufocus.registration.entity.RegistrationStatus; +import com.edufocus.edufocus.registration.repository.RegistrationRepository; import com.edufocus.edufocus.report.entity.dto.*; import com.edufocus.edufocus.report.entity.vo.Answer; import com.edufocus.edufocus.report.entity.vo.Report; +import com.edufocus.edufocus.report.entity.vo.ReportSet; import com.edufocus.edufocus.report.repository.AnswerRepository; import com.edufocus.edufocus.report.repository.ReportRepository; +import com.edufocus.edufocus.report.repository.ReportSetRepository; import com.edufocus.edufocus.user.model.entity.vo.User; import com.edufocus.edufocus.user.model.repository.UserRepository; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; -import org.checkerframework.checker.units.qual.C; import org.springframework.stereotype.Service; import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; +import java.util.*; @Service @Transactional @RequiredArgsConstructor public class ReportServiceImpl implements ReportService { - private final QuizSetService quizSetService; - private final QuizService quizService; - private final ReportRepository reportRepository; private final QuizRepository quizRepository; - - + private final RegistrationRepository registrationRepository; private final AnswerRepository answerRepository; - private final AnswerService answerService; - private final UserRepository userRepository; + private final ReportSetRepository reportSetRepository; + private final LectureRepository lectureRepository; private final QuizSetRepository quizSetRepository; @Override - public ReportResponse grading(Long userId, Long quizsetId, ReportRequset reportRequset, Long lectureId) throws SQLException { + public void grade(long userId, UUID reportSetId, ReportRequest reportRequest){ - QuizSet quizSet = quizSetService.findQuizSet(quizsetId); - List quizList = quizSet.getQuizzes(); - List answerInputList = reportRequset.getAnswer(); + ReportSet reportSet = reportSetRepository.findById(reportSetId).orElseThrow(NoSuchElementException::new); + + Report report = reportRepository.findByReportSetIdAndUserId(reportSetId, userId); + + List quizList = report.getQuizSet().getQuizzes(); + + List answerInputList = reportRequest.getAnswer(); List answerList = new ArrayList<>(); - int allCount = quizList.size(); int correctCount = 0; - User testuser = userRepository.findById(userId).orElse(null); - for (int idx = 0; idx < answerInputList.size(); idx++) { Quiz quiz = quizList.get(idx); String inputAnswer = answerInputList.get(idx); + boolean isCollect; Answer answer; - // if (quiz.getAnswer().equals(inputAnswer)) { correctCount++; - answer = Answer.builder() - .userAnswer(inputAnswer) - .isCorrect(true) - .report(null) - .quiz(quiz) - .build(); + isCollect = true; } else { - answer = Answer.builder() - .userAnswer(inputAnswer) - .isCorrect(false) - .report(null) - .quiz(quiz) - .build(); + isCollect = false; } + answer = Answer.builder() + .userAnswer(inputAnswer) + .isCorrect(isCollect) + .report(report) + .quiz(quiz) + .build(); answerList.add(answer); } - Report report = Report.builder() - .user(testuser) - .quizSet(quizSet) - .allCount(allCount) - .correctCount(correctCount) - .testAt(new Date()) - .lectureId(lectureId) - .build(); - + report.setAllCount(quizList.size()); + report.setCorrectCount(correctCount); + report.setReportSet(reportSet); reportRepository.save(report); - - for (Answer answer : answerList) { - answer.setReport(report); - answerRepository.save(answer); - } - - - ReportResponse reportResponse = ReportResponse.builder() - .quizesetId(quizSet.getId()) - .userId(testuser.getId()) - .title(quizSet.getTitle()) - .allCount(allCount) - .correctCount(correctCount) - .testAt(new Date()) - .build(); - - return reportResponse; + answerRepository.saveAll(answerList); } @Override - public ReportDetailResponseDto reportDetail(Long repordId) { + public ReportDetailResponseDto reportDetail(long reportId) { - Report report = reportRepository.findById(repordId).orElse(null); + Report report = reportRepository.findById(reportId).orElseThrow(NoSuchElementException::new); - QuizSet quizSet = quizSetService.findQuizSet(report.getQuizSet().getId()); + QuizSet quizSet = quizSetRepository.findById(report.getQuizSet().getId()).orElseThrow(NoSuchElementException::new); List correctQuiz = new ArrayList<>(); List incorrectQuiz = new ArrayList<>(); @@ -177,55 +150,54 @@ public class ReportServiceImpl implements ReportService { return dto; } - @Override - public List resultList(Long userId) throws SQLException { - - List reportList = reportRepository.findByUser_Id(userId); - - List reportListResponseDtoList = new ArrayList<>(); - - - for (Report report : reportList) { - - QuizSet quizSet = quizSetService.findQuizSet(report.getQuizSet().getId()); - ReportListResponseDto dto = ReportListResponseDto.builder() - .title(quizSet.getTitle()) // Assuming QuizSet has a method getTitle() - .date(report.getTestAt()) - .reportId(report.getId())// Assuming QuizSet has a method getDate() - .build(); - reportListResponseDtoList.add(dto); - - } - - return reportListResponseDtoList; + public List findReportSets(long lectureId) { + List reportSets = reportSetRepository.findByLectureId(lectureId); + return reportSets.stream() + .map(ReportSet::makeReportSetResponse) + .toList(); } @Override - public List studentResultList(Long lectureId) throws SQLException { + public List findReports(UUID reportSetId) { + List reports = reportRepository.findByReportSetId(reportSetId); - List reportList = reportRepository.findByLectureId(lectureId); + return reports.stream() + .map(Report::makeReportResponse) + .toList(); + } - List reportListResponseDtoList = new ArrayList<>(); + @Override + public List findReports(long lectureId, long userId) { + List reports = reportRepository.findByLectureIdAndUserId(lectureId, userId); + return reports.stream() + .map(Report::makeReportResponse) + .toList(); + } - for (Report report : reportList) { + @Override + public UUID initReportSet(long lectureId, long quizSetId) { + List registrations = registrationRepository.findByLectureIdAndStatus(lectureId, RegistrationStatus.ACCEPTED); - System.out.println(report.toString()); - QuizSet quizSet = quizSetService.findQuizSet(report.getQuizSet().getId()); - ReportListResponseDto dto = ReportListResponseDto.builder() - .title(quizSet.getTitle()) - .date(report.getTestAt()) - .reportId(report.getId()) - .allCount(report.getAllCount()) - .correctCount(report.getCorrectCount()) - .build(); - reportListResponseDtoList.add(dto); + ReportSet reportSet = ReportSet.builder() + .lecture(lectureRepository.getReferenceById(lectureId)) + .quizSet(quizSetRepository.getReferenceById(quizSetId)) + .build(); - } + reportSetRepository.save(reportSet); - return reportListResponseDtoList; + QuizSet quizSet = quizSetRepository.getReferenceById(quizSetId); + + List reports = registrations.stream() + .filter(Registration::isAccepted) + .map((Registration registration)-> registration.makeReport(reportSet, quizSet, lectureId)) + .toList(); + + reportRepository.saveAll(reports); + + return reportSet.getId(); } } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java index 0737045..481c0de 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java @@ -29,4 +29,6 @@ public interface UserService { boolean isEmailExist(String email); void changeForgottenPassword(Long id, String newPassword); + + boolean isTeacher(long id); } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java index c50e1c9..b4d20da 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java @@ -5,6 +5,7 @@ import com.edufocus.edufocus.user.model.entity.dto.InfoDto; import com.edufocus.edufocus.user.model.entity.dto.PasswordDto; import com.edufocus.edufocus.user.model.entity.dto.RequestJoinDto; import com.edufocus.edufocus.user.model.entity.vo.User; +import com.edufocus.edufocus.user.model.entity.vo.UserRole; import com.edufocus.edufocus.user.model.exception.UserException; import com.edufocus.edufocus.user.model.repository.UserRepository; import com.edufocus.edufocus.user.util.PasswordUtils; @@ -155,5 +156,8 @@ public class UserServiceImpl implements UserService { userRepository.save(user); } - + @Override + public boolean isTeacher(long id){ + return userRepository.findById(id).orElseThrow(IllegalArgumentException::new).getRole() == UserRole.ADMIN; + } } diff --git a/backend/src/main/java/com/edufocus/edufocus/ws/controller/ChatController.java b/backend/src/main/java/com/edufocus/edufocus/ws/controller/ChatController.java index dbf5d8e..4e280b9 100644 --- a/backend/src/main/java/com/edufocus/edufocus/ws/controller/ChatController.java +++ b/backend/src/main/java/com/edufocus/edufocus/ws/controller/ChatController.java @@ -2,40 +2,25 @@ package com.edufocus.edufocus.ws.controller; import com.edufocus.edufocus.global.constant.RabbitMQConstant; -import com.edufocus.edufocus.user.util.JWTUtil; +import com.edufocus.edufocus.report.service.ReportService; import com.edufocus.edufocus.ws.entity.dto.MessageDto; import com.edufocus.edufocus.ws.entity.dto.QuizDto; -import com.edufocus.edufocus.ws.entity.dto.ChatUserDto; -import com.edufocus.edufocus.ws.service.ChatService; import org.springframework.amqp.rabbit.core.RabbitTemplate; -import org.springframework.context.event.EventListener; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; import org.springframework.messaging.handler.annotation.DestinationVariable; -import org.springframework.messaging.handler.annotation.Header; import org.springframework.messaging.handler.annotation.MessageMapping; -import org.springframework.messaging.handler.annotation.SendTo; -import org.springframework.messaging.simp.SimpMessageHeaderAccessor; -import org.springframework.messaging.simp.SimpMessageSendingOperations; -import org.springframework.messaging.simp.stomp.StompHeaderAccessor; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.socket.messaging.SessionConnectedEvent; -import org.springframework.web.socket.messaging.SessionDisconnectEvent; -import org.springframework.web.socket.messaging.SessionSubscribeEvent; -import org.springframework.web.socket.messaging.SessionUnsubscribeEvent; -import java.util.List; +import java.util.UUID; @RestController public class ChatController { RabbitTemplate rabbitTemplate; + ReportService reportService; - public ChatController(RabbitTemplate rabbitTemplate){ + public ChatController(RabbitTemplate rabbitTemplate, ReportService reportService){ this.rabbitTemplate = rabbitTemplate; + this.reportService = reportService; } @MessageMapping("chat.message.{lectureId}") @@ -47,6 +32,10 @@ public class ChatController { @MessageMapping("chat.quiz.{lectureId}") public void quizStart(@DestinationVariable long lectureId, QuizDto quizDto){ + UUID reportSetId = reportService.initReportSet(lectureId, quizDto.getQuizSetId()); + + quizDto.setReportSetId(reportSetId); + rabbitTemplate.convertAndSend(RabbitMQConstant.CHAT_EXCHANGE.getConstant(), RabbitMQConstant.ROUTING_KEY_PREFIX.getConstant() + lectureId, quizDto); diff --git a/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/QuizDto.java b/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/QuizDto.java index bd97f35..2d91954 100644 --- a/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/QuizDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/ws/entity/dto/QuizDto.java @@ -4,9 +4,12 @@ package com.edufocus.edufocus.ws.entity.dto; import lombok.Getter; import lombok.Setter; +import java.util.UUID; + @Getter @Setter public class QuizDto { long userId; long quizSetId; + UUID ReportSetId; } diff --git a/backend/src/main/java/com/edufocus/edufocus/ws/service/ChatService.java b/backend/src/main/java/com/edufocus/edufocus/ws/service/ChatService.java deleted file mode 100644 index 5399bb9..0000000 --- a/backend/src/main/java/com/edufocus/edufocus/ws/service/ChatService.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.edufocus.edufocus.ws.service; - -import com.edufocus.edufocus.ws.entity.dto.ChatUserDto; - -import java.util.List; - -public interface ChatService { - public void saveChatUserInfo(long userId, long channelId, String sessionId); - public ChatUserDto getChatUserInfo(long userId); - public ChatUserDto getChatUserInfo(String sessionId); - public List findChatUsers(long lectureId); - public boolean checkTeacher(ChatUserDto chatUser); - public void closeChatRoom(long chatRoomId); - public void deleteChatUserInfo(long userId); -} diff --git a/backend/src/main/java/com/edufocus/edufocus/ws/service/ChatServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/ws/service/ChatServiceImpl.java deleted file mode 100644 index 29071cf..0000000 --- a/backend/src/main/java/com/edufocus/edufocus/ws/service/ChatServiceImpl.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.edufocus.edufocus.ws.service; - - -import com.edufocus.edufocus.lecture.entity.Lecture; -import com.edufocus.edufocus.lecture.repository.LectureRepository; -import com.edufocus.edufocus.user.model.entity.vo.User; -import com.edufocus.edufocus.user.model.repository.UserRepository; -import com.edufocus.edufocus.ws.entity.dto.ChatUserDto; -import com.edufocus.edufocus.ws.entity.vo.ChatUser; -import com.edufocus.edufocus.ws.repository.ChatUserRepository; -import org.springframework.stereotype.Service; - -import java.util.List; -import java.util.stream.Collectors; - -@Service -public class ChatServiceImpl implements ChatService{ - - private final ChatUserRepository chatUserRepository; - private final UserRepository userRepository; - private final LectureRepository lectureRepository; - - public ChatServiceImpl(ChatUserRepository chatUserRepository, UserRepository userRepository, LectureRepository lectureRepository) { - this.chatUserRepository = chatUserRepository; - this.userRepository = userRepository; - this.lectureRepository = lectureRepository; - } - - - @Override - public void saveChatUserInfo(long userId, long lectureId, String sessionId) { - User user = userRepository.getReferenceById(userId); - Lecture lecture = lectureRepository.getReferenceById(lectureId); - - ChatUser chatUser = ChatUser.builder() - .user(user) - .lecture(lecture) - .sessionId(sessionId) - .build(); - - chatUserRepository.save(chatUser); - } - - @Override - public ChatUserDto getChatUserInfo(long userId) { - ChatUser chatUser = chatUserRepository.findById(userId).orElseThrow(IllegalArgumentException::new); - - return chatUser.makeChatUserDto(); - } - - @Override - public ChatUserDto getChatUserInfo(String sessionId) { - ChatUser chatUser = chatUserRepository.findBySessionId(sessionId); - - return chatUser.makeChatUserDto(); - } - - @Override - public List findChatUsers(long lectureId) { - return chatUserRepository.findByLectureId(lectureId) - .stream() - .map(ChatUser::makeChatUserDto) - .collect(Collectors.toList()); - } - - @Override - public boolean checkTeacher(ChatUserDto chatUser) { - Lecture lecture = lectureRepository.findByIdAndUserId(chatUser.getLectureId(), chatUser.getUserId()); - return lecture != null; - } - - @Override - public void closeChatRoom(long lectureId) { - chatUserRepository.deleteByLectureId(lectureId); - } - - @Override - public void deleteChatUserInfo(long userId) { - ChatUser chatUser = chatUserRepository.getReferenceById(userId); - - chatUserRepository.delete(chatUser); - } -} From 918906de60b4b058c1b7f64e577455d52097a4af Mon Sep 17 00:00:00 2001 From: yulmam <70622601+yulmam@users.noreply.github.com> Date: Thu, 8 Aug 2024 09:47:06 +0900 Subject: [PATCH 145/197] =?UTF-8?q?feat=20:=20=EA=B2=8C=EC=8B=9C=ED=8C=90?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=20=EC=B5=9C=EC=8B=A0=EC=88=9C=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/edufocus/board/controller/BoardController.java | 2 +- .../com/edufocus/edufocus/board/service/BoardServiceImpl.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java b/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java index 309acb6..87e5410 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java @@ -38,7 +38,7 @@ public class BoardController { List boardSummaries = boardService.findBoards(pageNo, category, lectureId); if(boardSummaries.isEmpty()) - return new ResponseEntity<>(HttpStatus.NO_CONTENT); + return new ResponseEntity<>(boardSummaries, HttpStatus.NO_CONTENT); return new ResponseEntity<>(boardSummaries, HttpStatus.OK); } diff --git a/backend/src/main/java/com/edufocus/edufocus/board/service/BoardServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/board/service/BoardServiceImpl.java index 3fc7250..a357de2 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/service/BoardServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/service/BoardServiceImpl.java @@ -12,6 +12,7 @@ import com.edufocus.edufocus.user.model.entity.vo.User; import com.edufocus.edufocus.user.model.repository.UserRepository; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -39,7 +40,7 @@ public class BoardServiceImpl implements BoardService { @Transactional public List findBoards(int pageNo, String category, long lectureId) { - Pageable pageable = PageRequest.of(pageNo, PAGE_SIZE); + Pageable pageable = PageRequest.of(pageNo, PAGE_SIZE, Sort.by("created_at").descending()); List boards = boardRepository.findByLectureIdAndCategory(lectureId, category, pageable).getContent(); From e78821332d3d9fd94ff50ddc4487cf91f2671aa3 Mon Sep 17 00:00:00 2001 From: kgc91747 Date: Thu, 8 Aug 2024 10:14:36 +0900 Subject: [PATCH 146/197] =?UTF-8?q?feat:=20quiz=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=EB=B6=88=EA=B0=80=EB=8A=A5=ED=95=9C=20=EC=83=81=ED=83=9C?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/edufocus/quiz/entity/QuizSet.java | 3 +++ .../edufocus/quiz/service/QuizSetService.java | 2 ++ .../edufocus/quiz/service/QuizSetServiceImpl.java | 15 +++++++++++++++ 3 files changed, 20 insertions(+) diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSet.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSet.java index 90d13ac..19c7e35 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSet.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/QuizSet.java @@ -28,6 +28,9 @@ public class QuizSet { @Column private String title; + @Column + private boolean tested; + @OneToMany(mappedBy = "quizSet", orphanRemoval = true) @JsonManagedReference private List quizzes; diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetService.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetService.java index a8c3fa0..97e75d2 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetService.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetService.java @@ -21,4 +21,6 @@ public interface QuizSetService { QuizSetResponse findQuizSetResponse(long quizSetId); List findMyQuizSetResponses(long userId); + + void updateQuizSetTested(long quizSetId, long userId, boolean tested); } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java index b3b2b59..a636f0c 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java @@ -3,6 +3,7 @@ package com.edufocus.edufocus.quiz.service; import com.edufocus.edufocus.quiz.entity.*; import com.edufocus.edufocus.quiz.repository.QuizSetRepository; import com.edufocus.edufocus.user.model.entity.vo.User; +import com.edufocus.edufocus.user.model.exception.UnAuthorizedException; import com.edufocus.edufocus.user.model.repository.UserRepository; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; @@ -97,4 +98,18 @@ public class QuizSetServiceImpl implements QuizSetService { } + @Override + public void updateQuizSetTested(long quizSetId, long userId, boolean tested) { + QuizSet quizSet = quizSetRepository.findById(quizSetId).orElseThrow(NoSuchElementException::new); + + User user = userRepository.findById(userId).orElseThrow(NoSuchElementException::new); + + if (quizSet.getUser().getId() != user.getId()) { + throw new UnAuthorizedException(); + } + + quizSet.setTested(true); + quizSetRepository.save(quizSet); + } + } From 58ac496c41d4166540fb99166488a72b2ae745e9 Mon Sep 17 00:00:00 2001 From: yulmam <70622601+yulmam@users.noreply.github.com> Date: Thu, 8 Aug 2024 10:33:15 +0900 Subject: [PATCH 147/197] =?UTF-8?q?feat=20:=20reportDetail=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/edufocus/quiz/entity/Choice.java | 8 +++ .../registration/entity/Registration.java | 2 + .../report/controller/ReportController.java | 5 ++ .../edufocus/report/entity/dto/QuizDto.java | 1 + .../entity/dto/ReportDetailResponseDto.java | 5 +- .../report/repository/AnswerRepository.java | 2 +- .../report/service/ReportServiceImpl.java | 58 +++++-------------- .../user/model/service/UserService.java | 1 + .../user/model/service/UserServiceImpl.java | 4 +- 9 files changed, 36 insertions(+), 50 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Choice.java b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Choice.java index 8078db1..b8e82c2 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Choice.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/entity/Choice.java @@ -1,5 +1,6 @@ package com.edufocus.edufocus.quiz.entity; +import com.edufocus.edufocus.report.entity.dto.ChoiceDto; import com.fasterxml.jackson.annotation.JsonBackReference; import jakarta.persistence.*; import lombok.*; @@ -26,4 +27,11 @@ public class Choice { @Column private String content; + + public ChoiceDto makeChoiceDto(){ + return ChoiceDto.builder() + .num(num) + .content(content) + .build(); + } } diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/entity/Registration.java b/backend/src/main/java/com/edufocus/edufocus/registration/entity/Registration.java index 0b01d55..c5d302a 100644 --- a/backend/src/main/java/com/edufocus/edufocus/registration/entity/Registration.java +++ b/backend/src/main/java/com/edufocus/edufocus/registration/entity/Registration.java @@ -41,6 +41,8 @@ public class Registration { return Report.builder() .allCount(0) .correctCount(-1) + .reportSet(reportSet) + .quizSet(quizSet) .lectureId(lectureId) .user(user) .build(); diff --git a/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java b/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java index bc9b5f2..673bf19 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java @@ -55,6 +55,8 @@ public class ReportController { return new ResponseEntity<>(reportResponses, HttpStatus.OK); } + + @GetMapping("/reportDetail/{reportId}") public ResponseEntity searchDetailReport(@PathVariable("reportId") long reportId){ ReportDetailResponseDto detailReport = reportService.reportDetail(reportId); @@ -62,6 +64,9 @@ public class ReportController { return new ResponseEntity<>(detailReport, HttpStatus.OK); } + + + @GetMapping("/teacher/reportSet/{lectureId}") public ResponseEntity> searchReportSets(@PathVariable("lectureId") long lectureId){ List reportSetResponses = reportService.findReportSets(lectureId); diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/QuizDto.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/QuizDto.java index d73d6fb..d36281f 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/QuizDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/QuizDto.java @@ -18,5 +18,6 @@ public class QuizDto { private String image; private String answer; private String userAnswer; + private boolean isCollect; private List choices; } diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportDetailResponseDto.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportDetailResponseDto.java index 4dc0f76..6ef9d9c 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportDetailResponseDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportDetailResponseDto.java @@ -15,8 +15,5 @@ public class ReportDetailResponseDto { private String title; private int correctCount; private LocalDateTime testAt; - private List correctQuizzes; - private List incorrectQuizzes; - - + private List quizzes; } \ No newline at end of file diff --git a/backend/src/main/java/com/edufocus/edufocus/report/repository/AnswerRepository.java b/backend/src/main/java/com/edufocus/edufocus/report/repository/AnswerRepository.java index 2a9787f..0998a0a 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/repository/AnswerRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/repository/AnswerRepository.java @@ -6,6 +6,6 @@ import org.springframework.data.jpa.repository.JpaRepository; import java.util.List; public interface AnswerRepository extends JpaRepository { - List findByReport_Id(Long reportId); + List findByReportId(Long reportId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java index 016bb34..3ae6792 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java @@ -6,7 +6,6 @@ import com.edufocus.edufocus.quiz.entity.Quiz; import com.edufocus.edufocus.quiz.entity.QuizSet; import com.edufocus.edufocus.quiz.repository.QuizRepository; import com.edufocus.edufocus.quiz.repository.QuizSetRepository; -import com.edufocus.edufocus.quiz.service.QuizSetService; import com.edufocus.edufocus.registration.entity.Registration; import com.edufocus.edufocus.registration.entity.RegistrationStatus; import com.edufocus.edufocus.registration.repository.RegistrationRepository; @@ -17,13 +16,10 @@ import com.edufocus.edufocus.report.entity.vo.ReportSet; import com.edufocus.edufocus.report.repository.AnswerRepository; import com.edufocus.edufocus.report.repository.ReportRepository; import com.edufocus.edufocus.report.repository.ReportSetRepository; -import com.edufocus.edufocus.user.model.entity.vo.User; -import com.edufocus.edufocus.user.model.repository.UserRepository; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; -import java.sql.SQLException; import java.util.*; @Service @@ -78,7 +74,6 @@ public class ReportServiceImpl implements ReportService { report.setAllCount(quizList.size()); report.setCorrectCount(correctCount); - report.setReportSet(reportSet); reportRepository.save(report); @@ -92,62 +87,40 @@ public class ReportServiceImpl implements ReportService { QuizSet quizSet = quizSetRepository.findById(report.getQuizSet().getId()).orElseThrow(NoSuchElementException::new); - List correctQuiz = new ArrayList<>(); - List incorrectQuiz = new ArrayList<>(); + List quizDtos = new ArrayList<>(); - List myAnswer = answerRepository.findByReport_Id(report.getId()); + List myAnswer = answerRepository.findByReportId(report.getId()); for (Answer answer : myAnswer) { - QuizDto quizDto; Quiz quiz = quizRepository.findById(answer.getQuiz().getId()).orElse(null); - ArrayList choiceDtos = new ArrayList<>(); + List choiceDtos = quiz.getChoices() + .stream() + .map(Choice::makeChoiceDto) + .toList(); - for (Choice c : quiz.getChoices()) { - ChoiceDto choiceDto = null; - choiceDto = choiceDto.builder() - .num(c.getNum()) - .content(c.getContent()) - .build(); - choiceDtos.add(choiceDto); - - } - if (answer.isCorrect()) { - - quizDto = QuizDto.builder() + QuizDto quizDto = QuizDto.builder() .id(quiz.getId()) .question(quiz.getQuestion()) .image(quiz.getImage()) .question(quiz.getQuestion()) .answer(quiz.getAnswer()) .userAnswer(answer.getUserAnswer()) + .isCollect(answer.isCorrect()) .choices(choiceDtos) .build(); - correctQuiz.add(quizDto); - } else { - quizDto = QuizDto.builder() - .id(quiz.getId()) - .question(quiz.getQuestion()) - .image(quiz.getImage()) - .question(quiz.getQuestion()) - .answer(quiz.getAnswer()) - .userAnswer(answer.getUserAnswer()) - .choices(choiceDtos) - .build(); - incorrectQuiz.add(quizDto); - } + quizDtos.add(quizDto); } - ReportDetailResponseDto dto = ReportDetailResponseDto.builder() + + + return ReportDetailResponseDto.builder() .title(quizSet.getTitle()) .testAt(report.getTestAt()) .allCount(report.getAllCount()) .correctCount(report.getCorrectCount()) - .correctQuizzes(correctQuiz) - .incorrectQuizzes(incorrectQuiz) + .quizzes(quizDtos) .build(); - - return dto; } @Override @@ -179,8 +152,6 @@ public class ReportServiceImpl implements ReportService { @Override public UUID initReportSet(long lectureId, long quizSetId) { - List registrations = registrationRepository.findByLectureIdAndStatus(lectureId, RegistrationStatus.ACCEPTED); - ReportSet reportSet = ReportSet.builder() .lecture(lectureRepository.getReferenceById(lectureId)) .quizSet(quizSetRepository.getReferenceById(quizSetId)) @@ -190,8 +161,9 @@ public class ReportServiceImpl implements ReportService { QuizSet quizSet = quizSetRepository.getReferenceById(quizSetId); + List registrations = registrationRepository.findByLectureIdAndStatus(lectureId, RegistrationStatus.ACCEPTED); + List reports = registrations.stream() - .filter(Registration::isAccepted) .map((Registration registration)-> registration.makeReport(reportSet, quizSet, lectureId)) .toList(); diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java index eccbc12..7a42d0d 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserService.java @@ -28,6 +28,7 @@ public interface UserService { boolean isEmailExist(String email); + boolean isTeacher(long userId); void changeForgottenPassword(String email, String newPassword); } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java index 68f4e3b..ac6a6d8 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java @@ -159,7 +159,7 @@ public class UserServiceImpl implements UserService { } @Override - public boolean isTeacher(long id){ - return userRepository.findById(id).orElseThrow(IllegalArgumentException::new).getRole() == UserRole.ADMIN; + public boolean isTeacher(long userId){ + return userRepository.findById(userId).orElseThrow(IllegalArgumentException::new).getRole() == UserRole.ADMIN; } } From 35c98af73f89d0c5598234a2e3fa38b875156278 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Thu, 8 Aug 2024 10:51:07 +0900 Subject: [PATCH 148/197] =?UTF-8?q?feat:=20=20qna=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/qna/controller/QnaController.java | 13 ++++++++----- .../edufocus/qna/service/QnaServiceImpl.java | 14 ++++++-------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java b/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java index c4c2a0a..6a20a67 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java @@ -49,17 +49,20 @@ public class QnaController { public ResponseEntity createAnswer(@PathVariable("qna_id") Long qna_id, @RequestBody QnaRequestDto qnaRequestDto, HttpServletRequest request) { try { String token = request.getHeader("Authorization"); + System.out.println(token); Long userId = Long.parseLong(jwtUtil.getUserId(token)); User findUser = userRepository.findById(userId).orElse(null); if (findUser.getRole() != UserRole.ADMIN) { - throw new RuntimeException(); + return new ResponseEntity<>(HttpStatus.NOT_ACCEPTABLE); + } QnaResponseDto responseDto = qnaService.createAnswer(qna_id, qnaRequestDto); return new ResponseEntity<>(responseDto, HttpStatus.ACCEPTED); } catch (Exception e) { - throw new RuntimeException(e); + return new ResponseEntity<>(HttpStatus.NOT_ACCEPTABLE); + } } @@ -91,12 +94,12 @@ public class QnaController { System.out.println("delete answer"); if (findUser.getRole() != UserRole.ADMIN) { - throw new RuntimeException(); + return new ResponseEntity<>(HttpStatus.NOT_ACCEPTABLE); } qnaService.deleteAnswer(qna_id); return new ResponseEntity<>(HttpStatus.ACCEPTED); } catch (Exception e) { - throw new RuntimeException(e); + return new ResponseEntity<>(HttpStatus.NOT_ACCEPTABLE); } } @@ -110,7 +113,7 @@ public class QnaController { return new ResponseEntity<>(qnaResponseDto, HttpStatus.ACCEPTED); } catch (Exception e) { - throw new RuntimeException(e); + return new ResponseEntity<>(HttpStatus.NOT_ACCEPTABLE); } } diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java index 3454e27..6180416 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java @@ -57,18 +57,15 @@ public class QnaServiceImpl implements QnaService { System.out.println("userId:" + userId); - Qna qna = qnaRepository.findById(id).orElse(null); - System.out.println("quesiton에 있는거: " + qna.getUser().getId()); + Qna findQna = qnaRepository.findById(id).orElse(null); + System.out.println("quesiton에 있는거: " + findQna.getUser().getId()); User user = userRepository.findById(userId).orElse(null); - if (qna.getUser().getId() != userId) { + if (findQna.getUser().getId() != userId || user.getRole() != UserRole.STUDENT) { throw new RuntimeException(); } - Qna findQna = qnaRepository.findById(id) - .orElseThrow(() -> new RuntimeException("QnA not found")); - findQna.setModifiedAt(new Date()); findQna.setTitle(qnaRequestDto.getTitle()); findQna.setContent(qnaRequestDto.getContent()); @@ -129,11 +126,12 @@ public class QnaServiceImpl implements QnaService { public QnaResponseDto createAnswer(Long id, QnaRequestDto qnaRequestDto) throws SQLException { Qna findQna = qnaRepository.findById(id).orElse(null); - findQna.setAnswer(qnaRequestDto.getAnswer()); - if (findQna.getAnswer() != null) { throw new RuntimeException(); } + findQna.setAnswer(qnaRequestDto.getAnswer()); + + qnaRepository.save(findQna); return QnaResponseDto.toEntity(findQna); From 026e4c376647cedeef71b07f455efb24c02cb8f2 Mon Sep 17 00:00:00 2001 From: yulmam <70622601+yulmam@users.noreply.github.com> Date: Thu, 8 Aug 2024 10:54:17 +0900 Subject: [PATCH 149/197] =?UTF-8?q?refactor=20:=20=EA=B2=8C=EC=8B=9C?= =?UTF-8?q?=ED=8C=90=20=EC=A0=95=EB=A0=AC=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/edufocus/edufocus/board/service/BoardServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/board/service/BoardServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/board/service/BoardServiceImpl.java index a357de2..de97761 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/service/BoardServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/service/BoardServiceImpl.java @@ -40,7 +40,7 @@ public class BoardServiceImpl implements BoardService { @Transactional public List findBoards(int pageNo, String category, long lectureId) { - Pageable pageable = PageRequest.of(pageNo, PAGE_SIZE, Sort.by("created_at").descending()); + Pageable pageable = PageRequest.of(pageNo, PAGE_SIZE, Sort.by("id").descending()); List boards = boardRepository.findByLectureIdAndCategory(lectureId, category, pageable).getContent(); From 1567e6ce078ea7dbd000c514e5eed3e8066a0bbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Thu, 8 Aug 2024 13:05:08 +0900 Subject: [PATCH 150/197] =?UTF-8?q?feat:=20qna=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/qna/controller/QnaController.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java b/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java index 6a20a67..51d816b 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java @@ -75,13 +75,13 @@ public class QnaController { if (findUser.getRole() != UserRole.ADMIN) { System.out.println("role 안맞음"); - throw new RuntimeException("update 실패"); + return new ResponseEntity<>(HttpStatus.NOT_ACCEPTABLE); } QnaResponseDto responseDto = qnaService.updateAnswer(qna_id, qnaRequestDto); return new ResponseEntity<>(responseDto, HttpStatus.ACCEPTED); } catch (Exception e) { - throw new RuntimeException(e); + return new ResponseEntity<>(HttpStatus.NOT_ACCEPTABLE); } } @@ -126,7 +126,7 @@ public class QnaController { return new ResponseEntity<>(HttpStatus.ACCEPTED); } catch (SQLException e) { - throw new RuntimeException(e); + return new ResponseEntity<>(HttpStatus.NOT_ACCEPTABLE); } } @@ -137,7 +137,7 @@ public class QnaController { return new ResponseEntity<>(findQna, HttpStatus.ACCEPTED); } catch (SQLException e) { - throw new RuntimeException(e); + return new ResponseEntity<>(HttpStatus.NOT_ACCEPTABLE); } } @@ -150,7 +150,7 @@ public class QnaController { return new ResponseEntity<>(qnaList, HttpStatus.ACCEPTED); } catch (SQLException e) { - throw new RuntimeException(e); + return new ResponseEntity<>(HttpStatus.NOT_ACCEPTABLE); } } From ebadf5e5a7e38e44d0fc53247824021a1f45af33 Mon Sep 17 00:00:00 2001 From: kgc91747 Date: Thu, 8 Aug 2024 16:03:10 +0900 Subject: [PATCH 151/197] =?UTF-8?q?feat:=20quiz=20=EC=8B=A4=EC=8B=9C?= =?UTF-8?q?=EB=90=9C=20=EA=B8=B0=EB=A1=9D=EC=9D=B4=20=EC=9E=88=EB=8A=94=20?= =?UTF-8?q?=ED=80=B4=EC=A6=88=20=EC=88=98=EC=A0=95=20=EC=A0=9C=ED=95=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...871dfad-83fc-4665-b2d6-5edeada95134_bono.jpg | Bin 18333 -> 0 bytes ...da84650-3544-45e3-9677-f8187b8ceb34_bono.jpg | Bin 18333 -> 0 bytes .../quiz/controller/QuizController.java | 4 ++++ 3 files changed, 4 insertions(+) delete mode 100644 backend/${IMAGE_PATH}/5871dfad-83fc-4665-b2d6-5edeada95134_bono.jpg delete mode 100644 backend/${IMAGE_PATH}/7da84650-3544-45e3-9677-f8187b8ceb34_bono.jpg diff --git a/backend/${IMAGE_PATH}/5871dfad-83fc-4665-b2d6-5edeada95134_bono.jpg b/backend/${IMAGE_PATH}/5871dfad-83fc-4665-b2d6-5edeada95134_bono.jpg deleted file mode 100644 index c936434d25b4e01743eb3516d58e920c82857cdc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18333 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 diff --git a/backend/${IMAGE_PATH}/7da84650-3544-45e3-9677-f8187b8ceb34_bono.jpg b/backend/${IMAGE_PATH}/7da84650-3544-45e3-9677-f8187b8ceb34_bono.jpg deleted file mode 100644 index c936434d25b4e01743eb3516d58e920c82857cdc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18333 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 diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java b/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java index 49b009d..c95b595 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java @@ -73,6 +73,10 @@ public class QuizController { return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); } + if (quizset.isTested()) { + return new ResponseEntity<>(HttpStatus.CONFLICT); + } + quizSetService.updateQuizSet(quizSetUpdateRequest.getId(), quizSetUpdateRequest.getTitle()); Map quizUpdatedCheckMap = new HashMap<>(); From 6b81a22d6fc132dc5c85f7b8d06cd9e74fb69968 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Thu, 8 Aug 2024 16:10:45 +0900 Subject: [PATCH 152/197] =?UTF-8?q?feat:=20qna=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/edufocus/edufocus/qna/repository/QnaRepository.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/repository/QnaRepository.java b/backend/src/main/java/com/edufocus/edufocus/qna/repository/QnaRepository.java index 9d1c71e..19ebbcd 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/repository/QnaRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/repository/QnaRepository.java @@ -14,5 +14,7 @@ import java.util.List; public interface QnaRepository extends JpaRepository { List findByLectureId(Long lecturerId); + + @Query("SELECT q FROM Qna q WHERE q.lecture.id = :lectureId ORDER BY q.createdAt DESC") Page findByLectureId(Long lectureId, Pageable pageable); } From 159125a12a9a224fa1a668363a8864f6f0a6c696 Mon Sep 17 00:00:00 2001 From: kgc91747 Date: Thu, 8 Aug 2024 16:31:12 +0900 Subject: [PATCH 153/197] =?UTF-8?q?feat:=20registration=20=EC=88=98?= =?UTF-8?q?=EA=B0=95=20=ED=98=84=ED=99=A9=20=EC=A1=B0=ED=9A=8C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/RegistrationRepository.java | 3 +-- .../registration/service/RegistrationService.java | 2 +- .../service/RegistrationServiceImpl.java | 15 +++++++++++---- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/repository/RegistrationRepository.java b/backend/src/main/java/com/edufocus/edufocus/registration/repository/RegistrationRepository.java index 327893d..1ea354b 100644 --- a/backend/src/main/java/com/edufocus/edufocus/registration/repository/RegistrationRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/registration/repository/RegistrationRepository.java @@ -13,8 +13,7 @@ import java.util.List; public interface RegistrationRepository extends JpaRepository { List findAllByUserId(@Param("userId") Long userId); - @Query("SELECT r FROM Registration r WHERE r.lecture.id = :lectureId AND r.status = 'WAITING'") - List findAllNotAcceptedByLectureId(@Param("lectureId") Long lectureId); + List findAllByLectureId(Long lectureId); Registration findByUserIdAndLectureId(Long userId, Long lectureId); diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationService.java b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationService.java index b01c410..7fc0ece 100644 --- a/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationService.java +++ b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationService.java @@ -16,7 +16,7 @@ public interface RegistrationService { boolean deleteRegistration(Long userId, Long registrationId); - List searchRegistrations(Long LectureId); + List[] searchRegistrations(Long LectureId); RegistrationStatus getStatus(Long userId, Long lectureId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java index 26ac48d..78a539e 100644 --- a/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/registration/service/RegistrationServiceImpl.java @@ -74,19 +74,26 @@ public class RegistrationServiceImpl implements RegistrationService { } @Override - public List searchRegistrations(Long lectureId) { - List registrations = registrationRepository.findAllNotAcceptedByLectureId(lectureId); + public List[] searchRegistrations(Long lectureId) { + List registrations = registrationRepository.findAllByLectureId(lectureId); - List responses = new ArrayList<>(); + List[] responses = new ArrayList[2]; + responses[0] = new ArrayList<>(); + responses[1] = new ArrayList<>(); for (Registration registration : registrations) { RegistrationSearchResponse response = RegistrationSearchResponse.builder() .id(registration.getId()) .userName(registration.getUser().getName()) .build(); - responses.add(response); + if (registration.getStatus() == RegistrationStatus.ACCEPTED) { + responses[0].add(response); + } else { + responses[1].add(response); + } } + return responses; } From 349c85ff745bfa83ed2f51bfc6f7eb190885f56b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Thu, 8 Aug 2024 16:35:08 +0900 Subject: [PATCH 154/197] =?UTF-8?q?feat:=20qna=20createAT=20timestamp?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/edufocus/edufocus/qna/entity/Qna.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java b/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java index 901afd3..9a487ee 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java @@ -20,7 +20,7 @@ public class Qna { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name= "qna_id") + @Column(name = "qna_id") private Long id; @@ -32,7 +32,7 @@ public class Qna { @Column(name = "created_at") - @Temporal(TemporalType.DATE) + @Temporal(TemporalType.TIMESTAMP) private Date createdAt; @Column(name = "modified_at") @@ -45,13 +45,12 @@ public class Qna { private String name; @ManyToOne - @JoinColumn(name= "id") + @JoinColumn(name = "id") private User user; @ManyToOne - @JoinColumn(name= "lecture_id") + @JoinColumn(name = "lecture_id") private Lecture lecture; - } From 4b5bdb5ae5c4af033d69fbcfa70ff0f391ca8905 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Thu, 8 Aug 2024 16:59:44 +0900 Subject: [PATCH 155/197] =?UTF-8?q?feat:=20qna=20answer,content=20?= =?UTF-8?q?=EC=9E=90=EB=A3=8C=ED=98=95=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/edufocus/edufocus/qna/entity/Qna.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java b/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java index 9a487ee..96237a9 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java @@ -27,7 +27,7 @@ public class Qna { @Column private String title; - @Column + @Column(columnDefinition = "TEXT") private String content; @@ -39,7 +39,7 @@ public class Qna { @Temporal(TemporalType.DATE) private Date modifiedAt; - @Column + @Column(columnDefinition = "TEXT") private String answer; From d746a0006ff4b6445ce45fad53bb90553cbcbb92 Mon Sep 17 00:00:00 2001 From: yulmam <70622601+yulmam@users.noreply.github.com> Date: Thu, 8 Aug 2024 21:49:11 +0900 Subject: [PATCH 156/197] =?UTF-8?q?refactor=20:=20report=20=EC=98=A4?= =?UTF-8?q?=ED=83=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/edufocus/report/entity/dto/QuizDto.java | 2 +- .../edufocus/report/service/ReportServiceImpl.java | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/QuizDto.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/QuizDto.java index d36281f..5dbc56e 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/QuizDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/QuizDto.java @@ -18,6 +18,6 @@ public class QuizDto { private String image; private String answer; private String userAnswer; - private boolean isCollect; + private boolean isCorrect; private List choices; } diff --git a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java index 3ae6792..b4e637b 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java @@ -54,17 +54,17 @@ public class ReportServiceImpl implements ReportService { for (int idx = 0; idx < answerInputList.size(); idx++) { Quiz quiz = quizList.get(idx); String inputAnswer = answerInputList.get(idx); - boolean isCollect; + boolean isCorrect; Answer answer; if (quiz.getAnswer().equals(inputAnswer)) { correctCount++; - isCollect = true; + isCorrect = true; } else { - isCollect = false; + isCorrect = false; } answer = Answer.builder() .userAnswer(inputAnswer) - .isCorrect(isCollect) + .isCorrect(isCorrect) .report(report) .quiz(quiz) .build(); @@ -106,7 +106,7 @@ public class ReportServiceImpl implements ReportService { .question(quiz.getQuestion()) .answer(quiz.getAnswer()) .userAnswer(answer.getUserAnswer()) - .isCollect(answer.isCorrect()) + .isCorrect(answer.isCorrect()) .choices(choiceDtos) .build(); From 6ba555de6275ba5e185dae9b023ac929141b3aab Mon Sep 17 00:00:00 2001 From: yulmam <70622601+yulmam@users.noreply.github.com> Date: Thu, 8 Aug 2024 21:52:53 +0900 Subject: [PATCH 157/197] =?UTF-8?q?refactor=20:=20registartion=20=EC=98=A4?= =?UTF-8?q?=ED=83=80=20=EC=A0=95=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../registration/controller/RegistrationController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/controller/RegistrationController.java b/backend/src/main/java/com/edufocus/edufocus/registration/controller/RegistrationController.java index 4b8bba3..2b019c9 100644 --- a/backend/src/main/java/com/edufocus/edufocus/registration/controller/RegistrationController.java +++ b/backend/src/main/java/com/edufocus/edufocus/registration/controller/RegistrationController.java @@ -36,7 +36,7 @@ public class RegistrationController { } @PutMapping("/{registrationId}") - public ResponseEntity acceptRigistration(@RequestHeader("Authorization") String accessToken, @PathVariable long registrationId) { + public ResponseEntity acceptRegistration(@RequestHeader("Authorization") String accessToken, @PathVariable long registrationId) { Long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); if (!registrationService.acceptRegistration(userId, registrationId)) { @@ -47,7 +47,7 @@ public class RegistrationController { } @DeleteMapping("/{registrationId}") - public ResponseEntity deleteRigistration(@RequestHeader("Authorization") String accessToken, @PathVariable long registrationId) { + public ResponseEntity deleteRegistration(@RequestHeader("Authorization") String accessToken, @PathVariable long registrationId) { Long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); if (!registrationService.deleteRegistration(userId, registrationId)) { From 1962d5b2dfaabe95bc05535f2edaa2c8c44a16ee Mon Sep 17 00:00:00 2001 From: yulmam <70622601+yulmam@users.noreply.github.com> Date: Thu, 8 Aug 2024 21:55:54 +0900 Subject: [PATCH 158/197] =?UTF-8?q?feat=20:=20report,=20reportSet=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=EC=8B=9C=20=EC=8B=9C=EA=B0=84=20=EA=B0=B1?= =?UTF-8?q?=EC=8B=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/edufocus/edufocus/report/entity/vo/Report.java | 4 ++++ .../com/edufocus/edufocus/report/entity/vo/ReportSet.java | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java index dcc4b95..c588112 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java @@ -3,9 +3,11 @@ package com.edufocus.edufocus.report.entity.vo; import com.edufocus.edufocus.quiz.entity.QuizSet; import com.edufocus.edufocus.report.entity.dto.ReportResponse; import com.edufocus.edufocus.user.model.entity.vo.User; +import com.fasterxml.jackson.annotation.JsonAutoDetect; import jakarta.persistence.*; import lombok.*; import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; import java.time.LocalDateTime; import java.util.Date; @@ -17,6 +19,8 @@ import java.util.List; @NoArgsConstructor @AllArgsConstructor @Builder +@EntityListeners(AuditingEntityListener.class) +@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) public class Report { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java index 2dedc12..e097f97 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java @@ -3,11 +3,13 @@ package com.edufocus.edufocus.report.entity.vo; import com.edufocus.edufocus.lecture.entity.Lecture; import com.edufocus.edufocus.quiz.entity.QuizSet; import com.edufocus.edufocus.report.entity.dto.ReportSetResponse; +import com.fasterxml.jackson.annotation.JsonAutoDetect; import jakarta.persistence.*; import lombok.*; import org.hibernate.annotations.ColumnDefault; import org.hibernate.annotations.GenericGenerator; import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; import java.time.LocalDateTime; @@ -21,6 +23,8 @@ import java.util.UUID; @Builder @NoArgsConstructor @AllArgsConstructor +@EntityListeners(AuditingEntityListener.class) +@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) public class ReportSet { @Id @GeneratedValue(generator = "UUID") From 0f60c9c4cf0cf56b2e396475706fe1f3c126deed Mon Sep 17 00:00:00 2001 From: yulmam <70622601+yulmam@users.noreply.github.com> Date: Thu, 8 Aug 2024 21:57:39 +0900 Subject: [PATCH 159/197] =?UTF-8?q?feat=20:=20=EA=B2=8C=EC=8B=9C=ED=8C=90?= =?UTF-8?q?=20=EB=8C=93=EA=B8=80=20=ED=98=95=20text=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/edufocus/edufocus/board/entity/vo/Board.java | 2 +- .../java/com/edufocus/edufocus/board/entity/vo/Comment.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java index c2a2519..e4fba11 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java @@ -34,7 +34,7 @@ public class Board { @Column(nullable = false) private String category; - @Column(nullable = false) + @Column(columnDefinition = "TEXT", nullable = false) private String content; @Column(nullable = true) diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java index aa05c5b..9bd6361 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java @@ -22,7 +22,8 @@ public class Comment { @Id @GeneratedValue private long id; - @Column + + @Column(columnDefinition = "TEXT", nullable = false) private String content; @Column From 5dfbcb3dd204c5ac71bd97420271e631a9c00ef8 Mon Sep 17 00:00:00 2001 From: yulmam <70622601+yulmam@users.noreply.github.com> Date: Thu, 8 Aug 2024 22:04:47 +0900 Subject: [PATCH 160/197] =?UTF-8?q?feat=20:=20reportSet=20delete=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/report/controller/ReportController.java | 9 +++++++++ .../edufocus/edufocus/report/entity/vo/ReportSet.java | 4 ++++ .../edufocus/edufocus/report/service/ReportService.java | 2 ++ .../edufocus/report/service/ReportServiceImpl.java | 7 +++++++ 4 files changed, 22 insertions(+) diff --git a/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java b/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java index 673bf19..3dfda46 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java @@ -87,4 +87,13 @@ public class ReportController { return new ResponseEntity<>(reportResponses, HttpStatus.OK); } + @DeleteMapping("/teacher/report/{reportSetId}") + public ResponseEntity deleteReportSet(@PathVariable("reportSetId") UUID reportSetId, HttpServletRequest request){ + String token = request.getHeader("Authorization"); + long userId = Long.parseLong(jwtUtil.getUserId(token)); + + reportService.deleteReportSet(reportSetId, userId); + + return new ResponseEntity<>(HttpStatus.OK); + } } diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java index e097f97..5ff6b88 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java @@ -55,4 +55,8 @@ public class ReportSet { .testAt(createAt) .build(); } + + public long findUserId(){ + return lecture.getUser().getId(); + } } diff --git a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportService.java b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportService.java index 1e1b2b2..5c51ab5 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportService.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportService.java @@ -20,4 +20,6 @@ public interface ReportService { List findReports(long lectureId, long userid); UUID initReportSet(long lectureId, long quizSetId); + + void deleteReportSet(UUID reportSetId, long userId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java index b4e637b..33d0a71 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java @@ -172,4 +172,11 @@ public class ReportServiceImpl implements ReportService { return reportSet.getId(); } + + @Override + public void deleteReportSet(UUID reportSetId, long userId) { + ReportSet reportSet = reportSetRepository.findById(reportSetId).orElseThrow(NoSuchElementException::new); + if(reportSet.findUserId() == userId) + reportSetRepository.delete(reportSet); + } } From 5740b6f53a711e6893ba559b47c546b0168e18da Mon Sep 17 00:00:00 2001 From: kgc91747 Date: Fri, 9 Aug 2024 09:47:04 +0900 Subject: [PATCH 161/197] =?UTF-8?q?feat:=20Lecture=20=EA=B0=95=EC=9D=98=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EC=BB=AC=EB=9F=BC=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/edufocus/edufocus/lecture/entity/Lecture.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java index 5db4488..734354a 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/entity/Lecture.java @@ -27,10 +27,10 @@ public class Lecture { @Column private String title; - @Lob + @Column(columnDefinition = "text") private String description; - @Lob + @Column(columnDefinition = "text") private String plan; @Column From e07f47213da66eaedcd3f513079fabb0ee0a3628 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Fri, 9 Aug 2024 09:51:05 +0900 Subject: [PATCH 162/197] =?UTF-8?q?feat:=20qna=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../qna/controller/QnaController.java | 6 +++-- .../com/edufocus/edufocus/qna/entity/Qna.java | 2 ++ .../edufocus/qna/entity/QnaResponseDto.java | 10 ++++--- .../edufocus/qna/service/QnaService.java | 2 +- .../edufocus/qna/service/QnaServiceImpl.java | 19 ++++++++++--- .../report/controller/ReportController.java | 27 +++++++++---------- 6 files changed, 41 insertions(+), 25 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java b/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java index 51d816b..3235b2c 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java @@ -131,9 +131,11 @@ public class QnaController { } @GetMapping("/{id}") - public ResponseEntity getQna(@PathVariable Long id) { + public ResponseEntity getQna(@PathVariable Long id, HttpServletRequest request) { try { - QnaResponseDto findQna = qnaService.getQna(id); + String token = request.getHeader("Authorization"); + long userId = Long.parseLong(jwtUtil.getUserId(token)); + QnaResponseDto findQna = qnaService.getQna(id, userId); return new ResponseEntity<>(findQna, HttpStatus.ACCEPTED); } catch (SQLException e) { diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java b/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java index 96237a9..af797ee 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java @@ -52,5 +52,7 @@ public class Qna { @JoinColumn(name = "lecture_id") private Lecture lecture; + private boolean isMine; + } diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/entity/QnaResponseDto.java b/backend/src/main/java/com/edufocus/edufocus/qna/entity/QnaResponseDto.java index ee7c768..4a55d77 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/entity/QnaResponseDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/entity/QnaResponseDto.java @@ -1,6 +1,7 @@ package com.edufocus.edufocus.qna.entity; import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; import org.springframework.stereotype.Service; @@ -11,6 +12,7 @@ import java.util.Date; @NoArgsConstructor @AllArgsConstructor +@Builder public class QnaResponseDto { @@ -20,15 +22,17 @@ public class QnaResponseDto { private String content; private Date createtAt; private String answer; - public static QnaResponseDto toEntity(Qna qna) - { + private boolean isMine; + + public static QnaResponseDto toEntity(Qna qna) { return new QnaResponseDto( qna.getId(), qna.getTitle(), qna.getUser().getName(), qna.getContent(), qna.getCreatedAt(), - qna.getAnswer() + qna.getAnswer(), + qna.isMine() ); } diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaService.java b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaService.java index 912ed9e..877d4ef 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaService.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaService.java @@ -20,7 +20,7 @@ public interface QnaService { void deleteQna(Long id, Long userId) throws SQLException; - QnaResponseDto getQna(Long id) throws SQLException; + QnaResponseDto getQna(Long id, Long userId) throws SQLException; List getAllQnasByLecture(Long lectureId, int pageNumber) throws SQLException; diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java index 6180416..bad6f09 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java @@ -91,11 +91,12 @@ public class QnaServiceImpl implements QnaService { } @Override - public QnaResponseDto getQna(Long id) { - Optional qna; + public QnaResponseDto getQna(Long id, Long userId) { + + Qna qna; try { - qna = qnaRepository.findById(id); + qna = qnaRepository.findById(id).orElse(null); } catch (Exception e) { @@ -103,8 +104,18 @@ public class QnaServiceImpl implements QnaService { throw new RuntimeException("Qna 없음 " + id, e); } + QnaResponseDto dto = QnaResponseDto.builder() + .id(qna.getId()) + .title(qna.getTitle()) + .username(qna.getUser().getName()) + .content(qna.getContent()) + .createtAt(qna.getCreatedAt()) + .answer(qna.getAnswer()) + .isMine(userId == qna.getUser().getId()) + .build(); - return QnaResponseDto.toEntity(qna.get()); + + return dto; } diff --git a/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java b/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java index 673bf19..c58483c 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java @@ -29,7 +29,7 @@ public class ReportController { @PostMapping("/submit/quizSet/{reportSetId}") public ResponseEntity submit(@PathVariable("reportSetId") UUID reportSetId, @RequestBody ReportRequest reportRequest, HttpServletRequest request) { - String token = request.getHeader("Authorization"); + String token = request.getHeader("Authoriza]tion"); long userId = Long.parseLong(jwtUtil.getUserId(token)); if (userService.isTeacher(userId)) @@ -49,41 +49,38 @@ public class ReportController { List reportResponses = reportService.findReports(lectureId, userId); - if(reportResponses.isEmpty()) + if (reportResponses.isEmpty()) return new ResponseEntity<>(HttpStatus.NO_CONTENT); return new ResponseEntity<>(reportResponses, HttpStatus.OK); } - @GetMapping("/reportDetail/{reportId}") - public ResponseEntity searchDetailReport(@PathVariable("reportId") long reportId){ + public ResponseEntity searchDetailReport(@PathVariable("reportId") long reportId) { ReportDetailResponseDto detailReport = reportService.reportDetail(reportId); return new ResponseEntity<>(detailReport, HttpStatus.OK); } - - @GetMapping("/teacher/reportSet/{lectureId}") - public ResponseEntity> searchReportSets(@PathVariable("lectureId") long lectureId){ + public ResponseEntity> searchReportSets(@PathVariable("lectureId") long lectureId) { List reportSetResponses = reportService.findReportSets(lectureId); - - if(reportSetResponses.isEmpty()) + + if (reportSetResponses.isEmpty()) return new ResponseEntity<>(HttpStatus.NO_CONTENT); - + return new ResponseEntity<>(reportSetResponses, HttpStatus.OK); } - + @GetMapping("/teacher/report/{reportSetId}") - public ResponseEntity searchReports(@PathVariable("reportSetId") UUID reportSetId){ + public ResponseEntity searchReports(@PathVariable("reportSetId") UUID reportSetId) { List reportResponses = reportService.findReports(reportSetId); - - if(reportResponses.isEmpty()) + + if (reportResponses.isEmpty()) return new ResponseEntity<>(HttpStatus.NO_CONTENT); - + return new ResponseEntity<>(reportResponses, HttpStatus.OK); } From 49bf79dd05a9bfee133a78a18dcfa5e20fa21e4a Mon Sep 17 00:00:00 2001 From: yulmam <70622601+yulmam@users.noreply.github.com> Date: Fri, 9 Aug 2024 10:10:24 +0900 Subject: [PATCH 163/197] =?UTF-8?q?feat=20:=20=EC=8B=9C=EA=B0=84=EB=8C=80?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/edufocus/edufocus/board/entity/vo/Board.java | 2 ++ .../com/edufocus/edufocus/board/entity/vo/Comment.java | 8 ++++++-- .../edufocus/report/controller/ReportController.java | 3 --- .../com/edufocus/edufocus/report/entity/vo/Report.java | 1 + .../com/edufocus/edufocus/report/entity/vo/ReportSet.java | 1 + 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java index e4fba11..0f7d34a 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java @@ -40,9 +40,11 @@ public class Board { @Column(nullable = true) private int viewCount; + @Column(columnDefinition = "TIMESTAMP") @CreatedDate LocalDateTime createdAt; + @Column(columnDefinition = "TIMESTAMP") @LastModifiedDate LocalDateTime modifiedAt; diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java index 9bd6361..9887128 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java @@ -9,6 +9,8 @@ import lombok.AllArgsConstructor; import lombok.Builder; import lombok.NoArgsConstructor; import lombok.Setter; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; import java.time.LocalDateTime; @@ -26,10 +28,12 @@ public class Comment { @Column(columnDefinition = "TEXT", nullable = false) private String content; - @Column + @Column(columnDefinition = "TIMESTAMP") + @CreatedDate private LocalDateTime createdAt; - @Column + @Column(columnDefinition = "TIMESTAMP") + @LastModifiedDate private LocalDateTime modifiedAt; @ManyToOne diff --git a/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java b/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java index 3dfda46..ec1c747 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java @@ -64,9 +64,6 @@ public class ReportController { return new ResponseEntity<>(detailReport, HttpStatus.OK); } - - - @GetMapping("/teacher/reportSet/{lectureId}") public ResponseEntity> searchReportSets(@PathVariable("lectureId") long lectureId){ List reportSetResponses = reportService.findReportSets(lectureId); diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java index c588112..9205532 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java @@ -30,6 +30,7 @@ public class Report { private int correctCount; + @Column(columnDefinition = "TIMESTAMP") @CreatedDate private LocalDateTime testAt; diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java index 5ff6b88..7f8f691 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java @@ -34,6 +34,7 @@ public class ReportSet { ) private UUID id; + @Column(columnDefinition = "TIMESTAMP") @CreatedDate private LocalDateTime createAt; From 696fb85a21d45f5247aa5a6760402cc5eafa6e11 Mon Sep 17 00:00:00 2001 From: yulmam <70622601+yulmam@users.noreply.github.com> Date: Fri, 9 Aug 2024 10:10:46 +0900 Subject: [PATCH 164/197] =?UTF-8?q?feat=20:=20getter=20setter=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/report/entity/dto/ReportSetResponse.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportSetResponse.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportSetResponse.java index ad300bf..a7ea791 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportSetResponse.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportSetResponse.java @@ -1,14 +1,14 @@ package com.edufocus.edufocus.report.entity.dto; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.NoArgsConstructor; +import lombok.*; import java.time.LocalDateTime; import java.util.UUID; @Builder +@Getter +@Setter @NoArgsConstructor @AllArgsConstructor public class ReportSetResponse { From 3ccd5e99b0cb461d98b8c1b0741077235012ffb0 Mon Sep 17 00:00:00 2001 From: yulmam <70622601+yulmam@users.noreply.github.com> Date: Fri, 9 Aug 2024 10:12:57 +0900 Subject: [PATCH 165/197] =?UTF-8?q?feat=20:=20report=20=EC=A0=95=EB=A0=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/report/repository/ReportRepository.java | 7 ++----- .../edufocus/report/repository/ReportSetRepository.java | 2 +- .../edufocus/report/service/ReportServiceImpl.java | 6 +++--- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportRepository.java b/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportRepository.java index 7665f28..7b1e1ac 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportRepository.java @@ -9,13 +9,10 @@ import java.util.UUID; @Repository public interface ReportRepository extends JpaRepository { - List findByUserId(long userId); - - List findByLectureId(long lectureId); Report findByReportSetIdAndUserId(UUID reportSetId, long userId); - List findByReportSetId(UUID reportSetId); + List findByReportSetIdDesc(UUID reportSetId); - List findByLectureIdAndUserId(long lectureId, long userId); + List findByLectureIdAndUserIdDesc(long lectureId, long userId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportSetRepository.java b/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportSetRepository.java index f1b484c..f4f37fb 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportSetRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportSetRepository.java @@ -9,5 +9,5 @@ import java.util.UUID; @Repository public interface ReportSetRepository extends JpaRepository { - List findByLectureId(long userId); + List findByLectureIdDesc(long userId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java index 33d0a71..1b80593 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java @@ -125,7 +125,7 @@ public class ReportServiceImpl implements ReportService { @Override public List findReportSets(long lectureId) { - List reportSets = reportSetRepository.findByLectureId(lectureId); + List reportSets = reportSetRepository.findByLectureIdDesc(lectureId); return reportSets.stream() .map(ReportSet::makeReportSetResponse) @@ -134,7 +134,7 @@ public class ReportServiceImpl implements ReportService { @Override public List findReports(UUID reportSetId) { - List reports = reportRepository.findByReportSetId(reportSetId); + List reports = reportRepository.findByReportSetIdDesc(reportSetId); return reports.stream() .map(Report::makeReportResponse) @@ -143,7 +143,7 @@ public class ReportServiceImpl implements ReportService { @Override public List findReports(long lectureId, long userId) { - List reports = reportRepository.findByLectureIdAndUserId(lectureId, userId); + List reports = reportRepository.findByLectureIdAndUserIdDesc(lectureId, userId); return reports.stream() .map(Report::makeReportResponse) From aeb2d7f93233e293f8894db95d78f0716777e7b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=ED=95=9C=EC=96=BC?= Date: Fri, 9 Aug 2024 10:17:36 +0900 Subject: [PATCH 166/197] Revert "Merge branch 'Be/Report' into 'backend'" This reverts merge request !126 --- .../edufocus/report/repository/ReportRepository.java | 7 +++++-- .../edufocus/report/repository/ReportSetRepository.java | 2 +- .../edufocus/report/service/ReportServiceImpl.java | 6 +++--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportRepository.java b/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportRepository.java index 7b1e1ac..7665f28 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportRepository.java @@ -9,10 +9,13 @@ import java.util.UUID; @Repository public interface ReportRepository extends JpaRepository { + List findByUserId(long userId); + + List findByLectureId(long lectureId); Report findByReportSetIdAndUserId(UUID reportSetId, long userId); - List findByReportSetIdDesc(UUID reportSetId); + List findByReportSetId(UUID reportSetId); - List findByLectureIdAndUserIdDesc(long lectureId, long userId); + List findByLectureIdAndUserId(long lectureId, long userId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportSetRepository.java b/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportSetRepository.java index f4f37fb..f1b484c 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportSetRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportSetRepository.java @@ -9,5 +9,5 @@ import java.util.UUID; @Repository public interface ReportSetRepository extends JpaRepository { - List findByLectureIdDesc(long userId); + List findByLectureId(long userId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java index 1b80593..33d0a71 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java @@ -125,7 +125,7 @@ public class ReportServiceImpl implements ReportService { @Override public List findReportSets(long lectureId) { - List reportSets = reportSetRepository.findByLectureIdDesc(lectureId); + List reportSets = reportSetRepository.findByLectureId(lectureId); return reportSets.stream() .map(ReportSet::makeReportSetResponse) @@ -134,7 +134,7 @@ public class ReportServiceImpl implements ReportService { @Override public List findReports(UUID reportSetId) { - List reports = reportRepository.findByReportSetIdDesc(reportSetId); + List reports = reportRepository.findByReportSetId(reportSetId); return reports.stream() .map(Report::makeReportResponse) @@ -143,7 +143,7 @@ public class ReportServiceImpl implements ReportService { @Override public List findReports(long lectureId, long userId) { - List reports = reportRepository.findByLectureIdAndUserIdDesc(lectureId, userId); + List reports = reportRepository.findByLectureIdAndUserId(lectureId, userId); return reports.stream() .map(Report::makeReportResponse) From 479649a98771e14597d435bfd4062001e7c44eb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Fri, 9 Aug 2024 10:25:24 +0900 Subject: [PATCH 167/197] =?UTF-8?q?feat:=20qna=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/report/controller/ReportController.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java b/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java index 3feb224..7edb3b3 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java @@ -63,10 +63,7 @@ public class ReportController { return new ResponseEntity<>(detailReport, HttpStatus.OK); } -<<<<<<< HEAD -======= ->>>>>>> 935331e7e93d9c25ec6f32ba6155ed19b5fd60f9 @GetMapping("/teacher/reportSet/{lectureId}") public ResponseEntity> searchReportSets(@PathVariable("lectureId") long lectureId) { List reportSetResponses = reportService.findReportSets(lectureId); @@ -88,7 +85,7 @@ public class ReportController { } @DeleteMapping("/teacher/report/{reportSetId}") - public ResponseEntity deleteReportSet(@PathVariable("reportSetId") UUID reportSetId, HttpServletRequest request){ + public ResponseEntity deleteReportSet(@PathVariable("reportSetId") UUID reportSetId, HttpServletRequest request) { String token = request.getHeader("Authorization"); long userId = Long.parseLong(jwtUtil.getUserId(token)); From fa9361ca2dd4b6f3525fa55977b0c53ee0163321 Mon Sep 17 00:00:00 2001 From: yulmam <70622601+yulmam@users.noreply.github.com> Date: Fri, 9 Aug 2024 10:48:40 +0900 Subject: [PATCH 168/197] =?UTF-8?q?feat=20:=20report=20=EC=A0=95=EB=A0=AC?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/report/repository/ReportRepository.java | 8 ++------ .../edufocus/report/repository/ReportSetRepository.java | 2 +- .../edufocus/report/service/ReportServiceImpl.java | 6 +++--- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportRepository.java b/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportRepository.java index 7665f28..2ada83f 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportRepository.java @@ -9,13 +9,9 @@ import java.util.UUID; @Repository public interface ReportRepository extends JpaRepository { - List findByUserId(long userId); - - List findByLectureId(long lectureId); - Report findByReportSetIdAndUserId(UUID reportSetId, long userId); - List findByReportSetId(UUID reportSetId); + List findByReportSetIdOrderById(UUID reportSetId); - List findByLectureIdAndUserId(long lectureId, long userId); + List findByLectureIdAndUserIdOrderById(long lectureId, long userId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportSetRepository.java b/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportSetRepository.java index f1b484c..fcf2449 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportSetRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/repository/ReportSetRepository.java @@ -9,5 +9,5 @@ import java.util.UUID; @Repository public interface ReportSetRepository extends JpaRepository { - List findByLectureId(long userId); + List findByLectureIdOrderById(long userId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java index 33d0a71..8ebcaaa 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java @@ -125,7 +125,7 @@ public class ReportServiceImpl implements ReportService { @Override public List findReportSets(long lectureId) { - List reportSets = reportSetRepository.findByLectureId(lectureId); + List reportSets = reportSetRepository.findByLectureIdOrderById(lectureId); return reportSets.stream() .map(ReportSet::makeReportSetResponse) @@ -134,7 +134,7 @@ public class ReportServiceImpl implements ReportService { @Override public List findReports(UUID reportSetId) { - List reports = reportRepository.findByReportSetId(reportSetId); + List reports = reportRepository.findByReportSetIdOrderById(reportSetId); return reports.stream() .map(Report::makeReportResponse) @@ -143,7 +143,7 @@ public class ReportServiceImpl implements ReportService { @Override public List findReports(long lectureId, long userId) { - List reports = reportRepository.findByLectureIdAndUserId(lectureId, userId); + List reports = reportRepository.findByLectureIdAndUserIdOrderById(lectureId, userId); return reports.stream() .map(Report::makeReportResponse) From 811a835d4f966598c1659ed14a2572d30eb62229 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Fri, 9 Aug 2024 12:41:24 +0900 Subject: [PATCH 169/197] =?UTF-8?q?feat:=20report=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/edufocus/report/controller/ReportController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java b/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java index 7edb3b3..afddfe3 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/controller/ReportController.java @@ -29,7 +29,7 @@ public class ReportController { @PostMapping("/submit/quizSet/{reportSetId}") public ResponseEntity submit(@PathVariable("reportSetId") UUID reportSetId, @RequestBody ReportRequest reportRequest, HttpServletRequest request) { - String token = request.getHeader("Authoriza]tion"); + String token = request.getHeader("Authorization"); long userId = Long.parseLong(jwtUtil.getUserId(token)); if (userService.isTeacher(userId)) From 4ef7d81198bd2df5418834b2471058a69348c603 Mon Sep 17 00:00:00 2001 From: yulmam <70622601+yulmam@users.noreply.github.com> Date: Fri, 9 Aug 2024 13:37:50 +0900 Subject: [PATCH 170/197] =?UTF-8?q?feat=20:=20timestamp=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/edufocus/edufocus/board/entity/vo/Board.java | 6 ++++-- .../java/com/edufocus/edufocus/board/entity/vo/Comment.java | 6 ++++-- .../java/com/edufocus/edufocus/report/entity/vo/Report.java | 5 +++-- .../com/edufocus/edufocus/report/entity/vo/ReportSet.java | 5 +++-- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java index 0f7d34a..bc05d56 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java @@ -8,6 +8,8 @@ import com.edufocus.edufocus.user.model.entity.vo.User; import com.fasterxml.jackson.annotation.JsonAutoDetect; import jakarta.persistence.*; import lombok.*; +import org.hibernate.annotations.CreationTimestamp; +import org.hibernate.annotations.UpdateTimestamp; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; @@ -41,11 +43,11 @@ public class Board { private int viewCount; @Column(columnDefinition = "TIMESTAMP") - @CreatedDate + @CreationTimestamp LocalDateTime createdAt; @Column(columnDefinition = "TIMESTAMP") - @LastModifiedDate + @UpdateTimestamp LocalDateTime modifiedAt; @ManyToOne(fetch = FetchType.LAZY) diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java index 9887128..4928800 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java @@ -9,6 +9,8 @@ import lombok.AllArgsConstructor; import lombok.Builder; import lombok.NoArgsConstructor; import lombok.Setter; +import org.hibernate.annotations.CreationTimestamp; +import org.hibernate.annotations.UpdateTimestamp; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; @@ -29,11 +31,11 @@ public class Comment { private String content; @Column(columnDefinition = "TIMESTAMP") - @CreatedDate + @CreationTimestamp private LocalDateTime createdAt; @Column(columnDefinition = "TIMESTAMP") - @LastModifiedDate + @UpdateTimestamp private LocalDateTime modifiedAt; @ManyToOne diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java index 9205532..32a5b5c 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java @@ -6,6 +6,7 @@ import com.edufocus.edufocus.user.model.entity.vo.User; import com.fasterxml.jackson.annotation.JsonAutoDetect; import jakarta.persistence.*; import lombok.*; +import org.hibernate.annotations.CreationTimestamp; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; @@ -31,7 +32,7 @@ public class Report { private int correctCount; @Column(columnDefinition = "TIMESTAMP") - @CreatedDate + @CreationTimestamp private LocalDateTime testAt; private Long lectureId; @@ -48,7 +49,7 @@ public class Report { @JoinColumn(name = "reportset_id") private ReportSet reportSet; - @OneToMany(mappedBy = "report", cascade = CascadeType.ALL) + @OneToMany(mappedBy = "report", cascade = CascadeType.REMOVE) private List answers; public ReportResponse makeReportResponse(){ diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java index 7f8f691..d263393 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java @@ -7,6 +7,7 @@ import com.fasterxml.jackson.annotation.JsonAutoDetect; import jakarta.persistence.*; import lombok.*; import org.hibernate.annotations.ColumnDefault; +import org.hibernate.annotations.CreationTimestamp; import org.hibernate.annotations.GenericGenerator; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; @@ -35,10 +36,10 @@ public class ReportSet { private UUID id; @Column(columnDefinition = "TIMESTAMP") - @CreatedDate + @CreationTimestamp private LocalDateTime createAt; - @OneToMany(mappedBy = "reportSet", cascade = CascadeType.ALL) + @OneToMany(mappedBy = "reportSet", cascade = CascadeType.REMOVE) private List reports; @ManyToOne From a435fd4aca3add44e0a81924ba36ecd16897e5e4 Mon Sep 17 00:00:00 2001 From: yulmam <70622601+yulmam@users.noreply.github.com> Date: Fri, 9 Aug 2024 13:44:38 +0900 Subject: [PATCH 171/197] =?UTF-8?q?feat=20:=20jpa=20=EC=8B=9C=EA=B0=84=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/main/resources/application.properties | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index d46f4df..1ed7270 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -23,6 +23,7 @@ spring.mvc.pathmatch.matching-strategy=ant_path_matcher spring.jpa.database=mysql spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true +spring.jpa.properties.hibernate.jdbc.time_zone=UTC management.endpoints.web.exposure.include=health,info management.endpoint.health.show-details=always spring.rabbitmq.host=${RABBITMQ_HOST} From 365b12ad9eb98ea99bf129e9b05d0c4fd6b56eb7 Mon Sep 17 00:00:00 2001 From: kgc91747 Date: Fri, 9 Aug 2024 13:48:57 +0900 Subject: [PATCH 172/197] =?UTF-8?q?feat:=20mail=20=EC=9D=B4=EB=A9=94?= =?UTF-8?q?=EC=9D=BC=20=EC=9D=B8=EC=A6=9D=20=EB=B9=84=EB=8F=99=EA=B8=B0=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/EdufocusApplication.java | 2 ++ .../edufocus/global/config/AsyncConfig.java | 32 +++++++++++++++++++ .../mail/service/MailServiceImpl.java | 2 ++ 3 files changed, 36 insertions(+) create mode 100644 backend/src/main/java/com/edufocus/edufocus/global/config/AsyncConfig.java diff --git a/backend/src/main/java/com/edufocus/edufocus/EdufocusApplication.java b/backend/src/main/java/com/edufocus/edufocus/EdufocusApplication.java index e80c9fd..41669f4 100644 --- a/backend/src/main/java/com/edufocus/edufocus/EdufocusApplication.java +++ b/backend/src/main/java/com/edufocus/edufocus/EdufocusApplication.java @@ -3,7 +3,9 @@ package com.edufocus.edufocus; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +import org.springframework.scheduling.annotation.EnableAsync; +@EnableAsync @EnableJpaAuditing @SpringBootApplication public class EdufocusApplication { diff --git a/backend/src/main/java/com/edufocus/edufocus/global/config/AsyncConfig.java b/backend/src/main/java/com/edufocus/edufocus/global/config/AsyncConfig.java new file mode 100644 index 0000000..4a2cee9 --- /dev/null +++ b/backend/src/main/java/com/edufocus/edufocus/global/config/AsyncConfig.java @@ -0,0 +1,32 @@ +package com.edufocus.edufocus.global.config; + +import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.AsyncConfigurer; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; + +import java.util.concurrent.Executor; + +@Configuration +@EnableWebMvc +public class AsyncConfig implements AsyncConfigurer { + + @Override + @Bean(name = "mailExecutor") + public Executor getAsyncExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setCorePoolSize(5); + executor.setMaxPoolSize(10); + executor.setQueueCapacity(500); + executor.setThreadNamePrefix("MailExecutor-"); + executor.initialize(); + return executor; + } + + @Override + public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { + return AsyncConfigurer.super.getAsyncUncaughtExceptionHandler(); + } +} diff --git a/backend/src/main/java/com/edufocus/edufocus/mail/service/MailServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/mail/service/MailServiceImpl.java index 201c99d..a5c1eb9 100644 --- a/backend/src/main/java/com/edufocus/edufocus/mail/service/MailServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/mail/service/MailServiceImpl.java @@ -8,6 +8,7 @@ import lombok.ToString; import lombok.extern.slf4j.Slf4j; import org.springframework.mail.SimpleMailMessage; import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import java.util.Random; @@ -27,6 +28,7 @@ public class MailServiceImpl implements MailService { private final RedisUtil redisUtil; @Override + @Async("mailExecutor") public void sendMail(String email) { String code = createRandomCode(); From 7e7d30911257c723c8f4baaaa728f4a323444b2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Fri, 9 Aug 2024 13:56:01 +0900 Subject: [PATCH 173/197] =?UTF-8?q?db=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/main/resources/application.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index d46f4df..dc2432e 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -21,7 +21,7 @@ spring.datasource.username=${USER_NAME} spring.datasource.password=${USER_PASSWORD} spring.mvc.pathmatch.matching-strategy=ant_path_matcher spring.jpa.database=mysql -spring.jpa.hibernate.ddl-auto=update +spring.jpa.hibernate.ddl-auto=create spring.jpa.show-sql=true management.endpoints.web.exposure.include=health,info management.endpoint.health.show-details=always From f815c0ed21598347deee4638a4c002153acc3af5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Fri, 9 Aug 2024 13:57:00 +0900 Subject: [PATCH 174/197] =?UTF-8?q?db=20=EB=B3=80=EA=B2=BD=20update?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/main/resources/application.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index dc2432e..d46f4df 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -21,7 +21,7 @@ spring.datasource.username=${USER_NAME} spring.datasource.password=${USER_PASSWORD} spring.mvc.pathmatch.matching-strategy=ant_path_matcher spring.jpa.database=mysql -spring.jpa.hibernate.ddl-auto=create +spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true management.endpoints.web.exposure.include=health,info management.endpoint.health.show-details=always From bf735c4d5db8cdcaa649dc45cd48a85d9b76fc3d Mon Sep 17 00:00:00 2001 From: yulmam <70622601+yulmam@users.noreply.github.com> Date: Fri, 9 Aug 2024 14:02:23 +0900 Subject: [PATCH 175/197] =?UTF-8?q?feat=20:=20timezone=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/main/resources/application.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 1ed7270..943e868 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -23,7 +23,7 @@ spring.mvc.pathmatch.matching-strategy=ant_path_matcher spring.jpa.database=mysql spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true -spring.jpa.properties.hibernate.jdbc.time_zone=UTC +spring.jpa.properties.hibernate.jdbc.time_zone=Asia/Seoul management.endpoints.web.exposure.include=health,info management.endpoint.health.show-details=always spring.rabbitmq.host=${RABBITMQ_HOST} From 423332bacba71f05cf40275639aba3e549942b46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Fri, 9 Aug 2024 14:19:10 +0900 Subject: [PATCH 176/197] =?UTF-8?q?feat:=20=ED=9A=8C=EC=9B=90=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20=EB=B3=80=EA=B2=BD=EC=8B=9C=20=EC=9D=B4=EB=A9=94?= =?UTF-8?q?=EC=9D=BC=20=EC=A4=91=EB=B3=B5=20=EA=B2=80=EC=82=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/edufocus/user/controller/UserController.java | 4 ++-- .../edufocus/user/model/repository/UserRepository.java | 4 ++-- .../edufocus/user/model/service/UserServiceImpl.java | 8 +++++++- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java index bb3818f..c4c2c7a 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java @@ -37,7 +37,7 @@ public class UserController { if (userService.isUserIdExist(requestJoinDto.getUserId())) return new ResponseEntity<>("아이디가 중복 됐습니다.", HttpStatus.CONFLICT); - if(userService.isEmailExist(requestJoinDto.getEmail())) + if (userService.isEmailExist(requestJoinDto.getEmail())) return new ResponseEntity<>("이메일이 중복 됐습니다.", HttpStatus.CONFLICT); userService.join(requestJoinDto); @@ -65,7 +65,7 @@ public class UserController { userService.changePassword(passwordDto, userId); return ResponseEntity.ok("Password changed successfully"); } catch (Exception e) { - return ResponseEntity.badRequest().body(e.getMessage()); + return ResponseEntity.status(HttpStatus.NOT_ACCEPTABLE).body(e.getMessage()); } } diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/repository/UserRepository.java b/backend/src/main/java/com/edufocus/edufocus/user/model/repository/UserRepository.java index 6aea378..c3d42e6 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/repository/UserRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/repository/UserRepository.java @@ -9,7 +9,7 @@ import org.springframework.data.repository.query.Param; import java.util.Optional; -public interface UserRepository extends JpaRepository { +public interface UserRepository extends JpaRepository { @Modifying @Transactional @Query("UPDATE User u SET u.refreshToken = :refreshToken WHERE u.id = :id") @@ -26,7 +26,7 @@ public interface UserRepository extends JpaRepository { @Transactional @Modifying @Query("UPDATE User u set u.password = :password where u.id= :id") - void updatePassword(@Param("id") Long id , @Param("password") String password); + void updatePassword(@Param("id") Long id, @Param("password") String password); Optional findByUserId(String userId); diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java index ac6a6d8..9b71b61 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java @@ -74,6 +74,12 @@ public class UserServiceImpl implements UserService { User user = userRepository.findById(id).orElseThrow(IllegalArgumentException::new); + + if (isEmailExist(infoDto.getEmail())) { + throw new IllegalArgumentException("이미 사용 중인 이메일입니다."); + + } + if (infoDto.getName() != null) user.setName(infoDto.getName()); @@ -159,7 +165,7 @@ public class UserServiceImpl implements UserService { } @Override - public boolean isTeacher(long userId){ + public boolean isTeacher(long userId) { return userRepository.findById(userId).orElseThrow(IllegalArgumentException::new).getRole() == UserRole.ADMIN; } } From 405e45b9d198742eff81a9fe28088e5849623585 Mon Sep 17 00:00:00 2001 From: yulmam <70622601+yulmam@users.noreply.github.com> Date: Fri, 9 Aug 2024 14:20:31 +0900 Subject: [PATCH 177/197] =?UTF-8?q?feat=20:=20timezone=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../board/entity/dto/ResponseBoardDetailDto.java | 5 +++-- .../board/entity/dto/ResponseBoardSummaryDto.java | 3 ++- .../board/entity/dto/ResponseCommentDto.java | 5 +++-- .../com/edufocus/edufocus/board/entity/vo/Board.java | 11 +++++++---- .../edufocus/edufocus/board/entity/vo/Comment.java | 12 +++++++----- .../report/entity/dto/ReportDetailResponseDto.java | 2 +- .../edufocus/report/entity/dto/ReportResponse.java | 2 +- .../report/entity/dto/ReportSetResponse.java | 3 ++- .../edufocus/edufocus/report/entity/vo/Report.java | 5 +++-- .../edufocus/report/entity/vo/ReportSet.java | 6 ++++-- 10 files changed, 33 insertions(+), 21 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardDetailDto.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardDetailDto.java index 7a6e8fe..c0e1f28 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardDetailDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardDetailDto.java @@ -6,6 +6,7 @@ import lombok.Getter; import lombok.Setter; import java.time.LocalDateTime; +import java.util.Date; @Builder @Getter @@ -17,6 +18,6 @@ public class ResponseBoardDetailDto { private String title; private String content; private boolean isMine; - private LocalDateTime createdAt; - private LocalDateTime modifiedAt; + private Date createdAt; + private Date modifiedAt; } diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardSummaryDto.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardSummaryDto.java index bcd1f11..0e50f01 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardSummaryDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseBoardSummaryDto.java @@ -6,6 +6,7 @@ import lombok.Getter; import lombok.Setter; import java.time.LocalDateTime; +import java.util.Date; @Builder @Getter @@ -14,5 +15,5 @@ public class ResponseBoardSummaryDto { private long id; private String name; private String title; - private LocalDateTime createdAt; + private Date createdAt; } diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseCommentDto.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseCommentDto.java index 2e0ec6e..ee99823 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseCommentDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/dto/ResponseCommentDto.java @@ -6,6 +6,7 @@ import lombok.Setter; import java.time.LocalDateTime; import java.time.LocalTime; +import java.util.Date; @Builder @Getter @@ -15,6 +16,6 @@ public class ResponseCommentDto { private String name; private String content; private boolean isMine; - private LocalDateTime createAt; - private LocalDateTime modifiedAt; + private Date createAt; + private Date modifiedAt; } diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java index bc05d56..f7ee473 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java @@ -15,6 +15,7 @@ import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; import java.time.LocalDateTime; +import java.util.Date; import java.util.List; @Entity @@ -42,13 +43,15 @@ public class Board { @Column(nullable = true) private int viewCount; - @Column(columnDefinition = "TIMESTAMP") + @Column @CreationTimestamp - LocalDateTime createdAt; + @Temporal(TemporalType.TIMESTAMP) + private Date createdAt; - @Column(columnDefinition = "TIMESTAMP") + @Column @UpdateTimestamp - LocalDateTime modifiedAt; + @Temporal(TemporalType.TIMESTAMP) + private Date modifiedAt; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java index 4928800..80bb200 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java @@ -15,6 +15,7 @@ import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; import java.time.LocalDateTime; +import java.util.Date; @Entity @Builder @@ -30,13 +31,14 @@ public class Comment { @Column(columnDefinition = "TEXT", nullable = false) private String content; - @Column(columnDefinition = "TIMESTAMP") + @Column @CreationTimestamp - private LocalDateTime createdAt; + @Temporal(TemporalType.TIMESTAMP) + private Date createdAt; - @Column(columnDefinition = "TIMESTAMP") - @UpdateTimestamp - private LocalDateTime modifiedAt; + @Column + @Temporal(TemporalType.TIMESTAMP) + private Date modifiedAt; @ManyToOne @JoinColumn(name = "user_id") diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportDetailResponseDto.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportDetailResponseDto.java index 6ef9d9c..6cd671f 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportDetailResponseDto.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportDetailResponseDto.java @@ -14,6 +14,6 @@ public class ReportDetailResponseDto { private int allCount; private String title; private int correctCount; - private LocalDateTime testAt; + private Date testAt; private List quizzes; } \ No newline at end of file diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportResponse.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportResponse.java index 0740a0b..9248eef 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportResponse.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportResponse.java @@ -16,5 +16,5 @@ public class ReportResponse { private String title; private int allCount; private int correctCount; - private LocalDateTime date; + private Date date; } diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportSetResponse.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportSetResponse.java index a7ea791..119a662 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportSetResponse.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/dto/ReportSetResponse.java @@ -4,6 +4,7 @@ package com.edufocus.edufocus.report.entity.dto; import lombok.*; import java.time.LocalDateTime; +import java.util.Date; import java.util.UUID; @Builder @@ -14,5 +15,5 @@ import java.util.UUID; public class ReportSetResponse { private UUID reportSetId; private String quizSetTitle; - private LocalDateTime testAt; + private Date testAt; } diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java index 32a5b5c..df47ac2 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java @@ -31,9 +31,10 @@ public class Report { private int correctCount; - @Column(columnDefinition = "TIMESTAMP") + @Column @CreationTimestamp - private LocalDateTime testAt; + @Temporal(TemporalType.TIMESTAMP) + private Date testAt; private Long lectureId; diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java index d263393..fb293ec 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java @@ -14,6 +14,7 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener; import java.time.LocalDateTime; +import java.util.Date; import java.util.List; import java.util.UUID; @@ -35,9 +36,10 @@ public class ReportSet { ) private UUID id; - @Column(columnDefinition = "TIMESTAMP") + @Column @CreationTimestamp - private LocalDateTime createAt; + @Temporal(TemporalType.TIMESTAMP) + private Date createAt; @OneToMany(mappedBy = "reportSet", cascade = CascadeType.REMOVE) private List reports; From 0d8f5bc8a6d022929e824a25775cb222624fb2fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Fri, 9 Aug 2024 14:28:43 +0900 Subject: [PATCH 178/197] =?UTF-8?q?feat:=20=EC=9C=A0=EC=A0=80=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/user/controller/UserController.java | 13 +++++++++---- .../user/model/service/UserServiceImpl.java | 4 ++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java index c4c2c7a..7fe36d3 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/controller/UserController.java @@ -47,12 +47,17 @@ public class UserController { @PutMapping("/updateinfo") public ResponseEntity updateUserInfo(@RequestBody InfoDto infoDto, HttpServletRequest request) { - String token = request.getHeader("Authorization"); - Long userId = Long.parseLong(jwtUtil.getUserId(token)); - userService.changeUserInfo(infoDto, userId); + try { + String token = request.getHeader("Authorization"); + Long userId = Long.parseLong(jwtUtil.getUserId(token)); + + userService.changeUserInfo(infoDto, userId); + return ResponseEntity.ok("Password changed successfully"); + } catch (Exception e) { + return ResponseEntity.status(HttpStatus.NOT_ACCEPTABLE).body(e.getMessage()); + } - return new ResponseEntity<>(HttpStatus.OK); } // 비밀번호 변경 diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java index 9b71b61..310a2e6 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java @@ -72,11 +72,11 @@ public class UserServiceImpl implements UserService { @Override public void changeUserInfo(InfoDto infoDto, Long id) { - User user = userRepository.findById(id).orElseThrow(IllegalArgumentException::new); + User user = userRepository.findById(id).orElse(null); if (isEmailExist(infoDto.getEmail())) { - throw new IllegalArgumentException("이미 사용 중인 이메일입니다."); + throw new RuntimeException("이미 사용 중인 이메일입니다."); } From 3e509fa9eb2398cebca699c167dbd48d522f3392 Mon Sep 17 00:00:00 2001 From: yulmam <70622601+yulmam@users.noreply.github.com> Date: Fri, 9 Aug 2024 14:45:27 +0900 Subject: [PATCH 179/197] =?UTF-8?q?feat=20:=20=EC=B1=84=EC=A0=90=EC=8B=9C?= =?UTF-8?q?=20=EB=8C=80=EC=86=8C=EB=AC=B8=EC=9E=90=20=EC=B2=B4=ED=81=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/edufocus/edufocus/report/service/ReportServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java index 33d0a71..5f857da 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/service/ReportServiceImpl.java @@ -56,7 +56,7 @@ public class ReportServiceImpl implements ReportService { String inputAnswer = answerInputList.get(idx); boolean isCorrect; Answer answer; - if (quiz.getAnswer().equals(inputAnswer)) { + if (quiz.getAnswer().equalsIgnoreCase(inputAnswer)) { correctCount++; isCorrect = true; } else { From f628bbbd00e166fe9fea6633c194a4be3e371447 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Fri, 9 Aug 2024 15:17:28 +0900 Subject: [PATCH 180/197] =?UTF-8?q?feat:=20on=20delete=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/edufocus/edufocus/qna/entity/Qna.java | 4 ++++ .../com/edufocus/edufocus/report/entity/vo/Report.java | 7 +++++-- .../edufocus/edufocus/report/entity/vo/ReportSet.java | 9 ++++----- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java b/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java index af797ee..15ea83a 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java @@ -4,6 +4,8 @@ import com.edufocus.edufocus.lecture.entity.Lecture; import com.edufocus.edufocus.user.model.entity.vo.User; import jakarta.persistence.*; import lombok.*; +import org.hibernate.annotations.OnDelete; +import org.hibernate.annotations.OnDeleteAction; import java.util.Date; @@ -13,6 +15,8 @@ import java.util.Date; @Builder @NoArgsConstructor @AllArgsConstructor + +@OnDelete(action = OnDeleteAction.CASCADE) public class Qna { // 연관관계 주인 diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java index df47ac2..0ac149b 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java @@ -7,6 +7,8 @@ import com.fasterxml.jackson.annotation.JsonAutoDetect; import jakarta.persistence.*; import lombok.*; import org.hibernate.annotations.CreationTimestamp; +import org.hibernate.annotations.OnDelete; +import org.hibernate.annotations.OnDeleteAction; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; @@ -22,6 +24,7 @@ import java.util.List; @Builder @EntityListeners(AuditingEntityListener.class) @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) +@OnDelete(action = OnDeleteAction.CASCADE) public class Report { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -50,10 +53,10 @@ public class Report { @JoinColumn(name = "reportset_id") private ReportSet reportSet; - @OneToMany(mappedBy = "report", cascade = CascadeType.REMOVE) + @OneToMany(mappedBy = "report", cascade = CascadeType.REMOVE) private List answers; - public ReportResponse makeReportResponse(){ + public ReportResponse makeReportResponse() { return ReportResponse.builder() .reportId(id) .name(user.getName()) diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java index fb293ec..1fd87e1 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java @@ -5,10 +5,9 @@ import com.edufocus.edufocus.quiz.entity.QuizSet; import com.edufocus.edufocus.report.entity.dto.ReportSetResponse; import com.fasterxml.jackson.annotation.JsonAutoDetect; import jakarta.persistence.*; +import jakarta.persistence.CascadeType; import lombok.*; -import org.hibernate.annotations.ColumnDefault; -import org.hibernate.annotations.CreationTimestamp; -import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.*; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; @@ -19,7 +18,6 @@ import java.util.List; import java.util.UUID; - @Entity @Getter @Builder @@ -27,6 +25,7 @@ import java.util.UUID; @AllArgsConstructor @EntityListeners(AuditingEntityListener.class) @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) +@OnDelete(action = OnDeleteAction.CASCADE) public class ReportSet { @Id @GeneratedValue(generator = "UUID") @@ -60,7 +59,7 @@ public class ReportSet { .build(); } - public long findUserId(){ + public long findUserId() { return lecture.getUser().getId(); } } From 67153ca7863e0f8bf1e3c074804fcf155d0af090 Mon Sep 17 00:00:00 2001 From: yulmam <70622601+yulmam@users.noreply.github.com> Date: Fri, 9 Aug 2024 15:18:52 +0900 Subject: [PATCH 181/197] =?UTF-8?q?feat=20:=20cascade=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/edufocus/edufocus/board/entity/vo/Board.java | 4 +++- .../com/edufocus/edufocus/report/entity/vo/ReportSet.java | 6 +++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java index f7ee473..2cca933 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java @@ -9,6 +9,8 @@ import com.fasterxml.jackson.annotation.JsonAutoDetect; import jakarta.persistence.*; import lombok.*; import org.hibernate.annotations.CreationTimestamp; +import org.hibernate.annotations.OnDelete; +import org.hibernate.annotations.OnDeleteAction; import org.hibernate.annotations.UpdateTimestamp; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; @@ -59,9 +61,9 @@ public class Board { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "lecture_id") + @OnDelete(action = OnDeleteAction.CASCADE) private Lecture lecture; - @OneToMany(mappedBy = "board", cascade = CascadeType.ALL) private List comments; diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java index fb293ec..ab10529 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java @@ -5,10 +5,9 @@ import com.edufocus.edufocus.quiz.entity.QuizSet; import com.edufocus.edufocus.report.entity.dto.ReportSetResponse; import com.fasterxml.jackson.annotation.JsonAutoDetect; import jakarta.persistence.*; +import jakarta.persistence.CascadeType; import lombok.*; -import org.hibernate.annotations.ColumnDefault; -import org.hibernate.annotations.CreationTimestamp; -import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.*; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; @@ -46,6 +45,7 @@ public class ReportSet { @ManyToOne @JoinColumn(name = "lecture_id") + @OnDelete(action = OnDeleteAction.CASCADE) private Lecture lecture; @ManyToOne From 00680262a44d8ba84103cef4c0774a6938493dea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Fri, 9 Aug 2024 15:27:51 +0900 Subject: [PATCH 182/197] =?UTF-8?q?feat:=20ondelete=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java | 2 +- .../java/com/edufocus/edufocus/report/entity/vo/Report.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java b/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java index 15ea83a..2325ae2 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java @@ -16,7 +16,7 @@ import java.util.Date; @NoArgsConstructor @AllArgsConstructor -@OnDelete(action = OnDeleteAction.CASCADE) + public class Qna { // 연관관계 주인 diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java index 0ac149b..6e5d89a 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java @@ -24,7 +24,6 @@ import java.util.List; @Builder @EntityListeners(AuditingEntityListener.class) @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) -@OnDelete(action = OnDeleteAction.CASCADE) public class Report { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) From 4cc6cec8f8f3bdcf4feff132fe71b96d5a84b1e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Fri, 9 Aug 2024 15:35:02 +0900 Subject: [PATCH 183/197] =?UTF-8?q?feat:=20casacade=20=EC=B6=94=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java | 1 + .../java/com/edufocus/edufocus/report/entity/vo/ReportSet.java | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java b/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java index 2325ae2..6216f88 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/entity/Qna.java @@ -54,6 +54,7 @@ public class Qna { @ManyToOne @JoinColumn(name = "lecture_id") + @OnDelete(action = OnDeleteAction.CASCADE) private Lecture lecture; private boolean isMine; diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java index 1fd87e1..b0a245b 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java @@ -25,7 +25,6 @@ import java.util.UUID; @AllArgsConstructor @EntityListeners(AuditingEntityListener.class) @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) -@OnDelete(action = OnDeleteAction.CASCADE) public class ReportSet { @Id @GeneratedValue(generator = "UUID") From 1aaeac38fede8ed78b88dabfd10d89c744dc6d8f Mon Sep 17 00:00:00 2001 From: kgc91747 Date: Fri, 9 Aug 2024 15:53:42 +0900 Subject: [PATCH 184/197] =?UTF-8?q?feat:=20registration=20cascade=20?= =?UTF-8?q?=EC=98=B5=EC=85=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/edufocus/registration/entity/Registration.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/entity/Registration.java b/backend/src/main/java/com/edufocus/edufocus/registration/entity/Registration.java index c5d302a..1d2870d 100644 --- a/backend/src/main/java/com/edufocus/edufocus/registration/entity/Registration.java +++ b/backend/src/main/java/com/edufocus/edufocus/registration/entity/Registration.java @@ -22,11 +22,11 @@ public class Registration { @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; - @ManyToOne + @ManyToOne(cascade = CascadeType.ALL) @JoinColumn(name = "user_id") private User user; - @ManyToOne + @ManyToOne(cascade = CascadeType.ALL) @JoinColumn(name = "lecture_id") private Lecture lecture; From 4d479d702e914ffdaf376d466669424a45aaf6a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Fri, 9 Aug 2024 16:35:18 +0900 Subject: [PATCH 185/197] =?UTF-8?q?feat:=20cascade=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/edufocus/edufocus/board/entity/vo/Board.java | 6 +++--- .../edufocus/edufocus/board/entity/vo/Comment.java | 3 +++ .../edufocus/registration/entity/Registration.java | 11 +++++++---- backend/src/main/resources/application.properties | 2 +- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java index 2cca933..17274f4 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Board.java @@ -64,10 +64,10 @@ public class Board { @OnDelete(action = OnDeleteAction.CASCADE) private Lecture lecture; - @OneToMany(mappedBy = "board", cascade = CascadeType.ALL) + @OneToMany(mappedBy = "board") private List comments; - public ResponseBoardSummaryDto makeSummaryDto(){ + public ResponseBoardSummaryDto makeSummaryDto() { return ResponseBoardSummaryDto.builder() .id(id) .title(title) @@ -76,7 +76,7 @@ public class Board { .build(); } - public ResponseBoardDetailDto makeDetailDto(long userId){ + public ResponseBoardDetailDto makeDetailDto(long userId) { return ResponseBoardDetailDto.builder() .id(id) .name(user.getName()) diff --git a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java index 80bb200..3a44c96 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/entity/vo/Comment.java @@ -10,6 +10,8 @@ import lombok.Builder; import lombok.NoArgsConstructor; import lombok.Setter; import org.hibernate.annotations.CreationTimestamp; +import org.hibernate.annotations.OnDelete; +import org.hibernate.annotations.OnDeleteAction; import org.hibernate.annotations.UpdateTimestamp; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; @@ -46,6 +48,7 @@ public class Comment { @ManyToOne @JoinColumn(name = "board_id") + @OnDelete(action = OnDeleteAction.CASCADE) Board board; public ResponseCommentDto makeCommentDto(long userId) { diff --git a/backend/src/main/java/com/edufocus/edufocus/registration/entity/Registration.java b/backend/src/main/java/com/edufocus/edufocus/registration/entity/Registration.java index 1d2870d..ee0d3e7 100644 --- a/backend/src/main/java/com/edufocus/edufocus/registration/entity/Registration.java +++ b/backend/src/main/java/com/edufocus/edufocus/registration/entity/Registration.java @@ -7,6 +7,8 @@ import com.edufocus.edufocus.report.entity.vo.ReportSet; import com.edufocus.edufocus.user.model.entity.vo.User; import jakarta.persistence.*; import lombok.*; +import org.hibernate.annotations.OnDelete; +import org.hibernate.annotations.OnDeleteAction; import java.util.UUID; @@ -22,22 +24,23 @@ public class Registration { @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; - @ManyToOne(cascade = CascadeType.ALL) + @ManyToOne @JoinColumn(name = "user_id") private User user; - @ManyToOne(cascade = CascadeType.ALL) + @ManyToOne + @OnDelete(action = OnDeleteAction.CASCADE) @JoinColumn(name = "lecture_id") private Lecture lecture; @Enumerated(EnumType.STRING) private RegistrationStatus status; - public boolean isAccepted(){ + public boolean isAccepted() { return status == RegistrationStatus.ACCEPTED; } - public Report makeReport(ReportSet reportSet, QuizSet quizSet, long lectureId){ + public Report makeReport(ReportSet reportSet, QuizSet quizSet, long lectureId) { return Report.builder() .allCount(0) .correctCount(-1) diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 943e868..dd85ef5 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -21,7 +21,7 @@ spring.datasource.username=${USER_NAME} spring.datasource.password=${USER_PASSWORD} spring.mvc.pathmatch.matching-strategy=ant_path_matcher spring.jpa.database=mysql -spring.jpa.hibernate.ddl-auto=update +spring.jpa.hibernate.ddl-auto=create spring.jpa.show-sql=true spring.jpa.properties.hibernate.jdbc.time_zone=Asia/Seoul management.endpoints.web.exposure.include=health,info From d1e7f6d581708a28e751c8bed444acedf10d95eb Mon Sep 17 00:00:00 2001 From: yulmam <70622601+yulmam@users.noreply.github.com> Date: Fri, 9 Aug 2024 16:42:58 +0900 Subject: [PATCH 186/197] =?UTF-8?q?feat=20:=20cascade=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/edufocus/edufocus/report/entity/vo/Answer.java | 8 ++++++++ .../com/edufocus/edufocus/report/entity/vo/Report.java | 4 +++- .../com/edufocus/edufocus/report/entity/vo/ReportSet.java | 3 ++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Answer.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Answer.java index 53d0d35..969119a 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Answer.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Answer.java @@ -4,6 +4,8 @@ package com.edufocus.edufocus.report.entity.vo; import com.edufocus.edufocus.quiz.entity.Quiz; import jakarta.persistence.*; import lombok.*; +import org.hibernate.annotations.OnDelete; +import org.hibernate.annotations.OnDeleteAction; @Entity @Getter @@ -17,15 +19,21 @@ public class Answer { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; + + @Column private String userAnswer; + + @Column private boolean isCorrect; @ManyToOne @JoinColumn(name = "report_id") + @OnDelete(action = OnDeleteAction.CASCADE) private Report report; @ManyToOne @JoinColumn(name = "quiz_id") + @OnDelete(action = OnDeleteAction.CASCADE) private Quiz quiz; } diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java index 6e5d89a..9bb0440 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/Report.java @@ -46,13 +46,15 @@ public class Report { @ManyToOne @JoinColumn(name = "quizset_id") + @OnDelete(action = OnDeleteAction.CASCADE) private QuizSet quizSet; @ManyToOne @JoinColumn(name = "reportset_id") + @OnDelete(action = OnDeleteAction.CASCADE) private ReportSet reportSet; - @OneToMany(mappedBy = "report", cascade = CascadeType.REMOVE) + @OneToMany(mappedBy = "report") private List answers; public ReportResponse makeReportResponse() { diff --git a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java index c23547c..f5beca6 100644 --- a/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java +++ b/backend/src/main/java/com/edufocus/edufocus/report/entity/vo/ReportSet.java @@ -39,7 +39,7 @@ public class ReportSet { @Temporal(TemporalType.TIMESTAMP) private Date createAt; - @OneToMany(mappedBy = "reportSet", cascade = CascadeType.REMOVE) + @OneToMany(mappedBy = "reportSet") private List reports; @ManyToOne @@ -49,6 +49,7 @@ public class ReportSet { @ManyToOne @JoinColumn(name = "quizSet_id") + @OnDelete(action = OnDeleteAction.CASCADE) private QuizSet quizSet; public ReportSetResponse makeReportSetResponse() { From 6be1db104aa06e7dd9d71040a96b2c74fd8719fd Mon Sep 17 00:00:00 2001 From: kgc91747 Date: Fri, 9 Aug 2024 17:11:43 +0900 Subject: [PATCH 187/197] =?UTF-8?q?feat:=20quiz=20=EB=B9=88=20=ED=80=B4?= =?UTF-8?q?=EC=A6=88=EC=85=8B=20=EB=93=B1=EB=A1=9D=20=EC=9A=94=EC=B2=AD?= =?UTF-8?q?=EC=8B=9C=20=EA=B1=B0=EC=A0=88=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/edufocus/edufocus/quiz/controller/QuizController.java | 4 ++++ backend/src/main/resources/application.properties | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java b/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java index c95b595..b1e3fe5 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java @@ -34,6 +34,10 @@ public class QuizController { , @RequestPart(value = "images", required = false) List images) throws IOException { long userId = Long.parseLong(jwtUtil.getUserId(accessToken)); + if (quizSetCreateRequest.getQuizzes().isEmpty()) { + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } + QuizSet quizSet = quizSetService.createQuizSet(userId, quizSetCreateRequest.getTitle()); int imageIdx = 0; diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index dd85ef5..943e868 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -21,7 +21,7 @@ spring.datasource.username=${USER_NAME} spring.datasource.password=${USER_PASSWORD} spring.mvc.pathmatch.matching-strategy=ant_path_matcher spring.jpa.database=mysql -spring.jpa.hibernate.ddl-auto=create +spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true spring.jpa.properties.hibernate.jdbc.time_zone=Asia/Seoul management.endpoints.web.exposure.include=health,info From 879748d985684ebc7c9ef8eca8b11b238eaf12d6 Mon Sep 17 00:00:00 2001 From: yulmam <70622601+yulmam@users.noreply.github.com> Date: Fri, 9 Aug 2024 17:58:23 +0900 Subject: [PATCH 188/197] =?UTF-8?q?feat=20:=20lecture=20=EC=97=AD=EC=A0=95?= =?UTF-8?q?=EB=A0=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lecture/repository/LectureRepository.java | 2 +- .../lecture/service/LectureServiceImpl.java | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/repository/LectureRepository.java b/backend/src/main/java/com/edufocus/edufocus/lecture/repository/LectureRepository.java index eb708fd..34edc2a 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/repository/LectureRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/repository/LectureRepository.java @@ -14,7 +14,7 @@ public interface LectureRepository extends JpaRepository { List findAllByUserId(Long userId); - List findLecturesByUserId(Long userId); + List findLecturesByUserIdOrderById(Long userId); Lecture findByIdAndUserId(long id, long userId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java index c434f54..acddb48 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java @@ -11,6 +11,7 @@ import com.edufocus.edufocus.user.model.entity.vo.UserRole; import com.edufocus.edufocus.user.model.repository.UserRepository; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; @@ -118,7 +119,7 @@ public class LectureServiceImpl implements LectureService { @Override public List findAllLecture() { - List lectureList = lectureRepository.findAll(); + List lectureList = lectureRepository.findAll(Sort.by(Sort.Direction.DESC, "id")); List lectureSearchResponseList = new ArrayList<>(); for (Lecture lecture : lectureList) { @@ -190,7 +191,7 @@ public class LectureServiceImpl implements LectureService { List myLectureList = new ArrayList<>(); if (user.getRole() == UserRole.ADMIN) { - List lectureList = lectureRepository.findLecturesByUserId(userId); + List lectureList = lectureRepository.findLecturesByUserIdOrderById(userId); for (Lecture lecture : lectureList) { LectureSearchResponse lectureSearchResponse = LectureSearchResponse.builder() .id(lecture.getId()) @@ -214,6 +215,18 @@ public class LectureServiceImpl implements LectureService { myLectureList.add(lectureSearchResponse); } } + Collections.sort(myLectureList, new Comparator() { + @Override + public int compare(LectureSearchResponse lsr1, LectureSearchResponse lsr2) { + long lsr1Id = lsr1.getId(); + long lsr2Id = lsr2.getId(); + if(lsr2Id > lsr1Id) + return 1; + else if(lsr2Id == lsr1Id) + return 0; + return -1; + } + }); } return myLectureList; From a80fb528f6d0d3204a0586d2659a3e1cbb864745 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Mon, 12 Aug 2024 09:21:49 +0900 Subject: [PATCH 189/197] =?UTF-8?q?feat:=20qna=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=EB=84=A4=EC=9D=B4=EC=85=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/edufocus/edufocus/qna/repository/QnaRepository.java | 4 ++-- backend/src/main/resources/application.properties | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/repository/QnaRepository.java b/backend/src/main/java/com/edufocus/edufocus/qna/repository/QnaRepository.java index 19ebbcd..52ec462 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/repository/QnaRepository.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/repository/QnaRepository.java @@ -13,8 +13,8 @@ import java.util.List; @Repository public interface QnaRepository extends JpaRepository { - List findByLectureId(Long lecturerId); - + //List findByLectureId(Long lecturerId); + @Query("SELECT q FROM Qna q WHERE q.lecture.id = :lectureId ORDER BY q.createdAt DESC") Page findByLectureId(Long lectureId, Pageable pageable); } diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index dd85ef5..943e868 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -21,7 +21,7 @@ spring.datasource.username=${USER_NAME} spring.datasource.password=${USER_PASSWORD} spring.mvc.pathmatch.matching-strategy=ant_path_matcher spring.jpa.database=mysql -spring.jpa.hibernate.ddl-auto=create +spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true spring.jpa.properties.hibernate.jdbc.time_zone=Asia/Seoul management.endpoints.web.exposure.include=health,info From d4bd637abdf929d4b83efc9844277f232cda8560 Mon Sep 17 00:00:00 2001 From: kgc91747 Date: Mon, 12 Aug 2024 09:29:25 +0900 Subject: [PATCH 190/197] =?UTF-8?q?feat:=20board=20=EC=A0=84=EC=B2=B4?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EA=B2=B0=EA=B3=BC=EA=B0=80=20=EC=97=86?= =?UTF-8?q?=EB=8A=94=20=EA=B2=BD=EC=9A=B0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/edufocus/board/controller/BoardController.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java b/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java index 87e5410..da43e88 100644 --- a/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java +++ b/backend/src/main/java/com/edufocus/edufocus/board/controller/BoardController.java @@ -37,9 +37,6 @@ public class BoardController { ){ List boardSummaries = boardService.findBoards(pageNo, category, lectureId); - if(boardSummaries.isEmpty()) - return new ResponseEntity<>(boardSummaries, HttpStatus.NO_CONTENT); - return new ResponseEntity<>(boardSummaries, HttpStatus.OK); } From 7fe5ec3b2bf932124d68488676a978316c12f81b Mon Sep 17 00:00:00 2001 From: kgc91747 Date: Mon, 12 Aug 2024 09:43:48 +0900 Subject: [PATCH 191/197] =?UTF-8?q?feat:=20lecture=20=EA=B0=95=EC=9D=98=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=EC=8B=9C=20=EC=A0=80=EC=9E=A5=EC=86=8C?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EC=82=AC=EC=A7=84=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/lecture/service/LectureServiceImpl.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java index acddb48..1a3a572 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/service/LectureServiceImpl.java @@ -113,6 +113,12 @@ public class LectureServiceImpl implements LectureService { return false; } + String image = lecture.getImage(); + if (image != null) { + File file = new File(lecture.getImage()); + file.delete(); + } + lectureRepository.deleteById(lectureId); return true; } @@ -220,9 +226,9 @@ public class LectureServiceImpl implements LectureService { public int compare(LectureSearchResponse lsr1, LectureSearchResponse lsr2) { long lsr1Id = lsr1.getId(); long lsr2Id = lsr2.getId(); - if(lsr2Id > lsr1Id) + if (lsr2Id > lsr1Id) return 1; - else if(lsr2Id == lsr1Id) + else if (lsr2Id == lsr1Id) return 0; return -1; } From 064881b8518ad74685cb7804f041f1d70cb5787f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Mon, 12 Aug 2024 09:49:15 +0900 Subject: [PATCH 192/197] =?UTF-8?q?feat:=20qna=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=EB=84=A4=EC=9D=B4=EC=85=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/qna/controller/QnaController.java | 10 ++++------ .../com/edufocus/edufocus/qna/service/QnaService.java | 2 +- .../edufocus/edufocus/qna/service/QnaServiceImpl.java | 9 +++------ 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java b/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java index 3235b2c..dbc8c5b 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java @@ -144,16 +144,14 @@ public class QnaController { } @GetMapping("/all/{id}") - public ResponseEntity> getAllQna(@PathVariable Long id) { + public ResponseEntity> getAllQna( + @PathVariable Long id, + @RequestParam(defaultValue = "0") int page) { try { - - - List qnaList = qnaService.getAllQnasByLecture(id, PAGE_SIZE); - + List qnaList = qnaService.getAllQnasByLecture(id, page, PAGE_SIZE); return new ResponseEntity<>(qnaList, HttpStatus.ACCEPTED); } catch (SQLException e) { return new ResponseEntity<>(HttpStatus.NOT_ACCEPTABLE); - } } } diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaService.java b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaService.java index 877d4ef..c8468aa 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaService.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaService.java @@ -22,7 +22,7 @@ public interface QnaService { QnaResponseDto getQna(Long id, Long userId) throws SQLException; - List getAllQnasByLecture(Long lectureId, int pageNumber) throws SQLException; + List getAllQnasByLecture(Long lectureId, int page, int pageNumber) throws SQLException; QnaResponseDto createAnswer(Long id, QnaRequestDto qnaRequestDto) throws SQLException; diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java index bad6f09..b2b346a 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java @@ -120,19 +120,16 @@ public class QnaServiceImpl implements QnaService { } @Override - public List getAllQnasByLecture(Long lectureId, int pageSize) { - - Pageable pageable = PageRequest.of(0, pageSize); - + public List getAllQnasByLecture(Long lectureId, int page, int pageSize) { + Pageable pageable = PageRequest.of(page, pageSize); Page qnaPage = qnaRepository.findByLectureId(lectureId, pageable); - return qnaPage.getContent().stream() .map(QnaResponseDto::toEntity) .collect(Collectors.toList()); - } + @Override public QnaResponseDto createAnswer(Long id, QnaRequestDto qnaRequestDto) throws SQLException { From e37088c7ee366bb75e3ac63d4d59155f871378ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A0=95=EB=AF=BC?= Date: Mon, 12 Aug 2024 09:54:06 +0900 Subject: [PATCH 193/197] =?UTF-8?q?feat:=20qna=20page=EB=B3=80=EC=88=98=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/edufocus/edufocus/qna/controller/QnaController.java | 4 ++-- .../java/com/edufocus/edufocus/qna/service/QnaService.java | 2 +- .../com/edufocus/edufocus/qna/service/QnaServiceImpl.java | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java b/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java index dbc8c5b..7fafb44 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/controller/QnaController.java @@ -146,9 +146,9 @@ public class QnaController { @GetMapping("/all/{id}") public ResponseEntity> getAllQna( @PathVariable Long id, - @RequestParam(defaultValue = "0") int page) { + @RequestParam(defaultValue = "0") int pageNo) { try { - List qnaList = qnaService.getAllQnasByLecture(id, page, PAGE_SIZE); + List qnaList = qnaService.getAllQnasByLecture(id, pageNo, PAGE_SIZE); return new ResponseEntity<>(qnaList, HttpStatus.ACCEPTED); } catch (SQLException e) { return new ResponseEntity<>(HttpStatus.NOT_ACCEPTABLE); diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaService.java b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaService.java index c8468aa..6308a95 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaService.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaService.java @@ -22,7 +22,7 @@ public interface QnaService { QnaResponseDto getQna(Long id, Long userId) throws SQLException; - List getAllQnasByLecture(Long lectureId, int page, int pageNumber) throws SQLException; + List getAllQnasByLecture(Long lectureId, int pageNo, int pageNumber) throws SQLException; QnaResponseDto createAnswer(Long id, QnaRequestDto qnaRequestDto) throws SQLException; diff --git a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java index b2b346a..a60b3d9 100644 --- a/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/qna/service/QnaServiceImpl.java @@ -120,8 +120,8 @@ public class QnaServiceImpl implements QnaService { } @Override - public List getAllQnasByLecture(Long lectureId, int page, int pageSize) { - Pageable pageable = PageRequest.of(page, pageSize); + public List getAllQnasByLecture(Long lectureId, int pageNo, int pageSize) { + Pageable pageable = PageRequest.of(pageNo, pageSize); Page qnaPage = qnaRepository.findByLectureId(lectureId, pageable); return qnaPage.getContent().stream() From 148b6c6db02d456f2773284da5451ee35fff9e15 Mon Sep 17 00:00:00 2001 From: kgc91747 Date: Mon, 12 Aug 2024 10:10:33 +0900 Subject: [PATCH 194/197] =?UTF-8?q?feat:=20=ED=80=B4=EC=A6=88=20=EC=8B=9C?= =?UTF-8?q?=EC=9E=91=EC=9D=B4=ED=9B=84=20=20=ED=95=B4=EB=8B=B9=20=ED=80=B4?= =?UTF-8?q?=EC=A6=88=20=EB=B3=80=EA=B2=BD=20=EB=B6=88=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/quiz/service/QuizSetService.java | 2 +- .../edufocus/quiz/service/QuizSetServiceImpl.java | 10 ++-------- .../edufocus/ws/controller/ChatController.java | 12 ++++++++---- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetService.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetService.java index 97e75d2..8a610cc 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetService.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetService.java @@ -22,5 +22,5 @@ public interface QuizSetService { List findMyQuizSetResponses(long userId); - void updateQuizSetTested(long quizSetId, long userId, boolean tested); + void updateQuizSetTested(long quizSetId); } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java index a636f0c..07b68a3 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/service/QuizSetServiceImpl.java @@ -99,15 +99,9 @@ public class QuizSetServiceImpl implements QuizSetService { } @Override - public void updateQuizSetTested(long quizSetId, long userId, boolean tested) { + public void updateQuizSetTested(long quizSetId) { QuizSet quizSet = quizSetRepository.findById(quizSetId).orElseThrow(NoSuchElementException::new); - - User user = userRepository.findById(userId).orElseThrow(NoSuchElementException::new); - - if (quizSet.getUser().getId() != user.getId()) { - throw new UnAuthorizedException(); - } - + quizSet.setTested(true); quizSetRepository.save(quizSet); } diff --git a/backend/src/main/java/com/edufocus/edufocus/ws/controller/ChatController.java b/backend/src/main/java/com/edufocus/edufocus/ws/controller/ChatController.java index 4e280b9..6f149f0 100644 --- a/backend/src/main/java/com/edufocus/edufocus/ws/controller/ChatController.java +++ b/backend/src/main/java/com/edufocus/edufocus/ws/controller/ChatController.java @@ -2,6 +2,7 @@ package com.edufocus.edufocus.ws.controller; import com.edufocus.edufocus.global.constant.RabbitMQConstant; +import com.edufocus.edufocus.quiz.service.QuizSetService; import com.edufocus.edufocus.report.service.ReportService; import com.edufocus.edufocus.ws.entity.dto.MessageDto; import com.edufocus.edufocus.ws.entity.dto.QuizDto; @@ -17,22 +18,25 @@ public class ChatController { RabbitTemplate rabbitTemplate; ReportService reportService; + QuizSetService quizSetService; - public ChatController(RabbitTemplate rabbitTemplate, ReportService reportService){ + public ChatController(RabbitTemplate rabbitTemplate, ReportService reportService, QuizSetService quizSetService) { this.rabbitTemplate = rabbitTemplate; this.reportService = reportService; + this.quizSetService = quizSetService; } @MessageMapping("chat.message.{lectureId}") - public void sendMessage(@DestinationVariable long lectureId, MessageDto messageDto){ - rabbitTemplate.convertAndSend(RabbitMQConstant.CHAT_EXCHANGE.getConstant(), + public void sendMessage(@DestinationVariable long lectureId, MessageDto messageDto) { + rabbitTemplate.convertAndSend(RabbitMQConstant.CHAT_EXCHANGE.getConstant(), RabbitMQConstant.ROUTING_KEY_PREFIX.getConstant() + lectureId, messageDto); } @MessageMapping("chat.quiz.{lectureId}") - public void quizStart(@DestinationVariable long lectureId, QuizDto quizDto){ + public void quizStart(@DestinationVariable long lectureId, QuizDto quizDto) { UUID reportSetId = reportService.initReportSet(lectureId, quizDto.getQuizSetId()); + quizSetService.updateQuizSetTested(quizDto.getQuizSetId()); quizDto.setReportSetId(reportSetId); From a0b363d74f8147886730f69d3ee5ab90ae8d3aef Mon Sep 17 00:00:00 2001 From: kgc91747 Date: Mon, 12 Aug 2024 13:40:18 +0900 Subject: [PATCH 195/197] =?UTF-8?q?feat:=20quiz,=20lecture=20=EC=9D=B4?= =?UTF-8?q?=EB=AF=B8=EC=A7=80=20=EB=93=B1=EB=A1=9D=EC=8B=9C=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=ED=98=95=EC=8B=9D=20=ED=99=95=EC=9D=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lecture/controller/LectureController.java | 4 ++++ .../edufocus/quiz/controller/QuizController.java | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java b/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java index 7ad29a6..dfe142c 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java @@ -36,6 +36,10 @@ public class LectureController { return new ResponseEntity<>(HttpStatus.CONFLICT); } + if (!image.isEmpty() && !image.getContentType().startsWith("image")) { + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } + lectureService.createLecture(userId, lectureCreateRequest, image); return new ResponseEntity<>(HttpStatus.CREATED); diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java b/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java index b1e3fe5..4a874c9 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java @@ -38,6 +38,12 @@ public class QuizController { return new ResponseEntity<>(HttpStatus.BAD_REQUEST); } + for (MultipartFile image : images) { + if (!image.isEmpty() && !image.getContentType().startsWith("image")) { + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } + } + QuizSet quizSet = quizSetService.createQuizSet(userId, quizSetCreateRequest.getTitle()); int imageIdx = 0; @@ -81,6 +87,12 @@ public class QuizController { return new ResponseEntity<>(HttpStatus.CONFLICT); } + for (MultipartFile image : images) { + if (!image.isEmpty() && !image.getContentType().startsWith("image")) { + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } + } + quizSetService.updateQuizSet(quizSetUpdateRequest.getId(), quizSetUpdateRequest.getTitle()); Map quizUpdatedCheckMap = new HashMap<>(); From 4cd713f580927f0d54f869645538c6b449b4ad5f Mon Sep 17 00:00:00 2001 From: kgc91747 Date: Mon, 12 Aug 2024 15:26:04 +0900 Subject: [PATCH 196/197] =?UTF-8?q?feat:=20lecture,=20quiz=20=EC=9D=B4?= =?UTF-8?q?=EB=AF=B8=EC=A7=80=20=EB=AF=B8=ED=8F=AC=ED=95=A8=20=EB=93=B1?= =?UTF-8?q?=EB=A1=9D=20=EB=B6=88=EA=B0=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/lecture/controller/LectureController.java | 2 +- .../com/edufocus/edufocus/quiz/controller/QuizController.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java b/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java index dfe142c..3b15967 100644 --- a/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java +++ b/backend/src/main/java/com/edufocus/edufocus/lecture/controller/LectureController.java @@ -36,7 +36,7 @@ public class LectureController { return new ResponseEntity<>(HttpStatus.CONFLICT); } - if (!image.isEmpty() && !image.getContentType().startsWith("image")) { + if (image != null && !image.getContentType().startsWith("image")) { return new ResponseEntity<>(HttpStatus.BAD_REQUEST); } diff --git a/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java b/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java index 4a874c9..c9b2dbb 100644 --- a/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java +++ b/backend/src/main/java/com/edufocus/edufocus/quiz/controller/QuizController.java @@ -39,7 +39,7 @@ public class QuizController { } for (MultipartFile image : images) { - if (!image.isEmpty() && !image.getContentType().startsWith("image")) { + if (image != null && !image.getContentType().startsWith("image")) { return new ResponseEntity<>(HttpStatus.BAD_REQUEST); } } @@ -88,7 +88,7 @@ public class QuizController { } for (MultipartFile image : images) { - if (!image.isEmpty() && !image.getContentType().startsWith("image")) { + if (image != null && !image.getContentType().startsWith("image")) { return new ResponseEntity<>(HttpStatus.BAD_REQUEST); } } From 66ef65e4d50cf8afab5263c6f3f5e767dcaef62e Mon Sep 17 00:00:00 2001 From: kgc91747 Date: Tue, 13 Aug 2024 12:25:45 +0900 Subject: [PATCH 197/197] =?UTF-8?q?feat:=20user=20=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EC=88=98=EC=A0=95=20=EC=8B=9C=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=EB=A7=8C=20=EB=B3=80=EA=B2=BD=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edufocus/user/model/service/UserServiceImpl.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java index 310a2e6..516fc16 100644 --- a/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java +++ b/backend/src/main/java/com/edufocus/edufocus/user/model/service/UserServiceImpl.java @@ -13,6 +13,7 @@ import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import java.util.NoSuchElementException; import java.util.Optional; @Service @@ -72,10 +73,10 @@ public class UserServiceImpl implements UserService { @Override public void changeUserInfo(InfoDto infoDto, Long id) { - User user = userRepository.findById(id).orElse(null); + User user = userRepository.findById(id).orElseThrow(NoSuchElementException::new); - if (isEmailExist(infoDto.getEmail())) { + if (isEmailExist(infoDto.getEmail()) && !infoDto.getEmail().equals(user.getEmail())) { throw new RuntimeException("이미 사용 중인 이메일입니다."); }