From ae2bbd580b8c01ea4a5e36dfc92501a5c41f373c Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Sun, 11 Feb 2024 20:28:45 +0900 Subject: [PATCH 01/56] =?UTF-8?q?chore:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=ED=8C=8C=EC=9D=BC=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: kimnamgyu --- src/main/resources/application.properties | 1 - .../algobaroapi/AlgobaroApiApplicationTests.java | 13 ------------- 2 files changed, 14 deletions(-) delete mode 100644 src/main/resources/application.properties delete mode 100644 src/test/java/e5i/algobaroapi/AlgobaroApiApplicationTests.java diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties deleted file mode 100644 index 8b13789..0000000 --- a/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/test/java/e5i/algobaroapi/AlgobaroApiApplicationTests.java b/src/test/java/e5i/algobaroapi/AlgobaroApiApplicationTests.java deleted file mode 100644 index 635aa46..0000000 --- a/src/test/java/e5i/algobaroapi/AlgobaroApiApplicationTests.java +++ /dev/null @@ -1,13 +0,0 @@ -package e5i.algobaroapi; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class AlgobaroApiApplicationTests { - - @Test - void contextLoads() { - } - -} From ec5fa87d2a0cbc90a938ec6b55864a11d2f6edad Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Sun, 11 Feb 2024 20:31:31 +0900 Subject: [PATCH 02/56] =?UTF-8?q?chore:=20QueryDsl=20/=20Swagger=20/=20Val?= =?UTF-8?q?idation=20=EC=9D=98=EC=A1=B4=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: kimnamgyu --- build.gradle | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 28209dc..f90ea74 100644 --- a/build.gradle +++ b/build.gradle @@ -23,11 +23,30 @@ repositories { dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' - implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-web' + + // Validation + implementation 'org.springframework.boot:spring-boot-starter-validation' + + // Spring Security + implementation 'org.springframework.boot:spring-boot-starter-security' + + // Lombok compileOnly 'org.projectlombok:lombok' - runtimeOnly 'com.mysql:mysql-connector-j' annotationProcessor 'org.projectlombok:lombok' + + // MySQL + runtimeOnly 'com.mysql:mysql-connector-j' + + // QueryDSL + implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta' + annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jakarta" + annotationProcessor "jakarta.annotation:jakarta.annotation-api" + annotationProcessor "jakarta.persistence:jakarta.persistence-api" + + // Swagger + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2' + testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.security:spring-security-test' } From 095cae9eb527304b9d708526a6b5f413bcfc6e33 Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Sun, 11 Feb 2024 20:32:47 +0900 Subject: [PATCH 03/56] =?UTF-8?q?chore:=20=EC=BB=A8=EB=B2=A4=EC=85=98?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EC=9D=B8=ED=95=9C=20=ED=8C=A8=ED=82=A4?= =?UTF-8?q?=EC=A7=80=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: kimnamgyu --- .../java/{e5i => ei}/algobaroapi/AlgobaroApiApplication.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/main/java/{e5i => ei}/algobaroapi/AlgobaroApiApplication.java (92%) diff --git a/src/main/java/e5i/algobaroapi/AlgobaroApiApplication.java b/src/main/java/ei/algobaroapi/AlgobaroApiApplication.java similarity index 92% rename from src/main/java/e5i/algobaroapi/AlgobaroApiApplication.java rename to src/main/java/ei/algobaroapi/AlgobaroApiApplication.java index 7d92d90..39a656f 100644 --- a/src/main/java/e5i/algobaroapi/AlgobaroApiApplication.java +++ b/src/main/java/ei/algobaroapi/AlgobaroApiApplication.java @@ -1,4 +1,4 @@ -package e5i.algobaroapi; +package ei.algobaroapi; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; From 023dd42b0cc7960f6b104bf0105e1f9452665073 Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Sun, 11 Feb 2024 22:01:43 +0900 Subject: [PATCH 04/56] =?UTF-8?q?chore:=20JWT=20=EC=9D=98=EC=A1=B4?= =?UTF-8?q?=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: kimnamgyu --- build.gradle | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/build.gradle b/build.gradle index f90ea74..8a5000d 100644 --- a/build.gradle +++ b/build.gradle @@ -31,6 +31,11 @@ dependencies { // Spring Security implementation 'org.springframework.boot:spring-boot-starter-security' + // JWT + implementation 'io.jsonwebtoken:jjwt-api:0.11.5' + implementation 'io.jsonwebtoken:jjwt-impl:0.11.5' + implementation 'io.jsonwebtoken:jjwt-jackson:0.11.5' + // Lombok compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' From 3d5471b04dba8bfa951e4961d8f4dd5c0847de91 Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Sun, 11 Feb 2024 22:02:02 +0900 Subject: [PATCH 05/56] =?UTF-8?q?feat:=20QueryDsl=20Config=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: kimnamgyu --- .../algobaroapi/global/config/QueryDslConfig.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/main/java/ei/algobaroapi/global/config/QueryDslConfig.java diff --git a/src/main/java/ei/algobaroapi/global/config/QueryDslConfig.java b/src/main/java/ei/algobaroapi/global/config/QueryDslConfig.java new file mode 100644 index 0000000..b09198a --- /dev/null +++ b/src/main/java/ei/algobaroapi/global/config/QueryDslConfig.java @@ -0,0 +1,15 @@ +package ei.algobaroapi.global.config; + +import com.querydsl.jpa.impl.JPAQueryFactory; +import jakarta.persistence.EntityManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class QueryDslConfig { + + @Bean + JPAQueryFactory jpaQueryFactory(EntityManager entityManager) { + return new JPAQueryFactory(entityManager); + } +} From f8894cebddfd75e92180ea87979aa78f6b6f34aa Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Sun, 11 Feb 2024 22:02:07 +0900 Subject: [PATCH 06/56] =?UTF-8?q?feat:=20Swagger=20Config=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: kimnamgyu --- .../global/config/SwaggerConfig.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/main/java/ei/algobaroapi/global/config/SwaggerConfig.java diff --git a/src/main/java/ei/algobaroapi/global/config/SwaggerConfig.java b/src/main/java/ei/algobaroapi/global/config/SwaggerConfig.java new file mode 100644 index 0000000..350da93 --- /dev/null +++ b/src/main/java/ei/algobaroapi/global/config/SwaggerConfig.java @@ -0,0 +1,38 @@ +package ei.algobaroapi.global.config; + +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.security.SecurityRequirement; +import io.swagger.v3.oas.models.security.SecurityScheme; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class SwaggerConfig { + + @Bean + public OpenAPI openAPI(@Value("${springdoc.version}") String springdocVersion) { + Info info = new Info() + .title("AlgoBaro API Document") + .version(springdocVersion) + .description("Algobaro API 명세서"); + + String jwtScheme = "jwtAuth"; + SecurityRequirement securityRequirement = new SecurityRequirement().addList(jwtScheme); + Components components = new Components() + .addSecuritySchemes(jwtScheme, new SecurityScheme() + .name("Authorization") + .type(SecurityScheme.Type.HTTP) + .in(SecurityScheme.In.HEADER) + .scheme("Bearer") + .bearerFormat("JWT")); + + return new OpenAPI() + .components(new Components()) + .info(info) + .addSecurityItem(securityRequirement) + .components(components); + } +} From 23d569161e31e2632e827993bfb8e6745247ba1c Mon Sep 17 00:00:00 2001 From: kimnamgyu Date: Sun, 11 Feb 2024 22:53:13 +0900 Subject: [PATCH 07/56] =?UTF-8?q?feat:=20Security=20Config=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/config/WebSecurityConfig.java | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/main/java/ei/algobaroapi/global/config/WebSecurityConfig.java diff --git a/src/main/java/ei/algobaroapi/global/config/WebSecurityConfig.java b/src/main/java/ei/algobaroapi/global/config/WebSecurityConfig.java new file mode 100644 index 0000000..e9cfcaf --- /dev/null +++ b/src/main/java/ei/algobaroapi/global/config/WebSecurityConfig.java @@ -0,0 +1,70 @@ +package ei.algobaroapi.global.config; + +import ei.algobaroapi.global.jwt.JwtAuthenticationFilter; +import ei.algobaroapi.global.jwt.JwtProvider; +import java.util.List; +import lombok.AccessLevel; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.CorsConfigurationSource; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; + +@Configuration +@RequiredArgsConstructor(access = AccessLevel.PROTECTED) +public class WebSecurityConfig { + + private final JwtProvider jwtTokenProvider; + + @Value("${server.port}") + private String serverPort; + + @Bean + public CorsConfigurationSource corsConfigurationSource() { + CorsConfiguration config = new CorsConfiguration(); + + config.setAllowCredentials(true); + config.setAllowedOrigins(List.of("http://localhost:" + serverPort)); // 포트번호 + config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS")); + config.setAllowedHeaders(List.of("*")); + config.setExposedHeaders(List.of("*")); + + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", config); + return source; + } + + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http + .cors(httpSecurityCorsConfigurer -> httpSecurityCorsConfigurer.configurationSource( + corsConfigurationSource())) + + // csrf + .csrf(AbstractHttpConfigurer::disable) + + // 기존 세션 로그인 방식 제외 + .sessionManagement((manage) -> + manage.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) + + // api 별 권한 처리 + .authorizeHttpRequests((authorize) -> authorize + .requestMatchers("/api/v1/users/join").permitAll() + .requestMatchers("/api/v1/users/login").permitAll() + .requestMatchers("/api/v1/users/test").hasRole("USER") + .anyRequest().permitAll()) + + // JWT 권한 필터 적용 + .addFilterBefore(new JwtAuthenticationFilter(jwtTokenProvider), + UsernamePasswordAuthenticationFilter.class) + ; + return http.build(); + } +} From f86f1077078dcd2452ff2b416e422df42f336f5b Mon Sep 17 00:00:00 2001 From: kimnamgyu Date: Sun, 11 Feb 2024 22:56:41 +0900 Subject: [PATCH 08/56] =?UTF-8?q?feat:=20AccessToken=20=EC=83=9D=EC=84=B1/?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=ED=95=98=EB=8A=94=20JwtProvider=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../algobaroapi/global/jwt/JwtProvider.java | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 src/main/java/ei/algobaroapi/global/jwt/JwtProvider.java diff --git a/src/main/java/ei/algobaroapi/global/jwt/JwtProvider.java b/src/main/java/ei/algobaroapi/global/jwt/JwtProvider.java new file mode 100644 index 0000000..64cdea5 --- /dev/null +++ b/src/main/java/ei/algobaroapi/global/jwt/JwtProvider.java @@ -0,0 +1,83 @@ +package ei.algobaroapi.global.jwt; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.ExpiredJwtException; +import io.jsonwebtoken.Jws; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.MalformedJwtException; +import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.UnsupportedJwtException; +import io.jsonwebtoken.security.Keys; +import java.nio.charset.StandardCharsets; +import java.security.Key; +import java.util.Date; +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.stereotype.Component; + +@Slf4j +@Component +public class JwtProvider { + + private static final long TOKEN_VALID_TIME = 30 * 60 * 1000L; // 토큰 유효시간 30분 + private final Key secretKey; + private final UserDetailsService userDetailsService; + + public JwtProvider(@Value("${JWT_KEY}") String secretKey, + UserDetailsService userDetailsService) { + this.secretKey = Keys.hmacShaKeyFor(secretKey.getBytes(StandardCharsets.UTF_8)); + this.userDetailsService = userDetailsService; + } + + // 사용자 정보 기반 JWT 토큰 생성 + public String generateToken(String userId, List roles) { + Claims claims = Jwts.claims().setSubject(userId); + claims.put("roles", roles); + + Date now = new Date(); + + return Jwts.builder() + .setClaims(claims) + .setIssuedAt(now) + .setExpiration(new Date(now.getTime() + TOKEN_VALID_TIME)) + .signWith(secretKey, SignatureAlgorithm.HS256) + .compact(); + } + + public Authentication getAuthentication(String accessToken) { + UserDetails userDetails = userDetailsService.loadUserByUsername( + this.getUserId(accessToken)); + return new UsernamePasswordAuthenticationToken(userDetails, "", + userDetails.getAuthorities()); + } + + // 토큰 유효성 검사 + public boolean validateToken(String token) { + try { + Jws claims = Jwts.parserBuilder() + .setSigningKey(secretKey) + .build() + .parseClaimsJws(token); + return !claims.getBody().getExpiration().before(new Date()); + } catch (SecurityException | MalformedJwtException e) { + log.info("Invalid JWT Token", e); + } catch (ExpiredJwtException e) { + log.info("Expired JWT Token", e); + } catch (UnsupportedJwtException e) { + log.info("Unsupported JWT Token", e); + } catch (IllegalArgumentException e) { + log.info("JWT claims string is empty.", e); + } + return false; + } + + // 토큰에서 userId 값 반환 + private String getUserId(String token) { + return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody().getSubject(); + } +} From c8f0f498f595751a595881dd4fe1d798f789fe9c Mon Sep 17 00:00:00 2001 From: kimnamgyu Date: Sun, 11 Feb 2024 22:57:09 +0900 Subject: [PATCH 09/56] =?UTF-8?q?feat:=20JwtAuthenticationFilter=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/jwt/JwtAuthenticationFilter.java | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 src/main/java/ei/algobaroapi/global/jwt/JwtAuthenticationFilter.java diff --git a/src/main/java/ei/algobaroapi/global/jwt/JwtAuthenticationFilter.java b/src/main/java/ei/algobaroapi/global/jwt/JwtAuthenticationFilter.java new file mode 100644 index 0000000..d6475c1 --- /dev/null +++ b/src/main/java/ei/algobaroapi/global/jwt/JwtAuthenticationFilter.java @@ -0,0 +1,42 @@ +package ei.algobaroapi.global.jwt; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.util.StringUtils; +import org.springframework.web.filter.GenericFilterBean; + +import java.io.IOException; + +@RequiredArgsConstructor +public class JwtAuthenticationFilter extends GenericFilterBean { + + private static final String AUTHORIZATION_HEADER = "Authorization"; + private static final String TOKEN_PREFIX = "Bearer"; + private final JwtProvider jwtTokenProvider; + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + String token = resolveToken((HttpServletRequest) request); + + if(token != null && jwtTokenProvider.validateToken(token)) { + Authentication authentication = jwtTokenProvider.getAuthentication(token); + SecurityContextHolder.getContext().setAuthentication(authentication); + } + + chain.doFilter(request, response); + } + + private String resolveToken(HttpServletRequest request) { + String bearerToken = request.getHeader(AUTHORIZATION_HEADER); + if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(TOKEN_PREFIX)) { + return bearerToken.substring(7); + } + return null; + } +} From a34ef826be8b02dc6459fb1702dbb26e4352869d Mon Sep 17 00:00:00 2001 From: kimnamgyu Date: Sun, 11 Feb 2024 23:01:24 +0900 Subject: [PATCH 10/56] =?UTF-8?q?refactor:=20sonarLint=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/ei/algobaroapi/global/config/WebSecurityConfig.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/ei/algobaroapi/global/config/WebSecurityConfig.java b/src/main/java/ei/algobaroapi/global/config/WebSecurityConfig.java index e9cfcaf..24537b6 100644 --- a/src/main/java/ei/algobaroapi/global/config/WebSecurityConfig.java +++ b/src/main/java/ei/algobaroapi/global/config/WebSecurityConfig.java @@ -51,11 +51,11 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti .csrf(AbstractHttpConfigurer::disable) // 기존 세션 로그인 방식 제외 - .sessionManagement((manage) -> + .sessionManagement(manage -> manage.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) // api 별 권한 처리 - .authorizeHttpRequests((authorize) -> authorize + .authorizeHttpRequests(authorize -> authorize .requestMatchers("/api/v1/users/join").permitAll() .requestMatchers("/api/v1/users/login").permitAll() .requestMatchers("/api/v1/users/test").hasRole("USER") From 8ad9ebddb061e52ddbc6f3474d23488c14b468b3 Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Mon, 12 Feb 2024 00:59:58 +0900 Subject: [PATCH 11/56] =?UTF-8?q?feat:=20BaseEntity=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: kimnamgyu --- .../algobaroapi/global/entity/BaseEntity.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 src/main/java/ei/algobaroapi/global/entity/BaseEntity.java diff --git a/src/main/java/ei/algobaroapi/global/entity/BaseEntity.java b/src/main/java/ei/algobaroapi/global/entity/BaseEntity.java new file mode 100644 index 0000000..0b22c84 --- /dev/null +++ b/src/main/java/ei/algobaroapi/global/entity/BaseEntity.java @@ -0,0 +1,32 @@ +package ei.algobaroapi.global.entity; + +import jakarta.persistence.Column; +import jakarta.persistence.MappedSuperclass; +import lombok.Getter; +import org.springframework.data.annotation.CreatedDate; + +import java.time.LocalDateTime; + +@Getter +@MappedSuperclass +public abstract class BaseEntity { + + @CreatedDate + @Column(name = "created_at", columnDefinition = "datetime", updatable = false) + private LocalDateTime createdAt; + + @Column(name = "updated_at", columnDefinition = "datetime") + private LocalDateTime updatedAt; + + @Column(name = "deleted_at", columnDefinition = "datetime") + private LocalDateTime deletedAt; + + public boolean isDeleted() { + return this.deletedAt != null; + } + + protected void delete() { + if (isDeleted()) throw new IllegalArgumentException("이미 삭제된 엔티티 입니다."); + this.deletedAt = LocalDateTime.now(); + } +} From 726cb306517cd3231682f47007097254459f2d27 Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Mon, 12 Feb 2024 01:00:51 +0900 Subject: [PATCH 12/56] =?UTF-8?q?feat:=20Email=20=EA=B2=80=EC=A6=9D=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=EC=9D=84=20=EC=9C=84=ED=95=9C=20Email=20VO?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: kimnamgyu --- .../domain/member/domain/vo/EmailVo.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/main/java/ei/algobaroapi/domain/member/domain/vo/EmailVo.java diff --git a/src/main/java/ei/algobaroapi/domain/member/domain/vo/EmailVo.java b/src/main/java/ei/algobaroapi/domain/member/domain/vo/EmailVo.java new file mode 100644 index 0000000..8688913 --- /dev/null +++ b/src/main/java/ei/algobaroapi/domain/member/domain/vo/EmailVo.java @@ -0,0 +1,28 @@ +package ei.algobaroapi.domain.member.domain.vo; + +import jakarta.persistence.Column; +import jakarta.persistence.Embeddable; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Embeddable +@NoArgsConstructor(access = lombok.AccessLevel.PROTECTED) +public class EmailVo { + + private static final String EMAIL_REGEX = "^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$"; + + @Column(name = "email", nullable = false) + private String email; + + public EmailVo(String email) { + if (!isValidEmail(email)) { + throw new IllegalArgumentException("Invalid email"); + } + this.email = email; + } + + private boolean isValidEmail(String email) { + return email.matches(EMAIL_REGEX); + } +} From 0a880f2dd90a5ff69da5408540fc5c465178125d Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Mon, 12 Feb 2024 01:01:07 +0900 Subject: [PATCH 13/56] =?UTF-8?q?feat:=20=ED=95=84=EC=88=98=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=EB=A7=8C=20=ED=8F=AC=ED=95=A8=ED=95=9C=20Member=20Ent?= =?UTF-8?q?ity=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: kimnamgyu --- .../domain/member/domain/Member.java | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 src/main/java/ei/algobaroapi/domain/member/domain/Member.java diff --git a/src/main/java/ei/algobaroapi/domain/member/domain/Member.java b/src/main/java/ei/algobaroapi/domain/member/domain/Member.java new file mode 100644 index 0000000..76f4293 --- /dev/null +++ b/src/main/java/ei/algobaroapi/domain/member/domain/Member.java @@ -0,0 +1,74 @@ +package ei.algobaroapi.domain.member.domain; + +import ei.algobaroapi.domain.member.domain.vo.EmailVo; +import ei.algobaroapi.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +@Getter +@Entity +@Table(name = "members") +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class Member extends BaseEntity implements UserDetails { + + @ElementCollection(fetch = FetchType.LAZY) + private final List roles = new ArrayList<>(); + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Embedded + private EmailVo email; + + @Column(name = "password", nullable = false) + private String password; + + @Builder + public Member(String email, String password) { + this.email = new EmailVo(email); + this.password = password; + } + + @Override + public Collection getAuthorities() { + return this.roles.stream() + .map(SimpleGrantedAuthority::new) + .toList(); + } + + @Override + public String getUsername() { + return this.email.getEmail(); + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return true; + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return true; + } +} From 6ae8ba983ef87f511400aa4a243b99c0be628473 Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Mon, 12 Feb 2024 01:01:35 +0900 Subject: [PATCH 14/56] =?UTF-8?q?feat:=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85/=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EC=9D=84=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20Request=20DTO=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: kimnamgyu --- .../member/dto/MemberCreateRequest.java | 20 +++++++++++++++++++ .../member/dto/MemberSignInRequest.java | 10 ++++++++++ 2 files changed, 30 insertions(+) create mode 100644 src/main/java/ei/algobaroapi/domain/member/dto/MemberCreateRequest.java create mode 100644 src/main/java/ei/algobaroapi/domain/member/dto/MemberSignInRequest.java diff --git a/src/main/java/ei/algobaroapi/domain/member/dto/MemberCreateRequest.java b/src/main/java/ei/algobaroapi/domain/member/dto/MemberCreateRequest.java new file mode 100644 index 0000000..ed95fa4 --- /dev/null +++ b/src/main/java/ei/algobaroapi/domain/member/dto/MemberCreateRequest.java @@ -0,0 +1,20 @@ +package ei.algobaroapi.domain.member.dto; + +import ei.algobaroapi.domain.member.domain.Member; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class MemberCreateRequest { + + private String email; + private String password; + + public Member toEntity(String encryptPassword) { + return Member.builder() + .email(this.email) + .password(encryptPassword) + .build(); + } +} diff --git a/src/main/java/ei/algobaroapi/domain/member/dto/MemberSignInRequest.java b/src/main/java/ei/algobaroapi/domain/member/dto/MemberSignInRequest.java new file mode 100644 index 0000000..cb5fd69 --- /dev/null +++ b/src/main/java/ei/algobaroapi/domain/member/dto/MemberSignInRequest.java @@ -0,0 +1,10 @@ +package ei.algobaroapi.domain.member.dto; + +import lombok.Getter; + +@Getter +public class MemberSignInRequest { + + private String email; + private String password; +} From 9c2cebfe824f263dad1675ada7e161f0e48088a6 Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Mon, 12 Feb 2024 01:02:37 +0900 Subject: [PATCH 15/56] =?UTF-8?q?feat:=20Password=20Encoder=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=EC=9D=84=20=EC=9C=84=ED=95=B4=20Bean=20=EC=A3=BC?= =?UTF-8?q?=EC=9E=85=20Configuration=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: kimnamgyu --- .../global/config/PasswordEncoderConfig.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/main/java/ei/algobaroapi/global/config/PasswordEncoderConfig.java diff --git a/src/main/java/ei/algobaroapi/global/config/PasswordEncoderConfig.java b/src/main/java/ei/algobaroapi/global/config/PasswordEncoderConfig.java new file mode 100644 index 0000000..f68eff4 --- /dev/null +++ b/src/main/java/ei/algobaroapi/global/config/PasswordEncoderConfig.java @@ -0,0 +1,15 @@ +package ei.algobaroapi.global.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +@Configuration +public class PasswordEncoderConfig { + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } +} From 03c6d8b3e4679578141b1b7ce14e2fd415bef3c0 Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Mon, 12 Feb 2024 01:03:13 +0900 Subject: [PATCH 16/56] =?UTF-8?q?feat:=20Member=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=EC=8B=9C=20=ED=8C=A8=EC=8A=A4=EC=9B=8C=EB=93=9C=20=EC=A0=95?= =?UTF-8?q?=EC=B1=85=20=EA=B2=80=EC=A6=9D=20=EB=B0=8F=20=EC=9D=B8=EC=BD=94?= =?UTF-8?q?=EB=93=9C=EB=A5=BC=20=EC=9C=84=ED=95=9C=20Util=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: kimnamgyu --- .../domain/member/util/PasswordUtil.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 src/main/java/ei/algobaroapi/domain/member/util/PasswordUtil.java diff --git a/src/main/java/ei/algobaroapi/domain/member/util/PasswordUtil.java b/src/main/java/ei/algobaroapi/domain/member/util/PasswordUtil.java new file mode 100644 index 0000000..47e73bf --- /dev/null +++ b/src/main/java/ei/algobaroapi/domain/member/util/PasswordUtil.java @@ -0,0 +1,32 @@ +package ei.algobaroapi.domain.member.util; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Component; + +@Getter +@Component +@RequiredArgsConstructor +public class PasswordUtil { + + private static final int PASSWORD_LENGTH = 8; + private static final String SPECIAL_CHARACTERS_REGEX = ".*[!@#$%^&*()].*"; + + private final PasswordEncoder passwordEncoder; + + public String validateAndEncryptPassword(String rawPassword) { + if (!isValidPassword(rawPassword)) { + throw new IllegalArgumentException("Invalid password"); + } + return passwordEncoder.encode(rawPassword); + } + + private boolean isValidPassword(String password) { + return password.length() >= PASSWORD_LENGTH && password.matches(SPECIAL_CHARACTERS_REGEX); + } + + public boolean isPasswordMatch(String rawPassword, String encodedPassword) { + return passwordEncoder.matches(rawPassword, encodedPassword); + } +} From d86b44ad239fe88b763e9c9185489ed76127308f Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Mon, 12 Feb 2024 01:05:40 +0900 Subject: [PATCH 17/56] =?UTF-8?q?chore:=20=ED=9A=8C=EC=9B=90=20=EA=B0=80?= =?UTF-8?q?=EC=9E=85=20DTO=20=ED=81=B4=EB=9E=98=EC=8A=A4=EB=AA=85=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: kimnamgyu --- .../dto/{MemberCreateRequest.java => MemberSignUpRequest.java} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/main/java/ei/algobaroapi/domain/member/dto/{MemberCreateRequest.java => MemberSignUpRequest.java} (92%) diff --git a/src/main/java/ei/algobaroapi/domain/member/dto/MemberCreateRequest.java b/src/main/java/ei/algobaroapi/domain/member/dto/MemberSignUpRequest.java similarity index 92% rename from src/main/java/ei/algobaroapi/domain/member/dto/MemberCreateRequest.java rename to src/main/java/ei/algobaroapi/domain/member/dto/MemberSignUpRequest.java index ed95fa4..32f4c19 100644 --- a/src/main/java/ei/algobaroapi/domain/member/dto/MemberCreateRequest.java +++ b/src/main/java/ei/algobaroapi/domain/member/dto/MemberSignUpRequest.java @@ -6,7 +6,7 @@ @Getter @Builder -public class MemberCreateRequest { +public class MemberSignUpRequest { private String email; private String password; From 57a7e46b59c69a213773fa253d01696f777adb7a Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Mon, 12 Feb 2024 01:06:21 +0900 Subject: [PATCH 18/56] =?UTF-8?q?feat:=20Member=20Sign=20Up=20/=20Sign=20I?= =?UTF-8?q?n=20=EA=B8=B0=EB=8A=A5=20=EA=B0=9C=EB=B0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 토큰 정책 협의 필요로 인하여 최소한의 로직만 작성 Co-authored-by: kimnamgyu --- .../member/controller/MemberController.java | 28 +++++++++++++ .../member/domain/MemberRepository.java | 15 +++++++ .../domain/member/service/MemberService.java | 39 +++++++++++++++++++ 3 files changed, 82 insertions(+) create mode 100644 src/main/java/ei/algobaroapi/domain/member/controller/MemberController.java create mode 100644 src/main/java/ei/algobaroapi/domain/member/domain/MemberRepository.java create mode 100644 src/main/java/ei/algobaroapi/domain/member/service/MemberService.java diff --git a/src/main/java/ei/algobaroapi/domain/member/controller/MemberController.java b/src/main/java/ei/algobaroapi/domain/member/controller/MemberController.java new file mode 100644 index 0000000..466301e --- /dev/null +++ b/src/main/java/ei/algobaroapi/domain/member/controller/MemberController.java @@ -0,0 +1,28 @@ +package ei.algobaroapi.domain.member.controller; + +import ei.algobaroapi.domain.member.dto.MemberSignUpRequest; +import ei.algobaroapi.domain.member.dto.MemberSignInRequest; +import ei.algobaroapi.domain.member.service.MemberService; +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 +@RequiredArgsConstructor +@RequestMapping("/api/v1") +public class MemberController { + + private final MemberService memberService; + + @PostMapping("/members/sign-up") + public void signUp(@RequestBody MemberSignUpRequest request) { + this.memberService.signUp(request); + } + + @PostMapping("/members/sign-in") + public String signIn(@RequestBody MemberSignInRequest request) { + return this.memberService.signIn(request); + } +} diff --git a/src/main/java/ei/algobaroapi/domain/member/domain/MemberRepository.java b/src/main/java/ei/algobaroapi/domain/member/domain/MemberRepository.java new file mode 100644 index 0000000..156b8f7 --- /dev/null +++ b/src/main/java/ei/algobaroapi/domain/member/domain/MemberRepository.java @@ -0,0 +1,15 @@ +package ei.algobaroapi.domain.member.domain; + +import ei.algobaroapi.domain.member.domain.vo.EmailVo; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface MemberRepository extends JpaRepository { + + @Query("SELECT m FROM Member m WHERE m.email = :email AND m.deletedAt IS NULL") + Optional findByEmailAndDeletedAtIsNull(EmailVo email); +} diff --git a/src/main/java/ei/algobaroapi/domain/member/service/MemberService.java b/src/main/java/ei/algobaroapi/domain/member/service/MemberService.java new file mode 100644 index 0000000..8817bcf --- /dev/null +++ b/src/main/java/ei/algobaroapi/domain/member/service/MemberService.java @@ -0,0 +1,39 @@ +package ei.algobaroapi.domain.member.service; + +import ei.algobaroapi.domain.member.domain.Member; +import ei.algobaroapi.domain.member.domain.MemberRepository; +import ei.algobaroapi.domain.member.domain.vo.EmailVo; +import ei.algobaroapi.domain.member.dto.MemberSignUpRequest; +import ei.algobaroapi.domain.member.dto.MemberSignInRequest; +import ei.algobaroapi.domain.member.util.PasswordUtil; +import ei.algobaroapi.global.jwt.JwtProvider; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional(readOnly = true) +@RequiredArgsConstructor +public class MemberService { + + private final MemberRepository memberRepository; + private final JwtProvider jwtProvider; + private final PasswordUtil passwordUtil; + + @Transactional + public void signUp(MemberSignUpRequest request) { + String encryptPassword = passwordUtil.validateAndEncryptPassword(request.getPassword()); + memberRepository.save(request.toEntity(encryptPassword)); + } + + @Transactional + public String signIn(MemberSignInRequest request) { + Member user = memberRepository.findByEmailAndDeletedAtIsNull(new EmailVo(request.getEmail())) + .orElseThrow(() -> new IllegalArgumentException("Email not found")); + if (!passwordUtil.isPasswordMatch(request.getPassword(), user.getPassword())) { + throw new IllegalArgumentException("Password mismatch"); + } + + return jwtProvider.generateToken(user.getUsername(), user.getRoles()); + } +} From 250c1c559d3036cd22870ab93c5b024bdcee27e6 Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Tue, 13 Feb 2024 10:37:01 +0900 Subject: [PATCH 19/56] =?UTF-8?q?fix:=20UserDetailService=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=EC=B2=B4=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/jwt/UserDetailServiceImpl.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/main/java/ei/algobaroapi/global/jwt/UserDetailServiceImpl.java diff --git a/src/main/java/ei/algobaroapi/global/jwt/UserDetailServiceImpl.java b/src/main/java/ei/algobaroapi/global/jwt/UserDetailServiceImpl.java new file mode 100644 index 0000000..c164aa4 --- /dev/null +++ b/src/main/java/ei/algobaroapi/global/jwt/UserDetailServiceImpl.java @@ -0,0 +1,22 @@ +package ei.algobaroapi.global.jwt; + +import ei.algobaroapi.domain.member.domain.MemberRepository; +import ei.algobaroapi.domain.member.domain.vo.EmailVo; +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.Component; + +@Component +@RequiredArgsConstructor +public class UserDetailServiceImpl implements UserDetailsService { + + private final MemberRepository memberRepository; + + @Override + public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException { + return memberRepository.findByEmailAndDeletedAtIsNull(new EmailVo(email)) + .orElseThrow(() -> new UsernameNotFoundException("User not found with email: " + email)); + } +} From fd5b0246aafd9f73faa07ed812ed7b982d0eb9ef Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Tue, 13 Feb 2024 10:38:13 +0900 Subject: [PATCH 20/56] =?UTF-8?q?fix:=20Member=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=EC=8B=9C=20roles=20=EC=A0=95=EB=B3=B4=EB=8F=84=20=EA=B0=80?= =?UTF-8?q?=EC=A0=B8=EC=98=A4=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ei/algobaroapi/domain/member/domain/MemberRepository.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/ei/algobaroapi/domain/member/domain/MemberRepository.java b/src/main/java/ei/algobaroapi/domain/member/domain/MemberRepository.java index 156b8f7..a18de0b 100644 --- a/src/main/java/ei/algobaroapi/domain/member/domain/MemberRepository.java +++ b/src/main/java/ei/algobaroapi/domain/member/domain/MemberRepository.java @@ -10,6 +10,6 @@ @Repository public interface MemberRepository extends JpaRepository { - @Query("SELECT m FROM Member m WHERE m.email = :email AND m.deletedAt IS NULL") + @Query("SELECT m FROM Member m LEFT JOIN FETCH m.roles WHERE m.email = :email AND m.deletedAt IS NULL") Optional findByEmailAndDeletedAtIsNull(EmailVo email); } From 533dbd607889a413f7856eba61cbcc76c973cc91 Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Tue, 13 Feb 2024 11:05:49 +0900 Subject: [PATCH 21/56] chore: reformat code --- .../java/ei/algobaroapi/global/jwt/JwtAuthenticationFilter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/ei/algobaroapi/global/jwt/JwtAuthenticationFilter.java b/src/main/java/ei/algobaroapi/global/jwt/JwtAuthenticationFilter.java index d6475c1..7f83d9c 100644 --- a/src/main/java/ei/algobaroapi/global/jwt/JwtAuthenticationFilter.java +++ b/src/main/java/ei/algobaroapi/global/jwt/JwtAuthenticationFilter.java @@ -24,7 +24,7 @@ public class JwtAuthenticationFilter extends GenericFilterBean { public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { String token = resolveToken((HttpServletRequest) request); - if(token != null && jwtTokenProvider.validateToken(token)) { + if (token != null && jwtTokenProvider.validateToken(token)) { Authentication authentication = jwtTokenProvider.getAuthentication(token); SecurityContextHolder.getContext().setAuthentication(authentication); } From fb3d0994b7a369efaf11f9ee50c84c5dac6b71e1 Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Tue, 13 Feb 2024 11:07:08 +0900 Subject: [PATCH 22/56] =?UTF-8?q?refactor:=20roles=20final=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0=20=EB=B0=8F=20=EC=83=9D=EC=84=B1=20=EC=8B=9C=20ROLE?= =?UTF-8?q?=5FUSER=20=EA=B6=8C=ED=95=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/ei/algobaroapi/domain/member/domain/Member.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/ei/algobaroapi/domain/member/domain/Member.java b/src/main/java/ei/algobaroapi/domain/member/domain/Member.java index 76f4293..2da07ab 100644 --- a/src/main/java/ei/algobaroapi/domain/member/domain/Member.java +++ b/src/main/java/ei/algobaroapi/domain/member/domain/Member.java @@ -11,7 +11,6 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; -import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -21,9 +20,6 @@ @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Member extends BaseEntity implements UserDetails { - @ElementCollection(fetch = FetchType.LAZY) - private final List roles = new ArrayList<>(); - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @@ -34,10 +30,14 @@ public class Member extends BaseEntity implements UserDetails { @Column(name = "password", nullable = false) private String password; + @ElementCollection(fetch = FetchType.LAZY) + private List roles; + @Builder public Member(String email, String password) { this.email = new EmailVo(email); this.password = password; + roles = List.of("ROLE_USER"); } @Override From 744eec893fe7535469c70e1ca84f82faa2f63f8c Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Tue, 13 Feb 2024 11:09:26 +0900 Subject: [PATCH 23/56] =?UTF-8?q?feat:=20=EA=B6=8C=ED=95=9C=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20Controller=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/member/controller/MemberController.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/main/java/ei/algobaroapi/domain/member/controller/MemberController.java b/src/main/java/ei/algobaroapi/domain/member/controller/MemberController.java index 466301e..f048be7 100644 --- a/src/main/java/ei/algobaroapi/domain/member/controller/MemberController.java +++ b/src/main/java/ei/algobaroapi/domain/member/controller/MemberController.java @@ -1,13 +1,12 @@ package ei.algobaroapi.domain.member.controller; +import ei.algobaroapi.domain.member.domain.Member; import ei.algobaroapi.domain.member.dto.MemberSignUpRequest; import ei.algobaroapi.domain.member.dto.MemberSignInRequest; import ei.algobaroapi.domain.member.service.MemberService; 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; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.*; @RestController @RequiredArgsConstructor @@ -25,4 +24,10 @@ public void signUp(@RequestBody MemberSignUpRequest request) { public String signIn(@RequestBody MemberSignInRequest request) { return this.memberService.signIn(request); } + + @GetMapping("/members/test") + public String hello(@AuthenticationPrincipal Member member) { + System.out.println(member.getEmail().getEmail()); + return "Hello, World!"; + } } From d75000d2fbb6cbdca149e4d796ecf6a148376ebb Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Tue, 13 Feb 2024 11:09:39 +0900 Subject: [PATCH 24/56] =?UTF-8?q?fix:=20requestMatchers=20=EC=98=AC?= =?UTF-8?q?=EB=B0=94=EB=A5=B8=20URL=20=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ei/algobaroapi/global/config/WebSecurityConfig.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/ei/algobaroapi/global/config/WebSecurityConfig.java b/src/main/java/ei/algobaroapi/global/config/WebSecurityConfig.java index 24537b6..5befbf6 100644 --- a/src/main/java/ei/algobaroapi/global/config/WebSecurityConfig.java +++ b/src/main/java/ei/algobaroapi/global/config/WebSecurityConfig.java @@ -56,9 +56,9 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti // api 별 권한 처리 .authorizeHttpRequests(authorize -> authorize - .requestMatchers("/api/v1/users/join").permitAll() - .requestMatchers("/api/v1/users/login").permitAll() - .requestMatchers("/api/v1/users/test").hasRole("USER") + .requestMatchers("/api/v1/members/sign-up").permitAll() + .requestMatchers("/api/v1/members/sign-in").permitAll() + .requestMatchers("/api/v1/members/test").hasRole("USER") .anyRequest().permitAll()) // JWT 권한 필터 적용 From 183d2c5e652c8ea0b06d8d1d3fdf2f86a9f8ff7f Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Tue, 13 Feb 2024 11:34:30 +0900 Subject: [PATCH 25/56] =?UTF-8?q?docs:=20Swagger=20Docs=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=EC=9D=84=20=EC=9C=84=ED=95=9C=20interface=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/controller/MemberController.java | 6 ++++- .../swaggerdoc/MemberControllerDoc.java | 23 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 src/main/java/ei/algobaroapi/global/config/swaggerdoc/MemberControllerDoc.java diff --git a/src/main/java/ei/algobaroapi/domain/member/controller/MemberController.java b/src/main/java/ei/algobaroapi/domain/member/controller/MemberController.java index f048be7..2a7c564 100644 --- a/src/main/java/ei/algobaroapi/domain/member/controller/MemberController.java +++ b/src/main/java/ei/algobaroapi/domain/member/controller/MemberController.java @@ -4,6 +4,7 @@ import ei.algobaroapi.domain.member.dto.MemberSignUpRequest; import ei.algobaroapi.domain.member.dto.MemberSignInRequest; import ei.algobaroapi.domain.member.service.MemberService; +import ei.algobaroapi.global.config.swaggerdoc.MemberControllerDoc; import lombok.RequiredArgsConstructor; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.*; @@ -11,20 +12,23 @@ @RestController @RequiredArgsConstructor @RequestMapping("/api/v1") -public class MemberController { +public class MemberController implements MemberControllerDoc { private final MemberService memberService; + @Override @PostMapping("/members/sign-up") public void signUp(@RequestBody MemberSignUpRequest request) { this.memberService.signUp(request); } + @Override @PostMapping("/members/sign-in") public String signIn(@RequestBody MemberSignInRequest request) { return this.memberService.signIn(request); } + @Override @GetMapping("/members/test") public String hello(@AuthenticationPrincipal Member member) { System.out.println(member.getEmail().getEmail()); diff --git a/src/main/java/ei/algobaroapi/global/config/swaggerdoc/MemberControllerDoc.java b/src/main/java/ei/algobaroapi/global/config/swaggerdoc/MemberControllerDoc.java new file mode 100644 index 0000000..93a0714 --- /dev/null +++ b/src/main/java/ei/algobaroapi/global/config/swaggerdoc/MemberControllerDoc.java @@ -0,0 +1,23 @@ +package ei.algobaroapi.global.config.swaggerdoc; + +import ei.algobaroapi.domain.member.domain.Member; +import ei.algobaroapi.domain.member.dto.MemberSignInRequest; +import ei.algobaroapi.domain.member.dto.MemberSignUpRequest; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.RequestBody; + +@Tag(name = "Member", description = "회원 도메인 API") +@SuppressWarnings("unused") +public interface MemberControllerDoc { + + @Operation(summary = "회원 가입", description = "회원가입을 합니다.") + void signUp(@RequestBody MemberSignUpRequest request); + + @Operation(summary = "로그인", description = "이메일, 비밀번호로 로그인을 합니다.") + String signIn(@RequestBody MemberSignInRequest request); + + @Operation(summary = "테스트", description = "테스트용 API") + String hello(@AuthenticationPrincipal Member member); +} From 1d948a3fface1c9a7696d9a9f0fecff006f20492 Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Tue, 13 Feb 2024 11:39:53 +0900 Subject: [PATCH 26/56] =?UTF-8?q?mod:=20=EC=9D=B8=EC=A6=9D=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EA=B8=B0=EB=8A=A5=20Member*=20->=20Auth*=20prefix?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: kimnamgyu --- ...mberController.java => AuthController.java} | 18 +++++++++--------- .../{MemberService.java => AuthService.java} | 2 +- ...ntrollerDoc.java => AuthControllerDoc.java} | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) rename src/main/java/ei/algobaroapi/domain/member/controller/{MemberController.java => AuthController.java} (65%) rename src/main/java/ei/algobaroapi/domain/member/service/{MemberService.java => AuthService.java} (98%) rename src/main/java/ei/algobaroapi/global/config/swaggerdoc/{MemberControllerDoc.java => AuthControllerDoc.java} (90%) diff --git a/src/main/java/ei/algobaroapi/domain/member/controller/MemberController.java b/src/main/java/ei/algobaroapi/domain/member/controller/AuthController.java similarity index 65% rename from src/main/java/ei/algobaroapi/domain/member/controller/MemberController.java rename to src/main/java/ei/algobaroapi/domain/member/controller/AuthController.java index 2a7c564..921e0be 100644 --- a/src/main/java/ei/algobaroapi/domain/member/controller/MemberController.java +++ b/src/main/java/ei/algobaroapi/domain/member/controller/AuthController.java @@ -3,8 +3,8 @@ import ei.algobaroapi.domain.member.domain.Member; import ei.algobaroapi.domain.member.dto.MemberSignUpRequest; import ei.algobaroapi.domain.member.dto.MemberSignInRequest; -import ei.algobaroapi.domain.member.service.MemberService; -import ei.algobaroapi.global.config.swaggerdoc.MemberControllerDoc; +import ei.algobaroapi.domain.member.service.AuthService; +import ei.algobaroapi.global.config.swaggerdoc.AuthControllerDoc; import lombok.RequiredArgsConstructor; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.*; @@ -12,24 +12,24 @@ @RestController @RequiredArgsConstructor @RequestMapping("/api/v1") -public class MemberController implements MemberControllerDoc { +public class AuthController implements AuthControllerDoc { - private final MemberService memberService; + private final AuthService authService; @Override - @PostMapping("/members/sign-up") + @PostMapping("/auth/sign-up") public void signUp(@RequestBody MemberSignUpRequest request) { - this.memberService.signUp(request); + this.authService.signUp(request); } @Override - @PostMapping("/members/sign-in") + @PostMapping("/auth/sign-in") public String signIn(@RequestBody MemberSignInRequest request) { - return this.memberService.signIn(request); + return this.authService.signIn(request); } @Override - @GetMapping("/members/test") + @GetMapping("/auth/test") public String hello(@AuthenticationPrincipal Member member) { System.out.println(member.getEmail().getEmail()); return "Hello, World!"; diff --git a/src/main/java/ei/algobaroapi/domain/member/service/MemberService.java b/src/main/java/ei/algobaroapi/domain/member/service/AuthService.java similarity index 98% rename from src/main/java/ei/algobaroapi/domain/member/service/MemberService.java rename to src/main/java/ei/algobaroapi/domain/member/service/AuthService.java index 8817bcf..c65aa06 100644 --- a/src/main/java/ei/algobaroapi/domain/member/service/MemberService.java +++ b/src/main/java/ei/algobaroapi/domain/member/service/AuthService.java @@ -14,7 +14,7 @@ @Service @Transactional(readOnly = true) @RequiredArgsConstructor -public class MemberService { +public class AuthService { private final MemberRepository memberRepository; private final JwtProvider jwtProvider; diff --git a/src/main/java/ei/algobaroapi/global/config/swaggerdoc/MemberControllerDoc.java b/src/main/java/ei/algobaroapi/global/config/swaggerdoc/AuthControllerDoc.java similarity index 90% rename from src/main/java/ei/algobaroapi/global/config/swaggerdoc/MemberControllerDoc.java rename to src/main/java/ei/algobaroapi/global/config/swaggerdoc/AuthControllerDoc.java index 93a0714..41dbaad 100644 --- a/src/main/java/ei/algobaroapi/global/config/swaggerdoc/MemberControllerDoc.java +++ b/src/main/java/ei/algobaroapi/global/config/swaggerdoc/AuthControllerDoc.java @@ -8,9 +8,9 @@ import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.RequestBody; -@Tag(name = "Member", description = "회원 도메인 API") +@Tag(name = "Auth", description = "회원 인증 도메인 API") @SuppressWarnings("unused") -public interface MemberControllerDoc { +public interface AuthControllerDoc { @Operation(summary = "회원 가입", description = "회원가입을 합니다.") void signUp(@RequestBody MemberSignUpRequest request); From 02d81f578edbccde68791e0e1865acbf020231de Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Tue, 13 Feb 2024 11:47:04 +0900 Subject: [PATCH 27/56] =?UTF-8?q?feat:=20Entity=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=EC=8B=9C=20createdAt=20/=20updatedAt=20=EA=B8=B0=EB=B3=B8?= =?UTF-8?q?=EA=B0=92=EC=9C=BC=EB=A1=9C=20=EC=83=9D=EC=84=B1=EB=90=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=84=A4=EC=A0=95=20=EB=B0=8F=20updatedAt?= =?UTF-8?q?=20=EC=8B=9C=EA=B0=84=20=EB=B3=80=EA=B2=BD=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: kimnamgyu --- .../java/ei/algobaroapi/global/entity/BaseEntity.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/java/ei/algobaroapi/global/entity/BaseEntity.java b/src/main/java/ei/algobaroapi/global/entity/BaseEntity.java index 0b22c84..b9dc0d5 100644 --- a/src/main/java/ei/algobaroapi/global/entity/BaseEntity.java +++ b/src/main/java/ei/algobaroapi/global/entity/BaseEntity.java @@ -3,7 +3,6 @@ import jakarta.persistence.Column; import jakarta.persistence.MappedSuperclass; import lombok.Getter; -import org.springframework.data.annotation.CreatedDate; import java.time.LocalDateTime; @@ -11,7 +10,6 @@ @MappedSuperclass public abstract class BaseEntity { - @CreatedDate @Column(name = "created_at", columnDefinition = "datetime", updatable = false) private LocalDateTime createdAt; @@ -21,10 +19,19 @@ public abstract class BaseEntity { @Column(name = "deleted_at", columnDefinition = "datetime") private LocalDateTime deletedAt; + protected BaseEntity() { + this.createdAt = LocalDateTime.now(); + this.updatedAt = LocalDateTime.now(); + } + public boolean isDeleted() { return this.deletedAt != null; } + protected void update() { + this.updatedAt = LocalDateTime.now(); + } + protected void delete() { if (isDeleted()) throw new IllegalArgumentException("이미 삭제된 엔티티 입니다."); this.deletedAt = LocalDateTime.now(); From b8828f09c65d1388c7431a2770d464fd8c25475b Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Tue, 13 Feb 2024 12:15:10 +0900 Subject: [PATCH 28/56] =?UTF-8?q?feat:=20Error=20Response=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: kimnamgyu --- .../global/message/ErrorResponse.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/main/java/ei/algobaroapi/global/message/ErrorResponse.java diff --git a/src/main/java/ei/algobaroapi/global/message/ErrorResponse.java b/src/main/java/ei/algobaroapi/global/message/ErrorResponse.java new file mode 100644 index 0000000..f0a3041 --- /dev/null +++ b/src/main/java/ei/algobaroapi/global/message/ErrorResponse.java @@ -0,0 +1,17 @@ +package ei.algobaroapi.global.message; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor(access = AccessLevel.PRIVATE) +public class ErrorResponse { + + private final String errorCode; + private final String message; + + public static ErrorResponse of(String errorCode, String message) { + return new ErrorResponse(errorCode, message); + } +} From e6f6143fde2e04c88eef9b248ec5cfdcf2cd3cbf Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Tue, 13 Feb 2024 12:16:33 +0900 Subject: [PATCH 29/56] =?UTF-8?q?feat:=20=EC=9D=B8=EC=A6=9D=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20Custom=20Exception=20=EC=83=9D=EC=84=B1=20=EB=B0=8F?= =?UTF-8?q?=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: kimnamgyu --- .../member/exception/AuthErrorCode.java | 15 ++++++++++++++ .../exception/umm/MemberFoundException.java | 20 +++++++++++++++++++ .../umm/MemberPasswordException.java | 20 +++++++++++++++++++ .../domain/member/service/AuthService.java | 13 +++++++----- 4 files changed, 63 insertions(+), 5 deletions(-) create mode 100644 src/main/java/ei/algobaroapi/domain/member/exception/AuthErrorCode.java create mode 100644 src/main/java/ei/algobaroapi/domain/member/exception/umm/MemberFoundException.java create mode 100644 src/main/java/ei/algobaroapi/domain/member/exception/umm/MemberPasswordException.java diff --git a/src/main/java/ei/algobaroapi/domain/member/exception/AuthErrorCode.java b/src/main/java/ei/algobaroapi/domain/member/exception/AuthErrorCode.java new file mode 100644 index 0000000..4390fce --- /dev/null +++ b/src/main/java/ei/algobaroapi/domain/member/exception/AuthErrorCode.java @@ -0,0 +1,15 @@ +package ei.algobaroapi.domain.member.exception; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum AuthErrorCode { + + EMAIL_NOT_FOUND("E0300", "가입되지 않은 이메일입니다."), + PASSWORD_NOT_MATCH("E0201", "비밀번호가 일치하지 않습니다."); + + private final String errorCode; + private final String errorMessage; +} diff --git a/src/main/java/ei/algobaroapi/domain/member/exception/umm/MemberFoundException.java b/src/main/java/ei/algobaroapi/domain/member/exception/umm/MemberFoundException.java new file mode 100644 index 0000000..a4a6012 --- /dev/null +++ b/src/main/java/ei/algobaroapi/domain/member/exception/umm/MemberFoundException.java @@ -0,0 +1,20 @@ +package ei.algobaroapi.domain.member.exception.umm; + +import ei.algobaroapi.domain.member.exception.AuthErrorCode; +import lombok.Getter; + +@Getter +public class MemberFoundException extends RuntimeException { + + private final String errorCode; + private final String errorMessage; + + private MemberFoundException(AuthErrorCode errorCode) { + this.errorCode = errorCode.getErrorCode(); + this.errorMessage = errorCode.getErrorMessage(); + } + + public static MemberFoundException of(AuthErrorCode errorCode) { + return new MemberFoundException(errorCode); + } +} diff --git a/src/main/java/ei/algobaroapi/domain/member/exception/umm/MemberPasswordException.java b/src/main/java/ei/algobaroapi/domain/member/exception/umm/MemberPasswordException.java new file mode 100644 index 0000000..7862ac1 --- /dev/null +++ b/src/main/java/ei/algobaroapi/domain/member/exception/umm/MemberPasswordException.java @@ -0,0 +1,20 @@ +package ei.algobaroapi.domain.member.exception.umm; + +import ei.algobaroapi.domain.member.exception.AuthErrorCode; +import lombok.Getter; + +@Getter +public class MemberPasswordException extends RuntimeException { + + private final String errorCode; + private final String errorMessage; + + private MemberPasswordException(AuthErrorCode errorCode) { + this.errorCode = errorCode.getErrorCode(); + this.errorMessage = errorCode.getErrorMessage(); + } + + public static MemberPasswordException of(AuthErrorCode errorCode) { + return new MemberPasswordException(errorCode); + } +} diff --git a/src/main/java/ei/algobaroapi/domain/member/service/AuthService.java b/src/main/java/ei/algobaroapi/domain/member/service/AuthService.java index c65aa06..6f1db75 100644 --- a/src/main/java/ei/algobaroapi/domain/member/service/AuthService.java +++ b/src/main/java/ei/algobaroapi/domain/member/service/AuthService.java @@ -5,6 +5,9 @@ import ei.algobaroapi.domain.member.domain.vo.EmailVo; import ei.algobaroapi.domain.member.dto.MemberSignUpRequest; import ei.algobaroapi.domain.member.dto.MemberSignInRequest; +import ei.algobaroapi.domain.member.exception.AuthErrorCode; +import ei.algobaroapi.domain.member.exception.umm.MemberFoundException; +import ei.algobaroapi.domain.member.exception.umm.MemberPasswordException; import ei.algobaroapi.domain.member.util.PasswordUtil; import ei.algobaroapi.global.jwt.JwtProvider; import lombok.RequiredArgsConstructor; @@ -28,12 +31,12 @@ public void signUp(MemberSignUpRequest request) { @Transactional public String signIn(MemberSignInRequest request) { - Member user = memberRepository.findByEmailAndDeletedAtIsNull(new EmailVo(request.getEmail())) - .orElseThrow(() -> new IllegalArgumentException("Email not found")); - if (!passwordUtil.isPasswordMatch(request.getPassword(), user.getPassword())) { - throw new IllegalArgumentException("Password mismatch"); + Member member = memberRepository.findByEmailAndDeletedAtIsNull(new EmailVo(request.getEmail())) + .orElseThrow(() -> MemberFoundException.of(AuthErrorCode.EMAIL_NOT_FOUND)); + if (!passwordUtil.isPasswordMatch(request.getPassword(), member.getPassword())) { + throw MemberPasswordException.of(AuthErrorCode.PASSWORD_NOT_MATCH); } - return jwtProvider.generateToken(user.getUsername(), user.getRoles()); + return jwtProvider.generateToken(member.getUsername(), member.getRoles()); } } From 437603c37f350b12833961360d414fcc0183ceaf Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Tue, 13 Feb 2024 12:16:49 +0900 Subject: [PATCH 30/56] =?UTF-8?q?feat:=20=EC=9D=B8=EC=A6=9D=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20Global=20Exception=20Handler=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: kimnamgyu --- .../exception/AuthGlobalExceptionHandler.java | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/main/java/ei/algobaroapi/domain/member/exception/AuthGlobalExceptionHandler.java diff --git a/src/main/java/ei/algobaroapi/domain/member/exception/AuthGlobalExceptionHandler.java b/src/main/java/ei/algobaroapi/domain/member/exception/AuthGlobalExceptionHandler.java new file mode 100644 index 0000000..d854a0a --- /dev/null +++ b/src/main/java/ei/algobaroapi/domain/member/exception/AuthGlobalExceptionHandler.java @@ -0,0 +1,29 @@ +package ei.algobaroapi.domain.member.exception; + +import ei.algobaroapi.domain.member.exception.umm.MemberFoundException; +import ei.algobaroapi.domain.member.exception.umm.MemberPasswordException; +import ei.algobaroapi.global.message.ErrorResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@Slf4j +@RestControllerAdvice +public class AuthGlobalExceptionHandler { + + @ExceptionHandler(MemberFoundException.class) + @ResponseStatus(HttpStatus.NOT_FOUND) + public ErrorResponse catchMemberFoundException(MemberFoundException e) { + log.warn(e.getErrorMessage()); + return ErrorResponse.of(e.getErrorCode(), e.getErrorMessage()); + } + + @ExceptionHandler(MemberPasswordException.class) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public ErrorResponse catchMemberPasswordException(MemberPasswordException e) { + log.warn(e.getErrorMessage()); + return ErrorResponse.of(e.getErrorCode(), e.getErrorMessage()); + } +} From 792a99adb9061dc8d14e796c8253177e6d474354 Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Tue, 13 Feb 2024 12:20:37 +0900 Subject: [PATCH 31/56] =?UTF-8?q?refactor:=20Auth=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: kimnamgyu --- .../controller/AuthController.java | 8 ++++---- .../{member => auth}/dto/MemberSignInRequest.java | 2 +- .../{member => auth}/dto/MemberSignUpRequest.java | 2 +- .../{member => auth}/exception/AuthErrorCode.java | 2 +- .../exception/AuthGlobalExceptionHandler.java | 6 +++--- .../exception/umm/MemberFoundException.java | 4 ++-- .../exception/umm/MemberPasswordException.java | 4 ++-- .../{member => auth}/service/AuthService.java | 14 +++++++------- .../domain/{member => auth}/util/PasswordUtil.java | 2 +- .../config/swaggerdoc/AuthControllerDoc.java | 4 ++-- 10 files changed, 24 insertions(+), 24 deletions(-) rename src/main/java/ei/algobaroapi/domain/{member => auth}/controller/AuthController.java (81%) rename src/main/java/ei/algobaroapi/domain/{member => auth}/dto/MemberSignInRequest.java (74%) rename src/main/java/ei/algobaroapi/domain/{member => auth}/dto/MemberSignUpRequest.java (90%) rename src/main/java/ei/algobaroapi/domain/{member => auth}/exception/AuthErrorCode.java (88%) rename src/main/java/ei/algobaroapi/domain/{member => auth}/exception/AuthGlobalExceptionHandler.java (83%) rename src/main/java/ei/algobaroapi/domain/{member => auth}/exception/umm/MemberFoundException.java (80%) rename src/main/java/ei/algobaroapi/domain/{member => auth}/exception/umm/MemberPasswordException.java (81%) rename src/main/java/ei/algobaroapi/domain/{member => auth}/service/AuthService.java (76%) rename src/main/java/ei/algobaroapi/domain/{member => auth}/util/PasswordUtil.java (95%) diff --git a/src/main/java/ei/algobaroapi/domain/member/controller/AuthController.java b/src/main/java/ei/algobaroapi/domain/auth/controller/AuthController.java similarity index 81% rename from src/main/java/ei/algobaroapi/domain/member/controller/AuthController.java rename to src/main/java/ei/algobaroapi/domain/auth/controller/AuthController.java index 921e0be..0795a5d 100644 --- a/src/main/java/ei/algobaroapi/domain/member/controller/AuthController.java +++ b/src/main/java/ei/algobaroapi/domain/auth/controller/AuthController.java @@ -1,9 +1,9 @@ -package ei.algobaroapi.domain.member.controller; +package ei.algobaroapi.domain.auth.controller; import ei.algobaroapi.domain.member.domain.Member; -import ei.algobaroapi.domain.member.dto.MemberSignUpRequest; -import ei.algobaroapi.domain.member.dto.MemberSignInRequest; -import ei.algobaroapi.domain.member.service.AuthService; +import ei.algobaroapi.domain.auth.dto.MemberSignUpRequest; +import ei.algobaroapi.domain.auth.dto.MemberSignInRequest; +import ei.algobaroapi.domain.auth.service.AuthService; import ei.algobaroapi.global.config.swaggerdoc.AuthControllerDoc; import lombok.RequiredArgsConstructor; import org.springframework.security.core.annotation.AuthenticationPrincipal; diff --git a/src/main/java/ei/algobaroapi/domain/member/dto/MemberSignInRequest.java b/src/main/java/ei/algobaroapi/domain/auth/dto/MemberSignInRequest.java similarity index 74% rename from src/main/java/ei/algobaroapi/domain/member/dto/MemberSignInRequest.java rename to src/main/java/ei/algobaroapi/domain/auth/dto/MemberSignInRequest.java index cb5fd69..dac7a2d 100644 --- a/src/main/java/ei/algobaroapi/domain/member/dto/MemberSignInRequest.java +++ b/src/main/java/ei/algobaroapi/domain/auth/dto/MemberSignInRequest.java @@ -1,4 +1,4 @@ -package ei.algobaroapi.domain.member.dto; +package ei.algobaroapi.domain.auth.dto; import lombok.Getter; diff --git a/src/main/java/ei/algobaroapi/domain/member/dto/MemberSignUpRequest.java b/src/main/java/ei/algobaroapi/domain/auth/dto/MemberSignUpRequest.java similarity index 90% rename from src/main/java/ei/algobaroapi/domain/member/dto/MemberSignUpRequest.java rename to src/main/java/ei/algobaroapi/domain/auth/dto/MemberSignUpRequest.java index 32f4c19..0176ec8 100644 --- a/src/main/java/ei/algobaroapi/domain/member/dto/MemberSignUpRequest.java +++ b/src/main/java/ei/algobaroapi/domain/auth/dto/MemberSignUpRequest.java @@ -1,4 +1,4 @@ -package ei.algobaroapi.domain.member.dto; +package ei.algobaroapi.domain.auth.dto; import ei.algobaroapi.domain.member.domain.Member; import lombok.Builder; diff --git a/src/main/java/ei/algobaroapi/domain/member/exception/AuthErrorCode.java b/src/main/java/ei/algobaroapi/domain/auth/exception/AuthErrorCode.java similarity index 88% rename from src/main/java/ei/algobaroapi/domain/member/exception/AuthErrorCode.java rename to src/main/java/ei/algobaroapi/domain/auth/exception/AuthErrorCode.java index 4390fce..ceeb4c0 100644 --- a/src/main/java/ei/algobaroapi/domain/member/exception/AuthErrorCode.java +++ b/src/main/java/ei/algobaroapi/domain/auth/exception/AuthErrorCode.java @@ -1,4 +1,4 @@ -package ei.algobaroapi.domain.member.exception; +package ei.algobaroapi.domain.auth.exception; import lombok.Getter; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/ei/algobaroapi/domain/member/exception/AuthGlobalExceptionHandler.java b/src/main/java/ei/algobaroapi/domain/auth/exception/AuthGlobalExceptionHandler.java similarity index 83% rename from src/main/java/ei/algobaroapi/domain/member/exception/AuthGlobalExceptionHandler.java rename to src/main/java/ei/algobaroapi/domain/auth/exception/AuthGlobalExceptionHandler.java index d854a0a..e223756 100644 --- a/src/main/java/ei/algobaroapi/domain/member/exception/AuthGlobalExceptionHandler.java +++ b/src/main/java/ei/algobaroapi/domain/auth/exception/AuthGlobalExceptionHandler.java @@ -1,7 +1,7 @@ -package ei.algobaroapi.domain.member.exception; +package ei.algobaroapi.domain.auth.exception; -import ei.algobaroapi.domain.member.exception.umm.MemberFoundException; -import ei.algobaroapi.domain.member.exception.umm.MemberPasswordException; +import ei.algobaroapi.domain.auth.exception.umm.MemberFoundException; +import ei.algobaroapi.domain.auth.exception.umm.MemberPasswordException; import ei.algobaroapi.global.message.ErrorResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; diff --git a/src/main/java/ei/algobaroapi/domain/member/exception/umm/MemberFoundException.java b/src/main/java/ei/algobaroapi/domain/auth/exception/umm/MemberFoundException.java similarity index 80% rename from src/main/java/ei/algobaroapi/domain/member/exception/umm/MemberFoundException.java rename to src/main/java/ei/algobaroapi/domain/auth/exception/umm/MemberFoundException.java index a4a6012..c70323a 100644 --- a/src/main/java/ei/algobaroapi/domain/member/exception/umm/MemberFoundException.java +++ b/src/main/java/ei/algobaroapi/domain/auth/exception/umm/MemberFoundException.java @@ -1,6 +1,6 @@ -package ei.algobaroapi.domain.member.exception.umm; +package ei.algobaroapi.domain.auth.exception.umm; -import ei.algobaroapi.domain.member.exception.AuthErrorCode; +import ei.algobaroapi.domain.auth.exception.AuthErrorCode; import lombok.Getter; @Getter diff --git a/src/main/java/ei/algobaroapi/domain/member/exception/umm/MemberPasswordException.java b/src/main/java/ei/algobaroapi/domain/auth/exception/umm/MemberPasswordException.java similarity index 81% rename from src/main/java/ei/algobaroapi/domain/member/exception/umm/MemberPasswordException.java rename to src/main/java/ei/algobaroapi/domain/auth/exception/umm/MemberPasswordException.java index 7862ac1..cb179be 100644 --- a/src/main/java/ei/algobaroapi/domain/member/exception/umm/MemberPasswordException.java +++ b/src/main/java/ei/algobaroapi/domain/auth/exception/umm/MemberPasswordException.java @@ -1,6 +1,6 @@ -package ei.algobaroapi.domain.member.exception.umm; +package ei.algobaroapi.domain.auth.exception.umm; -import ei.algobaroapi.domain.member.exception.AuthErrorCode; +import ei.algobaroapi.domain.auth.exception.AuthErrorCode; import lombok.Getter; @Getter diff --git a/src/main/java/ei/algobaroapi/domain/member/service/AuthService.java b/src/main/java/ei/algobaroapi/domain/auth/service/AuthService.java similarity index 76% rename from src/main/java/ei/algobaroapi/domain/member/service/AuthService.java rename to src/main/java/ei/algobaroapi/domain/auth/service/AuthService.java index 6f1db75..0c2eb12 100644 --- a/src/main/java/ei/algobaroapi/domain/member/service/AuthService.java +++ b/src/main/java/ei/algobaroapi/domain/auth/service/AuthService.java @@ -1,14 +1,14 @@ -package ei.algobaroapi.domain.member.service; +package ei.algobaroapi.domain.auth.service; import ei.algobaroapi.domain.member.domain.Member; import ei.algobaroapi.domain.member.domain.MemberRepository; import ei.algobaroapi.domain.member.domain.vo.EmailVo; -import ei.algobaroapi.domain.member.dto.MemberSignUpRequest; -import ei.algobaroapi.domain.member.dto.MemberSignInRequest; -import ei.algobaroapi.domain.member.exception.AuthErrorCode; -import ei.algobaroapi.domain.member.exception.umm.MemberFoundException; -import ei.algobaroapi.domain.member.exception.umm.MemberPasswordException; -import ei.algobaroapi.domain.member.util.PasswordUtil; +import ei.algobaroapi.domain.auth.dto.MemberSignUpRequest; +import ei.algobaroapi.domain.auth.dto.MemberSignInRequest; +import ei.algobaroapi.domain.auth.exception.AuthErrorCode; +import ei.algobaroapi.domain.auth.exception.umm.MemberFoundException; +import ei.algobaroapi.domain.auth.exception.umm.MemberPasswordException; +import ei.algobaroapi.domain.auth.util.PasswordUtil; import ei.algobaroapi.global.jwt.JwtProvider; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; diff --git a/src/main/java/ei/algobaroapi/domain/member/util/PasswordUtil.java b/src/main/java/ei/algobaroapi/domain/auth/util/PasswordUtil.java similarity index 95% rename from src/main/java/ei/algobaroapi/domain/member/util/PasswordUtil.java rename to src/main/java/ei/algobaroapi/domain/auth/util/PasswordUtil.java index 47e73bf..4fa91e5 100644 --- a/src/main/java/ei/algobaroapi/domain/member/util/PasswordUtil.java +++ b/src/main/java/ei/algobaroapi/domain/auth/util/PasswordUtil.java @@ -1,4 +1,4 @@ -package ei.algobaroapi.domain.member.util; +package ei.algobaroapi.domain.auth.util; import lombok.Getter; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/ei/algobaroapi/global/config/swaggerdoc/AuthControllerDoc.java b/src/main/java/ei/algobaroapi/global/config/swaggerdoc/AuthControllerDoc.java index 41dbaad..0791e23 100644 --- a/src/main/java/ei/algobaroapi/global/config/swaggerdoc/AuthControllerDoc.java +++ b/src/main/java/ei/algobaroapi/global/config/swaggerdoc/AuthControllerDoc.java @@ -1,8 +1,8 @@ package ei.algobaroapi.global.config.swaggerdoc; import ei.algobaroapi.domain.member.domain.Member; -import ei.algobaroapi.domain.member.dto.MemberSignInRequest; -import ei.algobaroapi.domain.member.dto.MemberSignUpRequest; +import ei.algobaroapi.domain.auth.dto.MemberSignInRequest; +import ei.algobaroapi.domain.auth.dto.MemberSignUpRequest; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.security.core.annotation.AuthenticationPrincipal; From 4991d752e5102785e037e4a18f47aaa6eb765fba Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Tue, 13 Feb 2024 12:20:56 +0900 Subject: [PATCH 32/56] =?UTF-8?q?feat:=20getMemberByEmail=20/=20addMember?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: kimnamgyu --- .../domain/member/service/MemberService.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/main/java/ei/algobaroapi/domain/member/service/MemberService.java diff --git a/src/main/java/ei/algobaroapi/domain/member/service/MemberService.java b/src/main/java/ei/algobaroapi/domain/member/service/MemberService.java new file mode 100644 index 0000000..a268c6d --- /dev/null +++ b/src/main/java/ei/algobaroapi/domain/member/service/MemberService.java @@ -0,0 +1,28 @@ +package ei.algobaroapi.domain.member.service; + +import ei.algobaroapi.domain.auth.exception.AuthErrorCode; +import ei.algobaroapi.domain.auth.exception.umm.MemberFoundException; +import ei.algobaroapi.domain.member.domain.Member; +import ei.algobaroapi.domain.member.domain.MemberRepository; +import ei.algobaroapi.domain.member.domain.vo.EmailVo; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional(readOnly = true) +@RequiredArgsConstructor +public class MemberService { + + private final MemberRepository memberRepository; + + public Member getMemberByEmail(String email) { + return memberRepository.findByEmailAndDeletedAtIsNull(new EmailVo(email)) + .orElseThrow(() -> MemberFoundException.of(AuthErrorCode.EMAIL_NOT_FOUND)); + } + + @Transactional + public Member addMember(Member member) { + return memberRepository.save(member); + } +} From e7842342b923f0a828eeff459c25d25e03b54967 Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Tue, 13 Feb 2024 12:24:13 +0900 Subject: [PATCH 33/56] =?UTF-8?q?refactor:=20AuthService=EC=97=90=EC=84=9C?= =?UTF-8?q?=20MemberService=20=EC=9D=98=EC=A1=B4=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: kimnamgyu --- .../algobaroapi/domain/auth/service/AuthService.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/main/java/ei/algobaroapi/domain/auth/service/AuthService.java b/src/main/java/ei/algobaroapi/domain/auth/service/AuthService.java index 0c2eb12..cf36fcf 100644 --- a/src/main/java/ei/algobaroapi/domain/auth/service/AuthService.java +++ b/src/main/java/ei/algobaroapi/domain/auth/service/AuthService.java @@ -1,14 +1,12 @@ package ei.algobaroapi.domain.auth.service; import ei.algobaroapi.domain.member.domain.Member; -import ei.algobaroapi.domain.member.domain.MemberRepository; -import ei.algobaroapi.domain.member.domain.vo.EmailVo; import ei.algobaroapi.domain.auth.dto.MemberSignUpRequest; import ei.algobaroapi.domain.auth.dto.MemberSignInRequest; import ei.algobaroapi.domain.auth.exception.AuthErrorCode; -import ei.algobaroapi.domain.auth.exception.umm.MemberFoundException; import ei.algobaroapi.domain.auth.exception.umm.MemberPasswordException; import ei.algobaroapi.domain.auth.util.PasswordUtil; +import ei.algobaroapi.domain.member.service.MemberService; import ei.algobaroapi.global.jwt.JwtProvider; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -19,20 +17,19 @@ @RequiredArgsConstructor public class AuthService { - private final MemberRepository memberRepository; + private final MemberService memberService; private final JwtProvider jwtProvider; private final PasswordUtil passwordUtil; @Transactional public void signUp(MemberSignUpRequest request) { String encryptPassword = passwordUtil.validateAndEncryptPassword(request.getPassword()); - memberRepository.save(request.toEntity(encryptPassword)); + memberService.addMember(request.toEntity(encryptPassword)); } @Transactional public String signIn(MemberSignInRequest request) { - Member member = memberRepository.findByEmailAndDeletedAtIsNull(new EmailVo(request.getEmail())) - .orElseThrow(() -> MemberFoundException.of(AuthErrorCode.EMAIL_NOT_FOUND)); + Member member = memberService.getMemberByEmail(request.getEmail()); if (!passwordUtil.isPasswordMatch(request.getPassword(), member.getPassword())) { throw MemberPasswordException.of(AuthErrorCode.PASSWORD_NOT_MATCH); } From 33608a0de20efe481ad2bd0f57d0e9019dcc555d Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Tue, 13 Feb 2024 12:29:39 +0900 Subject: [PATCH 34/56] =?UTF-8?q?refactor:=20Member=20/=20Auth=20Exception?= =?UTF-8?q?=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: kimnamgyu --- .../domain/auth/exception/AuthErrorCode.java | 1 - .../exception/AuthGlobalExceptionHandler.java | 14 +++---------- ...eption.java => AuthPasswordException.java} | 8 +++---- .../domain/auth/service/AuthService.java | 4 ++-- .../member/exception/MemberErrorCode.java | 14 +++++++++++++ .../MemberGlobalExceptionHandler.java | 21 +++++++++++++++++++ .../exception/umm/MemberFoundException.java | 8 +++---- .../domain/member/service/MemberService.java | 6 +++--- 8 files changed, 51 insertions(+), 25 deletions(-) rename src/main/java/ei/algobaroapi/domain/auth/exception/umm/{MemberPasswordException.java => AuthPasswordException.java} (57%) create mode 100644 src/main/java/ei/algobaroapi/domain/member/exception/MemberErrorCode.java create mode 100644 src/main/java/ei/algobaroapi/domain/member/exception/MemberGlobalExceptionHandler.java rename src/main/java/ei/algobaroapi/domain/{auth => member}/exception/umm/MemberFoundException.java (58%) diff --git a/src/main/java/ei/algobaroapi/domain/auth/exception/AuthErrorCode.java b/src/main/java/ei/algobaroapi/domain/auth/exception/AuthErrorCode.java index ceeb4c0..7839349 100644 --- a/src/main/java/ei/algobaroapi/domain/auth/exception/AuthErrorCode.java +++ b/src/main/java/ei/algobaroapi/domain/auth/exception/AuthErrorCode.java @@ -7,7 +7,6 @@ @RequiredArgsConstructor public enum AuthErrorCode { - EMAIL_NOT_FOUND("E0300", "가입되지 않은 이메일입니다."), PASSWORD_NOT_MATCH("E0201", "비밀번호가 일치하지 않습니다."); private final String errorCode; diff --git a/src/main/java/ei/algobaroapi/domain/auth/exception/AuthGlobalExceptionHandler.java b/src/main/java/ei/algobaroapi/domain/auth/exception/AuthGlobalExceptionHandler.java index e223756..749bf73 100644 --- a/src/main/java/ei/algobaroapi/domain/auth/exception/AuthGlobalExceptionHandler.java +++ b/src/main/java/ei/algobaroapi/domain/auth/exception/AuthGlobalExceptionHandler.java @@ -1,7 +1,6 @@ package ei.algobaroapi.domain.auth.exception; -import ei.algobaroapi.domain.auth.exception.umm.MemberFoundException; -import ei.algobaroapi.domain.auth.exception.umm.MemberPasswordException; +import ei.algobaroapi.domain.auth.exception.umm.AuthPasswordException; import ei.algobaroapi.global.message.ErrorResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; @@ -13,16 +12,9 @@ @RestControllerAdvice public class AuthGlobalExceptionHandler { - @ExceptionHandler(MemberFoundException.class) - @ResponseStatus(HttpStatus.NOT_FOUND) - public ErrorResponse catchMemberFoundException(MemberFoundException e) { - log.warn(e.getErrorMessage()); - return ErrorResponse.of(e.getErrorCode(), e.getErrorMessage()); - } - - @ExceptionHandler(MemberPasswordException.class) + @ExceptionHandler(AuthPasswordException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) - public ErrorResponse catchMemberPasswordException(MemberPasswordException e) { + public ErrorResponse catchMemberPasswordException(AuthPasswordException e) { log.warn(e.getErrorMessage()); return ErrorResponse.of(e.getErrorCode(), e.getErrorMessage()); } diff --git a/src/main/java/ei/algobaroapi/domain/auth/exception/umm/MemberPasswordException.java b/src/main/java/ei/algobaroapi/domain/auth/exception/umm/AuthPasswordException.java similarity index 57% rename from src/main/java/ei/algobaroapi/domain/auth/exception/umm/MemberPasswordException.java rename to src/main/java/ei/algobaroapi/domain/auth/exception/umm/AuthPasswordException.java index cb179be..87ccfe7 100644 --- a/src/main/java/ei/algobaroapi/domain/auth/exception/umm/MemberPasswordException.java +++ b/src/main/java/ei/algobaroapi/domain/auth/exception/umm/AuthPasswordException.java @@ -4,17 +4,17 @@ import lombok.Getter; @Getter -public class MemberPasswordException extends RuntimeException { +public class AuthPasswordException extends RuntimeException { private final String errorCode; private final String errorMessage; - private MemberPasswordException(AuthErrorCode errorCode) { + private AuthPasswordException(AuthErrorCode errorCode) { this.errorCode = errorCode.getErrorCode(); this.errorMessage = errorCode.getErrorMessage(); } - public static MemberPasswordException of(AuthErrorCode errorCode) { - return new MemberPasswordException(errorCode); + public static AuthPasswordException of(AuthErrorCode errorCode) { + return new AuthPasswordException(errorCode); } } diff --git a/src/main/java/ei/algobaroapi/domain/auth/service/AuthService.java b/src/main/java/ei/algobaroapi/domain/auth/service/AuthService.java index cf36fcf..c1c82c1 100644 --- a/src/main/java/ei/algobaroapi/domain/auth/service/AuthService.java +++ b/src/main/java/ei/algobaroapi/domain/auth/service/AuthService.java @@ -4,7 +4,7 @@ import ei.algobaroapi.domain.auth.dto.MemberSignUpRequest; import ei.algobaroapi.domain.auth.dto.MemberSignInRequest; import ei.algobaroapi.domain.auth.exception.AuthErrorCode; -import ei.algobaroapi.domain.auth.exception.umm.MemberPasswordException; +import ei.algobaroapi.domain.auth.exception.umm.AuthPasswordException; import ei.algobaroapi.domain.auth.util.PasswordUtil; import ei.algobaroapi.domain.member.service.MemberService; import ei.algobaroapi.global.jwt.JwtProvider; @@ -31,7 +31,7 @@ public void signUp(MemberSignUpRequest request) { public String signIn(MemberSignInRequest request) { Member member = memberService.getMemberByEmail(request.getEmail()); if (!passwordUtil.isPasswordMatch(request.getPassword(), member.getPassword())) { - throw MemberPasswordException.of(AuthErrorCode.PASSWORD_NOT_MATCH); + throw AuthPasswordException.of(AuthErrorCode.PASSWORD_NOT_MATCH); } return jwtProvider.generateToken(member.getUsername(), member.getRoles()); diff --git a/src/main/java/ei/algobaroapi/domain/member/exception/MemberErrorCode.java b/src/main/java/ei/algobaroapi/domain/member/exception/MemberErrorCode.java new file mode 100644 index 0000000..6bee828 --- /dev/null +++ b/src/main/java/ei/algobaroapi/domain/member/exception/MemberErrorCode.java @@ -0,0 +1,14 @@ +package ei.algobaroapi.domain.member.exception; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum MemberErrorCode { + + EMAIL_NOT_FOUND("E1300", "가입되지 않은 이메일입니다."); + + private final String errorCode; + private final String errorMessage; +} diff --git a/src/main/java/ei/algobaroapi/domain/member/exception/MemberGlobalExceptionHandler.java b/src/main/java/ei/algobaroapi/domain/member/exception/MemberGlobalExceptionHandler.java new file mode 100644 index 0000000..b4f571d --- /dev/null +++ b/src/main/java/ei/algobaroapi/domain/member/exception/MemberGlobalExceptionHandler.java @@ -0,0 +1,21 @@ +package ei.algobaroapi.domain.member.exception; + +import ei.algobaroapi.domain.member.exception.umm.MemberFoundException; +import ei.algobaroapi.global.message.ErrorResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@Slf4j +@RestControllerAdvice +public class MemberGlobalExceptionHandler { + + @ExceptionHandler(MemberFoundException.class) + @ResponseStatus(HttpStatus.NOT_FOUND) + public ErrorResponse catchMemberFoundException(MemberFoundException e) { + log.warn(e.getErrorMessage()); + return ErrorResponse.of(e.getErrorCode(), e.getErrorMessage()); + } +} diff --git a/src/main/java/ei/algobaroapi/domain/auth/exception/umm/MemberFoundException.java b/src/main/java/ei/algobaroapi/domain/member/exception/umm/MemberFoundException.java similarity index 58% rename from src/main/java/ei/algobaroapi/domain/auth/exception/umm/MemberFoundException.java rename to src/main/java/ei/algobaroapi/domain/member/exception/umm/MemberFoundException.java index c70323a..cd73daf 100644 --- a/src/main/java/ei/algobaroapi/domain/auth/exception/umm/MemberFoundException.java +++ b/src/main/java/ei/algobaroapi/domain/member/exception/umm/MemberFoundException.java @@ -1,6 +1,6 @@ -package ei.algobaroapi.domain.auth.exception.umm; +package ei.algobaroapi.domain.member.exception.umm; -import ei.algobaroapi.domain.auth.exception.AuthErrorCode; +import ei.algobaroapi.domain.member.exception.MemberErrorCode; import lombok.Getter; @Getter @@ -9,12 +9,12 @@ public class MemberFoundException extends RuntimeException { private final String errorCode; private final String errorMessage; - private MemberFoundException(AuthErrorCode errorCode) { + private MemberFoundException(MemberErrorCode errorCode) { this.errorCode = errorCode.getErrorCode(); this.errorMessage = errorCode.getErrorMessage(); } - public static MemberFoundException of(AuthErrorCode errorCode) { + public static MemberFoundException of(MemberErrorCode errorCode) { return new MemberFoundException(errorCode); } } diff --git a/src/main/java/ei/algobaroapi/domain/member/service/MemberService.java b/src/main/java/ei/algobaroapi/domain/member/service/MemberService.java index a268c6d..646a6b8 100644 --- a/src/main/java/ei/algobaroapi/domain/member/service/MemberService.java +++ b/src/main/java/ei/algobaroapi/domain/member/service/MemberService.java @@ -1,10 +1,10 @@ package ei.algobaroapi.domain.member.service; -import ei.algobaroapi.domain.auth.exception.AuthErrorCode; -import ei.algobaroapi.domain.auth.exception.umm.MemberFoundException; import ei.algobaroapi.domain.member.domain.Member; import ei.algobaroapi.domain.member.domain.MemberRepository; import ei.algobaroapi.domain.member.domain.vo.EmailVo; +import ei.algobaroapi.domain.member.exception.MemberErrorCode; +import ei.algobaroapi.domain.member.exception.umm.MemberFoundException; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -18,7 +18,7 @@ public class MemberService { public Member getMemberByEmail(String email) { return memberRepository.findByEmailAndDeletedAtIsNull(new EmailVo(email)) - .orElseThrow(() -> MemberFoundException.of(AuthErrorCode.EMAIL_NOT_FOUND)); + .orElseThrow(() -> MemberFoundException.of(MemberErrorCode.EMAIL_NOT_FOUND)); } @Transactional From 9b712db7c297578f9c682e366697833ca5b0bd9f Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Tue, 13 Feb 2024 13:17:00 +0900 Subject: [PATCH 35/56] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20res?= =?UTF-8?q?ponse=20dto=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: kimnamgyu --- .../domain/auth/controller/AuthController.java | 3 ++- .../domain/auth/dto/MemberSignInResponse.java | 16 ++++++++++++++++ .../domain/auth/service/AuthService.java | 11 +++++++---- .../config/swaggerdoc/AuthControllerDoc.java | 3 ++- 4 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 src/main/java/ei/algobaroapi/domain/auth/dto/MemberSignInResponse.java diff --git a/src/main/java/ei/algobaroapi/domain/auth/controller/AuthController.java b/src/main/java/ei/algobaroapi/domain/auth/controller/AuthController.java index 0795a5d..16b2e00 100644 --- a/src/main/java/ei/algobaroapi/domain/auth/controller/AuthController.java +++ b/src/main/java/ei/algobaroapi/domain/auth/controller/AuthController.java @@ -1,5 +1,6 @@ package ei.algobaroapi.domain.auth.controller; +import ei.algobaroapi.domain.auth.dto.MemberSignInResponse; import ei.algobaroapi.domain.member.domain.Member; import ei.algobaroapi.domain.auth.dto.MemberSignUpRequest; import ei.algobaroapi.domain.auth.dto.MemberSignInRequest; @@ -24,7 +25,7 @@ public void signUp(@RequestBody MemberSignUpRequest request) { @Override @PostMapping("/auth/sign-in") - public String signIn(@RequestBody MemberSignInRequest request) { + public MemberSignInResponse signIn(@RequestBody MemberSignInRequest request) { return this.authService.signIn(request); } diff --git a/src/main/java/ei/algobaroapi/domain/auth/dto/MemberSignInResponse.java b/src/main/java/ei/algobaroapi/domain/auth/dto/MemberSignInResponse.java new file mode 100644 index 0000000..b181441 --- /dev/null +++ b/src/main/java/ei/algobaroapi/domain/auth/dto/MemberSignInResponse.java @@ -0,0 +1,16 @@ +package ei.algobaroapi.domain.auth.dto; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor(access = AccessLevel.PRIVATE) +public class MemberSignInResponse { + + private final String accessToken; + + public static MemberSignInResponse of(String accessToken) { + return new MemberSignInResponse(accessToken); + } +} diff --git a/src/main/java/ei/algobaroapi/domain/auth/service/AuthService.java b/src/main/java/ei/algobaroapi/domain/auth/service/AuthService.java index c1c82c1..10bda73 100644 --- a/src/main/java/ei/algobaroapi/domain/auth/service/AuthService.java +++ b/src/main/java/ei/algobaroapi/domain/auth/service/AuthService.java @@ -1,11 +1,12 @@ package ei.algobaroapi.domain.auth.service; -import ei.algobaroapi.domain.member.domain.Member; -import ei.algobaroapi.domain.auth.dto.MemberSignUpRequest; import ei.algobaroapi.domain.auth.dto.MemberSignInRequest; +import ei.algobaroapi.domain.auth.dto.MemberSignInResponse; +import ei.algobaroapi.domain.auth.dto.MemberSignUpRequest; import ei.algobaroapi.domain.auth.exception.AuthErrorCode; import ei.algobaroapi.domain.auth.exception.umm.AuthPasswordException; import ei.algobaroapi.domain.auth.util.PasswordUtil; +import ei.algobaroapi.domain.member.domain.Member; import ei.algobaroapi.domain.member.service.MemberService; import ei.algobaroapi.global.jwt.JwtProvider; import lombok.RequiredArgsConstructor; @@ -28,12 +29,14 @@ public void signUp(MemberSignUpRequest request) { } @Transactional - public String signIn(MemberSignInRequest request) { + public MemberSignInResponse signIn(MemberSignInRequest request) { Member member = memberService.getMemberByEmail(request.getEmail()); if (!passwordUtil.isPasswordMatch(request.getPassword(), member.getPassword())) { throw AuthPasswordException.of(AuthErrorCode.PASSWORD_NOT_MATCH); } - return jwtProvider.generateToken(member.getUsername(), member.getRoles()); + String accessToken = jwtProvider.generateToken(member.getUsername(), member.getRoles()); + + return MemberSignInResponse.of(accessToken); } } diff --git a/src/main/java/ei/algobaroapi/global/config/swaggerdoc/AuthControllerDoc.java b/src/main/java/ei/algobaroapi/global/config/swaggerdoc/AuthControllerDoc.java index 0791e23..42b93ee 100644 --- a/src/main/java/ei/algobaroapi/global/config/swaggerdoc/AuthControllerDoc.java +++ b/src/main/java/ei/algobaroapi/global/config/swaggerdoc/AuthControllerDoc.java @@ -1,5 +1,6 @@ package ei.algobaroapi.global.config.swaggerdoc; +import ei.algobaroapi.domain.auth.dto.MemberSignInResponse; import ei.algobaroapi.domain.member.domain.Member; import ei.algobaroapi.domain.auth.dto.MemberSignInRequest; import ei.algobaroapi.domain.auth.dto.MemberSignUpRequest; @@ -16,7 +17,7 @@ public interface AuthControllerDoc { void signUp(@RequestBody MemberSignUpRequest request); @Operation(summary = "로그인", description = "이메일, 비밀번호로 로그인을 합니다.") - String signIn(@RequestBody MemberSignInRequest request); + MemberSignInResponse signIn(@RequestBody MemberSignInRequest request); @Operation(summary = "테스트", description = "테스트용 API") String hello(@AuthenticationPrincipal Member member); From ac0ab2e14c344a72307bfbb9fcbfb41d3c198057 Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Tue, 13 Feb 2024 13:17:52 +0900 Subject: [PATCH 36/56] =?UTF-8?q?feat:=20=EC=9D=98=EB=8F=84=EC=B9=98=20?= =?UTF-8?q?=EC=95=8A=EC=9D=80=20=EC=97=90=EB=9F=AC=EB=A5=BC=20=EC=9E=A1?= =?UTF-8?q?=EB=8A=94=20Exception=20Handler=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: kimnamgyu --- .../exception/GlobalExceptionHandler.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/main/java/ei/algobaroapi/global/exception/GlobalExceptionHandler.java diff --git a/src/main/java/ei/algobaroapi/global/exception/GlobalExceptionHandler.java b/src/main/java/ei/algobaroapi/global/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..cf28463 --- /dev/null +++ b/src/main/java/ei/algobaroapi/global/exception/GlobalExceptionHandler.java @@ -0,0 +1,21 @@ +package ei.algobaroapi.global.exception; + +import ei.algobaroapi.global.message.ErrorResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@Slf4j +@RestControllerAdvice +public class GlobalExceptionHandler { + + @ExceptionHandler(RuntimeException.class) + @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) + public ErrorResponse catchMemberPasswordException(RuntimeException e) { + log.error(e.getMessage()); + + return ErrorResponse.of("E9999", "Internal Server Error"); + } +} From 5494877896e7c500ae88d026b22804cd4381eaa3 Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Tue, 13 Feb 2024 13:19:33 +0900 Subject: [PATCH 37/56] =?UTF-8?q?feat:=20Success=20Message=20AOP=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: kimnamgyu --- .../global/message/BasicResponse.java | 15 +++++++++++ .../global/message/ResponseAdvice.java | 26 +++++++++++++++++++ .../global/message/ResponseUtil.java | 12 +++++++++ 3 files changed, 53 insertions(+) create mode 100644 src/main/java/ei/algobaroapi/global/message/BasicResponse.java create mode 100644 src/main/java/ei/algobaroapi/global/message/ResponseAdvice.java create mode 100644 src/main/java/ei/algobaroapi/global/message/ResponseUtil.java diff --git a/src/main/java/ei/algobaroapi/global/message/BasicResponse.java b/src/main/java/ei/algobaroapi/global/message/BasicResponse.java new file mode 100644 index 0000000..a538cda --- /dev/null +++ b/src/main/java/ei/algobaroapi/global/message/BasicResponse.java @@ -0,0 +1,15 @@ +package ei.algobaroapi.global.message; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +@JsonInclude(JsonInclude.Include.NON_NULL) +public class BasicResponse { + + private boolean success; + private T response; + private ErrorResponse error; +} diff --git a/src/main/java/ei/algobaroapi/global/message/ResponseAdvice.java b/src/main/java/ei/algobaroapi/global/message/ResponseAdvice.java new file mode 100644 index 0000000..8781504 --- /dev/null +++ b/src/main/java/ei/algobaroapi/global/message/ResponseAdvice.java @@ -0,0 +1,26 @@ +package ei.algobaroapi.global.message; + +import org.springframework.core.MethodParameter; +import org.springframework.http.MediaType; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.server.ServerHttpRequest; +import org.springframework.http.server.ServerHttpResponse; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; + +@RestControllerAdvice +public class ResponseAdvice implements ResponseBodyAdvice { + + @Override + public boolean supports(MethodParameter returnType, Class> converterType) { + return true; + } + + @Override + public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { + if (body instanceof ErrorResponse) { + return ResponseUtil.error((ErrorResponse) body); + } + return ResponseUtil.success(body); + } +} diff --git a/src/main/java/ei/algobaroapi/global/message/ResponseUtil.java b/src/main/java/ei/algobaroapi/global/message/ResponseUtil.java new file mode 100644 index 0000000..8a4e51a --- /dev/null +++ b/src/main/java/ei/algobaroapi/global/message/ResponseUtil.java @@ -0,0 +1,12 @@ +package ei.algobaroapi.global.message; + +public class ResponseUtil { + + public static BasicResponse success(T response) { + return new BasicResponse<>(true, response, null); + } + + public static BasicResponse error(ErrorResponse e) { + return new BasicResponse<>(false, null, e); + } +} \ No newline at end of file From 70b4b09d6a5c16ecaa9acf0ad1bba55c857eb5b7 Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Tue, 13 Feb 2024 13:20:10 +0900 Subject: [PATCH 38/56] =?UTF-8?q?refactor:=20=ED=8C=A8=ED=82=A4=EC=A7=80?= =?UTF-8?q?=EB=AA=85=20=EB=AA=85=ED=99=95=ED=95=98=EA=B2=8C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: kimnamgyu --- .../domain/auth/exception/AuthGlobalExceptionHandler.java | 2 +- .../member/exception/MemberGlobalExceptionHandler.java | 2 +- .../algobaroapi/global/exception/GlobalExceptionHandler.java | 2 +- .../global/{message => response}/ResponseAdvice.java | 3 ++- .../global/{message => response}/ResponseUtil.java | 5 ++++- .../global/{ => response}/message/BasicResponse.java | 2 +- .../global/{ => response}/message/ErrorResponse.java | 2 +- 7 files changed, 11 insertions(+), 7 deletions(-) rename src/main/java/ei/algobaroapi/global/{message => response}/ResponseAdvice.java (91%) rename src/main/java/ei/algobaroapi/global/{message => response}/ResponseUtil.java (62%) rename src/main/java/ei/algobaroapi/global/{ => response}/message/BasicResponse.java (86%) rename src/main/java/ei/algobaroapi/global/{ => response}/message/ErrorResponse.java (88%) diff --git a/src/main/java/ei/algobaroapi/domain/auth/exception/AuthGlobalExceptionHandler.java b/src/main/java/ei/algobaroapi/domain/auth/exception/AuthGlobalExceptionHandler.java index 749bf73..5da9223 100644 --- a/src/main/java/ei/algobaroapi/domain/auth/exception/AuthGlobalExceptionHandler.java +++ b/src/main/java/ei/algobaroapi/domain/auth/exception/AuthGlobalExceptionHandler.java @@ -1,7 +1,7 @@ package ei.algobaroapi.domain.auth.exception; import ei.algobaroapi.domain.auth.exception.umm.AuthPasswordException; -import ei.algobaroapi.global.message.ErrorResponse; +import ei.algobaroapi.global.response.message.ErrorResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ExceptionHandler; diff --git a/src/main/java/ei/algobaroapi/domain/member/exception/MemberGlobalExceptionHandler.java b/src/main/java/ei/algobaroapi/domain/member/exception/MemberGlobalExceptionHandler.java index b4f571d..2fb6906 100644 --- a/src/main/java/ei/algobaroapi/domain/member/exception/MemberGlobalExceptionHandler.java +++ b/src/main/java/ei/algobaroapi/domain/member/exception/MemberGlobalExceptionHandler.java @@ -1,7 +1,7 @@ package ei.algobaroapi.domain.member.exception; import ei.algobaroapi.domain.member.exception.umm.MemberFoundException; -import ei.algobaroapi.global.message.ErrorResponse; +import ei.algobaroapi.global.response.message.ErrorResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ExceptionHandler; diff --git a/src/main/java/ei/algobaroapi/global/exception/GlobalExceptionHandler.java b/src/main/java/ei/algobaroapi/global/exception/GlobalExceptionHandler.java index cf28463..fc9a6a1 100644 --- a/src/main/java/ei/algobaroapi/global/exception/GlobalExceptionHandler.java +++ b/src/main/java/ei/algobaroapi/global/exception/GlobalExceptionHandler.java @@ -1,6 +1,6 @@ package ei.algobaroapi.global.exception; -import ei.algobaroapi.global.message.ErrorResponse; +import ei.algobaroapi.global.response.message.ErrorResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ExceptionHandler; diff --git a/src/main/java/ei/algobaroapi/global/message/ResponseAdvice.java b/src/main/java/ei/algobaroapi/global/response/ResponseAdvice.java similarity index 91% rename from src/main/java/ei/algobaroapi/global/message/ResponseAdvice.java rename to src/main/java/ei/algobaroapi/global/response/ResponseAdvice.java index 8781504..e2e6098 100644 --- a/src/main/java/ei/algobaroapi/global/message/ResponseAdvice.java +++ b/src/main/java/ei/algobaroapi/global/response/ResponseAdvice.java @@ -1,5 +1,6 @@ -package ei.algobaroapi.global.message; +package ei.algobaroapi.global.response; +import ei.algobaroapi.global.response.message.ErrorResponse; import org.springframework.core.MethodParameter; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; diff --git a/src/main/java/ei/algobaroapi/global/message/ResponseUtil.java b/src/main/java/ei/algobaroapi/global/response/ResponseUtil.java similarity index 62% rename from src/main/java/ei/algobaroapi/global/message/ResponseUtil.java rename to src/main/java/ei/algobaroapi/global/response/ResponseUtil.java index 8a4e51a..f8fcb46 100644 --- a/src/main/java/ei/algobaroapi/global/message/ResponseUtil.java +++ b/src/main/java/ei/algobaroapi/global/response/ResponseUtil.java @@ -1,4 +1,7 @@ -package ei.algobaroapi.global.message; +package ei.algobaroapi.global.response; + +import ei.algobaroapi.global.response.message.BasicResponse; +import ei.algobaroapi.global.response.message.ErrorResponse; public class ResponseUtil { diff --git a/src/main/java/ei/algobaroapi/global/message/BasicResponse.java b/src/main/java/ei/algobaroapi/global/response/message/BasicResponse.java similarity index 86% rename from src/main/java/ei/algobaroapi/global/message/BasicResponse.java rename to src/main/java/ei/algobaroapi/global/response/message/BasicResponse.java index a538cda..f7f3946 100644 --- a/src/main/java/ei/algobaroapi/global/message/BasicResponse.java +++ b/src/main/java/ei/algobaroapi/global/response/message/BasicResponse.java @@ -1,4 +1,4 @@ -package ei.algobaroapi.global.message; +package ei.algobaroapi.global.response.message; import com.fasterxml.jackson.annotation.JsonInclude; import lombok.AllArgsConstructor; diff --git a/src/main/java/ei/algobaroapi/global/message/ErrorResponse.java b/src/main/java/ei/algobaroapi/global/response/message/ErrorResponse.java similarity index 88% rename from src/main/java/ei/algobaroapi/global/message/ErrorResponse.java rename to src/main/java/ei/algobaroapi/global/response/message/ErrorResponse.java index f0a3041..a3e5508 100644 --- a/src/main/java/ei/algobaroapi/global/message/ErrorResponse.java +++ b/src/main/java/ei/algobaroapi/global/response/message/ErrorResponse.java @@ -1,4 +1,4 @@ -package ei.algobaroapi.global.message; +package ei.algobaroapi.global.response.message; import lombok.AccessLevel; import lombok.Getter; From 2743f0a6ceb4b514a6fe2a328eb832b990fef502 Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Tue, 13 Feb 2024 13:26:15 +0900 Subject: [PATCH 39/56] =?UTF-8?q?refactor:=20Exception=20=ED=8C=A8?= =?UTF-8?q?=ED=82=A4=EC=A7=80=20=EB=AA=85=ED=99=95=ED=95=98=EA=B2=8C=20?= =?UTF-8?q?=EA=B5=AC=EB=B6=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: kimnamgyu --- .../domain/auth/controller/AuthController.java | 10 +++++----- ...SignInRequest.java => AuthSignInRequest.java} | 2 +- ...gnInResponse.java => AuthSignInResponse.java} | 6 +++--- ...SignUpRequest.java => AuthSignUpRequest.java} | 2 +- .../{umm => }/AuthPasswordException.java | 4 ++-- .../exception/{ => common}/AuthErrorCode.java | 2 +- .../AuthExceptionHandler.java} | 6 +++--- .../domain/auth/service/AuthService.java | 16 ++++++++-------- .../{umm => }/MemberFoundException.java | 4 ++-- .../exception/{ => common}/MemberErrorCode.java | 2 +- .../MemberExceptionHandler.java} | 6 +++--- .../domain/member/service/MemberService.java | 4 ++-- .../config/swaggerdoc/AuthControllerDoc.java | 10 +++++----- 13 files changed, 37 insertions(+), 37 deletions(-) rename src/main/java/ei/algobaroapi/domain/auth/dto/{MemberSignInRequest.java => AuthSignInRequest.java} (78%) rename src/main/java/ei/algobaroapi/domain/auth/dto/{MemberSignInResponse.java => AuthSignInResponse.java} (61%) rename src/main/java/ei/algobaroapi/domain/auth/dto/{MemberSignUpRequest.java => AuthSignUpRequest.java} (92%) rename src/main/java/ei/algobaroapi/domain/auth/exception/{umm => }/AuthPasswordException.java (81%) rename src/main/java/ei/algobaroapi/domain/auth/exception/{ => common}/AuthErrorCode.java (84%) rename src/main/java/ei/algobaroapi/domain/auth/exception/{AuthGlobalExceptionHandler.java => common/AuthExceptionHandler.java} (80%) rename src/main/java/ei/algobaroapi/domain/member/exception/{umm => }/MemberFoundException.java (80%) rename src/main/java/ei/algobaroapi/domain/member/exception/{ => common}/MemberErrorCode.java (83%) rename src/main/java/ei/algobaroapi/domain/member/exception/{MemberGlobalExceptionHandler.java => common/MemberExceptionHandler.java} (80%) diff --git a/src/main/java/ei/algobaroapi/domain/auth/controller/AuthController.java b/src/main/java/ei/algobaroapi/domain/auth/controller/AuthController.java index 16b2e00..72487da 100644 --- a/src/main/java/ei/algobaroapi/domain/auth/controller/AuthController.java +++ b/src/main/java/ei/algobaroapi/domain/auth/controller/AuthController.java @@ -1,9 +1,9 @@ package ei.algobaroapi.domain.auth.controller; -import ei.algobaroapi.domain.auth.dto.MemberSignInResponse; +import ei.algobaroapi.domain.auth.dto.AuthSignInResponse; import ei.algobaroapi.domain.member.domain.Member; -import ei.algobaroapi.domain.auth.dto.MemberSignUpRequest; -import ei.algobaroapi.domain.auth.dto.MemberSignInRequest; +import ei.algobaroapi.domain.auth.dto.AuthSignUpRequest; +import ei.algobaroapi.domain.auth.dto.AuthSignInRequest; import ei.algobaroapi.domain.auth.service.AuthService; import ei.algobaroapi.global.config.swaggerdoc.AuthControllerDoc; import lombok.RequiredArgsConstructor; @@ -19,13 +19,13 @@ public class AuthController implements AuthControllerDoc { @Override @PostMapping("/auth/sign-up") - public void signUp(@RequestBody MemberSignUpRequest request) { + public void signUp(@RequestBody AuthSignUpRequest request) { this.authService.signUp(request); } @Override @PostMapping("/auth/sign-in") - public MemberSignInResponse signIn(@RequestBody MemberSignInRequest request) { + public AuthSignInResponse signIn(@RequestBody AuthSignInRequest request) { return this.authService.signIn(request); } diff --git a/src/main/java/ei/algobaroapi/domain/auth/dto/MemberSignInRequest.java b/src/main/java/ei/algobaroapi/domain/auth/dto/AuthSignInRequest.java similarity index 78% rename from src/main/java/ei/algobaroapi/domain/auth/dto/MemberSignInRequest.java rename to src/main/java/ei/algobaroapi/domain/auth/dto/AuthSignInRequest.java index dac7a2d..6ae32b1 100644 --- a/src/main/java/ei/algobaroapi/domain/auth/dto/MemberSignInRequest.java +++ b/src/main/java/ei/algobaroapi/domain/auth/dto/AuthSignInRequest.java @@ -3,7 +3,7 @@ import lombok.Getter; @Getter -public class MemberSignInRequest { +public class AuthSignInRequest { private String email; private String password; diff --git a/src/main/java/ei/algobaroapi/domain/auth/dto/MemberSignInResponse.java b/src/main/java/ei/algobaroapi/domain/auth/dto/AuthSignInResponse.java similarity index 61% rename from src/main/java/ei/algobaroapi/domain/auth/dto/MemberSignInResponse.java rename to src/main/java/ei/algobaroapi/domain/auth/dto/AuthSignInResponse.java index b181441..6b2fd9f 100644 --- a/src/main/java/ei/algobaroapi/domain/auth/dto/MemberSignInResponse.java +++ b/src/main/java/ei/algobaroapi/domain/auth/dto/AuthSignInResponse.java @@ -6,11 +6,11 @@ @Getter @RequiredArgsConstructor(access = AccessLevel.PRIVATE) -public class MemberSignInResponse { +public class AuthSignInResponse { private final String accessToken; - public static MemberSignInResponse of(String accessToken) { - return new MemberSignInResponse(accessToken); + public static AuthSignInResponse of(String accessToken) { + return new AuthSignInResponse(accessToken); } } diff --git a/src/main/java/ei/algobaroapi/domain/auth/dto/MemberSignUpRequest.java b/src/main/java/ei/algobaroapi/domain/auth/dto/AuthSignUpRequest.java similarity index 92% rename from src/main/java/ei/algobaroapi/domain/auth/dto/MemberSignUpRequest.java rename to src/main/java/ei/algobaroapi/domain/auth/dto/AuthSignUpRequest.java index 0176ec8..393ac58 100644 --- a/src/main/java/ei/algobaroapi/domain/auth/dto/MemberSignUpRequest.java +++ b/src/main/java/ei/algobaroapi/domain/auth/dto/AuthSignUpRequest.java @@ -6,7 +6,7 @@ @Getter @Builder -public class MemberSignUpRequest { +public class AuthSignUpRequest { private String email; private String password; diff --git a/src/main/java/ei/algobaroapi/domain/auth/exception/umm/AuthPasswordException.java b/src/main/java/ei/algobaroapi/domain/auth/exception/AuthPasswordException.java similarity index 81% rename from src/main/java/ei/algobaroapi/domain/auth/exception/umm/AuthPasswordException.java rename to src/main/java/ei/algobaroapi/domain/auth/exception/AuthPasswordException.java index 87ccfe7..617bc8b 100644 --- a/src/main/java/ei/algobaroapi/domain/auth/exception/umm/AuthPasswordException.java +++ b/src/main/java/ei/algobaroapi/domain/auth/exception/AuthPasswordException.java @@ -1,6 +1,6 @@ -package ei.algobaroapi.domain.auth.exception.umm; +package ei.algobaroapi.domain.auth.exception; -import ei.algobaroapi.domain.auth.exception.AuthErrorCode; +import ei.algobaroapi.domain.auth.exception.common.AuthErrorCode; import lombok.Getter; @Getter diff --git a/src/main/java/ei/algobaroapi/domain/auth/exception/AuthErrorCode.java b/src/main/java/ei/algobaroapi/domain/auth/exception/common/AuthErrorCode.java similarity index 84% rename from src/main/java/ei/algobaroapi/domain/auth/exception/AuthErrorCode.java rename to src/main/java/ei/algobaroapi/domain/auth/exception/common/AuthErrorCode.java index 7839349..3b2d171 100644 --- a/src/main/java/ei/algobaroapi/domain/auth/exception/AuthErrorCode.java +++ b/src/main/java/ei/algobaroapi/domain/auth/exception/common/AuthErrorCode.java @@ -1,4 +1,4 @@ -package ei.algobaroapi.domain.auth.exception; +package ei.algobaroapi.domain.auth.exception.common; import lombok.Getter; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/ei/algobaroapi/domain/auth/exception/AuthGlobalExceptionHandler.java b/src/main/java/ei/algobaroapi/domain/auth/exception/common/AuthExceptionHandler.java similarity index 80% rename from src/main/java/ei/algobaroapi/domain/auth/exception/AuthGlobalExceptionHandler.java rename to src/main/java/ei/algobaroapi/domain/auth/exception/common/AuthExceptionHandler.java index 5da9223..c76c0c6 100644 --- a/src/main/java/ei/algobaroapi/domain/auth/exception/AuthGlobalExceptionHandler.java +++ b/src/main/java/ei/algobaroapi/domain/auth/exception/common/AuthExceptionHandler.java @@ -1,6 +1,6 @@ -package ei.algobaroapi.domain.auth.exception; +package ei.algobaroapi.domain.auth.exception.common; -import ei.algobaroapi.domain.auth.exception.umm.AuthPasswordException; +import ei.algobaroapi.domain.auth.exception.AuthPasswordException; import ei.algobaroapi.global.response.message.ErrorResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; @@ -10,7 +10,7 @@ @Slf4j @RestControllerAdvice -public class AuthGlobalExceptionHandler { +public class AuthExceptionHandler { @ExceptionHandler(AuthPasswordException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) diff --git a/src/main/java/ei/algobaroapi/domain/auth/service/AuthService.java b/src/main/java/ei/algobaroapi/domain/auth/service/AuthService.java index 10bda73..c4a5e6f 100644 --- a/src/main/java/ei/algobaroapi/domain/auth/service/AuthService.java +++ b/src/main/java/ei/algobaroapi/domain/auth/service/AuthService.java @@ -1,10 +1,10 @@ package ei.algobaroapi.domain.auth.service; -import ei.algobaroapi.domain.auth.dto.MemberSignInRequest; -import ei.algobaroapi.domain.auth.dto.MemberSignInResponse; -import ei.algobaroapi.domain.auth.dto.MemberSignUpRequest; -import ei.algobaroapi.domain.auth.exception.AuthErrorCode; -import ei.algobaroapi.domain.auth.exception.umm.AuthPasswordException; +import ei.algobaroapi.domain.auth.dto.AuthSignInRequest; +import ei.algobaroapi.domain.auth.dto.AuthSignInResponse; +import ei.algobaroapi.domain.auth.dto.AuthSignUpRequest; +import ei.algobaroapi.domain.auth.exception.common.AuthErrorCode; +import ei.algobaroapi.domain.auth.exception.AuthPasswordException; import ei.algobaroapi.domain.auth.util.PasswordUtil; import ei.algobaroapi.domain.member.domain.Member; import ei.algobaroapi.domain.member.service.MemberService; @@ -23,13 +23,13 @@ public class AuthService { private final PasswordUtil passwordUtil; @Transactional - public void signUp(MemberSignUpRequest request) { + public void signUp(AuthSignUpRequest request) { String encryptPassword = passwordUtil.validateAndEncryptPassword(request.getPassword()); memberService.addMember(request.toEntity(encryptPassword)); } @Transactional - public MemberSignInResponse signIn(MemberSignInRequest request) { + public AuthSignInResponse signIn(AuthSignInRequest request) { Member member = memberService.getMemberByEmail(request.getEmail()); if (!passwordUtil.isPasswordMatch(request.getPassword(), member.getPassword())) { throw AuthPasswordException.of(AuthErrorCode.PASSWORD_NOT_MATCH); @@ -37,6 +37,6 @@ public MemberSignInResponse signIn(MemberSignInRequest request) { String accessToken = jwtProvider.generateToken(member.getUsername(), member.getRoles()); - return MemberSignInResponse.of(accessToken); + return AuthSignInResponse.of(accessToken); } } diff --git a/src/main/java/ei/algobaroapi/domain/member/exception/umm/MemberFoundException.java b/src/main/java/ei/algobaroapi/domain/member/exception/MemberFoundException.java similarity index 80% rename from src/main/java/ei/algobaroapi/domain/member/exception/umm/MemberFoundException.java rename to src/main/java/ei/algobaroapi/domain/member/exception/MemberFoundException.java index cd73daf..2079087 100644 --- a/src/main/java/ei/algobaroapi/domain/member/exception/umm/MemberFoundException.java +++ b/src/main/java/ei/algobaroapi/domain/member/exception/MemberFoundException.java @@ -1,6 +1,6 @@ -package ei.algobaroapi.domain.member.exception.umm; +package ei.algobaroapi.domain.member.exception; -import ei.algobaroapi.domain.member.exception.MemberErrorCode; +import ei.algobaroapi.domain.member.exception.common.MemberErrorCode; import lombok.Getter; @Getter diff --git a/src/main/java/ei/algobaroapi/domain/member/exception/MemberErrorCode.java b/src/main/java/ei/algobaroapi/domain/member/exception/common/MemberErrorCode.java similarity index 83% rename from src/main/java/ei/algobaroapi/domain/member/exception/MemberErrorCode.java rename to src/main/java/ei/algobaroapi/domain/member/exception/common/MemberErrorCode.java index 6bee828..b58f1f4 100644 --- a/src/main/java/ei/algobaroapi/domain/member/exception/MemberErrorCode.java +++ b/src/main/java/ei/algobaroapi/domain/member/exception/common/MemberErrorCode.java @@ -1,4 +1,4 @@ -package ei.algobaroapi.domain.member.exception; +package ei.algobaroapi.domain.member.exception.common; import lombok.Getter; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/ei/algobaroapi/domain/member/exception/MemberGlobalExceptionHandler.java b/src/main/java/ei/algobaroapi/domain/member/exception/common/MemberExceptionHandler.java similarity index 80% rename from src/main/java/ei/algobaroapi/domain/member/exception/MemberGlobalExceptionHandler.java rename to src/main/java/ei/algobaroapi/domain/member/exception/common/MemberExceptionHandler.java index 2fb6906..2faec5d 100644 --- a/src/main/java/ei/algobaroapi/domain/member/exception/MemberGlobalExceptionHandler.java +++ b/src/main/java/ei/algobaroapi/domain/member/exception/common/MemberExceptionHandler.java @@ -1,6 +1,6 @@ -package ei.algobaroapi.domain.member.exception; +package ei.algobaroapi.domain.member.exception.common; -import ei.algobaroapi.domain.member.exception.umm.MemberFoundException; +import ei.algobaroapi.domain.member.exception.MemberFoundException; import ei.algobaroapi.global.response.message.ErrorResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; @@ -10,7 +10,7 @@ @Slf4j @RestControllerAdvice -public class MemberGlobalExceptionHandler { +public class MemberExceptionHandler { @ExceptionHandler(MemberFoundException.class) @ResponseStatus(HttpStatus.NOT_FOUND) diff --git a/src/main/java/ei/algobaroapi/domain/member/service/MemberService.java b/src/main/java/ei/algobaroapi/domain/member/service/MemberService.java index 646a6b8..6e7561f 100644 --- a/src/main/java/ei/algobaroapi/domain/member/service/MemberService.java +++ b/src/main/java/ei/algobaroapi/domain/member/service/MemberService.java @@ -3,8 +3,8 @@ import ei.algobaroapi.domain.member.domain.Member; import ei.algobaroapi.domain.member.domain.MemberRepository; import ei.algobaroapi.domain.member.domain.vo.EmailVo; -import ei.algobaroapi.domain.member.exception.MemberErrorCode; -import ei.algobaroapi.domain.member.exception.umm.MemberFoundException; +import ei.algobaroapi.domain.member.exception.common.MemberErrorCode; +import ei.algobaroapi.domain.member.exception.MemberFoundException; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; diff --git a/src/main/java/ei/algobaroapi/global/config/swaggerdoc/AuthControllerDoc.java b/src/main/java/ei/algobaroapi/global/config/swaggerdoc/AuthControllerDoc.java index 42b93ee..8f1859a 100644 --- a/src/main/java/ei/algobaroapi/global/config/swaggerdoc/AuthControllerDoc.java +++ b/src/main/java/ei/algobaroapi/global/config/swaggerdoc/AuthControllerDoc.java @@ -1,9 +1,9 @@ package ei.algobaroapi.global.config.swaggerdoc; -import ei.algobaroapi.domain.auth.dto.MemberSignInResponse; +import ei.algobaroapi.domain.auth.dto.AuthSignInResponse; import ei.algobaroapi.domain.member.domain.Member; -import ei.algobaroapi.domain.auth.dto.MemberSignInRequest; -import ei.algobaroapi.domain.auth.dto.MemberSignUpRequest; +import ei.algobaroapi.domain.auth.dto.AuthSignInRequest; +import ei.algobaroapi.domain.auth.dto.AuthSignUpRequest; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.security.core.annotation.AuthenticationPrincipal; @@ -14,10 +14,10 @@ public interface AuthControllerDoc { @Operation(summary = "회원 가입", description = "회원가입을 합니다.") - void signUp(@RequestBody MemberSignUpRequest request); + void signUp(@RequestBody AuthSignUpRequest request); @Operation(summary = "로그인", description = "이메일, 비밀번호로 로그인을 합니다.") - MemberSignInResponse signIn(@RequestBody MemberSignInRequest request); + AuthSignInResponse signIn(@RequestBody AuthSignInRequest request); @Operation(summary = "테스트", description = "테스트용 API") String hello(@AuthenticationPrincipal Member member); From f5d8f27a78401e5f9b656f5221743a702c61db30 Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Tue, 13 Feb 2024 13:28:17 +0900 Subject: [PATCH 40/56] =?UTF-8?q?refactor:=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=EB=AA=85=20=EB=AA=85=ED=99=95=ED=95=98=EA=B2=8C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: kimnamgyu --- .../algobaroapi/global/jwt/JwtProvider.java | 26 +++++++------------ 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/src/main/java/ei/algobaroapi/global/jwt/JwtProvider.java b/src/main/java/ei/algobaroapi/global/jwt/JwtProvider.java index 64cdea5..347ef7a 100644 --- a/src/main/java/ei/algobaroapi/global/jwt/JwtProvider.java +++ b/src/main/java/ei/algobaroapi/global/jwt/JwtProvider.java @@ -1,17 +1,7 @@ package ei.algobaroapi.global.jwt; -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.ExpiredJwtException; -import io.jsonwebtoken.Jws; -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.MalformedJwtException; -import io.jsonwebtoken.SignatureAlgorithm; -import io.jsonwebtoken.UnsupportedJwtException; +import io.jsonwebtoken.*; import io.jsonwebtoken.security.Keys; -import java.nio.charset.StandardCharsets; -import java.security.Key; -import java.util.Date; -import java.util.List; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; @@ -20,6 +10,11 @@ import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.stereotype.Component; +import java.nio.charset.StandardCharsets; +import java.security.Key; +import java.util.Date; +import java.util.List; + @Slf4j @Component public class JwtProvider { @@ -29,12 +24,11 @@ public class JwtProvider { private final UserDetailsService userDetailsService; public JwtProvider(@Value("${JWT_KEY}") String secretKey, - UserDetailsService userDetailsService) { + UserDetailsService userDetailsService) { this.secretKey = Keys.hmacShaKeyFor(secretKey.getBytes(StandardCharsets.UTF_8)); this.userDetailsService = userDetailsService; } - // 사용자 정보 기반 JWT 토큰 생성 public String generateToken(String userId, List roles) { Claims claims = Jwts.claims().setSubject(userId); claims.put("roles", roles); @@ -51,12 +45,11 @@ public String generateToken(String userId, List roles) { public Authentication getAuthentication(String accessToken) { UserDetails userDetails = userDetailsService.loadUserByUsername( - this.getUserId(accessToken)); + this.getUserEmailByToken(accessToken)); return new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities()); } - // 토큰 유효성 검사 public boolean validateToken(String token) { try { Jws claims = Jwts.parserBuilder() @@ -76,8 +69,7 @@ public boolean validateToken(String token) { return false; } - // 토큰에서 userId 값 반환 - private String getUserId(String token) { + private String getUserEmailByToken(String token) { return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody().getSubject(); } } From f2ef421bf24cd428bd77c37ca641e4cd3a582fe5 Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Tue, 13 Feb 2024 13:28:45 +0900 Subject: [PATCH 41/56] refactor: Reformat Code Co-authored-by: kimnamgyu --- .../ei/algobaroapi/domain/auth/controller/AuthController.java | 4 ++-- .../java/ei/algobaroapi/domain/auth/service/AuthService.java | 2 +- .../ei/algobaroapi/domain/member/service/MemberService.java | 2 +- .../java/ei/algobaroapi/global/config/WebSecurityConfig.java | 3 ++- .../global/config/swaggerdoc/AuthControllerDoc.java | 4 ++-- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/main/java/ei/algobaroapi/domain/auth/controller/AuthController.java b/src/main/java/ei/algobaroapi/domain/auth/controller/AuthController.java index 72487da..4f6c50c 100644 --- a/src/main/java/ei/algobaroapi/domain/auth/controller/AuthController.java +++ b/src/main/java/ei/algobaroapi/domain/auth/controller/AuthController.java @@ -1,10 +1,10 @@ package ei.algobaroapi.domain.auth.controller; +import ei.algobaroapi.domain.auth.dto.AuthSignInRequest; import ei.algobaroapi.domain.auth.dto.AuthSignInResponse; -import ei.algobaroapi.domain.member.domain.Member; import ei.algobaroapi.domain.auth.dto.AuthSignUpRequest; -import ei.algobaroapi.domain.auth.dto.AuthSignInRequest; import ei.algobaroapi.domain.auth.service.AuthService; +import ei.algobaroapi.domain.member.domain.Member; import ei.algobaroapi.global.config.swaggerdoc.AuthControllerDoc; import lombok.RequiredArgsConstructor; import org.springframework.security.core.annotation.AuthenticationPrincipal; diff --git a/src/main/java/ei/algobaroapi/domain/auth/service/AuthService.java b/src/main/java/ei/algobaroapi/domain/auth/service/AuthService.java index c4a5e6f..1b12317 100644 --- a/src/main/java/ei/algobaroapi/domain/auth/service/AuthService.java +++ b/src/main/java/ei/algobaroapi/domain/auth/service/AuthService.java @@ -3,8 +3,8 @@ import ei.algobaroapi.domain.auth.dto.AuthSignInRequest; import ei.algobaroapi.domain.auth.dto.AuthSignInResponse; import ei.algobaroapi.domain.auth.dto.AuthSignUpRequest; -import ei.algobaroapi.domain.auth.exception.common.AuthErrorCode; import ei.algobaroapi.domain.auth.exception.AuthPasswordException; +import ei.algobaroapi.domain.auth.exception.common.AuthErrorCode; import ei.algobaroapi.domain.auth.util.PasswordUtil; import ei.algobaroapi.domain.member.domain.Member; import ei.algobaroapi.domain.member.service.MemberService; diff --git a/src/main/java/ei/algobaroapi/domain/member/service/MemberService.java b/src/main/java/ei/algobaroapi/domain/member/service/MemberService.java index 6e7561f..605d780 100644 --- a/src/main/java/ei/algobaroapi/domain/member/service/MemberService.java +++ b/src/main/java/ei/algobaroapi/domain/member/service/MemberService.java @@ -3,8 +3,8 @@ import ei.algobaroapi.domain.member.domain.Member; import ei.algobaroapi.domain.member.domain.MemberRepository; import ei.algobaroapi.domain.member.domain.vo.EmailVo; -import ei.algobaroapi.domain.member.exception.common.MemberErrorCode; import ei.algobaroapi.domain.member.exception.MemberFoundException; +import ei.algobaroapi.domain.member.exception.common.MemberErrorCode; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; diff --git a/src/main/java/ei/algobaroapi/global/config/WebSecurityConfig.java b/src/main/java/ei/algobaroapi/global/config/WebSecurityConfig.java index 5befbf6..b34abd3 100644 --- a/src/main/java/ei/algobaroapi/global/config/WebSecurityConfig.java +++ b/src/main/java/ei/algobaroapi/global/config/WebSecurityConfig.java @@ -2,7 +2,6 @@ import ei.algobaroapi.global.jwt.JwtAuthenticationFilter; import ei.algobaroapi.global.jwt.JwtProvider; -import java.util.List; import lombok.AccessLevel; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; @@ -17,6 +16,8 @@ import org.springframework.web.cors.CorsConfigurationSource; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import java.util.List; + @Configuration @RequiredArgsConstructor(access = AccessLevel.PROTECTED) public class WebSecurityConfig { diff --git a/src/main/java/ei/algobaroapi/global/config/swaggerdoc/AuthControllerDoc.java b/src/main/java/ei/algobaroapi/global/config/swaggerdoc/AuthControllerDoc.java index 8f1859a..1aa7c6b 100644 --- a/src/main/java/ei/algobaroapi/global/config/swaggerdoc/AuthControllerDoc.java +++ b/src/main/java/ei/algobaroapi/global/config/swaggerdoc/AuthControllerDoc.java @@ -1,9 +1,9 @@ package ei.algobaroapi.global.config.swaggerdoc; -import ei.algobaroapi.domain.auth.dto.AuthSignInResponse; -import ei.algobaroapi.domain.member.domain.Member; import ei.algobaroapi.domain.auth.dto.AuthSignInRequest; +import ei.algobaroapi.domain.auth.dto.AuthSignInResponse; import ei.algobaroapi.domain.auth.dto.AuthSignUpRequest; +import ei.algobaroapi.domain.member.domain.Member; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.security.core.annotation.AuthenticationPrincipal; From e9712941eb6ebdbe9e77f5014f9e6fee4e9ed80e Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Tue, 13 Feb 2024 13:49:01 +0900 Subject: [PATCH 42/56] =?UTF-8?q?refactor:=20google=20style=20guide=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: kimnamgyu --- .../auth/controller/AuthController.java | 6 +++++- .../domain/member/domain/Member.java | 15 +++++++++++---- .../member/domain/MemberRepository.java | 3 +-- .../global/config/WebSecurityConfig.java | 3 +-- .../algobaroapi/global/entity/BaseEntity.java | 7 ++++--- .../global/jwt/JwtAuthenticationFilter.java | 6 +++--- .../algobaroapi/global/jwt/JwtProvider.java | 19 ++++++++++++------- .../global/jwt/UserDetailServiceImpl.java | 3 ++- .../global/response/ResponseAdvice.java | 8 ++++++-- 9 files changed, 45 insertions(+), 25 deletions(-) diff --git a/src/main/java/ei/algobaroapi/domain/auth/controller/AuthController.java b/src/main/java/ei/algobaroapi/domain/auth/controller/AuthController.java index 4f6c50c..6305a21 100644 --- a/src/main/java/ei/algobaroapi/domain/auth/controller/AuthController.java +++ b/src/main/java/ei/algobaroapi/domain/auth/controller/AuthController.java @@ -8,7 +8,11 @@ import ei.algobaroapi.global.config.swaggerdoc.AuthControllerDoc; import lombok.RequiredArgsConstructor; import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.GetMapping; +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 @RequiredArgsConstructor diff --git a/src/main/java/ei/algobaroapi/domain/member/domain/Member.java b/src/main/java/ei/algobaroapi/domain/member/domain/Member.java index 2da07ab..430b2a3 100644 --- a/src/main/java/ei/algobaroapi/domain/member/domain/Member.java +++ b/src/main/java/ei/algobaroapi/domain/member/domain/Member.java @@ -2,7 +2,17 @@ import ei.algobaroapi.domain.member.domain.vo.EmailVo; import ei.algobaroapi.global.entity.BaseEntity; -import jakarta.persistence.*; +import jakarta.persistence.Column; +import jakarta.persistence.ElementCollection; +import jakarta.persistence.Embedded; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import java.util.Collection; +import java.util.List; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; @@ -11,9 +21,6 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; -import java.util.Collection; -import java.util.List; - @Getter @Entity @Table(name = "members") diff --git a/src/main/java/ei/algobaroapi/domain/member/domain/MemberRepository.java b/src/main/java/ei/algobaroapi/domain/member/domain/MemberRepository.java index a18de0b..f774c23 100644 --- a/src/main/java/ei/algobaroapi/domain/member/domain/MemberRepository.java +++ b/src/main/java/ei/algobaroapi/domain/member/domain/MemberRepository.java @@ -1,12 +1,11 @@ package ei.algobaroapi.domain.member.domain; import ei.algobaroapi.domain.member.domain.vo.EmailVo; +import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; -import java.util.Optional; - @Repository public interface MemberRepository extends JpaRepository { diff --git a/src/main/java/ei/algobaroapi/global/config/WebSecurityConfig.java b/src/main/java/ei/algobaroapi/global/config/WebSecurityConfig.java index b34abd3..5befbf6 100644 --- a/src/main/java/ei/algobaroapi/global/config/WebSecurityConfig.java +++ b/src/main/java/ei/algobaroapi/global/config/WebSecurityConfig.java @@ -2,6 +2,7 @@ import ei.algobaroapi.global.jwt.JwtAuthenticationFilter; import ei.algobaroapi.global.jwt.JwtProvider; +import java.util.List; import lombok.AccessLevel; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; @@ -16,8 +17,6 @@ import org.springframework.web.cors.CorsConfigurationSource; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; -import java.util.List; - @Configuration @RequiredArgsConstructor(access = AccessLevel.PROTECTED) public class WebSecurityConfig { diff --git a/src/main/java/ei/algobaroapi/global/entity/BaseEntity.java b/src/main/java/ei/algobaroapi/global/entity/BaseEntity.java index b9dc0d5..ed63d5f 100644 --- a/src/main/java/ei/algobaroapi/global/entity/BaseEntity.java +++ b/src/main/java/ei/algobaroapi/global/entity/BaseEntity.java @@ -2,9 +2,8 @@ import jakarta.persistence.Column; import jakarta.persistence.MappedSuperclass; -import lombok.Getter; - import java.time.LocalDateTime; +import lombok.Getter; @Getter @MappedSuperclass @@ -33,7 +32,9 @@ protected void update() { } protected void delete() { - if (isDeleted()) throw new IllegalArgumentException("이미 삭제된 엔티티 입니다."); + if (isDeleted()) { + throw new IllegalArgumentException("이미 삭제된 엔티티 입니다."); + } this.deletedAt = LocalDateTime.now(); } } diff --git a/src/main/java/ei/algobaroapi/global/jwt/JwtAuthenticationFilter.java b/src/main/java/ei/algobaroapi/global/jwt/JwtAuthenticationFilter.java index 7f83d9c..616f020 100644 --- a/src/main/java/ei/algobaroapi/global/jwt/JwtAuthenticationFilter.java +++ b/src/main/java/ei/algobaroapi/global/jwt/JwtAuthenticationFilter.java @@ -5,14 +5,13 @@ import jakarta.servlet.ServletRequest; import jakarta.servlet.ServletResponse; import jakarta.servlet.http.HttpServletRequest; +import java.io.IOException; import lombok.RequiredArgsConstructor; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.util.StringUtils; import org.springframework.web.filter.GenericFilterBean; -import java.io.IOException; - @RequiredArgsConstructor public class JwtAuthenticationFilter extends GenericFilterBean { @@ -21,7 +20,8 @@ public class JwtAuthenticationFilter extends GenericFilterBean { private final JwtProvider jwtTokenProvider; @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { String token = resolveToken((HttpServletRequest) request); if (token != null && jwtTokenProvider.validateToken(token)) { diff --git a/src/main/java/ei/algobaroapi/global/jwt/JwtProvider.java b/src/main/java/ei/algobaroapi/global/jwt/JwtProvider.java index 347ef7a..187aa7a 100644 --- a/src/main/java/ei/algobaroapi/global/jwt/JwtProvider.java +++ b/src/main/java/ei/algobaroapi/global/jwt/JwtProvider.java @@ -1,7 +1,17 @@ package ei.algobaroapi.global.jwt; -import io.jsonwebtoken.*; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.ExpiredJwtException; +import io.jsonwebtoken.Jws; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.MalformedJwtException; +import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.UnsupportedJwtException; import io.jsonwebtoken.security.Keys; +import java.nio.charset.StandardCharsets; +import java.security.Key; +import java.util.Date; +import java.util.List; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; @@ -10,11 +20,6 @@ import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.stereotype.Component; -import java.nio.charset.StandardCharsets; -import java.security.Key; -import java.util.Date; -import java.util.List; - @Slf4j @Component public class JwtProvider { @@ -24,7 +29,7 @@ public class JwtProvider { private final UserDetailsService userDetailsService; public JwtProvider(@Value("${JWT_KEY}") String secretKey, - UserDetailsService userDetailsService) { + UserDetailsService userDetailsService) { this.secretKey = Keys.hmacShaKeyFor(secretKey.getBytes(StandardCharsets.UTF_8)); this.userDetailsService = userDetailsService; } diff --git a/src/main/java/ei/algobaroapi/global/jwt/UserDetailServiceImpl.java b/src/main/java/ei/algobaroapi/global/jwt/UserDetailServiceImpl.java index c164aa4..ffd110c 100644 --- a/src/main/java/ei/algobaroapi/global/jwt/UserDetailServiceImpl.java +++ b/src/main/java/ei/algobaroapi/global/jwt/UserDetailServiceImpl.java @@ -17,6 +17,7 @@ public class UserDetailServiceImpl implements UserDetailsService { @Override public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException { return memberRepository.findByEmailAndDeletedAtIsNull(new EmailVo(email)) - .orElseThrow(() -> new UsernameNotFoundException("User not found with email: " + email)); + .orElseThrow( + () -> new UsernameNotFoundException("User not found with email: " + email)); } } diff --git a/src/main/java/ei/algobaroapi/global/response/ResponseAdvice.java b/src/main/java/ei/algobaroapi/global/response/ResponseAdvice.java index e2e6098..554538d 100644 --- a/src/main/java/ei/algobaroapi/global/response/ResponseAdvice.java +++ b/src/main/java/ei/algobaroapi/global/response/ResponseAdvice.java @@ -13,12 +13,16 @@ public class ResponseAdvice implements ResponseBodyAdvice { @Override - public boolean supports(MethodParameter returnType, Class> converterType) { + public boolean supports(MethodParameter returnType, + Class> converterType) { return true; } @Override - public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { + public Object beforeBodyWrite(Object body, MethodParameter returnType, + MediaType selectedContentType, + Class> selectedConverterType, + ServerHttpRequest request, ServerHttpResponse response) { if (body instanceof ErrorResponse) { return ResponseUtil.error((ErrorResponse) body); } From 0b07ded297b1d11e1b7b295fa8b335023fa3b0c3 Mon Sep 17 00:00:00 2001 From: NamGyu Kim Date: Wed, 14 Feb 2024 09:39:41 +0900 Subject: [PATCH 43/56] =?UTF-8?q?docs:=20issue=20template=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/ISSUE_TEMPLATE/feat.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/feat.md diff --git a/.github/ISSUE_TEMPLATE/feat.md b/.github/ISSUE_TEMPLATE/feat.md new file mode 100644 index 0000000..518d8dd --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feat.md @@ -0,0 +1,18 @@ +--- +name: feat +about: 기능 개발 이슈 템플릿 +title: "[Feat]" +labels: feat +assignees: '' + +--- + +## 어떤 기능인가요? + +> 추가하려는 기능에 대해 간결하게 설명해주세요 + +## 작업 상세 내용 + +- [ ] TODO + +## 참고할만한 자료(선택) From 023352f47a5adc3e678b7eb4dfa581e9d7d51db3 Mon Sep 17 00:00:00 2001 From: NamGyu Kim Date: Wed, 14 Feb 2024 09:45:12 +0900 Subject: [PATCH 44/56] =?UTF-8?q?docs:=20bug,=20etc=20=EC=9D=B4=EC=8A=88?= =?UTF-8?q?=20=ED=85=9C=ED=94=8C=EB=A6=BF=20=EC=9E=91=EC=84=B1=20=EB=B0=8F?= =?UTF-8?q?=20feat=20=ED=85=9C=ED=94=8C=EB=A6=BF=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/ISSUE_TEMPLATE/-etc.md | 14 ++++++++++++++ .github/ISSUE_TEMPLATE/bug.md | 22 ++++++++++++++++++++++ .github/ISSUE_TEMPLATE/feat.md | 2 +- 3 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 .github/ISSUE_TEMPLATE/-etc.md create mode 100644 .github/ISSUE_TEMPLATE/bug.md diff --git a/.github/ISSUE_TEMPLATE/-etc.md b/.github/ISSUE_TEMPLATE/-etc.md new file mode 100644 index 0000000..3d6d830 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/-etc.md @@ -0,0 +1,14 @@ +--- +name: "\betc" +about: 기타 이슈 템플릿 +title: '' +labels: '' +assignees: '' + +--- + +## 어떤 이슈인가요? + +> 해당 이슈에 대해 간단히 서술해주세요 + +## 참고할만한 자료(선택) diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md new file mode 100644 index 0000000..4bf3c7f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug.md @@ -0,0 +1,22 @@ +--- +name: bug +about: 버그 관련 이슈 템플릿 +title: '' +labels: bug +assignees: '' + +--- + +## 어떤 버그인가요? + +> 어떤 버그인지 간결하게 설명해주세요 + +## 어떤 상황에서 발생한 버그인가요? + +> (가능하면) Given-When-Then 형식으로 서술해주세요 + +## 예상 결과 + +> 예상했던 정상적인 결과가 어떤 것이었는지 설명해주세요 + +## 참고할만한 자료(선택) diff --git a/.github/ISSUE_TEMPLATE/feat.md b/.github/ISSUE_TEMPLATE/feat.md index 518d8dd..05910b4 100644 --- a/.github/ISSUE_TEMPLATE/feat.md +++ b/.github/ISSUE_TEMPLATE/feat.md @@ -1,7 +1,7 @@ --- name: feat about: 기능 개발 이슈 템플릿 -title: "[Feat]" +title: '' labels: feat assignees: '' From 93e680902ee20e95ff724e170f7c6d791985a9e5 Mon Sep 17 00:00:00 2001 From: NamGyu Kim Date: Wed, 14 Feb 2024 09:52:25 +0900 Subject: [PATCH 45/56] =?UTF-8?q?=08docs:=20Pull=20Request=20Template=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/PULL_REQUEST_TEMPLATE.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .github/PULL_REQUEST_TEMPLATE.md diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..b56ea85 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,18 @@ +## 🧙 PR 타입 +- [ ] 기능 추가 +- [ ] 기능 삭제 +- [ ] 버그 수정 +- [ ] 의존성, 환경 변수, 빌드 관련 코드 업데이트 + +## #️⃣연관 이슈 + +> ex) #이슈번호 + +## 📝작업 내용 + +> 이번 PR에서 작업한 내용을 간략히 설명해주세요 + +## 💬리뷰 시 요구사항 (선택) + +> 리뷰어가 특별히 봐주었으면 하는 부분이 있다면 작성해주세요 +> From 2422513f6a09b3d460409e3439fdb214fd558cc2 Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Wed, 14 Feb 2024 10:41:51 +0900 Subject: [PATCH 46/56] =?UTF-8?q?fix:=20swagger=20json=20=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=20=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ei/algobaroapi/global/response/ResponseAdvice.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/ei/algobaroapi/global/response/ResponseAdvice.java b/src/main/java/ei/algobaroapi/global/response/ResponseAdvice.java index 554538d..6dcb7e8 100644 --- a/src/main/java/ei/algobaroapi/global/response/ResponseAdvice.java +++ b/src/main/java/ei/algobaroapi/global/response/ResponseAdvice.java @@ -1,6 +1,7 @@ package ei.algobaroapi.global.response; import ei.algobaroapi.global.response.message.ErrorResponse; +import org.springframework.beans.factory.annotation.Value; import org.springframework.core.MethodParameter; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; @@ -12,6 +13,9 @@ @RestControllerAdvice public class ResponseAdvice implements ResponseBodyAdvice { + @Value("${springdoc.api-docs.path}") + private String apiDocsPath; + @Override public boolean supports(MethodParameter returnType, Class> converterType) { @@ -26,6 +30,9 @@ public Object beforeBodyWrite(Object body, MethodParameter returnType, if (body instanceof ErrorResponse) { return ResponseUtil.error((ErrorResponse) body); } + if (request.getURI().getPath().contains(apiDocsPath)) { + return body; + } return ResponseUtil.success(body); } } From be6faeb0e51dab17358b38499d21760a69874ffe Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Wed, 14 Feb 2024 10:42:09 +0900 Subject: [PATCH 47/56] =?UTF-8?q?chore:=20=ED=8C=8C=EC=9D=BC=20=EB=A7=88?= =?UTF-8?q?=EC=A7=80=EB=A7=89=20=EC=A4=84=20=EA=B0=9C=ED=96=89=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/ei/algobaroapi/global/response/ResponseUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/ei/algobaroapi/global/response/ResponseUtil.java b/src/main/java/ei/algobaroapi/global/response/ResponseUtil.java index f8fcb46..790fb9b 100644 --- a/src/main/java/ei/algobaroapi/global/response/ResponseUtil.java +++ b/src/main/java/ei/algobaroapi/global/response/ResponseUtil.java @@ -12,4 +12,4 @@ public static BasicResponse success(T response) { public static BasicResponse error(ErrorResponse e) { return new BasicResponse<>(false, null, e); } -} \ No newline at end of file +} From 2cbf6c21ebf120fae5e67b371f1ac72377998bd0 Mon Sep 17 00:00:00 2001 From: NamGyu Kim Date: Wed, 14 Feb 2024 12:07:00 +0900 Subject: [PATCH 48/56] =?UTF-8?q?infra:=20CI=20=EC=84=B8=ED=8C=85=20(#2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/gradle.yml | 67 ++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 .github/workflows/gradle.yml diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml new file mode 100644 index 0000000..27ac457 --- /dev/null +++ b/.github/workflows/gradle.yml @@ -0,0 +1,67 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. +# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle + +name: Java CI with Gradle + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + build: + + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - uses: actions/checkout@v4 + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + + # Configure Gradle for optimal use in GiHub Actions, including caching of downloaded dependencies. + # See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md + - name: Setup Gradle + uses: gradle/actions/setup-gradle@ec92e829475ac0c2315ea8f9eced72db85bb337a # v3.0.0 + + - name: Build with Gradle Wrapper + run: ./gradlew build + + # NOTE: The Gradle Wrapper is the default and recommended way to run Gradle (https://docs.gradle.org/current/userguide/gradle_wrapper.html). + # If your project does not have the Gradle Wrapper configured, you can use the following configuration to run Gradle with a specified version. + # + # - name: Setup Gradle + # uses: gradle/actions/setup-gradle@ec92e829475ac0c2315ea8f9eced72db85bb337a # v3.0.0 + # with: + # gradle-version: '8.5' + # + # - name: Build with Gradle 8.5 + # run: gradle build + + dependency-submission: + + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - uses: actions/checkout@v4 + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + + # Generates and submits a dependency graph, enabling Dependabot Alerts for all project dependencies. + # See: https://github.com/gradle/actions/blob/main/dependency-submission/README.md + - name: Generate and submit dependency graph + uses: gradle/actions/dependency-submission@ec92e829475ac0c2315ea8f9eced72db85bb337a # v3.0.0 From 752da3ee7ffc3c0b506433d16856a309dbc4bd33 Mon Sep 17 00:00:00 2001 From: kimnamgyu Date: Thu, 15 Feb 2024 11:24:24 +0900 Subject: [PATCH 49/56] =?UTF-8?q?chore:=20CI/CD=EB=A5=BC=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20docker=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: hyoguoo --- Dockerfile | 4 ++++ docker-compose.yml | 29 +++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 Dockerfile create mode 100644 docker-compose.yml diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..d3eeeef --- /dev/null +++ b/Dockerfile @@ -0,0 +1,4 @@ +FROM openjdk:17 +ARG JAR_FILE=./build/libs/algobaro-api-0.0.1-SNAPSHOT.jar +COPY ${JAR_FILE} app.jar +ENTRYPOINT ["java","-jar","/app.jar", "--spring.profiles.active=prod"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..4000cef --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,29 @@ +version: "3" + +services: + database: + container_name: mysql + image: mysql/mysql-server:latest + environment: + MYSQL_DATABASE: algobaro + MYSQL_USER: admin + MYSQL_PASSWORD: admin1234 + MYSQL_ROOT_HOST: '%' + MYSQL_ROOT_PASSWORD: rootpwd + command: + - --default-authentication-plugin=mysql_native_password + ports: + - 3305:3306 + networks: + - db_network + restart: always + mytamla: + build: . + expose: + - 8080 + depends_on: + - database + +networks: + db_network: + driver: bridge From b60a875cce46f070740e389253066ea50fe0fa99 Mon Sep 17 00:00:00 2001 From: kimnamgyu Date: Thu, 15 Feb 2024 11:34:49 +0900 Subject: [PATCH 50/56] =?UTF-8?q?chore:=20CI=20Workflow=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: hyoguoo --- .github/workflows/gradle.yml | 98 ++++++++++++++++++++---------------- 1 file changed, 56 insertions(+), 42 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 27ac457..d1d63c8 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -8,60 +8,74 @@ name: Java CI with Gradle on: - push: - branches: [ "main" ] pull_request: branches: [ "main" ] +# 테스트 결과 작성을 위해 쓰기권한 추가 +permissions: write-all + +# 해당 Workflow의 Job 목록 jobs: build: - + # Runner가 실행되는 환경을 정의 runs-on: ubuntu-latest - permissions: - contents: read + # build Job 내의 step 목록 steps: - - uses: actions/checkout@v4 - - name: Set up JDK 17 - uses: actions/setup-java@v4 - with: - java-version: '17' - distribution: 'temurin' + # uses 키워드를 통해 Action 호출 + - uses: actions/checkout@v4 + # jdk 세팅 + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' - # Configure Gradle for optimal use in GiHub Actions, including caching of downloaded dependencies. - # See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md - - name: Setup Gradle - uses: gradle/actions/setup-gradle@ec92e829475ac0c2315ea8f9eced72db85bb337a # v3.0.0 + # gradle 캐싱 + - name: Gradle Caching + uses: actions/cache@v3 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.os }}-gradle- - - name: Build with Gradle Wrapper - run: ./gradlew build + ### CI + #gradlew 권한 추가 + - name: Grant Execute Permission For Gradlew + run: chmod +x gradlew - # NOTE: The Gradle Wrapper is the default and recommended way to run Gradle (https://docs.gradle.org/current/userguide/gradle_wrapper.html). - # If your project does not have the Gradle Wrapper configured, you can use the following configuration to run Gradle with a specified version. - # - # - name: Setup Gradle - # uses: gradle/actions/setup-gradle@ec92e829475ac0c2315ea8f9eced72db85bb337a # v3.0.0 - # with: - # gradle-version: '8.5' - # - # - name: Build with Gradle 8.5 - # run: gradle build + #test를 제외한 프로젝트 빌드 + - name: Build With Gradle + run: ./gradlew build -x test - dependency-submission: + #test를 위한 mysql설정 + - name: Start MySQL + uses: samin/mysql-action@v1.3 + with: + host port: 3305 + container port: 3305 + mysql database: 'algobaro' + mysql user: 'admin' + mysql password: 'admin1234' - runs-on: ubuntu-latest - permissions: - contents: write + #테스트를 위한 test properties 설정 + - name: Make application-test.properties + run: | + cd ./src/test/resources + touch ./application.properties + echo "${{ secrets.PROPERTIES_TEST }}" > ./application.properties + shell: bash - steps: - - uses: actions/checkout@v4 - - name: Set up JDK 17 - uses: actions/setup-java@v4 - with: - java-version: '17' - distribution: 'temurin' + #test코드 빌드 + - name: Build With Test + run: ./gradlew test - # Generates and submits a dependency graph, enabling Dependabot Alerts for all project dependencies. - # See: https://github.com/gradle/actions/blob/main/dependency-submission/README.md - - name: Generate and submit dependency graph - uses: gradle/actions/dependency-submission@ec92e829475ac0c2315ea8f9eced72db85bb337a # v3.0.0 + #테스트 결과 파일 생성 + - name: Publish Unit Test Results + uses: EnricoMi/publish-unit-test-result-action@v1 + if: ${{ always() }} + with: + files: build/test-results/**/*.xml From 13bd18ed5d3dea49d2687fffe28a483a2376f304 Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Thu, 15 Feb 2024 11:38:41 +0900 Subject: [PATCH 51/56] =?UTF-8?q?chore:=20CI=EB=A5=BC=20=EC=9C=84=ED=95=9C?= =?UTF-8?q?=20test=20application.properties=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/resources/application.properties | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/test/resources/application.properties diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties new file mode 100644 index 0000000..e69de29 From 660d240af8c8563425a1d1371ef910c5eb38b624 Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Thu, 15 Feb 2024 11:46:02 +0900 Subject: [PATCH 52/56] =?UTF-8?q?test:=20DB=20Connection=20test=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AlgobaroApiApplicationTest.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/test/java/ei/algobaroapi/AlgobaroApiApplicationTest.java diff --git a/src/test/java/ei/algobaroapi/AlgobaroApiApplicationTest.java b/src/test/java/ei/algobaroapi/AlgobaroApiApplicationTest.java new file mode 100644 index 0000000..1a3600f --- /dev/null +++ b/src/test/java/ei/algobaroapi/AlgobaroApiApplicationTest.java @@ -0,0 +1,28 @@ +package ei.algobaroapi; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.fail; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.jdbc.core.JdbcTemplate; + +@SpringBootTest +class AlgobaroApiApplicationTest { + + @Autowired + private JdbcTemplate jdbcTemplate; + + @Test + @DisplayName("DB Connection 테스트") + void testDatabaseConnection() { + try { + Integer test = jdbcTemplate.queryForObject("SELECT 1", Integer.class); + assertThat(test).isEqualTo(1); + } catch (Exception e) { + fail(e.getMessage()); + } + } +} From c785104117d08a9b52de704244514af3549a15ec Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Thu, 15 Feb 2024 12:02:32 +0900 Subject: [PATCH 53/56] =?UTF-8?q?chore:=20flow=20=EC=9D=B4=EB=A6=84=20?= =?UTF-8?q?=EB=AA=85=ED=99=95=ED=95=98=EA=B2=8C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/{gradle.yml => ci.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{gradle.yml => ci.yml} (100%) diff --git a/.github/workflows/gradle.yml b/.github/workflows/ci.yml similarity index 100% rename from .github/workflows/gradle.yml rename to .github/workflows/ci.yml From 777b990356511f77f32436d4af948d0e8f47f438 Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Thu, 15 Feb 2024 12:18:07 +0900 Subject: [PATCH 54/56] =?UTF-8?q?test:=20DB=20Connection=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20DATA=20JPA=20=EC=82=AC=EC=9A=A9=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AlgobaroApiApplicationTest.java | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/test/java/ei/algobaroapi/AlgobaroApiApplicationTest.java b/src/test/java/ei/algobaroapi/AlgobaroApiApplicationTest.java index 1a3600f..85f721d 100644 --- a/src/test/java/ei/algobaroapi/AlgobaroApiApplicationTest.java +++ b/src/test/java/ei/algobaroapi/AlgobaroApiApplicationTest.java @@ -1,28 +1,30 @@ package ei.algobaroapi; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.fail; +import ei.algobaroapi.domain.member.domain.Member; +import ei.algobaroapi.domain.member.domain.MemberRepository; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.jdbc.core.JdbcTemplate; @SpringBootTest class AlgobaroApiApplicationTest { @Autowired - private JdbcTemplate jdbcTemplate; + private MemberRepository memberRepository; @Test @DisplayName("DB Connection 테스트") void testDatabaseConnection() { - try { - Integer test = jdbcTemplate.queryForObject("SELECT 1", Integer.class); - assertThat(test).isEqualTo(1); - } catch (Exception e) { - fail(e.getMessage()); - } + Member newMember = Member.builder() + .email("test@test.com") + .password("test") + .build(); + + Member savedMember = memberRepository.save(newMember); + + assertThat(savedMember).isNotNull(); } } From 7ecf006d63f2d30918a058936e4ee828e6bf9239 Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Thu, 15 Feb 2024 12:28:24 +0900 Subject: [PATCH 55/56] =?UTF-8?q?test:=20DB=20Connection=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=9B=90=EB=B3=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AlgobaroApiApplicationTest.java | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/test/java/ei/algobaroapi/AlgobaroApiApplicationTest.java b/src/test/java/ei/algobaroapi/AlgobaroApiApplicationTest.java index 85f721d..1a3600f 100644 --- a/src/test/java/ei/algobaroapi/AlgobaroApiApplicationTest.java +++ b/src/test/java/ei/algobaroapi/AlgobaroApiApplicationTest.java @@ -1,30 +1,28 @@ package ei.algobaroapi; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.fail; -import ei.algobaroapi.domain.member.domain.Member; -import ei.algobaroapi.domain.member.domain.MemberRepository; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.jdbc.core.JdbcTemplate; @SpringBootTest class AlgobaroApiApplicationTest { @Autowired - private MemberRepository memberRepository; + private JdbcTemplate jdbcTemplate; @Test @DisplayName("DB Connection 테스트") void testDatabaseConnection() { - Member newMember = Member.builder() - .email("test@test.com") - .password("test") - .build(); - - Member savedMember = memberRepository.save(newMember); - - assertThat(savedMember).isNotNull(); + try { + Integer test = jdbcTemplate.queryForObject("SELECT 1", Integer.class); + assertThat(test).isEqualTo(1); + } catch (Exception e) { + fail(e.getMessage()); + } } } From 9ec7ffa9edc3334124a249082172ac371a047d12 Mon Sep 17 00:00:00 2001 From: hyoguoo Date: Thu, 15 Feb 2024 12:43:53 +0900 Subject: [PATCH 56/56] =?UTF-8?q?chore:=20CD=20workflow=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/cd.yml | 65 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 .github/workflows/cd.yml diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml new file mode 100644 index 0000000..a1a19a1 --- /dev/null +++ b/.github/workflows/cd.yml @@ -0,0 +1,65 @@ +name: CD + +on: + push: + branches: + - main + +permissions: write-all + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + + # gradle 캐싱 + - name: Gradle Caching + uses: actions/cache@v3 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.os }}-gradle- + + # prod properties 설정 + - name: Make application-prod.properties + run: | + cd ./src/main/resources + touch ./application-prod.properties + echo "${{ secrets.PROPERTIES_PROD }}" > ./application-prod.properties + shell: bash + + # test를 제외한 프로젝트 빌드 + - name: Build With Gradle + run: ./gradlew build -x test + + # 도커 빌드 & 이미지 push + - name: Docker build & Push + run: | + docker login -u ${{ secrets.DOCKER_ID }} -p ${{ secrets.DOCKER_PASSWORD }} + docker build -f Dockerfile -t ${{ secrets.DOCKER_REPO }}/algobaro-api . + docker push ${{ secrets.DOCKER_REPO }}/algobaro-api + # docker-compose 파일을 ec2 서버에 배포 + - name: Deploy to Prod + uses: appleboy/ssh-action@master + id: deploy-prod + with: + host: ${{ secrets.EC2_HOST }} + username: ${{ secrets.EC2_USERNAME }} + key: ${{ secrets.EC2_SSH_PRIVATE_KEY }} + envs: GITHUB_SHA + script: | + docker stop algobaro-api + docker rm algobaro-api + sudo docker pull ${{ secrets.DOCKER_REPO }}/algobaro-api + docker run -d --name algobaro-api -p 8080:8080 ${{ secrets.DOCKER_REPO }}/algobaro-api + docker rmi -f $(docker images -f "dangling=true" -q)