diff --git a/src/main/java/site/sonisori/sonisori/config/SecurityConfig.java b/src/main/java/site/sonisori/sonisori/config/SecurityConfig.java index 24fadc8..edab1ca 100644 --- a/src/main/java/site/sonisori/sonisori/config/SecurityConfig.java +++ b/src/main/java/site/sonisori/sonisori/config/SecurityConfig.java @@ -51,7 +51,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti .authorizeHttpRequests((auth) -> auth .requestMatchers( - "/login/oauth2/code/*", "/api/auth/signup", "/api/auth/login", "/api/auth" + "/login/**", "/api/auth/signup", "/api/auth/login", "/api/auth" ).permitAll() .requestMatchers("/api/admin/**").hasRole("ADMIN") .anyRequest().authenticated() diff --git a/src/main/java/site/sonisori/sonisori/controller/SignWordController.java b/src/main/java/site/sonisori/sonisori/controller/SignWordController.java index 132a6eb..6821938 100644 --- a/src/main/java/site/sonisori/sonisori/controller/SignWordController.java +++ b/src/main/java/site/sonisori/sonisori/controller/SignWordController.java @@ -15,6 +15,7 @@ import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import site.sonisori.sonisori.common.response.SuccessResponse; +import site.sonisori.sonisori.dto.signword.SignWordDetailResponse; import site.sonisori.sonisori.dto.signword.SignWordRequest; import site.sonisori.sonisori.dto.signword.SignWordResponse; import site.sonisori.sonisori.service.SignWordService; @@ -31,6 +32,14 @@ public ResponseEntity> getAllSignWords() { return ResponseEntity.ok(signWords); } + @GetMapping("/words/{wordId}") + public ResponseEntity getSignWordDetails( + @PathVariable(name = "wordId") Long wordId + ) { + SignWordDetailResponse signWordDetail = signWordService.getSignWordDetail(wordId); + return ResponseEntity.ok(signWordDetail); + } + @PostMapping("/admin/words") public ResponseEntity addSignWordByAdmin(@RequestBody @Valid SignWordRequest signWordRequest) { SuccessResponse successResponse = signWordService.addSignWord(signWordRequest); diff --git a/src/main/java/site/sonisori/sonisori/dto/signword/SignWordDetailResponse.java b/src/main/java/site/sonisori/sonisori/dto/signword/SignWordDetailResponse.java new file mode 100644 index 0000000..58ab6dd --- /dev/null +++ b/src/main/java/site/sonisori/sonisori/dto/signword/SignWordDetailResponse.java @@ -0,0 +1,12 @@ +package site.sonisori.sonisori.dto.signword; + +import java.util.List; + +import site.sonisori.sonisori.dto.signwordresource.SignWordResourceDto; + +public record SignWordDetailResponse( + String word, + String description, + List resources +) { +} diff --git a/src/main/java/site/sonisori/sonisori/dto/signwordresource/SignWordResourceRequest.java b/src/main/java/site/sonisori/sonisori/dto/signwordresource/SignWordResourceDto.java similarity index 89% rename from src/main/java/site/sonisori/sonisori/dto/signwordresource/SignWordResourceRequest.java rename to src/main/java/site/sonisori/sonisori/dto/signwordresource/SignWordResourceDto.java index a57b16b..c610637 100644 --- a/src/main/java/site/sonisori/sonisori/dto/signwordresource/SignWordResourceRequest.java +++ b/src/main/java/site/sonisori/sonisori/dto/signwordresource/SignWordResourceDto.java @@ -5,7 +5,7 @@ import jakarta.validation.constraints.Size; import site.sonisori.sonisori.common.enums.ResourceType; -public record SignWordResourceRequest( +public record SignWordResourceDto( @NotNull ResourceType resourceType, diff --git a/src/main/java/site/sonisori/sonisori/dto/signwordresource/SignWordResourceListRequest.java b/src/main/java/site/sonisori/sonisori/dto/signwordresource/SignWordResourceListRequest.java index 5a3b8e3..b9f03d5 100644 --- a/src/main/java/site/sonisori/sonisori/dto/signwordresource/SignWordResourceListRequest.java +++ b/src/main/java/site/sonisori/sonisori/dto/signwordresource/SignWordResourceListRequest.java @@ -8,6 +8,6 @@ public record SignWordResourceListRequest( @NotNull @Size(min = 1) - List resources + List resources ) { } diff --git a/src/main/java/site/sonisori/sonisori/entity/SignWord.java b/src/main/java/site/sonisori/sonisori/entity/SignWord.java index a0323e0..89976e9 100644 --- a/src/main/java/site/sonisori/sonisori/entity/SignWord.java +++ b/src/main/java/site/sonisori/sonisori/entity/SignWord.java @@ -1,10 +1,14 @@ package site.sonisori.sonisori.entity; +import java.util.List; + import jakarta.persistence.Column; import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; import jakarta.persistence.Table; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Size; @@ -36,6 +40,9 @@ public class SignWord extends DateEntity { @Size(max = 500) private String description; + @OneToMany(mappedBy = "signWord", fetch = FetchType.LAZY) + private List signWordResources; + public SignWordResponse toDto() { return new SignWordResponse(this.id, this.word); } diff --git a/src/main/java/site/sonisori/sonisori/service/SignWordService.java b/src/main/java/site/sonisori/sonisori/service/SignWordService.java index eaea894..398a56d 100644 --- a/src/main/java/site/sonisori/sonisori/service/SignWordService.java +++ b/src/main/java/site/sonisori/sonisori/service/SignWordService.java @@ -9,9 +9,12 @@ import lombok.RequiredArgsConstructor; import site.sonisori.sonisori.common.constants.ErrorMessage; import site.sonisori.sonisori.common.response.SuccessResponse; +import site.sonisori.sonisori.dto.signword.SignWordDetailResponse; import site.sonisori.sonisori.dto.signword.SignWordRequest; import site.sonisori.sonisori.dto.signword.SignWordResponse; +import site.sonisori.sonisori.dto.signwordresource.SignWordResourceDto; import site.sonisori.sonisori.entity.SignWord; +import site.sonisori.sonisori.entity.SignWordResource; import site.sonisori.sonisori.exception.NotFoundException; import site.sonisori.sonisori.repository.SignWordRepository; @@ -27,6 +30,26 @@ public List getAllSignWords() { .collect(Collectors.toList()); } + @Transactional(readOnly = true) + public SignWordDetailResponse getSignWordDetail(Long wordId) { + SignWord signWord = signWordRepository.findById(wordId) + .orElseThrow(() -> new NotFoundException(ErrorMessage.NOT_FOUND_WORD.getMessage())); + + List resources = mapSignWordResources(signWord.getSignWordResources()); + + return new SignWordDetailResponse( + signWord.getWord(), + signWord.getDescription(), + resources + ); + } + + private List mapSignWordResources(List resources) { + return resources.stream() + .map(resource -> new SignWordResourceDto(resource.getResourceType(), resource.getResourceUrl())) + .toList(); + } + @Transactional public SuccessResponse addSignWord(SignWordRequest signWordRequest) { SignWord signWord = SignWord.builder() diff --git a/src/main/resources/db/migration/V5__add_cascade_settings.sql b/src/main/resources/db/migration/V5__add_cascade_settings.sql new file mode 100644 index 0000000..8ad35e6 --- /dev/null +++ b/src/main/resources/db/migration/V5__add_cascade_settings.sql @@ -0,0 +1,7 @@ +ALTER TABLE `sonisori`.`sign_word_resources` +DROP FOREIGN KEY `fk_sign-word-resources_sign-word_id`; +ALTER TABLE `sonisori`.`sign_word_resources` + ADD CONSTRAINT `fk_sign-word-resources_sign-word_id` + FOREIGN KEY (`sign_word_id`) + REFERENCES `sonisori`.`sign_words` (`id`) + ON DELETE CASCADE;