From e21dea1e18c60bfc8bb425418901a05475d6d7aa Mon Sep 17 00:00:00 2001 From: Lobo Date: Sat, 11 Apr 2026 12:07:27 +0200 Subject: [PATCH] Added lots of new stuff - extended the jwt and put userid into it - completed update settings - added settings also in me call --- .../configuration/AsyncConfig.java | 10 ++++ .../security/JwtAuthenticationFilter.java | 7 ++- .../configuration/security/JwtService.java | 12 ++++- .../configuration/security/UserPrincipal.java | 18 +++++++ .../login/controller/LoginController.java | 3 +- .../user/controller/UserController.java | 21 ++++++--- .../dto/request/UserSettingsRequest.java | 4 ++ .../dto/response/SettingsResponse.java | 7 +++ .../dto/response/UserProfileResponse.java | 2 +- .../user/controller/mapper/ApiMapper.java | 19 +++++++- .../auth_service/domain/user/model/User.java | 2 + .../domain/user/model/UserSettings.java | 11 +++++ .../user/persistence/UserRepository.java | 9 ++++ .../user/persistence/UserRepositoryImpl.java | 44 ++++++++++++++++- .../user/persistence/entities/UserEntity.java | 4 ++ .../entities/UserSettingsEntity.java | 26 ++++++++++ .../user/persistence/mapper/EntityMapper.java | 47 +++++++++++++++---- .../domain/user/service/UserService.java | 15 ++++++ ...plication-dev.yaml => application-dev.yml} | 0 .../{application.yaml => application.yml} | 3 ++ .../db/migration/V2__Add_User_Details.sql | 2 +- .../db/migration/V3__Add_User_Settings.sql | 10 ++++ .../security/JwtServiceTest.java | 23 +++++++-- .../login/controller/LoginControllerTest.java | 2 +- 24 files changed, 271 insertions(+), 30 deletions(-) create mode 100644 src/main/java/auth_service/configuration/AsyncConfig.java create mode 100644 src/main/java/auth_service/configuration/security/UserPrincipal.java create mode 100644 src/main/java/auth_service/domain/user/controller/dto/request/UserSettingsRequest.java create mode 100644 src/main/java/auth_service/domain/user/controller/dto/response/SettingsResponse.java create mode 100644 src/main/java/auth_service/domain/user/model/UserSettings.java create mode 100644 src/main/java/auth_service/domain/user/persistence/entities/UserSettingsEntity.java rename src/main/resources/{application-dev.yaml => application-dev.yml} (100%) rename src/main/resources/{application.yaml => application.yml} (96%) create mode 100644 src/main/resources/db/migration/V3__Add_User_Settings.sql diff --git a/src/main/java/auth_service/configuration/AsyncConfig.java b/src/main/java/auth_service/configuration/AsyncConfig.java new file mode 100644 index 0000000..314bbd0 --- /dev/null +++ b/src/main/java/auth_service/configuration/AsyncConfig.java @@ -0,0 +1,10 @@ +package auth_service.configuration; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableAsync; + +@Configuration +@EnableAsync +public class AsyncConfig { + // This class enables Spring's @Async annotation functionality globally +} \ No newline at end of file diff --git a/src/main/java/auth_service/configuration/security/JwtAuthenticationFilter.java b/src/main/java/auth_service/configuration/security/JwtAuthenticationFilter.java index a74b047..d60cbee 100644 --- a/src/main/java/auth_service/configuration/security/JwtAuthenticationFilter.java +++ b/src/main/java/auth_service/configuration/security/JwtAuthenticationFilter.java @@ -45,10 +45,13 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { try { final String userEmail = jwtService.extractEmail(jwt); + final String userId = jwtService.extractUserId(jwt); - if (userEmail != null && SecurityContextHolder.getContext().getAuthentication() == null) { + if (userEmail != null && userId != null && SecurityContextHolder.getContext().getAuthentication() == null) { + + UserPrincipal principal = new UserPrincipal(userId, userEmail); UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken( - userEmail, + principal, null, Collections.emptyList() ); diff --git a/src/main/java/auth_service/configuration/security/JwtService.java b/src/main/java/auth_service/configuration/security/JwtService.java index 94479d9..ccd9e43 100644 --- a/src/main/java/auth_service/configuration/security/JwtService.java +++ b/src/main/java/auth_service/configuration/security/JwtService.java @@ -28,9 +28,10 @@ public class JwtService { * * @return A signed JWT string */ - public String generateToken(String email) { + public String generateToken(String userId, String email) { return Jwts.builder() .subject(email) + .claim("userId", userId) .issuedAt(new Date(System.currentTimeMillis())) .expiration(new Date(System.currentTimeMillis() + JWT_EXPIRATION_MS)) .signWith(getSigningKey()) @@ -46,6 +47,15 @@ public class JwtService { .getSubject(); } + public String extractUserId(String token) { + return Jwts.parser() + .verifyWith(getSigningKey()) + .build() + .parseSignedClaims(token) + .getPayload() + .get("userId", String.class); + } + public boolean isTokenValid(String token) { try { Jwts.parser() diff --git a/src/main/java/auth_service/configuration/security/UserPrincipal.java b/src/main/java/auth_service/configuration/security/UserPrincipal.java new file mode 100644 index 0000000..ccfa99e --- /dev/null +++ b/src/main/java/auth_service/configuration/security/UserPrincipal.java @@ -0,0 +1,18 @@ +package auth_service.configuration.security; + +import java.security.Principal; + +public record UserPrincipal( + String id, + String email +) implements Principal { + + @Override + public String getName() { + return id; + } + + public long getIdAsLong() { + return Long.parseLong(id); + } +} \ No newline at end of file diff --git a/src/main/java/auth_service/domain/login/controller/LoginController.java b/src/main/java/auth_service/domain/login/controller/LoginController.java index 3d5f5aa..a8faf5a 100644 --- a/src/main/java/auth_service/domain/login/controller/LoginController.java +++ b/src/main/java/auth_service/domain/login/controller/LoginController.java @@ -36,8 +36,7 @@ public class LoginController { var user = ApiMapper.toModel(request); var authenticatedUser = loginService.login(user); - var token = jwtService.generateToken(authenticatedUser.getEmail()); - + var token = jwtService.generateToken(authenticatedUser.getId() + "", authenticatedUser.getEmail()); return ResponseEntity.ok(new LoginResponse("Login successful", token)); } } \ No newline at end of file diff --git a/src/main/java/auth_service/domain/user/controller/UserController.java b/src/main/java/auth_service/domain/user/controller/UserController.java index df3f1d6..66565db 100644 --- a/src/main/java/auth_service/domain/user/controller/UserController.java +++ b/src/main/java/auth_service/domain/user/controller/UserController.java @@ -1,16 +1,15 @@ package auth_service.domain.user.controller; +import auth_service.configuration.security.UserPrincipal; +import auth_service.domain.user.controller.dto.request.UserSettingsRequest; import auth_service.domain.user.controller.dto.response.UserProfileResponse; import auth_service.domain.user.controller.mapper.ApiMapper; import auth_service.domain.user.service.UserService; import io.micrometer.core.annotation.Timed; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import java.security.Principal; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.*; /** * Controller handling user profile operations for the dashboard. @@ -28,11 +27,19 @@ public class UserController { */ @GetMapping(value = "/me", version = "1.0", produces = "application/json") @Timed(value = "user.me.v1.requests.time", description = "Time taken to process v1 user profile requests") - public ResponseEntity getCurrentUserV1(Principal principal) { + public ResponseEntity getCurrentUserV1(@AuthenticationPrincipal UserPrincipal principal) { // this is the email from the login, if a user is not authenticated, it will not even come to this point. - var authenticatedEmail = principal.getName(); + var authenticatedEmail = principal.email(); var profileResponse = this.userService.getUserByEmail(authenticatedEmail); return ResponseEntity.ok(ApiMapper.toApi(profileResponse)); } + + @PutMapping(value = "/settings", version = "1.0", produces = "application/json") + @Timed(value = "user.me.v1.requests.time", description = "Time taken to process v1 user profile requests") + public ResponseEntity updateUserSettings(@AuthenticationPrincipal UserPrincipal principal, + @RequestBody UserSettingsRequest request) { + this.userService.updateUserSettings(principal.getIdAsLong(), request.steamId(), ApiMapper.toDomain(request)); + return ResponseEntity.ok().build(); + } } \ No newline at end of file diff --git a/src/main/java/auth_service/domain/user/controller/dto/request/UserSettingsRequest.java b/src/main/java/auth_service/domain/user/controller/dto/request/UserSettingsRequest.java new file mode 100644 index 0000000..a21a63e --- /dev/null +++ b/src/main/java/auth_service/domain/user/controller/dto/request/UserSettingsRequest.java @@ -0,0 +1,4 @@ +package auth_service.domain.user.controller.dto.request; + +public record UserSettingsRequest(boolean useDarkTheme, String language, long steamId) { +} \ No newline at end of file diff --git a/src/main/java/auth_service/domain/user/controller/dto/response/SettingsResponse.java b/src/main/java/auth_service/domain/user/controller/dto/response/SettingsResponse.java new file mode 100644 index 0000000..5974651 --- /dev/null +++ b/src/main/java/auth_service/domain/user/controller/dto/response/SettingsResponse.java @@ -0,0 +1,7 @@ +package auth_service.domain.user.controller.dto.response; + +import lombok.Builder; + +@Builder +public record SettingsResponse(long id, boolean useDarkTheme, String language) { +} \ No newline at end of file diff --git a/src/main/java/auth_service/domain/user/controller/dto/response/UserProfileResponse.java b/src/main/java/auth_service/domain/user/controller/dto/response/UserProfileResponse.java index 5692bc2..ed71824 100644 --- a/src/main/java/auth_service/domain/user/controller/dto/response/UserProfileResponse.java +++ b/src/main/java/auth_service/domain/user/controller/dto/response/UserProfileResponse.java @@ -5,5 +5,5 @@ import lombok.Builder; import java.time.LocalDateTime; @Builder -public record UserProfileResponse(long id, String email, String role, LocalDateTime lastLogin, LocalDateTime createdDate, long steamId) { +public record UserProfileResponse(long id, String email, String role, LocalDateTime lastLogin, LocalDateTime createdDate, long steamId, SettingsResponse settings) { } \ No newline at end of file diff --git a/src/main/java/auth_service/domain/user/controller/mapper/ApiMapper.java b/src/main/java/auth_service/domain/user/controller/mapper/ApiMapper.java index f7eeb72..fd27464 100644 --- a/src/main/java/auth_service/domain/user/controller/mapper/ApiMapper.java +++ b/src/main/java/auth_service/domain/user/controller/mapper/ApiMapper.java @@ -1,8 +1,11 @@ package auth_service.domain.user.controller.mapper; +import auth_service.domain.user.controller.dto.request.UserSettingsRequest; +import auth_service.domain.user.controller.dto.response.SettingsResponse; import auth_service.domain.user.controller.dto.response.UserProfileResponse; import auth_service.domain.user.model.User; +import auth_service.domain.user.model.UserSettings; public abstract class ApiMapper { private ApiMapper() { @@ -15,6 +18,20 @@ public abstract class ApiMapper { .createdDate(user.getCreatedDate()) .lastLogin(user.getLastLogin()) .steamId(user.getSteamId()) - .role("USER").build(); + .role("USER") + .settings(SettingsResponse.builder() + .id(user.getId()) + .useDarkTheme(user.getSettings().getTheme().equals("dark")) + .language(user.getSettings().getLanguage()) + .build()) + .build(); } + + public static UserSettings toDomain(UserSettingsRequest request) { + return UserSettings.builder() + .theme(request.useDarkTheme() ? "dark" : "light") + .language(request.language()) + .build(); + } + } \ No newline at end of file diff --git a/src/main/java/auth_service/domain/user/model/User.java b/src/main/java/auth_service/domain/user/model/User.java index 924e0e9..bb18bf3 100644 --- a/src/main/java/auth_service/domain/user/model/User.java +++ b/src/main/java/auth_service/domain/user/model/User.java @@ -14,4 +14,6 @@ public class User { private LocalDateTime lastLogin; private LocalDateTime createdDate; private long steamId; + + private UserSettings settings; } \ No newline at end of file diff --git a/src/main/java/auth_service/domain/user/model/UserSettings.java b/src/main/java/auth_service/domain/user/model/UserSettings.java new file mode 100644 index 0000000..694202e --- /dev/null +++ b/src/main/java/auth_service/domain/user/model/UserSettings.java @@ -0,0 +1,11 @@ +package auth_service.domain.user.model; + +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class UserSettings { + private String language; + private String theme; +} \ No newline at end of file diff --git a/src/main/java/auth_service/domain/user/persistence/UserRepository.java b/src/main/java/auth_service/domain/user/persistence/UserRepository.java index 95af5d7..b4c18bb 100644 --- a/src/main/java/auth_service/domain/user/persistence/UserRepository.java +++ b/src/main/java/auth_service/domain/user/persistence/UserRepository.java @@ -2,6 +2,9 @@ package auth_service.domain.user.persistence; import auth_service.domain.user.model.User; +import auth_service.domain.user.model.UserSettings; +import jakarta.transaction.Transactional; +import jakarta.validation.constraints.NotNull; import java.util.Optional; @@ -16,4 +19,10 @@ public interface UserRepository { * @return An Optional containing the user if found */ Optional findByEmail(String email); + + @NotNull + UserSettings findSettingsByUserId(String userId); + + @Transactional + boolean updateSettings(long userId, long steamId, UserSettings settings); } \ No newline at end of file diff --git a/src/main/java/auth_service/domain/user/persistence/UserRepositoryImpl.java b/src/main/java/auth_service/domain/user/persistence/UserRepositoryImpl.java index 1d5c545..249bed8 100644 --- a/src/main/java/auth_service/domain/user/persistence/UserRepositoryImpl.java +++ b/src/main/java/auth_service/domain/user/persistence/UserRepositoryImpl.java @@ -1,14 +1,19 @@ package auth_service.domain.user.persistence; import auth_service.domain.user.model.User; +import auth_service.domain.user.model.UserSettings; import auth_service.domain.user.persistence.entities.UserEntity; +import auth_service.domain.user.persistence.entities.UserSettingsEntity; import auth_service.domain.user.persistence.mapper.EntityMapper; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; import jakarta.persistence.TypedQuery; +import jakarta.transaction.Transactional; +import jakarta.validation.constraints.NotNull; import org.springframework.stereotype.Repository; import java.util.Optional; +import java.util.UUID; @Repository public class UserRepositoryImpl implements UserRepository { @@ -21,7 +26,11 @@ public class UserRepositoryImpl implements UserRepository { var userEntityCriteriaQuery = criteriaBuilder.createQuery(UserEntity.class); var userEntity = userEntityCriteriaQuery.from(UserEntity.class); - // Build the query: SELECT u FROM UserEntity u WHERE u.email = :email + // Fetch the settings eagerly using a LEFT JOIN to prevent N+1 queries. + // A LEFT JOIN ensures the user is returned even if no settings exist yet. + userEntity.fetch("settings", jakarta.persistence.criteria.JoinType.LEFT); + + // Build the query: SELECT u FROM UserEntity u LEFT JOIN FETCH u.settings WHERE u.email = :email userEntityCriteriaQuery.select(userEntity).where(criteriaBuilder.equal(userEntity.get("email"), email)); TypedQuery typedQuery = entityManager.createQuery(userEntityCriteriaQuery); @@ -30,4 +39,37 @@ public class UserRepositoryImpl implements UserRepository { .findFirst() .map(EntityMapper::mapToModel); } + + @Override + public @NotNull UserSettings findSettingsByUserId(String userId) { + UserSettingsEntity entity = entityManager.find(UserSettingsEntity.class, UUID.fromString(userId)); + + if (entity == null) { + // Return defaults if none exist yet + return UserSettings.builder() + .language("") + .theme("light") + .build(); + } + + return UserSettings.builder() + .language(entity.getLanguage()) + .theme(entity.getTheme()) + .build(); + } + + @Transactional + @Override + public boolean updateSettings(long userId, long steamId, UserSettings settings) { + var entity = EntityMapper.toPersistence(userId, settings); + // merge() acts as an upsert: it updates if the ID exists, or inserts if it doesn't. + entityManager.merge(entity); + + var userEntity = entityManager.find(UserEntity.class, userId); + if (userEntity != null && userEntity.getSteamId() != steamId) { + userEntity.setSteamId(steamId); + return true; + } + return false; + } } \ No newline at end of file diff --git a/src/main/java/auth_service/domain/user/persistence/entities/UserEntity.java b/src/main/java/auth_service/domain/user/persistence/entities/UserEntity.java index a016897..3d5c80c 100644 --- a/src/main/java/auth_service/domain/user/persistence/entities/UserEntity.java +++ b/src/main/java/auth_service/domain/user/persistence/entities/UserEntity.java @@ -38,4 +38,8 @@ public class UserEntity { @Column(name = "last_login_date") private LocalDateTime lastLoginDate; + + @OneToOne(cascade = jakarta.persistence.CascadeType.ALL, fetch = jakarta.persistence.FetchType.LAZY) + @jakarta.persistence.PrimaryKeyJoinColumn + private UserSettingsEntity settings; } \ No newline at end of file diff --git a/src/main/java/auth_service/domain/user/persistence/entities/UserSettingsEntity.java b/src/main/java/auth_service/domain/user/persistence/entities/UserSettingsEntity.java new file mode 100644 index 0000000..16ced69 --- /dev/null +++ b/src/main/java/auth_service/domain/user/persistence/entities/UserSettingsEntity.java @@ -0,0 +1,26 @@ +package auth_service.domain.user.persistence.entities; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import lombok.Getter; +import lombok.Setter; + +@Entity +@Table(name = "user_settings") +@Getter +@Setter +public class UserSettingsEntity { + + // No @GeneratedValue! The ID is strictly the user_id from the users table. + @Id + @Column(name = "user_id") + private long userId; + + @Column(nullable = false) + private String language; + + @Column(nullable = false) + private String theme; +} \ No newline at end of file diff --git a/src/main/java/auth_service/domain/user/persistence/mapper/EntityMapper.java b/src/main/java/auth_service/domain/user/persistence/mapper/EntityMapper.java index 666d20f..2f24fe7 100644 --- a/src/main/java/auth_service/domain/user/persistence/mapper/EntityMapper.java +++ b/src/main/java/auth_service/domain/user/persistence/mapper/EntityMapper.java @@ -1,7 +1,9 @@ package auth_service.domain.user.persistence.mapper; import auth_service.domain.user.model.User; +import auth_service.domain.user.model.UserSettings; import auth_service.domain.user.persistence.entities.UserEntity; +import auth_service.domain.user.persistence.entities.UserSettingsEntity; public abstract class EntityMapper { @@ -9,17 +11,42 @@ public abstract class EntityMapper { } public static User mapToModel(UserEntity entity) { - User model = User.builder().build(); - - if (entity != null) { - model.setId(entity.getId()); - model.setEmail(entity.getEmail()); - model.setEncryptedPassword(entity.getPassword()); - model.setLastLogin(entity.getLastLoginDate()); - model.setCreatedDate(entity.getRegistrationDate()); - model.setSteamId(entity.getSteamId()); + if (entity == null) { + return null; } - return model; + // 1. Map the settings if they exist, otherwise use defaults + UserSettings settingsModel; + if (entity.getSettings() != null) { + settingsModel = UserSettings.builder() + .language(entity.getSettings().getLanguage()) + .theme(entity.getSettings().getTheme()) + .build(); + } else { + // Fallback default settings for users without an entry in the database + settingsModel = UserSettings.builder() + .language("en") + .theme("system") + .build(); + } + + // 2. Map the main user fields and attach the settings + return User.builder() + .id(entity.getId()) + .email(entity.getEmail()) + .encryptedPassword(entity.getPassword()) + .lastLogin(entity.getLastLoginDate()) + .createdDate(entity.getRegistrationDate()) + .steamId(entity.getSteamId()) + .settings(settingsModel) + .build(); + } + + public static UserSettingsEntity toPersistence(long userId, UserSettings settings) { + UserSettingsEntity entity = new UserSettingsEntity(); + entity.setUserId(userId); + entity.setLanguage(settings.getLanguage()); + entity.setTheme(settings.getTheme()); + return entity; } } \ No newline at end of file diff --git a/src/main/java/auth_service/domain/user/service/UserService.java b/src/main/java/auth_service/domain/user/service/UserService.java index 8993540..9869eeb 100644 --- a/src/main/java/auth_service/domain/user/service/UserService.java +++ b/src/main/java/auth_service/domain/user/service/UserService.java @@ -2,11 +2,16 @@ package auth_service.domain.user.service; import auth_service.domain.user.exception.UserNotFoundException; import auth_service.domain.user.model.User; +import auth_service.domain.user.model.UserSettings; import auth_service.domain.user.persistence.UserRepository; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.cache.annotation.Cacheable; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +@Slf4j @Service @RequiredArgsConstructor public class UserService { @@ -23,4 +28,14 @@ public class UserService { public User getUserByEmail(String email) { return userRepository.findByEmail(email).orElseThrow(() -> new UserNotFoundException("Could not find user with email " + email)); } + + @Async + @Transactional + public void updateUserSettings(long userId, long steamId, UserSettings userSettings) { + var updated = userRepository.updateSettings(userId, steamId, userSettings); + if (updated) { + log.info("Steam id has changed!"); + } + log.info("User settings has been updated!"); + } } \ No newline at end of file diff --git a/src/main/resources/application-dev.yaml b/src/main/resources/application-dev.yml similarity index 100% rename from src/main/resources/application-dev.yaml rename to src/main/resources/application-dev.yml diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yml similarity index 96% rename from src/main/resources/application.yaml rename to src/main/resources/application.yml index 4166143..bfaa386 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yml @@ -15,6 +15,9 @@ spring: baseline-on-migrate: true # Explicitly state where to look for scripts locations: classpath:db/migration + threads: + virtual: + enabled: true mvc: apiversion: use: diff --git a/src/main/resources/db/migration/V2__Add_User_Details.sql b/src/main/resources/db/migration/V2__Add_User_Details.sql index 3392ebb..9983b0c 100644 --- a/src/main/resources/db/migration/V2__Add_User_Details.sql +++ b/src/main/resources/db/migration/V2__Add_User_Details.sql @@ -1,6 +1,6 @@ -- Create the users table ALTER TABLE users - ADD COLUMN steam_id BIGINT, + ADD COLUMN steam_id BIGINT DEFAULT 0, ADD COLUMN registration_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP, ADD COLUMN last_login_date TIMESTAMP; diff --git a/src/main/resources/db/migration/V3__Add_User_Settings.sql b/src/main/resources/db/migration/V3__Add_User_Settings.sql new file mode 100644 index 0000000..1945856 --- /dev/null +++ b/src/main/resources/db/migration/V3__Add_User_Settings.sql @@ -0,0 +1,10 @@ +CREATE TABLE user_settings +( + user_id BIGSERIAL PRIMARY KEY REFERENCES users (id) ON DELETE CASCADE, + language VARCHAR(10) NOT NULL DEFAULT '', + theme VARCHAR(20) NOT NULL DEFAULT 'light' +); + +INSERT INTO user_settings (user_id, language, theme) +SELECT id, '', 'light' +FROM users; \ No newline at end of file diff --git a/src/test/java/auth_service/configuration/security/JwtServiceTest.java b/src/test/java/auth_service/configuration/security/JwtServiceTest.java index 2f1d687..1a45529 100644 --- a/src/test/java/auth_service/configuration/security/JwtServiceTest.java +++ b/src/test/java/auth_service/configuration/security/JwtServiceTest.java @@ -29,10 +29,11 @@ class JwtServiceTest { @Test void generateToken_Success() { // Arrange + var userId = "0815"; var email = "test@example.com"; // Act - var token = jwtService.generateToken(email); + var token = jwtService.generateToken(userId, email); // Assert assertNotNull(token); @@ -42,8 +43,9 @@ class JwtServiceTest { @Test void extractEmail_Success() { // Arrange + var userId = "0815"; var email = "test@example.com"; - var token = jwtService.generateToken(email); + var token = jwtService.generateToken(userId, email); // Act var extractedEmail = jwtService.extractEmail(token); @@ -52,11 +54,26 @@ class JwtServiceTest { assertEquals(email, extractedEmail); } + @Test + void extractUserId_Success() { + // Arrange + var userId = "0815"; + var email = "test@example.com"; + var token = jwtService.generateToken(userId, email); + + // Act + var extractedUserId = jwtService.extractUserId(token); + + // Assert + assertEquals(userId, extractedUserId); + } + @Test void isTokenValid_Success() { // Arrange + var userId = "0815"; var email = "test@example.com"; - var token = jwtService.generateToken(email); + var token = jwtService.generateToken(userId, email); // Act var isValid = jwtService.isTokenValid(token); diff --git a/src/test/java/auth_service/domain/login/controller/LoginControllerTest.java b/src/test/java/auth_service/domain/login/controller/LoginControllerTest.java index e078a0f..aa0bc61 100644 --- a/src/test/java/auth_service/domain/login/controller/LoginControllerTest.java +++ b/src/test/java/auth_service/domain/login/controller/LoginControllerTest.java @@ -51,7 +51,7 @@ class LoginControllerTest { var request = new LoginRequest("test@example.com", "password"); var authenticatedUser = User.builder().email("test@example.com").build(); when(loginService.login(any(User.class))).thenReturn(authenticatedUser); - when(jwtService.generateToken("test@example.com")).thenReturn("mock-token"); + when(jwtService.generateToken("0815", "test@example.com")).thenReturn("mock-token"); // Act & Assert mockMvc.perform(post("/api/auth/login")