diff --git a/src/main/java/com/friends/easybud/auth/controller/AuthController.java b/src/main/java/com/friends/easybud/auth/controller/AuthController.java index 9cac29a..68943f3 100644 --- a/src/main/java/com/friends/easybud/auth/controller/AuthController.java +++ b/src/main/java/com/friends/easybud/auth/controller/AuthController.java @@ -3,6 +3,7 @@ import com.friends.easybud.auth.dto.IdTokenRequest; import com.friends.easybud.auth.dto.RefreshTokenRequest; import com.friends.easybud.auth.service.AuthService; +import com.friends.easybud.global.annotation.AuthUser; import com.friends.easybud.global.response.ResponseDto; import com.friends.easybud.jwt.JwtDto; import com.friends.easybud.jwt.JwtProvider; @@ -50,7 +51,7 @@ public ResponseDto logout(@RequestBody RefreshTokenRequest request) { @Operation(summary = "회원 탈퇴", description = "회원 탈퇴를 진행합니다.") @PostMapping("/withdrawal") - public ResponseDto withdrawal(@RequestBody Member member) { + public ResponseDto withdrawal(@AuthUser Member member) { return ResponseDto.onSuccess(memberCommandService.withdrawal(member)); } diff --git a/src/main/java/com/friends/easybud/card/controller/CardController.java b/src/main/java/com/friends/easybud/card/controller/CardController.java index d7fbcf8..9dea68a 100644 --- a/src/main/java/com/friends/easybud/card/controller/CardController.java +++ b/src/main/java/com/friends/easybud/card/controller/CardController.java @@ -7,7 +7,9 @@ import com.friends.easybud.card.dto.CardResponse.CardListDto; import com.friends.easybud.card.service.CardCommandService; import com.friends.easybud.card.service.CardQueryService; +import com.friends.easybud.global.annotation.AuthUser; import com.friends.easybud.global.response.ResponseDto; +import com.friends.easybud.member.domain.Member; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; @@ -31,32 +33,33 @@ public class CardController { @Operation(summary = "카드 생성", description = "새로운 카드를 생성합니다.") @PostMapping - public ResponseDto createCard(@RequestBody CardCreateDto request) { - return ResponseDto.onSuccess(cardCommandService.createCard(request)); + public ResponseDto createCard(@AuthUser Member member, @RequestBody CardCreateDto request) { + return ResponseDto.onSuccess(cardCommandService.createCard(member, request)); } @Operation(summary = "카드 삭제", description = "기존의 카드를 삭제합니다.") @DeleteMapping("/{cardId}") - public ResponseDto deleteCard(@PathVariable Long cardId) { - return ResponseDto.onSuccess(cardCommandService.deleteCard(cardId)); + public ResponseDto deleteCard(@AuthUser Member member, @PathVariable Long cardId) { + return ResponseDto.onSuccess(cardCommandService.deleteCard(member, cardId)); } @Operation(summary = "카드 수정", description = "기존의 카드를 수정합니다.") @PutMapping("/{cardId}") - public ResponseDto updateCard(@PathVariable Long cardId, @RequestBody CardUpdateDto request) { - return ResponseDto.onSuccess(cardCommandService.updateCard(cardId, request)); + public ResponseDto updateCard(@AuthUser Member member, @PathVariable Long cardId, + @RequestBody CardUpdateDto request) { + return ResponseDto.onSuccess(cardCommandService.updateCard(member, cardId, request)); } @Operation(summary = "카드 조회", description = "특정 카드를 조회합니다.") @GetMapping("/{cardId}") - public ResponseDto getCard(@PathVariable Long cardId) { - return ResponseDto.onSuccess(CardConverter.toCardDto(cardQueryService.getCard(cardId))); + public ResponseDto getCard(@AuthUser Member member, @PathVariable Long cardId) { + return ResponseDto.onSuccess(CardConverter.toCardDto(cardQueryService.getCard(member, cardId))); } @Operation(summary = "카드 목록 조회", description = "특정 회원의 카드 목록을 조회합니다.") @GetMapping - public ResponseDto getCards() { - return ResponseDto.onSuccess(CardConverter.toCardListDto(cardQueryService.getCards())); + public ResponseDto getCards(@AuthUser Member member) { + return ResponseDto.onSuccess(CardConverter.toCardListDto(cardQueryService.getCards(member))); } } diff --git a/src/main/java/com/friends/easybud/card/service/CardCommandService.java b/src/main/java/com/friends/easybud/card/service/CardCommandService.java index 9806f88..d26cecb 100644 --- a/src/main/java/com/friends/easybud/card/service/CardCommandService.java +++ b/src/main/java/com/friends/easybud/card/service/CardCommandService.java @@ -2,13 +2,14 @@ import com.friends.easybud.card.dto.CardRequest.CardCreateDto; import com.friends.easybud.card.dto.CardRequest.CardUpdateDto; +import com.friends.easybud.member.domain.Member; public interface CardCommandService { - Long createCard(CardCreateDto request); + Long createCard(Member member, CardCreateDto request); - Long updateCard(Long cardId, CardUpdateDto request); + Long updateCard(Member member, Long cardId, CardUpdateDto request); - Boolean deleteCard(Long cardId); + Boolean deleteCard(Member member, Long cardId); } diff --git a/src/main/java/com/friends/easybud/card/service/CardCommandServiceImpl.java b/src/main/java/com/friends/easybud/card/service/CardCommandServiceImpl.java index d80cba3..5af4fb9 100644 --- a/src/main/java/com/friends/easybud/card/service/CardCommandServiceImpl.java +++ b/src/main/java/com/friends/easybud/card/service/CardCommandServiceImpl.java @@ -8,7 +8,6 @@ import com.friends.easybud.global.exception.GeneralException; import com.friends.easybud.global.response.code.ErrorStatus; import com.friends.easybud.member.domain.Member; -import com.friends.easybud.member.repository.MemberRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -18,13 +17,10 @@ @Service public class CardCommandServiceImpl implements CardCommandService { - private final MemberRepository memberRepository; // TODO MemberQueryService 주입 private final CardRepository cardRepository; @Override - public Long createCard(CardCreateDto request) { - Member member = memberRepository.findById(1L).get(); // TODO 로그인 된 사용자 정보 조회 - + public Long createCard(Member member, CardCreateDto request) { Card card = buildCard(request, member); cardRepository.save(card); @@ -42,22 +38,33 @@ private Card buildCard(CardRequest.CardCreateDto request, Member member) { } @Override - public Long updateCard(Long cardId, CardUpdateDto request) { + public Long updateCard(Member member, Long cardId, CardUpdateDto request) { Card card = cardRepository.findById(cardId) .orElseThrow(() -> new GeneralException(ErrorStatus.CARD_NOT_FOUND)); + checkCardOwnership(member, card); + card.update(request); return card.getId(); } @Override - public Boolean deleteCard(Long cardId) { + public Boolean deleteCard(Member member, Long cardId) { Card card = cardRepository.findById(cardId) .orElseThrow(() -> new GeneralException(ErrorStatus.CARD_NOT_FOUND)); + + checkCardOwnership(member, card); + // TODO 연관된 Account 처리 cardRepository.delete(card); return Boolean.TRUE; } + private void checkCardOwnership(Member member, Card card) { + if (!card.getMember().equals(member)) { + throw new GeneralException(ErrorStatus.UNAUTHORIZED_CARD_ACCESS); + } + } + } diff --git a/src/main/java/com/friends/easybud/card/service/CardQueryService.java b/src/main/java/com/friends/easybud/card/service/CardQueryService.java index 6500b85..331d72e 100644 --- a/src/main/java/com/friends/easybud/card/service/CardQueryService.java +++ b/src/main/java/com/friends/easybud/card/service/CardQueryService.java @@ -1,12 +1,13 @@ package com.friends.easybud.card.service; import com.friends.easybud.card.domain.Card; +import com.friends.easybud.member.domain.Member; import java.util.List; public interface CardQueryService { - Card getCard(Long cardId); + Card getCard(Member member, Long cardId); - List getCards(); + List getCards(Member member); } diff --git a/src/main/java/com/friends/easybud/card/service/CardQueryServiceImpl.java b/src/main/java/com/friends/easybud/card/service/CardQueryServiceImpl.java index faded58..ec65653 100644 --- a/src/main/java/com/friends/easybud/card/service/CardQueryServiceImpl.java +++ b/src/main/java/com/friends/easybud/card/service/CardQueryServiceImpl.java @@ -5,7 +5,6 @@ import com.friends.easybud.global.exception.GeneralException; import com.friends.easybud.global.response.code.ErrorStatus; import com.friends.easybud.member.domain.Member; -import com.friends.easybud.member.repository.MemberRepository; import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -16,18 +15,16 @@ @Service public class CardQueryServiceImpl implements CardQueryService { - private final MemberRepository memberRepository; // TODO MemberQueryService 주입 private final CardRepository cardRepository; @Override - public Card getCard(Long cardId) { + public Card getCard(Member member, Long cardId) { return cardRepository.findById(cardId) .orElseThrow(() -> new GeneralException(ErrorStatus.CARD_NOT_FOUND)); } @Override - public List getCards() { - Member member = memberRepository.findById(1L).get(); // TODO 로그인 된 사용자 정보 조회 + public List getCards(Member member) { return member.getCards(); } diff --git a/src/main/java/com/friends/easybud/category/controller/CategoryController.java b/src/main/java/com/friends/easybud/category/controller/CategoryController.java index cee668b..0eb3710 100644 --- a/src/main/java/com/friends/easybud/category/controller/CategoryController.java +++ b/src/main/java/com/friends/easybud/category/controller/CategoryController.java @@ -6,7 +6,9 @@ import com.friends.easybud.category.dto.CategoryRequest.TertiaryCategoryCreateDto; import com.friends.easybud.category.service.CategoryCommandService; import com.friends.easybud.category.service.CategoryQueryService; +import com.friends.easybud.global.annotation.AuthUser; import com.friends.easybud.global.response.ResponseDto; +import com.friends.easybud.member.domain.Member; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -30,22 +32,23 @@ public class CategoryController { @Operation(summary = "계정 소분류 생성", description = "새로운 소분류를 생성합니다.") @PostMapping("/tertiary") - public ResponseDto createTertiaryCategory(@RequestBody TertiaryCategoryCreateDto request) { - return ResponseDto.onSuccess(categoryCommandService.createTertiaryCategory(request)); + public ResponseDto createTertiaryCategory(@AuthUser Member member, + @RequestBody TertiaryCategoryCreateDto request) { + return ResponseDto.onSuccess(categoryCommandService.createTertiaryCategory(member, request)); } @Operation(summary = "계정 소분류 삭제", description = "기존의 소분류를 삭제합니다.") @Parameter(name = "tertiaryCategoryId", description = "삭제할 소분류의 ID") @DeleteMapping("/tertiary/{tertiaryCategoryId}") - public ResponseDto deleteTertiaryCategory(@PathVariable Long tertiaryCategoryId) { - return ResponseDto.onSuccess(categoryCommandService.deleteTertiaryCategory(tertiaryCategoryId)); + public ResponseDto deleteTertiaryCategory(@AuthUser Member member, @PathVariable Long tertiaryCategoryId) { + return ResponseDto.onSuccess(categoryCommandService.deleteTertiaryCategory(member, tertiaryCategoryId)); } @Operation(summary = "계정 카테고리 목록 조회", description = "로그인 된 회원의 계정 카테고리 목록을 조회합니다.") @GetMapping - public ResponseDto getAccountCategories() { + public ResponseDto getAccountCategories(@AuthUser Member member) { return ResponseDto.onSuccess( - CategoryConverter.toAccountCategoryListDto(categoryQueryService.getTertiaryCategories(1L))); + CategoryConverter.toAccountCategoryListDto(categoryQueryService.getTertiaryCategories(member))); } } diff --git a/src/main/java/com/friends/easybud/category/service/CategoryCommandService.java b/src/main/java/com/friends/easybud/category/service/CategoryCommandService.java index 660b025..c682f6f 100644 --- a/src/main/java/com/friends/easybud/category/service/CategoryCommandService.java +++ b/src/main/java/com/friends/easybud/category/service/CategoryCommandService.java @@ -2,10 +2,12 @@ import static com.friends.easybud.category.dto.CategoryRequest.TertiaryCategoryCreateDto; +import com.friends.easybud.member.domain.Member; + public interface CategoryCommandService { - Long createTertiaryCategory(TertiaryCategoryCreateDto request); + Long createTertiaryCategory(Member member, TertiaryCategoryCreateDto request); - Boolean deleteTertiaryCategory(Long accountCategoryId); + Boolean deleteTertiaryCategory(Member member, Long accountCategoryId); } diff --git a/src/main/java/com/friends/easybud/category/service/CategoryCommandServiceImpl.java b/src/main/java/com/friends/easybud/category/service/CategoryCommandServiceImpl.java index 0b4ae4a..f90e9e4 100644 --- a/src/main/java/com/friends/easybud/category/service/CategoryCommandServiceImpl.java +++ b/src/main/java/com/friends/easybud/category/service/CategoryCommandServiceImpl.java @@ -10,7 +10,6 @@ import com.friends.easybud.global.exception.GeneralException; import com.friends.easybud.global.response.code.ErrorStatus; import com.friends.easybud.member.domain.Member; -import com.friends.easybud.member.repository.MemberRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -23,11 +22,9 @@ public class CategoryCommandServiceImpl implements CategoryCommandService { private final SecondaryCategoryRepository secondaryCategoryRepository; private final TertiaryCategoryRepository tertiaryCategoryRepository; private final TertiaryCategoryCustomRepository tertiaryCategoryCustomRepository; - private final MemberRepository memberRepository; // TODO MemberQueryService 주입 @Override - public Long createTertiaryCategory(TertiaryCategoryCreateDto request) { - Member member = memberRepository.findById(1L).get(); // TODO 로그인 된 사용자 정보 조회 + public Long createTertiaryCategory(Member member, TertiaryCategoryCreateDto request) { SecondaryCategory secondaryCategory = secondaryCategoryRepository.findByContent(request.getSecondaryCategory()) .orElseThrow(() -> new GeneralException(ErrorStatus.SECONDARY_CATEGORY_NOT_FOUND)); @@ -61,10 +58,12 @@ private TertiaryCategory buildTertiaryCategory(TertiaryCategoryCreateDto request } @Override - public Boolean deleteTertiaryCategory(Long tertiaryCategoryId) { + public Boolean deleteTertiaryCategory(Member member, Long tertiaryCategoryId) { TertiaryCategory tertiaryCategory = tertiaryCategoryRepository.findById(tertiaryCategoryId) .orElseThrow(() -> new GeneralException(ErrorStatus.TERTIARY_CATEGORY_NOT_FOUND)); + checkTertiaryCategoryOwnership(member, tertiaryCategory); + if (tertiaryCategory.getIsDefault().equals(Boolean.TRUE)) { throw new GeneralException(ErrorStatus.CANNOT_DELETE_DEFAULT_CATEGORY); } @@ -73,4 +72,10 @@ public Boolean deleteTertiaryCategory(Long tertiaryCategoryId) { return Boolean.TRUE; } + private void checkTertiaryCategoryOwnership(Member member, TertiaryCategory tertiaryCategory) { + if (!tertiaryCategory.getMember().equals(member)) { + throw new GeneralException(ErrorStatus.UNAUTHORIZED_TERTIARY_CATEGORY_ACCESS); + } + } + } \ No newline at end of file diff --git a/src/main/java/com/friends/easybud/category/service/CategoryQueryService.java b/src/main/java/com/friends/easybud/category/service/CategoryQueryService.java index 30fc890..dd38f00 100644 --- a/src/main/java/com/friends/easybud/category/service/CategoryQueryService.java +++ b/src/main/java/com/friends/easybud/category/service/CategoryQueryService.java @@ -1,10 +1,11 @@ package com.friends.easybud.category.service; import com.friends.easybud.category.domain.TertiaryCategory; +import com.friends.easybud.member.domain.Member; import java.util.List; public interface CategoryQueryService { - List getTertiaryCategories(Long memberId); + List getTertiaryCategories(Member member); } diff --git a/src/main/java/com/friends/easybud/category/service/CategoryQueryServiceImpl.java b/src/main/java/com/friends/easybud/category/service/CategoryQueryServiceImpl.java index 239f073..d7002f5 100644 --- a/src/main/java/com/friends/easybud/category/service/CategoryQueryServiceImpl.java +++ b/src/main/java/com/friends/easybud/category/service/CategoryQueryServiceImpl.java @@ -2,6 +2,7 @@ import com.friends.easybud.category.domain.TertiaryCategory; import com.friends.easybud.category.repository.TertiaryCategoryRepository; +import com.friends.easybud.member.domain.Member; import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -15,8 +16,8 @@ public class CategoryQueryServiceImpl implements CategoryQueryService { private final TertiaryCategoryRepository tertiaryCategoryRepository; @Override - public List getTertiaryCategories(Long memberId) { - return tertiaryCategoryRepository.findByMemberIdOrIsDefaultTrue(memberId); + public List getTertiaryCategories(Member member) { + return tertiaryCategoryRepository.findByMemberIdOrIsDefaultTrue(member.getId()); } } diff --git a/src/main/java/com/friends/easybud/financial/controller/FinancialController.java b/src/main/java/com/friends/easybud/financial/controller/FinancialController.java index 021eda5..55bfeb9 100644 --- a/src/main/java/com/friends/easybud/financial/controller/FinancialController.java +++ b/src/main/java/com/friends/easybud/financial/controller/FinancialController.java @@ -8,7 +8,9 @@ import com.friends.easybud.financial.dto.FinancialResponse.IncomeStatementSummaryDto; import com.friends.easybud.financial.dto.FinancialResponse.ProfitLossListDto; import com.friends.easybud.financial.service.FinancialService; +import com.friends.easybud.global.annotation.AuthUser; import com.friends.easybud.global.response.ResponseDto; +import com.friends.easybud.member.domain.Member; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -32,49 +34,53 @@ public class FinancialController { @Operation(summary = "가용자금 조회", description = "사용자의 가용자금을 조회합니다.") @GetMapping("/available-funds") - public ResponseDto getAvailableFunds() { - return ResponseDto.onSuccess(financialService.getAvailableFunds()); + public ResponseDto getAvailableFunds(@AuthUser Member member) { + return ResponseDto.onSuccess(financialService.getAvailableFunds(member)); } @Operation(summary = "재무 상태 조회", description = "사용자의 재무 상태를 조회합니다.") @GetMapping("/financial-statement") - public ResponseDto getFinancialStatement() { - return ResponseDto.onSuccess(financialService.getFinancialStatement()); + public ResponseDto getFinancialStatement(@AuthUser Member member) { + return ResponseDto.onSuccess(financialService.getFinancialStatement(member)); } @Operation(summary = "손익현황 조회", description = "사용자의 손익현황을 조회합니다.") @Parameter(name = "startDate", example = "2024-02-01") @Parameter(name = "endDate", example = "2024-02-02") @GetMapping("/income-statement") - public ResponseDto getIncomeStatement(@RequestParam LocalDate startDate, + public ResponseDto getIncomeStatement(@AuthUser Member member, + @RequestParam LocalDate startDate, @RequestParam LocalDate endDate) { LocalDateTime startOfDay = startDate.atStartOfDay(); LocalDateTime endOfDay = endDate.atTime(23, 59, 59); - return ResponseDto.onSuccess(financialService.getIncomeStatement(startOfDay, endOfDay)); + return ResponseDto.onSuccess(financialService.getIncomeStatement(member, startOfDay, endOfDay)); } @Operation(summary = "월간 손익현황 요약 조회", description = "특정 연도와 월에 대한 손익현황을 조회합니다.") @Parameter(name = "year", example = "2024") @Parameter(name = "month", example = "2") @GetMapping("/income-statement/summary/monthly") - public ResponseDto getMonthlyIncomeStatementSummary(@RequestParam int year, + public ResponseDto getMonthlyIncomeStatementSummary(@AuthUser Member member, + @RequestParam int year, @RequestParam int month) { LocalDateTime startOfMonth = LocalDateTime.of(year, month, 1, 0, 0, 0); LocalDateTime endOfMonth = YearMonth.of(year, month) .atEndOfMonth() .atTime(LocalTime.MAX) .withNano(0); - return ResponseDto.onSuccess(financialService.getIncomeStatementSummary(startOfMonth, endOfMonth)); + return ResponseDto.onSuccess(financialService.getIncomeStatementSummary(member, startOfMonth, endOfMonth)); } @Operation(summary = "월간 일별 손익현황 요약 조회", description = "특정 연도와 월에 대해 해당 월의 모든 일자별 손익현황을 조회합니다.") @Parameter(name = "year", example = "2024") @Parameter(name = "month", example = "2") @GetMapping("/income-statement/summary/daily") - public ResponseDto getDailyIncomeStatementSummary(@RequestParam int year, + public ResponseDto getDailyIncomeStatementSummary(@AuthUser Member member, + @RequestParam int year, @RequestParam int month) { return ResponseDto.onSuccess( - FinancialConverter.toProfitLossListDto(financialService.getDailyIncomeStatementSummaries(year, month))); + FinancialConverter.toProfitLossListDto( + financialService.getDailyIncomeStatementSummaries(member, year, month))); } diff --git a/src/main/java/com/friends/easybud/financial/service/FinancialService.java b/src/main/java/com/friends/easybud/financial/service/FinancialService.java index 88a2512..ea40214 100644 --- a/src/main/java/com/friends/easybud/financial/service/FinancialService.java +++ b/src/main/java/com/friends/easybud/financial/service/FinancialService.java @@ -5,19 +5,20 @@ import com.friends.easybud.financial.dto.FinancialResponse.IncomeStatementDto; import com.friends.easybud.financial.dto.FinancialResponse.IncomeStatementSummaryDto; import com.friends.easybud.financial.dto.FinancialResponse.ProfitLossDto; +import com.friends.easybud.member.domain.Member; import java.time.LocalDateTime; import java.util.List; public interface FinancialService { - AvailableFundsDto getAvailableFunds(); + AvailableFundsDto getAvailableFunds(Member member); - FinancialStatementDto getFinancialStatement(); + FinancialStatementDto getFinancialStatement(Member member); - IncomeStatementDto getIncomeStatement(LocalDateTime startDate, LocalDateTime endDate); + IncomeStatementDto getIncomeStatement(Member member, LocalDateTime startDate, LocalDateTime endDate); - IncomeStatementSummaryDto getIncomeStatementSummary(LocalDateTime startDate, LocalDateTime endDate); + IncomeStatementSummaryDto getIncomeStatementSummary(Member member, LocalDateTime startDate, LocalDateTime endDate); - List getDailyIncomeStatementSummaries(int year, int month); + List getDailyIncomeStatementSummaries(Member member, int year, int month); } diff --git a/src/main/java/com/friends/easybud/financial/service/FinancialServiceImpl.java b/src/main/java/com/friends/easybud/financial/service/FinancialServiceImpl.java index 3034960..a237aac 100644 --- a/src/main/java/com/friends/easybud/financial/service/FinancialServiceImpl.java +++ b/src/main/java/com/friends/easybud/financial/service/FinancialServiceImpl.java @@ -7,6 +7,7 @@ import com.friends.easybud.financial.dto.FinancialResponse.IncomeStatementDto; import com.friends.easybud.financial.dto.FinancialResponse.IncomeStatementSummaryDto; import com.friends.easybud.financial.dto.FinancialResponse.ProfitLossDto; +import com.friends.easybud.member.domain.Member; import com.friends.easybud.transaction.domain.AccountName; import com.friends.easybud.transaction.repository.AccountCustomRepository; import java.math.BigDecimal; @@ -32,12 +33,11 @@ public class FinancialServiceImpl implements FinancialService { private final AccountCustomRepository accountCustomRepository; @Override - public AvailableFundsDto getAvailableFunds() { - Long memberId = 1L; - BigDecimal cash = getSumBySecondaryCategory("현금", memberId); - BigDecimal ordinaryDeposits = getSumBySecondaryCategory("보통예금", memberId); + public AvailableFundsDto getAvailableFunds(Member member) { + BigDecimal cash = getSumBySecondaryCategory("현금", member.getId()); + BigDecimal ordinaryDeposits = getSumBySecondaryCategory("보통예금", member.getId()); - List cards = cardRepository.findByMemberId(memberId); + List cards = cardRepository.findByMemberId(member.getId()); BigDecimal cardPayment = cards.stream() .map(card -> calculateUpcomingCardPayment(card, LocalDate.now())) .reduce(BigDecimal.ZERO, BigDecimal::add); @@ -121,31 +121,29 @@ private LocalDate findUsageEndDate(Card card, LocalDate nextPaymentDate) { @Override - public FinancialStatementDto getFinancialStatement() { - Long memberId = 1L; - BigDecimal totalAssets = getSumByPrimaryCategory("자산", memberId); - BigDecimal totalLiabilities = getSumByPrimaryCategory("부채", memberId); + public FinancialStatementDto getFinancialStatement(Member member) { + BigDecimal totalAssets = getSumByPrimaryCategory("자산", member.getId()); + BigDecimal totalLiabilities = getSumByPrimaryCategory("부채", member.getId()); BigDecimal netAssets = totalAssets.subtract(totalLiabilities); return FinancialStatementDto.builder() .totalAssets(totalAssets) .totalLiabilities(totalLiabilities) .netAssets(netAssets) - .initialNetAssetDefined(accountCustomRepository.existsInitialNetAsset(memberId)) + .initialNetAssetDefined(accountCustomRepository.existsInitialNetAsset(member.getId())) .build(); } @Override - public IncomeStatementDto getIncomeStatement(LocalDateTime startDate, LocalDateTime endDate) { - Long memberId = 1L; - BigDecimal revenue = getSumOfRevenueAccounts(memberId, startDate, endDate); - BigDecimal expense = getSumOfExpenseAccounts(memberId, startDate, endDate); + public IncomeStatementDto getIncomeStatement(Member member, LocalDateTime startDate, LocalDateTime endDate) { + BigDecimal revenue = getSumOfRevenueAccounts(member.getId(), startDate, endDate); + BigDecimal expense = getSumOfExpenseAccounts(member.getId(), startDate, endDate); LocalDateTime lastMonthStart = startDate.minusMonths(1).withDayOfMonth(1); LocalDateTime lastMonthEnd = lastMonthStart.plusMonths(1).minusDays(1); - BigDecimal lastMonthRevenue = getSumOfRevenueAccounts(memberId, lastMonthStart, lastMonthEnd); - BigDecimal lastMonthExpense = getSumOfExpenseAccounts(memberId, lastMonthStart, lastMonthEnd); + BigDecimal lastMonthRevenue = getSumOfRevenueAccounts(member.getId(), lastMonthStart, lastMonthEnd); + BigDecimal lastMonthExpense = getSumOfExpenseAccounts(member.getId(), lastMonthStart, lastMonthEnd); BigDecimal revenueChangePercentage = calculateChangePercentage(revenue, lastMonthRevenue); BigDecimal expenseChangePercentage = calculateChangePercentage(expense, lastMonthExpense); @@ -182,10 +180,10 @@ private BigDecimal calculateChangePercentage(BigDecimal current, BigDecimal prev } @Override - public IncomeStatementSummaryDto getIncomeStatementSummary(LocalDateTime startDate, LocalDateTime endDate) { - Long memberId = 1L; - BigDecimal revenue = getSumOfRevenueAccounts(memberId, startDate, endDate); - BigDecimal expense = getSumOfExpenseAccounts(memberId, startDate, endDate); + public IncomeStatementSummaryDto getIncomeStatementSummary(Member member, LocalDateTime startDate, + LocalDateTime endDate) { + BigDecimal revenue = getSumOfRevenueAccounts(member.getId(), startDate, endDate); + BigDecimal expense = getSumOfExpenseAccounts(member.getId(), startDate, endDate); return IncomeStatementSummaryDto.builder() .revenue(revenue) @@ -195,8 +193,7 @@ public IncomeStatementSummaryDto getIncomeStatementSummary(LocalDateTime startDa } @Override - public List getDailyIncomeStatementSummaries(int year, int month) { - Long memberId = 1L; + public List getDailyIncomeStatementSummaries(Member member, int year, int month) { List profitLossDtos = new ArrayList<>(); YearMonth yearMonth = YearMonth.of(year, month); int daysInMonth = yearMonth.lengthOfMonth(); @@ -206,8 +203,8 @@ public List getDailyIncomeStatementSummaries(int year, int month) LocalDateTime startOfDay = date.atStartOfDay(); LocalDateTime endOfDay = date.atTime(23, 59, 59); - BigDecimal revenue = getSumOfRevenueAccounts(memberId, startOfDay, endOfDay); - BigDecimal expense = getSumOfExpenseAccounts(memberId, startOfDay, endOfDay); + BigDecimal revenue = getSumOfRevenueAccounts(member.getId(), startOfDay, endOfDay); + BigDecimal expense = getSumOfExpenseAccounts(member.getId(), startOfDay, endOfDay); ProfitLossDto profitLossDto = ProfitLossDto.builder() .date(date) diff --git a/src/main/java/com/friends/easybud/global/annotation/Authuser.java b/src/main/java/com/friends/easybud/global/annotation/AuthUser.java similarity index 90% rename from src/main/java/com/friends/easybud/global/annotation/Authuser.java rename to src/main/java/com/friends/easybud/global/annotation/AuthUser.java index 3659ca2..a1622b4 100644 --- a/src/main/java/com/friends/easybud/global/annotation/Authuser.java +++ b/src/main/java/com/friends/easybud/global/annotation/AuthUser.java @@ -7,5 +7,5 @@ @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) -public @interface Authuser { +public @interface AuthUser { } diff --git a/src/main/java/com/friends/easybud/global/annotation/AuthenticationArgumentResolver.java b/src/main/java/com/friends/easybud/global/annotation/AuthenticationArgumentResolver.java index 710d7cb..6c513b4 100644 --- a/src/main/java/com/friends/easybud/global/annotation/AuthenticationArgumentResolver.java +++ b/src/main/java/com/friends/easybud/global/annotation/AuthenticationArgumentResolver.java @@ -11,6 +11,7 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; import org.springframework.web.bind.support.WebDataBinderFactory; import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.method.support.HandlerMethodArgumentResolver; @@ -25,7 +26,7 @@ public class AuthenticationArgumentResolver implements HandlerMethodArgumentReso @Override public boolean supportsParameter(MethodParameter parameter) { - final boolean isRegUserAnnotation = parameter.getParameterAnnotation(Authuser.class) != null; + final boolean isRegUserAnnotation = parameter.getParameterAnnotation(AuthUser.class) != null; final boolean isMember = parameter.getParameterType().equals(Member.class); return isRegUserAnnotation && isMember; } @@ -34,13 +35,18 @@ public boolean supportsParameter(MethodParameter parameter) { public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { final Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - if (authentication != null) { - HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest(); - String token = jwtProvider.resolveToken(request); - String uid = jwtProvider.getAuthentication(token).getName(); - return memberQueryService.getMemberByUid(uid); - } else { + if (authentication == null) { + throw new GeneralException(ErrorStatus.AUTHENTICATION_REQUIRED); + } + + HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest(); + String token = jwtProvider.resolveToken(request); + + if (!StringUtils.hasText(token) || !jwtProvider.validateToken(token)) { throw new GeneralException(ErrorStatus.TOKEN_INVALID); } + + String uid = jwtProvider.getAuthentication(token).getName(); + return memberQueryService.getMemberByUid(uid); } } diff --git a/src/main/java/com/friends/easybud/global/response/code/ErrorStatus.java b/src/main/java/com/friends/easybud/global/response/code/ErrorStatus.java index 21c2348..c7fea20 100644 --- a/src/main/java/com/friends/easybud/global/response/code/ErrorStatus.java +++ b/src/main/java/com/friends/easybud/global/response/code/ErrorStatus.java @@ -29,6 +29,7 @@ public enum ErrorStatus implements BaseCode { TOKEN_UNSUPPORTED(BAD_REQUEST, 4102, "지원되지 않는 토큰 형식입니다."), TOKEN_CLAIMS_EMPTY(BAD_REQUEST, 4103, "토큰 클레임이 비어있습니다."), REFRESH_TOKEN_NOT_FOUND(BAD_REQUEST, 4104, "헤더에 refresh token이 존재하지 않습니다."), + AUTHENTICATION_REQUIRED(BAD_REQUEST, 4105, "인증 정보가 필요합니다."), // AccountCategory: 4150 ~ 4199 PRIMARY_CATEGORY_NOT_FOUND(NOT_FOUND, 4150, "존재하지 않는 계정 대분류입니다."), @@ -36,12 +37,15 @@ public enum ErrorStatus implements BaseCode { TERTIARY_CATEGORY_NOT_FOUND(NOT_FOUND, 4152, "존재하지 않는 계정 소분류입니다."), CANNOT_DELETE_DEFAULT_CATEGORY(BAD_REQUEST, 4153, "기본값은 삭제할 수 없습니다."), TERTIARY_CATEGORY_ALREADY_EXISTS(BAD_REQUEST, 4154, "이미 존재하는 계정 소분류입니다."), + UNAUTHORIZED_TERTIARY_CATEGORY_ACCESS(BAD_REQUEST, 4155, "접근 권한이 없는 소분류입니다."), // Card: 4200 ~ 4249 CARD_NOT_FOUND(NOT_FOUND, 4200, "존재하지 않는 카드입니다."), + UNAUTHORIZED_CARD_ACCESS(BAD_REQUEST, 4201, "접근 권한이 없는 카드입니다."), // Transaction: 4250 ~ 4299 TRANSACTION_NOT_FOUND(NOT_FOUND, 4250, "존재하지 않는 거래입니다."), + UNAUTHORIZED_TRANSACTION_ACCESS(BAD_REQUEST, 4251, "접근 권한이 없는 거래입니다."), // Account: 4300 ~ 4349 ACCOUNT_NOT_FOUND(NOT_FOUND, 4300, "존재하지 않는 계정입니다."), diff --git a/src/main/java/com/friends/easybud/transaction/controller/TransactionController.java b/src/main/java/com/friends/easybud/transaction/controller/TransactionController.java index 793facf..18f20a6 100644 --- a/src/main/java/com/friends/easybud/transaction/controller/TransactionController.java +++ b/src/main/java/com/friends/easybud/transaction/controller/TransactionController.java @@ -1,6 +1,8 @@ package com.friends.easybud.transaction.controller; +import com.friends.easybud.global.annotation.AuthUser; import com.friends.easybud.global.response.ResponseDto; +import com.friends.easybud.member.domain.Member; import com.friends.easybud.transaction.converter.TransactionConverter; import com.friends.easybud.transaction.dto.TransactionRequest.TransactionCreateDto; import com.friends.easybud.transaction.dto.TransactionResponse.TransactionDto; @@ -33,44 +35,48 @@ public class TransactionController { @Operation(summary = "거래 생성", description = "새로운 거래를 생성합니다.") @PostMapping - public ResponseDto createTransaction(@RequestBody TransactionCreateDto request) { - return ResponseDto.onSuccess(transactionCommandService.createTransaction(request)); + public ResponseDto createTransaction(@AuthUser Member member, + @RequestBody TransactionCreateDto request) { + return ResponseDto.onSuccess(transactionCommandService.createTransaction(member, request)); } @Operation(summary = "거래 삭제", description = "기존의 거래를 삭제합니다.") @DeleteMapping("/{transactionId}") - public ResponseDto deleteTransaction(@PathVariable Long transactionId) { - return ResponseDto.onSuccess(transactionCommandService.deleteTransaction(transactionId)); + public ResponseDto deleteTransaction(@AuthUser Member member, + @PathVariable Long transactionId) { + return ResponseDto.onSuccess(transactionCommandService.deleteTransaction(member, transactionId)); } @Operation(summary = "거래 조회", description = "특정 거래를 조회합니다.") @GetMapping("/{transactionId}") - public ResponseDto getTransaction(@PathVariable Long transactionId) { + public ResponseDto getTransaction(@AuthUser Member member, + @PathVariable Long transactionId) { return ResponseDto.onSuccess( - TransactionConverter.toTransactionDto(transactionQueryService.getTransaction(transactionId))); + TransactionConverter.toTransactionDto(transactionQueryService.getTransaction(member, transactionId))); } @Operation(summary = "특정 날짜의 거래 조회", description = "주어진 날짜에 해당하는 모든 거래 목록을 조회합니다.") @GetMapping("/date/{date}") - public ResponseDto getTransactionsByDate( - @PathVariable @DateTimeFormat(iso = ISO.DATE) LocalDate date) { + public ResponseDto getTransactionsByDate(@AuthUser Member member, + @PathVariable @DateTimeFormat(iso = ISO.DATE) LocalDate date) { LocalDateTime startOfDay = date.atStartOfDay(); LocalDateTime endOfDay = date.atTime(23, 59, 59); return ResponseDto.onSuccess( TransactionConverter.toTransactionListDto( - transactionQueryService.getTransactionsBetweenDates(startOfDay, endOfDay))); + transactionQueryService.getTransactionsBetweenDates(member, startOfDay, endOfDay))); } @Operation(summary = "최근 3개의 거래 조회", description = "가장 최근에 이루어진 3개의 거래를 조회합니다.") @GetMapping("/recent") - public ResponseDto getRecentTransactions() { + public ResponseDto getRecentTransactions(@AuthUser Member member) { return ResponseDto.onSuccess( - TransactionConverter.toTransactionListDto(transactionQueryService.getRecentTransactions())); + TransactionConverter.toTransactionListDto(transactionQueryService.getRecentTransactions(member))); } @Operation(summary = "특정 연도와 달의 거래 조회", description = "주어진 연도와 달에 해당하는 모든 거래 목록을 조회합니다.") @GetMapping("/year/{year}/month/{month}") public ResponseDto getTransactionsByYearAndMonth( + @AuthUser Member member, @PathVariable int year, @PathVariable int month) { LocalDate startOfMonth = LocalDate.of(year, month, 1); @@ -81,8 +87,7 @@ public ResponseDto getTransactionsByYearAndMonth( return ResponseDto.onSuccess( TransactionConverter.toTransactionListDto( - transactionQueryService.getTransactionsBetweenDates(startDateTime, endDateTime))); + transactionQueryService.getTransactionsBetweenDates(member, startDateTime, endDateTime))); } - } diff --git a/src/main/java/com/friends/easybud/transaction/service/TransactionCommandService.java b/src/main/java/com/friends/easybud/transaction/service/TransactionCommandService.java index a7afec5..464b1ae 100644 --- a/src/main/java/com/friends/easybud/transaction/service/TransactionCommandService.java +++ b/src/main/java/com/friends/easybud/transaction/service/TransactionCommandService.java @@ -1,11 +1,12 @@ package com.friends.easybud.transaction.service; +import com.friends.easybud.member.domain.Member; import com.friends.easybud.transaction.dto.TransactionRequest.TransactionCreateDto; public interface TransactionCommandService { - Long createTransaction(TransactionCreateDto request); + Long createTransaction(Member member, TransactionCreateDto request); - Boolean deleteTransaction(Long transactionId); + Boolean deleteTransaction(Member member, Long transactionId); } diff --git a/src/main/java/com/friends/easybud/transaction/service/TransactionCommandServiceImpl.java b/src/main/java/com/friends/easybud/transaction/service/TransactionCommandServiceImpl.java index 61b5a41..6be44e8 100644 --- a/src/main/java/com/friends/easybud/transaction/service/TransactionCommandServiceImpl.java +++ b/src/main/java/com/friends/easybud/transaction/service/TransactionCommandServiceImpl.java @@ -7,7 +7,6 @@ import com.friends.easybud.global.exception.GeneralException; import com.friends.easybud.global.response.code.ErrorStatus; import com.friends.easybud.member.domain.Member; -import com.friends.easybud.member.repository.MemberRepository; import com.friends.easybud.transaction.domain.Account; import com.friends.easybud.transaction.domain.Transaction; import com.friends.easybud.transaction.dto.TransactionRequest.AccountCreateDto; @@ -25,15 +24,12 @@ public class TransactionCommandServiceImpl implements TransactionCommandService private final TransactionRepository transactionRepository; private final AccountRepository accountRepository; - private final MemberRepository memberRepository; // TODO MemberQueryService 주입 private final CardRepository cardRepository; private final TertiaryCategoryRepository tertiaryCategoryRepository; @Override - public Long createTransaction(TransactionCreateDto request) { - Member member = memberRepository.findById(1L).get(); // TODO 로그인 된 사용자 정보 조회 - + public Long createTransaction(Member member, TransactionCreateDto request) { Transaction transaction = buildTransaction(request, member); transactionRepository.save(transaction); @@ -89,12 +85,20 @@ private void validateAccountDto(AccountCreateDto accountDto) { } @Override - public Boolean deleteTransaction(Long transactionId) { + public Boolean deleteTransaction(Member member, Long transactionId) { Transaction transaction = transactionRepository.findById(transactionId) .orElseThrow(() -> new GeneralException(ErrorStatus.TRANSACTION_NOT_FOUND)); + checkTransactionOwnership(member, transaction); + transactionRepository.delete(transaction); return Boolean.TRUE; } + private void checkTransactionOwnership(Member member, Transaction transaction) { + if (!transaction.getMember().equals(member)) { + throw new GeneralException(ErrorStatus.UNAUTHORIZED_TRANSACTION_ACCESS); + } + } + } diff --git a/src/main/java/com/friends/easybud/transaction/service/TransactionQueryService.java b/src/main/java/com/friends/easybud/transaction/service/TransactionQueryService.java index c0225ed..77ddbea 100644 --- a/src/main/java/com/friends/easybud/transaction/service/TransactionQueryService.java +++ b/src/main/java/com/friends/easybud/transaction/service/TransactionQueryService.java @@ -1,15 +1,16 @@ package com.friends.easybud.transaction.service; +import com.friends.easybud.member.domain.Member; import com.friends.easybud.transaction.domain.Transaction; import java.time.LocalDateTime; import java.util.List; public interface TransactionQueryService { - Transaction getTransaction(Long transactionId); + Transaction getTransaction(Member member, Long transactionId); - List getTransactionsBetweenDates(LocalDateTime startOfDay, LocalDateTime endOfDay); + List getTransactionsBetweenDates(Member member, LocalDateTime startOfDay, LocalDateTime endOfDay); - List getRecentTransactions(); + List getRecentTransactions(Member member); } \ No newline at end of file diff --git a/src/main/java/com/friends/easybud/transaction/service/TransactionQueryServiceImpl.java b/src/main/java/com/friends/easybud/transaction/service/TransactionQueryServiceImpl.java index 163ca0f..347b257 100644 --- a/src/main/java/com/friends/easybud/transaction/service/TransactionQueryServiceImpl.java +++ b/src/main/java/com/friends/easybud/transaction/service/TransactionQueryServiceImpl.java @@ -2,6 +2,7 @@ import com.friends.easybud.global.exception.GeneralException; import com.friends.easybud.global.response.code.ErrorStatus; +import com.friends.easybud.member.domain.Member; import com.friends.easybud.transaction.domain.Transaction; import com.friends.easybud.transaction.repository.TransactionRepository; import java.time.LocalDateTime; @@ -18,21 +19,20 @@ public class TransactionQueryServiceImpl implements TransactionQueryService { private final TransactionRepository transactionRepository; @Override - public Transaction getTransaction(Long transactionId) { + public Transaction getTransaction(Member member, Long transactionId) { return transactionRepository.findById(transactionId) .orElseThrow(() -> new GeneralException(ErrorStatus.TRANSACTION_NOT_FOUND)); } @Override - public List getTransactionsBetweenDates(LocalDateTime startDateTime, LocalDateTime endDateTime) { - Long memberId = 1L; - return transactionRepository.findByMemberIdAndDateBetween(memberId, startDateTime, endDateTime); + public List getTransactionsBetweenDates(Member member, LocalDateTime startDateTime, + LocalDateTime endDateTime) { + return transactionRepository.findByMemberIdAndDateBetween(member.getId(), startDateTime, endDateTime); } @Override - public List getRecentTransactions() { - Long memberId = 1L; - return transactionRepository.findTop3ByMemberIdOrderByDateDesc(memberId); + public List getRecentTransactions(Member member) { + return transactionRepository.findTop3ByMemberIdOrderByDateDesc(member.getId()); } }