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

[NAYB-153] feat: api 권한 설정 #113

Merged
merged 3 commits into from
Sep 18, 2023
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 @@ -46,6 +46,9 @@ public void callUnlinkOAuthUser(final FindUserDetailResponse userDetailResponse)
Map<String, Object> response = sendPostApiRequest(unlinkHttpMessage);
log.info("회원의 연결이 종료되었습니다. 회원 ID={}", response);
oAuthHttpMessageProvider.checkSuccessUnlinkRequest(response);
authorizedClientService.removeAuthorizedClient(
userDetailResponse.provider(),
userDetailResponse.provider());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
package com.prgrms.nabmart.global.config;

import static org.springframework.http.HttpMethod.GET;
import static org.springframework.http.HttpMethod.POST;
import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher;

import com.prgrms.nabmart.global.auth.jwt.JwtAuthenticationProvider;
import com.prgrms.nabmart.global.auth.jwt.filter.JwtAuthenticationFilter;
import com.prgrms.nabmart.global.auth.oauth.handler.OAuth2AuthenticationSuccessHandler;
import java.util.List;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcOperations;
Expand All @@ -17,6 +22,7 @@
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.context.SecurityContextHolderFilter;
import org.springframework.security.web.util.matcher.RequestMatcher;

@Configuration
@EnableWebSecurity
Expand All @@ -37,7 +43,11 @@ public SecurityFilterChain filterChain(
JwtAuthenticationProvider jwtAuthenticationProvider) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.anyRequest().permitAll())
.requestMatchers(requestPermitAll()).permitAll()
.requestMatchers(requestHasRoleUser()).hasRole("USER")
.requestMatchers(requestHasRoleRider()).hasRole("RIDER")
.requestMatchers(requestHasRoleAdmin()).hasRole("ADMIN")
.anyRequest().denyAll())
.csrf(AbstractHttpConfigurer::disable)
.headers(AbstractHttpConfigurer::disable)
.httpBasic(AbstractHttpConfigurer::disable)
Expand All @@ -53,6 +63,48 @@ public SecurityFilterChain filterChain(
return http.build();
}

private RequestMatcher[] requestPermitAll() {
List<RequestMatcher> requestMatchers = List.of(
antMatcher(POST, "/oauth2/authorization/**"),
antMatcher(POST, "/api/v1/riders/**"),
antMatcher(GET, "/api/v1/categories/**"),
antMatcher(GET, "/api/v1/items/**"),
antMatcher(GET, "/api/v1/events/**"));
return requestMatchers.toArray(RequestMatcher[]::new);
}

private RequestMatcher[] requestHasRoleUser() {
List<RequestMatcher> requestMatchers = List.of(
antMatcher("/api/v1/users/me"),
antMatcher("/api/v1/cart-items/**"),
antMatcher("/api/v1/my-cart-items"),
antMatcher("/api/v1/likes/**"),
antMatcher("/api/v1/reviews/**"),
antMatcher("/api/v1/users/my-reviews"),
antMatcher("/api/v1/orders/**"),
antMatcher("/api/v1/pays/**"),
antMatcher("/api/v1/coupons/**")
);
return requestMatchers.toArray(RequestMatcher[]::new);
}

private RequestMatcher[] requestHasRoleRider() {
List<RequestMatcher> requestMatchers = List.of(
antMatcher("/api/v1/deliveries/**")
);
return requestMatchers.toArray(RequestMatcher[]::new);
}

private RequestMatcher[] requestHasRoleAdmin() {
List<RequestMatcher> requestMatchers = List.of(
antMatcher("/api/v1/main-categories/**"),
antMatcher("/api/v1/sub-categories/**"),
antMatcher("/api/v1/items/**"),
antMatcher("/api/v1/events/**"),
antMatcher(POST, "/api/v1/coupons"));
return requestMatchers.toArray(RequestMatcher[]::new);
}

