-
Notifications
You must be signed in to change notification settings - Fork 8
feat: 관리자 role 추가 #192
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: 관리자 role 추가 #192
Changes from 14 commits
c58f732
9d3f5e7
5e5fda9
ed584a3
1ac57ff
5ced9e3
f698ada
dbca920
df11c1d
a1b98d1
b0b78cc
cf2c2d6
b04de5f
719762e
c7bc0fd
34970ce
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 |
|---|---|---|
| @@ -1,6 +1,7 @@ | ||
| package com.example.solidconnection.custom.security.filter; | ||
|
|
||
| import com.example.solidconnection.custom.exception.CustomException; | ||
| import com.example.solidconnection.custom.exception.ErrorCode; | ||
| import com.example.solidconnection.custom.response.ErrorResponse; | ||
| import com.fasterxml.jackson.databind.ObjectMapper; | ||
| import jakarta.servlet.FilterChain; | ||
|
|
@@ -9,12 +10,16 @@ | |
| import jakarta.servlet.http.HttpServletResponse; | ||
| import lombok.NonNull; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.security.access.AccessDeniedException; | ||
| import org.springframework.security.authentication.AnonymousAuthenticationToken; | ||
| import org.springframework.security.core.Authentication; | ||
| import org.springframework.security.core.context.SecurityContextHolder; | ||
| import org.springframework.stereotype.Component; | ||
| import org.springframework.web.filter.OncePerRequestFilter; | ||
|
|
||
| import java.io.IOException; | ||
|
|
||
| import static com.example.solidconnection.custom.exception.ErrorCode.ACCESS_DENIED; | ||
| import static com.example.solidconnection.custom.exception.ErrorCode.AUTHENTICATION_FAILED; | ||
|
|
||
| @Component | ||
|
|
@@ -31,25 +36,28 @@ protected void doFilterInternal(@NonNull HttpServletRequest request, | |
| filterChain.doFilter(request, response); | ||
| } catch (CustomException e) { | ||
| customCommence(response, e); | ||
| } catch (AccessDeniedException e) { | ||
| Authentication auth = SecurityContextHolder.getContext().getAuthentication(); | ||
| ErrorCode errorCode = auth instanceof AnonymousAuthenticationToken ? AUTHENTICATION_FAILED : ACCESS_DENIED; | ||
| generalCommence(response, e, errorCode); | ||
| } catch (Exception e) { | ||
| generalCommence(response, e); | ||
| generalCommence(response, e, AUTHENTICATION_FAILED); | ||
| } | ||
| } | ||
|
|
||
| public void customCommence(HttpServletResponse response, CustomException customException) throws IOException { | ||
| SecurityContextHolder.clearContext(); | ||
| ErrorResponse errorResponse = new ErrorResponse(customException); | ||
| writeResponse(response, errorResponse); | ||
| writeResponse(response, errorResponse, customException.getCode()); | ||
| } | ||
|
|
||
| public void generalCommence(HttpServletResponse response, Exception exception) throws IOException { | ||
| SecurityContextHolder.clearContext(); | ||
| ErrorResponse errorResponse = new ErrorResponse(AUTHENTICATION_FAILED, exception.getMessage()); | ||
| writeResponse(response, errorResponse); | ||
| public void generalCommence(HttpServletResponse response, Exception exception, ErrorCode errorCode) throws IOException { | ||
| ErrorResponse errorResponse = new ErrorResponse(errorCode, exception.getMessage()); | ||
| writeResponse(response, errorResponse, errorCode.getCode()); | ||
|
Comment on lines
48
to
+55
Collaborator
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. 다시 보니 |
||
| } | ||
|
|
||
| private void writeResponse(HttpServletResponse response, ErrorResponse errorResponse) throws IOException { | ||
| response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); | ||
| private void writeResponse(HttpServletResponse response, ErrorResponse errorResponse, int statusCode) throws IOException { | ||
| SecurityContextHolder.clearContext(); | ||
| response.setStatus(statusCode); | ||
|
Comment on lines
+63
to
+60
Collaborator
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. 이제야 보이는 부분이긴 한데😅 SecurityContextHolder.clearContext(); 를 |
||
| response.setContentType("application/json"); | ||
| response.setCharacterEncoding("UTF-8"); | ||
| response.getWriter().write(objectMapper.writeValueAsString(errorResponse)); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| package com.example.solidconnection.custom.security.mapper; | ||
|
Collaborator
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. 이 클래스는 SiteUserDetails 에서만 사용되니 |
||
|
|
||
| import com.example.solidconnection.type.Role; | ||
| import org.springframework.security.core.authority.SimpleGrantedAuthority; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| public class SecurityRoleMapper { | ||
|
|
||
| private static final String ROLE_PREFIX = "ROLE_"; | ||
|
|
||
| private SecurityRoleMapper() { | ||
| } | ||
|
Comment on lines
+12
to
+
Collaborator
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. 인스턴스 생성 방지 좋네요😊 |
||
|
|
||
| public static List<SimpleGrantedAuthority> mapRoleToAuthorities(Role role) { | ||
| return List.of(new SimpleGrantedAuthority(ROLE_PREFIX + role.name())); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,8 @@ | ||
| package com.example.solidconnection.type; | ||
|
|
||
| public enum Role { | ||
|
|
||
| ADMIN, | ||
| MENTOR, | ||
| MENTEE | ||
| MENTEE; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| ALTER TABLE site_user | ||
| modify ROLE enum ('MENTEE', 'MENTOR', 'ADMIN') NOT NULL; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -46,6 +46,21 @@ class SiteUserDetailsServiceTest { | |
| ); | ||
| } | ||
|
|
||
| @Test | ||
| void 사용자_권한_정보를_정상적으로_반환한다() { | ||
| // given | ||
| SiteUser siteUser = siteUserRepository.save(createSiteUser()); | ||
| String username = getUserName(siteUser); | ||
|
Collaborator
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. SiteUserDetailsServiceTest 에서 SiteUserDetails의 |
||
|
|
||
| // when | ||
| SiteUserDetails userDetails = (SiteUserDetails) userDetailsService.loadUserByUsername(username); | ||
|
|
||
| // then | ||
| assertThat(userDetails.getAuthorities()) | ||
| .extracting("authority") | ||
| .containsExactly("ROLE_" + siteUser.getRole().name()); | ||
| } | ||
|
|
||
| @Nested | ||
| class 예외_응답을_반환한다 { | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.