Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BE] issue92: 스터디 개설 #110

Merged
merged 6 commits into from
Jul 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public void addArgumentResolvers(final List<HandlerMethodArgumentResolver> resol
@Override
public void addInterceptors(final InterceptorRegistry registry) {
registry.addInterceptor(authenticationInterceptor)
.excludePathPatterns("/**");
.addPathPatterns("/**");
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package com.woowacourse.moamoa.auth.controller;

import com.woowacourse.moamoa.auth.config.AuthenticationExtractor;
import com.woowacourse.moamoa.auth.config.AuthenticationPrincipal;
import com.woowacourse.moamoa.auth.infrastructure.JwtTokenProvider;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.support.WebDataBinderFactory;
Expand All @@ -12,6 +15,9 @@
@Component
public class AuthenticationArgumentResolver implements HandlerMethodArgumentResolver {

@Autowired
private JwtTokenProvider jwtTokenProvider;

@Override
public boolean supportsParameter(final MethodParameter parameter) {
return parameter.hasParameterAnnotation(AuthenticationPrincipal.class);
Expand All @@ -21,6 +27,8 @@ public boolean supportsParameter(final MethodParameter parameter) {
public Object resolveArgument(final MethodParameter parameter, final ModelAndViewContainer mavContainer,
final NativeWebRequest webRequest, final WebDataBinderFactory binderFactory) {
final HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
return request.getServletContext().getAttribute("payload");

final String token = AuthenticationExtractor.extract(request);
return Long.valueOf(jwtTokenProvider.getPayload(token));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.woowacourse.moamoa.auth.config.AuthenticationExtractor;
import com.woowacourse.moamoa.auth.infrastructure.JwtTokenProvider;
import com.woowacourse.moamoa.common.exception.UnauthorizedException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
Expand All @@ -21,10 +22,12 @@ public boolean preHandle(final HttpServletRequest request, final HttpServletResp
return true;
}

String token = AuthenticationExtractor.extract(request);
validateToken(token);
if (request.getMethod().equals("POST") && request.getServletPath().equals("/api/studies")) {
String token = AuthenticationExtractor.extract(request);
validateToken(token);

request.setAttribute("payload", jwtTokenProvider.getPayload(token));
request.setAttribute("payload", jwtTokenProvider.getPayload(token));
}

return true;
}
Expand All @@ -34,8 +37,8 @@ private boolean isPreflight(HttpServletRequest request) {
}

private void validateToken(String token) {
if (token == null || token.isEmpty()) {
throw new IllegalStateException("토큰이 존재하지 않습니다.");
if (token == null || !jwtTokenProvider.validateToken(token)) {
throw new UnauthorizedException("유효하지 않은 토큰입니다.");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package com.woowacourse.moamoa.auth.infrastructure;

import com.woowacourse.moamoa.auth.service.oauthclient.OAuthClient;
import com.woowacourse.moamoa.common.exception.UnauthorizedException;
import com.woowacourse.moamoa.auth.service.request.AccessTokenRequest;
import com.woowacourse.moamoa.auth.service.oauthclient.response.GithubProfileResponse;
import java.util.Map;
import java.util.Objects;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;

@Component
public class GithubOAuthClient implements OAuthClient {

private static final String ACCESS_TOKEN_URL = "https://github.com/login/oauth/access_token";
private static final String PROFILE_URL = "https://api.github.com/user";

private final String clientId;
private final String clientSecret;
private final RestTemplate restTemplate;

public GithubOAuthClient(
@Value("${oauth2.github.client-id}") final String clientId,
@Value("${oauth2.github.client-secret}") final String clientSecret,
final RestTemplate restTemplate) {
this.clientId = clientId;
this.clientSecret = clientSecret;
this.restTemplate = restTemplate;
}

/*
Github에서 유효하지 않는 Authorization Code로 Access Token을 요청 시 200 응답이 오고,
body로 error, error_description, error_uri가 담겨서 온다.
에러 처리를 위해서는 body의 필드를 확인하여 처리해야 하므로 Map을 사용했다.
Access Token 요청이 정상적인 경우 body로 access_token, token_type, scope를 응답한다.
*/
@Override
public String getAccessToken(final String code) {
final AccessTokenRequest accessTokenRequest = new AccessTokenRequest(clientId, clientSecret, code);

final HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);

final HttpEntity<AccessTokenRequest> httpEntity = new HttpEntity<>(accessTokenRequest, headers);

try {
final ResponseEntity<?> response = restTemplate.exchange(
ACCESS_TOKEN_URL, HttpMethod.POST, httpEntity, Map.class
);

if (response.getStatusCode().is2xxSuccessful()) {
Map<Object, Object> body = (Map<Object, Object>) Objects.requireNonNull(response.getBody());
if (body.containsKey("error")) {
throw new UnauthorizedException("Access Token을 가져올 수 없습니다.");
}
return String.valueOf(body.get("access_token"));
}
throw new UnauthorizedException("Access Token을 가져올 수 없습니다.");
} catch (HttpClientErrorException e) {
throw new UnauthorizedException("Access Token을 가져올 수 없습니다.");
}
}

@Override
public GithubProfileResponse getProfile(final String accessToken) {
HttpHeaders headers = new HttpHeaders();
headers.add("Accept", MediaType.APPLICATION_JSON_VALUE);
headers.add("Authorization", "token " + accessToken);

HttpEntity<Void> httpEntity = new HttpEntity<>(headers);

try {
final ResponseEntity<GithubProfileResponse> response = restTemplate.exchange(
PROFILE_URL, HttpMethod.GET, httpEntity, GithubProfileResponse.class);

if (response.getStatusCode().is2xxSuccessful()) {
return Objects.requireNonNull(response.getBody());
}
throw new UnauthorizedException("Github에서 사용자 정보를 가져올 수 없습니다.");
} catch (HttpClientErrorException e) {
throw new UnauthorizedException("Github에서 사용자 정보를 가져올 수 없습니다.");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import com.woowacourse.moamoa.auth.infrastructure.JwtTokenProvider;
import com.woowacourse.moamoa.auth.service.oauthclient.OAuthClient;
import com.woowacourse.moamoa.auth.service.response.GithubProfileResponse;
import com.woowacourse.moamoa.auth.service.oauthclient.response.GithubProfileResponse;
import com.woowacourse.moamoa.auth.service.response.TokenResponse;
import com.woowacourse.moamoa.member.service.MemberService;
import lombok.RequiredArgsConstructor;
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.woowacourse.moamoa.auth.service.oauthclient;

import com.woowacourse.moamoa.auth.service.response.GithubProfileResponse;
import com.woowacourse.moamoa.auth.service.oauthclient.response.GithubProfileResponse;

public interface OAuthClient {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.woowacourse.moamoa.auth.service.response;
package com.woowacourse.moamoa.auth.service.oauthclient.response;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.woowacourse.moamoa.member.domain.Member;
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package com.woowacourse.moamoa.auth.service.request;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.EqualsAndHashCode;
import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@EqualsAndHashCode
public class AccessTokenRequest {

@JsonProperty("client_id")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package com.woowacourse.moamoa.common.advice;

import com.woowacourse.moamoa.auth.service.oauthclient.exception.UnauthorizedException;
import com.woowacourse.moamoa.common.exception.UnauthorizedException;
import com.woowacourse.moamoa.common.advice.response.ErrorResponse;
import com.woowacourse.moamoa.common.exception.InvalidFormatException;
import com.woowacourse.moamoa.study.domain.exception.InvalidPeriodException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
Expand All @@ -11,8 +12,11 @@
@RestControllerAdvice
public class CommonControllerAdvice {

@ExceptionHandler
public ResponseEntity<ErrorResponse> handleBadRequest(final InvalidFormatException e) {
@ExceptionHandler({
InvalidFormatException.class,
InvalidPeriodException.class
})
public ResponseEntity<ErrorResponse> handleBadRequest(final Exception e) {
return ResponseEntity.badRequest().body(new ErrorResponse(e.getMessage()));
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.woowacourse.moamoa.auth.service.oauthclient.exception;
package com.woowacourse.moamoa.common.exception;

public class UnauthorizedException extends RuntimeException {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import com.woowacourse.moamoa.study.domain.Study;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.OneToMany;
import lombok.Getter;
import lombok.NoArgsConstructor;

Expand All @@ -26,6 +30,9 @@ public class Member {

private String profileUrl;

@OneToMany(mappedBy = "owner")
private List<Study> establishedStudies = new ArrayList<>();

public Member(final Long githubId, final String username, final String imageUrl, final String profileUrl) {
this(null, githubId, username, imageUrl, profileUrl);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.woowacourse.moamoa.member.service;

import com.woowacourse.moamoa.auth.service.oauthclient.exception.InvalidMemberException;
import com.woowacourse.moamoa.member.service.exception.InvalidMemberException;
import com.woowacourse.moamoa.member.domain.Member;
import com.woowacourse.moamoa.member.domain.repository.MemberRepository;
import com.woowacourse.moamoa.member.service.response.MemberResponse;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
package com.woowacourse.moamoa.auth.service.oauthclient.exception;
package com.woowacourse.moamoa.member.service.exception;

import com.woowacourse.moamoa.common.exception.UnauthorizedException;

public class InvalidMemberException extends UnauthorizedException {
public InvalidMemberException(final String message) {
Expand Down
Loading