@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
Expand Down
15 changes: 8 additions & 7 deletions src/test/java/com/prgrms/nabmart/base/BaseControllerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
import com.prgrms.nabmart.domain.payment.service.PaymentService;
import com.prgrms.nabmart.domain.review.service.ReviewService;
import com.prgrms.nabmart.domain.user.service.UserService;
import com.prgrms.nabmart.global.auth.jwt.JwtAuthenticationProvider;
import com.prgrms.nabmart.global.auth.jwt.filter.JwtAuthenticationFilter;
import com.prgrms.nabmart.global.auth.oauth.client.OAuthRestClient;
import com.prgrms.nabmart.global.auth.service.RiderAuthenticationService;
import com.prgrms.nabmart.global.auth.support.AuthFixture;
Expand All @@ -31,8 +33,6 @@
import org.springframework.restdocs.RestDocumentationExtension;
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation;
import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
Expand Down Expand Up @@ -107,21 +107,22 @@ public abstract class BaseControllerTest {

@BeforeEach
void authenticationSetUp() {
Authentication authentication = AuthFixture.usernamePasswordAuthenticationToken();
SecurityContextHolder.getContext().setAuthentication(authentication);

accessToken = AuthFixture.accessToken();
}

@BeforeEach
void restDocsSetUp(
void mockMvcSetUp(
final WebApplicationContext context,
final RestDocumentationContextProvider provider) {
JwtAuthenticationProvider jwtAuthenticationProvider
= new JwtAuthenticationProvider(AuthFixture.tokenProvider());

this.mockMvc = MockMvcBuilders.webAppContextSetup(context)
.apply(MockMvcRestDocumentation.documentationConfiguration(provider))
.alwaysDo(print())
.alwaysDo(restDocs)
.addFilter(new CharacterEncodingFilter("UTF-8", true))
.addFilter(new JwtAuthenticationFilter(jwtAuthenticationProvider))
.apply(MockMvcRestDocumentation.documentationConfiguration(provider))
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ void registerCartItem() throws Exception {
// when
ResultActions resultActions = mockMvc.perform(post("/api/v1/cart-items")
.content(objectMapper.writeValueAsString(registerCartItemCommand))
.contentType(MediaType.APPLICATION_JSON));
.contentType(MediaType.APPLICATION_JSON)
.header(AUTHORIZATION, accessToken));

// then
resultActions
Expand Down Expand Up @@ -146,7 +147,8 @@ void findCartItemsByUserId() throws Exception {
// when
ResultActions resultActions = mockMvc.perform(
get("/api/v1/my-cart-items")
.contentType(MediaType.APPLICATION_JSON));
.contentType(MediaType.APPLICATION_JSON)
.header(AUTHORIZATION, accessToken));

// then
resultActions.andExpect(status().isOk())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ void RegisterUserCoupon() throws Exception {
ResultActions resultActions = mockMvc.perform(
post("/api/v1/my-coupons/{couponId}", couponId)
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(registerUserCouponCommand)));
.content(objectMapper.writeValueAsString(registerUserCouponCommand))
.header(AUTHORIZATION, accessToken));

// Then
resultActions
Expand Down Expand Up @@ -166,7 +167,8 @@ void findIssuedCoupons() throws Exception {

// When
ResultActions resultActions = mockMvc.perform(get("/api/v1/my-coupons")
.contentType(MediaType.APPLICATION_JSON));
.contentType(MediaType.APPLICATION_JSON)
.header(AUTHORIZATION, accessToken));

// Then
resultActions.andExpect(status().isOk())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,8 @@ void findWaitingDeliveries() throws Exception {
ResultActions resultActions = mockMvc.perform(get("/api/v1/deliveries/waiting")
.param("page", String.valueOf(page))
.param("size", String.valueOf(size))
.accept(MediaType.APPLICATION_JSON));
.accept(MediaType.APPLICATION_JSON)
.header(AUTHORIZATION, accessToken));

//then
resultActions.andExpect(status().isOk())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ void findOrder() throws Exception {
// when
ResultActions result = mockMvc.perform(
get("/api/v1/orders/{orderId}", order.getOrderId())
.contentType(MediaType.APPLICATION_JSON));
.contentType(MediaType.APPLICATION_JSON)
.header(AUTHORIZATION, accessToken));

// then
result
Expand Down Expand Up @@ -100,7 +101,8 @@ void findOrders() throws Exception {
// when
ResultActions result = mockMvc.perform(
get("/api/v1/orders?page={page}", 1)
.contentType(MediaType.APPLICATION_JSON));
.contentType(MediaType.APPLICATION_JSON)
.header(AUTHORIZATION, accessToken));

// then
result
Expand Down Expand Up @@ -148,7 +150,8 @@ void createOrder() throws Exception {
ResultActions result = mockMvc.perform(
post("/api/v1/orders")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(createOrderRequest)));
.content(objectMapper.writeValueAsString(createOrderRequest))
.header(AUTHORIZATION, accessToken));

// then
result
Expand Down Expand Up @@ -183,7 +186,8 @@ void createOrder() throws Exception {
ResultActions result = mockMvc.perform(
post("/api/v1/orders/{orderId}/apply-coupon", order.getOrderId())
.param("couponId", String.valueOf(1L))
.contentType(MediaType.APPLICATION_JSON));
.contentType(MediaType.APPLICATION_JSON)
.header(AUTHORIZATION, accessToken));

// then
result
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ void postPay() throws Exception {
// when
ResultActions result = mockMvc.perform(
post("/api/v1/pays/{orderId}", order.getOrderId())
.contentType(MediaType.APPLICATION_JSON));
.contentType(MediaType.APPLICATION_JSON)
.header(AUTHORIZATION, accessToken));

// then
result
Expand Down Expand Up @@ -104,7 +105,8 @@ void paySuccess() throws Exception {
.queryParam("orderId", order.getUuid())
.queryParam("paymentKey", paymentKey)
.queryParam("amount", String.valueOf(order.getPrice()))
.contentType(MediaType.APPLICATION_JSON));
.contentType(MediaType.APPLICATION_JSON)
.header(AUTHORIZATION, accessToken));

