diff --git a/.github/workflows/CD.yml b/.github/workflows/CD.yml index 08e0966..b07fb22 100644 --- a/.github/workflows/CD.yml +++ b/.github/workflows/CD.yml @@ -30,6 +30,7 @@ jobs: uses: appleboy/ssh-action@master with: host: ${{ secrets.SERVER_HOST }} + port: ${{ secrets.SERVER_PORT }} username: ${{ secrets.SERVER_USERNAME }} key: ${{ secrets.SERVER_KEY }} script: | @@ -38,9 +39,17 @@ jobs: git commit -m "temp commit" git fetch origin main git merge origin/main + if [ $? -ne 0 ]; then # 병합 명령어의 종료 상태를 확인합니다. + echo "Merge conflict detected. Resolving by applying remote changes." + git checkout --theirs $(git diff --name-only --diff-filter=U) # 충돌이 발생한 파일에 원격 변경 사항을 적용합니다. + git add . # 충돌이 해결된 파일을 스테이징합니다. + git commit -m "Resolved merge conflicts by applying remote changes." # 커밋 메시지를 작성하여 충돌 해결을 커밋합니다. + else + echo "Merge successful, no conflicts detected." + fi - ./gradlew clean build - ./gradlew openapi3 - docker rm bbo-gak-server_back_1 --force - docker rmi bbo-gak-server_back + ./gradlew clean build + ./gradlew openapi3 + docker rm bbo-gak-server-back-1 --force + docker rmi bbo-gak-server-back docker-compose -f docker-compose-dev.yml up --build -d diff --git a/build.gradle b/build.gradle index 67101b2..e1eeef0 100644 --- a/build.gradle +++ b/build.gradle @@ -45,6 +45,9 @@ dependencies { implementation 'com.h2database:h2' testImplementation 'com.h2database:h2' + //sentry + implementation 'io.sentry:sentry-spring-boot-starter-jakarta:7.14.0' + // Test testRuntimeOnly 'org.junit.platform:junit-platform-launcher' testImplementation 'org.springframework.boot:spring-boot-starter-test' diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml index a4f4ae6..7be8af6 100644 --- a/docker-compose-dev.yml +++ b/docker-compose-dev.yml @@ -1,5 +1,3 @@ -version: '3.8' - services: back: build: @@ -29,8 +27,38 @@ services: - GOOGLE_LOGIN_CLIENT_ID=${GOOGLE_LOGIN_CLIENT_ID} - GOOGLE_LOGIN_CLIENT_SECRET=${GOOGLE_LOGIN_CLIENT_SECRET} - GOOGLE_LOGIN_REDIRECT_URI=${GOOGLE_LOGIN_REDIRECT_URI} + - SENTRY_DSN=${SENTRY_DSN} depends_on: - mysql + networks: + - bbogak + + nginx: + image: nginx:latest + container_name: nginx + volumes: + - /etc/nginx/:/etc/nginx/ + - ./data/certbot/conf:/etc/letsencrypt + - ./data/certbot/www:/var/www/certbot + ports: + - "80:80" + - "443:443" + depends_on: + - back + networks: + - bbogak + command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'" + + certbot: + container_name: certbot + image: certbot/certbot + restart: unless-stopped + volumes: + - ./data/certbot/conf:/etc/letsencrypt + - ./data/certbot/www:/var/www/certbot + entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'" + networks: + - bbogak mysql: image: mysql:8.0 @@ -44,6 +72,11 @@ services: - "3306:3306" volumes: - mysql_data:/var/lib/mysql - + networks: + - bbogak volumes: mysql_data: + +networks: + bbogak: + driver: bridge \ No newline at end of file diff --git a/nginx/Dockerfile b/nginx/Dockerfile new file mode 100644 index 0000000..834b701 --- /dev/null +++ b/nginx/Dockerfile @@ -0,0 +1,3 @@ +FROM nginx:latest +RUN rm /etc/nginx/conf.d/default.conf +COPY nginx.conf /etc/nginx/conf.d \ No newline at end of file diff --git a/nginx/nginx.conf b/nginx/nginx.conf new file mode 100644 index 0000000..96b8fbb --- /dev/null +++ b/nginx/nginx.conf @@ -0,0 +1,41 @@ +events { + worker_connections 1024; +} + +https { + upstream was { + server backend:8080; #서비스명 + } + + server { + listen 80; + server_name dev.anifriends.site; # 발급한 도메인 주소 + server_tokens off; + + location /.well-known/acme-challenge/ { + root /var/www/certbot; # Certbot을 통해 Let's Encrypt 인증서를 발급받을 때 사용하는 경로 + } + + location / { + return 301 https://$host$request_uri; # 모든 HTTP 요청을 HTTPS로 리다이렉션 + } + } + + server { + listen 443 ssl; + server_name dev.anifriends.site; + server_tokens off; + + ssl_certificate /etc/letsencrypt/live/dev.anifriends.site/fullchain.pem; # SSL/TLS 인증서 경로 + ssl_certificate_key /etc/letsencrypt/live/dev.anifriends.site/privkey.pem; # SSL/TLS 개인 키 경로 + include /etc/letsencrypt/options-ssl-nginx.conf; # Let's Encrypt에서 제공하는 Nginx SSL 옵션 + ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; + + location / { + proxy_pass http://was; + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/server/bbo_gak/domain/card/entity/CardCopyInfo.java b/src/main/java/com/server/bbo_gak/domain/card/entity/CardCopyInfo.java index 4d7af8f..d08b72e 100644 --- a/src/main/java/com/server/bbo_gak/domain/card/entity/CardCopyInfo.java +++ b/src/main/java/com/server/bbo_gak/domain/card/entity/CardCopyInfo.java @@ -13,9 +13,13 @@ import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; +import org.hibernate.annotations.SQLDelete; +import org.hibernate.annotations.SQLRestriction; @Getter @Entity +@SQLRestriction("deleted = false") +@SQLDelete(sql = "UPDATE card_copy_info SET deleted = true WHERE card_copy_info_id = ?") @NoArgsConstructor(access = AccessLevel.PROTECTED) public class CardCopyInfo extends BaseEntity { diff --git a/src/main/java/com/server/bbo_gak/domain/card/entity/CardImage.java b/src/main/java/com/server/bbo_gak/domain/card/entity/CardImage.java index 1eb6f3a..c15a4b2 100644 --- a/src/main/java/com/server/bbo_gak/domain/card/entity/CardImage.java +++ b/src/main/java/com/server/bbo_gak/domain/card/entity/CardImage.java @@ -1,5 +1,6 @@ package com.server.bbo_gak.domain.card.entity; +import com.server.bbo_gak.global.common.BaseEntity; import com.server.bbo_gak.global.constant.FileExtension; import jakarta.persistence.Column; import jakarta.persistence.Entity; @@ -15,11 +16,15 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import org.hibernate.annotations.SQLDelete; +import org.hibernate.annotations.SQLRestriction; @Getter @Entity +@SQLRestriction("deleted = false") +@SQLDelete(sql = "UPDATE card_image SET deleted = true WHERE card_image_id = ?") @NoArgsConstructor(access = AccessLevel.PROTECTED) -public class CardImage { +public class CardImage extends BaseEntity { private final String TYPE = "card_content"; @Id diff --git a/src/main/java/com/server/bbo_gak/domain/card/entity/CardMemo.java b/src/main/java/com/server/bbo_gak/domain/card/entity/CardMemo.java index 895a263..4657921 100644 --- a/src/main/java/com/server/bbo_gak/domain/card/entity/CardMemo.java +++ b/src/main/java/com/server/bbo_gak/domain/card/entity/CardMemo.java @@ -12,9 +12,13 @@ import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; +import org.hibernate.annotations.SQLDelete; +import org.hibernate.annotations.SQLRestriction; @Getter @Entity +@SQLRestriction("deleted = false") +@SQLDelete(sql = "UPDATE card_memo SET deleted = true WHERE card_memo_id = ?") @NoArgsConstructor(access = AccessLevel.PROTECTED) public class CardMemo extends BaseEntity { diff --git a/src/main/java/com/server/bbo_gak/domain/card/entity/CardTag.java b/src/main/java/com/server/bbo_gak/domain/card/entity/CardTag.java index e7112ab..bdb8041 100644 --- a/src/main/java/com/server/bbo_gak/domain/card/entity/CardTag.java +++ b/src/main/java/com/server/bbo_gak/domain/card/entity/CardTag.java @@ -12,9 +12,13 @@ import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; +import org.hibernate.annotations.SQLDelete; +import org.hibernate.annotations.SQLRestriction; @Getter @Entity +@SQLRestriction("deleted = false") +@SQLDelete(sql = "UPDATE card_tag SET deleted = true WHERE card_tag_id = ?") @NoArgsConstructor(access = AccessLevel.PROTECTED) public class CardTag extends BaseEntity { diff --git a/src/main/java/com/server/bbo_gak/domain/card/entity/CardType.java b/src/main/java/com/server/bbo_gak/domain/card/entity/CardType.java index 8fd7bfb..9503672 100644 --- a/src/main/java/com/server/bbo_gak/domain/card/entity/CardType.java +++ b/src/main/java/com/server/bbo_gak/domain/card/entity/CardType.java @@ -14,9 +14,13 @@ import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; +import org.hibernate.annotations.SQLDelete; +import org.hibernate.annotations.SQLRestriction; @Getter @Entity +@SQLRestriction("deleted = false") +@SQLDelete(sql = "UPDATE card_type SET deleted = true WHERE card_type_id = ?") @NoArgsConstructor(access = AccessLevel.PROTECTED) public class CardType extends BaseEntity { diff --git a/src/main/java/com/server/bbo_gak/domain/card/entity/Tag.java b/src/main/java/com/server/bbo_gak/domain/card/entity/Tag.java index e378517..dddf4c4 100644 --- a/src/main/java/com/server/bbo_gak/domain/card/entity/Tag.java +++ b/src/main/java/com/server/bbo_gak/domain/card/entity/Tag.java @@ -1,6 +1,8 @@ package com.server.bbo_gak.domain.card.entity; import com.server.bbo_gak.domain.user.entity.Job; +import com.server.bbo_gak.global.common.BaseEntity; + import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.EnumType; @@ -11,11 +13,15 @@ import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; +import org.hibernate.annotations.SQLDelete; +import org.hibernate.annotations.SQLRestriction; @Getter @Entity +@SQLRestriction("deleted = false") +@SQLDelete(sql = "UPDATE tag SET deleted = true WHERE tag_id = ?") @NoArgsConstructor(access = AccessLevel.PROTECTED) -public class Tag { +public class Tag extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/src/main/java/com/server/bbo_gak/domain/notification/entity/Notification.java b/src/main/java/com/server/bbo_gak/domain/notification/entity/Notification.java index 9cfaf72..7c8cc0e 100644 --- a/src/main/java/com/server/bbo_gak/domain/notification/entity/Notification.java +++ b/src/main/java/com/server/bbo_gak/domain/notification/entity/Notification.java @@ -18,9 +18,13 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import org.hibernate.annotations.SQLDelete; +import org.hibernate.annotations.SQLRestriction; @Getter @Entity +@SQLRestriction("deleted = false") +@SQLDelete(sql = "UPDATE notification SET deleted = true WHERE notification_id = ?") @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Notification extends BaseEntity { diff --git a/src/main/java/com/server/bbo_gak/domain/recruit/controller/RecruitController.java b/src/main/java/com/server/bbo_gak/domain/recruit/controller/RecruitController.java index 6829e07..97a7c3c 100644 --- a/src/main/java/com/server/bbo_gak/domain/recruit/controller/RecruitController.java +++ b/src/main/java/com/server/bbo_gak/domain/recruit/controller/RecruitController.java @@ -5,6 +5,7 @@ import com.server.bbo_gak.domain.recruit.dto.request.RecruitUpdateSiteUrlRequest; import com.server.bbo_gak.domain.recruit.dto.request.RecruitUpdateStatusRequest; import com.server.bbo_gak.domain.recruit.dto.request.RecruitUpdateTitleRequest; +import com.server.bbo_gak.domain.recruit.dto.response.RecruitGetInnerResponse; import com.server.bbo_gak.domain.recruit.dto.response.RecruitGetResponse; import com.server.bbo_gak.domain.recruit.service.RecruitService; import com.server.bbo_gak.domain.user.entity.User; @@ -36,6 +37,14 @@ public ResponseEntity> getTotalRecruitList( return ResponseEntity.ok(recruitService.getTotalRecruitList(user)); } + @GetMapping("{id}") + public ResponseEntity getRecruitInnerInfo( + @AuthUser User user, + @PathVariable("id") Long id + ) { + return ResponseEntity.ok(recruitService.getRecruit(user, id)); + } + @GetMapping("/bySeason") public ResponseEntity> getRecruitListBySeason( diff --git a/src/main/java/com/server/bbo_gak/domain/recruit/dto/response/RecruitGetInnerResponse.java b/src/main/java/com/server/bbo_gak/domain/recruit/dto/response/RecruitGetInnerResponse.java new file mode 100644 index 0000000..1828a29 --- /dev/null +++ b/src/main/java/com/server/bbo_gak/domain/recruit/dto/response/RecruitGetInnerResponse.java @@ -0,0 +1,25 @@ +package com.server.bbo_gak.domain.recruit.dto.response; + +import com.server.bbo_gak.domain.recruit.entity.Recruit; +import lombok.Builder; + +@Builder +public record RecruitGetInnerResponse( + Long id, + String title, + String season, + String siteUrl, + String recruitStatus +) { + + public static RecruitGetInnerResponse from(Recruit recruit) { + + return RecruitGetInnerResponse.builder() + .id(recruit.getId()) + .title(recruit.getTitle()) + .season(recruit.getSeason().getName()) + .siteUrl(recruit.getSiteUrl()) + .recruitStatus(recruit.getRecruitStatus().getValue()) + .build(); + } +} diff --git a/src/main/java/com/server/bbo_gak/domain/recruit/entity/RecruitSchedule.java b/src/main/java/com/server/bbo_gak/domain/recruit/entity/RecruitSchedule.java index e88c96c..f0f3b2d 100644 --- a/src/main/java/com/server/bbo_gak/domain/recruit/entity/RecruitSchedule.java +++ b/src/main/java/com/server/bbo_gak/domain/recruit/entity/RecruitSchedule.java @@ -1,5 +1,6 @@ package com.server.bbo_gak.domain.recruit.entity; +import com.server.bbo_gak.global.common.BaseEntity; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.EnumType; @@ -15,11 +16,15 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import org.hibernate.annotations.SQLDelete; +import org.hibernate.annotations.SQLRestriction; @Getter @Entity +@SQLRestriction("deleted = false") +@SQLDelete(sql = "UPDATE recruit_schedule SET deleted = true WHERE recruit_schedule_id = ?") @NoArgsConstructor(access = AccessLevel.PROTECTED) -public class RecruitSchedule { +public class RecruitSchedule extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/src/main/java/com/server/bbo_gak/domain/recruit/entity/Season.java b/src/main/java/com/server/bbo_gak/domain/recruit/entity/Season.java index 67b5f59..616a082 100644 --- a/src/main/java/com/server/bbo_gak/domain/recruit/entity/Season.java +++ b/src/main/java/com/server/bbo_gak/domain/recruit/entity/Season.java @@ -1,6 +1,7 @@ package com.server.bbo_gak.domain.recruit.entity; import com.server.bbo_gak.domain.user.entity.User; +import com.server.bbo_gak.global.common.BaseEntity; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.FetchType; @@ -13,12 +14,16 @@ import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; +import org.hibernate.annotations.SQLDelete; +import org.hibernate.annotations.SQLRestriction; @Getter @Entity @Table(name = "recruit_season") +@SQLRestriction("deleted = false") +@SQLDelete(sql = "UPDATE recruit_season SET deleted = true WHERE recruit_season_id = ?") @NoArgsConstructor(access = AccessLevel.PROTECTED) -public class Season { +public class Season extends BaseEntity { String name; @Id diff --git a/src/main/java/com/server/bbo_gak/domain/recruit/service/RecruitService.java b/src/main/java/com/server/bbo_gak/domain/recruit/service/RecruitService.java index a054f9c..20dba03 100644 --- a/src/main/java/com/server/bbo_gak/domain/recruit/service/RecruitService.java +++ b/src/main/java/com/server/bbo_gak/domain/recruit/service/RecruitService.java @@ -2,6 +2,7 @@ import com.server.bbo_gak.domain.recruit.dao.RecruitRepository; import com.server.bbo_gak.domain.recruit.dto.request.RecruitCreateRequest; +import com.server.bbo_gak.domain.recruit.dto.response.RecruitGetInnerResponse; import com.server.bbo_gak.domain.recruit.dto.response.RecruitGetResponse; import com.server.bbo_gak.domain.recruit.entity.Recruit; import com.server.bbo_gak.domain.recruit.entity.RecruitSchedule; @@ -89,6 +90,11 @@ private boolean isNeedsScheduleUpdate(Recruit recruit) { .allMatch(schedule -> schedule.getDeadLine().isBefore(LocalDate.now())); } + public RecruitGetInnerResponse getRecruit(User user, Long recruitId) { + Recruit recruit = findRecruitByUserAndId(user, recruitId); + return RecruitGetInnerResponse.from(recruit); + } + @Transactional public RecruitGetResponse createRecruit(User user, RecruitCreateRequest request) { diff --git a/src/main/java/com/server/bbo_gak/domain/user/entity/User.java b/src/main/java/com/server/bbo_gak/domain/user/entity/User.java index 61b77a9..ad27d37 100644 --- a/src/main/java/com/server/bbo_gak/domain/user/entity/User.java +++ b/src/main/java/com/server/bbo_gak/domain/user/entity/User.java @@ -14,11 +14,15 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.experimental.SuperBuilder; +import org.hibernate.annotations.SQLDelete; +import org.hibernate.annotations.SQLRestriction; @Getter @Entity @SuperBuilder @NoArgsConstructor(access = AccessLevel.PROTECTED) +@SQLRestriction("deleted = false") +@SQLDelete(sql = "UPDATE users SET deleted = true WHERE user_id = ?") @Table(name = "users") public class User extends BaseEntity { diff --git a/src/main/java/com/server/bbo_gak/global/config/WebConfig.java b/src/main/java/com/server/bbo_gak/global/config/WebConfig.java index f705947..57e249b 100644 --- a/src/main/java/com/server/bbo_gak/global/config/WebConfig.java +++ b/src/main/java/com/server/bbo_gak/global/config/WebConfig.java @@ -25,7 +25,7 @@ public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("http://114.70.23.79:8080", "http://localhost:8080", "http://52.65.6.74:8080", - "http://localhost:3000") + "http://localhost:3000", "https://www.bbogak.com/", "https://dev.bbogak.com/") .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") .allowedHeaders("*") .allowCredentials(true); diff --git a/src/main/java/com/server/bbo_gak/global/config/security/SecurityConfig.java b/src/main/java/com/server/bbo_gak/global/config/security/SecurityConfig.java index 93588c6..ef04ebf 100644 --- a/src/main/java/com/server/bbo_gak/global/config/security/SecurityConfig.java +++ b/src/main/java/com/server/bbo_gak/global/config/security/SecurityConfig.java @@ -65,7 +65,8 @@ public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); configuration.setAllowedOrigins( List.of("http://114.70.23.79:8080", "http://localhost:8080", "http://52.65.6.74:8080", - "http://localhost:3000", "http://118.67.129.12", "https://bbogak.com")); + "http://localhost:3000", "http://118.67.129.12", "https://bbogak.com", "https://www.bbogak.com/", + "https://dev.bbogak.com/")); configuration.addAllowedMethod("*"); configuration.setAllowedHeaders(List.of("*")); // 허용할 헤더 configuration.setAllowCredentials(true); diff --git a/src/main/java/com/server/bbo_gak/global/config/sentry/SentryConfig.java b/src/main/java/com/server/bbo_gak/global/config/sentry/SentryConfig.java new file mode 100644 index 0000000..93c22ac --- /dev/null +++ b/src/main/java/com/server/bbo_gak/global/config/sentry/SentryConfig.java @@ -0,0 +1,30 @@ +package com.server.bbo_gak.global.config.sentry; + +import com.server.bbo_gak.global.error.exception.BusinessException; +import io.sentry.Sentry; +import io.sentry.SentryOptions; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class SentryConfig { + + @Value("${sentry.dsn}") + private String dsn; + + @Bean + public Sentry.OptionsConfiguration sentryOptions() { + return options -> { + options.setDsn(dsn); + + options.setBeforeSend((event, hint) -> { + // 특정 예외 필터링 로직 + if (event.getThrowable() != null && event.getThrowable() instanceof BusinessException) { + return null; // 이 이벤트는 Sentry로 전송되지 않음 + } + return event; // 필터링하지 않을 경우, 이벤트 반환 + }); + }; + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index b1b5d10..8f34631 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -21,3 +21,7 @@ scheduler: pool: size: 2 +sentry: + dsn: ${SENTRY_DSN} + exception-resolver-order: -2147483647 + tracesSampleRate: 1.0 diff --git a/src/test/java/com/server/bbo_gak/domain/recruit/controller/RecruitControllerTest.java b/src/test/java/com/server/bbo_gak/domain/recruit/controller/RecruitControllerTest.java index 8f535ea..725828a 100644 --- a/src/test/java/com/server/bbo_gak/domain/recruit/controller/RecruitControllerTest.java +++ b/src/test/java/com/server/bbo_gak/domain/recruit/controller/RecruitControllerTest.java @@ -17,6 +17,7 @@ import com.server.bbo_gak.domain.recruit.dto.request.RecruitUpdateSiteUrlRequest; import com.server.bbo_gak.domain.recruit.dto.request.RecruitUpdateStatusRequest; import com.server.bbo_gak.domain.recruit.dto.request.RecruitUpdateTitleRequest; +import com.server.bbo_gak.domain.recruit.dto.response.RecruitGetInnerResponse; import com.server.bbo_gak.domain.recruit.dto.response.RecruitGetResponse; import com.server.bbo_gak.domain.recruit.dto.response.RecruitScheduleGetResponse; import com.server.bbo_gak.domain.recruit.entity.RecruitScheduleStage; @@ -249,6 +250,36 @@ class 공고_생성 { } } + @Nested + class 공고_조회 { + + RecruitGetInnerResponse response = RecruitGetInnerResponse.builder() + .id(1L) + .title("New Title") + .season("2024 상반기") + .siteUrl("https://example.com") + .recruitStatus(RecruitStatus.APPLICATION_COMPLETED.getValue()) + .build(); + + @Test + public void 성공() throws Exception { + mockMvc.perform( + restDocsFactory.createRequest(DEFAULT_URL + "/{id}", null, HttpMethod.GET, objectMapper, 1L)) + .andExpect(status().isOk()) + .andDo(restDocsFactory.getSuccessResource("[GET] 공고 조회 성공", "공고 조회", "Recruit", null, response)); + + } + + @Test + public void 찾을수_없음_실패() throws Exception { + + mockMvc.perform( + restDocsFactory.createRequest(DEFAULT_URL + "/{id}", null, HttpMethod.GET, objectMapper, 100L)) + .andExpect(status().isNotFound()) + .andDo(restDocsFactory.getFailureResource("[GET] 공고 조회 실패", "Recruit", null)); + } + } + @Nested class 공고_삭제 { diff --git a/src/test/resources/application-test.yml b/src/test/resources/application-test.yml index 04360d8..075d1ee 100644 --- a/src/test/resources/application-test.yml +++ b/src/test/resources/application-test.yml @@ -47,4 +47,9 @@ google: scheduler: thread: pool: - size: 2 \ No newline at end of file + size: 2 + +sentry: + dsn: https://b0e61ee9ddb2c12240759111df8b607c@o4505869811908608.ingest.us.sentry.io/4507831077240832 + exception-resolver-order: -2147483647 + tracesSampleRate: 1.0 \ No newline at end of file diff --git a/src/test/resources/card-test-data.sql b/src/test/resources/card-test-data.sql index 82d5ae4..765379b 100644 --- a/src/test/resources/card-test-data.sql +++ b/src/test/resources/card-test-data.sql @@ -31,14 +31,14 @@ INSERT INTO card (deleted, copy_flag, access_time, card_id, created_at, update_a VALUES (false, true, '2024-07-24 21:22:04.000000', 6, '2024-07-24 21:22:07.000000', '2024-07-24 21:22:08.000000', 1, 'test_contents', 'test_title', 1); -INSERT INTO tag (tag_id, name, tag_type, job) -VALUES (1, '스프링', 'CAPABILITY', 'DEVELOPER'); -INSERT INTO tag (tag_id, name, tag_type, job) -VALUES (2, '리액트', 'CAPABILITY', 'DEVELOPER'); -INSERT INTO tag (tag_id, name, tag_type, job) -VALUES (3, '알고리즘', 'CAPABILITY', 'DEVELOPER'); -INSERT INTO tag (tag_id, name, tag_type, job) -VALUES (4, '봉사활동', 'PERSONALITY', 'DESIGNER'); +INSERT INTO tag (tag_id, name, tag_type, job, deleted, update_at, created_at) +VALUES (1, '스프링', 'CAPABILITY', 'DEVELOPER', false, '2024-07-24 21:26:28.000000', '2024-07-24 21:26:28.000000'); +INSERT INTO tag (tag_id, name, tag_type, job, deleted, update_at, created_at) +VALUES (2, '리액트', 'CAPABILITY', 'DEVELOPER', false, '2024-07-24 21:26:28.000000', '2024-07-24 21:26:28.000000'); +INSERT INTO tag (tag_id, name, tag_type, job, deleted, update_at, created_at) +VALUES (3, '알고리즘', 'CAPABILITY', 'DEVELOPER', false, '2024-07-24 21:26:28.000000', '2024-07-24 21:26:28.000000'); +INSERT INTO tag (tag_id, name, tag_type, job, deleted, update_at, created_at) +VALUES (4, '봉사활동', 'PERSONALITY', 'DESIGNER', false, '2024-07-24 21:26:28.000000', '2024-07-24 21:26:28.000000'); INSERT INTO card_type (card_type_id, card_type_value, card_id, deleted, update_at, created_at) VALUES (1, 'EXPERIENCE', 1, false, '2024-07-24 21:26:28.000000', '2024-07-24 21:26:28.000000'); diff --git a/src/test/resources/notification-test-data.sql b/src/test/resources/notification-test-data.sql index f1c807e..c3482d0 100644 --- a/src/test/resources/notification-test-data.sql +++ b/src/test/resources/notification-test-data.sql @@ -3,10 +3,10 @@ VALUES (false, '2024-07-24 21:27:20.000000', '2024-07-24 21:27:21.000000', 1, 'A 'test', 'USER', 'DEVELOPER'); -- 다음으로 recruit_season 테이블에 데이터를 삽입합니다. -INSERT INTO recruit_season (recruit_season_id, name, user_id) -VALUES (1, '2024 상반기', 1); -INSERT INTO recruit_season (recruit_season_id, name, user_id) -VALUES (2, '2024 하반기', 1); +INSERT INTO recruit_season (recruit_season_id, name, user_id, deleted, update_at, created_at) +VALUES (1, '2024 상반기', 1, false, '2024-07-24 21:26:28.000000', '2024-07-24 21:26:28.000000'); +INSERT INTO recruit_season (recruit_season_id, name, user_id, deleted, update_at, created_at) +VALUES (2, '2024 하반기', 1, false, '2024-07-24 21:26:28.000000', '2024-07-24 21:26:28.000000'); INSERT INTO recruit (recruit_id, title, site_url, recruit_status, recruit_season_id, user_id, created_at, update_at, deleted) @@ -16,6 +16,9 @@ VALUES (1, 'Title for one day left', 'http://example.com/1', 'DOCUMENT_PASSED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, false); -- RecruitSchedule 테이블에 데이터 삽입 -INSERT INTO recruit_schedule (recruit_schedule_id, recruit_id, recruit_schedule_stage, dead_line) -VALUES (1, 1, 'FIRST_INTERVIEW', CURRENT_DATE + 1), -- 하루 남은 스케줄 - (2, 2, 'CLOSING_DOCUMENT', CURRENT_DATE + 2); -- 하루 이상 남은 스케줄 \ No newline at end of file +INSERT INTO recruit_schedule (recruit_schedule_id, recruit_id, recruit_schedule_stage, dead_line, deleted, created_at, + update_at) +VALUES (1, 1, 'FIRST_INTERVIEW', CURRENT_DATE + 1, false, '2024-07-24 21:27:20.000000', + '2024-07-24 21:27:21.000000'), -- 하루 남은 스케줄 + (2, 2, 'CLOSING_DOCUMENT', CURRENT_DATE + 2, false, '2024-07-24 21:27:20.000000', + '2024-07-24 21:27:21.000000'); -- 하루 이상 남은 스케줄 \ No newline at end of file diff --git a/src/test/resources/recruit-test-data.sql b/src/test/resources/recruit-test-data.sql index 983f43d..63e64c4 100644 --- a/src/test/resources/recruit-test-data.sql +++ b/src/test/resources/recruit-test-data.sql @@ -8,13 +8,13 @@ VALUES (false, '2024-07-24 21:27:20.000000', '2024-07-24 21:27:21.000000', 1, 'A ; -- Season 테이블에 데이터 삽입 -INSERT INTO recruit_season (recruit_season_id, name, user_id) -VALUES (1, '2024 상반기', 1), - (2, '2024 하반기', 1), - (3, '2024 상반기', 2), - (4, '2024 하반기', 2), - (5, '2024 상반기', 3), - (6, '2024 하반기', 3) +INSERT INTO recruit_season (recruit_season_id, name, user_id, deleted, update_at, created_at) +VALUES (1, '2024 상반기', 1, false, '2024-07-24 21:27:20.000000', '2024-07-24 21:27:21.000000'), + (2, '2024 하반기', 1, false, '2024-07-24 21:27:20.000000', '2024-07-24 21:27:21.000000'), + (3, '2024 상반기', 2, false, '2024-07-24 21:27:20.000000', '2024-07-24 21:27:21.000000'), + (4, '2024 하반기', 2, false, '2024-07-24 21:27:20.000000', '2024-07-24 21:27:21.000000'), + (5, '2024 상반기', 3, false, '2024-07-24 21:27:20.000000', '2024-07-24 21:27:21.000000'), + (6, '2024 하반기', 3, false, '2024-07-24 21:27:20.000000', '2024-07-24 21:27:21.000000') ; -- Recruit 테이블에 데이터 삽입 @@ -37,15 +37,15 @@ VALUES (1, 'Title for one day left', 'http://example.com/1', 'DOCUMENT_PASSED', ; -- RecruitSchedule 테이블에 데이터 삽입 -INSERT INTO recruit_schedule (recruit_schedule_id, recruit_id, recruit_schedule_stage, dead_line) -VALUES (1, 1, 'FIRST_INTERVIEW', '2024-12-31'), - (2, 4, 'FIRST_INTERVIEW', TIMESTAMPADD(DAY, 3, CURRENT_TIMESTAMP)), - (3, 5, 'FIRST_INTERVIEW', TIMESTAMPADD(DAY, 1, CURRENT_TIMESTAMP)), - (4, 6, 'FIRST_INTERVIEW', TIMESTAMPADD(DAY, 2, CURRENT_TIMESTAMP)), - (5, 6, 'SECOND_INTERVIEW', TIMESTAMPADD(DAY, 3, CURRENT_TIMESTAMP)), - (6, 7, 'FIRST_INTERVIEW', TIMESTAMPADD(DAY, -2, CURRENT_TIMESTAMP)), - (7, 7, 'SECOND_INTERVIEW', TIMESTAMPADD(DAY, -1, CURRENT_TIMESTAMP)), - (8, 7, 'FINAL_INTERVIEW', TIMESTAMPADD(DAY, 1, CURRENT_TIMESTAMP)) +INSERT INTO recruit_schedule (recruit_schedule_id, recruit_id, recruit_schedule_stage, dead_line, deleted, update_at, created_at) +VALUES (1, 1, 'FIRST_INTERVIEW', TIMESTAMPADD(DAY, 3, CURRENT_TIMESTAMP), false, '2024-07-24 21:26:28.000000', '2024-07-24 21:26:28.000000'), + (2, 4, 'FIRST_INTERVIEW', TIMESTAMPADD(DAY, 3, CURRENT_TIMESTAMP), false, '2024-07-24 21:26:28.000000', '2024-07-24 21:26:28.000000'), + (3, 5, 'FIRST_INTERVIEW', TIMESTAMPADD(DAY, 1, CURRENT_TIMESTAMP), false, '2024-07-24 21:26:28.000000', '2024-07-24 21:26:28.000000'), + (4, 6, 'FIRST_INTERVIEW', TIMESTAMPADD(DAY, 2, CURRENT_TIMESTAMP), false, '2024-07-24 21:26:28.000000', '2024-07-24 21:26:28.000000'), + (5, 6, 'SECOND_INTERVIEW', TIMESTAMPADD(DAY, 3, CURRENT_TIMESTAMP), false, '2024-07-24 21:26:28.000000', '2024-07-24 21:26:28.000000'), + (6, 7, 'FIRST_INTERVIEW', TIMESTAMPADD(DAY, -2, CURRENT_TIMESTAMP), false, '2024-07-24 21:26:28.000000', '2024-07-24 21:26:28.000000'), + (7, 7, 'SECOND_INTERVIEW', TIMESTAMPADD(DAY, -1, CURRENT_TIMESTAMP), false, '2024-07-24 21:26:28.000000', '2024-07-24 21:26:28.000000'), + (8, 7, 'FINAL_INTERVIEW', TIMESTAMPADD(DAY, 1, CURRENT_TIMESTAMP), false, '2024-07-24 21:26:28.000000', '2024-07-24 21:26:28.000000') ; INSERT INTO card (deleted, copy_flag, access_time, card_id, created_at, update_at, user_id, content, title, recruit_id) diff --git a/src/test/resources/season-test-data.sql b/src/test/resources/season-test-data.sql index f3825ed..8d37979 100644 --- a/src/test/resources/season-test-data.sql +++ b/src/test/resources/season-test-data.sql @@ -4,10 +4,10 @@ VALUES (false, '2024-07-24 21:27:20.000000', '2024-07-24 21:27:21.000000', 1, 'A (false, '2024-07-24 21:27:20.000000', '2024-07-24 21:27:21.000000', 2, 'AuthTestUser', 'email', 'test', 'test', 'test123', 'USER', 'DEVELOPER'); -INSERT INTO recruit_season (recruit_season_id, name, user_id) -VALUES (1, '2024 상반기', 2), - (2, '2024 하반기', 2), - (3, '2025 상반기', 2); +INSERT INTO recruit_season (recruit_season_id, name, user_id, deleted, update_at, created_at) +VALUES (1, '2024 상반기', 2, false, '2024-07-24 21:26:28.000000', '2024-07-24 21:26:28.000000'), + (2, '2024 하반기', 2, false, '2024-07-24 21:26:28.000000', '2024-07-24 21:26:28.000000'), + (3, '2025 상반기', 2, false, '2024-07-24 21:26:28.000000', '2024-07-24 21:26:28.000000');