Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
9a21b37
[BE] feat: user local db config 파일 추가 (#10)
bianbbc87 Jan 30, 2025
a7eeb38
[BE] refactor: user config mysql url, driver-class-name은 constant로 변경…
bianbbc87 Jan 30, 2025
7b6a59d
[BE] feat: user domain, entity 정의 (#10)
bianbbc87 Jan 30, 2025
ac9a31f
[BE] refactor: base entity, birth, name 필드 추가 (#10)
bianbbc87 Jan 30, 2025
1faba40
[BE] feat: stmp config 설정 (#10)
bianbbc87 Jan 31, 2025
8208486
[BE] refactor: jwt 만료 시간 config 추가 (#10)
bianbbc87 Jan 31, 2025
959d460
[BE] refactor: user server 접근 및 jwt 검증 설정 (#10)
bianbbc87 Feb 3, 2025
3ae032c
[BE] feat: security 설정 (#10)
bianbbc87 Jan 31, 2025
584cc40
[BE] feat: jwt, security, email dependency 추가 (#10)
bianbbc87 Jan 31, 2025
f2d12e7
[BE] feat: security no need url 확인용 controller 추가 (#10)
bianbbc87 Jan 31, 2025
f6267cc
[BE] feat: member repository 추가 (#10)
bianbbc87 Jan 31, 2025
e7ce36c
[BE] feat: bean 주입용 usecase 추가 (#10)
bianbbc87 Jan 31, 2025
8059ad8
[BE] feat: 임시 회원가입 메서드 구현 (#10)
bianbbc87 Jan 31, 2025
4ff3725
[BE] feat: 인증번호 인증 및 회원가입 메서드 구현 (#10)
bianbbc87 Jan 31, 2025
dd2418d
[BE] feat: 로그인 메서드 구현 (#10)
bianbbc87 Jan 31, 2025
a8d959a
[BE] refactor: apigateway user server path 정의 (#10)
bianbbc87 Jan 31, 2025
551bd0f
[BE] refactor: user controller 반환값 null -> string으로 변경 (#10)
bianbbc87 Jan 31, 2025
820a6b1
[BE] refactor: user controller request dto final 정의 (#10)
bianbbc87 Jan 31, 2025
ee5e886
[BE] refactor: usecase, service method final 정의, requestDto request로 …
bianbbc87 Jan 31, 2025
1d9d369
[BE] refactor: 이메일 중복 검사 api 분리 (#10)
bianbbc87 Feb 1, 2025
ce10e7d
[BE] refactor: id genertative 생성 어노테이션 제거 (#10)
bianbbc87 Feb 1, 2025
68d81b5
[BE] refactor: 비밀번호 중복 검사 BCryptPasswordEncoder로 변경 (#10)
bianbbc87 Feb 1, 2025
be0bd43
[BE] refactor: 생성자 public -> private으로 변경, domain redis 구분 제거 (#10)
bianbbc87 Feb 1, 2025
064fa72
[BE] refactor: failtype 500, 400 구분 리팩토링 (#10)
bianbbc87 Feb 1, 2025
86e67f4
[BE] refactor: discord용 템플릿으로 변경 (#10)
bianbbc87 Feb 1, 2025
54c363b
[BE] refactor: user details account non expired, account non locked, …
bianbbc87 Feb 1, 2025
a8204d3
[BE] refactor: jwon util 메서드 이름 간결하게 변경 (#10)
bianbbc87 Feb 1, 2025
ce2d4d7
[BE] fix: 이메일 중복 검사 usecase implements 누락 추가 (#10)
bianbbc87 Feb 1, 2025
03629cc
[BE] refactor: password encoder 추상화 빈으로 변경 (#10)
bianbbc87 Feb 1, 2025
ce856df
[BE] refactor: member repository OptimisticLockException catch문 제거 (#10)
bianbbc87 Feb 1, 2025
549452a
[BE] refactor: cors config 추가 (#10)
bianbbc87 Feb 1, 2025
433bc0f
[BE] feat: user details SimpleAuthority 권한 추가 (#10)
bianbbc87 Feb 1, 2025
07dbe18
[BE] refactor: base entity, time entity 분리 (#10)
bianbbc87 Feb 1, 2025
bd92624
[BE] refactor: AOP logging으로 변경 (#10)
bianbbc87 Feb 1, 2025
5ddcd4a
[BE] feat: user info update, user delete 메서드 구현 (#10)
bianbbc87 Feb 1, 2025
707323e
[BE] feat: default profile image config value 등록 (#10)
bianbbc87 Feb 1, 2025
1de812a
[BE] refactor: redis repository 역할 분리 (#10)
bianbbc87 Feb 1, 2025
30ab556
[BE] fix: delete user service 주입 안 되던 이슈 해결 (#10)
bianbbc87 Feb 1, 2025
29a1f9d
[BE] feat: 디바이스 토큰 업데이트 메서드 추가 (#10)
bianbbc87 Feb 1, 2025
3d9d2be
[BE] fix: delete user usecase final 주입 이슈 해결 (#10)
bianbbc87 Feb 1, 2025
5390143
[BE] feat: 유저 정보 업데이트 메서드 구현, 기본 프로필 이미지 설정 (#10)
bianbbc87 Feb 1, 2025
6e64977
[BE] refactor: 유저 서버 경로 user로 변경 (#10)
bianbbc87 Feb 1, 2025
b2a9784
[BE] feat: @MemberID 파싱용 resolver, webconfig 설정 (#10)
bianbbc87 Feb 1, 2025
fd8796e
[BE] refactor: response 출력 오류 해결, global exception handler 추가 (#10)
bianbbc87 Feb 1, 2025
b729ea7
[BE] feat: intelliJ http test code 추가 (#10)
bianbbc87 Feb 3, 2025
4016aae
[BE] refactor: apigateway filter 특정 url 제외 (#10)
bianbbc87 Feb 3, 2025
9d90de8
[BE] refactor: member delete soft delete로 변경 (#10)
bianbbc87 Feb 3, 2025
9c18ee3
[BE] refactor: api gateway server 유저 서버 filter 처리 (#10)
bianbbc87 Feb 3, 2025
8bbf079
[BE] refactor: userinfo http 수정, 디바이스 토큰 재발급 controller 정의 (#10)
bianbbc87 Feb 3, 2025
208bbc4
[BE] fix: jwt 생성 key base64 제거 (#10)
bianbbc87 Feb 3, 2025
2c9f9bd
[BE] feat: base entity config 추가 (#10)
bianbbc87 Feb 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,6 @@ src/backend/**/src/main/resources/bootstrap.yml

# Ignore all generated directories under backend
src/backend/**/generated/

# http env
src/backend/**/http/http-client.private.env.json
48 changes: 47 additions & 1 deletion config/user-server.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ eureka:
defaultZone: '{cipher}f0d4232ceb8d3d476ebc0895b8ef4530a1a8992acaa373a904e559c3ac3f7b6054801cb979d0b481124de1cee9dd6633'
jwt:
secret-key: '{cipher}e3ee7c81dedbd05d33e9e934a192a67cca17890d39faebc6645fe3eeb6c7b16034312dad499dd72f869cb03a6f2d6b7498b5204a523412735009f0c8b8f56eb6'
temporary-token-expire-period: 900000
access-token-expire-period: 1209600000

cloud:
aws:
Expand All @@ -14,4 +16,48 @@ cloud:
static: '{cipher}9c1fddf30981e4a52bb3b5d483faf3640277ea98e56cd896c4af07fc74f8a7d1'
s3:
bucket: '{cipher}791ddfe9003ecb7c329f694bbc05d386cf783189f0e7196d5a3dcbfec48d84bd'
url: '{cipher}0d5e7427241949e0656366472edde113f98d7b215ef6f982cbf6725264510beffa4da0f650b56d13c71eea6b5827179650b9aaf563bda7a0d6a14375ff7d8eff6a603b1063687a88b2073d3ca273d1f9'
url: '{cipher}0d5e7427241949e0656366472edde113f98d7b215ef6f982cbf6725264510beffa4da0f650b56d13c71eea6b5827179650b9aaf563bda7a0d6a14375ff7d8eff6a603b1063687a88b2073d3ca273d1f9'
profile:
default:
url: '{cipher}cb5a8d7a800e3b5558a7ad39e592f88dd22a6f81d5143d3571e51f1ac690f96f639280d2fe55c13d8ecfb0f5e91339812d41df429df17b6b9e65b33e644554719f03e300c1d9cde8776b463c3daeea1d10af9c563addf7d4ae74801d721fdc48'

spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/user?useSSL=false&serverTimezone=Asia/Seoul
username: '{cipher}56d454dea6f1332e8d9b5656400700369e6024c027fbc51e372dd64ff7ecb6a4'
password: '{cipher}1e4d1a106597d4b9efd8a80f25ccb4cec28a08b2f02d9b4c3b1ff3ffae90ad83'
hikari:
pool-name: '{cipher}b5848c642d7a307f92f1579de1809bcd68584ddbd8a474cc1d2ddef834c093e9'
maximum-pool-size: 5
data-source-properties:
rewriteBatchedStatements: true

jpa:
hibernate:
ddl-auto: update
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

테스트할때 update로 두고 배포환경에서는 none 이나 validate가 좋을 것 같아요

show-sql: true
properties:
hibernate:
dialect: '{cipher}623b0560db7816d2ffd55845e924030f6acdc6d044abce0a1826e873e268b17d1171767fd2e21614d47fd6cdd9f07ff0cd2a39d7c956e179ad7e850a8a375292'
default_batch_fetch_size: 100
jdbc.batch_size: 20
order_inserts: true
order_updates: true
format_sql: true
open-in-view: false

mail:
host: smtp.gmail.com
port: 587
username: '{cipher}55c4145543a06549c17f7ae1a9fc1ff241cf5b04a6b12596c5585d4163826c0fd5de29fff4acd199bf7d4a03f5cad596'
password: '{cipher}d821571e7ad6e5c3aa5c0bd2353b1e79bc93f0940d22a8763616e504b7bd870627e0b18d3fba6e330771f8732cfbad8b'
properties:
mail:
smtp:
auth: true
connectiontimeout: 5000
timeout: 5000
starttls:
enable: true
auth-code-expiration-millis: 300000
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import com.asyncgate.apigatewayserver.exception.FailType;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.nio.charset.StandardCharsets;
import java.util.List;

import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
Expand All @@ -25,6 +27,10 @@ public class AuthorizationHeaderFilter extends AbstractGatewayFilterFactory<Auth
private final JwtTokenProvider jwtTokenProvider;
private final ObjectMapper objectMapper;

private static final List<String> NO_NEED_URLS = List.of(
"/sign-up", "/sign-in", "/validation/email", "/validation/authentication-code"
);

public AuthorizationHeaderFilter(
final JwtTokenProvider jwtTokenProvider,
final ObjectMapper objectMapper
Expand All @@ -38,6 +44,12 @@ public AuthorizationHeaderFilter(
public GatewayFilter apply(final Config config) {
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
String path = request.getURI().getPath();

// user server 특정 url인 경우 filter 제외
if (NO_NEED_URLS.contains(path)) {
return chain.filter(exchange);
}

if (!request.getHeaders().containsKey(HttpHeaders.AUTHORIZATION)) {
return onError(exchange, FailType.AUTHORIZATION_MISSING_HEADER);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,49 @@ spring:
- RemoveRequestHeader=Cookie
- RewritePath=/user-service/(?<segment>.*), /$\{segment}
- AuthorizationHeaderFilter
# ToDo 유저 서버 개발 후 활성화
- id: user-server
uri: lb://USER-SERVER
predicates:
- Path=/user/sign-up
filters:
- RemoveRequestHeader=Cookie
- RewritePath=/user/(?<segment>.*), /$\{segment}

- id: user-server
uri: lb://USER-SERVER
predicates:
- Path=/user/sign-in
filters:
- RemoveRequestHeader=Cookie
- RewritePath=/user/(?<segment>.*), /$\{segment}

- id: user-server
uri: lb://USER-SERVER
predicates:
- Path=/user/validation/authentication-code
filters:
- RemoveRequestHeader=Cookie
- RewritePath=/user/(?<segment>.*), /$\{segment}

- id: user-server
uri: lb://USER-SERVER
predicates:
- Path=/user/validation/email
filters:
- RemoveRequestHeader=Cookie
- RewritePath=/user/(?<segment>.*), /$\{segment}

- id: user-server
uri: lb://USER-SERVER
predicates:
- Path=/user/**
filters:
- RemoveRequestHeader=Cookie
- RewritePath=/user/(?<segment>.*), /$\{segment}
- AuthorizationHeaderFilter


management:
endpoints:
web:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ spring:
git:
uri: https://github.com/sgdevcamp2025/asyncgate
# ToDo 테스트 후 변경
# default-label: be/feat/5-s3
# default-label: be/feat/10-user
# default-label: dev
default-label: main
default-label: main
search-paths:
- "config"

Expand Down
22 changes: 21 additions & 1 deletion src/backend/user-server/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ ext {
dependencies {

implementation 'org.springframework.boot:spring-boot-starter-web'
// implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-actuator'

implementation 'org.springframework.cloud:spring-cloud-starter'
Expand All @@ -46,8 +46,28 @@ dependencies {
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

// Security
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.security:spring-security-oauth2-client'

// JWT
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
implementation 'jakarta.xml.bind:jakarta.xml.bind-api:4.0.0'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5'
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5'

// Spring Boot Mail
implementation 'org.springframework.boot:spring-boot-starter-mail'

// Validation
implementation 'org.springframework.boot:spring-boot-starter-validation'

// AWS
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'

// mysql
runtimeOnly 'com.mysql:mysql-connector-j'
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
}

dependencyManagement {
Expand Down
86 changes: 86 additions & 0 deletions src/backend/user-server/http/UserControllerHttpRequest.http
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
### 0.0 health check
// @no-log
GET {{host_url}}/health

### 1.0 임시 회원가입
// @no-log
POST {{host_url}}/sign-up
Content-Type: application/json

{
"email": "{{user.API_1_0_SIGNUP.email}}",
"password": "{{user.API_1_0_SIGNUP.password}}",
"name": "{{user.API_1_0_SIGNUP.name}}",
"nickname": "{{user.API_1_0_SIGNUP.nickname}}",
"birth": "{{user.API_1_0_SIGNUP.birth}}"
}


### 1.1 로그인
// @no-log
POST {{host_url}}/sign-in
Content-Type: application/json

{
"email": "{{user.API_1_1_SIGNIN.email}}",
"password": "{{user.API_1_1_SIGNIN.password}}"
}

> {%
client.global.set("access_token", response.body.result.access_token);
%}


### 1.2 인증코드 인증
// @no-log
POST {{host_url}}/validation/authentication-code
Content-Type: application/json

{
"email": "{{user.API_1_2_AUTHENTICATION_CODE.email}}",
"authentication_code": "{{user.API_1_2_AUTHENTICATION_CODE.authentication_code}}"
}

### 1.3 이메일 중복 검사
// @no-log
POST {{host_url}}/validation/email?email={{user.API_1_3_DUPLICATE_EMAIL.email}}

### 1.4 디바이스 토큰 등록
// @no-log
PATCH {{host_url}}/device-token
Authorization: Bearer {{access_token}}
Content-Type: application/json

{
"device_token": "{{user.API_1_4_UPDATE_DEVICE_TOKEN.device_token}}"
}

### 1.5 사용자 정보 수정
// @no-log
PATCH {{host_url}}/info
Authorization: Bearer {{access_token}}
Content-Type: multipart/form-data; boundary=boundary

--boundary
Content-Disposition: form-data; name="profile_image"; filename="image.png"
Content-Type: image/png

< /Users/eunji/Desktop/profile2.png

--boundary
Content-Disposition: form-data; name="name"

{{user.API_1_5_UPDATE_USERINFO.name}}

--boundary
Content-Disposition: form-data; name="nickname"

{{user.API_1_5_UPDATE_USERINFO.nickname}}

--boundary--


### 1.6 회원 탈퇴
// @no-log
DELETE {{host_url}}/auth
Authorization: Bearer {{access_token}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.asyncgate.user_server.config;

import com.asyncgate.user_server.security.info.CustomUserPrincipal;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.domain.AuditorAware;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;

import java.util.Optional;

@EnableJpaAuditing
@Configuration
public class BaseEntityConfig {

@Bean("user-auditorProvider")
public AuditorAware<String> auditorProvider() {
return () -> {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

if (authentication == null || !authentication.isAuthenticated()) {
return Optional.of("AnonymousNULL");
}

Object principal = authentication.getPrincipal();

if (principal instanceof CustomUserPrincipal) {
return Optional.of(((CustomUserPrincipal) principal).getId());
}

return Optional.of("AnonymousNOT_TYPE");
};
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.asyncgate.user_server.config;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.ArrayList;
import java.util.Collections;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class CorsConfig {

public static CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();

//리소스를 허용
ArrayList<String> allowedOriginPatterns = new ArrayList<>();
allowedOriginPatterns.add("http://localhost:5173"); // vite
allowedOriginPatterns.add("http://127.0.0.1:5173");
configuration.setAllowedOrigins(allowedOriginPatterns);

//허용하는 HTTP METHOD
ArrayList<String> allowedHttpMethods = new ArrayList<>();
allowedHttpMethods.add("GET");
allowedHttpMethods.add("POST");
allowedHttpMethods.add("PUT");
allowedHttpMethods.add("PATCH");
allowedHttpMethods.add("DELETE");
allowedHttpMethods.add("OPTIONS");
configuration.setAllowedMethods(allowedHttpMethods);

configuration.setAllowedHeaders(Collections.singletonList("*"));
// configuration.setAllowedHeaders(List.of(HttpHeaders.AUTHORIZATION, HttpHeaders.CONTENT_TYPE));

//인증, 인가를 위한 credentials 를 TRUE로 설정
configuration.setAllowCredentials(true);

UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);

return source;
}
}
Loading