diff --git a/.github/workflows/checkstyle-validation.yml b/.github/workflows/checkstyle-validation.yml index caba78380..fa88a50a3 100644 --- a/.github/workflows/checkstyle-validation.yml +++ b/.github/workflows/checkstyle-validation.yml @@ -1,8 +1,10 @@ name: ๐Ÿ‘ฎCheckstyle validation on: + push: + branches: [ 1151-feature-42api-๋ชจ๋‹ˆํ„ฐ๋ง์Šค๋ ˆ๋“œ์—์ž‘์—… ] pull_request: - branches: [ main, dev , recruit-dev] + branches: [ main, dev ] jobs: checkstyle: diff --git a/.github/workflows/http-client.env.json b/.github/workflows/http-client.env.json new file mode 100644 index 000000000..0551c776c --- /dev/null +++ b/.github/workflows/http-client.env.json @@ -0,0 +1,5 @@ +{ + "dev": { + "name": "value" + } +} diff --git a/.github/workflows/test-code-validation.yml b/.github/workflows/test-code-validation.yml index d0caf7823..299d7d01b 100644 --- a/.github/workflows/test-code-validation.yml +++ b/.github/workflows/test-code-validation.yml @@ -1,8 +1,10 @@ name: ๐Ÿ’ป Test code validation on: + push: + branches: [ 1151-feature-42api-๋ชจ๋‹ˆํ„ฐ๋ง์Šค๋ ˆ๋“œ์—์ž‘์—… ] pull_request: - branches: [main, dev] + branches: [ main, dev ] jobs: test: diff --git a/.github/workflows/test-deploy.yml b/.github/workflows/test-deploy.yml index fb05335fe..3c8acb89f 100644 --- a/.github/workflows/test-deploy.yml +++ b/.github/workflows/test-deploy.yml @@ -1,22 +1,10 @@ -# This workflow uses actions that are not certified by GitHub. -# They are provided by a third-party and are governed by -# separate terms of service, privacy policy, and support -# documentation. -# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time -# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle - name: test-deploy on: push: - branches: [ dev ] + branches: [ dev, 1151-feature-42api-๋ชจ๋‹ˆํ„ฐ๋ง์Šค๋ ˆ๋“œ์—์ž‘์—… ] workflow_dispatch: -env: - DOCKER_USER: ${{ secrets.DOCKER_USER }} - DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} - IMAGE_NAME: wken5577/test-migrate-server - permissions: contents: read @@ -41,52 +29,8 @@ jobs: echo "${{ secrets.MIGRATE_APPLICATION_YML }}" | base64 -d > application.yml shell: bash - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ env.DOCKER_USER }} - password: ${{ env.DOCKER_PASSWORD }} - - name: Test with Gradle run: ./gradlew clean test - name: Build with Gradle run: ./gradlew clean build -x test - - - name: build new docker image as latest tag - run: | - docker build -t ${{ env.IMAGE_NAME }}:latest . - docker push ${{ env.IMAGE_NAME }}:latest - - - name: Create the configuration file - run: | - cat << EOF > config.json - { - "AutoScalingGroupName": "gg-dev", - "DesiredConfiguration": { - "LaunchTemplate": { - "LaunchTemplateId": "${{ secrets.DEV_LAUNCH_TEMPLATE_ID }}", - "Version": "\$Latest" - } - }, - "Preferences": { - "MinHealthyPercentage": 100, - "MaxHealthyPercentage": 110, - "InstanceWarmup": 300, - "ScaleInProtectedInstances": "Ignore", - "StandbyInstances": "Ignore" - } - } - EOF - cat config.json - - - name: Configure AWS CLI - uses: aws-actions/configure-aws-credentials@v2 - with: - aws-access-key-id: ${{ secrets.AWS_TEST_MIGRATE_SECURITY_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.AWS_TEST_MIGRATE_SECURITY_SECRET_KEY }} - aws-region: ap-northeast-2 - - - name: Trigger Instance Refresh - run: | - aws autoscaling start-instance-refresh --cli-input-json file://config.json diff --git a/build.gradle b/build.gradle index f9deb3d1c..60c83209f 100644 --- a/build.gradle +++ b/build.gradle @@ -8,6 +8,11 @@ plugins { id 'checkstyle' } +java { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 +} + editorconfig { excludes = ['build'] } diff --git a/gg-admin-repo/src/test/java/gg/admin/repo/TestSpringBootApplication.java b/gg-admin-repo/src/test/java/gg/admin/repo/TestSpringBootApplication.java index cb0a5c276..b95a2c391 100644 --- a/gg-admin-repo/src/test/java/gg/admin/repo/TestSpringBootApplication.java +++ b/gg-admin-repo/src/test/java/gg/admin/repo/TestSpringBootApplication.java @@ -3,6 +3,6 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication(scanBasePackages = {"gg.recruit.api", "gg.utils", "gg.data", "gg.repo", - "gg.admin.repo", "gg.auth", "gg.pingpong.api"}) + "gg.admin.repo", "gg.auth", "gg.pingpong.api", "gg.calendar.api"}) public class TestSpringBootApplication { } diff --git a/gg-auth/src/main/java/gg/auth/FortyTwoAuthUtil.java b/gg-auth/src/main/java/gg/auth/FortyTwoAuthUtil.java index 9a6b6299d..76633ec37 100644 --- a/gg-auth/src/main/java/gg/auth/FortyTwoAuthUtil.java +++ b/gg-auth/src/main/java/gg/auth/FortyTwoAuthUtil.java @@ -23,17 +23,21 @@ import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; +import gg.auth.config.ScheduleConfig; import gg.utils.exception.ErrorCode; import gg.utils.exception.custom.NotExistException; import gg.utils.exception.user.TokenNotValidException; import gg.utils.external.ApiUtil; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +@Slf4j @Component @RequiredArgsConstructor public class FortyTwoAuthUtil { private final ApiUtil apiUtil; private final OAuth2AuthorizedClientService authorizedClientService; + private final ScheduleConfig scheduleConfig; public String getAccessToken() { Authentication authentication = getAuthenticationFromContext(); @@ -62,6 +66,32 @@ public String refreshAccessToken() { return newClient.getAccessToken().getTokenValue(); } + /* 42event client credential token */ + public String getClientCredentialToken() { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("grant_type", "client_credentials"); + params.add("client_id", scheduleConfig.getClientId()); + params.add("client_secret", scheduleConfig.getClientSecret()); + + try { + Map response = apiUtil.apiCall( + scheduleConfig.getTokenUri(), + Map.class, + headers, + params, + HttpMethod.POST + ); + log.info("Raw Api Response : {}", response); + // System.out.println("Response : " + response); + return (String)response.get("access_token"); + } catch (Exception e) { + throw new TokenNotValidException(); + } + } + private Authentication getAuthenticationFromContext() { SecurityContext context = SecurityContextHolder.getContext(); return context.getAuthentication(); diff --git a/gg-auth/src/main/java/gg/auth/config/ScheduleConfig.java b/gg-auth/src/main/java/gg/auth/config/ScheduleConfig.java new file mode 100644 index 000000000..b58d125b6 --- /dev/null +++ b/gg-auth/src/main/java/gg/auth/config/ScheduleConfig.java @@ -0,0 +1,17 @@ +package gg.auth.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; + +import lombok.Getter; + +@Configuration +@Getter +public class ScheduleConfig { + @Value("${spring.security.oauth2.client.registration.42.client-id}") + private String clientId; + @Value("${spring.security.oauth2.client.registration.42.client-secret}") + private String clientSecret; + @Value("${spring.security.oauth2.client.provider.42.token-uri}") + private String tokenUri; +} diff --git a/gg-calendar-api/src/main/java/gg/api42/ApiClient.java b/gg-calendar-api/src/main/java/gg/api42/ApiClient.java deleted file mode 100644 index aa8cd914e..000000000 --- a/gg-calendar-api/src/main/java/gg/api42/ApiClient.java +++ /dev/null @@ -1,78 +0,0 @@ -package gg.api42; - -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.net.HttpURLConnection; -import java.net.URL; -import java.nio.charset.StandardCharsets; - -import net.minidev.json.JSONObject; -import net.minidev.json.parser.JSONParser; - -public class ApiClient { - private String appId = "u-s4t2ud-c7e81a6ebe4feb0e6d9b40e36455e546e86a75f22695a82292d4d368e7b59773"; - private String appSecret = "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"; - private String apiTokenUrl = "http://localhost:8080/login/oauth2/code/42"; - private String token; - - public String getToken() { - try { - // Prepare JSON payload - JSONObject parameters = new JSONObject(); - parameters.put("grant_type", "client_credentials"); - parameters.put("client_id", appId); // ํ‚ค ์ด๋ฆ„ ๋ณ€๊ฒฝ - parameters.put("client_secret", appSecret); // ํ‚ค ์ด๋ฆ„ ๋ณ€๊ฒฝ - String jsonInputString = parameters.toString(); - - System.out.println("Request: " + jsonInputString); - System.out.println("URL: " + apiTokenUrl); - - // Create connection - URL url = new URL(apiTokenUrl); - HttpURLConnection conn = (HttpURLConnection)url.openConnection(); - conn.setRequestMethod("POST"); - conn.setRequestProperty("Content-Type", "application/json"); - conn.setRequestProperty("Content-Length", String.valueOf(jsonInputString.getBytes().length)); - conn.setDoOutput(true); - - // Send request - try (OutputStream os = conn.getOutputStream()) { - byte[] input = jsonInputString.getBytes(StandardCharsets.UTF_8); - os.write(input, 0, input.length); - } - - // Check response code - int responseCode = conn.getResponseCode(); - if (responseCode != 200) { - System.out.println("HTTP Error: " + responseCode); - System.out.println("Response: " + conn.getResponseMessage()); - return null; - } - - // Read response - try (BufferedReader br = new BufferedReader( - new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) { - StringBuilder response = new StringBuilder(); - String responseLine; - while ((responseLine = br.readLine()) != null) { - response.append(responseLine.trim()); - } - - // Parse JSON response - JSONParser parser = new JSONParser(); // ๋ณ€๊ฒฝ๋œ ๋ถ€๋ถ„ - JSONObject jsonResponse = (JSONObject)parser.parse(response.toString()); // ๋ณ€๊ฒฝ๋œ ๋ถ€๋ถ„ - this.token = (String)jsonResponse.get("access_token"); // ๋ณ€๊ฒฝ๋œ ๋ถ€๋ถ„ - return this.token; - } - - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - - public String getCurrentToken() { - return this.token; - } -} diff --git a/gg-calendar-api/src/main/java/gg/calendar/api/admin/schedule/publicschedule/controller/PublicScheduleAdminController.java b/gg-calendar-api/src/main/java/gg/calendar/api/admin/schedule/publicschedule/controller/PublicScheduleAdminController.java index 0524ff04e..0901fcdf7 100644 --- a/gg-calendar-api/src/main/java/gg/calendar/api/admin/schedule/publicschedule/controller/PublicScheduleAdminController.java +++ b/gg-calendar-api/src/main/java/gg/calendar/api/admin/schedule/publicschedule/controller/PublicScheduleAdminController.java @@ -61,6 +61,5 @@ public ResponseEntity publicScheduleDelete(@PathVariable Long id) { public ResponseEntity publicScheduleDetail(@PathVariable Long id) { PublicScheduleAdminResDto publicScheduleAdminResDto = publicScheduleAdminService.detailPublicSchedule(id); return ResponseEntity.ok(publicScheduleAdminResDto); - } } diff --git a/gg-calendar-api/src/main/java/gg/calendar/api/user/schedule/publicschedule/service/PublicScheduleService.java b/gg-calendar-api/src/main/java/gg/calendar/api/user/schedule/publicschedule/service/PublicScheduleService.java index 5fcc43cf5..28f29f5c9 100644 --- a/gg-calendar-api/src/main/java/gg/calendar/api/user/schedule/publicschedule/service/PublicScheduleService.java +++ b/gg-calendar-api/src/main/java/gg/calendar/api/user/schedule/publicschedule/service/PublicScheduleService.java @@ -90,7 +90,7 @@ public PublicSchedule getPublicScheduleDetailRetrieve(Long scheduleId, Long user User user = userRepository.getById(userId); PublicSchedule publicRetrieveSchedule = publicScheduleRepository.findById(scheduleId) .orElseThrow(() -> new NotExistException(ErrorCode.PUBLIC_SCHEDULE_NOT_FOUND)); - checkAuthor(publicRetrieveSchedule.getAuthor(), user); + // checkAuthor(publicRetrieveSchedule.getAuthor(), user); return publicRetrieveSchedule; } diff --git a/gg-calendar-api/src/main/java/gg/calendar/api/user/utils/controller/response/FortyTwoEventResponse.java b/gg-calendar-api/src/main/java/gg/calendar/api/user/utils/controller/response/FortyTwoEventResponse.java new file mode 100644 index 000000000..435b14218 --- /dev/null +++ b/gg-calendar-api/src/main/java/gg/calendar/api/user/utils/controller/response/FortyTwoEventResponse.java @@ -0,0 +1,40 @@ +package gg.calendar.api.user.utils.controller.response; + +import java.time.LocalDateTime; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class FortyTwoEventResponse { + @JsonProperty("id") + private Long id; + + @JsonProperty("name") + private String name; + + @JsonProperty("description") + private String description; + + @JsonProperty("location") + private String location; + + @JsonProperty("kind") + private String kind; + + @JsonProperty("begin_at") + private LocalDateTime beginAt; + + @JsonProperty("end_at") + private LocalDateTime endAt; + + @JsonProperty("created_at") + private LocalDateTime createdAt; + + @JsonProperty("updated_at") + private LocalDateTime updatedAt; +} diff --git a/gg-calendar-api/src/main/java/gg/calendar/api/user/utils/service/FortyTwoEventApiClient.java b/gg-calendar-api/src/main/java/gg/calendar/api/user/utils/service/FortyTwoEventApiClient.java new file mode 100644 index 000000000..1cca39669 --- /dev/null +++ b/gg-calendar-api/src/main/java/gg/calendar/api/user/utils/service/FortyTwoEventApiClient.java @@ -0,0 +1,40 @@ +package gg.calendar.api.user.utils.service; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Component; +import org.springframework.web.client.HttpClientErrorException; + +import gg.auth.FortyTwoAuthUtil; +import gg.calendar.api.user.utils.controller.response.FortyTwoEventResponse; +import gg.utils.external.ApiUtil; +import lombok.RequiredArgsConstructor; + +@Component +@RequiredArgsConstructor +public class FortyTwoEventApiClient { + private final ApiUtil apiUtil; + private final FortyTwoAuthUtil fortyTwoAuthUtil; + + @Value("https://api.intra.42.fr/v2/campus/29/events") + private String eventUrl; + + public List getEvents() { + ParameterizedTypeReference> responseType = new ParameterizedTypeReference<>() { + }; + + try { + String accessToken = fortyTwoAuthUtil.getClientCredentialToken(); + return apiUtil.callApiWithAccessTokenEvent(eventUrl, accessToken, responseType); + } catch (HttpClientErrorException e) { + if (e.getStatusCode() == HttpStatus.UNAUTHORIZED) { + String refreshToken = fortyTwoAuthUtil.getClientCredentialToken(); + return apiUtil.callApiWithAccessTokenEvent(eventUrl, refreshToken, responseType); + } + throw e; + } + } +} diff --git a/gg-calendar-api/src/main/java/gg/calendar/api/user/utils/service/FortyTwoEventService.java b/gg-calendar-api/src/main/java/gg/calendar/api/user/utils/service/FortyTwoEventService.java new file mode 100644 index 000000000..b07be98bf --- /dev/null +++ b/gg-calendar-api/src/main/java/gg/calendar/api/user/utils/service/FortyTwoEventService.java @@ -0,0 +1,85 @@ +package gg.calendar.api.user.utils.service; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.calendar.api.user.utils.controller.response.FortyTwoEventResponse; +import gg.data.calendar.PublicSchedule; +import gg.data.calendar.type.DetailClassification; +import gg.data.calendar.type.EventTag; +import gg.data.calendar.type.ScheduleStatus; +import gg.repo.calendar.PublicScheduleRepository; +import lombok.RequiredArgsConstructor; + +@Service +@Transactional +@RequiredArgsConstructor +public class FortyTwoEventService { + private final FortyTwoEventApiClient fortyTwoEventApiClient; + private final PublicScheduleRepository publicScheduleRepository; + + public void checkEvent() { + List events = fortyTwoEventApiClient.getEvents(); + List newEvents = filterEvents(events); + saveEventsToPublicSchedule(newEvents); + } + + private List filterEvents(List events) { + return events.stream() + .filter(event -> !isEventExists(event.getName(), event.getBeginAt())) + .collect(Collectors.toList()); + } + + private void saveEventsToPublicSchedule(List events) { + events.forEach(this::convertAndSaveEvent); + } + + private void convertAndSaveEvent(FortyTwoEventResponse event) { + String description = event.getDescription(); + if (description != null && description.length() > 255) { + description = description.substring(0, 255); + } + PublicSchedule publicSchedule = PublicSchedule.builder() + .classification(DetailClassification.EVENT) + .eventTag(determineEventTag(event)) + .author("42Seoul") + .title(event.getName()) + .content(description) + .link("https://profile.intra.42.fr/events") + .status(ScheduleStatus.ACTIVATE) + .startTime(event.getBeginAt()) + .endTime(event.getEndAt()) + .build(); + publicScheduleRepository.save(publicSchedule); + } + + private boolean isEventExists(String title, LocalDateTime beginAt) { + return publicScheduleRepository.existsByTitleAndStartTime(title, beginAt); + } + + private EventTag determineEventTag(FortyTwoEventResponse eventResponse) { + String kind = eventResponse.getKind(); + switch (kind) { + case "pedago": + case "rush": + case "piscine": + case "partnership": + case "event": + case "meet": + case "hackathon": + return EventTag.OFFICIAL_EVENT; + case "meet_up": + return EventTag.WENDS_FORUM; + case "conference": + return EventTag.INSTRUCTION; + default: + return EventTag.ETC; + } + } +} + + diff --git a/gg-calendar-api/src/main/java/gg/calendar/api/user/utils/service/ScheduleCheckService.java b/gg-calendar-api/src/main/java/gg/calendar/api/user/utils/service/ScheduleCheckService.java new file mode 100644 index 000000000..49889fd1e --- /dev/null +++ b/gg-calendar-api/src/main/java/gg/calendar/api/user/utils/service/ScheduleCheckService.java @@ -0,0 +1,25 @@ +package gg.calendar.api.user.utils.service; + +import java.time.LocalDateTime; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.data.calendar.type.ScheduleStatus; +import gg.repo.calendar.PrivateScheduleRepository; +import gg.repo.calendar.PublicScheduleRepository; +import lombok.RequiredArgsConstructor; + +@Service +@Transactional +@RequiredArgsConstructor +public class ScheduleCheckService { + private final PublicScheduleRepository publicScheduleRepository; + private final PrivateScheduleRepository privateScheduleRepository; + + public void deactivateExpiredSchedules() { + publicScheduleRepository.updateExpiredPublicSchedules(ScheduleStatus.DEACTIVATE, ScheduleStatus.ACTIVATE, + LocalDateTime.now()); + privateScheduleRepository.updateRelatedPrivateSchedules(ScheduleStatus.DEACTIVATE, ScheduleStatus.DEACTIVATE); + } +} diff --git a/gg-calendar-api/src/main/java/gg/calendar/api/user/utils/service/ScheduleNotiService.java b/gg-calendar-api/src/main/java/gg/calendar/api/user/utils/service/ScheduleNotiService.java new file mode 100644 index 000000000..29d855ffd --- /dev/null +++ b/gg-calendar-api/src/main/java/gg/calendar/api/user/utils/service/ScheduleNotiService.java @@ -0,0 +1,47 @@ +package gg.calendar.api.user.utils.service; + +import java.time.LocalDateTime; +import java.util.List; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.data.calendar.PrivateSchedule; +import gg.data.calendar.type.ScheduleStatus; +import gg.repo.calendar.PrivateScheduleRepository; +import gg.repo.calendar.PublicScheduleRepository; +import gg.utils.sns.MessageSender; +import lombok.RequiredArgsConstructor; + +@Service +@Transactional +@RequiredArgsConstructor +public class ScheduleNotiService { + private final PublicScheduleRepository publicScheduleRepository; + private final PrivateScheduleRepository privateScheduleRepository; + private final MessageSender messageSender; + private static final String SCHEDULE_MESSAGE_D_DAY = "๐Ÿ“†์ผ์ •์š”์ •๐Ÿงš์œผ๋กœ๋ถ€ํ„ฐ ์•Œ๋ฆผ์ด ๋„์ฐฉํ–ˆ์Šต๋‹ˆ๋‹ค.\n" + + "[42ggCalendar]์™€ ์˜ค๋Š˜์˜ ์ผ์ •์„ ํ™•์ธํ•ด๋ณด์„ธ์š”!\n"; + private static final String SCHEDULE_MESSAGE_BEFORE_D_DAY = "๐Ÿ“…์ผ์ •์š”์ •๐Ÿงš์œผ๋กœ๋ถ€ํ„ฐ ์•Œ๋ฆผ์ด ๋„์ฐฉํ–ˆ์Šต๋‹ˆ๋‹ค.\n" + + "[42ggCalendar]์™€ ๋‚ด์ผ์˜ ์ผ์ •์„ ํ™•์ธํ•ด๋ณด์„ธ์š”!\n"; + + @Transactional + public void sendScheduleNotifications() { + LocalDateTime currentTime = LocalDateTime.now(); + LocalDateTime startOfDay = LocalDateTime.now().toLocalDate().atStartOfDay(); + LocalDateTime endOfDay = startOfDay.plusDays(1).minusNanos(1); + LocalDateTime startDday = startOfDay.plusDays(1); + LocalDateTime endDday = endOfDay.plusDays(1); + + List alarmSchedule = privateScheduleRepository.findSchedulesWithAlarmForBothDays(startOfDay, + endOfDay, startDday, endDday, ScheduleStatus.ACTIVATE); + for (PrivateSchedule schedule : alarmSchedule) { + String message = schedule.getPublicSchedule().getEndTime() + .isBefore(currentTime.plusDays(1)) + ? SCHEDULE_MESSAGE_D_DAY : SCHEDULE_MESSAGE_BEFORE_D_DAY; + messageSender.send(schedule.getUser().getIntraId(), + message + "[" + schedule.getPublicSchedule().getTitle() + "] : " + + schedule.getPublicSchedule().getLink() + "\n"); + } + } +} diff --git a/gg-calendar-api/src/test/java/gg/calendar/api/user/schedule/publicschedule/controller/PublicScheduleControllerTest.java b/gg-calendar-api/src/test/java/gg/calendar/api/user/schedule/publicschedule/controller/PublicScheduleControllerTest.java index 39c5bba9f..82387732a 100644 --- a/gg-calendar-api/src/test/java/gg/calendar/api/user/schedule/publicschedule/controller/PublicScheduleControllerTest.java +++ b/gg-calendar-api/src/test/java/gg/calendar/api/user/schedule/publicschedule/controller/PublicScheduleControllerTest.java @@ -349,7 +349,8 @@ void updatePublicScheduleFailNotMatchAuthor() throws Exception { // when mockMvc.perform( - put("/calendar/public/" + jobPublicSchedule.getId()).header("Authorization", "Bearer " + accessToken) + put("/calendar/public/" + + jobPublicSchedule.getId()).header("Authorization", "Bearer " + accessToken) .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(updateDto))) .andExpect(status().isForbidden()) @@ -391,7 +392,8 @@ void updatePublicScheduleFailExistingAuthorNotMatch() throws Exception { //when & then mockMvc.perform( - put("/calendar/public/" + jobPublicSchedule.getId()).header("Authorization", "Bearer " + accessToken) + put("/calendar/public/" + + jobPublicSchedule.getId()).header("Authorization", "Bearer " + accessToken) .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(updateDto))) .andExpect(status().isForbidden()) @@ -432,7 +434,8 @@ void updatePublicScheduleFailFaultPeriod() throws Exception { // when mockMvc.perform( - put("/calendar/public/" + jobPublicSchedule.getId()).header("Authorization", "Bearer " + accessToken) + put("/calendar/public/" + + jobPublicSchedule.getId()).header("Authorization", "Bearer " + accessToken) .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(updateDto))) .andExpect(status().isBadRequest()) @@ -824,7 +827,8 @@ void retrievePublicScheduleDetailSuccess() throws Exception { publicScheduleRepository.save(publicSchedule); // when mockMvc.perform( - get("/calendar/public/" + publicSchedule.getId()).header("Authorization", "Bearer " + accessToken)) + get("/calendar/public/" + + publicSchedule.getId()).header("Authorization", "Bearer " + accessToken)) .andExpect(status().isOk()) .andExpect(jsonPath("$.title").value("Original Title")) .andExpect(jsonPath("$.content").value("Original Content")) @@ -832,28 +836,6 @@ void retrievePublicScheduleDetailSuccess() throws Exception { .andDo(print()); } - @Test - @DisplayName("[403]๊ณต๊ฐœ์ผ์ •์ƒ์„ธ์กฐํšŒ์‹คํŒจ-์ž‘์„ฑ์ž๊ฐ€ ๋‹ค๋ฅผ ๋•Œ") - void retrievePublicScheduleDetailFailNotMatchAuthor() throws Exception { - // given - PublicSchedule publicSchedule = PublicScheduleCreateEventReqDto.toEntity("another", - PublicScheduleCreateEventReqDto.builder() - .author("another") - .title("Original Title") - .content("Original Content") - .link("https://original.com") - .startTime(LocalDateTime.now()) - .endTime(LocalDateTime.now().plusDays(1)) - .build()); - publicScheduleRepository.save(publicSchedule); - - // when & then - mockMvc.perform( - get("/calendar/public/" + publicSchedule.getId()).header("Authorization", "Bearer " + accessToken)) - .andExpect(status().isForbidden()) - .andDo(print()); - } - @Test @DisplayName("[400]๊ณต๊ฐœ์ผ์ •์ƒ์„ธ์กฐํšŒ์‹คํŒจ-์ž˜๋ชป๋œ id์ผ ๋•Œ(์ˆซ์ž๊ฐ€ ์•„๋‹Œ ๋ฌธ์ž์—ด)") void retrievePublicScheduleDetailFailWrongId() throws Exception { @@ -935,8 +917,10 @@ void retrievePublicScheduleByJobPeriodSuccess() throws Exception { LocalDateTime end = LocalDateTime.now().plusDays(7); //when mockMvc.perform( - get("/calendar/public/period/{detail_classification}", detailClassification).header("Authorization", - "Bearer " + accessToken).param("start", start.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))) + get("/calendar/public/period/{detail_classification}", + detailClassification).header("Authorization", + "Bearer " + accessToken).param("start", + start.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))) .param("end", end.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))) .andExpect(status().isOk()) .andDo(print()); @@ -956,8 +940,10 @@ void retrievePublicScheduleFailFaultPeriod() throws Exception { LocalDateTime end = LocalDateTime.now().minusDays(7); //when & then mockMvc.perform( - get("/calendar/public/period/{detail_classification}", detailClassification).header("Authorization", - "Bearer " + accessToken).param("start", start.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))) + get("/calendar/public/period/{detail_classification}", + detailClassification).header("Authorization", + "Bearer " + accessToken).param("start", + start.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))) .param("end", end.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))) .andExpect(status().isBadRequest()) .andDo(print()); @@ -971,7 +957,8 @@ void retrievePublicScheduleFaultDetailClassification() throws Exception { LocalDateTime start = LocalDateTime.now().plusDays(0); LocalDateTime end = LocalDateTime.now().plusDays(7); //when & then - mockMvc.perform(get("/calendar/public/period/{detail_classification}", "wrong").header("Authorization", + mockMvc.perform(get("/calendar/public/period/{detail_classification}", "wrong") + .header("Authorization", "Bearer " + accessToken).param("start", start.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))) .param("end", end.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))) .andExpect(status().isBadRequest()) @@ -993,8 +980,10 @@ void retrievePublicScheduleFaultDateFormat() throws Exception { LocalDateTime end = LocalDateTime.now().plusDays(7); //when & then mockMvc.perform( - get("/calendar/public/period/{detail_classification}", detailClassification).header("Authorization", - "Bearer " + accessToken).param("start", start.format(DateTimeFormatter.ofPattern("yyyy/MM/dd"))) + get("/calendar/public/period/{detail_classification}", + detailClassification).header("Authorization", + "Bearer " + accessToken).param("start", + start.format(DateTimeFormatter.ofPattern("yyyy/MM/dd"))) .param("end", end.format(DateTimeFormatter.ofPattern("yyyy/MM/dd")))) .andExpect(status().isBadRequest()) .andDo(print()); @@ -1003,7 +992,7 @@ void retrievePublicScheduleFaultDateFormat() throws Exception { @Nested @DisplayName("๊ฐ€์ ธ์˜จ ๊ฐœ์ธ์ผ์ • ์กฐํšŒํ•˜๊ธฐ") - class publicToPrivate { + class PublicToPrivate { @Autowired private ScheduleGroupRepository scheduleGroupRepository; @@ -1074,7 +1063,8 @@ void addPublicToPrivateFailNotExistGroup() throws Exception { publicSchedule = publicScheduleRepository.save(publicSchedule); // when mockMvc.perform( - post("/calendar/public/{id}/{groupId}", publicSchedule.getId(), 1).header("Authorization", + post("/calendar/public/{id}/{groupId}", + publicSchedule.getId(), 1).header("Authorization", "Bearer " + accessToken)) .andExpect(status().isNotFound()).andDo(print()); // then diff --git a/gg-calendar-api/src/test/java/gg/calendar/api/user/schedule/publicschedule/controller/response/PublicScheduleDetailRetrieveResDtoTest.java b/gg-calendar-api/src/test/java/gg/calendar/api/user/schedule/publicschedule/controller/response/PublicScheduleDetailRetrieveResDtoTest.java index 44b120fcf..2a0dcf98d 100644 --- a/gg-calendar-api/src/test/java/gg/calendar/api/user/schedule/publicschedule/controller/response/PublicScheduleDetailRetrieveResDtoTest.java +++ b/gg-calendar-api/src/test/java/gg/calendar/api/user/schedule/publicschedule/controller/response/PublicScheduleDetailRetrieveResDtoTest.java @@ -44,7 +44,7 @@ void toDto_Success() { () -> assertEquals("testUser", responseDto.getAuthor()), () -> assertEquals("Test Title", responseDto.getTitle()), () -> assertEquals("Test Content", responseDto.getContent()), - () -> assertEquals("http://test.com", responseDto.getLink()), + () -> assertEquals("https://test.com", responseDto.getLink()), () -> assertEquals(startTime.toString(), responseDto.getStartTime()), () -> assertEquals(endTime.toString(), responseDto.getEndTime()), () -> assertEquals(schedule.getSharedCount(), responseDto.getSharedCount()) diff --git a/gg-calendar-api/src/test/java/gg/calendar/api/user/schedule/publicschedule/controller/response/TotalScheduleRetrieveResDtoTest.java b/gg-calendar-api/src/test/java/gg/calendar/api/user/schedule/publicschedule/controller/response/TotalScheduleRetrieveResDtoTest.java index e04a2068c..f4585f556 100644 --- a/gg-calendar-api/src/test/java/gg/calendar/api/user/schedule/publicschedule/controller/response/TotalScheduleRetrieveResDtoTest.java +++ b/gg-calendar-api/src/test/java/gg/calendar/api/user/schedule/publicschedule/controller/response/TotalScheduleRetrieveResDtoTest.java @@ -49,7 +49,7 @@ void toDtoSuccess() { () -> assertEquals("testUser", responseDto.getAuthor()), () -> assertEquals("Test Title", responseDto.getTitle()), () -> assertEquals("Test Content", responseDto.getContent()), - () -> assertEquals("http://test.com", responseDto.getLink()), + () -> assertEquals("https://test.com", responseDto.getLink()), () -> assertEquals(startTime.toString(), responseDto.getStartTime()), () -> assertEquals(endTime.toString(), responseDto.getEndTime()), () -> assertEquals("ACTIVATE", responseDto.getStatus())); diff --git a/gg-calendar-api/src/test/java/gg/calendar/api/user/utils/controller/response/FortyTwoEventResponseTest.java b/gg-calendar-api/src/test/java/gg/calendar/api/user/utils/controller/response/FortyTwoEventResponseTest.java new file mode 100644 index 000000000..a8b5dd4c1 --- /dev/null +++ b/gg-calendar-api/src/test/java/gg/calendar/api/user/utils/controller/response/FortyTwoEventResponseTest.java @@ -0,0 +1,57 @@ +package gg.calendar.api.user.utils.controller.response; + +import static org.assertj.core.api.AssertionsForClassTypes.*; + +import java.time.LocalDateTime; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; + +import gg.utils.annotation.UnitTest; +import lombok.Getter; + +@Getter +@UnitTest +class FortyTwoEventResponseTest { + + @Test + @DisplayName("FortyTwoEventResDto ์ƒ์„ฑ์ž ํ…Œ์ŠคํŠธ") + void toSuccess() throws JsonProcessingException { + //Given + + ObjectMapper objectMapper = new ObjectMapper() + .registerModule(new JavaTimeModule()) + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + + String jsonResponse = "{" + + "\"id\": 1," + + "\"name\": \"Exam06\"," + + "\"description\": \"ft_irc\"," + + "\"location\": \"location\"," + + "\"kind\": \"event\"," + + "\"begin_at\": \"2025-01-19T10:00:00\"," + + "\"end_at\": \"2025-01-30T12:00:00\"," + + "\"created_at\": \"2025-01-17T10:00:00\"," + + "\"updated_at\": \"2025-01-18T12:00:00\"" + + "}"; + //When + FortyTwoEventResponse response = objectMapper.readValue(jsonResponse, FortyTwoEventResponse.class); + + //Then + assertThat(response.getId()).isEqualTo(1L); + assertThat(response.getName()).isEqualTo("Exam06"); + assertThat(response.getDescription()).isEqualTo("ft_irc"); + assertThat(response.getLocation()).isEqualTo("location"); + assertThat(response.getKind()).isEqualTo("event"); + assertThat(response.getBeginAt()).isEqualTo(LocalDateTime.parse("2025-01-19T10:00:00")); + assertThat(response.getEndAt()).isEqualTo(LocalDateTime.parse("2025-01-30T12:00:00")); + assertThat(response.getCreatedAt()).isEqualTo(LocalDateTime.parse("2025-01-17T10:00:00")); + assertThat(response.getUpdatedAt()).isEqualTo(LocalDateTime.parse("2025-01-18T12:00:00")); + } + +} diff --git a/gg-data/src/main/java/gg/data/calendar/PublicSchedule.java b/gg-data/src/main/java/gg/data/calendar/PublicSchedule.java index 437b3a215..157b301ca 100644 --- a/gg-data/src/main/java/gg/data/calendar/PublicSchedule.java +++ b/gg-data/src/main/java/gg/data/calendar/PublicSchedule.java @@ -86,8 +86,8 @@ private PublicSchedule(DetailClassification classification, EventTag eventTag, J this.endTime = endTime; } - public void update(DetailClassification classification, EventTag eventTag, JobTag jobTag, - TechTag techTag, String title, String content, String link, LocalDateTime startTime, LocalDateTime endTime) { + public void update(DetailClassification classification, EventTag eventTag, JobTag jobTag, TechTag techTag, + String title, String content, String link, LocalDateTime startTime, LocalDateTime endTime) { this.classification = classification; this.eventTag = eventTag; this.jobTag = jobTag; diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/scheduler/CalendarEventScheduler.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/scheduler/CalendarEventScheduler.java new file mode 100644 index 000000000..60826d5ec --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/scheduler/CalendarEventScheduler.java @@ -0,0 +1,35 @@ +package gg.pingpong.api.global.scheduler; + +import org.springframework.stereotype.Component; + +import gg.calendar.api.user.utils.service.FortyTwoEventService; +import gg.calendar.api.user.utils.service.ScheduleCheckService; +import gg.calendar.api.user.utils.service.ScheduleNotiService; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Component +public class CalendarEventScheduler extends AbstractScheduler { + private final FortyTwoEventService fortyTwoEventService; + private final ScheduleCheckService scheduleCheckService; + private final ScheduleNotiService scheduleNotiService; + + public CalendarEventScheduler(FortyTwoEventService fortyTwoEventService, + ScheduleCheckService scheduleCheckService, ScheduleNotiService scheduleNotiService) { + this.fortyTwoEventService = fortyTwoEventService; + this.scheduleCheckService = scheduleCheckService; + this.scheduleNotiService = scheduleNotiService; + this.setCron("0 0 0 * * *"); + } + + @Override + public Runnable runnable() { + return () -> { + log.info("FortyTwo Event Scheduler Started"); + fortyTwoEventService.checkEvent(); + log.info("Schedule check service deactivate Expired Schedules!"); + scheduleCheckService.deactivateExpiredSchedules(); + scheduleNotiService.sendScheduleNotifications(); + }; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/service/NotiService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/service/NotiService.java index c7d6148ed..eec9e793f 100644 --- a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/service/NotiService.java +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/service/NotiService.java @@ -161,8 +161,9 @@ public String getMessage(Noti noti) { "๐Ÿงš: \"์ƒˆ๋กœ์šด ์•Œ๋ฆผ์ด ๋„์ฐฉํ–ˆํ•‘.\"\n" + "๐Ÿงš: \"" + noti.getType().getMessage() + "\"\n\n ๐Ÿ“42GG์™€ ํ•จ๊ป˜ํ•˜๋Š” ํ–‰๋ณตํ•œ ํƒ๊ตฌ์ƒํ™œ๐Ÿ“" + "\n$$์ง€๊ธˆ ์ฆ‰์‹œ ์ ‘์†$$ ----> https://42gg.kr"; } else { - message = "๐Ÿงš: \"์ƒˆ๋กœ์šด ์•Œ๋ฆผ์ด ๋„์ฐฉํ–ˆํ•‘.\"\n" + "๐Ÿงš: \"" + noti.getType().getMessage() + "\"\n\n๊ณต์ง€์‚ฌํ•ญ: " - + noti.getMessage() + "\n\n ๐Ÿ“42GG์™€ ํ•จ๊ป˜ํ•˜๋Š” ํ–‰๋ณตํ•œ ํƒ๊ตฌ์ƒํ™œ๐Ÿ“" + "\n$$์ง€๊ธˆ ์ฆ‰์‹œ ์ ‘์†$$ ----> https://42gg.kr"; + message = + "๐Ÿงš: \"์ƒˆ๋กœ์šด ์•Œ๋ฆผ์ด ๋„์ฐฉํ–ˆํ•‘.\"\n" + "๐Ÿงš: \"" + noti.getType().getMessage() + "\"\n\n๊ณต์ง€์‚ฌํ•ญ: " + noti.getMessage() + + "\n\n ๐Ÿ“42GG์™€ ํ•จ๊ป˜ํ•˜๋Š” ํ–‰๋ณตํ•œ ํƒ๊ตฌ์ƒํ™œ๐Ÿ“" + "\n$$์ง€๊ธˆ ์ฆ‰์‹œ ์ ‘์†$$ ----> https://42gg.kr"; } return message; } diff --git a/gg-recruit-api/src/test/java/gg/recruit/api/TestSpringBootApplication.java b/gg-recruit-api/src/test/java/gg/recruit/api/TestSpringBootApplication.java index dcc4eecb9..a76ff4172 100644 --- a/gg-recruit-api/src/test/java/gg/recruit/api/TestSpringBootApplication.java +++ b/gg-recruit-api/src/test/java/gg/recruit/api/TestSpringBootApplication.java @@ -3,6 +3,6 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication(scanBasePackages = {"gg.recruit.api", "gg.utils", "gg.data", "gg.repo", - "gg.admin.repo", "gg.auth", "gg.pingpong.api"}) + "gg.admin.repo", "gg.auth", "gg.pingpong.api", "gg.calendar.api"}) public class TestSpringBootApplication { } diff --git a/gg-repo/src/main/java/gg/repo/calendar/FortyTwoEventRepository.java b/gg-repo/src/main/java/gg/repo/calendar/FortyTwoEventRepository.java new file mode 100644 index 000000000..8453da633 --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/calendar/FortyTwoEventRepository.java @@ -0,0 +1,10 @@ +package gg.repo.calendar; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import gg.data.calendar.PublicSchedule; + +@Repository +public interface FortyTwoEventRepository extends JpaRepository { +} diff --git a/gg-repo/src/main/java/gg/repo/calendar/PrivateScheduleRepository.java b/gg-repo/src/main/java/gg/repo/calendar/PrivateScheduleRepository.java index ab40c6d89..dbe25b12a 100644 --- a/gg-repo/src/main/java/gg/repo/calendar/PrivateScheduleRepository.java +++ b/gg-repo/src/main/java/gg/repo/calendar/PrivateScheduleRepository.java @@ -3,12 +3,17 @@ import java.time.LocalDateTime; import java.util.List; +import javax.transaction.Transactional; + import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; import gg.data.calendar.PrivateSchedule; import gg.data.calendar.PublicSchedule; +import gg.data.calendar.type.ScheduleStatus; import gg.data.user.User; @Repository @@ -20,4 +25,20 @@ public interface PrivateScheduleRepository extends JpaRepository :endTime OR pu.endTime < :startTime) " + "AND pr.user = :user") List findOverlappingSchedulesByUser(LocalDateTime startTime, LocalDateTime endTime, User user); + + @Modifying(clearAutomatically = true) + @Transactional + @Query("UPDATE PrivateSchedule ps SET ps.status = :status WHERE ps.publicSchedule.id IN " + + "(SELECT p.id FROM PublicSchedule p WHERE p.status = :publicStatus)") + void updateRelatedPrivateSchedules(@Param("status") ScheduleStatus status, + @Param("publicStatus") ScheduleStatus publicStatus); + + @Query("SELECT ps FROM PrivateSchedule ps " + "JOIN ps.publicSchedule p " + "WHERE ps.alarm = true " + + "AND ps.status = :status " + "AND (p.endTime BETWEEN :startOfDay AND :endOfDay OR " + + "p.endTime BETWEEN :nextStartOfDay AND :nextEndOfDay)") + List findSchedulesWithAlarmForBothDays(@Param("startOfDay") LocalDateTime startOfDay, + @Param("endOfDay") LocalDateTime endOfDay, + @Param("nextStartOfDay") LocalDateTime nextStartOfDay, + @Param("nextEndOfDay") LocalDateTime nextEndOfDay, + @Param("status") ScheduleStatus status); } diff --git a/gg-repo/src/main/java/gg/repo/calendar/PublicScheduleRepository.java b/gg-repo/src/main/java/gg/repo/calendar/PublicScheduleRepository.java index 2db4cc736..94c82f11c 100644 --- a/gg-repo/src/main/java/gg/repo/calendar/PublicScheduleRepository.java +++ b/gg-repo/src/main/java/gg/repo/calendar/PublicScheduleRepository.java @@ -3,11 +3,17 @@ import java.time.LocalDateTime; import java.util.List; +import javax.transaction.Transactional; + import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; import gg.data.calendar.PublicSchedule; import gg.data.calendar.type.DetailClassification; +import gg.data.calendar.type.ScheduleStatus; @Repository public interface PublicScheduleRepository extends JpaRepository { @@ -18,4 +24,13 @@ List findByEndTimeGreaterThanEqualAndStartTimeLessThanEqual(Loca List findByEndTimeGreaterThanEqualAndStartTimeLessThanEqualAndClassification( LocalDateTime startTime, LocalDateTime endTime, DetailClassification classification); + + boolean existsByTitleAndStartTime(String title, LocalDateTime beginAt); + + @Modifying(clearAutomatically = true) + @Transactional + @Query("UPDATE PublicSchedule ps SET ps.status = :status WHERE ps.status = :currentStatus AND ps.endTime < :time") + void updateExpiredPublicSchedules(@Param("status") ScheduleStatus status, + @Param("currentStatus") ScheduleStatus currentStatus, + @Param("time") LocalDateTime time); } diff --git a/gg-utils/build.gradle b/gg-utils/build.gradle index 0d494e2b0..3ec9d1b01 100644 --- a/gg-utils/build.gradle +++ b/gg-utils/build.gradle @@ -82,6 +82,8 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-mail' testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1' + testImplementation 'org.springframework.security:spring-security-oauth2-client' + testImplementation 'org.mockito:mockito-core' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1' testFixturesImplementation("org.junit.jupiter:junit-jupiter:5.8.1") diff --git a/gg-utils/src/main/java/gg/utils/external/ApiUtil.java b/gg-utils/src/main/java/gg/utils/external/ApiUtil.java index e8c1df77b..4aaa6e584 100644 --- a/gg-utils/src/main/java/gg/utils/external/ApiUtil.java +++ b/gg-utils/src/main/java/gg/utils/external/ApiUtil.java @@ -90,4 +90,12 @@ public List> callApiWithAccessToken(String url, String acces return apiCall(url, responseType, headers, HttpMethod.GET); } + + public T callApiWithAccessTokenEvent(String url, String accessToken, + ParameterizedTypeReference responseType) { + HttpHeaders headers = new HttpHeaders(); + headers.setBearerAuth(accessToken); + headers.setContentType(MediaType.APPLICATION_JSON); + return apiCall(url, responseType, headers, HttpMethod.GET); + } }