Skip to content
This repository has been archived by the owner on Jul 29, 2024. It is now read-only.

Commit

Permalink
[BE] feat: Notion OAuth 연동 기능 구현 (#244)
Browse files Browse the repository at this point in the history
* feat: notion oauth 연동 기능 구현

* refactor: `ConnectionController`로 통합 및 환경 변수 추가

* chore: 환경 변수 설정 변경

* style: 컨벤션 적용

* refactor: static 제거
  • Loading branch information
cheon-eunjeong authored Aug 11, 2023
1 parent fc53c73 commit ab9a25b
Show file tree
Hide file tree
Showing 15 changed files with 133 additions and 26 deletions.
7 changes: 1 addition & 6 deletions .github/workflows/build-be-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,6 @@ jobs:
run: |
cd ./backend
./gradlew test
env:
KAKAO_CLIENT_SECRET: ${{ secrets.KAKAO_CLIENT_SECRET }}
KAKAO_CLIENT_ID: ${{ secrets.KAKAO_CLIENT_ID }}
TISTORY_CLIENT_ID: ${{ secrets.TISTORY_CLIENT_ID }}
TISTORY_CLIENT_SECRET: ${{ secrets.TISTORY_CLIENT_SECRET }}
- name: Build with Gradle
run: |
Expand Down Expand Up @@ -72,4 +67,4 @@ jobs:
deploy:
needs: build
uses: ./.github/workflows/deploy-dev.yml
secrets: inherit
secrets: inherit
7 changes: 1 addition & 6 deletions .github/workflows/build-be-prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,6 @@ jobs:
run: |
cd ./backend
./gradlew test
env:
KAKAO_CLIENT_ID: ${{ secrets.KAKAO_CLIENT_ID }}
KAKAO_CLIENT_SECRET: ${{ secrets.KAKAO_CLIENT_SECRET }}
TISTORY_CLIENT_ID: ${{ secrets.TISTORY_CLIENT_ID }}
TISTORY_CLIENT_SECRET: ${{ secrets.TISTORY_CLIENT_SECRET }}
- name: Build with Gradle
run: |
Expand Down Expand Up @@ -72,4 +67,4 @@ jobs:
deploy:
needs: build
uses: ./.github/workflows/deploy-prod.yml
secrets: inherit
secrets: inherit
4 changes: 3 additions & 1 deletion .github/workflows/deploy-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@ jobs:
echo "KAKAO_CLIENT_SECRET"=${{ secrets.KAKAO_CLIENT_SECRET }} >> .env
echo "TISTORY_CLIENT_ID"=${{ secrets.TISTORY_CLIENT_ID }} >> .env
echo "TISTORY_CLIENT_SECRET"=${{ secrets.TISTORY_CLIENT_SECRET }} >> .env
echo "NOTION_CLIENT_ID"=${{ secrets.NOTION_CLIENT_ID }} >> .env
echo "NOTION_CLIENT_SECRET"=${{ secrets.NOTION_CLIENT_SECRET }} >> .env
## deploy to production
- name: Deploy to prod
run: |
sudo docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
sudo docker compose down
sudo docker compose pull
sudo docker compose up -d
sudo docker compose up -d
4 changes: 3 additions & 1 deletion .github/workflows/deploy-prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@ jobs:
echo "KAKAO_CLIENT_SECRET"=${{ secrets.KAKAO_CLIENT_SECRET }} >> .env
echo "TISTORY_CLIENT_ID"=${{ secrets.TISTORY_CLIENT_ID }} >> .env
echo "TISTORY_CLIENT_SECRET"=${{ secrets.TISTORY_CLIENT_SECRET }} >> .env
echo "NOTION_CLIENT_ID"=${{ secrets.NOTION_CLIENT_ID }} >> .env
echo "NOTION_CLIENT_SECRET"=${{ secrets.NOTION_CLIENT_SECRET }} >> .env
## deploy to production
- name: Deploy to prod
run: |
sudo docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
sudo docker compose down
sudo docker compose pull
sudo docker compose up -d
sudo docker compose up -d
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package org.donggle.backend.application.service.oauth.notion;

import org.donggle.backend.application.service.oauth.notion.dto.NotionTokenRequest;
import org.donggle.backend.application.service.oauth.notion.dto.NotionTokenResponse;
import org.donggle.backend.application.service.request.OAuthAccessTokenRequest;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.util.UriComponentsBuilder;

@Service
public class NotionOAuthService {
public static final String AUTHORIZE_URL = "https://api.notion.com/v1/oauth/authorize";
public static final String TOKEN_URL = "https://api.notion.com/v1/oauth/token";
private static final String GRANT_TYPE = "authorization_code";
private static final String RESPONSE_TYPE = "code";
private static final String OWNER = "user";

private final String clientId;
private final String clientSecret;
private final WebClient webClient;

public NotionOAuthService(@Value("${notion_client_id}") final String clientId,
@Value("${notion_client_secret}") final String clientSecret) {
this.clientId = clientId;
this.clientSecret = clientSecret;
this.webClient = WebClient.create();
}

public String createRedirectUri(final String redirectUri) {
return UriComponentsBuilder.fromUriString(AUTHORIZE_URL)
.queryParam("client_id", clientId)
.queryParam("redirect_uri", redirectUri)
.queryParam("response_type", RESPONSE_TYPE)
.queryParam("owner", OWNER)
.build()
.toUriString();
}

public void getAccessToken(final OAuthAccessTokenRequest oAuthAccessTokenRequest) {
final String redirectUri = oAuthAccessTokenRequest.redirectUri();
final String code = oAuthAccessTokenRequest.code();

NotionTokenResponse response = webClient.post()
.uri(TOKEN_URL)
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.header(HttpHeaders.AUTHORIZATION, "Basic " + base64Encode(clientId + ":" + clientSecret))
.bodyValue(new NotionTokenRequest(GRANT_TYPE, code, redirectUri))
.retrieve()
.bodyToMono(NotionTokenResponse.class)
.block();
}

private String base64Encode(String value) {
return java.util.Base64.getEncoder().encodeToString(value.getBytes());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.donggle.backend.application.service.oauth.notion.dto;

public record NotionOwnerResponse(
String type,
NotionUserResponse user
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package org.donggle.backend.application.service.oauth.notion.dto;

public record NotionTokenRequest(String grant_type, String code, String redirect_uri) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.donggle.backend.application.service.oauth.notion.dto;

public record NotionTokenResponse(
String access_token, // accessToken
String bot_id, // 승인에 대한 식별자
String duplicated_template_id,
// 사용자 작업 공간에 생성된 새 페이지(개발자가 통합과 함께 제공한 템플릿의 복제본)의 ID, 개발자가 통합을 위한 템플릿을 제공하지 않은 경우 값은 null
NotionOwnerResponse owner, // 이 통합을 보고 공유할 수 있는 사람에 대한 정보가 포함된 개체
String workspace_icon, // UI에서 이 승인을 표시하는 데 사용할 수 있는 이미지의 URL
String workspace_id, // 이 승인이 발생한 워크스페이스의 ID
String workspace_name // UI에서 이 승인을 표시하는 데 사용할 수 있는 사람이 읽을 수 있는 이름
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.donggle.backend.application.service.oauth.notion.dto;

public record NotionUserResponse(
Long id,
String obejct
) {
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.donggle.backend.ui;

import lombok.RequiredArgsConstructor;
import org.donggle.backend.application.service.oauth.notion.NotionOAuthService;
import org.donggle.backend.application.service.oauth.tistory.TistoryOAuthService;
import org.donggle.backend.application.service.request.OAuthAccessTokenRequest;
import org.springframework.http.HttpHeaders;
Expand All @@ -14,12 +15,13 @@
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/connections/tistory")
@RequiredArgsConstructor
public class TistoryOAuthController {
@RequestMapping("/connections")
public class ConnectionController {
private final TistoryOAuthService tistoryOAuthService;
private final NotionOAuthService notionOAuthService;

@GetMapping
@GetMapping("/tistory")
public ResponseEntity<Void> connectionsRedirectTistory(@RequestParam final String redirect_uri) {
final String redirectUri = tistoryOAuthService.createAuthorizeRedirectUri(redirect_uri);
return ResponseEntity
Expand All @@ -28,9 +30,24 @@ public ResponseEntity<Void> connectionsRedirectTistory(@RequestParam final Strin
.build();
}

@PostMapping
@PostMapping("/tistory")
public ResponseEntity<Void> connectionsAddTistory(@RequestBody final OAuthAccessTokenRequest oAuthAccessTokenRequest) {
final String accessToken = tistoryOAuthService.getAccessToken(oAuthAccessTokenRequest);
return ResponseEntity.ok().build();
}

@GetMapping("/notion")
public ResponseEntity<Void> connectionsRedirectNotion(@RequestParam final String redirect_uri) {
final String redirectUri = notionOAuthService.createRedirectUri(redirect_uri);
return ResponseEntity
.status(HttpStatus.FOUND)
.header(HttpHeaders.LOCATION, redirectUri)
.build();
}

@PostMapping("/notion")
public ResponseEntity<Void> connectionsAddNotion(@RequestBody final OAuthAccessTokenRequest oAuthAccessTokenRequest) {
notionOAuthService.getAccessToken(oAuthAccessTokenRequest);
return ResponseEntity.ok().build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(("/oauth/login/kakao"))
@RequiredArgsConstructor
@RequestMapping(("/oauth/login/kakao"))
public class KakaoOAuthController {
private final KakaoOAuthService kakaoOAuthService;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
import java.net.URI;

@RestController
@RequestMapping("/writings")
@RequiredArgsConstructor
@RequestMapping("/writings")
public class WritingController {
private final WritingService writingService;
private final PublishService publishService;
Expand Down
6 changes: 4 additions & 2 deletions backend/src/main/resources/application-prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ spring:
hibernate:
format_sql: true
show-sql: true
kakao_client_secret: ${KAKAO_CLIENT_SECRET}
kakao_client_id: ${KAKAO_CLIENT_ID}
kakao_client_secret: ${KAKAO_CLIENT_SECRET}
tistory_client_id: ${TISTORY_CLIENT_ID}
tistory_client_secret: ${TISTORY_CLIENT_SECRET}
tistory_client_secret: ${TISTORY_CLIENT_SECRET}
notion_client_id: ${NOTION_CLIENT_ID}
notion_client_secret: ${NOTION_CLIENT_SECRET}
10 changes: 6 additions & 4 deletions backend/src/main/resources/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ spring:
h2:
console:
enabled: true
kakao_client_secret: ${KAKAO_CLIENT_SECRET}
kakao_client_id: ${KAKAO_CLIENT_ID}
tistory_client_id: ${TISTORY_CLIENT_ID}
tistory_client_secret: ${TISTORY_CLIENT_SECRET}
kakao_client_id: kakao_client_id
kakao_client_secret: kakao_client_secret
tistory_client_id: tistory_client_id
tistory_client_secret: tistory_client_secret
notion_client_id: notion_client_id
notion_client_secret: notion_client_secret
2 changes: 2 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ services:
- KAKAO_CLIENT_SECRET
- TISTORY_CLIENT_ID
- TISTORY_CLIENT_SECRET
- NOTION_CLIENT_ID
- NOTION_CLIENT_SECRET

nginx:
container_name: nginx
Expand Down

0 comments on commit ab9a25b

Please sign in to comment.