// then
result
Expand Down Expand Up @@ -143,7 +145,8 @@ void pay() throws Exception {
get("/api/v1/pays/toss/fail")
.queryParam("orderId", order.getUuid())
.queryParam("message", errorMessage)
.contentType(MediaType.APPLICATION_JSON));
.contentType(MediaType.APPLICATION_JSON)
.header(AUTHORIZATION, accessToken));

// then
result
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ void registerReview() throws Exception {
// when
ResultActions resultActions = mockMvc.perform(post("/api/v1/reviews")
.content(objectMapper.writeValueAsString(registerReviewCommand))
.contentType(MediaType.APPLICATION_JSON));
.contentType(MediaType.APPLICATION_JSON)
.header(AUTHORIZATION, accessToken));

// then
resultActions
Expand Down Expand Up @@ -142,7 +143,8 @@ void findReviewsByUser() throws Exception {
// when
ResultActions resultActions = mockMvc.perform(
get("/api/v1/users/my-reviews")
.contentType(MediaType.APPLICATION_JSON));
.contentType(MediaType.APPLICATION_JSON)
.header(AUTHORIZATION, accessToken));

// then
resultActions.andExpect(status().isOk())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import lombok.NoArgsConstructor;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.crypto.password.PasswordEncoder;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
Expand All @@ -23,7 +24,6 @@ public final class AuthFixture {
private static final String CLIENT_SECRET = "thisIsClientSecretForTestNotARealSecretSoDontWorry";
private static final int EXPIRY_SECONDS = 60;
private static final Long USER_ID = 1L;
private static final String TOKEN = "token";
private static final String RIDER_USERNAME = "rider123";
private static final String RIDER_PASSWORD = "rider123";
private static final String RIDER_ADDRESS = "address";
Expand All @@ -33,8 +33,11 @@ public static TokenProvider tokenProvider() {
}

public static Authentication usernamePasswordAuthenticationToken() {
JwtAuthentication authentication = new JwtAuthentication(USER_ID, TOKEN);
return new UsernamePasswordAuthenticationToken(authentication, null);
JwtAuthentication authentication = new JwtAuthentication(USER_ID, accessToken());
return new UsernamePasswordAuthenticationToken(
authentication,
null,
UserRole.ROLE_USER.getAuthorities().stream().map(SimpleGrantedAuthority::new).toList());
}

public static RegisterUserResponse registerUserResponse() {
Expand Down