-
Notifications
You must be signed in to change notification settings - Fork 3
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
feat: 회원 Authorization Grant와 페이지 반환 기능 구현 #18
Changes from all commits
2cb3959
3c119f8
729d7d2
9cbfc2e
e056905
0dc50e4
233661a
18f3496
a1e7533
b5163eb
9c10d45
92cb531
a7291a8
47ef3ea
5a76a50
ab0063d
ab0b0ab
dff5e2e
31407ab
448011e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -121,3 +121,4 @@ gradle-app.setting | |
logs/ | ||
application-*.yml | ||
src/main/resources/config | ||
!application-test.yml |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package com.moabam.api.application; | ||
|
||
import static com.moabam.global.common.util.OAuthParameterNames.*; | ||
|
||
import java.io.IOException; | ||
|
||
import org.springframework.http.MediaType; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.web.util.UriComponentsBuilder; | ||
|
||
import com.moabam.api.dto.AuthorizationCodeRequest; | ||
import com.moabam.api.mapper.OAuthMapper; | ||
import com.moabam.global.common.util.GlobalConstant; | ||
import com.moabam.global.config.OAuthConfig; | ||
import com.moabam.global.error.exception.BadRequestException; | ||
import com.moabam.global.error.model.ErrorMessage; | ||
|
||
import jakarta.servlet.http.HttpServletResponse; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
public class AuthenticationService { | ||
|
||
private final OAuthConfig oAuthConfig; | ||
|
||
private String getAuthorizaionCodeUri() { | ||
AuthorizationCodeRequest authorizationCodeRequest = OAuthMapper.toAuthorizationCodeRequest(oAuthConfig); | ||
return generateQueryParamsWith(authorizationCodeRequest); | ||
} | ||
|
||
private String generateQueryParamsWith(AuthorizationCodeRequest authorizationCodeRequest) { | ||
UriComponentsBuilder authorizationCodeUri = UriComponentsBuilder | ||
.fromUriString(oAuthConfig.provider().authorizationUri()) | ||
.queryParam(RESPONSE_TYPE, CODE) | ||
.queryParam(CLIENT_ID, authorizationCodeRequest.clientId()) | ||
.queryParam(REDIRECT_URI, authorizationCodeRequest.redirectUri()); | ||
|
||
if (!authorizationCodeRequest.scope().isEmpty()) { | ||
String scopes = String.join(GlobalConstant.COMMA, authorizationCodeRequest.scope()); | ||
authorizationCodeUri.queryParam(SCOPE, scopes); | ||
} | ||
|
||
return authorizationCodeUri.toUriString(); | ||
} | ||
|
||
public void redirectToLoginPage(HttpServletResponse httpServletResponse) { | ||
String authorizationCodeUri = getAuthorizaionCodeUri(); | ||
|
||
try { | ||
httpServletResponse.setContentType(MediaType.APPLICATION_FORM_URLENCODED + GlobalConstant.CHARSET_UTF_8); | ||
httpServletResponse.sendRedirect(authorizationCodeUri); | ||
} catch (IOException e) { | ||
throw new BadRequestException(ErrorMessage.REQUEST_FAILD); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
package com.moabam.api.domain; | ||
|
||
import static java.util.Objects.*; | ||
|
||
import java.time.LocalDateTime; | ||
|
||
import org.hibernate.annotations.ColumnDefault; | ||
import org.hibernate.annotations.SQLDelete; | ||
import org.hibernate.annotations.Where; | ||
|
||
import com.moabam.global.common.entity.BaseTimeEntity; | ||
import com.moabam.global.common.util.BaseImageUrl; | ||
|
||
import jakarta.persistence.Column; | ||
import jakarta.persistence.Entity; | ||
import jakarta.persistence.EnumType; | ||
import jakarta.persistence.Enumerated; | ||
import jakarta.persistence.GeneratedValue; | ||
import jakarta.persistence.GenerationType; | ||
import jakarta.persistence.Id; | ||
import jakarta.persistence.Table; | ||
import lombok.AccessLevel; | ||
import lombok.Builder; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
@Getter | ||
@Entity | ||
@Table(name = "member") | ||
@SQLDelete(sql = "UPDATE member SET deleted_at = CURRENT_TIMESTAMP where participant_id = ?") | ||
@Where(clause = "deleted_at IS NOT NULL") | ||
@NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
public class Member extends BaseTimeEntity { | ||
|
||
@Id | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
@Column(name = "id") | ||
private Long id; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. R : pk는 id로 통일하기로 했던 것 같습니다. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 넵 확인했습니다. |
||
|
||
@Column(name = "social_id", nullable = false, unique = true) | ||
private String socialId; | ||
|
||
@Column(name = "nickname", nullable = false, unique = true) | ||
private String nickname; | ||
|
||
@Column(name = "intro", length = 30) | ||
private String intro; | ||
|
||
@Column(name = "profile_image", nullable = false) | ||
private String profileImage; | ||
|
||
@Column(name = "total_certify_count", nullable = false) | ||
@ColumnDefault("0") | ||
private long totalCertifyCount; | ||
|
||
@Column(name = "report_count", nullable = false) | ||
@ColumnDefault("0") | ||
private int reportCount; | ||
|
||
@Column(name = "current_night_count", nullable = false) | ||
@ColumnDefault("0") | ||
private int currentNightCount; | ||
|
||
@Column(name = "current_morning_count", nullable = false) | ||
@ColumnDefault("0") | ||
private int currentMorningCount; | ||
|
||
@Column(name = "morning_bug", nullable = false) | ||
@ColumnDefault("0") | ||
private int morningBug; | ||
|
||
@Column(name = "night_bug", nullable = false) | ||
@ColumnDefault("0") | ||
private int nightBug; | ||
|
||
@Column(name = "golden_bug", nullable = false) | ||
@ColumnDefault("0") | ||
private int goldenBug; | ||
|
||
@Enumerated(EnumType.STRING) | ||
@Column(name = "role", nullable = false) | ||
@ColumnDefault("USER") | ||
private Role role; | ||
|
||
@Column(name = "deleted_at") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. R: deleted_at이 member에서는 hard delete인가요 !? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @SQLdelete 논의가 아직 끝나지 않았었던 시기라, 곧 적용하겠습니다! |
||
private LocalDateTime deletedAt; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. R: @SQLDelete 적용! 그리고 삭제된 회원은 관리자가 아닌 이상 접근할 필요가 없으니까 @where도 넣어주면 좋을것 같아요! |
||
|
||
@Builder | ||
private Member(Long id, String socialId, String nickname, String profileImage) { | ||
this.id = id; | ||
this.socialId = requireNonNull(socialId); | ||
this.nickname = requireNonNull(nickname); | ||
this.profileImage = requireNonNullElse(profileImage, BaseImageUrl.PROFILE_URL); | ||
this.role = Role.USER; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package com.moabam.api.domain; | ||
|
||
public enum Role { | ||
|
||
USER, | ||
BLACK, | ||
ADMIN | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package com.moabam.api.dto; | ||
|
||
import static java.util.Objects.*; | ||
|
||
import java.util.List; | ||
|
||
import lombok.Builder; | ||
|
||
public record AuthorizationCodeRequest( | ||
String clientId, | ||
String redirectUri, | ||
String responseType, | ||
List<String> scope, | ||
String state | ||
) { | ||
|
||
@Builder | ||
public AuthorizationCodeRequest(String clientId, String redirectUri, String responseType, List<String> scope, | ||
String state) { | ||
this.clientId = requireNonNull(clientId); | ||
this.redirectUri = requireNonNull(redirectUri); | ||
this.responseType = responseType; | ||
this.scope = scope; | ||
this.state = state; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package com.moabam.api.mapper; | ||
|
||
import com.moabam.api.dto.AuthorizationCodeRequest; | ||
import com.moabam.global.config.OAuthConfig; | ||
|
||
import lombok.AccessLevel; | ||
import lombok.NoArgsConstructor; | ||
|
||
@NoArgsConstructor(access = AccessLevel.PRIVATE) | ||
public class OAuthMapper { | ||
|
||
public static AuthorizationCodeRequest toAuthorizationCodeRequest(OAuthConfig oAuthConfig) { | ||
return AuthorizationCodeRequest.builder() | ||
.clientId(oAuthConfig.client().clientId()) | ||
.redirectUri(oAuthConfig.provider().redirectUri()) | ||
.scope(oAuthConfig.client().scope()) | ||
.build(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package com.moabam.api.presentation; | ||
|
||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
import com.moabam.api.application.AuthenticationService; | ||
|
||
import jakarta.servlet.http.HttpServletResponse; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
@RestController | ||
@RequestMapping("/members") | ||
@RequiredArgsConstructor | ||
public class MemberController { | ||
|
||
private final AuthenticationService authenticationService; | ||
|
||
@GetMapping | ||
public void socialLogin(HttpServletResponse httpServletResponse) { | ||
authenticationService.redirectToLoginPage(httpServletResponse); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package com.moabam.global.common.util; | ||
|
||
import lombok.AccessLevel; | ||
import lombok.NoArgsConstructor; | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. C: Global Constant처럼 public static final로 하는거는 어떤가요? Enum으로 하신 이유가 무엇인가요!? |
||
@NoArgsConstructor(access = AccessLevel.PRIVATE) | ||
public class BaseImageUrl { | ||
|
||
public static final String PROFILE_URL = "/profile/baseUrl"; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package com.moabam.global.common.util; | ||
|
||
import lombok.AccessLevel; | ||
import lombok.NoArgsConstructor; | ||
|
||
@NoArgsConstructor(access = AccessLevel.PRIVATE) | ||
public class GlobalConstant { | ||
|
||
public static final String COMMA = ","; | ||
public static final String CHARSET_UTF_8 = ";charset=UTF-8"; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package com.moabam.global.common.util; | ||
|
||
import lombok.AccessLevel; | ||
import lombok.NoArgsConstructor; | ||
|
||
@NoArgsConstructor(access = AccessLevel.PRIVATE) | ||
public class OAuthParameterNames { | ||
|
||
public static final String RESPONSE_TYPE = "response_type"; | ||
public static final String CODE = "code"; | ||
public static final String CLIENT_ID = "client_id"; | ||
public static final String REDIRECT_URI = "redirect_uri"; | ||
public static final String SCOPE = "scope"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. C : 매직넘버를 빼려는 의도는 알겠으나, 과도한 static 사용 시 메모리에 대한 걱정을 해야할 것 같아요. |
||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. C: 대소문자만 차이가 나서 굳이 하는게 좋을까 생각이 듭니다! |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package com.moabam.global.config; | ||
|
||
import java.util.List; | ||
|
||
import org.springframework.boot.context.properties.ConfigurationProperties; | ||
|
||
@ConfigurationProperties(prefix = "oauth2") | ||
public record OAuthConfig( | ||
Provider provider, | ||
Client client | ||
) { | ||
|
||
public record Client( | ||
String provider, | ||
String clientId, | ||
String authorizationGrantType, | ||
List<String> scope | ||
) { | ||
|
||
} | ||
|
||
public record Provider( | ||
String authorizationUri, | ||
String redirectUri | ||
) { | ||
|
||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Q : @ConfigurationPropertiesScan 에 대한 방식은 논의가 필요할 것 같습니다 !
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
완