From 71bcf866d7a3afde1a751e899d31842deaf093d0 Mon Sep 17 00:00:00 2001 From: Ho Xuan Hieu Date: Tue, 16 Apr 2024 01:08:24 +0700 Subject: [PATCH] feat: add logic check session --- .../codeE/controller/AuthController.java | 10 +++ .../codeE/controller/ExerciseController.java | 47 +++++++----- .../exception/AllExceptionHandler.java | 1 - .../helper/AuditingMongoEventListener.java | 1 - .../exercise/common/SessionExercise.java | 42 +++++++++++ .../repository/SessionExerciseRepository.java | 10 +++ .../exercise/GetDetailExerciseRequest.java | 3 +- .../exercise/code/CodeDetailResponse.java | 8 +-- .../exercise/essay/EssayDetailResponse.java | 18 ++--- .../exercise/quiz/QuizDetailResponse.java | 8 +-- .../service/authentication/AuthenImpl.java | 12 +++- .../service/exercise/CodeExerciseImpl.java | 43 +++++++++-- .../service/exercise/CodeExerciseService.java | 3 +- .../service/exercise/EssayExerciseImpl.java | 43 ++++++++++- .../exercise/EssayExerciseService.java | 3 +- .../codeE/service/exercise/ExerciseImpl.java | 71 ++++++++++++++++++- .../service/exercise/ExerciseService.java | 3 +- .../service/exercise/QuizExerciseImpl.java | 43 ++++++++++- .../service/exercise/QuizExerciseService.java | 3 +- .../exercise/common/SessionExerciseImpl.java | 36 ++++++++++ .../common/SessionExerciseService.java | 8 +++ 21 files changed, 361 insertions(+), 55 deletions(-) create mode 100644 src/main/java/com/example/codeE/model/exercise/common/SessionExercise.java create mode 100644 src/main/java/com/example/codeE/repository/SessionExerciseRepository.java create mode 100644 src/main/java/com/example/codeE/service/exercise/common/SessionExerciseImpl.java create mode 100644 src/main/java/com/example/codeE/service/exercise/common/SessionExerciseService.java diff --git a/src/main/java/com/example/codeE/controller/AuthController.java b/src/main/java/com/example/codeE/controller/AuthController.java index b429a230..bacf06bc 100644 --- a/src/main/java/com/example/codeE/controller/AuthController.java +++ b/src/main/java/com/example/codeE/controller/AuthController.java @@ -7,6 +7,7 @@ import com.example.codeE.request.user.UserAuthenRequest; import com.example.codeE.request.user.forgetPasswordRequest; import com.example.codeE.service.authentication.AuthenService; +import com.example.codeE.service.exercise.common.SessionExerciseService; import com.example.codeE.service.user.UserService; import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; @@ -29,6 +30,9 @@ public class AuthController { private JWTUtils jwtHelper; @Autowired private UserService userService; + @Autowired + private SessionExerciseService SessionExerciseService; + @PostMapping @RequestMapping(value = "/login/user", method = RequestMethod.POST) @@ -198,6 +202,12 @@ private void clearAuthenticationTokens(HttpServletRequest request, HttpServletRe cookie.setPath("/"); response.addCookie(cookie); } + if ("LoginSessionId".equals(cookie.getName())) { + this.SessionExerciseService.removeSession(response, request, cookie.getValue()); + cookie.setMaxAge(0); + cookie.setPath("/"); + response.addCookie(cookie); + } } } } diff --git a/src/main/java/com/example/codeE/controller/ExerciseController.java b/src/main/java/com/example/codeE/controller/ExerciseController.java index ccc2f547..65858d04 100644 --- a/src/main/java/com/example/codeE/controller/ExerciseController.java +++ b/src/main/java/com/example/codeE/controller/ExerciseController.java @@ -22,6 +22,7 @@ import com.example.codeE.request.exercise.quiz.*; import com.example.codeE.service.course.CourseService; import com.example.codeE.service.exercise.*; +import com.example.codeE.service.exercise.common.SessionExerciseService; import com.example.codeE.service.exercise.common.SubmissionTestCaseService; import com.example.codeE.service.exercise.problem.CodeExerciseTestcaseService; import com.example.codeE.service.exercise.submission.CodeSubmissionService; @@ -31,6 +32,7 @@ import com.example.codeE.service.judge.JudgeService; import com.example.codeE.service.user.UserService; import com.mongodb.client.MongoDatabase; +import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; @@ -87,6 +89,8 @@ public class ExerciseController { @Autowired private CourseService courseService; + @Autowired + private SessionExerciseService sessionExerciseService; @PostMapping @RequestMapping(value = "code",method = RequestMethod.POST) @@ -193,18 +197,20 @@ public ResponseEntity getExerciseById(@PathVariable String exerciseId){ @PostMapping @RequestMapping(value = "detail", method = RequestMethod.POST) - public ResponseEntity getExerciseDetail(@RequestBody GetDetailExerciseRequest request){ - Exercise exercise = this.exerciseService.getDetailExercise(request.getExerciseId(), request.getKey(), request.getStudentId()); + public ResponseEntity getExerciseDetail(@RequestBody GetDetailExerciseRequest requestGetDetail, HttpServletRequest request, HttpServletResponse response) { + Exercise exercise = this.exerciseService.getDetailExercise(requestGetDetail.getExerciseId(), requestGetDetail.getKey(), requestGetDetail.getStudentId(), requestGetDetail.getUserUrgent(), request, response); + if (exercise == null) { + return ResponseEntity.status(HttpStatus.CONFLICT).body(Map.of("message", "Student can not enroll exercise now.")); + } switch (exercise.getType()){ case "code" : - CodeDetailResponse response = this.codeExerciseService.getCodeExerciseDetail(request.getExerciseId()); - return ResponseEntity.status(HttpStatus.OK).body(response); + return ResponseEntity.status(HttpStatus.OK).body(this.codeExerciseService.getCodeExerciseDetail(requestGetDetail.getExerciseId(), request)); case "quiz": - return ResponseEntity.status(HttpStatus.OK).body(this.quizExerciseService.getQuizExerciseDetail(request.getExerciseId())); + return ResponseEntity.status(HttpStatus.OK).body(this.quizExerciseService.getQuizExerciseDetail(requestGetDetail.getExerciseId(), request)); case "essay": - return ResponseEntity.status(HttpStatus.OK).body(this.essayExerciseService.getEssayExerciseDetail(request.getExerciseId() )); + return ResponseEntity.status(HttpStatus.OK).body(this.essayExerciseService.getEssayExerciseDetail(requestGetDetail.getExerciseId(), request)); case "file": - return ResponseEntity.status(HttpStatus.OK).body(this.fileExerciseService.getFileExerciseDetail(request.getExerciseId())); + return ResponseEntity.status(HttpStatus.OK).body(this.fileExerciseService.getFileExerciseDetail(requestGetDetail.getExerciseId())); default: return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(Map.of("message","Something went wrong, type must be quiz/essay/code")); } @@ -212,27 +218,27 @@ public ResponseEntity getExerciseDetail(@RequestBody GetDetailExerciseRequest @PostMapping @RequestMapping(value = "code/submit", method = RequestMethod.POST) - public ResponseEntity submitCodeExercise(@Valid @RequestBody SubmitCodeExerciseRequest request){ + public ResponseEntity submitCodeExercise(@Valid @RequestBody SubmitCodeExerciseRequest requestSubmit, HttpServletRequest request, HttpServletResponse response) { MongoDatabase database = mongoTemplate.getDb(); AutoIncrement autoIncrement = new AutoIncrement(database); try{ CodeSubmission submission = new CodeSubmission(judgeService); submission.setSubmissionId(String.valueOf(autoIncrement.getNextSequence("code_submission"))); - submission.setExerciseId(request.getExerciseId()); - submission.setLanguageId(request.getLanguageId()); - submission.setSource(request.getSource()); - submission.setStudentId(request.getStudentId()); + submission.setExerciseId(requestSubmit.getExerciseId()); + submission.setLanguageId(requestSubmit.getLanguageId()); + submission.setSource(requestSubmit.getSource()); + submission.setStudentId(requestSubmit.getStudentId()); submission.setPretested(false); - CodeExercise codeExercise = this.codeExerciseService.getCodeExerciseById(request.getExerciseId()); + CodeExercise codeExercise = this.codeExerciseService.getCodeExerciseById(requestSubmit.getExerciseId()); submission.setTime(codeExercise.getTimeLimit()); submission.setMemory(codeExercise.getMemoryLimit()); submission.setLockedAfter(codeExercise.getEndTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime()); CodeSubmission savedSubmission = codeSubmissionService.saveCodeSubmission(submission); savedSubmission.judge(false, false); - + sessionExerciseService.removeSession(response, request, requestSubmit.getExerciseId()); } catch (Exception e){ return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(Map.of("message", e.getMessage())); } @@ -291,18 +297,21 @@ public ResponseEntity runCodeExercise(@PathVariable String submissionId, @Req @PostMapping @RequestMapping(value = "quiz/submit", method = RequestMethod.POST) - public ResponseEntity submitQuizExercise(@Valid @RequestBody CreateQuizSubmissionRequest quizSubmission){ + public ResponseEntity submitQuizExercise(@Valid @RequestBody CreateQuizSubmissionRequest quizSubmission, HttpServletRequest request, HttpServletResponse response) { QuizExercise quizExercise = this.quizExerciseService.getQuizExerciseById(quizSubmission.getExerciseId()); float score = this.quizSubmissionService.gradeSubmission(quizSubmission.getSubmission(), quizExercise.getQuestions()); var submission = new QuizSubmission(quizSubmission, score); - QuizSubmission response = this.quizSubmissionService.createSubmission(submission); - return ResponseEntity.status(HttpStatus.OK).body(response); + QuizSubmission responseExercise = this.quizSubmissionService.createSubmission(submission); + sessionExerciseService.removeSession(response, request, quizExercise.getExerciseId()); + return ResponseEntity.status(HttpStatus.OK).body(responseExercise); } @PostMapping @RequestMapping(value = "essay/submit", method = RequestMethod.POST) - public ResponseEntity submitEssayExercise(@Valid @RequestBody CreateEssaySubmissionRequest essaySubmission){ - return ResponseEntity.status(HttpStatus.OK).body(this.essaySubmissionService.createSubmission(essaySubmission)); + public ResponseEntity submitEssayExercise(@Valid @RequestBody CreateEssaySubmissionRequest essaySubmission, HttpServletRequest request, HttpServletResponse response) { + var essayExercise = this.essaySubmissionService.createSubmission(essaySubmission); + sessionExerciseService.removeSession(response, request, essayExercise.getExerciseId()); + return ResponseEntity.status(HttpStatus.OK).body(essayExercise); } @PostMapping diff --git a/src/main/java/com/example/codeE/controller/exception/AllExceptionHandler.java b/src/main/java/com/example/codeE/controller/exception/AllExceptionHandler.java index e678d483..2d4175d5 100644 --- a/src/main/java/com/example/codeE/controller/exception/AllExceptionHandler.java +++ b/src/main/java/com/example/codeE/controller/exception/AllExceptionHandler.java @@ -1,7 +1,6 @@ package com.example.codeE.controller.exception; import jakarta.validation.ConstraintViolationException; -import javassist.NotFoundException; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; diff --git a/src/main/java/com/example/codeE/helper/AuditingMongoEventListener.java b/src/main/java/com/example/codeE/helper/AuditingMongoEventListener.java index 34c8994b..8d863de4 100644 --- a/src/main/java/com/example/codeE/helper/AuditingMongoEventListener.java +++ b/src/main/java/com/example/codeE/helper/AuditingMongoEventListener.java @@ -1,6 +1,5 @@ package com.example.codeE.helper; -import com.example.codeE.constant.Constant; import com.example.codeE.model.exercise.Exercise; import com.example.codeE.model.exercise.Submission; import com.example.codeE.util.DateTimeUtil; diff --git a/src/main/java/com/example/codeE/model/exercise/common/SessionExercise.java b/src/main/java/com/example/codeE/model/exercise/common/SessionExercise.java new file mode 100644 index 00000000..f9e8fb65 --- /dev/null +++ b/src/main/java/com/example/codeE/model/exercise/common/SessionExercise.java @@ -0,0 +1,42 @@ +package com.example.codeE.model.exercise.common; + +import jakarta.persistence.Id; +import jakarta.validation.constraints.NotBlank; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.springframework.data.mongodb.core.mapping.Document; +import org.springframework.data.mongodb.core.mapping.Field; + +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +@Document(collection = "session_exercise") +public class SessionExercise { + @Id + private String sessionId; + @NotBlank + @Field("login_id") + private String loginId; + @NotBlank + @Field("student_id") + private String studentId; + @NotBlank + @Field("exercise_id") + private String exerciseId; + @NotBlank + @Field("time_start") + private String timeStart; + @NotBlank + @Field("user_urgent") + private String userUrgent; + public SessionExercise(String loginId,String studentId, String exerciseId, String timeStart, String userUrgent){ + this.loginId =loginId; + this.studentId = studentId; + this.exerciseId = exerciseId; + this.timeStart = timeStart; + this.userUrgent = userUrgent; + } +} diff --git a/src/main/java/com/example/codeE/repository/SessionExerciseRepository.java b/src/main/java/com/example/codeE/repository/SessionExerciseRepository.java new file mode 100644 index 00000000..1f7c00e1 --- /dev/null +++ b/src/main/java/com/example/codeE/repository/SessionExerciseRepository.java @@ -0,0 +1,10 @@ +package com.example.codeE.repository; + +import com.example.codeE.model.exercise.common.SessionExercise; +import org.springframework.data.mongodb.repository.MongoRepository; + +import java.util.List; + +public interface SessionExerciseRepository extends MongoRepository { + List findByStudentIdAndLoginId(String studentId, String loginId); +} diff --git a/src/main/java/com/example/codeE/request/exercise/GetDetailExerciseRequest.java b/src/main/java/com/example/codeE/request/exercise/GetDetailExerciseRequest.java index 1287bdf9..3d525ce2 100644 --- a/src/main/java/com/example/codeE/request/exercise/GetDetailExerciseRequest.java +++ b/src/main/java/com/example/codeE/request/exercise/GetDetailExerciseRequest.java @@ -17,5 +17,6 @@ public class GetDetailExerciseRequest { private String studentId; @NotNull(message = "Exercise key is required") private String key; - + @NotNull(message = "User urgent is request is required") + private String userUrgent; } diff --git a/src/main/java/com/example/codeE/request/exercise/code/CodeDetailResponse.java b/src/main/java/com/example/codeE/request/exercise/code/CodeDetailResponse.java index 44798326..73abfbf5 100644 --- a/src/main/java/com/example/codeE/request/exercise/code/CodeDetailResponse.java +++ b/src/main/java/com/example/codeE/request/exercise/code/CodeDetailResponse.java @@ -35,7 +35,7 @@ public class CodeDetailResponse { private HashMap languageTemplate; private boolean isUsingAiGrading = false; - public CodeDetailResponse(CodeExercise codeExercise) { + public CodeDetailResponse(CodeExercise codeExercise, Date timeDoExercise) { this.exerciseId = codeExercise.getExerciseId(); this.exerciseName = codeExercise.getExerciseName(); this.topicId = codeExercise.getTopicId(); @@ -44,18 +44,18 @@ public CodeDetailResponse(CodeExercise codeExercise) { this.durationTime = codeExercise.getDurationTime(); this.reAttempt = codeExercise.getReAttempt(); this.type = codeExercise.getType(); - this.timeLess = GetTimeLess(codeExercise.getStartTime(), codeExercise.getEndTime(), codeExercise.getDurationTime()); + this.timeLess = GetTimeLess(codeExercise.getStartTime(), codeExercise.getEndTime(), codeExercise.getDurationTime(),timeDoExercise); this.description = codeExercise.getDescription(); this.testCases = codeExercise.getTestCases(); this.languageTemplate = getTemplateMap(codeExercise.getAllowedLanguageIds()); this.isUsingAiGrading = codeExercise.isUsingAiGrading(); } - private Date GetTimeLess(Date startTime, Date endTime, int durationTime) { + private Date GetTimeLess(Date startTime, Date endTime, int durationTime, Date timeDoExercise) { if(startTime == endTime){ return new Date(0); } - var current = new Date().getTime(); + var current = timeDoExercise.getTime(); if(current > endTime.getTime()){ return new Date(0); } diff --git a/src/main/java/com/example/codeE/request/exercise/essay/EssayDetailResponse.java b/src/main/java/com/example/codeE/request/exercise/essay/EssayDetailResponse.java index bfb02d6f..6c251fd7 100644 --- a/src/main/java/com/example/codeE/request/exercise/essay/EssayDetailResponse.java +++ b/src/main/java/com/example/codeE/request/exercise/essay/EssayDetailResponse.java @@ -31,7 +31,7 @@ public class EssayDetailResponse { private String question; private boolean isUsingAiGrading = false; - public EssayDetailResponse(EssayExercise essayExercise){ + public EssayDetailResponse(EssayExercise essayExercise, Date timeDoExercise){ this.exerciseId = essayExercise.getExerciseId(); this.exerciseName = essayExercise.getExerciseName(); this.topicId = essayExercise.getTopicId(); @@ -41,22 +41,24 @@ public EssayDetailResponse(EssayExercise essayExercise){ this.reAttempt = essayExercise.getReAttempt(); this.type = essayExercise.getType(); this.exerciseDescription = essayExercise.getExerciseDescription(); - this.timeLess = GetTimeLess(essayExercise.getStartTime(), essayExercise.getEndTime(), essayExercise.getDurationTime()); + this.timeLess = GetTimeLess(essayExercise.getStartTime(), essayExercise.getEndTime(), essayExercise.getDurationTime(), timeDoExercise); this.question = essayExercise.getQuestion(); this.isUsingAiGrading = essayExercise.isUsingAiGrading(); } - private Date GetTimeLess(Date startTime, Date endTime, int durationTime) { + private Date GetTimeLess(Date startTime, Date endTime, int durationTime,Date timeDoExercise) { if(startTime == endTime){ return new Date(0); } - var current = new Date().getTime(); - if(current > endTime.getTime()){ + var currentStart = timeDoExercise.getTime(); + var timeNow = new Date().getTime(); + if(timeNow > endTime.getTime()){ return new Date(0); } - if (current + ((long) durationTime * 60 * 1000) < endTime.getTime()) { - return new Date((long) durationTime * 60 * 1000); + if (currentStart + ((long) durationTime * 60 * 1000) < endTime.getTime()) { + var a = currentStart + ((long) durationTime * 60 * 1000); + return new Date((long) a - timeNow); } else { - return new Date((long) endTime.getTime() - current); + return new Date((long) endTime.getTime() - timeNow); } } } diff --git a/src/main/java/com/example/codeE/request/exercise/quiz/QuizDetailResponse.java b/src/main/java/com/example/codeE/request/exercise/quiz/QuizDetailResponse.java index 4fca16da..434446be 100644 --- a/src/main/java/com/example/codeE/request/exercise/quiz/QuizDetailResponse.java +++ b/src/main/java/com/example/codeE/request/exercise/quiz/QuizDetailResponse.java @@ -33,7 +33,7 @@ public class QuizDetailResponse { private String exerciseDescription; private List questions; - public QuizDetailResponse(QuizExercise quizExercise) { + public QuizDetailResponse(QuizExercise quizExercise, Date timeDoExercise) { this.exerciseId = quizExercise.getExerciseId(); this.exerciseName = quizExercise.getExerciseName(); this.topicId = quizExercise.getTopicId(); @@ -42,16 +42,16 @@ public QuizDetailResponse(QuizExercise quizExercise) { this.durationTime = quizExercise.getDurationTime(); this.reAttempt = quizExercise.getReAttempt(); this.type = quizExercise.getType(); - this.timeLess = GetTimeLess(quizExercise.getStartTime(), quizExercise.getEndTime(), quizExercise.getDurationTime()); + this.timeLess = GetTimeLess(quizExercise.getStartTime(), quizExercise.getEndTime(), quizExercise.getDurationTime(), timeDoExercise); this.exerciseDescription = quizExercise.getExerciseDescription(); this.questions = convertQuestion(quizExercise.getQuestions()); } - private Date GetTimeLess(Date startTime, Date endTime, int durationTime) { + private Date GetTimeLess(Date startTime, Date endTime, int durationTime, Date timeDoExercise) { if(startTime == endTime){ return new Date(0); } - var current = new Date().getTime(); + var current = timeDoExercise.getTime(); if(current > endTime.getTime()){ return new Date(0); } diff --git a/src/main/java/com/example/codeE/service/authentication/AuthenImpl.java b/src/main/java/com/example/codeE/service/authentication/AuthenImpl.java index 429f9d1e..24cf453a 100644 --- a/src/main/java/com/example/codeE/service/authentication/AuthenImpl.java +++ b/src/main/java/com/example/codeE/service/authentication/AuthenImpl.java @@ -10,6 +10,7 @@ import com.example.codeE.request.user.UserAuthenRequest; import com.example.codeE.security.BCryptPassword; import com.example.codeE.service.course.CourseService; +import com.example.codeE.service.exercise.common.SessionExerciseService; import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @@ -23,6 +24,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.Random; +import java.util.UUID; @Service public class AuthenImpl implements AuthenService{ @@ -56,7 +58,14 @@ public UserAuthenRequest signIn(LoginRequest signInRequest, HttpServletResponse .httpOnly(true) .secure(false) .path("/") - .maxAge(3600) + .maxAge(3600 * 4) + .build(); + response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString()); + cookie = ResponseCookie.from("LoginSessionId", UUID.randomUUID().toString()) + .httpOnly(true) + .secure(false) + .path("/") + .maxAge(3600 * 4) .build(); response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString()); }catch (Exception e){ @@ -131,7 +140,6 @@ public UserAuthenRequest createNewSessionUser(String token, HttpServletResponse @Override public void SendForgetPasswordOTP(String userName, HttpServletResponse response) throws NoSuchMethodException { -// System.out.println(AuthenImpl.class.getResourceAsStream("/credential_gmail_api.json")); var user = this.userRepository.findUserByUserName(userName); System.out.println(user.getEmail()); if (user == null) throw new NoSuchMethodException("No user found by: " + userName); diff --git a/src/main/java/com/example/codeE/service/exercise/CodeExerciseImpl.java b/src/main/java/com/example/codeE/service/exercise/CodeExerciseImpl.java index 682f0efe..b98f26bc 100644 --- a/src/main/java/com/example/codeE/service/exercise/CodeExerciseImpl.java +++ b/src/main/java/com/example/codeE/service/exercise/CodeExerciseImpl.java @@ -3,11 +3,15 @@ import com.example.codeE.constant.Constant; import com.example.codeE.helper.FileHelper; import com.example.codeE.model.exercise.CodeExercise; +import com.example.codeE.model.exercise.common.SessionExercise; import com.example.codeE.model.exercise.common.problem.TestCase; import com.example.codeE.repository.CodeExerciseRepository; import com.example.codeE.repository.ExerciseRepository; +import com.example.codeE.repository.SessionExerciseRepository; import com.example.codeE.request.exercise.code.CodeDetailResponse; import com.example.codeE.request.exercise.code.UpdateCodeExerciseRequest; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -18,7 +22,10 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.text.ParseException; +import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Date; import java.util.List; @Service @@ -28,7 +35,8 @@ public class CodeExerciseImpl implements CodeExerciseService{ @Autowired private ExerciseRepository exerciseRepository; - + @Autowired + private SessionExerciseRepository sessionExerciseRepository; @Override public List getProblemIds(List problems) { List result = new ArrayList<>(); @@ -49,7 +57,7 @@ public CodeExercise getCodeExerciseById(String exerciseId) { } @Override - public CodeDetailResponse getCodeExerciseDetail(String exerciseId) { + public CodeDetailResponse getCodeExerciseDetail(String exerciseId, HttpServletRequest request) { CodeExercise codeExercise = codeExerciseRepository.findById(exerciseId).get(); // Get only TestCase with 0 points List testCases = codeExercise.getTestCases(); @@ -60,9 +68,36 @@ public CodeDetailResponse getCodeExerciseDetail(String exerciseId) { } } codeExercise.setTestCases(pretestCases); - return new CodeDetailResponse(codeExercise); + var sessionlist = this.sessionExerciseRepository.findAll(); + SessionExercise session = getSessionExercise(request, sessionlist); + Date timeStart = new Date(); + try { + var timeString = session.getTimeStart(); + SimpleDateFormat sdf = new SimpleDateFormat(Constant.DATE_TIME_ISO_FORMAT); + timeStart = sdf.parse(timeString); + } catch (ParseException e) { + e.printStackTrace(); + } + return new CodeDetailResponse(codeExercise, timeStart); + } + private static SessionExercise getSessionExercise(HttpServletRequest request, List sessionlist) { + SessionExercise session = new SessionExercise(); + String loginId = ""; + Cookie[] cookies = request.getCookies(); + if (cookies != null) { + for (Cookie cookie : cookies) { + if ("LoginSessionId".equals(cookie.getName())) { + loginId = cookie.getValue(); + } + } + } + for (var item : sessionlist) { + if (item.getLoginId().equals(loginId)) { + session = item; + } + } + return session; } - @Override public CodeExercise createCodeExercise(CodeExercise codeExercise) { return codeExerciseRepository.save(codeExercise); diff --git a/src/main/java/com/example/codeE/service/exercise/CodeExerciseService.java b/src/main/java/com/example/codeE/service/exercise/CodeExerciseService.java index 885f4f0f..dcbb718e 100644 --- a/src/main/java/com/example/codeE/service/exercise/CodeExerciseService.java +++ b/src/main/java/com/example/codeE/service/exercise/CodeExerciseService.java @@ -4,6 +4,7 @@ import com.example.codeE.model.exercise.common.problem.TestCase; import com.example.codeE.request.exercise.code.CodeDetailResponse; import com.example.codeE.request.exercise.code.UpdateCodeExerciseRequest; +import jakarta.servlet.http.HttpServletRequest; import java.util.List; @@ -13,7 +14,7 @@ public interface CodeExerciseService { CodeExercise getCodeExerciseById(String exerciseId); - CodeDetailResponse getCodeExerciseDetail(String exerciseId); + CodeDetailResponse getCodeExerciseDetail(String exerciseId, HttpServletRequest request); void createProblemFolder(List testCaseList, String exerciseId); diff --git a/src/main/java/com/example/codeE/service/exercise/EssayExerciseImpl.java b/src/main/java/com/example/codeE/service/exercise/EssayExerciseImpl.java index cfe03b91..567f2586 100644 --- a/src/main/java/com/example/codeE/service/exercise/EssayExerciseImpl.java +++ b/src/main/java/com/example/codeE/service/exercise/EssayExerciseImpl.java @@ -1,15 +1,24 @@ package com.example.codeE.service.exercise; +import com.example.codeE.constant.Constant; import com.example.codeE.helper.LoggerHelper; import com.example.codeE.model.exercise.EssayExercise; +import com.example.codeE.model.exercise.common.SessionExercise; import com.example.codeE.repository.EssayExerciseRepository; import com.example.codeE.repository.ExerciseRepository; import com.example.codeE.repository.GroupRepository; +import com.example.codeE.repository.SessionExerciseRepository; import com.example.codeE.request.exercise.essay.EssayDetailResponse; import com.example.codeE.request.exercise.essay.UpdateEssayExerciseRequest; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; import java.util.NoSuchElementException; @Service @@ -20,6 +29,8 @@ public class EssayExerciseImpl implements EssayExerciseService{ private GroupRepository groupRepository; @Autowired private ExerciseRepository exerciseRepository; + @Autowired + private SessionExerciseRepository sessionExerciseRepository; @Override public EssayExercise createEssayExercise(EssayExercise essayExercise) { try{ @@ -41,9 +52,19 @@ public EssayExercise getEssayExerciseById(String exerciseId) { return this.essayExerciseRepository.findById(exerciseId).orElseThrow(() -> new NoSuchElementException("No exercise essay found by Id: "+ exerciseId)); } @Override - public EssayDetailResponse getEssayExerciseDetail(String exerciseId) { + public EssayDetailResponse getEssayExerciseDetail(String exerciseId, HttpServletRequest request) { var exercise = this.essayExerciseRepository.findById(exerciseId).orElseThrow(() -> new NoSuchElementException("No exercise essay found by Id: "+ exerciseId)); - return new EssayDetailResponse(exercise); + var sessionlist = this.sessionExerciseRepository.findAll(); + SessionExercise session = getSessionExercise(request, sessionlist); + Date timeStart = new Date(); + try { + var timeString = session.getTimeStart(); + SimpleDateFormat sdf = new SimpleDateFormat(Constant.DATE_TIME_ISO_FORMAT); + timeStart = sdf.parse(timeString); + } catch (ParseException e) { + e.printStackTrace(); + } + return new EssayDetailResponse(exercise, timeStart); } @Override public void deleteEssayExerciseById(String exerciseId) { @@ -61,4 +82,22 @@ public EssayExercise updateEssayExercise(String exerciseId, UpdateEssayExerciseR throw new RuntimeException("Something wrong when update essay exercise"); } } + private static SessionExercise getSessionExercise(HttpServletRequest request, List sessionlist) { + SessionExercise session = new SessionExercise(); + String loginId = ""; + Cookie[] cookies = request.getCookies(); + if (cookies != null) { + for (Cookie cookie : cookies) { + if ("LoginSessionId".equals(cookie.getName())) { + loginId = cookie.getValue(); + } + } + } + for (var item : sessionlist) { + if (item.getLoginId().equals(loginId)) { + session = item; + } + } + return session; + } } diff --git a/src/main/java/com/example/codeE/service/exercise/EssayExerciseService.java b/src/main/java/com/example/codeE/service/exercise/EssayExerciseService.java index 798fd172..8d61c088 100644 --- a/src/main/java/com/example/codeE/service/exercise/EssayExerciseService.java +++ b/src/main/java/com/example/codeE/service/exercise/EssayExerciseService.java @@ -3,11 +3,12 @@ import com.example.codeE.model.exercise.EssayExercise; import com.example.codeE.request.exercise.essay.EssayDetailResponse; import com.example.codeE.request.exercise.essay.UpdateEssayExerciseRequest; +import jakarta.servlet.http.HttpServletRequest; public interface EssayExerciseService { EssayExercise createEssayExercise (EssayExercise essayExercise); EssayExercise getEssayExerciseById(String exerciseId); void deleteEssayExerciseById(String exerciseId); EssayExercise updateEssayExercise(String exerciseId,UpdateEssayExerciseRequest updateRequest); - EssayDetailResponse getEssayExerciseDetail(String exerciseId); + EssayDetailResponse getEssayExerciseDetail(String exerciseId, HttpServletRequest request); } diff --git a/src/main/java/com/example/codeE/service/exercise/ExerciseImpl.java b/src/main/java/com/example/codeE/service/exercise/ExerciseImpl.java index cd6b172e..3de096a8 100644 --- a/src/main/java/com/example/codeE/service/exercise/ExerciseImpl.java +++ b/src/main/java/com/example/codeE/service/exercise/ExerciseImpl.java @@ -1,7 +1,9 @@ package com.example.codeE.service.exercise; +import com.example.codeE.constant.Constant; import com.example.codeE.helper.LoggerHelper; import com.example.codeE.model.exercise.*; +import com.example.codeE.model.exercise.common.SessionExercise; import com.example.codeE.model.topic.Topic; import com.example.codeE.model.user.User; import com.example.codeE.repository.*; @@ -9,6 +11,7 @@ import com.example.codeE.request.exercise.file.response.FilePreviewResponse; import com.example.codeE.request.group.GroupTopicResponse; import com.example.codeE.request.user.StudentSubmissionInformation; +import com.example.codeE.service.exercise.common.SessionExerciseService; import com.example.codeE.service.exercise.submission.CodeSubmissionService; import com.example.codeE.service.exercise.submission.EssaySubmissionService; import com.example.codeE.service.exercise.submission.FileSubmissionService; @@ -18,12 +21,20 @@ import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import com.example.codeE.util.DateTimeUtil; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.stereotype.Service; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.LocalDateTime; import java.io.IOException; import java.util.ArrayList; +import java.util.Date; import java.util.List; import java.util.NoSuchElementException; @@ -56,6 +67,10 @@ public class ExerciseImpl implements ExerciseService{ @Autowired private FileSubmissionService fileSubmissionService; @Autowired + private SessionExerciseRepository sessionExerciseRepository; + @Autowired + private SessionExerciseService sessionExerciseService; + @Autowired private CourseRepository courseRepository; @Override @@ -135,14 +150,64 @@ public Exercise getExerciseById(String exerciseId) { } @Override - public Exercise getDetailExercise(String exerciseId, String key, String studentId) { + public Exercise getDetailExercise(String exerciseId, String key, String studentId, String userUrgent, HttpServletRequest request, HttpServletResponse response) { var exercise = this.exerciseRepository.findById(exerciseId).orElseThrow(() -> new NoSuchElementException("No exercise found with ID: " + exerciseId)); if (!exercise.getKey().equals(key)) throw new IllegalArgumentException("Invalid enrollment key. Please double-check and try again."); else if (!isReTemp(exercise.getExerciseId(), studentId, exercise.getType(), exercise.getReAttempt())) throw new DataIntegrityViolationException("You have already submitted the exercise the maximum number of times allowed."); - else if (exercise.getKey().equals(key) && isReTemp(exercise.getExerciseId(), studentId, exercise.getType(), exercise.getReAttempt())) - return exercise; + else if (exercise.getKey().equals(key) && isReTemp(exercise.getExerciseId(), studentId, exercise.getType(), exercise.getReAttempt())) { + // login id from cookie + String loginId = ""; + Cookie[] cookies = request.getCookies(); + if (cookies != null) { + for (Cookie cookie : cookies) { + if ("LoginSessionId".equals(cookie.getName())) { + loginId = cookie.getValue(); + } + } + } + //check session exercise + var sessionExercises = this.sessionExerciseRepository.findByStudentIdAndLoginId(studentId, loginId); + if (sessionExercises.isEmpty()) { + // if it does not have any session has been saved create new one. + // get time now + LocalDateTime dateNow = LocalDateTime.now(); + //user Urgent ? + var session = new SessionExercise(loginId, studentId, exerciseId, DateTimeUtil.formatToIso(dateNow), ""); + sessionExerciseRepository.save(session); + return exercise; + } else { + var session = sessionExercises.get(0); + if (session.getLoginId().equals(loginId) && session.getStudentId().equals(studentId)) { + if (session.getExerciseId().equals(exerciseId)) { + Date timeStart = new Date(); + try { + var timeString = session.getTimeStart(); + SimpleDateFormat sdf = new SimpleDateFormat(Constant.DATE_TIME_ISO_FORMAT); + timeStart = sdf.parse(timeString); + } catch (ParseException e) { + e.printStackTrace(); + } + Date now = new Date(); + if ((long) exercise.getDurationTime() * 1000 * 60 + timeStart.getTime() < now.getTime()) { + this.sessionExerciseService.removeSession(response, request, loginId); + LocalDateTime dateNow = LocalDateTime.now(); + //user Urgent ? + session = new SessionExercise(loginId, studentId, exerciseId, DateTimeUtil.formatToIso(dateNow), ""); + sessionExerciseRepository.save(session); + } + return exercise; + //after return, system need to calculate a time left + } else { + //student has joined another exercise + throw new IllegalArgumentException("Student need to complete another current exercise before participating in a new one."); + } + } else { + throw new IllegalArgumentException("Failed to retrieve exercise information."); + } + } + } else throw new IllegalArgumentException("Failed to retrieve exercise information."); } diff --git a/src/main/java/com/example/codeE/service/exercise/ExerciseService.java b/src/main/java/com/example/codeE/service/exercise/ExerciseService.java index 4b44c054..2e1e9f08 100644 --- a/src/main/java/com/example/codeE/service/exercise/ExerciseService.java +++ b/src/main/java/com/example/codeE/service/exercise/ExerciseService.java @@ -7,6 +7,7 @@ import com.example.codeE.request.exercise.ExerciseResponse; import com.example.codeE.request.exercise.ExerciseStudentResponse; import com.example.codeE.request.exercise.file.response.FilePreviewResponse; +import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; @@ -21,7 +22,7 @@ public interface ExerciseService { FilePreviewResponse getFilePreviewExercise(String exerciseId, String studentId); List getExercisesByCourseId(String courseId); Exercise getExerciseById(String exerciseId); - Exercise getDetailExercise(String exerciseId, String key, String studentId); + Exercise getDetailExercise(String exerciseId, String key, String studentId, String userUrgent, HttpServletRequest request, HttpServletResponse response); void deleteExerciseById(String exerciseId); List getExercisesByTopicId(String topicId); List getExercisesByUserId(String topicId, String userId); diff --git a/src/main/java/com/example/codeE/service/exercise/QuizExerciseImpl.java b/src/main/java/com/example/codeE/service/exercise/QuizExerciseImpl.java index 45f995b3..a3e8fef7 100644 --- a/src/main/java/com/example/codeE/service/exercise/QuizExerciseImpl.java +++ b/src/main/java/com/example/codeE/service/exercise/QuizExerciseImpl.java @@ -1,14 +1,21 @@ package com.example.codeE.service.exercise; +import com.example.codeE.constant.Constant; import com.example.codeE.model.exercise.QuizExercise; import com.example.codeE.model.exercise.common.QuizChoice; import com.example.codeE.model.exercise.common.QuizQuestion; +import com.example.codeE.model.exercise.common.SessionExercise; import com.example.codeE.repository.*; import com.example.codeE.request.exercise.quiz.QuizDetailResponse; import com.example.codeE.request.exercise.quiz.UpdateQuizExerciseRequest; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; import java.util.List; import java.util.NoSuchElementException; @@ -23,6 +30,8 @@ public class QuizExerciseImpl implements QuizExerciseService{ @Autowired private ExerciseRepository exerciseRepository; @Autowired + private SessionExerciseRepository sessionExerciseRepository; + @Autowired private TopicRepository topicRepository; @Override public QuizExercise createQuizExercise(QuizExercise quizExercise) { @@ -56,10 +65,40 @@ public QuizExercise getQuizExerciseById(String exerciseId) { return quizExerciseRepository.findById(exerciseId).orElseThrow(() -> new NoSuchElementException("No exercise quiz found by Id: "+ exerciseId)); } @Override - public QuizDetailResponse getQuizExerciseDetail(String exerciseId){ + public QuizDetailResponse getQuizExerciseDetail(String exerciseId, HttpServletRequest request) { var quiz = quizExerciseRepository.findById(exerciseId).orElseThrow(() -> new NoSuchElementException("No exercise essay found by Id: "+ exerciseId)); - return new QuizDetailResponse(quiz); + var sessionlist = this.sessionExerciseRepository.findAll(); + SessionExercise session = getSessionExercise(request, sessionlist); + Date timeStart = new Date(); + try { + var timeString = session.getTimeStart(); + SimpleDateFormat sdf = new SimpleDateFormat(Constant.DATE_TIME_ISO_FORMAT); + timeStart = sdf.parse(timeString); + } catch (ParseException e) { + e.printStackTrace(); + } + return new QuizDetailResponse(quiz, timeStart); } + + private static SessionExercise getSessionExercise(HttpServletRequest request, List sessionlist) { + SessionExercise session = new SessionExercise(); + String loginId = ""; + Cookie[] cookies = request.getCookies(); + if (cookies != null) { + for (Cookie cookie : cookies) { + if ("LoginSessionId".equals(cookie.getName())) { + loginId = cookie.getValue(); + } + } + } + for (var item : sessionlist) { + if (item.getLoginId().equals(loginId)) { + session = item; + } + } + return session; + } + @Override public QuizQuestion getQuizQuestionByQuestionId(String questionId) { return this.quizQuestionRepository.findById(questionId).get(); diff --git a/src/main/java/com/example/codeE/service/exercise/QuizExerciseService.java b/src/main/java/com/example/codeE/service/exercise/QuizExerciseService.java index 3735cfb7..1d02fb03 100644 --- a/src/main/java/com/example/codeE/service/exercise/QuizExerciseService.java +++ b/src/main/java/com/example/codeE/service/exercise/QuizExerciseService.java @@ -4,6 +4,7 @@ import com.example.codeE.model.exercise.common.QuizQuestion; import com.example.codeE.request.exercise.quiz.QuizDetailResponse; import com.example.codeE.request.exercise.quiz.UpdateQuizExerciseRequest; +import jakarta.servlet.http.HttpServletRequest; public interface QuizExerciseService { public QuizExercise createQuizExercise(QuizExercise quizExercise); @@ -11,5 +12,5 @@ public interface QuizExerciseService { public QuizQuestion getQuizQuestionByQuestionId(String questionId); public QuizExercise updateQuizExercise(String exerciseId, UpdateQuizExerciseRequest updateExercise); public void deleteQuizExerciseById(String exerciseId); - QuizDetailResponse getQuizExerciseDetail(String exerciseId); + QuizDetailResponse getQuizExerciseDetail(String exerciseId, HttpServletRequest request); } diff --git a/src/main/java/com/example/codeE/service/exercise/common/SessionExerciseImpl.java b/src/main/java/com/example/codeE/service/exercise/common/SessionExerciseImpl.java new file mode 100644 index 00000000..f5e10078 --- /dev/null +++ b/src/main/java/com/example/codeE/service/exercise/common/SessionExerciseImpl.java @@ -0,0 +1,36 @@ +package com.example.codeE.service.exercise.common; + +import com.example.codeE.repository.SessionExerciseRepository; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.Objects; + +@Service +public class SessionExerciseImpl implements SessionExerciseService{ + + @Autowired + private SessionExerciseRepository sessionExerciseRepository; + + @Override + public void removeSession(HttpServletResponse response, HttpServletRequest request, String exerciseId) { + var sessionList = this.sessionExerciseRepository.findAll(); + String loginId = ""; + Cookie[] cookies = request.getCookies(); + if (cookies != null) { + for (Cookie cookie : cookies) { + if ("LoginSessionId".equals(cookie.getName())) { + loginId = cookie.getValue(); + } + } + } + for (var item: sessionList){ + if(Objects.equals(item.getLoginId(), loginId)){ + this.sessionExerciseRepository.delete(item); + } + } + } +} diff --git a/src/main/java/com/example/codeE/service/exercise/common/SessionExerciseService.java b/src/main/java/com/example/codeE/service/exercise/common/SessionExerciseService.java new file mode 100644 index 00000000..4d0b5bb1 --- /dev/null +++ b/src/main/java/com/example/codeE/service/exercise/common/SessionExerciseService.java @@ -0,0 +1,8 @@ +package com.example.codeE.service.exercise.common; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +public interface SessionExerciseService { + void removeSession(HttpServletResponse response, HttpServletRequest request,String exerciseId); +}