Skip to content

Commit c4c8822

Browse files
authored
Merge pull request #565 from woowacourse-teams/dev/be
[BE] 코드잽 프로덕션 v1.1.0 배포
2 parents 511d0c4 + 153a976 commit c4c8822

File tree

74 files changed

+1670
-1711
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+1670
-1711
lines changed

.github/workflows/backend_cd.yml

Lines changed: 12 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,16 @@ name: Backend CD
33
on:
44
push:
55
branches:
6+
- main
67
- dev/be
78

89
jobs:
910
build:
10-
runs-on: [self-hosted, develop, spring]
11+
runs-on:
12+
- self-hosted
13+
- spring
14+
- ${{ contains(github.ref, 'main') && 'production' || 'develop' }}
1115
steps:
12-
- name: 브랜치명을 통해 개발 환경 알아내기
13-
run: |
14-
cd ${{ secrets.SCRIPT_DIRECTORY }}
15-
bash find-env-by-branch.sh
16-
1716
- name: 체크아웃
1817
uses: actions/checkout@v4
1918

@@ -23,7 +22,7 @@ jobs:
2322
- name: bootJar로 jar 파일 생성
2423
run: |
2524
./gradlew bootJar
26-
mv build/libs/*.jar ${{ secrets.WORK_DIRECTORY }}/${{ env.ENVIRONMENT }}
25+
mv build/libs/*.jar ${{ secrets.JAR_DIRECTORY }}
2726
working-directory: ./backend
2827

2928
- name: 클린업
@@ -32,24 +31,12 @@ jobs:
3231

3332
deploy:
3433
needs: build
35-
runs-on: [self-hosted, develop, spring]
34+
runs-on:
35+
- self-hosted
36+
- spring
37+
- ${{ contains(github.ref, 'main') && 'production' || 'develop' }}
3638
steps:
37-
- name: 브랜치명을 통해 개발 환경 알아내기
38-
run: |
39-
cd ${{ secrets.SCRIPT_DIRECTORY }}
40-
bash find-env-by-branch.sh
41-
42-
- name: 실행 프로세스 확인
43-
run: |
44-
cd ${{ secrets.SCRIPT_DIRECTORY }}
45-
bash check-old-pids.sh
46-
4739
- name: 배포 스크립트 실행
4840
run: |
49-
cd ${{ secrets.SCRIPT_DIRECTORY }}
50-
RUNNER_TRACKING_ID="" && bash start.sh ${{ env.ENVIRONMENT }}
51-
52-
- name: 실행 프로세스 확인으로 배포 검증
53-
run: |
54-
cd ${{ secrets.SCRIPT_DIRECTORY }}
55-
bash verify-deploy.sh
41+
cd ${{ secrets.ZAP_DIRECTORY }}
42+
docker compose restart

.github/workflows/backend_cd_prod.yml

Lines changed: 0 additions & 35 deletions
This file was deleted.

backend/src/main/java/codezap/auth/dto/response/LoginResponse.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import codezap.member.domain.Member;
44

55
public record LoginResponse(
6-
long memberId,
6+
Long memberId,
77
String name
88
) {
99
public static LoginResponse from(Member member) {

backend/src/main/java/codezap/auth/provider/basic/BasicAuthCredentialProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public String createCredential(Member member) {
2626
@Override
2727
public Member extractMember(String credential) {
2828
String[] nameAndPassword = BasicAuthDecoder.decodeBasicAuth(credential);
29-
Member member = memberRepository.fetchByname(nameAndPassword[0]);
29+
Member member = memberRepository.fetchByName(nameAndPassword[0]);
3030
checkMatchPassword(member, nameAndPassword[1]);
3131
return member;
3232
}

backend/src/main/java/codezap/auth/service/AuthService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public LoginAndCredentialDto login(LoginRequest loginRequest) {
2626
}
2727

2828
private Member getVerifiedMember(String name, String password) {
29-
Member member = memberRepository.fetchByname(name);
29+
Member member = memberRepository.fetchByName(name);
3030
validateCorrectPassword(member, password);
3131
return member;
3232
}

backend/src/main/java/codezap/category/controller/CategoryController.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
import codezap.category.dto.request.UpdateCategoryRequest;
2020
import codezap.category.dto.response.CreateCategoryResponse;
2121
import codezap.category.dto.response.FindAllCategoriesResponse;
22-
import codezap.category.service.CategoryService;
22+
import codezap.category.service.facade.MemberCategoryApplicationService;
23+
import codezap.category.service.facade.MemberCategoryTemplateApplicationService;
2324
import codezap.global.validation.ValidationSequence;
2425
import codezap.member.dto.MemberDto;
2526
import lombok.RequiredArgsConstructor;
@@ -29,24 +30,24 @@
2930
@RequestMapping("/categories")
3031
public class CategoryController implements SpringDocCategoryController {
3132

32-
private final CategoryService categoryService;
33+
private final MemberCategoryApplicationService memberCategoryApplicationService;
34+
private final MemberCategoryTemplateApplicationService memberCategoryTemplateApplicationService;
3335

3436
@PostMapping
3537
public ResponseEntity<CreateCategoryResponse> createCategory(
3638
@AuthenticationPrinciple MemberDto memberDto,
3739
@Validated(ValidationSequence.class) @RequestBody CreateCategoryRequest createCategoryRequest
3840
) {
39-
CreateCategoryResponse response = categoryService.create(memberDto, createCategoryRequest);
40-
return ResponseEntity.created(URI.create("/categories/" + response.id()))
41-
.body(response);
41+
CreateCategoryResponse createdCategory = memberCategoryApplicationService.create(memberDto, createCategoryRequest);
42+
return ResponseEntity.created(URI.create("/categories/" + createdCategory.id()))
43+
.body(createdCategory);
4244
}
4345

4446
@GetMapping
4547
public ResponseEntity<FindAllCategoriesResponse> getCategories(
46-
@AuthenticationPrinciple MemberDto memberDto,
4748
@RequestParam Long memberId
4849
) {
49-
return ResponseEntity.ok(categoryService.findAllByMember(memberId));
50+
return ResponseEntity.ok(memberCategoryApplicationService.findAllByMember(memberId));
5051
}
5152

5253
@PutMapping("/{id}")
@@ -55,13 +56,13 @@ public ResponseEntity<Void> updateCategory(
5556
@PathVariable Long id,
5657
@Validated(ValidationSequence.class) @RequestBody UpdateCategoryRequest updateCategoryRequest
5758
) {
58-
categoryService.update(memberDto, id, updateCategoryRequest);
59+
memberCategoryApplicationService.update(memberDto, id, updateCategoryRequest);
5960
return ResponseEntity.ok().build();
6061
}
6162

6263
@DeleteMapping("/{id}")
6364
public ResponseEntity<Void> deleteCategory(@AuthenticationPrinciple MemberDto memberDto, @PathVariable Long id) {
64-
categoryService.deleteById(memberDto, id);
65+
memberCategoryTemplateApplicationService.deleteById(memberDto, id);
6566
return ResponseEntity.noContent()
6667
.build();
6768
}

backend/src/main/java/codezap/category/controller/SpringDocCategoryController.java

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public interface SpringDocCategoryController {
3030
@Header(name = "생성된 카테고리의 API 경로", example = "/categories/1")})
3131
@ApiErrorResponse(status = HttpStatus.BAD_REQUEST, instance = "/categories", errorCases = {
3232
@ErrorCase(description = "모든 필드 중 null인 값이 있는 경우", exampleMessage = "카테고리 이름이 null 입니다."),
33-
@ErrorCase(description = "카테고리 이름이 255자를 초과한 경우", exampleMessage = "카테고리 이름은 최대 255자까지 입력 가능합니다."),
33+
@ErrorCase(description = "카테고리 이름이 15자를 초과한 경우", exampleMessage = "카테고리 이름은 최대 15자까지 입력 가능합니다."),
3434
@ErrorCase(description = "동일한 이름의 카테고리가 존재하는 경우", exampleMessage = "이름이 Spring 인 카테고리가 이미 존재합니다."),
3535
})
3636
ResponseEntity<CreateCategoryResponse> createCategory(
@@ -42,20 +42,18 @@ ResponseEntity<CreateCategoryResponse> createCategory(
4242
@Operation(summary = "카테고리 목록 조회", description = "생성된 모든 카테고리를 조회합니다.")
4343
@ApiResponse(responseCode = "200", description = "조회 성공",
4444
content = {@Content(schema = @Schema(implementation = FindAllCategoriesResponse.class))})
45-
ResponseEntity<FindAllCategoriesResponse> getCategories(MemberDto memberDto, Long memberId);
45+
ResponseEntity<FindAllCategoriesResponse> getCategories(Long memberId);
4646

4747
@SecurityRequirement(name = "쿠키 인증 토큰")
4848
@Operation(summary = "카테고리 수정", description = "해당하는 식별자의 카테고리를 수정합니다.")
4949
@ApiResponse(responseCode = "200", description = "카테고리 수정 성공")
5050
@ApiErrorResponse(status = HttpStatus.BAD_REQUEST, instance = "/categories/1", errorCases = {
51-
@ErrorCase(description = "해당하는 id 값인 카테고리가 없는 경우",
52-
exampleMessage = "식별자 1에 해당하는 카테고리가 존재하지 않습니다."),
53-
@ErrorCase(description = "동일한 이름의 카테고리가 존재하는 경우",
54-
exampleMessage = "이름이 Spring 인 카테고리가 이미 존재합니다."),
51+
@ErrorCase(description = "카테고리 이름이 15자를 초과한 경우", exampleMessage = "카테고리 이름은 최대 15자까지 입력 가능합니다."),
52+
@ErrorCase(description = "해당하는 id 값인 카테고리가 없는 경우", exampleMessage = "식별자 1에 해당하는 카테고리가 존재하지 않습니다."),
53+
@ErrorCase(description = "동일한 이름의 카테고리가 존재하는 경우", exampleMessage = "이름이 Spring 인 카테고리가 이미 존재합니다."),
5554
})
5655
@ApiErrorResponse(status = HttpStatus.FORBIDDEN, instance = "/categories/1", errorCases = {
57-
@ErrorCase(description = "카테고리를 수정할 권한이 없는 경우",
58-
exampleMessage = "해당 카테고리를 수정 또는 삭제할 권한이 없는 유저입니다.")
56+
@ErrorCase(description = "카테고리를 수정할 권한이 없는 경우", exampleMessage = "해당 카테고리를 수정 또는 삭제할 권한이 없는 유저입니다.")
5957
})
6058
ResponseEntity<Void> updateCategory(MemberDto memberDto, Long id, UpdateCategoryRequest updateCategoryRequest);
6159

backend/src/main/java/codezap/category/domain/Category.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@
1212
import jakarta.persistence.Table;
1313
import jakarta.persistence.UniqueConstraint;
1414

15+
import org.springframework.http.HttpStatus;
16+
1517
import codezap.global.auditing.BaseTimeEntity;
18+
import codezap.global.exception.CodeZapException;
1619
import codezap.member.domain.Member;
1720
import lombok.AccessLevel;
1821
import lombok.AllArgsConstructor;
@@ -62,6 +65,12 @@ public void updateName(String name) {
6265
this.name = name;
6366
}
6467

68+
public void validateAuthorization(Member member) {
69+
if (!member.equals(this.member)) {
70+
throw new CodeZapException(HttpStatus.UNAUTHORIZED, "해당 카테고리에 대한 권한이 없습니다.");
71+
}
72+
}
73+
6574
@Override
6675
public boolean equals(Object o) {
6776
if (this == o) {

backend/src/main/java/codezap/category/service/CategoryService.java

Lines changed: 15 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -12,43 +12,44 @@
1212
import codezap.category.repository.CategoryRepository;
1313
import codezap.global.exception.CodeZapException;
1414
import codezap.member.domain.Member;
15-
import codezap.member.dto.MemberDto;
16-
import codezap.member.repository.MemberRepository;
17-
import codezap.template.repository.TemplateRepository;
1815
import lombok.RequiredArgsConstructor;
1916

2017
@Service
2118
@RequiredArgsConstructor
2219
public class CategoryService {
2320

2421
private final CategoryRepository categoryRepository;
25-
private final TemplateRepository templateRepository;
26-
private final MemberRepository memberRepository;
2722

28-
@Transactional
29-
public CreateCategoryResponse create(MemberDto memberDto, CreateCategoryRequest createCategoryRequest) {
23+
public CreateCategoryResponse create(Member member, CreateCategoryRequest createCategoryRequest) {
3024
String categoryName = createCategoryRequest.name();
31-
Member member = memberRepository.fetchById(memberDto.id());
3225
validateDuplicatedCategory(categoryName, member);
3326
Category category = categoryRepository.save(new Category(categoryName, member));
3427
return CreateCategoryResponse.from(category);
35-
}
28+
}
3629

37-
public FindAllCategoriesResponse findAllByMember(Long memberId) {
38-
Member member = memberRepository.fetchById(memberId);
30+
public FindAllCategoriesResponse findAllByMember(Member member) {
3931
return FindAllCategoriesResponse.from(categoryRepository.findAllByMemberOrderById(member));
4032
}
4133

4234
public FindAllCategoriesResponse findAll() {
4335
return FindAllCategoriesResponse.from(categoryRepository.findAll());
4436
}
4537

38+
public Category fetchById(Long id) {
39+
return categoryRepository.fetchById(id);
40+
}
41+
42+
public void validateExistsById(Long id) {
43+
if (!categoryRepository.existsById(id)) {
44+
throw new CodeZapException(HttpStatus.NOT_FOUND, "식별자 " + id + "에 해당하는 카테고리가 존재하지 않습니다.");
45+
}
46+
}
47+
4648
@Transactional
47-
public void update(MemberDto memberDto, Long id, UpdateCategoryRequest updateCategoryRequest) {
48-
Member member = memberRepository.fetchById(memberDto.id());
49+
public void update(Member member, Long id, UpdateCategoryRequest updateCategoryRequest) {
4950
validateDuplicatedCategory(updateCategoryRequest.name(), member);
5051
Category category = categoryRepository.fetchById(id);
51-
validateAuthorizeMember(category, member);
52+
category.validateAuthorization(member);
5253
category.updateName(updateCategoryRequest.name());
5354
}
5455

@@ -57,24 +58,4 @@ private void validateDuplicatedCategory(String categoryName, Member member) {
5758
throw new CodeZapException(HttpStatus.CONFLICT, "이름이 " + categoryName + "인 카테고리가 이미 존재합니다.");
5859
}
5960
}
60-
61-
public void deleteById(MemberDto memberDto, Long id) {
62-
Category category = categoryRepository.fetchById(id);
63-
Member member = memberRepository.fetchById(memberDto.id());
64-
validateAuthorizeMember(category, member);
65-
66-
if (templateRepository.existsByCategoryId(id)) {
67-
throw new CodeZapException(HttpStatus.BAD_REQUEST, "템플릿이 존재하는 카테고리는 삭제할 수 없습니다.");
68-
}
69-
if (category.getIsDefault()) {
70-
throw new CodeZapException(HttpStatus.BAD_REQUEST, "기본 카테고리는 삭제할 수 없습니다.");
71-
}
72-
categoryRepository.deleteById(id);
73-
}
74-
75-
private void validateAuthorizeMember(Category category, Member member) {
76-
if (!category.getMember().equals(member)) {
77-
throw new CodeZapException(HttpStatus.FORBIDDEN, "해당 카테고리를 수정 또는 삭제할 권한이 없는 유저입니다.");
78-
}
79-
}
8061
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package codezap.category.service;
2+
3+
import org.springframework.http.HttpStatus;
4+
import org.springframework.stereotype.Service;
5+
import org.springframework.transaction.annotation.Transactional;
6+
7+
import codezap.category.domain.Category;
8+
import codezap.category.repository.CategoryRepository;
9+
import codezap.global.exception.CodeZapException;
10+
import codezap.member.domain.Member;
11+
import codezap.template.repository.TemplateRepository;
12+
import lombok.RequiredArgsConstructor;
13+
14+
@Service
15+
@RequiredArgsConstructor
16+
public class CategoryTemplateService {
17+
18+
private final CategoryRepository categoryRepository;
19+
private final TemplateRepository templateRepository;
20+
21+
@Transactional
22+
public void deleteById(Member member, Long id) {
23+
Category category = categoryRepository.fetchById(id);
24+
validateAuthorizeMember(category, member);
25+
26+
if (templateRepository.existsByCategoryId(id)) {
27+
throw new CodeZapException(HttpStatus.BAD_REQUEST, "템플릿이 존재하는 카테고리는 삭제할 수 없습니다.");
28+
}
29+
if (category.getIsDefault()) {
30+
throw new CodeZapException(HttpStatus.BAD_REQUEST, "기본 카테고리는 삭제할 수 없습니다.");
31+
}
32+
categoryRepository.deleteById(id);
33+
}
34+
35+
private void validateAuthorizeMember(Category category, Member member) {
36+
if (!category.getMember().equals(member)) {
37+
throw new CodeZapException(HttpStatus.FORBIDDEN, "해당 카테고리를 수정 또는 삭제할 권한이 없는 유저입니다.");
38+
}
39+
}
40+
}

0 commit comments

Comments
 (0)