Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
21 changes: 11 additions & 10 deletions .github/workflows/docker-ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,9 @@ name: Docker CI/CD

on:
pull_request:
branches:
- 'develop'
branches: [ develop ]
push:
branches:
- 'develop'

branches: [ develop ]
workflow_dispatch:

jobs:
Expand All @@ -24,6 +21,12 @@ jobs:
java-version: '21'
distribution: 'temurin'

- name: Clone external repo with jar into libs/
run: |
mkdir -p libs
git clone https://x-access-token:${{ secrets.GH_PAT }}@github.com/mosu-dev/mosu-kmc-jar.git temp-jar
cp temp-jar/*.jar libs/

- name: Build with Gradle
run: ./gradlew clean build -x test

Expand All @@ -34,9 +37,7 @@ jobs:
password: ${{ secrets.DOCKER_PASSWORD }}

- name: Build Docker image
run: |
docker build -t kangtaehyun1107/mosu-server:${{ github.sha }} .

run: docker build -t kangtaehyun1107/mosu-server:${{ github.sha }} .
working-directory:
- name: Push Docker image
run: |
docker push kangtaehyun1107/mosu-server:${{ github.sha }}
run: docker push kangtaehyun1107/mosu-server:${{ github.sha }}
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,6 @@ out/

docker-compose/.env
docker-compose/.env.local
/logs/app.log

/logs/**
/libs/**
8 changes: 4 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM openjdk:21-jdk
ARG JAR_FILE=build/libs/*.jar
ADD ${JAR_FILE} app.jar
ENTRYPOINT ["java", "-Duser.timezone=GMT+9", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app.jar"]
FROM amazoncorretto:21
COPY build/libs/*SNAPSHOT.war app.war

ENTRYPOINT ["java", "-Duser.timezone=GMT+9", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app.war"]
24 changes: 21 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ plugins {
id 'java'
id 'org.springframework.boot' version '3.4.5'
id 'io.spring.dependency-management' version '1.1.7'
id 'war'
}

group = 'life.mosu'
Expand All @@ -24,22 +25,26 @@ repositories {
}

dependencies {

implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-validation'
testImplementation 'org.projectlombok:lombok'
testImplementation 'org.projectlombok:lombok'
testCompileOnly 'org.projectlombok:lombok'
testAnnotationProcessor 'org.projectlombok:lombok'
// developmentOnly 'org.springframework.boot:spring-boot-devtools'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

// 인증사 관련 의존성
implementation 'javax.servlet:jstl:1.2'
implementation "org.apache.tomcat.embed:tomcat-embed-jasper"

// swagger
implementation "org.springdoc:springdoc-openapi-starter-webmvc-ui:2.7.0"
implementation "org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.9"
Comment on lines +43 to +47
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify JSP dependency versions for security.

The JSP and servlet dependencies should be checked for known security vulnerabilities, especially since they're handling user authentication flows.


🌐 Web query:

Are there any known security vulnerabilities in javax.servlet:jstl:1.2 and org.apache.tomcat.embed:tomcat-embed-jasper for Spring Boot 3.4.5?

💡 Result:

There are known security vulnerabilities affecting both javax.servlet:jstl:1.2 and, indirectly, some versions of org.apache.tomcat.embed:tomcat-embed-jasper, which you should consider when using them with Spring Boot 3.4.5.

javax.servlet:jstl:1.2

  • This version is affected by a security vulnerability (notably, XXE and Remote Code Execution via XSLT extension) that allows processing of external entities in untrusted XML documents, posing a risk of information disclosure or arbitrary code execution[4][1][7].
  • The vulnerability applies to Standard Taglib up to version 1.2.1 (javax.servlet:jstl:1.2 is affected)[4].
  • Remediation: Use a newer, compatible taglib implementation, such as org.apache.taglibs:taglibs-standard-impl:1.2.5, or jakarta equivalents, as suggested in multiple security advisories[4]. JSTL 1.2 is outdated and not considered secure for modern deployments.

org.apache.tomcat.embed:tomcat-embed-jasper

  • This artifact is a part of the embedded Tomcat used in Spring Boot for JSP/Servlet processing.
  • Recent security disclosures, such as CVE-2025-24813, affect Apache Tomcat itself, specifically in handling HTTP PUT requests, which could allow unauthenticated remote code execution under non-default, uncommon configurations[2]. The vulnerability can affect applications using embedded Tomcat if exploitable configurations are present.
  • Remediation: Use a version of Tomcat (and thus tomcat-embed-jasper) that includes patches for all relevant CVEs (especially CVE-2025-24813). Monitor the official Tomcat security pages for the exact fixed versions[9][6]. Spring Boot does not always include the latest Tomcat by default, so explicit version management may be needed.
  • No direct vulnerabilities in tomcat-embed-jasper itself were listed in Snyk, but the underlying Tomcat engine must be kept up to date[5].

Key Recommendations

  • Avoid javax.servlet:jstl:1.2. If you require JSTL, use a maintained implementation (such as org.apache.taglibs:taglibs-standard-impl:1.2.5) to address known vulnerabilities[4].
  • Ensure Tomcat (embedded via tomcat-embed-jasper) is up to date and at a version patched for known CVEs, especially CVE-2025-24813[2].
  • Regularly review your dependency versions for security advisories.

Caveats & Limitations

  • The identified vulnerabilities depend on application use and configuration. Not all environments may be directly exploitable, but risk remains significant if defaults are used or if untrusted XML/XSLT inputs are processed.
  • No comprehensive vulnerability list for org.apache.tomcat.embed:tomcat-embed-jasper as a standalone artifact was provided[5]; always refer to Tomcat’s official security notifications[9].

In summary: javax.servlet:jstl:1.2 is insecure and should be replaced; keep Tomcat and related embed packages updated to a patched version matching Spring Boot 3.4.5, watching for any new disclosures.

Citations:


Update JSP/Servlet dependencies to secure versions

Please replace the outdated JSTL artifact and pin your embedded Tomcat to a patched release:

• File: build.gradle (lines 43–47)
• Replace javax.servlet:jstl:1.2 (XXE/RCE risk) with a maintained implementation
• Pin tomcat-embed-jasper to a Tomcat version patched for CVE-2025-24813 (and other recent CVEs)

Suggested diff:

-    implementation 'javax.servlet:jstl:1.2'
-    implementation "org.apache.tomcat.embed:tomcat-embed-jasper"
+    implementation 'org.apache.taglibs:taglibs-standard-impl:1.2.5'
+    implementation "org.apache.tomcat.embed:tomcat-embed-jasper:10.1.17"

(Optional) If you’re migrating fully to Jakarta EE 9+, consider:

implementation 'jakarta.servlet.jsp.jstl-api:3.0.0'
implementation 'org.apache.taglibs:taglibs-standard-impl:3.0.0'
🤖 Prompt for AI Agents
In build.gradle around lines 43 to 47, update the JSP/Servlet dependencies to
secure versions by replacing 'javax.servlet:jstl:1.2' with a maintained JSTL
implementation such as 'jakarta.servlet.jsp.jstl-api:3.0.0' and
'org.apache.taglibs:taglibs-standard-impl:3.0.0'. Also, pin
'org.apache.tomcat.embed:tomcat-embed-jasper' to a specific Tomcat version that
includes patches for CVE-2025-24813 and other recent vulnerabilities to ensure
security.


// jwt
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
Expand All @@ -58,6 +63,13 @@ dependencies {
implementation 'org.flywaydb:flyway-mysql'
runtimeOnly 'com.mysql:mysql-connector-j'

// Testcontainers
testImplementation 'org.springframework.boot:spring-boot-testcontainers:3.3.5'
testImplementation 'org.testcontainers:testcontainers:1.19.3'
testImplementation 'org.testcontainers:junit-jupiter:1.19.3'
testImplementation 'org.testcontainers:mysql:1.20.0'


// security
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
Expand Down Expand Up @@ -96,6 +108,12 @@ dependencies {
testImplementation 'org.testcontainers:mysql:1.20.0'
}

configurations.configureEach {
resolutionStrategy {
force 'org.apache.commons:commons-lang3:3.18.0'
}
}

tasks.named('test') {
useJUnitPlatform()
}
Binary file added gradle/.DS_Store
Binary file not shown.
Binary file added src/.DS_Store
Binary file not shown.
Binary file added src/main/.DS_Store
Binary file not shown.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package life.mosu.mosuserver.application.auth;

import jakarta.servlet.http.HttpServletRequest;
import life.mosu.mosuserver.application.auth.provider.AuthTokenManager;
import life.mosu.mosuserver.domain.profile.ProfileJpaRepository;
import life.mosu.mosuserver.domain.user.UserJpaEntity;
import life.mosu.mosuserver.global.exception.CustomRuntimeException;
Expand Down Expand Up @@ -44,7 +44,7 @@ public LoginCommandResponse login(final LoginRequest request) {
}

@Transactional
public Token reissueAccessToken(final HttpServletRequest servletRequest) {
return authTokenManager.reissueAccessToken(servletRequest);
public Token reissueAccessToken(final String refreshTokenHeader) {
return authTokenManager.reissueAccessToken(refreshTokenHeader);
Comment on lines +47 to +48
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

LGTM! Method signature improvement enhances testability and separation of concerns.

The change from HttpServletRequest to String refreshTokenHeader decouples the service layer from HTTP servlet dependencies, making the code more testable and following better architectural principles.

Verify that proper validation is implemented in the controller layer or argument resolver to ensure the refresh token string is valid before reaching this service method:


🏁 Script executed:

#!/bin/bash
# Description: Verify that RefreshTokenHeaderArgumentResolver properly validates the refresh token
# Expected: Find validation logic in the argument resolver or controller

# Search for the RefreshTokenHeaderArgumentResolver implementation
ast-grep --pattern 'class RefreshTokenHeaderArgumentResolver {
  $$$
}'

# Search for RefreshTokenHeader annotation usage and validation
rg -A 10 "@RefreshTokenHeader"

Length of output: 1347


Missing RefreshTokenHeaderArgumentResolver & validation for refreshTokenHeader

I couldn’t find any implementation of RefreshTokenHeaderArgumentResolver or validation logic for the @RefreshTokenHeader parameter. Without it, malformed or missing refresh-token values will reach the service layer unchecked.

Please add and wire up a HandlerMethodArgumentResolver (e.g. RefreshTokenHeaderArgumentResolver) that:

  • Extracts the header value
  • Verifies it’s non-null/non-blank
  • Validates its format (e.g. proper JWT structure)
  • Fails fast with a clear 4xx response on invalid input

Likely locations to update:

  • Create src/main/java/life/mosu/mosuserver/presentation/auth/RefreshTokenHeaderArgumentResolver.java implementing HandlerMethodArgumentResolver
  • Register it in your MVC configuration
  • Ensure controller method in AuthController.java relies on this resolver
🤖 Prompt for AI Agents
In src/main/java/life/mosu/mosuserver/application/auth/AuthService.java around
lines 47-48, the refreshTokenHeader parameter lacks validation and a custom
argument resolver. Create a new class RefreshTokenHeaderArgumentResolver in
src/main/java/life/mosu/mosuserver/presentation/auth/ that implements
HandlerMethodArgumentResolver to extract the refresh token header, check it is
non-null and non-blank, validate its JWT format, and throw a 4xx error on
invalid input. Register this resolver in the MVC configuration so it is used
automatically in controller methods, and update AuthController.java to use the
@RefreshTokenHeader annotation on the parameter to leverage this validation
before reaching the service layer.

}
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package life.mosu.mosuserver.application.auth;

import life.mosu.mosuserver.domain.user.UserJpaEntity;
import lombok.Getter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
Expand All @@ -10,7 +9,9 @@
import java.util.Collection;
import java.util.List;

public record PrincipalDetails(@Getter UserJpaEntity user) implements UserDetails {
public record PrincipalDetails(
UserJpaEntity user
) implements UserDetails {

@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public class PrincipalDetailsService implements UserDetailsService {

@Override
public UserDetails loadUserByUsername(final String username) throws UsernameNotFoundException {
return new PrincipalDetails(userRepository.findByLoginId(username).orElseThrow(() -> new CustomRuntimeException(ErrorCode.USER_NOT_FOUND)));
return new PrincipalDetails(userRepository.findByLoginId(username)
.orElseThrow(() -> new CustomRuntimeException(ErrorCode.USER_NOT_FOUND)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

import life.mosu.mosuserver.application.auth.processor.SignUpAccountStepProcessor;
import life.mosu.mosuserver.application.auth.processor.SignUpProfileStepProcessor;
import life.mosu.mosuserver.application.auth.provider.AuthTokenManager;
import life.mosu.mosuserver.domain.profile.ProfileJpaEntity;
import life.mosu.mosuserver.domain.user.UserJpaEntity;
import life.mosu.mosuserver.presentation.auth.dto.SignUpAccountRequest;
import life.mosu.mosuserver.presentation.auth.dto.SignUpProfileRequest;
import life.mosu.mosuserver.presentation.auth.dto.SignUpRequest;
import life.mosu.mosuserver.presentation.auth.dto.Token;
import lombok.RequiredArgsConstructor;
import org.springframework.security.crypto.password.PasswordEncoder;
Expand All @@ -23,23 +23,20 @@ public class SignUpService {
private final PasswordEncoder passwordEncoder;

@Transactional
public Token signUp(final SignUpRequest request) {
//STEP1 - add account into persistence storage
UserJpaEntity user = doAccountStep(request.signUpAccountStep());

//STEP2 - add profile into persistence storage
doProfileStep(user.getId(), request.signUpProfileStep());
public Token signUp(final SignUpAccountRequest request) {
UserJpaEntity user = doAccountStep(request);

return authTokenManager.generateAuthToken(user);
}

@Transactional
public void registerProfile(final Long userId, final SignUpProfileRequest request) {
ProfileJpaEntity profile = request.toEntity(userId);
signUpProfileStepProcessor.process(profile);
}

private UserJpaEntity doAccountStep(SignUpAccountRequest request) {
UserJpaEntity user = request.toAuthEntity(passwordEncoder);
return signUpAccountStepProcessor.process(user);
}

private void doProfileStep(Long userId, SignUpProfileRequest request) {
ProfileJpaEntity profile = request.toEntity(userId);
signUpProfileStepProcessor.process(profile);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package life.mosu.mosuserver.application.auth.kmc;

import life.mosu.mosuserver.application.auth.kmc.tx.KmcContext;
import life.mosu.mosuserver.application.auth.kmc.tx.KmcTxEventFactory;
import life.mosu.mosuserver.global.tx.TxEvent;
import life.mosu.mosuserver.global.tx.TxEventPublisher;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
public class KmcEventTxService {
private final TxEventPublisher txEventPublisher;
private final KmcTxEventFactory eventFactory;

@Transactional
public void publishIssueEvent(String certNum, Long expiration) {
TxEvent<?> event = eventFactory.create(
KmcContext.ofSuccess(certNum, expiration)
);
txEventPublisher.publish(event);
}
Comment on lines +17 to +23
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add parameter validation for certification number

The method doesn't validate input parameters, which could lead to runtime issues if null or empty values are passed.

Add parameter validation:

@Transactional
public void publishIssueEvent(String certNum, Long expiration) {
+   if (certNum == null || certNum.trim().isEmpty()) {
+       throw new IllegalArgumentException("Certificate number cannot be null or empty");
+   }
+   if (expiration == null || expiration <= 0) {
+       throw new IllegalArgumentException("Expiration must be positive");
+   }
+   
    TxEvent<?> event = eventFactory.create(
            KmcContext.ofSuccess(certNum, expiration)
    );
    txEventPublisher.publish(event);
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Transactional
public void publishIssueEvent(String certNum, Long expiration) {
TxEvent<?> event = eventFactory.create(
KmcContext.ofSuccess(certNum, expiration)
);
txEventPublisher.publish(event);
}
@Transactional
public void publishIssueEvent(String certNum, Long expiration) {
if (certNum == null || certNum.trim().isEmpty()) {
throw new IllegalArgumentException("Certificate number cannot be null or empty");
}
if (expiration == null || expiration <= 0) {
throw new IllegalArgumentException("Expiration must be positive");
}
TxEvent<?> event = eventFactory.create(
KmcContext.ofSuccess(certNum, expiration)
);
txEventPublisher.publish(event);
}
🤖 Prompt for AI Agents
In
src/main/java/life/mosu/mosuserver/application/auth/kmc/KmcEventTxService.java
around lines 17 to 23, the publishIssueEvent method lacks validation for the
certNum parameter. Add checks to ensure certNum is neither null nor empty before
proceeding. If validation fails, throw an appropriate exception such as
IllegalArgumentException with a clear message. This prevents runtime errors
caused by invalid input.


@Transactional
public void publishFailureEvent(String certNum) {
TxEvent<?> event = eventFactory.create(
KmcContext.ofFailure(certNum)
);
txEventPublisher.publish(event);
}
}
Comment on lines +25 to +32
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add parameter validation for failure events

Similar to the success case, the failure event method should validate the certification number parameter.

@Transactional
public void publishFailureEvent(String certNum) {
+   if (certNum == null || certNum.trim().isEmpty()) {
+       throw new IllegalArgumentException("Certificate number cannot be null or empty");
+   }
+   
    TxEvent<?> event = eventFactory.create(
            KmcContext.ofFailure(certNum)
    );
    txEventPublisher.publish(event);
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Transactional
public void publishFailureEvent(String certNum) {
TxEvent<?> event = eventFactory.create(
KmcContext.ofFailure(certNum)
);
txEventPublisher.publish(event);
}
}
@Transactional
public void publishFailureEvent(String certNum) {
if (certNum == null || certNum.trim().isEmpty()) {
throw new IllegalArgumentException("Certificate number cannot be null or empty");
}
TxEvent<?> event = eventFactory.create(
KmcContext.ofFailure(certNum)
);
txEventPublisher.publish(event);
}
}
🤖 Prompt for AI Agents
In
src/main/java/life/mosu/mosuserver/application/auth/kmc/KmcEventTxService.java
around lines 25 to 32, the publishFailureEvent method lacks validation for the
certNum parameter. Add a check at the start of the method to validate certNum
(e.g., ensure it is not null or empty) and handle invalid input appropriately,
such as throwing an IllegalArgumentException, to match the validation approach
used in the success event method.

Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package life.mosu.mosuserver.application.auth.kmc.tx;

import life.mosu.mosuserver.domain.auth.signup.SignUpToken;

public record KmcContext(
String certNum,
Long expiration,
Boolean isSuccess
) {
public static KmcContext ofSuccess(String certNum, Long expiration) {
return new KmcContext(certNum, expiration, true);
}

public static KmcContext ofFailure(String certNum) {
return new KmcContext(certNum, 0L, false);
}
Comment on lines +10 to +16
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add parameter validation to factory methods

The factory methods don't validate input parameters, which could lead to invalid contexts being created.

Add validation to factory methods:

public static KmcContext ofSuccess(String certNum, Long expiration) {
+   if (certNum == null || certNum.trim().isEmpty()) {
+       throw new IllegalArgumentException("Certificate number cannot be null or empty");
+   }
+   if (expiration == null || expiration <= 0) {
+       throw new IllegalArgumentException("Expiration must be positive");
+   }
    return new KmcContext(certNum, expiration, true);
}

public static KmcContext ofFailure(String certNum) {
+   if (certNum == null || certNum.trim().isEmpty()) {
+       throw new IllegalArgumentException("Certificate number cannot be null or empty");
+   }
    return new KmcContext(certNum, 0L, false);
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public static KmcContext ofSuccess(String certNum, Long expiration) {
return new KmcContext(certNum, expiration, true);
}
public static KmcContext ofFailure(String certNum) {
return new KmcContext(certNum, 0L, false);
}
public static KmcContext ofSuccess(String certNum, Long expiration) {
if (certNum == null || certNum.trim().isEmpty()) {
throw new IllegalArgumentException("Certificate number cannot be null or empty");
}
if (expiration == null || expiration <= 0) {
throw new IllegalArgumentException("Expiration must be positive");
}
return new KmcContext(certNum, expiration, true);
}
public static KmcContext ofFailure(String certNum) {
if (certNum == null || certNum.trim().isEmpty()) {
throw new IllegalArgumentException("Certificate number cannot be null or empty");
}
return new KmcContext(certNum, 0L, false);
}
🤖 Prompt for AI Agents
In src/main/java/life/mosu/mosuserver/application/auth/kmc/tx/KmcContext.java
around lines 10 to 16, the factory methods ofSuccess and ofFailure lack input
parameter validation. Add checks to ensure certNum is not null or empty, and for
ofSuccess, verify expiration is a positive value. Throw appropriate exceptions
if validations fail to prevent creation of invalid KmcContext instances.


public SignUpToken toSignUpToken() {
return SignUpToken.of(
this.certNum,
this.expiration
);
}
}
Comment on lines +18 to +24
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider validating success state before token conversion

The toSignUpToken method converts the context to a SignUpToken without checking if the context represents a successful operation. This could create tokens for failed KMC attempts.

Add success state validation:

public SignUpToken toSignUpToken() {
+   if (!isSuccess) {
+       throw new IllegalStateException("Cannot create SignUpToken from failed KMC context");
+   }
    return SignUpToken.of(
        this.certNum,
        this.expiration
    );
}

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/main/java/life/mosu/mosuserver/application/auth/kmc/tx/KmcContext.java
around lines 18 to 24, the toSignUpToken method converts the context to a
SignUpToken without verifying if the context indicates a successful operation.
To fix this, add a check for the success state before creating the SignUpToken,
and only proceed with token creation if the context represents success;
otherwise, handle the failure case appropriately, such as throwing an exception
or returning null.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package life.mosu.mosuserver.application.auth.kmc.tx;

import life.mosu.mosuserver.global.tx.TxEvent;

public class KmcIssueTxEvent extends TxEvent<KmcContext> {

public KmcIssueTxEvent(boolean success, KmcContext context) {
super(success, context);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package life.mosu.mosuserver.application.auth.kmc.tx;

import life.mosu.mosuserver.global.tx.TxEvent;
import life.mosu.mosuserver.global.tx.TxEventFactory;
import org.springframework.stereotype.Component;

@Component
public class KmcTxEventFactory implements TxEventFactory<KmcContext> {

@Override
public TxEvent<?> create(KmcContext context) {
return new KmcIssueTxEvent(context.isSuccess(), context);
}
}
Loading