Skip to content

Commit

Permalink
release: 0.1.6 (#122)
Browse files Browse the repository at this point in the history
* feat: 모임 삭제 기능 구현 (#102)

* refactor: 기획 변경에 따른 회원 카드 등록 API 리팩토링 (#105)

* refactor: sql 변경 (#104)

* refactor: User 클래스 필드명 변경 (#104)

* refactor: API 변경에 따른 코드 리팩토링 (#104)

* refactor: 불필요한 getId() 제거 ( 피드백 반영 ) (#104)

* feat: 유효성 검증 관련 에러 일괄 처리을 위한 메소드 추가 (#104)

* test: API 변경에 따른 통합 테스트 수정 및 단위 테스트 구현 (#104)

* refactor: UserMeGetResponse 필드 변경 (#104)

* fix: CI 에러 수정 (#104)

* refactor: 피드백 반영 (#104)

* fix: CI 에러 수정 (#104)

* refactor: JWT 에러 응답 리팩토링 및 인가 인증 예최 처리 코드 수정 (#103)

* refactor: 기타 코드 리팩토링( 피드백 반영 ) (#101)

* chore: JWT 관련 의존성 변경 (#101)

* refactor: JWT 및 인증 관련 로직 리팩토링 (#101)

* test: 테스트 코드 및 설정 관련 변경(#101)

* refactor: ObjectMapper Autowired 로 주입 (#101)

* refactor: AuthService 반환 타입 Optional<User> -> User 변경 (#101)

* fix: V6_create_users_interests.sql 추가 (#109) (#110)

* refactor: 회원 카드 등록시 JWT 정보도 함께 반환하도록 수정 (#114)

* chore : application.properties 에 jwt 관련 설정 값 추가 (#113)

* refactor : userService 회원 카드 등록 로직 수정 (#113)

* feat : UserRegisterResponse 필드 추가(#113)

* test: API 변경에 따른 테스트 관련 코드 수정 (#113)

* fix: 소셜 로그인 관련 500 에러 수정 및 OAuth 로직 일부 개선 (#112)

* fix: OAuthLoginController @RestController 어노테이션 추가(나는 바보..) 및 favicon 관련 임시 컨트롤러 생성 (#111)

* refactor : 설정 yml 리팩토링 (#111)

* refactor : SecurityConfig 리팩토링 (#111)

* refactor : 기타 OAuth 관련 로직 리팩토링(#111)

* refactor : Cors 허용 주소 임시 전부 허용 (#111)

* fix : SonarCloud 오류 수정 (#111)

* fix : SonarCloud 오류 수정 (#111)

* feat: 위치 기반 API 구현 및 테스트 (#108)

* refactor: 기타 코드 리팩토링( 피드백 반영 ) (#101)

* chore: JWT 관련 의존성 변경 (#101)

* refactor: JWT 및 인증 관련 로직 리팩토링 (#101)

* test: 테스트 코드 및 설정 관련 변경(#101)

* refactor: ObjectMapper Autowired 로 주입 (#101)

* refactor: AuthService 반환 타입 Optional<User> -> User 변경 (#101)

* refactor: application.properties redis.port 변경 (#91)

* refactor: 기존 Redis 설정 리팩토링 및 추가 구현 (#91)

* feat: 유저 위치 기반 관련 DTO 및 VO 구현 (#91)

* feat: 유저 위치 기반 API 구현 (#91)

* test: 유저 위치 기반 통합 테스트 관련 클래스 구현 및 테스트 (#91)

* test: redis port 변경에 따른 테스트 수정 (#91)

* fix: CI 에러 수정 (#91)

* fix: sonarCloud 에러 수정 (#91)

* refactor: 리뷰 반영 (#108)

* build: Gatling 세팅 (#115)

* feat: 부하테스트 툴 Gatling을 세팅한다

* feat: 예시 코드를 작성한다

* refactor: Sample 코드의 이름을 변경한다

* feat: 내 정보 조회에 Oauth 정보 추가 (#119)

* feat: 내 정보 조회에 Oauth 정보 추가

* test: Oauth 정보 추가에 따른 테스트 변경

* fix: 모임 목록 조회 조건에 활동 지역 조건이 안걸리는 버그 수정 (#121)

---------

Co-authored-by: ddingmin <[email protected]>
Co-authored-by: xb205 <[email protected]>
  • Loading branch information
3 people authored Jan 19, 2024
1 parent 6d9d376 commit 61df878
Show file tree
Hide file tree
Showing 12 changed files with 278 additions and 9 deletions.
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ plugins {
id 'io.spring.dependency-management'
id 'org.sonarqube'
id 'io.sentry.jvm.gradle'
id "io.gatling.gradle" version "${gatlingVersion}"
}

apply from: "gradle/spring.gradle"
Expand All @@ -13,6 +14,7 @@ apply from: "gradle/sonar.gradle"
apply from: "gradle/db.gradle"
apply from: "gradle/aws.gradle"
apply from: "gradle/sentry.gradle"
apply from: "gradle/gatling.gradle"

allprojects {

Expand Down
4 changes: 4 additions & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,7 @@ sentryVersion=4.1.1
springCloudAwsVersion=3.1.0
### JWT ###
jwtVersion=0.11.5
### Gatling ###
gatlingVersion=3.9.5.6
### Data faker ###
datafakerVersion=2.0.2
12 changes: 12 additions & 0 deletions gradle/gatling.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
gatling {
simulations = {
include "**/*Simulation.java"
}
jvmArgs = ["-server", "-Xms512M", "-Xmx2G"]
systemProperties = ['file.encoding': 'UTF-8']
includeTestOutput = false
}

dependencies {
gatlingImplementation "net.datafaker:datafaker:${datafakerVersion}"
}
17 changes: 17 additions & 0 deletions src/gatling/java/protocol/Protocol.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package protocol;

import io.gatling.javaapi.http.HttpDsl;
import io.gatling.javaapi.http.HttpProtocolBuilder;

public class Protocol {

private static final String USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0) Gecko/20100101 Firefox/16.0";

public static final HttpProtocolBuilder httpProtocol = HttpDsl.http.baseUrl("https://api.teum.org")
.header("Content-Type", "application/json")
.userAgentHeader(USER_AGENT);

private Protocol() {
throw new UnsupportedOperationException("Cannot invoke constructor \"protocol.Protocol()\"");
}
}
27 changes: 27 additions & 0 deletions src/gatling/java/simulation/SimulationSample.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package simulation;

import static io.gatling.javaapi.core.CoreDsl.rampUsers;
import static io.gatling.javaapi.core.CoreDsl.scenario;
import static io.gatling.javaapi.http.HttpDsl.http;
import static io.gatling.javaapi.http.HttpDsl.status;

import io.gatling.javaapi.core.ScenarioBuilder;
import io.gatling.javaapi.core.Simulation;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import protocol.Protocol;

public class SimulationSample extends Simulation {

private final ScenarioBuilder scn = scenario(this.getClass().getSimpleName())
.exec(http("get user")
.get("/users/1")
.check(status().is(200))
);

{
setUp(
scn.injectOpen(rampUsers(10).during(Duration.of(10, ChronoUnit.MINUTES)))
).protocols(Protocol.httpProtocol);
}
}
127 changes: 127 additions & 0 deletions src/gatling/resources/gatling.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
#########################
# Gatling Configuration #
#########################

# This file contains all the settings configurable for Gatling with their default values

gatling {
core {
#outputDirectoryBaseName = "" # The prefix for each simulation result folder (then suffixed by the report generation timestamp)
#runDescription = "" # The description for this simulation run, displayed in each report
#encoding = "utf-8" # Encoding to use throughout Gatling for file and string manipulation
#simulationClass = "" # The FQCN of the simulation to run (when used in conjunction with noReports, the simulation for which assertions will be validated)
#elFileBodiesCacheMaxCapacity = 200 # Cache size for request body EL templates, set to 0 to disable
#rawFileBodiesCacheMaxCapacity = 200 # Cache size for request body raw files, set to 0 to disable
#rawFileBodiesInMemoryMaxSize = 1000 # Max bite size of raw files to be cached in memory
#pebbleFileBodiesCacheMaxCapacity = 200 # Cache size for request body Pebble templates, set to 0 to disable
#feederAdaptiveLoadModeThreshold = 100 # File size threshold (in MB). Below load eagerly in memory, above use batch mode with default buffer size
#shutdownTimeout = 10000 # Milliseconds to wait for the actor system to shutdown
extract {
regex {
#cacheMaxCapacity = 200 # Cache size for the compiled regexes, set to 0 to disable caching
}
xpath {
#cacheMaxCapacity = 200 # Cache size for the compiled XPath queries, set to 0 to disable caching
}
jsonPath {
#cacheMaxCapacity = 200 # Cache size for the compiled jsonPath queries, set to 0 to disable caching
}
css {
#cacheMaxCapacity = 200 # Cache size for the compiled CSS selectors queries, set to 0 to disable caching
}
}
directory {
#simulations = "" # If set, directory where simulation classes are located
#resources = "" # If set, directory where resources, such as feeder files and request bodies, are located
#reportsOnly = "" # If set, name of report folder to look for in order to generate its report
#binaries = "" # If set, name of the folder where compiles classes are located: Defaults to GATLING_HOME/target.
#results = results # Name of the folder where all reports folder are located
}
}
socket {
#connectTimeout = 10000 # Timeout in millis for establishing a TCP socket
#tcpNoDelay = true
#soKeepAlive = false # if TCP keepalive configured at OS level should be used
#soReuseAddress = false
}
netty {
#useNativeTransport = true # if Netty Linux native transport should be used instead of Java NIO
#useIoUring = false # if io_uring should be used instead of epoll if available
#allocator = "pooled" # switch to unpooled for unpooled ByteBufAllocator
#maxThreadLocalCharBufferSize = 200000 # Netty's default is 16k
}
ssl {
#useOpenSsl = true # if OpenSSL should be used instead of JSSE (only the latter can be debugged with -Djavax.net.debug=ssl)
#useOpenSslFinalizers = false # if OpenSSL contexts should be freed with Finalizer or if using RefCounted is fine
#handshakeTimeout = 10000 # TLS handshake timeout in millis
#useInsecureTrustManager = true # Use an insecure TrustManager that trusts all server certificates
#enabledProtocols = [] # Array of enabled protocols for HTTPS, if empty use Netty's defaults
#enabledCipherSuites = [] # Array of enabled cipher suites for HTTPS, if empty enable all available ciphers
#sessionCacheSize = 0 # SSLSession cache size, set to 0 to use JDK's default
#sessionTimeout = 0 # SSLSession timeout in seconds, set to 0 to use JDK's default (24h)
#enableSni = true # When set to true, enable Server Name indication (SNI)
keyStore {
#type = "" # Type of SSLContext's KeyManagers store, possible values are jks and p12
#file = "" # Location of SSLContext's KeyManagers store
#password = "" # Password for SSLContext's KeyManagers store
#algorithm = "" # Algorithm used SSLContext's KeyManagers store, typically RSA
}
trustStore {
#type = "" # Type of SSLContext's TrustManagers store, possible values are jks and p12
#file = "" # Location of SSLContext's TrustManagers store
#password = "" # Password for SSLContext's TrustManagers store
#algorithm = "" # Algorithm used by SSLContext's TrustManagers store, typically RSA
}
}
charting {
#noReports = false # When set to true, don't generate HTML reports
#maxPlotPerSeries = 1000 # Number of points per graph in Gatling reports
#useGroupDurationMetric = false # Switch group timings from cumulated response time to group duration.
indicators {
#lowerBound = 800 # Lower bound for the requests' response time to track in the reports and the console summary
#higherBound = 1200 # Higher bound for the requests' response time to track in the reports and the console summary
#percentile1 = 50 # Value for the 1st percentile to track in the reports, the console summary and Graphite
#percentile2 = 75 # Value for the 2nd percentile to track in the reports, the console summary and Graphite
#percentile3 = 95 # Value for the 3rd percentile to track in the reports, the console summary and Graphite
#percentile4 = 99 # Value for the 4th percentile to track in the reports, the console summary and Graphite
}
}
http {
#fetchedCssCacheMaxCapacity = 200 # Cache size for CSS parsed content, set to 0 to disable
#fetchedHtmlCacheMaxCapacity = 200 # Cache size for HTML parsed content, set to 0 to disable
#perUserCacheMaxCapacity = 200 # Per virtual user cache size, set to 0 to disable
#warmUpUrl = "https://gatling.io" # The URL to use to warm-up the HTTP stack (blank means disabled)
#pooledConnectionIdleTimeout = 60000 # Timeout in millis for a connection to stay idle in the pool
#requestTimeout = 60000 # Timeout in millis for performing an HTTP request
#enableHostnameVerification = false # When set to true, enable hostname verification: SSLEngine.setHttpsEndpointIdentificationAlgorithm("HTTPS")
dns {
#queryTimeout = 5000 # Timeout in millis of each DNS query in millis
#maxQueriesPerResolve = 6 # Maximum allowed number of DNS queries for a given name resolution
}
}
jms {
#replyTimeoutScanPeriod = 1000 # scan period for timed out reply messages
}
data {
#writers = [console, file] # The list of DataWriters to which Gatling write simulation data (currently supported : console, file, graphite)
console {
#light = false # When set to true, displays a light version without detailed request stats
#writePeriod = 5 # Write interval, in seconds
}
file {
#bufferSize = 8192 # FileDataWriter's internal data buffer size, in bytes
}
leak {
#noActivityTimeout = 30 # Period, in seconds, for which Gatling may have no activity before considering a leak may be happening
}
graphite {
#light = false # only send the all* stats
#host = "localhost" # The host where the Carbon server is located
#port = 2003 # The port to which the Carbon server listens to (2003 is default for plaintext, 2004 is default for pickle)
#protocol = "tcp" # The protocol used to send data to Carbon (currently supported : "tcp", "udp")
#rootPathPrefix = "gatling" # The common prefix of all metrics sent to Graphite
#bufferSize = 8192 # Internal data buffer size, in bytes
#writePeriod = 1 # Write period, in seconds
}
}
}
56 changes: 56 additions & 0 deletions src/gatling/resources/recorder.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
recorder {
core {
# mode = "Proxy"
# encoding = "utf-8" # The encoding used for reading/writing request bodies and the generated simulation
# simulationsFolder = "" # The folder where generated simulation will be generated
# package = "" # The package's name of the generated simulation
# className = "RecordedSimulation" # The name of the generated Simulation class
# thresholdForPauseCreation = 100 # The minimum time, in milliseconds, that must pass between requests to trigger a pause creation
# saveConfig = false # When set to true, the configuration from the Recorder GUI overwrites this configuration
# headless = false # When set to true, run the Recorder in headless mode instead of the GUI
# harFilePath = "" # The path of the HAR file to convert
# format = "java8" # java8|java11|java17|kotlin|scala
}
filters {
# enable = false # If filters are enabled
# allowList = [] # The list of ressources patterns that are part of the Recorder's allow list
# denyList = [] # The list of ressources patterns that are part of the Recorder's deny list
}
http {
# automaticReferer = true # When set to false, write the referer + enable 'disableAutoReferer' in the generated simulation
# followRedirect = true # When set to false, write redirect requests + enable 'disableFollowRedirect' in the generated simulation
# removeCacheHeaders = true # When set to true, removes from the generated requests headers leading to request caching
# inferHtmlResources = true # When set to true, add inferred resources + set 'inferHtmlResources' with the configured blacklist/whitelist in the generated simulation
# checkResponseBodies = false # When set to true, save response bodies as files and add raw checks in the generated simulation
# useSimulationAsPrefix = false # When set to true, use the simulation class name instead of 'request' as a prefix for http(s) requests
# useMethodAndUriAsPostfix = false # When set to true, use the HTTP method and the URI as a postfix for http(s) requests
}
proxy {
# port = 8000 # Local port used by Gatling's Proxy for HTTP/HTTPS
https {
# mode = "SelfSignedCertificate" # The selected "HTTPS mode" (currently supported : "SelfSignedCertificate", "ProvidedKeyStore", "CertificateAuthority")
keyStore {
# path = "" # The path of the custom key store
# password = "" # The password for this key store
# type = "JKS" # The type of the key store (currently supported: "JKS" and "PKCS#12")
}
certificateAuthority {
# certificatePath = "" # The path of the custom certificate
# privateKeyPath = "" # The certificate's private key path
}
}
outgoing {
# host = "" # The outgoing proxy's hostname
# username = "" # The username to use to connect to the outgoing proxy
# password = "" # The password corresponding to the user to use to connect to the outgoing proxy
# port = 0 # The HTTP port to use to connect to the outgoing proxy
# sslPort = 0 # If set, The HTTPS port to use to connect to the outgoing proxy
}
}
netty {
# maxInitialLineLength = 10000 # Maximum length of the initial line of the response (e.g. "HTTP/1.0 200 OK")
# maxHeaderSize = 20000 # Maximum size, in bytes, of each request's headers
# maxChunkSize = 8192 # Maximum length of the content or each chunk
# maxContentLength = 100000000 # Maximum length of the aggregated content of each response
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public MeetingResponse getMeetingById(@PathVariable("meetingId") Long meetingId)

@GetMapping
@ResponseStatus(HttpStatus.OK)
public PageDto<MeetingsResponse> getMeetingsOrderByDate(
public PageDto<MeetingsResponse> getMeetingsByCondition(
Pageable pageable,
@RequestParam(value = "isOpen") boolean isOpen,
@RequestParam(value = "topic", required = false) Topic topic,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public PageDto<MeetingsResponse> getMeetingsBySpecification(Pageable pageable, T
if (topic != null) {
spec = spec.and(MeetingSpecification.withTopic(topic));
} else if (meetingAreaStreet != null) {
spec.and(MeetingSpecification.withAreaStreet(meetingAreaStreet));
spec = spec.and(MeetingSpecification.withAreaStreet(meetingAreaStreet));
} else if (participantUserId != null) {
spec = spec.and(MeetingSpecification.withParticipantUserId(participantUserId));
} else if (searchWord != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,37 @@ public record UserMeGetResponse(
String status,
String goal,
Job job,
String oauthType,
List<String> interests
) {

public static UserMeGetResponse of(User user) {
return new UserMeGetResponse(user.getId(), user.getName(), user.getBirth(), user.getCharacterId(),
user.getMannerTemperature(), user.getOauth().getAuthenticated(), user.getActivityArea(), user.getMbti(),
user.getStatus().name(), user.getGoal(), Job.of(user), user.getInterests());
return new UserMeGetResponse(
user.getId(),
user.getName(),
user.getBirth(),
user.getCharacterId(),
user.getMannerTemperature(),
user.getOauth().getAuthenticated(),
user.getActivityArea(),
user.getMbti(),
user.getStatus().name(),
user.getGoal(),
Job.of(user),
user.getOauth().getAuthenticated().name(),
user.getInterests()
);
}


public record Job(String name, boolean certificated, @JsonProperty("class") String jobClass, String detailClass) {

public static Job of(User user) {
return new Job(user.getJob().getName(), user.getJob().isCertificated(), user.getJob().getJobClass(),
user.getJob().getDetailJobClass());
return new Job(
user.getJob().getName(),
user.getJob().isCertificated(),
user.getJob().getJobClass(),
user.getJob().getDetailJobClass()
);
}
}
}
8 changes: 8 additions & 0 deletions src/test/java/net/teumteum/integration/Api.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ ResponseSpec getUser(String token, Long userId) {
.exchange();
}

ResponseSpec getMe(String token) {
return webTestClient
.get()
.uri("/users/me")
.header(HttpHeaders.AUTHORIZATION, token)
.exchange();
}

ResponseSpec getUsersById(String token, String userIds) {
return webTestClient.get()
.uri("/users?id=" + userIds)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ void Return_my_info_if_valid_token_received() {
var expected = UserMeGetResponse.of(me);

// when
var result = api.getUser(VALID_TOKEN, me.getId());
var result = api.getMe(VALID_TOKEN);

// then
Assertions.assertThat(result.expectStatus().isOk()
Expand Down

0 comments on commit 61df878

Please sign in to comment.