diff --git a/backend/src/main/java/codezap/template/controller/SpringDocTemplateController.java b/backend/src/main/java/codezap/template/controller/SpringDocTemplateController.java index 7076558e7..747ab737b 100644 --- a/backend/src/main/java/codezap/template/controller/SpringDocTemplateController.java +++ b/backend/src/main/java/codezap/template/controller/SpringDocTemplateController.java @@ -106,6 +106,9 @@ ResponseEntity findAllTemplates( @ApiErrorResponse(status = HttpStatus.BAD_REQUEST, instance = "/templates/1/login", errorCases = { @ErrorCase(description = "해당하는 ID 값인 템플릿이 없는 경우", exampleMessage = "식별자 1에 해당하는 템플릿이 존재하지 않습니다."), }) + @ApiErrorResponse(status = HttpStatus.FORBIDDEN, instance = "/templates/1", errorCases = { + @ErrorCase(description = "다른 사람의 private 템플릿인 경우", exampleMessage = "해당 템플릿은 비공개 템플릿입니다."), + }) ResponseEntity findTemplateById(Member member, Long id); @SecurityRequirement(name = "쿠키 인증 토큰") diff --git a/backend/src/main/java/codezap/template/domain/Template.java b/backend/src/main/java/codezap/template/domain/Template.java index 3d91767ef..4c4d590af 100644 --- a/backend/src/main/java/codezap/template/domain/Template.java +++ b/backend/src/main/java/codezap/template/domain/Template.java @@ -14,12 +14,11 @@ import jakarta.persistence.ManyToOne; import jakarta.persistence.OneToMany; +import org.hibernate.annotations.ColumnDefault; import org.hibernate.annotations.Formula; import codezap.category.domain.Category; import codezap.global.auditing.BaseTimeEntity; -import codezap.global.exception.CodeZapException; -import codezap.global.exception.ErrorCode; import codezap.member.domain.Member; import lombok.AccessLevel; import lombok.AllArgsConstructor; @@ -57,6 +56,7 @@ public class Template extends BaseTimeEntity { private Long likesCount; @Column(nullable = false) + @ColumnDefault("'PUBLIC'") @Enumerated(EnumType.STRING) private Visibility visibility; @@ -65,11 +65,7 @@ public Template(Member member, String title, String description, Category catego } public Template(Member member, String title, String description, Category category, Visibility visibility) { - this.member = member; - this.title = title; - this.description = description; - this.category = category; - this.visibility = visibility; + this(null, member, title, description, category, null, 0L, visibility); } public void updateTemplate(String title, String description, Category category, Visibility visibility) { @@ -79,9 +75,11 @@ public void updateTemplate(String title, String description, Category category, this.visibility = visibility; } - public void validateAuthorization(Member member) { - if (!getMember().equals(member)) { - throw new CodeZapException(ErrorCode.FORBIDDEN_ACCESS, "해당 템플릿에 대한 권한이 없습니다."); - } + public boolean matchMember(Member member) { + return this.member.equals(member); + } + + public boolean isPrivate() { + return visibility == Visibility.PRIVATE; } } diff --git a/backend/src/main/java/codezap/template/service/TemplateService.java b/backend/src/main/java/codezap/template/service/TemplateService.java index f6143784e..ed04667fd 100644 --- a/backend/src/main/java/codezap/template/service/TemplateService.java +++ b/backend/src/main/java/codezap/template/service/TemplateService.java @@ -66,7 +66,9 @@ public Template update( Category category ) { Template template = templateRepository.fetchById(templateId); - template.validateAuthorization(member); + if (!template.matchMember(member)) { + throw new CodeZapException(ErrorCode.FORBIDDEN_ACCESS, "해당 템플릿에 대한 권한이 없습니다."); + } template.updateTemplate( updateTemplateRequest.title(), updateTemplateRequest.description(), @@ -86,7 +88,9 @@ public void deleteByMemberAndIds(Member member, List ids) { private void deleteById(Member member, Long id) { Template template = templateRepository.fetchById(id); - template.validateAuthorization(member); + if (!template.matchMember(member)) { + throw new CodeZapException(ErrorCode.FORBIDDEN_ACCESS, "해당 템플릿에 대한 권한이 없습니다."); + } templateRepository.deleteById(id); } } diff --git a/backend/src/main/java/codezap/template/service/facade/TemplateApplicationService.java b/backend/src/main/java/codezap/template/service/facade/TemplateApplicationService.java index c2b380cbe..cb9234388 100644 --- a/backend/src/main/java/codezap/template/service/facade/TemplateApplicationService.java +++ b/backend/src/main/java/codezap/template/service/facade/TemplateApplicationService.java @@ -11,6 +11,8 @@ import codezap.category.domain.Category; import codezap.category.service.CategoryService; +import codezap.global.exception.CodeZapException; +import codezap.global.exception.ErrorCode; import codezap.likes.service.LikedChecker; import codezap.likes.service.LikesService; import codezap.member.domain.Member; @@ -58,18 +60,29 @@ public Long create(Member member, CreateTemplateRequest createTemplateRequest) { } public FindTemplateResponse findById(Long id) { - Template template = templateService.getById(id); - List tags = tagService.findAllByTemplate(template); - List sourceCodes = sourceCodeService.findAllByTemplate(template); - return FindTemplateResponse.of(template, sourceCodes, tags, false); + return makeTemplateResponse(id, template -> false, template -> false); } public FindTemplateResponse findById(Long id, Member loginMember) { + return makeTemplateResponse( + id, + template -> template.matchMember(loginMember), + template -> likesService.isLiked(loginMember, template) + ); + } + + private FindTemplateResponse makeTemplateResponse( + Long id, + TemplateOwnershipChecker templateOwnershipChecker, + LikedChecker likedChecker + ) { Template template = templateService.getById(id); + if (!templateOwnershipChecker.isOwner(template) && template.isPrivate()) { + throw new CodeZapException(ErrorCode.FORBIDDEN_ACCESS, "해당 템플릿은 비공개 템플릿입니다."); + } List tags = tagService.findAllByTemplate(template); List sourceCodes = sourceCodeService.findAllByTemplate(template); - boolean isLiked = likesService.isLiked(loginMember, template); - return FindTemplateResponse.of(template, sourceCodes, tags, isLiked); + return FindTemplateResponse.of(template, sourceCodes, tags, likedChecker.isLiked(template)); } public FindAllTemplatesResponse findAllBy( @@ -82,7 +95,7 @@ public FindAllTemplatesResponse findAllBy( Page