Skip to content

Commit

Permalink
fix: 회원 이벤트 생성 버그 수정
Browse files Browse the repository at this point in the history
  • Loading branch information
Arachneee committed Dec 4, 2024
1 parent f098cd0 commit 497a592
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 97 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package haengdong.common.auth.application;


import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import haengdong.event.application.EventService;
import haengdong.common.auth.TokenProvider;
import haengdong.user.domain.Role;
import haengdong.common.exception.AuthenticationException;
import haengdong.common.exception.HaengdongErrorCode;
import haengdong.event.application.EventService;
import haengdong.user.domain.Role;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class AuthService {
Expand Down Expand Up @@ -36,7 +36,7 @@ public String createMemberToken(Long userId) {
return tokenProvider.createToken(payload);
}

public Long findUserIdByToken(String token) {
public Long findUserIdByJWT(String token) {
validateToken(token);
Map<String, Object> payload = tokenProvider.getPayload(token);
return ((Integer) payload.get(CLAIM_SUB)).longValue();
Expand Down
36 changes: 36 additions & 0 deletions server/src/main/java/haengdong/common/auth/config/AuthConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package haengdong.common.auth.config;

import haengdong.common.auth.TokenProvider;
import haengdong.common.auth.application.AuthService;
import haengdong.common.auth.infrastructure.AuthenticationExtractor;
import haengdong.common.auth.infrastructure.JwtTokenProvider;
import haengdong.common.properties.JwtProperties;
import haengdong.event.application.EventService;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@RequiredArgsConstructor
@EnableConfigurationProperties({JwtProperties.class})
@Configuration
public class AuthConfig {

private final JwtProperties jwtProperties;
private final EventService eventService;

@Bean
public AuthService authService() {
return new AuthService(tokenProvider(), eventService);
}

@Bean
public TokenProvider tokenProvider() {
return new JwtTokenProvider(jwtProperties);
}

@Bean
public AuthenticationExtractor authenticationExtractor() {
return new AuthenticationExtractor();
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
package haengdong.common.auth.infrastructure;

import haengdong.common.auth.application.AuthService;
import haengdong.common.exception.AuthenticationException;
import haengdong.common.exception.HaengdongErrorCode;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import haengdong.common.auth.application.AuthService;
import haengdong.common.exception.AuthenticationException;
import haengdong.common.exception.HaengdongErrorCode;

@Slf4j
@RequiredArgsConstructor
public class AdminInterceptor implements HandlerInterceptor {

public static final String LOGIN_MEMBER_REQUEST = "loginUserId";
Expand All @@ -23,11 +25,6 @@ public class AdminInterceptor implements HandlerInterceptor {
private final AuthService authService;
private final AuthenticationExtractor authenticationExtractor;

public AdminInterceptor(AuthService authService, AuthenticationExtractor authenticationExtractor) {
this.authService = authService;
this.authenticationExtractor = authenticationExtractor;
}

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
HttpMethod method = HttpMethod.valueOf(request.getMethod());
Expand All @@ -39,8 +36,8 @@ public boolean preHandle(HttpServletRequest request, HttpServletResponse respons
}

private void validateToken(HttpServletRequest request) {
String token = authenticationExtractor.extract(request, authService.getTokenName());
Long userId = authService.findUserIdByToken(token);
String jwt = authenticationExtractor.extract(request, authService.getTokenName());
Long userId = authService.findUserIdByJWT(jwt);
String uri = request.getRequestURI();
Matcher matcher = ADMIN_URI_PATTERN.matcher(uri);
if (!matcher.find()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
package haengdong.common.auth.infrastructure;

import static haengdong.common.auth.infrastructure.AdminInterceptor.LOGIN_MEMBER_REQUEST;

import haengdong.common.auth.Login;
import haengdong.common.auth.application.AuthService;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

@RequiredArgsConstructor
public class AuthenticationPrincipalArgumentResolver implements HandlerMethodArgumentResolver {

private final AuthService authService;
private final AuthenticationExtractor authenticationExtractor;

@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(Login.class) && parameter.getParameterType().equals(Long.class);
Expand All @@ -20,7 +24,8 @@ public boolean supportsParameter(MethodParameter parameter) {
@Override
public Long resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
String jwt = authenticationExtractor.extract(request, authService.getTokenName());

return (Long) request.getAttribute(LOGIN_MEMBER_REQUEST);
return authService.findUserIdByJWT(jwt);
}
}
34 changes: 14 additions & 20 deletions server/src/main/java/haengdong/common/config/WebMvcConfig.java
Original file line number Diff line number Diff line change
@@ -1,28 +1,27 @@
package haengdong.common.config;

import haengdong.common.auth.TokenProvider;
import haengdong.common.auth.application.AuthService;
import haengdong.common.auth.infrastructure.AuthenticationExtractor;
import haengdong.common.auth.infrastructure.JwtTokenProvider;
import haengdong.common.auth.infrastructure.AdminInterceptor;
import haengdong.common.auth.infrastructure.AuthenticationExtractor;
import haengdong.common.auth.infrastructure.AuthenticationPrincipalArgumentResolver;
import haengdong.common.properties.CorsProperties;
import haengdong.common.properties.JwtProperties;
import haengdong.event.application.EventService;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@RequiredArgsConstructor
@EnableConfigurationProperties({JwtProperties.class, CorsProperties.class})
@EnableConfigurationProperties({CorsProperties.class})
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

private final JwtProperties jwtProperties;
private final EventService eventService;
private final AuthService authService;
private final AuthenticationExtractor authenticationExtractor;
private final CorsProperties corsProperties;

@Override
Expand All @@ -41,23 +40,18 @@ public void addInterceptors(InterceptorRegistry registry) {
.addPathPatterns("/api/admin/**");
}

@Bean
public AdminInterceptor adminInterceptor() {
return new AdminInterceptor(authService(), authenticationExtractor());
}

@Bean
public AuthService authService() {
return new AuthService(tokenProvider(), eventService);
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(authenticationPrincipalArgumentResolver());
}

@Bean
public TokenProvider tokenProvider() {
return new JwtTokenProvider(jwtProperties);
public AdminInterceptor adminInterceptor() {
return new AdminInterceptor(authService, authenticationExtractor);
}

@Bean
public AuthenticationExtractor authenticationExtractor() {
return new AuthenticationExtractor();
public AuthenticationPrincipalArgumentResolver authenticationPrincipalArgumentResolver() {
return new AuthenticationPrincipalArgumentResolver(authService, authenticationExtractor);
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
package haengdong.event.presentation;

import haengdong.common.auth.Login;
import haengdong.common.auth.application.AuthService;
import haengdong.common.properties.CookieProperties;
import haengdong.event.application.EventImageFacadeService;
import haengdong.event.application.EventService;
import haengdong.event.application.request.EventAppRequest;
import haengdong.event.application.response.EventAppResponse;
import haengdong.event.application.response.EventImageUrlAppResponse;
import haengdong.event.application.response.MemberBillReportAppResponse;
import haengdong.event.presentation.request.EventGuestSaveRequest;
import haengdong.event.presentation.request.EventLoginRequest;
import haengdong.event.presentation.request.EventSaveRequest;
import haengdong.event.presentation.response.EventDetailResponse;
import haengdong.event.presentation.response.EventImagesResponse;
import haengdong.event.presentation.response.EventResponse;
Expand Down Expand Up @@ -66,6 +69,12 @@ public ResponseEntity<EventResponse> saveEventGuest(@Valid @RequestBody EventGue
.body(eventResponse);
}

@PostMapping("/api/events")
public ResponseEntity<EventResponse> saveEvent(@Login Long userId, @Valid @RequestBody EventSaveRequest request) {
EventResponse eventResponse = EventResponse.of(eventService.saveEvent(new EventAppRequest(request.eventName(), userId)));
return ResponseEntity.ok(eventResponse);
}

@PostMapping("/api/events/{eventId}/login")
public ResponseEntity<Void> loginEvent(
@PathVariable("eventId") String token,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package haengdong.event.presentation.admin;

import haengdong.event.application.EventImageFacadeService;
import haengdong.event.application.EventService;
import haengdong.event.presentation.request.EventUpdateRequest;
import jakarta.validation.Valid;
import java.util.List;
import lombok.RequiredArgsConstructor;
Expand All @@ -13,13 +16,6 @@
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import haengdong.event.application.EventImageFacadeService;
import haengdong.event.application.EventService;
import haengdong.event.application.request.EventAppRequest;
import haengdong.common.auth.Login;
import haengdong.event.presentation.request.EventSaveRequest;
import haengdong.event.presentation.request.EventUpdateRequest;
import haengdong.event.presentation.response.EventResponse;

@Slf4j
@RequiredArgsConstructor
Expand All @@ -29,12 +25,6 @@ public class AdminEventController {
private final EventService eventService;
private final EventImageFacadeService eventImageFacadeService;

@PostMapping("/api/admin/events")
public ResponseEntity<EventResponse> saveEvent(@Login Long userId, @Valid @RequestBody EventSaveRequest request) {
EventResponse eventResponse = EventResponse.of(eventService.saveEvent(new EventAppRequest(request.eventName(), userId)));
return ResponseEntity.ok(eventResponse);
}

@PostMapping("/api/admin/events/{eventId}/auth")
public ResponseEntity<Void> authenticate() {
return ResponseEntity.ok().build();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,42 +1,35 @@
package haengdong.docs;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
import static haengdong.support.fixture.Fixture.EVENT_COOKIE;
import static org.mockito.Mockito.mock;
import static org.springframework.restdocs.cookies.CookieDocumentation.cookieWithName;
import static org.springframework.restdocs.cookies.CookieDocumentation.requestCookies;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.multipart;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.patch;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete;
import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest;
import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse;
import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint;
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields;
import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields;
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
import static org.springframework.restdocs.request.RequestDocumentation.partWithName;
import static org.springframework.restdocs.request.RequestDocumentation.pathParameters;
import static org.springframework.restdocs.request.RequestDocumentation.requestParts;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static haengdong.support.fixture.Fixture.EVENT_COOKIE;

import haengdong.event.application.EventImageFacadeService;
import haengdong.event.application.EventService;
import haengdong.event.presentation.admin.AdminEventController;
import haengdong.event.presentation.request.EventUpdateRequest;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.restdocs.payload.JsonFieldType;
import haengdong.event.application.EventImageFacadeService;
import haengdong.event.application.EventService;
import haengdong.event.application.request.EventAppRequest;
import haengdong.event.application.response.EventAppResponse;
import haengdong.event.presentation.admin.AdminEventController;
import haengdong.event.presentation.request.EventSaveRequest;
import haengdong.event.presentation.request.EventUpdateRequest;
import haengdong.support.fixture.Fixture;

class AdminEventControllerDocsTest extends RestDocsSupport {

Expand Down Expand Up @@ -157,37 +150,4 @@ void deleteImage() throws Exception {
)
);
}

@DisplayName("이벤트를 생성한다.")
@Test
void saveEvent() throws Exception {
EventSaveRequest eventSaveRequest = new EventSaveRequest("토다리");
String requestBody = objectMapper.writeValueAsString(eventSaveRequest);
String eventId = "쿠키 토큰";
EventAppResponse eventAppResponse = new EventAppResponse(eventId, 1L);
given(eventService.saveEvent(any(EventAppRequest.class))).willReturn(eventAppResponse);

mockMvc.perform(post("/api/admin/events")
.contentType(MediaType.APPLICATION_JSON)
.content(requestBody)
.cookie(Fixture.EVENT_COOKIE))
.andDo(print())
.andExpect(status().isOk())
.andDo(
document("createEvent",
preprocessRequest(prettyPrint()),
preprocessResponse(prettyPrint()),
requestFields(
fieldWithPath("eventName").type(JsonFieldType.STRING).description("행사 이름")
),
requestCookies(
cookieWithName("accessToken").description("행사 관리자 토큰")
),
responseFields(
fieldWithPath("eventId").type(JsonFieldType.STRING)
.description("행사 ID")
)
)
);
}
}
Loading

0 comments on commit 497a592

Please sign in to comment.