Skip to content

Commit

Permalink
Merge pull request #425 from kyum-q/docs/delete-templates
Browse files Browse the repository at this point in the history
템플릿 선택 삭제 및 조회 시 썸네일 스니펫 추가한 API 문서 작성
  • Loading branch information
zangsu authored Aug 14, 2024
2 parents 2a71e50 + 3c584e5 commit 207a054
Show file tree
Hide file tree
Showing 14 changed files with 215 additions and 171 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ public class TemplateController implements SpringDocTemplateController {
private final TemplateService templateService;

@PostMapping
public ResponseEntity<Void> create(
@Validated(ValidationSequence.class) @RequestBody CreateTemplateRequest createTemplateRequest,
@BasicAuthentication MemberDto memberDto
public ResponseEntity<Void> createTemplate(
@BasicAuthentication MemberDto memberDto,
@Validated(ValidationSequence.class) @RequestBody CreateTemplateRequest createTemplateRequest
) {
Long createdTemplateId = templateService.createTemplate(createTemplateRequest, memberDto);
Long createdTemplateId = templateService.createTemplate(memberDto, createTemplateRequest);
return ResponseEntity.created(URI.create("/templates/" + createdTemplateId))
.build();
}
Expand All @@ -59,6 +59,14 @@ public ResponseEntity<FindAllTemplatesResponse> getTemplates(
return ResponseEntity.ok(response);
}

@GetMapping("/{id}")
public ResponseEntity<FindTemplateResponse> getTemplateById(
@BasicAuthentication MemberDto memberDto,
@PathVariable Long id
) {
return ResponseEntity.ok(templateService.findByIdAndMember(id, memberDto));
}

@GetMapping("/tags")
public ResponseEntity<FindAllTagsResponse> getTags(
@BasicAuthentication MemberDto memberDto,
Expand All @@ -73,26 +81,22 @@ public ResponseEntity<ExploreTemplatesResponse> explore() {
return ResponseEntity.ok(templateService.findAll());
}

@GetMapping("/{id}")
public ResponseEntity<FindTemplateResponse> getTemplateById(@PathVariable Long id,
@BasicAuthentication MemberDto memberDto
) {
return ResponseEntity.ok(templateService.findByIdAndMember(id, memberDto));
}

@PostMapping("/{id}")
public ResponseEntity<Void> updateTemplate(
@BasicAuthentication MemberDto memberDto,
@PathVariable Long id,
@Validated(ValidationSequence.class) @RequestBody UpdateTemplateRequest updateTemplateRequest,
@BasicAuthentication MemberDto memberDto
@Validated(ValidationSequence.class) @RequestBody UpdateTemplateRequest updateTemplateRequest
) {
templateService.update(id, updateTemplateRequest, memberDto);
templateService.update(memberDto, id, updateTemplateRequest);
return ResponseEntity.ok().build();
}

@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteTemplate(@PathVariable Long id, @BasicAuthentication MemberDto memberDto) {
templateService.deleteById(id, memberDto);
@DeleteMapping("/{ids}")
public ResponseEntity<Void> deleteTemplates(
@BasicAuthentication MemberDto memberDto,
@PathVariable List<Long> ids
) {
templateService.deleteByIds(memberDto, ids);
return ResponseEntity.noContent().build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@
import io.swagger.v3.oas.annotations.media.Schema;

public record CreateSnippetRequest(
@Schema(description = "파일 이름", example = "Main.java")
@NotBlank(message = "파일 이름이 null 입니다.", groups = NotNullGroup.class)
@Size(max = 255, message = "파일 이름은 최대 255자까지 입력 가능합니다.", groups = SizeCheckGroup.class)
@Schema(description = "파일명", example = "Main.java")
@NotBlank(message = "파일명이 비어 있거나 공백입니다.", groups = NotNullGroup.class)
@Size(max = 255, message = "파일명은 최대 255자까지 입력 가능합니다.", groups = SizeCheckGroup.class)
String filename,

@Schema(description = "소스 코드", example = "public class Main { // ...")
@NotBlank(message = "파일 내용이 null 입니다.", groups = NotNullGroup.class)
@ByteLength(max = 65_535, message = "파일 내용은 최대 65,535 Byte까지 입력 가능합니다.", groups = SizeCheckGroup.class)
@NotBlank(message = "소스 코드가 비어 있거나 공백입니다.", groups = NotNullGroup.class)
@ByteLength(max = 65_535, message = "소스 코드는 최대 65,535 Byte까지 입력 가능합니다.", groups = SizeCheckGroup.class)
String content,

@Schema(description = "스니펫 순서", example = "1")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,32 @@
import io.swagger.v3.oas.annotations.media.Schema;

public record CreateTemplateRequest(
@Schema(description = "템플릿 이름", example = "스프링 로그인 구현")
@NotBlank(message = "템플릿 이름이 null 입니다.", groups = NotNullGroup.class)
@Size(max = 255, message = "템플릿 이름은 최대 255자까지 입력 가능합니다.", groups = SizeCheckGroup.class)
@Schema(description = "템플릿명", example = "스프링 로그인 구현")
@NotBlank(message = "템플릿명이 비어 있거나 공백입니다.", groups = NotNullGroup.class)
@Size(max = 255, message = "템플릿명은 최대 255자까지 입력 가능합니다.", groups = SizeCheckGroup.class)
String title,

@Schema(description = "템플릿 설명", example = "JWT를 사용하여 로그인 기능을 구현함")
@NotNull(message = "템플릿 설명이 null 입니다.", groups = NotNullGroup.class)
@ByteLength(max = 65_535, message = "템플릿 설명은 최대 65,535 Byte까지 입력 가능합니다.", groups = SizeCheckGroup.class)
String description,

@Schema(description = "템플릿의 스니펫 내역")
@NotNull(message = "스니펫 리스트가 null 입니다.", groups = NotNullGroup.class)
@Schema(description = "스니펫 목록")
@NotNull(message = "스니펫 목록이 null 입니다.", groups = NotNullGroup.class)
@Size(min = 1, message = "스니펫은 최소 1개 입력해야 합니다.", groups = SizeCheckGroup.class)
@Valid
List<CreateSnippetRequest> snippets,

@Schema(description = "썸네일 스니펫 순서", example = "1")
@NotNull(message = "썸네일 스니펫 순서가 null 입니다.")
int thumbnailOrdinal,

@Schema(description = "카테고리 ID", example = "1")
@NotNull(message = "카테고리 id가 null 입니다.")
@NotNull(message = "카테고리 ID가 null 입니다.")
Long categoryId,

@Schema(description = "태그 리스트")
@NotNull(message = "태그 리스트가 null 입니다.")
@Schema(description = "태그 목록")
@NotNull(message = "태그 목록이 null 입니다.")
List<String> tags
) implements ValidatedSnippetsOrdinalRequest {
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@
import io.swagger.v3.oas.annotations.media.Schema;

public record UpdateSnippetRequest(
@Schema(description = "파일 식별자", example = "0")
@NotNull(message = "파일 id가 null 입니다.")
@Schema(description = "스니펫 ID", example = "0")
@NotNull(message = "스니펫 ID가 null 입니다.")
Long id,

@Schema(description = "파일 이름", example = "Main.java")
@NotBlank(message = "파일 이름이 null 입니다.", groups = NotNullGroup.class)
@Size(max = 255, message = "파일 이름은 최대 255자까지 입력 가능합니다.", groups = SizeCheckGroup.class)
@Schema(description = "파일명", example = "Main.java")
@NotBlank(message = "파일명이 비어 있거나 공백입니다.", groups = NotNullGroup.class)
@Size(max = 255, message = "파일명은 최대 255자까지 입력 가능합니다.", groups = SizeCheckGroup.class)
String filename,

@Schema(description = "소스 코드", example = "public class Main { // ...")
@NotBlank(message = "파일 내용이 null 입니다.", groups = NotNullGroup.class)
@ByteLength(max = 65_535, message = "파일 내용은 최대 65,535 Byte까지 입력 가능합니다.", groups = SizeCheckGroup.class)
@NotBlank(message = "소스 코드가 비어 있거나 공백입니다.", groups = NotNullGroup.class)
@ByteLength(max = 65_535, message = "소스 코드는 최대 65,535 Byte까지 입력 가능합니다.", groups = SizeCheckGroup.class)
String content,

@Schema(description = "스니펫 순서", example = "1")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,36 +16,36 @@
import io.swagger.v3.oas.annotations.media.Schema;

public record UpdateTemplateRequest(
@Schema(description = "템플릿 이름", example = "스프링 로그인 구현")
@NotBlank(message = "템플릿 이름이 null 입니다.", groups = NotNullGroup.class)
@Size(max = 255, message = "템플릿 이름은 최대 255자까지 입력 가능합니다.", groups = SizeCheckGroup.class)
@Schema(description = "템플릿명", example = "스프링 로그인 구현")
@NotBlank(message = "템플릿명이 비어 있거나 공백입니다.", groups = NotNullGroup.class)
@Size(max = 255, message = "템플릿명은 최대 255자까지 입력 가능합니다.", groups = SizeCheckGroup.class)
String title,

@Schema(description = "템플릿 설명", example = "JWT를 사용하여 로그인 기능을 구현함")
@NotNull(message = "템플릿 설명이 null 입니다.", groups = NotNullGroup.class)
@ByteLength(max = 65_535, message = "템플릿 설명은 최대 65,535 Byte까지 입력 가능합니다.", groups = SizeCheckGroup.class)
String description,

@Schema(description = "새로 추가한 스니펫 내역")
@NotNull(message = "createSnippets 리스트가 null 입니다.", groups = NotNullGroup.class)
@Schema(description = "추가하는 스니펫 목록")
@NotNull(message = "추가하는 스니펫 목록이 null 입니다.", groups = NotNullGroup.class)
@Valid
List<CreateSnippetRequest> createSnippets,

@Schema(description = "삭제, 생성 스니펫을 제외한 모든 스니펫 내역")
@NotNull(message = "updateSnippets 리스트가 null 입니다.", groups = NotNullGroup.class)
@Schema(description = "삭제, 생성 스니펫을 제외한 모든 스니펫 목록")
@NotNull(message = "삭제, 생성 스니펫을 제외한 모든 스니펫 목록이 null 입니다.", groups = NotNullGroup.class)
@Valid
List<UpdateSnippetRequest> updateSnippets,

@Schema(description = "삭제한 스니펫 식별자")
@NotNull(message = "deleteSnippetIds 리스트가 null 입니다.")
@Schema(description = "삭제하는 스니펫 ID 목록")
@NotNull(message = "삭제하는 스니펫 ID 목록이 null 입니다.")
List<Long> deleteSnippetIds,

@Schema(description = "카테고리 ID", example = "1")
@NotNull(message = "카테고리 id가 null 입니다.")
@NotNull(message = "카테고리 ID가 null 입니다.")
Long categoryId,

@Schema(description = "태그 리스트")
@NotNull(message = "태그 리스트가 null 입니다.")
@Schema(description = "태그 목록")
@NotNull(message = "태그 목록이 null 입니다.")
List<String> tags
) implements ValidatedSnippetsOrdinalRequest, ValidatedSnippetsCountRequest {
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,16 @@ public record FindAllTemplatesResponse(
List<ItemResponse> templates
) {
public record ItemResponse(
@Schema(description = "템플릿 식별자", example = "0")
@Schema(description = "템플릿 ID", example = "0")
Long id,
@Schema(description = "템플릿 이름", example = "스프링 로그인 구현")
@Schema(description = "템플릿명", example = "스프링 로그인 구현")
String title,
@Schema(description = "템플릿 설명", example = "Jwt 토큰을 이용하여 로그인 기능을 구현합니다.")
String description,
@Schema(description = "태그 목록")
List<FindTagResponse> tags,
@Schema(description = "썸네일 스니펫")
FindThumbnailSnippetResponse thumbnailSnippet,
@Schema(description = "템플릿 생성 시간", example = "2024-11-10 12:00", type = "string")
LocalDateTime createdAt,
@Schema(description = "템플릿 수정 시간", example = "2024-11-11 12:00", type = "string")
Expand All @@ -37,6 +39,7 @@ public static ItemResponse of(Template template, List<Tag> templateTags) {
templateTags.stream()
.map(tag -> new FindTagResponse(tag.getId(), tag.getName()))
.toList(),
null,
template.getCreatedAt(),
template.getModifiedAt()
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
import io.swagger.v3.oas.annotations.media.Schema;

public record FindThumbnailSnippetResponse(
@Schema(description = "파일 이름", example = "Main.java")
@Schema(description = "썸네일 파일명", example = "Main.java")
String filename,

@Schema(description = "목록 조회 시 보여질 코드", example = "public class Main { // ...")
String thumbnailContent
@Schema(description = "썸네일 소스 코드", example = "public class Main { // ...")
String content
) {
public static FindThumbnailSnippetResponse from(Snippet snippet) {
return new FindThumbnailSnippetResponse(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public class TemplateService {
private final MemberRepository memberRepository;

@Transactional
public Long createTemplate(CreateTemplateRequest createTemplateRequest, MemberDto memberDto) {
public Long createTemplate(MemberDto memberDto, CreateTemplateRequest createTemplateRequest) {
Member member = memberRepository.fetchById(memberDto.id());
Category category = categoryRepository.fetchById(createTemplateRequest.categoryId());
validateCategoryAuthorizeMember(category, member);
Expand All @@ -75,7 +75,7 @@ public Long createTemplate(CreateTemplateRequest createTemplateRequest, MemberDt

private void validateCategoryAuthorizeMember(Category category, Member member) {
if (!category.getMember().equals(member)) {
throw new CodeZapException(HttpStatus.UNAUTHORIZED, "해당 카테고리에 대한 권한이 없는 유저입니다.");
throw new CodeZapException(HttpStatus.UNAUTHORIZED, "해당 카테고리에 대한 권한이 없습니다.");
}
}

Expand Down Expand Up @@ -121,7 +121,7 @@ public FindTemplateResponse findByIdAndMember(Long id, MemberDto memberDto) {

private void validateTemplateAuthorizeMember(Template template, Member member) {
if (!template.getMember().equals(member)) {
throw new CodeZapException(HttpStatus.UNAUTHORIZED, "해당 템플릿에 대한 권한이 없는 유저입니다.");
throw new CodeZapException(HttpStatus.UNAUTHORIZED, "해당 템플릿에 대한 권한이 없습니다.");
}
}

Expand Down Expand Up @@ -168,7 +168,7 @@ private List<Tag> getTemplateTags(Template template) {
}

@Transactional
public void update(Long templateId, UpdateTemplateRequest updateTemplateRequest, MemberDto memberDto) {
public void update(MemberDto memberDto, Long templateId, UpdateTemplateRequest updateTemplateRequest) {
Member member = memberRepository.fetchById(memberDto.id());
Category category = categoryRepository.fetchById(updateTemplateRequest.categoryId());
validateCategoryAuthorizeMember(category, member);
Expand Down Expand Up @@ -245,7 +245,13 @@ private void validateSnippetsCount(UpdateTemplateRequest updateTemplateRequest,
}

@Transactional
public void deleteById(Long id, MemberDto memberDto) {
public void deleteByIds(MemberDto memberDto, List<Long> ids) {
for (Long id : ids) {
deleteById(memberDto, id);
}
}

private void deleteById(MemberDto memberDto, Long id) {
Member member = memberRepository.fetchById(memberDto.id());
Template template = templateRepository.fetchById(id);
validateTemplateAuthorizeMember(template, member);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -285,14 +285,15 @@ void updateCategoryFailWithDuplicatedName() throws Exception {
void updateCategoryFailWithLongName() throws Exception {
// given
templateService.createTemplate(
MemberDtoFixture.getFirstMemberDto(),
new CreateTemplateRequest(
"title",
"description",
List.of(new CreateSnippetRequest("filename", "content", 1)),
1,
savedCategoryId,
List.of("tag1", "tag2")
),
MemberDtoFixture.getFirstMemberDto()
)
);

// when & then
Expand Down
Loading

0 comments on commit 207a054

Please sign in to comment.