Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
9b15a18
fix(community): CommunityComment 엔티티 및 Dto에 communityBoardId 추가
ayoung-dev Nov 29, 2024
cc82066
feat(community): CommunityBoardRepository에 existsById 추가 및 검증 테스트 추가
ayoung-dev Nov 29, 2024
0f63ec6
feat(community): CommunityComment 생성 시 게시글 검증 로직 추가
ayoung-dev Nov 29, 2024
b7b0d9d
test(community): CommunityComment 생성 시 게시글 검증 테스트 추가
ayoung-dev Nov 29, 2024
5af09e9
test(community): CommunityCommentRepositoryTest 수정
ayoung-dev Nov 29, 2024
3b6552f
test(community): 불필요한 import 및 변수 삭제
ayoung-dev Nov 29, 2024
ff886b7
Feature/75 관심기관 등록, 취소 기능 구현 (#85)
7zrv Nov 29, 2024
c339f4f
cicd: workflow 환경변수 추가 (#90)
7zrv Nov 30, 2024
4e00263
cicd: workflow 환경변수 추가 (#92)
7zrv Nov 30, 2024
c5ea384
feat: 스웨거 API 테스트를 위한 봉사자 / 기관 토큰 발급 (#91)
leebs0521 Nov 30, 2024
511c89d
hotfix: fix typo (#94)
leebs0521 Nov 30, 2024
5350e83
fix(community): CommunityComment 엔티티 및 Dto에 communityBoardId 추가
ayoung-dev Nov 29, 2024
aefe88e
feat(community): CommunityBoardRepository에 existsById 추가 및 검증 테스트 추가
ayoung-dev Nov 29, 2024
58b731e
feat(community): CommunityComment 생성 시 게시글 검증 로직 추가
ayoung-dev Nov 29, 2024
139c454
test(community): CommunityComment 생성 시 게시글 검증 테스트 추가
ayoung-dev Nov 29, 2024
1e53d65
test(community): CommunityCommentRepositoryTest 수정
ayoung-dev Nov 29, 2024
53576ef
test(community): 불필요한 import 및 변수 삭제
ayoung-dev Nov 29, 2024
1412311
refactor(community): 코드 리뷰 사항 반영
ayoung-dev Nov 30, 2024
7e4f4c4
Merge remote-tracking branch 'origin/bug/80-modify-community-comment-…
ayoung-dev Nov 30, 2024
6f73258
test(community): 변수명 변경
ayoung-dev Nov 30, 2024
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
18 changes: 10 additions & 8 deletions .github/workflows/CD.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,17 @@ jobs:
NAVER_CLIENT_ID: ${{ secrets.NAVER_CLIENT_ID }}
NAVER_CLIENT_SECRET: ${{ secrets.NAVER_CLIENT_SECRET }}
NAVER_SCOPE: ${{ secrets.NAVER_SCOPE }}
NAVER_REDIRECT_URL: ${{secrets.NAVER_REDIRECT_URL}}
NAVER_REDIRECT_URL: ${{ secrets.NAVER_REDIRECT_URL }}
JWT_SECRET: ${{ secrets.JWT_SECRET }}
FRONT_URL: ${{secrets.FRONT_URL}}
BACK_URL: ${{secrets.BACK_URL}}
BUCKET_NAME: ${{secrets.BUCKET_NAME}}
BUCKET_REGION: ${{secrets.BUCKET_REGION}}
IMG_BASE_URL: ${{secrets.BASE_URL}}
S3_ACCESS_KEY: ${{secrets.S3_ACCESS_KEY}}
S3_SECRET_KEY: ${{secrets.S3_SECRET_KEY}}
FRONT_URL: ${{ secrets.FRONT_URL }}
BACK_URL: ${{ secrets.BACK_URL }}
BUCKET_NAME: ${{ secrets.BUCKET_NAME }}
BUCKET_REGION: ${{ secrets.BUCKET_REGION }}
IMG_BASE_URL: ${{ secrets.BASE_URL }}
S3_ACCESS_KEY: ${{ secrets.S3_ACCESS_KEY }}
S3_SECRET_KEY: ${{ secrets.S3_SECRET_KEY }}
DEFAULT_IMG_URL: ${{ secrets.DEFAULT_IMG_URL }}
APP_DEVELOP_MODE: ${{ secrets.APP_DEVELOP_MODE }}

steps:
- name: Github Repository 파일 불러오기
Expand Down
18 changes: 10 additions & 8 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,17 @@ jobs:
NAVER_CLIENT_ID: ${{ secrets.NAVER_CLIENT_ID }}
NAVER_CLIENT_SECRET: ${{ secrets.NAVER_CLIENT_SECRET }}
NAVER_SCOPE: ${{ secrets.NAVER_SCOPE }}
NAVER_REDIRECT_URL: ${{secrets.NAVER_REDIRECT_URL}}
NAVER_REDIRECT_URL: ${{ secrets.NAVER_REDIRECT_URL }}
JWT_SECRET: ${{ secrets.JWT_SECRET }}
FRONT_URL: ${{secrets.FRONT_URL}}
BACK_URL: ${{secrets.BACK_URL}}
BUCKET_NAME: ${{secrets.BUCKET_NAME}}
BUCKET_REGION: ${{secrets.BUCKET_REGION}}
IMG_BASE_URL: ${{secrets.BASE_URL}}
S3_ACCESS_KEY: ${{secrets.S3_ACCESS_KEY}}
S3_SECRET_KEY: ${{secrets.S3_SECRET_KEY}}
FRONT_URL: ${{ secrets.FRONT_URL }}
BACK_URL: ${{ secrets.BACK_URL }}
BUCKET_NAME: ${{ secrets.BUCKET_NAME }}
BUCKET_REGION: ${{ secrets.BUCKET_REGION }}
IMG_BASE_URL: ${{ secrets.BASE_URL }}
S3_ACCESS_KEY: ${{ secrets.S3_ACCESS_KEY }}
S3_SECRET_KEY: ${{ secrets.S3_SECRET_KEY }}
DEFAULT_IMG_URL: ${{ secrets.DEFAULT_IMG_URL }}
APP_DEVELOP_MODE: ${{ secrets.APP_DEVELOP_MODE }}


steps:
Expand Down
22 changes: 13 additions & 9 deletions src/main/java/com/somemore/auth/jwt/filter/JwtAuthFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
Expand All @@ -17,9 +19,6 @@
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.List;

@RequiredArgsConstructor
@Slf4j
@Component
Expand All @@ -29,12 +28,13 @@ public class JwtAuthFilter extends OncePerRequestFilter {

@Override
protected boolean shouldNotFilter(HttpServletRequest request) {
return true; // 개발 중 모든 요청 허용
// return httpServletRequest.getRequestURI().contains("token");
String token = request.getHeader("Authorization");
return token == null || token.isEmpty();
}

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
EncodedToken accessToken = getAccessToken(request);
jwtUseCase.processAccessToken(accessToken, response);

Expand All @@ -47,15 +47,19 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse

private EncodedToken getAccessToken(HttpServletRequest request) {
String accessToken = request.getHeader("Authorization");
if (accessToken == null || accessToken.isEmpty()) {
if (!accessToken.startsWith("Bearer ")) {
throw new JwtException(JwtErrorType.MISSING_TOKEN);
}

accessToken = accessToken.substring(7);

return new EncodedToken(accessToken);
}

private JwtAuthenticationToken createAuthenticationToken(Claims claims, EncodedToken accessToken) {
private JwtAuthenticationToken createAuthenticationToken(Claims claims,
EncodedToken accessToken) {
String userId = claims.get("id", String.class);
UserRole role = claims.get("role", UserRole.class);
UserRole role = UserRole.valueOf(claims.get("role", String.class));

return new JwtAuthenticationToken(
userId,
Expand Down
99 changes: 99 additions & 0 deletions src/main/java/com/somemore/auth/util/DevAccountSetUpConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package com.somemore.auth.util;

import static com.somemore.auth.oauth.OAuthProvider.NAVER;

import com.somemore.auth.jwt.domain.EncodedToken;
import com.somemore.auth.jwt.domain.TokenType;
import com.somemore.auth.jwt.domain.UserRole;
import com.somemore.auth.jwt.generator.JwtGenerator;
import com.somemore.auth.jwt.refresh.domain.RefreshToken;
import com.somemore.auth.jwt.refresh.manager.RefreshTokenManager;
import com.somemore.center.domain.Center;
import com.somemore.center.repository.CenterJpaRepository;
import com.somemore.volunteer.domain.Volunteer;
import com.somemore.volunteer.repository.VolunteerJpaRepository;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Slf4j
@RequiredArgsConstructor
@Component
public class DevAccountSetUpConfig {

private final VolunteerJpaRepository volunteerRepository;
private final CenterJpaRepository centerRepository;
private final JwtGenerator jwtGenerator;
private final RefreshTokenManager refreshTokenManager;

private Volunteer volunteer;
private Center center;

@Value("${app.develop.mode}")
private boolean developMode;

@PostConstruct
public void generateAccessTokenForDev() {
if (!developMode) {
return; // 개발 모드에서만 실행
}

volunteer = Volunteer.createDefault(NAVER, "bongdari");
center = Center.create(
"봉다리 자원봉사센터",
"02-1234-5678",
"",
"봉다리 기관 테스트 계정입니다.",
"https://somemore.bongdari.com",
"bongdari",
"1234"
);

volunteer = volunteerRepository.findByOauthId(volunteer.getOauthId())
.orElseGet(() -> volunteerRepository.save(volunteer));

center = centerRepository.findByName(center.getName())
.orElseGet(() -> centerRepository.save(center));

EncodedToken volunteerToken = saveRefreshTokenAndReturnAccessToken(volunteer.getId(),
UserRole.VOLUNTEER);
EncodedToken centerToken = saveRefreshTokenAndReturnAccessToken(center.getId(),
UserRole.CENTER);

log.info("테스트용 봉사자 AccessToken: {}", volunteerToken.value());
log.info("테스트용 기관 AccessToken: {}", centerToken.value());
}

@PreDestroy
public void cleanup() {
if (volunteer != null) {
refreshTokenManager.removeRefreshToken(volunteer.getId().toString());
log.info("테스트용 AccessToken 제거, 봉사자 ID: {}", volunteer.getId());
}
if (center != null) {
refreshTokenManager.removeRefreshToken(center.getId().toString());
log.info("테스트용 AccessToken 제거, 기관 ID: {}", center.getId());
}
}

private EncodedToken saveRefreshTokenAndReturnAccessToken(UUID id, UserRole role) {
EncodedToken accessToken = generateToken(id, role, TokenType.ACCESS);
RefreshToken refreshToken = generateRefreshToken(id, role, accessToken);
refreshTokenManager.save(refreshToken);
return accessToken;
}

private EncodedToken generateToken(UUID id, UserRole role, TokenType tokenType) {
return jwtGenerator.generateToken(id.toString(), role.name(), tokenType);
}

private RefreshToken generateRefreshToken(UUID id, UserRole role, EncodedToken accessToken) {
return new RefreshToken(id.toString(), accessToken,
generateToken(id, role, TokenType.REFRESH));
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@
public interface CenterJpaRepository extends JpaRepository<Center, Long> {
boolean existsById(UUID id);
Optional<Center> findCenterById(UUID id);
Optional<Center> findByName(String name);
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ public class CommunityComment extends BaseEntity {
@Column(name = "id", nullable = false)
private Long id;

@Column(name = "community_board_id", nullable = false)
private Long communityBoardId;

@Column(name = "writer_id", nullable = false, length = 16)
private UUID writerId;

Expand All @@ -33,7 +36,8 @@ public class CommunityComment extends BaseEntity {
private Long parentCommentId;

@Builder
public CommunityComment(UUID writerId, String content, Long parentCommentId) {
public CommunityComment(Long communityBoardId, UUID writerId, String content, Long parentCommentId) {
this.communityBoardId = communityBoardId;
this.writerId = writerId;
this.content = content;
this.parentCommentId = parentCommentId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,27 @@
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.annotation.Nullable;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Builder;

import java.util.UUID;

@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
@Builder
public record CommunityCommentCreateRequestDto(
@Schema(description = "커뮤니티 게시글 ID", example = "33")
@NotNull(message = "게시글 ID는 필수 값입니다.")
Long communityBoardId,
@Schema(description = "커뮤니티 댓글 내용", example = "저도 함께 하고 싶습니다.")
@NotBlank(message = "댓글 내용은 필수 값입니다.")
String content,
@Schema(description = "부모 댓글의 ID", example = "1234", nullable = true)
@Schema(description = "부모 댓글 ID", example = "1234", nullable = true)
@Nullable
Long parentCommentId
) {
public CommunityComment toEntity(UUID writerId) {
return CommunityComment.builder()
.communityBoardId(communityBoardId)
.writerId(writerId)
.content(content)
.parentCommentId(parentCommentId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
import org.springframework.data.jpa.repository.JpaRepository;

public interface CommunityBoardJpaRepository extends JpaRepository<CommunityBoard, Long> {
boolean existsByIdAndDeletedFalse(Long id);
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,9 @@ public interface CommunityBoardRepository {
Optional<CommunityBoard> findById(Long id);
List<CommunityBoardView> getCommunityBoards();
List<CommunityBoardView> findByWriterId(UUID writerId);
boolean existsById(Long id);
default boolean doesNotExistById(Long id) {
return !existsById(id);
}
Comment on lines +16 to +18
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 메서드가 필요할까요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

서진님 코드에서 멋져 보여서 저도 따라해봤습니다 ㅎ

Copy link
Collaborator Author

@ayoung-dev ayoung-dev Nov 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저는 !를 쓰지 않으려고 만든다고 생각했습니다..!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵 참고하겠습니다!

void deleteAllInBatch();
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ public List<CommunityBoardView> findByWriterId(UUID writerId) {
.fetch();
}

@Override
public boolean existsById(Long id) {
return communityBoardJpaRepository.existsByIdAndDeletedFalse(id);
}

private JPAQuery<CommunityBoardView> getCommunityBoardsQuery() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이건 이번 변경사항은 아닌데 repo에 find로 맞추기로 하지 않았는지 여쭤보고 싶습니다!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

안그래도 저도 다시 수정하면서 거슬렸는데
board의 controller 만들면서 같이 수정하려고 놔뒀습니다!
그떄 같이 수정할게욤

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵 !

QCommunityBoard communityBoard = QCommunityBoard.communityBoard;
QVolunteer volunteer = QVolunteer.volunteer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,8 @@ public interface CommunityCommentRepository {
CommunityComment save(CommunityComment communityComment);
Optional<CommunityComment> findById(Long id);
boolean existsById(Long id);
default boolean doesNotExistById(Long id) {
return !existsById(id);
}
void deleteAllInBatch();
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.somemore.community.domain.CommunityComment;
import com.somemore.community.dto.request.CommunityCommentCreateRequestDto;
import com.somemore.community.repository.board.CommunityBoardRepository;
import com.somemore.community.repository.comment.CommunityCommentRepository;
import com.somemore.community.usecase.comment.CreateCommunityCommentUseCase;
import com.somemore.global.exception.BadRequestException;
Expand All @@ -11,26 +12,38 @@

import java.util.UUID;

import static com.somemore.global.exception.ExceptionMessage.NOT_EXISTS_COMMUNITY_BOARD;
import static com.somemore.global.exception.ExceptionMessage.NOT_EXISTS_COMMUNITY_COMMENT;

@RequiredArgsConstructor
@Transactional
@Service
public class CreateCommunityCommentService implements CreateCommunityCommentUseCase {

private final CommunityBoardRepository communityBoardRepository;
private final CommunityCommentRepository communityCommentRepository;

@Override
public Long createCommunityComment(CommunityCommentCreateRequestDto requestDto, UUID writerId) {
CommunityComment communityComment = requestDto.toEntity(writerId);

validateParentCommentExists(communityComment.getParentCommentId());
validateCommunityBoardExists(communityComment.getCommunityBoardId());

if (requestDto.parentCommentId() != null) {
validateParentCommentExists(communityComment.getParentCommentId());
}

return communityCommentRepository.save(communityComment).getId();
}

private void validateCommunityBoardExists(Long communityBoardId) {
if (communityBoardRepository.doesNotExistById(communityBoardId)) {
throw new BadRequestException(NOT_EXISTS_COMMUNITY_BOARD.getMessage());
}
}
Comment on lines +39 to +43
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이전에는 early return 으로 해결하시지 않으셨는지, 변경하게 된 의도도 여쭤보고 싶습니다!

Copy link
Collaborator Author

@ayoung-dev ayoung-dev Nov 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아 지난번에는 validator가 아니고 리턴 값이 있었는데
이번에는 void라 validate 부분은 이렇게 하게 되었습니다!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

감사합니다. 이해했습니다. 저는 반환값이 없는 return을 적어두는 편이라서 여쭤보고 싶었습니다 ㅎㅎ


private void validateParentCommentExists(Long parentCommentId) {
if (parentCommentId != null && !communityCommentRepository.existsById(parentCommentId)) {
if (communityCommentRepository.doesNotExistById(parentCommentId)) {
throw new BadRequestException(NOT_EXISTS_COMMUNITY_COMMENT.getMessage());
}
}
Expand Down
18 changes: 0 additions & 18 deletions src/main/java/com/somemore/domains/InterestCenter.java

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,10 @@ public static <T> ApiResponse<T> ok(int status, T data, String message) {
return new ApiResponse<>(status, message, data);
}

public static ApiResponse<?> ok(String message) {
public static ApiResponse<String> ok(String message) {
return new ApiResponse<>(200, message, "");
}

public static ApiResponse<?> error(int code, String message) {
return new ApiResponse<>(code, message, "");
}

public ApiResponse(int code, String message, T data) {
this.code = code;
this.message = message;
Expand Down
Loading