Implement secure quiz question retrieval
This commit is contained in:
1 parent
7b5d091989
commit
c03a7e6362
1 file changed
+47
@@ -1,5 +1,6 @@
|
|||||||
package com.example.questionbank.service.quiz;
|
package com.example.questionbank.service.quiz;
|
||||||
|
|
||||||
|
import com.example.questionbank.domain.Choice;
|
||||||
import com.example.questionbank.domain.ExamAttempt;
|
import com.example.questionbank.domain.ExamAttempt;
|
||||||
import com.example.questionbank.domain.Question;
|
import com.example.questionbank.domain.Question;
|
||||||
import com.example.questionbank.domain.Subject;
|
import com.example.questionbank.domain.Subject;
|
||||||
@@ -9,8 +10,11 @@ import com.example.questionbank.repository.ExamAttemptRepository;
|
|||||||
import com.example.questionbank.repository.QuestionRepository;
|
import com.example.questionbank.repository.QuestionRepository;
|
||||||
import com.example.questionbank.repository.SubjectRepository;
|
import com.example.questionbank.repository.SubjectRepository;
|
||||||
import com.example.questionbank.repository.UserRepository;
|
import com.example.questionbank.repository.UserRepository;
|
||||||
|
import com.example.questionbank.web.rest.dto.ChoiceView;
|
||||||
import com.example.questionbank.web.rest.dto.ExamAttemptStartResult;
|
import com.example.questionbank.web.rest.dto.ExamAttemptStartResult;
|
||||||
|
import com.example.questionbank.web.rest.dto.ExamQuestionView;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@@ -37,6 +41,7 @@ public class QuizAttemptService {
|
|||||||
this.userRepository = userRepository;
|
this.userRepository = userRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 1. 시험 응시 시작
|
||||||
@Transactional
|
@Transactional
|
||||||
public ExamAttemptStartResult start(Long subjectId, String login) {
|
public ExamAttemptStartResult start(Long subjectId, String login) {
|
||||||
Subject subject = subjectRepository
|
Subject subject = subjectRepository
|
||||||
@@ -65,6 +70,48 @@ public class QuizAttemptService {
|
|||||||
attempt.setScore(0);
|
attempt.setScore(0);
|
||||||
|
|
||||||
ExamAttempt saved = attemptRepository.save(attempt);
|
ExamAttempt saved = attemptRepository.save(attempt);
|
||||||
|
|
||||||
return new ExamAttemptStartResult(saved.getId(), saved.getStartedAt());
|
return new ExamAttemptStartResult(saved.getId(), saved.getStartedAt());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 2. 시험 문제 조회 (정답은 숨김)
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
public List<ExamQuestionView> getQuestions(Long attemptId, String login) {
|
||||||
|
ExamAttempt attempt = getOwnedAttempt(attemptId, login);
|
||||||
|
|
||||||
|
if (attempt.getStatus() != AttemptStatus.IN_PROGRESS) {
|
||||||
|
throw new ResponseStatusException(HttpStatus.CONFLICT, "진행 중인 응시만 문제를 조회할 수 있습니다.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return questionRepository
|
||||||
|
.findAllBySubjectIdAndActiveTrue(attempt.getSubject().getId())
|
||||||
|
.stream()
|
||||||
|
.sorted(Comparator.comparing(Question::getId))
|
||||||
|
.map(question ->
|
||||||
|
new ExamQuestionView(
|
||||||
|
question.getId(),
|
||||||
|
question.getPrompt(),
|
||||||
|
question
|
||||||
|
.getChoices()
|
||||||
|
.stream()
|
||||||
|
.sorted(Comparator.comparing(Choice::getDisplayOrder))
|
||||||
|
.map(choice -> new ChoiceView(choice.getOptionKey(), choice.getContent(), choice.getDisplayOrder()))
|
||||||
|
.toList()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 응시 기록이 로그인한 사용자 본인의 것인지 확인
|
||||||
|
private ExamAttempt getOwnedAttempt(Long attemptId, String login) {
|
||||||
|
ExamAttempt attempt = attemptRepository
|
||||||
|
.findById(attemptId)
|
||||||
|
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "응시를 찾을 수 없습니다."));
|
||||||
|
|
||||||
|
if (!attempt.getUser().getLogin().equals(login)) {
|
||||||
|
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "응시를 찾을 수 없습니다.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return attempt;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user