Skip to content
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
@@ -1,11 +1,12 @@
package com.retrip.auth.application.config;

import com.retrip.auth.application.in.MemberService;
import com.retrip.auth.application.in.MemberQueryService;
import com.retrip.auth.infra.adapter.in.rest.filter.JwtAuthenticationFilter;
import com.retrip.auth.infra.adapter.in.rest.filter.LoginAuthenticationFilter;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
Expand All @@ -30,16 +31,17 @@ public LoginAuthenticationFilter loginAuthenticationFilter(JwtConfig jwtConfig,
}

@Bean
public JwtAuthenticationFilter jwtAuthenticationFilter(JwtConfig jwtConfig){
public JwtAuthenticationFilter jwtAuthenticationFilter(JwtConfig jwtConfig) {
return new JwtAuthenticationFilter(jwtConfig);
}

@Bean
public AuthenticationManager authenticationManager(
HttpSecurity http,
UsernamePasswordAuthenticationProvider usernamePasswordAuthenticationProvider,
MemberService memberService) throws Exception {
MemberQueryService memberQueryService) throws Exception {
return http.authenticationProvider(usernamePasswordAuthenticationProvider)
.userDetailsService(memberService)
.userDetailsService(memberQueryService)
.getSharedObject(AuthenticationManagerBuilder.class)
.build();
}
Expand All @@ -50,7 +52,18 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http, LoginAuthentic
http.csrf(AbstractHttpConfigurer::disable)
.addFilterAt(loginAuthenticationFilter, BasicAuthenticationFilter.class)
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
http.authorizeHttpRequests(auth -> auth.anyRequest().authenticated());
http.authorizeHttpRequests(auth -> {
auth
.requestMatchers(HttpMethod.POST, "users").permitAll()
.requestMatchers(
"/swagger-ui/**",
"/v3/api-docs/**",
"/swagger-resources/**",
"/webjars/**"
).permitAll()
.anyRequest().authenticated();
}
);

return http.build();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.retrip.auth.application.config;

import com.retrip.auth.application.in.MemberService;
import com.retrip.auth.application.in.MemberQueryService;
import lombok.RequiredArgsConstructor;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
Expand All @@ -15,7 +15,7 @@
@RequiredArgsConstructor
public class UsernamePasswordAuthenticationProvider implements AuthenticationProvider {

private final MemberService memberService;
private final MemberQueryService memberQueryService;
private final PasswordEncoder passwordEncoder;

@Override
Expand All @@ -24,7 +24,7 @@ public Authentication authenticate(Authentication authentication)
String username = authentication.getName();
String password = String.valueOf(authentication.getCredentials());

UserDetails user = memberService.loadUserByUsername(username);
UserDetails user = memberQueryService.loadUserByUsername(username);

if (!passwordEncoder.matches(password, user.getPassword())) {
throw new BadCredentialsException("Bad credentials");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.retrip.auth.application.in;

import com.retrip.auth.application.config.CustomUserDetails;
import com.retrip.auth.application.out.repository.MemberQueryRepository;
import com.retrip.auth.domain.entity.Member;
import com.retrip.auth.domain.exception.MemberNotFoundException;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class MemberQueryService implements UserDetailsService {

private final MemberQueryRepository memberQueryRepository;

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Member member = memberQueryRepository.findByEmailWithAuthorities(username).orElseThrow(MemberNotFoundException::new);
return new CustomUserDetails(member);
}
}
21 changes: 10 additions & 11 deletions src/main/java/com/retrip/auth/application/in/MemberService.java
Original file line number Diff line number Diff line change
@@ -1,28 +1,27 @@
package com.retrip.auth.application.in;

import com.retrip.auth.application.config.CustomUserDetails;
import com.retrip.auth.application.in.request.MemberCreateRequest;
import com.retrip.auth.application.in.response.MemberCreateResponse;
import com.retrip.auth.application.in.usercase.ManageMemberUseCase;
import com.retrip.auth.application.out.repository.MemberQueryRepository;
import com.retrip.auth.application.out.repository.MemberRepository;
import com.retrip.auth.domain.entity.Member;
import com.retrip.auth.domain.exception.MemberNotFoundException;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
@Transactional
public class MemberService implements ManageMemberUseCase, UserDetailsService {
public class MemberService implements ManageMemberUseCase {

private final MemberQueryRepository memberQueryRepository;
private final MemberRepository memberRepository;
private final PasswordEncoder passwordEncoder;

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Member member = memberQueryRepository.findByEmailWithAuthorities(username).orElseThrow(MemberNotFoundException::new);
return new CustomUserDetails(member);
public MemberCreateResponse createUser(MemberCreateRequest request) {
String encode = passwordEncoder.encode(request.password());
Member member = memberRepository.save(request.to(encode));
return MemberCreateResponse.of(member);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.retrip.auth.application.in.request;

import com.retrip.auth.domain.entity.Member;
import io.swagger.v3.oas.annotations.media.Schema;

@Schema(description = "Member νšŒμ›κ°€μž… Request")
public record MemberCreateRequest(
@Schema(description = "이메일")
String email,
@Schema(description = "λΉ„λ°€λ²ˆν˜Έ")
String password,
@Schema(description = "μ‚¬μš©μž 이름")
String name
) {
public Member to(String encodePassword) {
return Member.create(name, email, encodePassword);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.retrip.auth.application.in.response;

import com.retrip.auth.domain.entity.Member;

import java.util.UUID;

public record MemberCreateResponse(
UUID id,
String email,
String name
) {
public static MemberCreateResponse of(Member member) {
return new MemberCreateResponse(member.getId(), member.getEmail().getValue(), member.getName().getValue());
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package com.retrip.auth.application.in.usercase;


import com.retrip.auth.application.in.request.MemberCreateRequest;
import com.retrip.auth.application.in.response.MemberCreateResponse;

public interface ManageMemberUseCase {
MemberCreateResponse createUser(MemberCreateRequest request);
}
18 changes: 14 additions & 4 deletions src/main/java/com/retrip/auth/domain/entity/Member.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,11 @@
import com.retrip.auth.domain.vo.MemberName;
import com.retrip.auth.domain.vo.MemberPassword;
import jakarta.persistence.*;
import lombok.*;

import java.util.List;
import java.util.UUID;

import lombok.*;
import org.springframework.security.crypto.password.PasswordEncoder;

@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Builder
Expand All @@ -37,7 +35,7 @@ public class Member extends BaseEntity {
private Authorities authorities;


public static Member create(String name, String email, String password, List<String> authorities) {
public static Member create(String name, String email, String password, List<String> authorities) {
Member member = Member.builder()
.id(UUID.randomUUID())
.name(new MemberName(name))
Expand All @@ -47,4 +45,16 @@ public static Member create(String name, String email, String password, List<St
member.authorities = new Authorities(authorities, member);
return member;
}


public static Member create(String name, String email, String password) {
Member member = Member.builder()
.id(UUID.randomUUID())
.name(new MemberName(name))
.email(new MemberEmail(email))
.password(new MemberPassword(password))
.build();
member.authorities = new Authorities(List.of("user"), member);
return member;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,14 @@
@Slf4j
@RequiredArgsConstructor
public class JwtAuthenticationFilter extends OncePerRequestFilter {
private static final String AUTHORIZATION_HEADER = "Authorization";
private static final List<String> URI = List.of("/login", "/users");
private final JwtConfig jwtConfig;

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
String token = getToken(request.getHeader("Authorization"));
String token = getToken(request.getHeader(AUTHORIZATION_HEADER));
SecretKey key = Keys.hmacShaKeyFor(jwtConfig.getSecret().getBytes(StandardCharsets.UTF_8));
if (token == null || !validToken(token, key)) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
Expand Down Expand Up @@ -86,6 +88,10 @@ private List<GrantedAuthority> getAuthorities(String authorities) {
@Override
protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
//둜그인 μ œμ™Έ λͺ¨λ“  ν•„ν„° 타기
return request.getRequestURI().equals("/login");
return URI.contains(request.getRequestURI())
|| request.getRequestURI().startsWith("/swagger-ui")
|| request.getRequestURI().startsWith("/v3/api-docs")
|| request.getRequestURI().startsWith("/swagger-resources")
|| request.getRequestURI().startsWith("/webjars");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.retrip.auth.infra.adapter.in.rest.in;

import com.retrip.auth.application.in.request.MemberCreateRequest;
import com.retrip.auth.application.in.response.MemberCreateResponse;
import com.retrip.auth.application.in.usercase.ManageMemberUseCase;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/users")
@RequiredArgsConstructor
@Tag(name = "User", description = "νšŒμ› κ΄€λ ¨ API")
public class MemberController {

private final ManageMemberUseCase manageMemberUseCase;

@PostMapping
@Schema(description = "νšŒμ› κ°€μž…")
public MemberCreateResponse createUser(
@RequestBody MemberCreateRequest request
){
return manageMemberUseCase.createUser(request);
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package com.retrip.auth.infra.adapter.in.rest.in;

import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/test")
@RequiredArgsConstructor
@Tag(name = "Test", description = "ν…ŒμŠ€νŠΈ κ΄€λ ¨ API")
public class TestController {
@GetMapping
public String test(Authentication authentication){
Expand Down
7 changes: 0 additions & 7 deletions src/main/java/com/retrip/auth/infra/config/SwaggerConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,4 @@ public OpenAPI springShopOpenAPI() {
.version("v0.0.1")
);
}
@Bean
public GroupedOpenApi authApi(){
return GroupedOpenApi.builder()
.group("auth")
.pathsToMatch("/auth/**")
.build();
}
}
4 changes: 4 additions & 0 deletions src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,7 @@ token:
expire-min: 120
refresh:
expire-min: 1051200 #2λ…„

springdoc:
swagger-ui:
use-root-path: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.retrip.auth.application.in;


import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;

import com.retrip.auth.application.in.request.MemberCreateRequest;
import com.retrip.auth.application.in.response.MemberCreateResponse;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class MemberServiceTest {

@Autowired
private MemberService memberService;

@Test
void νšŒμ›κ°€μž…_성곡() throws Exception {
// given
MemberCreateRequest request = new MemberCreateRequest("test@naver.com", "1234", "test");

//when
MemberCreateResponse response = memberService.createUser(request);

//then
assertThat(response.id()).isNotNull();
assertThat(response.name()).isEqualTo("test");
assertThat(response.email()).isEqualTo("test@naver.com");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.retrip.auth.application.in.factory;

import com.retrip.auth.application.in.MemberService;
import org.junit.jupiter.api.BeforeEach;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class BaseMemberServiceTest {
@Autowired
protected MemberService memberService;



@BeforeEach
void setUp() {
}
}
Loading