Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/main/java/com/studai/config/CorsConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOriginPatterns("*")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.allowedHeaders("Authorization", "Content-Type")
.allowCredentials(true)
.maxAge(3600);
}
Expand Down
4 changes: 3 additions & 1 deletion src/main/java/com/studai/domain/quiz/Quiz.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import jakarta.persistence.*;
import lombok.*;
import com.studai.domain.question.Question;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

Expand Down Expand Up @@ -44,6 +46,6 @@ public class Quiz {

@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "quiz_id")
private List<QuizAttempt> attempts;
private List<QuizAttempt> attempts = new ArrayList<>();

}
3 changes: 2 additions & 1 deletion src/main/java/com/studai/domain/quiz/dto/QuizDTO.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import jakarta.persistence.Column;
import lombok.*;

import java.util.ArrayList;
import java.util.List;

@Getter
Expand All @@ -24,6 +25,6 @@ public class QuizDTO {
private QuizSourceType sourceType;
private String sourceUri;
private String userId;
private List<QuizAttemptDTO> attempts;
private List<QuizAttemptDTO> attempts = new ArrayList<>();

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,26 +22,26 @@ public class QuestionService {
private QuizRepository quizRepository;

public QuestionDTO create(QuestionDTO dto){
Quiz quiz = quizRepository.findById(UUID.fromString(dto.getQuizId())).orElseThrow(ResourceNotFoundException::new);
Quiz quiz = quizRepository.findById(UUID.fromString(dto.getQuizId())).orElseThrow(() -> new ResourceNotFoundException("Quiz not found with ID: " + dto.getQuizId()));
Question entity = questionRepository.save(QuestionAssembler.toEntity(dto, quiz));
return QuestionAssembler.toDTO(entity);
}

public QuestionDTO findById(String id){
Question entity = questionRepository.findById(UUID.fromString(id)).orElseThrow(ResourceNotFoundException::new);
Question entity = questionRepository.findById(UUID.fromString(id)).orElseThrow(() -> new ResourceNotFoundException("Question not found with ID: " + id));
return QuestionAssembler.toDTO(entity);
}

public QuestionDTO update(QuestionDTO questionDTO) {
Question existingQuestion = questionRepository.findById(UUID.fromString(questionDTO.getId())).orElseThrow(ResourceNotFoundException::new);
Question existingQuestion = questionRepository.findById(UUID.fromString(questionDTO.getId())).orElseThrow(() -> new ResourceNotFoundException("Question not found with ID: " + questionDTO.getId()));
Question updatedQuestion = QuestionAssembler.toEntity(questionDTO, existingQuestion.getQuiz());
updatedQuestion.setId(existingQuestion.getId());

return QuestionAssembler.toDTO(questionRepository.save(updatedQuestion));
}

public QuestionDTO delete(String id) {
Question entity = questionRepository.findById(UUID.fromString(id)).orElseThrow(ResourceNotFoundException::new);
Question entity = questionRepository.findById(UUID.fromString(id)).orElseThrow(() -> new ResourceNotFoundException("Question not found with ID: " + id));
questionRepository.delete(entity);
return QuestionAssembler.toDTO(entity);
}
Expand Down
13 changes: 7 additions & 6 deletions src/main/java/com/studai/service/quiz/QuizService.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,15 @@ public QuizDTO create(String videoId, int questionsNumber, String language){
return QuizAssembler.toDTO(entity);
}

public QuizDTO findById(String id){
Quiz quiz = quizRepository.findById(UUID.fromString(id)).orElseThrow(ResourceNotFoundException::new);
public QuizDTO findById(String id) {
Quiz quiz = quizRepository.findById(UUID.fromString(id))
.orElseThrow(() -> new ResourceNotFoundException("Quiz not found with ID: " + id));
return QuizAssembler.toDTO(quiz);
}


public List<QuizDTO> findAll() {
List<Quiz> quizzes = quizRepository.findByUser(userService.getCurrentUser());
if(quizzes.isEmpty()) throw new ResourceNotFoundException();
List<QuizDTO> quizDtos = new ArrayList<>();
for(Quiz quiz : quizzes){
quizDtos.add(QuizAssembler.toDTO(quiz));
Expand All @@ -76,7 +77,7 @@ public List<QuizDTO> findAll() {

public QuizDTO update(QuizDTO quizDTO) {
Quiz quiz = quizRepository.findById(UUID.fromString(quizDTO.getId()))
.orElseThrow(ResourceNotFoundException::new);
.orElseThrow(() -> new ResourceNotFoundException("Quiz not found with ID: " + quizDTO.getId()));

quiz.setTitle(quizDTO.getTitle());
quiz.setDescription(quizDTO.getDescription());
Expand Down Expand Up @@ -112,14 +113,14 @@ public QuizDTO update(QuizDTO quizDTO) {


public QuizDTO delete(String id) {
Quiz quiz = quizRepository.findById(UUID.fromString(id)).orElseThrow(ResourceNotFoundException::new);
Quiz quiz = quizRepository.findById(UUID.fromString(id)).orElseThrow(() -> new ResourceNotFoundException("Quiz not found with ID: " + id));
quizRepository.delete(quiz);
return QuizAssembler.toDTO(quiz);
}

public QuizAttemptDTO submitAttempt(String quizId, Double score, Long timeSpent){
QuizAttempt attempt = QuizAttempt.builder()
.quiz(quizRepository.findById(UUID.fromString(quizId)).orElseThrow(ResourceNotFoundException::new))
.quiz(quizRepository.findById(UUID.fromString(quizId)).orElseThrow(() -> new ResourceNotFoundException("Quiz not found with ID: " + quizId)))
.user(userService.getCurrentUser())
.score(score)
.timeSpent(timeSpent)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
import com.studai.domain.question.Question;
import com.studai.domain.question.dto.QuestionDTO;
import com.studai.domain.quiz.Quiz;
import com.studai.domain.quiz.attempt.QuizAttempt;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -38,14 +40,14 @@ public static QuestionDTO toDTO(Question question) {
}

public static List<Question> toEntityList(List<QuestionDTO> dtoList, Quiz quiz) {
if(dtoList == null) return null;
if(dtoList == null) return new ArrayList<>();
return dtoList.stream()
.map(dto -> toEntity(dto, quiz))
.collect(Collectors.toList());
}

public static List<QuestionDTO> toDTOList(List<Question> questions) {
if(questions == null) return null;
if(questions == null) return new ArrayList<>();
return questions.stream()
.map(QuestionAssembler::toDTO)
.collect(Collectors.toList());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public static Quiz toEntity(QuizDTO dto, User user){
quiz.setQuestions(questions);

List<QuizAttempt> attempts = QuizAttemptAssembler.toEntityList(dto.getAttempts(), quiz, user);
quiz.setAttempts(attempts);

return quiz;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.studai.domain.quiz.Quiz;
import com.studai.domain.user.User;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -34,14 +35,14 @@ public static QuizAttemptDTO toDTO(QuizAttempt quizAttempt) {
}

public static List<QuizAttempt> toEntityList(List<QuizAttemptDTO> dtoList, Quiz quiz, User user) {
if(dtoList == null || dtoList.isEmpty()) return null;
if(dtoList == null || dtoList.isEmpty()) return new ArrayList<>();
return dtoList.stream()
.map(dto -> toEntity(dto, quiz, user))
.collect(Collectors.toList());
}

public static List<QuizAttemptDTO> toDTOList(List<QuizAttempt> questions) {
if(questions == null || questions.isEmpty()) return null;
if(questions == null || questions.isEmpty()) return new ArrayList<>();
return questions.stream()
.map(QuizAttemptAssembler::toDTO)
.collect(Collectors.toList());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.ServletWebRequest;
Expand Down Expand Up @@ -34,6 +35,22 @@ public ResponseEntity<Object> handleResourceNotFoundException(ResourceNotFoundEx
return new ResponseEntity<>(errorResponse, new HttpHeaders(), HttpStatus.NOT_FOUND);
}

@ExceptionHandler(BadCredentialsException.class)
public ResponseEntity<Object> handleBadCredentialsException(RuntimeException ex, WebRequest request) {
String path = ((ServletWebRequest) request).getRequest().getRequestURI();
logger.error("Bad credentials exception at {}: {}", path, ex.getMessage(), ex);

ErrorResponse errorResponse = ErrorResponse.builder()
.timestamp(new Date())
.status(HttpStatus.UNAUTHORIZED.value())
.error(HttpStatus.UNAUTHORIZED.getReasonPhrase())
.message(ex.getMessage())
.path(path)
.build();

return new ResponseEntity<>(errorResponse, new HttpHeaders(), HttpStatus.UNAUTHORIZED);
}

@ExceptionHandler(RuntimeException.class)
public ResponseEntity<Object> handleRuntimeException(RuntimeException ex, WebRequest request) {
String path = ((ServletWebRequest) request).getRequest().getRequestURI();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
package com.studai.utils.exception;

public class ResourceNotFoundException extends RuntimeException{

public ResourceNotFoundException(){};

public ResourceNotFoundException(String message) {
super(message);
}

public ResourceNotFoundException(String message, Throwable cause) {
super(message, cause);
}

}
6 changes: 2 additions & 4 deletions src/test/java/com/studai/service/quiz/QuizServiceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@
import org.mockito.junit.jupiter.MockitoExtension;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.*;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
Expand Down Expand Up @@ -100,7 +98,7 @@ void testFindAll_Empty() {
when(userService.getCurrentUser()).thenReturn(user);
when(quizRepository.findByUser(user)).thenReturn(List.of());

assertThrows(ResourceNotFoundException.class, () -> quizService.findAll());
assertEquals(Collections.emptyList(), quizService.findAll());
}

@Test
Expand Down