Skip to content

Commit

Permalink
[Feat] 디스코드 계정 연결 해제 (#48)
Browse files Browse the repository at this point in the history
* feat : 엑세스 토큰 재발급 로직 구현

* feat : 디스코드 연결 해제

* fix : 파라미터 이용 수정
  • Loading branch information
iiqcov authored Nov 14, 2024
1 parent 82c60ad commit c35ecb1
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package gigedi.dev.domain.discord.api;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;

import gigedi.dev.domain.discord.application.DiscordAuthService;
import gigedi.dev.domain.discord.dto.response.DiscordInfoResponse;
Expand All @@ -23,4 +20,10 @@ public class DiscordAuthController {
public DiscordInfoResponse discordSocialLogin(@RequestParam String code) {
return discordAuthService.discordConnect(code);
}

@Operation(summary = "디스코드 연결 해제", description = "디스코드 연결을 해제하는 API")
@GetMapping("/discord/disconnect/{discordId}")
public void discordSocialLogin(@PathVariable Long discordId) {
discordAuthService.discordDisconnect(discordId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import gigedi.dev.domain.discord.dto.response.DiscordLoginResponse;
import gigedi.dev.domain.discord.dto.response.DiscordUserResponse;
import gigedi.dev.domain.discord.dto.response.ReissueDiscordTokenResponse;
import gigedi.dev.global.error.exception.CustomException;
import gigedi.dev.global.error.exception.ErrorCode;
import gigedi.dev.infra.config.oauth.DiscordProperties;
Expand All @@ -35,7 +36,7 @@ public DiscordLoginResponse discordLogin(String code) {

return restClient
.post()
.uri(DISCORD_ID_TOKEN_URL)
.uri(DISCORD_TOKEN_URL)
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
.body(formData)
.retrieve()
Expand Down Expand Up @@ -71,4 +72,59 @@ public DiscordUserResponse getDiscordUserInfo(String accessToken) {
throw new CustomException(ErrorCode.DISCORD_USER_INFO_FAILED);
}
}

public ReissueDiscordTokenResponse reissueDiscordToken(String refreshToken) {
try {
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
formData.add(CLIENT_ID_KEY, discordProperties.id());
formData.add(CLIENT_ID_SECRET, discordProperties.secret());
formData.add(GRANT_TYPE_KEY, REISSUE_GRANT_TYPE_VALUE);
formData.add(REFRESH_TOKEN, refreshToken);

return restClient
.post()
.uri(DISCORD_TOKEN_URL)
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.body(formData)
.retrieve()
.onStatus(
status -> !status.is2xxSuccessful(),
(request, response) -> {
log.error("Discord 토큰 갱신 실패: {}", response.getStatusCode());
throw new CustomException(ErrorCode.DISCORD_TOKEN_REISSUE_FAILED);
})
.body(ReissueDiscordTokenResponse.class);
} catch (Exception e) {
log.error("Discord 토큰 갱신 중 예외 발생: {}", e.getMessage(), e);
throw new CustomException(ErrorCode.DISCORD_TOKEN_REISSUE_FAILED);
}
}

public void disconnectDiscordAccount(String accessToken) {
try {
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
formData.add(CLIENT_ID_KEY, discordProperties.id());
formData.add(CLIENT_ID_SECRET, discordProperties.secret());
formData.add("token", accessToken);

restClient
.post()
.uri(DISCORD_DISCONNECT_URL)
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.body(formData)
.retrieve()
.onStatus(
status -> !status.is2xxSuccessful(),
(request, response) -> {
log.error("Discord 연결 해제 실패: {}", response.getStatusCode());
throw new CustomException(ErrorCode.DISCORD_DISCONNECT_FAILED);
})
.toBodilessEntity();

log.info("Discord 연결 해제 성공");
} catch (Exception e) {
log.error("Discord 연결 해제 중 예외 발생: {}", e.getMessage(), e);
throw new CustomException(ErrorCode.DISCORD_DISCONNECT_FAILED);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@

import gigedi.dev.domain.discord.dao.DiscordRepository;
import gigedi.dev.domain.discord.domain.Discord;
import gigedi.dev.domain.discord.dto.response.CreateDMChannelResponse;
import gigedi.dev.domain.discord.dto.response.DiscordInfoResponse;
import gigedi.dev.domain.discord.dto.response.DiscordLoginResponse;
import gigedi.dev.domain.discord.dto.response.DiscordUserResponse;
import gigedi.dev.domain.discord.dto.response.*;
import gigedi.dev.domain.member.domain.Member;
import gigedi.dev.global.error.exception.CustomException;
import gigedi.dev.global.error.exception.ErrorCode;
import gigedi.dev.global.util.MemberUtil;
import lombok.RequiredArgsConstructor;

Expand Down Expand Up @@ -51,4 +50,27 @@ private DiscordInfoResponse saveDiscord(
loginResponse.getGuildId());
return DiscordInfoResponse.from(discordRepository.save(discord));
}

public void discordDisconnect(Long discordId) {
Discord discordById = findDiscordById(discordId);
ReissueDiscordTokenResponse tokenResponse =
discordAuthApiService.reissueDiscordToken(discordById.getRefreshToken());
discordById.updateRefreshToken(tokenResponse.refreshToken());

discordAuthApiService.disconnectDiscordAccount(tokenResponse.accessToken());
discordById.disconnectDiscordAccount();
}

private Discord findDiscordById(Long discordId) {
Member currentMember = memberUtil.getCurrentMember();
Discord discord =
discordRepository
.findById(discordId)
.orElseThrow(
() -> new CustomException(ErrorCode.DISCORD_ACCOUNT_NOT_FOUND));
if (!discord.getMember().equals(currentMember)) {
throw new CustomException(ErrorCode.DISCORD_ACCOUNT_NOT_OWNER);
}
return discord;
}
}
8 changes: 8 additions & 0 deletions src/main/java/gigedi/dev/domain/discord/domain/Discord.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,12 @@ public static Discord createDiscord(
.guildId(guildId)
.build();
}

public void updateRefreshToken(String refreshToken) {
this.refreshToken = refreshToken;
}

public void disconnectDiscordAccount() {
this.deletedAt = LocalDateTime.now();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package gigedi.dev.domain.discord.dto.response;

import com.fasterxml.jackson.annotation.JsonProperty;

public record ReissueDiscordTokenResponse(
@JsonProperty("access_token") String accessToken,
@JsonProperty("refresh_token") String refreshToken) {}
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ public final class SecurityConstants {
public static final String GOOGLE_WITHDRAWAL_URL =
"https://accounts.google.com/o/oauth2/revoke?token=";

public static final String DISCORD_ID_TOKEN_URL = "https://discord.com/api/oauth2/token";
public static final String DISCORD_TOKEN_URL = "https://discord.com/api/oauth2/token";
public static final String DISCORD_USER_INFO_URL = "https://discord.com/api/users/@me";
public static final String DISCORD_CREATE_DM_CHANNEL_URL =
"https://discord.com/api/v9/users/@me/channels";
public static final String DISCORD_GUILD_URL = "https://discord.com/api/v10/guilds";
public static final String DISCORD_DISCONNECT_URL =
"https://discord.com/api/oauth2/token/revoke";

public static final String FIGMA_GET_ID_TOKEN_URL = "https://www.figma.com/api/oauth/token";
public static final String FIGMA_GET_USER_INFO_URL = "https://api.figma.com/v1/me";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ public enum ErrorCode {
DISCORD_USER_INFO_FAILED(HttpStatus.BAD_REQUEST, "디스코드 사용자 정보 조회에 실패했습니다."),
DISCORD_DM_CHANNEL_CREATION_FAILED(HttpStatus.BAD_REQUEST, "디스코드 DM 채널 생성에 실패했습니다."),
DISCORD_GUILD_UPDATE_FAILED(HttpStatus.BAD_REQUEST, "디스코드 길드 설정에 실패했습니다."),
DISCORD_ACCOUNT_NOT_FOUND(HttpStatus.NOT_FOUND, "해당 디스코드 계정이 존재하지 않습니다."),
DISCORD_ACCOUNT_NOT_OWNER(HttpStatus.NOT_FOUND, "해당 디스코드 계정의 소유자가 아닙니다."),
DISCORD_TOKEN_REISSUE_FAILED(HttpStatus.BAD_REQUEST, "디스코드 토큰 재발급 과정에서 오류가 발생했습니다."),
DISCORD_DISCONNECT_FAILED(HttpStatus.BAD_REQUEST, "디스코드 연결 해제 과정에서 오류가 발생했습니다."),

// 추가
GOOGLE_LOGIN_FAILED(HttpStatus.BAD_REQUEST, "구글 로그인 과정에서 오류가 발생했습니다."),
Expand Down

0 comments on commit c35ecb1

Please sign in to comment.