diff --git a/.github/workflows/cd-workflow.yml b/.github/workflows/cd-workflow.yml index 5733e340..1b0674c4 100644 --- a/.github/workflows/cd-workflow.yml +++ b/.github/workflows/cd-workflow.yml @@ -26,6 +26,15 @@ jobs: - name: "πŸ‘πŸ» grant execute permission for gradlew" run: chmod +x gradlew + - name: "πŸ” Copy Secret" + env: + OCCUPY_SECRET: ${{ secrets.OCCUPY_SECRET }} + OCCUPY_SECRET_DIR: src/main/resources + OCCUPY_SECRET_DIR_FILE_NAME: application-secret.yml + run: | + mkdir -p $OCCUPY_SECRET_DIR + echo $OCCUPY_SECRET | base64 --decode > $OCCUPY_SECRET_DIR/$OCCUPY_SECRET_DIR_FILE_NAME + - name: "🐘 build with Gradle (without test)" run: ./gradlew clean build -x test --stacktrace @@ -34,25 +43,24 @@ jobs: with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - - - name: "πŸ” Copy Secret" - env: - OCCUPY_SECRET: ${{ secrets.OCCUPY_SECRET }} - OCCUPY_SECRET_DIR: src/main/resources - OCCUPY_SECRET_DIR_FILE_NAME: application-secret.yml + + - name: πŸ“ Generate .env file run: | - mkdir -p $OCCUPY_SECRET_DIR - echo $OCCUPY_SECRET | base64 --decode > $OCCUPY_SECRET_DIR/$OCCUPY_SECRET_DIR_FILE_NAME + echo "DOCKER_USERNAME=${{ secrets.DOCKER_USERNAME }}" >> .env + echo "DOCKER_IMAGE=${{ secrets.DOCKER_IMAGE }}" >> .env + echo "PROD_DATASOURCE_URL=${{ secrets.PROD_DATASOURCE_URL }}" >> .env + echo "PROD_DATASOURCE_USERNAME=${{ secrets.PROD_DATASOURCE_USERNAME }}" >> .env + echo "PROD_DATASOURCE_PASSWORD=${{ secrets.PROD_DATASOURCE_PASSWORD }}" >> .env + echo "REDIS_HOST=${{ secrets.REDIS_HOST }}" >> .env + echo "REDIS_PORT=${{ secrets.REDIS_PORT }}" >> .env - name: "🐳 Docker build & push" run: | - docker build -f Dockerfile \ - -t ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE }} . + docker compose -f docker-compose.yml --env-file .env build + docker compose -f docker-compose.yml --env-file .env push - docker push ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE }} - # AWS 인증 - - name: AWS configure credentials + - name: βœ… AWS configure credentials uses: aws-actions/configure-aws-credentials@v1 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} @@ -75,9 +83,10 @@ jobs: "echo \"PROD_DATASOURCE_PASSWORD=${{ secrets.PROD_DATASOURCE_PASSWORD }}\" >> .env", "echo \"REDIS_HOST=${{ secrets.REDIS_HOST }}\" >> .env", "echo \"REDIS_PORT=${{ secrets.REDIS_PORT }}\" >> .env", + "echo \"MAIL_USERNAME=${{ secrets.MAIL_USERNAME }}\" >> .env", + "echo \"MAIL_PASSWORD=${{ secrets.MAIL_PASSWORD }}\" >> .env", "sudo docker-compose -f docker-compose.yml --env-file .env pull", "sudo docker-compose -f docker-compose.yml --env-file .env down || true", "sudo docker-compose -f docker-compose.yml --env-file .env up -d", "sudo docker image prune -f" - ]' - --output text + ]' --output text diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..11ce8d0d --- /dev/null +++ b/Dockerfile @@ -0,0 +1,6 @@ +FROM openjdk:17 +EXPOSE 8001 +ARG JAR_FILE=build/libs/*.jar +COPY ${JAR_FILE} app.jar + +ENTRYPOINT ["java", "-jar", "/app.jar"] \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 800b2f78..5d14b828 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,6 +2,7 @@ version: '3.8' services: app: + build: . image: "${DOCKER_USERNAME}/${DOCKER_IMAGE}" container_name: BARO_CONTAINER ports: diff --git a/src/main/java/konkuk/kuit/baro/domain/pin/service/PinService.java b/src/main/java/konkuk/kuit/baro/domain/pin/service/PinService.java index d7d7c488..a10e1620 100644 --- a/src/main/java/konkuk/kuit/baro/domain/pin/service/PinService.java +++ b/src/main/java/konkuk/kuit/baro/domain/pin/service/PinService.java @@ -23,6 +23,7 @@ import org.springframework.transaction.annotation.Transactional; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; @Service @@ -66,6 +67,11 @@ public void registerPinData(PinRequestDTO request, Long userId){ Place place; if (request.getPlaceId() == -1) { Point placePoint = GeometryUtil.createPoint(request.getLatitude(), request.getLongitude()); + Optional existingPlace = placeRepository.findPlaceByPlaceAddress(request.getPlaceAddress()); + + if (existingPlace.isPresent()) { + throw new CustomException(ErrorCode.PLACE_ALREADY_EXISTS); + } place = Place.builder() .placeName(request.getPlaceName()) .location(placePoint) diff --git a/src/main/java/konkuk/kuit/baro/domain/place/repository/PlaceRepository.java b/src/main/java/konkuk/kuit/baro/domain/place/repository/PlaceRepository.java index 7cbaa567..25b9b22e 100644 --- a/src/main/java/konkuk/kuit/baro/domain/place/repository/PlaceRepository.java +++ b/src/main/java/konkuk/kuit/baro/domain/place/repository/PlaceRepository.java @@ -27,6 +27,8 @@ List findByDistanceAndPlaceCategories( Optional findPlaceById(Long id); + Optional findPlaceByPlaceAddress(String placeAddress); + @Query(value = """ SELECT NEW konkuk.kuit.baro.domain.place.dto.response.PlaceSummaryInfoResponseDTO( diff --git a/src/main/java/konkuk/kuit/baro/domain/promise/dto/response/SuggestedPromiseResponseDTO.java b/src/main/java/konkuk/kuit/baro/domain/promise/dto/response/SuggestedPromiseResponseDTO.java index 9d4c2f1f..26e90f28 100644 --- a/src/main/java/konkuk/kuit/baro/domain/promise/dto/response/SuggestedPromiseResponseDTO.java +++ b/src/main/java/konkuk/kuit/baro/domain/promise/dto/response/SuggestedPromiseResponseDTO.java @@ -27,5 +27,5 @@ public class SuggestedPromiseResponseDTO { private LocalDate suggestedStartDate; @Schema(description = "약속 μ œμ•ˆλœ 끝 λ‚ μ§œ", example = "2025-01-02") - private LocalDate SuggestedEndDate; + private LocalDate suggestedEndDate; } diff --git a/src/main/java/konkuk/kuit/baro/domain/promise/service/PromiseAvailableTimeService.java b/src/main/java/konkuk/kuit/baro/domain/promise/service/PromiseAvailableTimeService.java index 9bf9c963..7a173e5a 100644 --- a/src/main/java/konkuk/kuit/baro/domain/promise/service/PromiseAvailableTimeService.java +++ b/src/main/java/konkuk/kuit/baro/domain/promise/service/PromiseAvailableTimeService.java @@ -52,7 +52,7 @@ public PromiseAvailableTimeResponseDTO getPromiseAvailableTime(Long promiseId) { @Transactional public void setPromiseAvailableTime(SetPromiseAvailableTimeRequestDTO req, Long userId, Long promiseId) { - User loginUser = userRepository.findById(1L).orElseThrow(() -> new CustomException(USER_NOT_FOUND)); + User loginUser = userRepository.findById(userId).orElseThrow(() -> new CustomException(USER_NOT_FOUND)); Promise promise = promiseRepository.findById(promiseId).orElseThrow(() -> new CustomException(PROMISE_NOT_FOUND)); diff --git a/src/main/java/konkuk/kuit/baro/domain/schedule/controller/ScheduleController.java b/src/main/java/konkuk/kuit/baro/domain/schedule/controller/ScheduleController.java index 05747c86..d4b38038 100644 --- a/src/main/java/konkuk/kuit/baro/domain/schedule/controller/ScheduleController.java +++ b/src/main/java/konkuk/kuit/baro/domain/schedule/controller/ScheduleController.java @@ -6,6 +6,7 @@ import konkuk.kuit.baro.domain.schedule.dto.response.GetSchedulesResponseDTO; import konkuk.kuit.baro.domain.schedule.dto.response.SchedulesDTO; import konkuk.kuit.baro.domain.schedule.service.ScheduleService; +import konkuk.kuit.baro.global.auth.resolver.CurrentUserId; import konkuk.kuit.baro.global.common.annotation.CustomExceptionDescription; import konkuk.kuit.baro.global.common.response.BaseResponse; import lombok.RequiredArgsConstructor; @@ -28,8 +29,9 @@ public class ScheduleController { @Operation(summary = "일정 μΆ”κ°€", description = "μΌμ •ν‘œμ— 일정을 μΆ”κ°€ν•©λ‹ˆλ‹€.") @PostMapping("") @CustomExceptionDescription(SCHEDULE_ADD) - public BaseResponse addSchedule(@RequestBody @Validated AddScheduleRequestDTO req){ - scheduleService.addSchedule(req); + public BaseResponse addSchedule(@RequestBody @Validated AddScheduleRequestDTO req, + @CurrentUserId Long userId) { + scheduleService.addSchedule(req, userId); return BaseResponse.ok(null); } @@ -37,8 +39,10 @@ public BaseResponse addSchedule(@RequestBody @Validated AddScheduleRequest @Operation(summary = "일정 μˆ˜μ •", description = "μΌμ •ν‘œμ˜ 일정을 μˆ˜μ •ν•©λ‹ˆλ‹€.") @PatchMapping("{scheduleId}") @CustomExceptionDescription(SCHEDULE_UPDATE) - public BaseResponse updateSchedule(@PathVariable Long scheduleId, @RequestBody @Validated AddScheduleRequestDTO req){ - scheduleService.updateSchedule(req, scheduleId); + public BaseResponse updateSchedule(@PathVariable Long scheduleId, + @RequestBody @Validated AddScheduleRequestDTO req, + @CurrentUserId Long userId){ + scheduleService.updateSchedule(req, scheduleId, userId); return BaseResponse.ok(null); } @@ -46,8 +50,8 @@ public BaseResponse updateSchedule(@PathVariable Long scheduleId, @Request @Operation(summary = "μΌμ •ν‘œ 쑰회", description = "λ§ˆμ΄νŽ˜μ΄μ§€μ—μ„œ μΌμ •ν‘œλ₯Ό μ‘°νšŒν•©λ‹ˆλ‹€.") @GetMapping("") @CustomExceptionDescription(GET_SCHEDULES) - public BaseResponse getSchedules(){ - return BaseResponse.ok(scheduleService.getSchedules()); + public BaseResponse getSchedules(@CurrentUserId Long userId){ + return BaseResponse.ok(scheduleService.getSchedules(userId)); } @Tag(name = "My Page", description = "μœ μ € λ§ˆμ΄νŽ˜μ΄μ§€ κ΄€λ ¨ API") diff --git a/src/main/java/konkuk/kuit/baro/domain/schedule/service/ScheduleService.java b/src/main/java/konkuk/kuit/baro/domain/schedule/service/ScheduleService.java index c6a01673..70b48adb 100644 --- a/src/main/java/konkuk/kuit/baro/domain/schedule/service/ScheduleService.java +++ b/src/main/java/konkuk/kuit/baro/domain/schedule/service/ScheduleService.java @@ -26,8 +26,8 @@ public class ScheduleService { private final UserRepository userRepository; @Transactional - public void addSchedule(AddScheduleRequestDTO req) { - User loginUser = userRepository.findById(1L) + public void addSchedule(AddScheduleRequestDTO req, Long userId) { + User loginUser = userRepository.findById(userId) .orElseThrow(() -> new CustomException(USER_NOT_FOUND)); validateNewSchedule(req, loginUser); @@ -45,8 +45,8 @@ public void addSchedule(AddScheduleRequestDTO req) { } @Transactional - public void updateSchedule(AddScheduleRequestDTO req, Long scheduleId) { - User loginUser = userRepository.findById(1L) + public void updateSchedule(AddScheduleRequestDTO req, Long scheduleId, Long userId) { + User loginUser = userRepository.findById(userId) .orElseThrow(() -> new CustomException(USER_NOT_FOUND)); Schedule existingSchedule = scheduleRepository.findById(scheduleId) @@ -104,8 +104,8 @@ private void validateCommonScheduleRules(AddScheduleRequestDTO req) { } } - public GetSchedulesResponseDTO getSchedules() { - User loginUser = userRepository.findById(1L).orElseThrow(() -> new CustomException(USER_NOT_FOUND)); + public GetSchedulesResponseDTO getSchedules(Long userId) { + User loginUser = userRepository.findById(userId).orElseThrow(() -> new CustomException(USER_NOT_FOUND)); List schedules = scheduleRepository.findAllByUserId(loginUser.getId()); return new GetSchedulesResponseDTO( loginUser.getProfileImage(), diff --git a/src/main/java/konkuk/kuit/baro/domain/user/controller/UserController.java b/src/main/java/konkuk/kuit/baro/domain/user/controller/UserController.java index b3607fb7..56d6d5de 100644 --- a/src/main/java/konkuk/kuit/baro/domain/user/controller/UserController.java +++ b/src/main/java/konkuk/kuit/baro/domain/user/controller/UserController.java @@ -26,6 +26,7 @@ public class UserController { private final UserService userService; + @Tag(name = "Auth API", description = "Auth κ΄€λ ¨ API") @Operation( summary = "νšŒμ›κ°€μž…", description = "νšŒμ›κ°€μž…μ„ ν•©λ‹ˆλ‹€. 토큰이 ν•„μš”ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€." @@ -41,8 +42,9 @@ public BaseResponse signup(@RequestBody SignUpRequestDTO request) { @Operation(summary = "μœ μ € ν”„λ‘œν•„ μˆ˜μ •", description = "μœ μ €μ˜ 이름, ν”„λ‘œν•„ 사진을 λ³€κ²½ν•©λ‹ˆλ‹€.") @PostMapping("profile") @CustomExceptionDescription(USER_PROFILE_UPDATE) - public BaseResponse updateProfile(@RequestBody @Validated UserUpdateProfileRequestDTO req){ - userService.updateProfile(req); + public BaseResponse updateProfile(@RequestBody @Validated UserUpdateProfileRequestDTO req, + @CurrentUserId Long userId){ + userService.updateProfile(req, userId); return BaseResponse.ok(null); } @@ -59,7 +61,7 @@ public BaseResponse getProfile(@CurrentUserId Long userI @Operation(summary = "λ§ˆμ΄νŽ˜μ΄μ§€ μ„€μ • ν™”λ©΄", description = "λ§ˆμ΄νŽ˜μ΄μ§€μ—μ„œ μ„€μ • κΈ°λŠ₯ 호좜 μ‹œ ν”„λ‘œν•„μ„ μ‘°νšŒν•˜λŠ” κΈ°λŠ₯μž…λ‹ˆλ‹€.") @GetMapping("profile-setting") @CustomExceptionDescription(USER_PROFILE) - public BaseResponse getProfileSetting(Long userId){ + public BaseResponse getProfileSetting(@CurrentUserId Long userId){ return BaseResponse.ok(userService.getProfileSetting(userId)); } @@ -67,8 +69,9 @@ public BaseResponse getProfileSetting(Long userId @Operation(summary = "λΉ„λ°€λ²ˆν˜Έ λ³€κ²½", description = "μ‚¬μš©μžμ˜ λΉ„λ°€λ²ˆν˜Έλ₯Ό λ³€κ²½ν•©λ‹ˆλ‹€.") @PostMapping("password") @CustomExceptionDescription(USER_PASSWORD_UPDATE) - public BaseResponse updatePassword(@RequestBody @Validated UserUpdatePasswordRequestDTO req){ - userService.updatePassword(req); + public BaseResponse updatePassword(@RequestBody @Validated UserUpdatePasswordRequestDTO req, + @CurrentUserId Long userId){ + userService.updatePassword(req, userId); return BaseResponse.ok(null); } @@ -76,7 +79,7 @@ public BaseResponse updatePassword(@RequestBody @Validated UserUpdatePassw @Operation(summary = "νšŒμ› νƒˆν‡΄", description = "μ‚¬μš©μžκ°€ νšŒμ› νƒˆν‡΄λ₯Ό ν•©λ‹ˆλ‹€.") @DeleteMapping() @CustomExceptionDescription(USER_DELETE) - public BaseResponse delete(Long userId){ + public BaseResponse delete(@CurrentUserId Long userId){ userService.deleteUser(userId); return BaseResponse.ok(null); } @@ -85,7 +88,7 @@ public BaseResponse delete(Long userId){ @Operation(summary = "ν™ˆ ν™”λ©΄ 쑰회", description = "메인 ν™ˆ 화면을 μ‘°νšŒν•©λ‹ˆλ‹€.") @GetMapping() @CustomExceptionDescription(USER_HOME) - public BaseResponse getHomePage(){ - return BaseResponse.ok(userService.getHomePage(1L)); + public BaseResponse getHomePage(@CurrentUserId Long userId){ + return BaseResponse.ok(userService.getHomePage(userId)); } } diff --git a/src/main/java/konkuk/kuit/baro/domain/user/service/UserService.java b/src/main/java/konkuk/kuit/baro/domain/user/service/UserService.java index d0fc1679..6f1b4295 100644 --- a/src/main/java/konkuk/kuit/baro/domain/user/service/UserService.java +++ b/src/main/java/konkuk/kuit/baro/domain/user/service/UserService.java @@ -64,8 +64,9 @@ public void signup(SignUpRequestDTO request){ @Transactional - public void updateProfile(UserUpdateProfileRequestDTO req) { - User loginUser = userRepository.findById(1L).orElseThrow(() -> new CustomException(USER_NOT_FOUND)); + public void updateProfile(UserUpdateProfileRequestDTO req, Long userId) { + User loginUser = userRepository.findById(userId) + .orElseThrow(() -> new CustomException(USER_NOT_FOUND)); validateName(req.getNewName()); @@ -81,18 +82,18 @@ private void validateName(String name){ } public UserProfileResponseDTO getProfile(Long userId){ - User loginUser = userRepository.findById(1L).orElseThrow(() -> new CustomException(USER_NOT_FOUND)); + User loginUser = userRepository.findById(userId).orElseThrow(() -> new CustomException(USER_NOT_FOUND)); return new UserProfileResponseDTO(loginUser.getName(), loginUser.getProfileImage()); } public UserProfileSettingResponseDTO getProfileSetting(Long userId){ - User loginUser = userRepository.findById(1L).orElseThrow(() -> new CustomException(USER_NOT_FOUND)); + User loginUser = userRepository.findById(userId).orElseThrow(() -> new CustomException(USER_NOT_FOUND)); return new UserProfileSettingResponseDTO(loginUser.getName(), loginUser.getEmail(), loginUser.getProfileImage()); } @Transactional - public void updatePassword(UserUpdatePasswordRequestDTO req){ - User loginUser = userRepository.findById(1L).orElseThrow(() -> new CustomException(USER_NOT_FOUND)); + public void updatePassword(UserUpdatePasswordRequestDTO req, Long userId){ + User loginUser = userRepository.findById(userId).orElseThrow(() -> new CustomException(USER_NOT_FOUND)); validateCurrentPassword(req, loginUser); validateNewPassword(req); @@ -124,7 +125,7 @@ private void validateCurrentPassword(UserUpdatePasswordRequestDTO req, User logi @Transactional public void deleteUser(Long userId){ - User loginUser = userRepository.findById(1L).orElseThrow(() -> new CustomException(USER_NOT_FOUND)); + User loginUser = userRepository.findById(userId).orElseThrow(() -> new CustomException(USER_NOT_FOUND)); userRepository.delete(loginUser); } diff --git a/src/main/java/konkuk/kuit/baro/global/auth/controller/AuthController.java b/src/main/java/konkuk/kuit/baro/global/auth/controller/AuthController.java index 339e10a5..99d509c4 100644 --- a/src/main/java/konkuk/kuit/baro/global/auth/controller/AuthController.java +++ b/src/main/java/konkuk/kuit/baro/global/auth/controller/AuthController.java @@ -77,9 +77,9 @@ public BaseResponse sendAuthCodeMail(@RequestBody MailRequestDTO mailReque summary = "인증번호 검증", description = "λ©”μΌλ‘œ 받은 인증번호λ₯Ό κ²€μ¦ν•©λ‹ˆλ‹€. μ•‘μ„ΈμŠ€ 토큰이 ν•„μš”ν•©λ‹ˆλ‹€." ) - @GetMapping("/mail/check") - public BaseResponse checkAuthCode(@RequestBody CodeCheckRequestDTO checkCodeRequestDTO) { + @PostMapping("/mail/check") + public BaseResponse checkAuthCode(@RequestBody CodeCheckRequestDTO checkCodeRequestDTO) { mailService.checkAuthCode(checkCodeRequestDTO); return BaseResponse.ok(null); } -} \ No newline at end of file +} diff --git a/src/main/java/konkuk/kuit/baro/global/common/response/status/ErrorCode.java b/src/main/java/konkuk/kuit/baro/global/common/response/status/ErrorCode.java index b1dfcbe0..56cd5f65 100644 --- a/src/main/java/konkuk/kuit/baro/global/common/response/status/ErrorCode.java +++ b/src/main/java/konkuk/kuit/baro/global/common/response/status/ErrorCode.java @@ -33,6 +33,7 @@ public enum ErrorCode implements ResponseStatus { // Place INVALID_LOCATION(400, BAD_REQUEST.value(), "μœ„λ„, 경도값이 μ˜¬λ°”λ₯΄μ§€ μ•ŠμŠ΅λ‹ˆλ‹€."), PLACE_NOT_FOUND(401, HttpStatus.NOT_FOUND.value(), "μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” μž₯μ†Œμž…λ‹ˆλ‹€."), + PLACE_ALREADY_EXISTS(402, BAD_REQUEST.value(), "이미 μ‘΄μž¬ν•˜λŠ” μž₯μ†Œμž…λ‹ˆλ‹€"), //Promise PROMISE_NOT_FOUND(500, HttpStatus.NOT_FOUND.value(),"μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” μ•½μ†μž…λ‹ˆλ‹€."), PROMISE_NOT_CONFIRMED(501, BAD_REQUEST.value(), "ν™•μ •λ˜μ§€ μ•Šμ€ μ•½μ†μž…λ‹ˆλ‹€."), diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index a40413e5..12343d5f 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -6,7 +6,7 @@ spring: local : local-db, dev-port, common dev: dev-db, dev-port, common prod: prod-db, prod-port,common - active: local + active: prod --- # 둜컬용 DB spring: @@ -61,7 +61,7 @@ spring: activate: on-profile: prod-db datasource: - url: ${PROD_DATASOURCE_USERNAME} + url: ${PROD_DATASOURCE_URL} username: ${PROD_DATASOURCE_USERNAME} password: ${PROD_DATASOURCE_PASSWORD} driver-class-name: com.mysql.cj.jdbc.Driver @@ -121,4 +121,4 @@ spring: activate: on-profile: prod-port server: - port: 8001 \ No newline at end of file + port: 8001