diff --git a/pom.xml b/pom.xml index 553d789..b8de0ce 100644 --- a/pom.xml +++ b/pom.xml @@ -11,16 +11,17 @@ - com.aplp + aplp.backend web 0.1.0-SNAPSHOT aplp-backend APLP — Adaptive Personal Learning Platform (backend) - 21 + 17 0.12.6 2.8.6 + 1.6.3 @@ -50,6 +51,12 @@ ${springdoc.version} + + aplp.backend + core + 1.0-SNAPSHOT + + org.flywaydb flyway-core @@ -58,6 +65,10 @@ org.flywaydb flyway-database-postgresql + + org.springframework.boot + spring-boot-flyway + io.jsonwebtoken @@ -98,6 +109,11 @@ spring-security-test test + + org.springframework.boot + spring-boot-webmvc-test + test + org.springframework.boot spring-boot-devtools @@ -108,6 +124,17 @@ lombok provided + + org.mapstruct + mapstruct + ${mapstruct.version} + + + org.mapstruct + mapstruct-processor + ${mapstruct.version} + provided + diff --git a/src/main/java/com/aplp/backend/AplpBackendApplication.java b/src/main/java/alpl/backend/web/AplpBackendWebApplication.java similarity index 69% rename from src/main/java/com/aplp/backend/AplpBackendApplication.java rename to src/main/java/alpl/backend/web/AplpBackendWebApplication.java index 28af15f..32d88ed 100644 --- a/src/main/java/com/aplp/backend/AplpBackendApplication.java +++ b/src/main/java/alpl/backend/web/AplpBackendWebApplication.java @@ -1,4 +1,4 @@ -package com.aplp.backend; +package aplp.backend.web; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -6,9 +6,9 @@ import org.springframework.boot.context.properties.ConfigurationPropertiesScan; @SpringBootApplication @ConfigurationPropertiesScan -public class AplpBackendApplication { +public class AplpBackendWebApplication { public static void main(String[] args) { - SpringApplication.run(AplpBackendApplication.class, args); + SpringApplication.run(AplpBackendWebApplication.class, args); } } diff --git a/src/main/java/com/aplp/backend/common/api/GlobalExceptionHandler.java b/src/main/java/alpl/backend/web/common/api/GlobalExceptionHandler.java similarity index 93% rename from src/main/java/com/aplp/backend/common/api/GlobalExceptionHandler.java rename to src/main/java/alpl/backend/web/common/api/GlobalExceptionHandler.java index 1187250..0a562c1 100644 --- a/src/main/java/com/aplp/backend/common/api/GlobalExceptionHandler.java +++ b/src/main/java/alpl/backend/web/common/api/GlobalExceptionHandler.java @@ -1,6 +1,8 @@ -package com.aplp.backend.common.api; +package aplp.backend.web.common.api; -import com.aplp.backend.common.error.DomainException; +import aplp.backend.core.common.exception.DomainException; +import aplp.backend.core.common.exception.ErrorCode; +import aplp.backend.core.common.response.ApiError; import jakarta.servlet.http.HttpServletRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -26,7 +28,7 @@ public class GlobalExceptionHandler { @ExceptionHandler(DomainException.class) public ResponseEntity handleDomainException(DomainException ex) { - HttpStatus status = ex.code().httpStatus(); + HttpStatus status = HttpStatus.valueOf(ex.code().status()); return build(status, ex.code().name(), ex.getMessage()); } diff --git a/src/main/java/com/aplp/backend/common/config/CommonConfig.java b/src/main/java/alpl/backend/web/common/config/CommonConfig.java similarity index 86% rename from src/main/java/com/aplp/backend/common/config/CommonConfig.java rename to src/main/java/alpl/backend/web/common/config/CommonConfig.java index 70132ad..add8eb7 100644 --- a/src/main/java/com/aplp/backend/common/config/CommonConfig.java +++ b/src/main/java/alpl/backend/web/common/config/CommonConfig.java @@ -1,4 +1,4 @@ -package com.aplp.backend.common.config; +package aplp.backend.web.common.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/src/main/java/com/aplp/backend/common/config/OpenApiConfig.java b/src/main/java/alpl/backend/web/common/config/OpenApiConfig.java similarity index 95% rename from src/main/java/com/aplp/backend/common/config/OpenApiConfig.java rename to src/main/java/alpl/backend/web/common/config/OpenApiConfig.java index d3fa7ac..3222d73 100644 --- a/src/main/java/com/aplp/backend/common/config/OpenApiConfig.java +++ b/src/main/java/alpl/backend/web/common/config/OpenApiConfig.java @@ -1,4 +1,4 @@ -package com.aplp.backend.common.config; +package aplp.backend.web.common.config; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.enums.SecuritySchemeType; diff --git a/src/main/java/com/aplp/backend/common/security/AuthenticatedUser.java b/src/main/java/alpl/backend/web/common/security/AuthenticatedUser.java similarity index 66% rename from src/main/java/com/aplp/backend/common/security/AuthenticatedUser.java rename to src/main/java/alpl/backend/web/common/security/AuthenticatedUser.java index 2bb531a..d76ffe0 100644 --- a/src/main/java/com/aplp/backend/common/security/AuthenticatedUser.java +++ b/src/main/java/alpl/backend/web/common/security/AuthenticatedUser.java @@ -1,4 +1,4 @@ -package com.aplp.backend.common.security; +package aplp.backend.web.common.security; public record AuthenticatedUser(Long userId, String email, String displayName) { } diff --git a/src/main/java/com/aplp/backend/common/security/CorsProperties.java b/src/main/java/alpl/backend/web/common/security/CorsProperties.java similarity index 83% rename from src/main/java/com/aplp/backend/common/security/CorsProperties.java rename to src/main/java/alpl/backend/web/common/security/CorsProperties.java index 33a1ec8..d729e18 100644 --- a/src/main/java/com/aplp/backend/common/security/CorsProperties.java +++ b/src/main/java/alpl/backend/web/common/security/CorsProperties.java @@ -1,4 +1,4 @@ -package com.aplp.backend.common.security; +package aplp.backend.web.common.security; import org.springframework.boot.context.properties.ConfigurationProperties; diff --git a/src/main/java/com/aplp/backend/common/security/JwtAuthenticationFilter.java b/src/main/java/alpl/backend/web/common/security/JwtAuthenticationFilter.java similarity index 98% rename from src/main/java/com/aplp/backend/common/security/JwtAuthenticationFilter.java rename to src/main/java/alpl/backend/web/common/security/JwtAuthenticationFilter.java index b3f0c39..515516e 100644 --- a/src/main/java/com/aplp/backend/common/security/JwtAuthenticationFilter.java +++ b/src/main/java/alpl/backend/web/common/security/JwtAuthenticationFilter.java @@ -1,4 +1,4 @@ -package com.aplp.backend.common.security; +package aplp.backend.web.common.security; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; diff --git a/src/main/java/com/aplp/backend/common/security/JwtClaims.java b/src/main/java/alpl/backend/web/common/security/JwtClaims.java similarity index 72% rename from src/main/java/com/aplp/backend/common/security/JwtClaims.java rename to src/main/java/alpl/backend/web/common/security/JwtClaims.java index 040efa2..042966e 100644 --- a/src/main/java/com/aplp/backend/common/security/JwtClaims.java +++ b/src/main/java/alpl/backend/web/common/security/JwtClaims.java @@ -1,4 +1,4 @@ -package com.aplp.backend.common.security; +package aplp.backend.web.common.security; import java.time.Instant; diff --git a/src/main/java/com/aplp/backend/common/security/JwtProperties.java b/src/main/java/alpl/backend/web/common/security/JwtProperties.java similarity index 86% rename from src/main/java/com/aplp/backend/common/security/JwtProperties.java rename to src/main/java/alpl/backend/web/common/security/JwtProperties.java index aeaa60e..33eaf60 100644 --- a/src/main/java/com/aplp/backend/common/security/JwtProperties.java +++ b/src/main/java/alpl/backend/web/common/security/JwtProperties.java @@ -1,4 +1,4 @@ -package com.aplp.backend.common.security; +package aplp.backend.web.common.security; import org.springframework.boot.context.properties.ConfigurationProperties; diff --git a/src/main/java/com/aplp/backend/common/security/JwtTokenProvider.java b/src/main/java/alpl/backend/web/common/security/JwtTokenProvider.java similarity index 97% rename from src/main/java/com/aplp/backend/common/security/JwtTokenProvider.java rename to src/main/java/alpl/backend/web/common/security/JwtTokenProvider.java index 69e0fbe..f47192e 100644 --- a/src/main/java/com/aplp/backend/common/security/JwtTokenProvider.java +++ b/src/main/java/alpl/backend/web/common/security/JwtTokenProvider.java @@ -1,4 +1,4 @@ -package com.aplp.backend.common.security; +package aplp.backend.web.common.security; import io.jsonwebtoken.Claims; import io.jsonwebtoken.JwtException; diff --git a/src/main/java/com/aplp/backend/common/security/SecurityConfig.java b/src/main/java/alpl/backend/web/common/security/SecurityConfig.java similarity index 98% rename from src/main/java/com/aplp/backend/common/security/SecurityConfig.java rename to src/main/java/alpl/backend/web/common/security/SecurityConfig.java index c9d9748..c57ce89 100644 --- a/src/main/java/com/aplp/backend/common/security/SecurityConfig.java +++ b/src/main/java/alpl/backend/web/common/security/SecurityConfig.java @@ -1,4 +1,4 @@ -package com.aplp.backend.common.security; +package aplp.backend.web.common.security; import org.springframework.boot.security.autoconfigure.web.servlet.PathRequest; import org.springframework.context.annotation.Bean; diff --git a/src/main/java/com/aplp/backend/common/security/SecurityErrorHandlers.java b/src/main/java/alpl/backend/web/common/security/SecurityErrorHandlers.java similarity index 91% rename from src/main/java/com/aplp/backend/common/security/SecurityErrorHandlers.java rename to src/main/java/alpl/backend/web/common/security/SecurityErrorHandlers.java index 97d5c56..e89c605 100644 --- a/src/main/java/com/aplp/backend/common/security/SecurityErrorHandlers.java +++ b/src/main/java/alpl/backend/web/common/security/SecurityErrorHandlers.java @@ -1,7 +1,7 @@ -package com.aplp.backend.common.security; +package aplp.backend.web.common.security; -import com.aplp.backend.common.api.ApiError; -import com.aplp.backend.common.api.ErrorCode; +import aplp.backend.core.common.exception.ErrorCode; +import aplp.backend.core.common.response.ApiError; import jakarta.servlet.http.HttpServletResponse; import org.slf4j.MDC; import org.springframework.http.HttpStatus; diff --git a/src/main/java/com/aplp/backend/common/security/SecurityUtils.java b/src/main/java/alpl/backend/web/common/security/SecurityUtils.java similarity index 81% rename from src/main/java/com/aplp/backend/common/security/SecurityUtils.java rename to src/main/java/alpl/backend/web/common/security/SecurityUtils.java index 1ca21ac..9a285d6 100644 --- a/src/main/java/com/aplp/backend/common/security/SecurityUtils.java +++ b/src/main/java/alpl/backend/web/common/security/SecurityUtils.java @@ -1,7 +1,7 @@ -package com.aplp.backend.common.security; +package aplp.backend.web.common.security; -import com.aplp.backend.common.api.ErrorCode; -import com.aplp.backend.common.error.DomainException; +import aplp.backend.core.common.exception.DomainException; +import aplp.backend.core.common.exception.ErrorCode; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; diff --git a/src/main/java/com/aplp/backend/common/web/RequestIdFilter.java b/src/main/java/alpl/backend/web/common/web/RequestIdFilter.java similarity index 97% rename from src/main/java/com/aplp/backend/common/web/RequestIdFilter.java rename to src/main/java/alpl/backend/web/common/web/RequestIdFilter.java index 17af56e..2e4239a 100644 --- a/src/main/java/com/aplp/backend/common/web/RequestIdFilter.java +++ b/src/main/java/alpl/backend/web/common/web/RequestIdFilter.java @@ -1,4 +1,4 @@ -package com.aplp.backend.common.web; +package aplp.backend.web.common.web; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; diff --git a/src/main/java/com/aplp/backend/identity/api/AuthController.java b/src/main/java/alpl/backend/web/identity/api/controller/AuthController.java similarity index 66% rename from src/main/java/com/aplp/backend/identity/api/AuthController.java rename to src/main/java/alpl/backend/web/identity/api/controller/AuthController.java index b6d7a2f..b4078cb 100644 --- a/src/main/java/com/aplp/backend/identity/api/AuthController.java +++ b/src/main/java/alpl/backend/web/identity/api/controller/AuthController.java @@ -1,6 +1,10 @@ -package com.aplp.backend.identity.api; +package aplp.backend.web.identity.api.controller; -import com.aplp.backend.identity.application.AuthService; +import aplp.backend.web.identity.application.dtos.AuthResponse; +import aplp.backend.web.identity.application.dtos.LoginRequest; +import aplp.backend.web.identity.application.dtos.RefreshTokenRequest; +import aplp.backend.web.identity.application.dtos.RegisterRequest; +import aplp.backend.web.identity.application.services.AuthService; import jakarta.validation.Valid; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.PostMapping; @@ -22,17 +26,17 @@ public class AuthController { @PostMapping("/register") @ResponseStatus(HttpStatus.CREATED) public AuthResponse register(@Valid @RequestBody RegisterRequest request) { - return AuthResponse.from(authService.register(request.email(), request.password(), request.displayName())); + return authService.register(request.email(), request.password(), request.displayName()); } @PostMapping("/login") public AuthResponse login(@Valid @RequestBody LoginRequest request) { - return AuthResponse.from(authService.login(request.email(), request.password())); + return authService.login(request.email(), request.password()); } @PostMapping("/refresh") public AuthResponse refresh(@Valid @RequestBody RefreshTokenRequest request) { - return AuthResponse.from(authService.refresh(request.refreshToken())); + return authService.refresh(request.refreshToken()); } @PostMapping("/logout") diff --git a/src/main/java/alpl/backend/web/identity/application/dtos/AuthResponse.java b/src/main/java/alpl/backend/web/identity/application/dtos/AuthResponse.java new file mode 100644 index 0000000..332d9bc --- /dev/null +++ b/src/main/java/alpl/backend/web/identity/application/dtos/AuthResponse.java @@ -0,0 +1,13 @@ +package aplp.backend.web.identity.application.dtos; + +public record AuthResponse( + String accessToken, + String refreshToken, + String tokenType, + long expiresIn, + UserDto user +) { + + public record UserDto(Long id, String email, String displayName) { + } +} diff --git a/src/main/java/com/aplp/backend/identity/api/LoginRequest.java b/src/main/java/alpl/backend/web/identity/application/dtos/LoginRequest.java similarity index 82% rename from src/main/java/com/aplp/backend/identity/api/LoginRequest.java rename to src/main/java/alpl/backend/web/identity/application/dtos/LoginRequest.java index f69510f..0178012 100644 --- a/src/main/java/com/aplp/backend/identity/api/LoginRequest.java +++ b/src/main/java/alpl/backend/web/identity/application/dtos/LoginRequest.java @@ -1,4 +1,4 @@ -package com.aplp.backend.identity.api; +package aplp.backend.web.identity.application.dtos; import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; diff --git a/src/main/java/com/aplp/backend/identity/api/RefreshTokenRequest.java b/src/main/java/alpl/backend/web/identity/application/dtos/RefreshTokenRequest.java similarity index 71% rename from src/main/java/com/aplp/backend/identity/api/RefreshTokenRequest.java rename to src/main/java/alpl/backend/web/identity/application/dtos/RefreshTokenRequest.java index 610ea23..079ee7d 100644 --- a/src/main/java/com/aplp/backend/identity/api/RefreshTokenRequest.java +++ b/src/main/java/alpl/backend/web/identity/application/dtos/RefreshTokenRequest.java @@ -1,4 +1,4 @@ -package com.aplp.backend.identity.api; +package aplp.backend.web.identity.application.dtos; import jakarta.validation.constraints.NotBlank; diff --git a/src/main/java/com/aplp/backend/identity/api/RegisterRequest.java b/src/main/java/alpl/backend/web/identity/application/dtos/RegisterRequest.java similarity index 89% rename from src/main/java/com/aplp/backend/identity/api/RegisterRequest.java rename to src/main/java/alpl/backend/web/identity/application/dtos/RegisterRequest.java index 7449aa7..bfc5894 100644 --- a/src/main/java/com/aplp/backend/identity/api/RegisterRequest.java +++ b/src/main/java/alpl/backend/web/identity/application/dtos/RegisterRequest.java @@ -1,4 +1,4 @@ -package com.aplp.backend.identity.api; +package aplp.backend.web.identity.application.dtos; import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; diff --git a/src/main/java/alpl/backend/web/identity/application/mappers/AuthMapper.java b/src/main/java/alpl/backend/web/identity/application/mappers/AuthMapper.java new file mode 100644 index 0000000..ffb536d --- /dev/null +++ b/src/main/java/alpl/backend/web/identity/application/mappers/AuthMapper.java @@ -0,0 +1,11 @@ +package aplp.backend.web.identity.application.mappers; + +import aplp.backend.web.identity.application.dtos.AuthResponse; +import aplp.backend.web.identity.domain.entities.User; +import org.mapstruct.Mapper; + +@Mapper(componentModel = "spring") +public interface AuthMapper { + + AuthResponse.UserDto toUserDto(User user); +} \ No newline at end of file diff --git a/src/main/java/com/aplp/backend/identity/application/AuthService.java b/src/main/java/alpl/backend/web/identity/application/services/AuthService.java similarity index 72% rename from src/main/java/com/aplp/backend/identity/application/AuthService.java rename to src/main/java/alpl/backend/web/identity/application/services/AuthService.java index 6af09dd..0160950 100644 --- a/src/main/java/com/aplp/backend/identity/application/AuthService.java +++ b/src/main/java/alpl/backend/web/identity/application/services/AuthService.java @@ -1,16 +1,20 @@ -package com.aplp.backend.identity.application; +package aplp.backend.web.identity.application.services; -import com.aplp.backend.common.security.AuthenticatedUser; -import com.aplp.backend.common.security.JwtClaims; -import com.aplp.backend.common.security.JwtProperties; -import com.aplp.backend.common.security.JwtTokenProvider; -import com.aplp.backend.identity.domain.EmailAlreadyExistsException; -import com.aplp.backend.identity.domain.InvalidCredentialsException; -import com.aplp.backend.identity.domain.RefreshToken; -import com.aplp.backend.identity.domain.RefreshTokenInvalidException; -import com.aplp.backend.identity.domain.RefreshTokenRepository; -import com.aplp.backend.identity.domain.User; -import com.aplp.backend.identity.domain.UserRepository; +import aplp.backend.core.common.util.TokenHasher; +import aplp.backend.web.common.security.AuthenticatedUser; +import aplp.backend.web.common.security.JwtClaims; +import aplp.backend.web.common.security.JwtProperties; +import aplp.backend.web.common.security.JwtTokenProvider; +import aplp.backend.web.identity.application.dtos.AuthResponse; +import aplp.backend.web.identity.application.mappers.AuthMapper; +import aplp.backend.web.identity.domain.exceptions.EmailAlreadyExistsException; +import aplp.backend.web.identity.domain.exceptions.InvalidCredentialsException; +import aplp.backend.web.identity.domain.entities.RefreshToken; +import aplp.backend.web.identity.domain.exceptions.RefreshTokenInvalidException; +import aplp.backend.web.identity.domain.repositories.RefreshTokenRepository; +import aplp.backend.web.identity.domain.entities.User; +import aplp.backend.web.identity.domain.repositories.UserRepository; +import aplp.backend.web.learner.application.services.LearnerProvisioner; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -27,6 +31,7 @@ public class AuthService { private final JwtTokenProvider tokenProvider; private final JwtProperties jwtProperties; private final LearnerProvisioner learnerProvisioner; + private final AuthMapper authMapper; private final Clock clock; public AuthService(UserRepository userRepository, @@ -35,6 +40,7 @@ public class AuthService { JwtTokenProvider tokenProvider, JwtProperties jwtProperties, LearnerProvisioner learnerProvisioner, + AuthMapper authMapper, Clock clock) { this.userRepository = userRepository; this.refreshTokenRepository = refreshTokenRepository; @@ -42,11 +48,12 @@ public class AuthService { this.tokenProvider = tokenProvider; this.jwtProperties = jwtProperties; this.learnerProvisioner = learnerProvisioner; + this.authMapper = authMapper; this.clock = clock; } @Transactional - public AuthResult register(String email, String rawPassword, String displayName) { + public AuthResponse register(String email, String rawPassword, String displayName) { Instant now = clock.instant(); String normalizedEmail = email.trim().toLowerCase(); if (userRepository.existsByEmail(normalizedEmail)) { @@ -59,7 +66,7 @@ public class AuthService { } @Transactional - public AuthResult login(String email, String rawPassword) { + public AuthResponse login(String email, String rawPassword) { String normalizedEmail = email.trim().toLowerCase(); User user = userRepository.findByEmail(normalizedEmail).orElseThrow(InvalidCredentialsException::new); if (!passwordEncoder.matches(rawPassword, user.passwordHash())) { @@ -69,7 +76,7 @@ public class AuthService { } @Transactional - public AuthResult refresh(String rawRefreshToken) { + public AuthResponse refresh(String rawRefreshToken) { Instant now = clock.instant(); RefreshToken stored = refreshTokenRepository.findByTokenHash(TokenHasher.sha256Hex(rawRefreshToken)) .orElseThrow(RefreshTokenInvalidException::new); @@ -112,7 +119,7 @@ public class AuthService { } } - private AuthResult issueTokens(User user) { + private AuthResponse issueTokens(User user) { Instant now = clock.instant(); AuthenticatedUser principal = new AuthenticatedUser(user.id(), user.email(), user.displayName()); String accessToken = tokenProvider.createAccessToken(principal); @@ -123,6 +130,11 @@ public class AuthService { now.plus(jwtProperties.refreshTokenTtl()), now); refreshTokenRepository.save(refresh); - return new AuthResult(accessToken, rawRefreshToken, jwtProperties.accessTokenTtl().toSeconds(), principal); + return new AuthResponse( + accessToken, + rawRefreshToken, + "Bearer", + jwtProperties.accessTokenTtl().toSeconds(), + authMapper.toUserDto(user)); } } diff --git a/src/main/java/com/aplp/backend/identity/domain/RefreshToken.java b/src/main/java/alpl/backend/web/identity/domain/entities/RefreshToken.java similarity index 64% rename from src/main/java/com/aplp/backend/identity/domain/RefreshToken.java rename to src/main/java/alpl/backend/web/identity/domain/entities/RefreshToken.java index a8e3324..1d69d2f 100644 --- a/src/main/java/com/aplp/backend/identity/domain/RefreshToken.java +++ b/src/main/java/alpl/backend/web/identity/domain/entities/RefreshToken.java @@ -1,15 +1,41 @@ -package com.aplp.backend.identity.domain; +package aplp.backend.web.identity.domain.entities; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import lombok.Getter; import java.time.Instant; +@Getter +@Entity +@Table(name = "refresh_token") public class RefreshToken { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - private final Long userId; - private final String tokenHash; - private final Instant expiresAt; + + @Column(name = "user_id", nullable = false) + private Long userId; + + @Column(name = "token_hash", nullable = false, unique = true, length = 64) + private String tokenHash; + + @Column(name = "expires_at", nullable = false) + private Instant expiresAt; + + @Column(name = "revoked_at") private Instant revokedAt; - private final Instant createdAt; + + @Column(name = "created_at", nullable = false, updatable = false) + private Instant createdAt; + + protected RefreshToken() { + } private RefreshToken(Long id, Long userId, String tokenHash, Instant expiresAt, Instant revokedAt, Instant createdAt) { this.id = id; @@ -64,4 +90,4 @@ public class RefreshToken { public Instant createdAt() { return createdAt; } -} +} \ No newline at end of file diff --git a/src/main/java/com/aplp/backend/identity/domain/User.java b/src/main/java/alpl/backend/web/identity/domain/entities/User.java similarity index 67% rename from src/main/java/com/aplp/backend/identity/domain/User.java rename to src/main/java/alpl/backend/web/identity/domain/entities/User.java index e5ad74c..16a194a 100644 --- a/src/main/java/com/aplp/backend/identity/domain/User.java +++ b/src/main/java/alpl/backend/web/identity/domain/entities/User.java @@ -1,17 +1,48 @@ -package com.aplp.backend.identity.domain; +package aplp.backend.web.identity.domain.entities; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import lombok.Getter; import java.time.Instant; +@Getter +@Entity +@Table(name = "users") public class User { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - private final String email; + + @Column(nullable = false, unique = true, length = 320) + private String email; + + @Column(name = "password_hash", nullable = false) private String passwordHash; + + @Column(name = "display_name", nullable = false, length = 100) private String displayName; + + @Enumerated(EnumType.STRING) + @Column(nullable = false, length = 20) private UserStatus status; - private final Instant createdAt; + + @Column(name = "created_at", nullable = false, updatable = false) + private Instant createdAt; + + @Column(name = "updated_at", nullable = false) private Instant updatedAt; + protected User() { + } + private User(Long id, String email, String passwordHash, String displayName, UserStatus status, Instant createdAt, Instant updatedAt) { this.id = id; @@ -73,4 +104,4 @@ public class User { public Instant updatedAt() { return updatedAt; } -} +} \ No newline at end of file diff --git a/src/main/java/com/aplp/backend/identity/domain/UserStatus.java b/src/main/java/alpl/backend/web/identity/domain/entities/UserStatus.java similarity index 50% rename from src/main/java/com/aplp/backend/identity/domain/UserStatus.java rename to src/main/java/alpl/backend/web/identity/domain/entities/UserStatus.java index e0788e0..0630875 100644 --- a/src/main/java/com/aplp/backend/identity/domain/UserStatus.java +++ b/src/main/java/alpl/backend/web/identity/domain/entities/UserStatus.java @@ -1,4 +1,4 @@ -package com.aplp.backend.identity.domain; +package aplp.backend.web.identity.domain.entities; public enum UserStatus { ACTIVE, diff --git a/src/main/java/com/aplp/backend/identity/domain/EmailAlreadyExistsException.java b/src/main/java/alpl/backend/web/identity/domain/exceptions/EmailAlreadyExistsException.java similarity index 57% rename from src/main/java/com/aplp/backend/identity/domain/EmailAlreadyExistsException.java rename to src/main/java/alpl/backend/web/identity/domain/exceptions/EmailAlreadyExistsException.java index 0010a53..1d478a6 100644 --- a/src/main/java/com/aplp/backend/identity/domain/EmailAlreadyExistsException.java +++ b/src/main/java/alpl/backend/web/identity/domain/exceptions/EmailAlreadyExistsException.java @@ -1,7 +1,7 @@ -package com.aplp.backend.identity.domain; +package aplp.backend.web.identity.domain.exceptions; -import com.aplp.backend.common.api.ErrorCode; -import com.aplp.backend.common.error.DomainException; +import aplp.backend.core.common.exception.DomainException; +import aplp.backend.core.common.exception.ErrorCode; public class EmailAlreadyExistsException extends DomainException { diff --git a/src/main/java/com/aplp/backend/identity/domain/InvalidCredentialsException.java b/src/main/java/alpl/backend/web/identity/domain/exceptions/InvalidCredentialsException.java similarity index 54% rename from src/main/java/com/aplp/backend/identity/domain/InvalidCredentialsException.java rename to src/main/java/alpl/backend/web/identity/domain/exceptions/InvalidCredentialsException.java index e7750a8..20a9f2b 100644 --- a/src/main/java/com/aplp/backend/identity/domain/InvalidCredentialsException.java +++ b/src/main/java/alpl/backend/web/identity/domain/exceptions/InvalidCredentialsException.java @@ -1,7 +1,7 @@ -package com.aplp.backend.identity.domain; +package aplp.backend.web.identity.domain.exceptions; -import com.aplp.backend.common.api.ErrorCode; -import com.aplp.backend.common.error.DomainException; +import aplp.backend.core.common.exception.DomainException; +import aplp.backend.core.common.exception.ErrorCode; public class InvalidCredentialsException extends DomainException { diff --git a/src/main/java/com/aplp/backend/identity/domain/RefreshTokenInvalidException.java b/src/main/java/alpl/backend/web/identity/domain/exceptions/RefreshTokenInvalidException.java similarity index 56% rename from src/main/java/com/aplp/backend/identity/domain/RefreshTokenInvalidException.java rename to src/main/java/alpl/backend/web/identity/domain/exceptions/RefreshTokenInvalidException.java index c34c844..b9711c4 100644 --- a/src/main/java/com/aplp/backend/identity/domain/RefreshTokenInvalidException.java +++ b/src/main/java/alpl/backend/web/identity/domain/exceptions/RefreshTokenInvalidException.java @@ -1,7 +1,7 @@ -package com.aplp.backend.identity.domain; +package aplp.backend.web.identity.domain.exceptions; -import com.aplp.backend.common.api.ErrorCode; -import com.aplp.backend.common.error.DomainException; +import aplp.backend.core.common.exception.DomainException; +import aplp.backend.core.common.exception.ErrorCode; public class RefreshTokenInvalidException extends DomainException { diff --git a/src/main/java/com/aplp/backend/identity/domain/RefreshTokenRepository.java b/src/main/java/alpl/backend/web/identity/domain/repositories/RefreshTokenRepository.java similarity index 68% rename from src/main/java/com/aplp/backend/identity/domain/RefreshTokenRepository.java rename to src/main/java/alpl/backend/web/identity/domain/repositories/RefreshTokenRepository.java index 2f7e0a6..3d9c861 100644 --- a/src/main/java/com/aplp/backend/identity/domain/RefreshTokenRepository.java +++ b/src/main/java/alpl/backend/web/identity/domain/repositories/RefreshTokenRepository.java @@ -1,4 +1,6 @@ -package com.aplp.backend.identity.domain; +package aplp.backend.web.identity.domain.repositories; + +import aplp.backend.web.identity.domain.entities.RefreshToken; import java.util.List; import java.util.Optional; diff --git a/src/main/java/com/aplp/backend/identity/domain/UserRepository.java b/src/main/java/alpl/backend/web/identity/domain/repositories/UserRepository.java similarity index 66% rename from src/main/java/com/aplp/backend/identity/domain/UserRepository.java rename to src/main/java/alpl/backend/web/identity/domain/repositories/UserRepository.java index c9c8879..caad2e3 100644 --- a/src/main/java/com/aplp/backend/identity/domain/UserRepository.java +++ b/src/main/java/alpl/backend/web/identity/domain/repositories/UserRepository.java @@ -1,4 +1,6 @@ -package com.aplp.backend.identity.domain; +package aplp.backend.web.identity.domain.repositories; + +import aplp.backend.web.identity.domain.entities.User; import java.util.Optional; diff --git a/src/main/java/alpl/backend/web/identity/infrastructure/persistence/RefreshTokenJpaRepository.java b/src/main/java/alpl/backend/web/identity/infrastructure/persistence/RefreshTokenJpaRepository.java new file mode 100644 index 0000000..4092d58 --- /dev/null +++ b/src/main/java/alpl/backend/web/identity/infrastructure/persistence/RefreshTokenJpaRepository.java @@ -0,0 +1,14 @@ +package aplp.backend.web.identity.infrastructure.persistence; + +import aplp.backend.web.identity.domain.entities.RefreshToken; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; +import java.util.Optional; + +public interface RefreshTokenJpaRepository extends JpaRepository { + + Optional findByTokenHash(String tokenHash); + + List findAllByUserId(Long userId); +} \ No newline at end of file diff --git a/src/main/java/alpl/backend/web/identity/infrastructure/persistence/RefreshTokenRepositoryImpl.java b/src/main/java/alpl/backend/web/identity/infrastructure/persistence/RefreshTokenRepositoryImpl.java new file mode 100644 index 0000000..e2715d9 --- /dev/null +++ b/src/main/java/alpl/backend/web/identity/infrastructure/persistence/RefreshTokenRepositoryImpl.java @@ -0,0 +1,33 @@ +package aplp.backend.web.identity.infrastructure.persistence; + +import aplp.backend.web.identity.domain.entities.RefreshToken; +import aplp.backend.web.identity.domain.repositories.RefreshTokenRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Optional; + +@Repository +public class RefreshTokenRepositoryImpl implements RefreshTokenRepository { + + private final RefreshTokenJpaRepository jpaRepository; + + public RefreshTokenRepositoryImpl(RefreshTokenJpaRepository jpaRepository) { + this.jpaRepository = jpaRepository; + } + + @Override + public Optional findByTokenHash(String tokenHash) { + return jpaRepository.findByTokenHash(tokenHash); + } + + @Override + public List findAllByUserId(Long userId) { + return jpaRepository.findAllByUserId(userId); + } + + @Override + public RefreshToken save(RefreshToken token) { + return jpaRepository.save(token); + } +} \ No newline at end of file diff --git a/src/main/java/alpl/backend/web/identity/infrastructure/persistence/UserJpaRepository.java b/src/main/java/alpl/backend/web/identity/infrastructure/persistence/UserJpaRepository.java new file mode 100644 index 0000000..ea21d3a --- /dev/null +++ b/src/main/java/alpl/backend/web/identity/infrastructure/persistence/UserJpaRepository.java @@ -0,0 +1,11 @@ +package aplp.backend.web.identity.infrastructure.persistence; + +import aplp.backend.web.identity.domain.entities.User; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface UserJpaRepository extends JpaRepository { + + boolean existsByEmail(String email); + + java.util.Optional findByEmail(String email); +} \ No newline at end of file diff --git a/src/main/java/alpl/backend/web/identity/infrastructure/persistence/UserRepositoryImpl.java b/src/main/java/alpl/backend/web/identity/infrastructure/persistence/UserRepositoryImpl.java new file mode 100644 index 0000000..83da823 --- /dev/null +++ b/src/main/java/alpl/backend/web/identity/infrastructure/persistence/UserRepositoryImpl.java @@ -0,0 +1,37 @@ +package aplp.backend.web.identity.infrastructure.persistence; + +import aplp.backend.web.identity.domain.entities.User; +import aplp.backend.web.identity.domain.repositories.UserRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public class UserRepositoryImpl implements UserRepository { + + private final UserJpaRepository jpaRepository; + + public UserRepositoryImpl(UserJpaRepository jpaRepository) { + this.jpaRepository = jpaRepository; + } + + @Override + public Optional findByEmail(String email) { + return jpaRepository.findByEmail(email); + } + + @Override + public Optional findById(Long id) { + return jpaRepository.findById(id); + } + + @Override + public boolean existsByEmail(String email) { + return jpaRepository.existsByEmail(email); + } + + @Override + public User save(User user) { + return jpaRepository.save(user); + } +} \ No newline at end of file diff --git a/src/main/java/com/aplp/backend/learner/api/LearnerController.java b/src/main/java/alpl/backend/web/learner/api/controller/LearnerController.java similarity index 54% rename from src/main/java/com/aplp/backend/learner/api/LearnerController.java rename to src/main/java/alpl/backend/web/learner/api/controller/LearnerController.java index 4f0f4b1..e013d62 100644 --- a/src/main/java/com/aplp/backend/learner/api/LearnerController.java +++ b/src/main/java/alpl/backend/web/learner/api/controller/LearnerController.java @@ -1,7 +1,10 @@ -package com.aplp.backend.learner.api; +package aplp.backend.web.learner.api.controller; -import com.aplp.backend.common.security.SecurityUtils; -import com.aplp.backend.learner.application.LearnerService; +import aplp.backend.web.common.security.SecurityUtils; +import aplp.backend.web.learner.application.dtos.LearnerProfileResponse; +import aplp.backend.web.learner.application.dtos.UpdateLearnerProfileRequest; +import aplp.backend.web.learner.application.mappers.LearnerMapper; +import aplp.backend.web.learner.application.services.LearnerService; import jakarta.validation.Valid; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PatchMapping; @@ -14,19 +17,21 @@ import org.springframework.web.bind.annotation.RestController; public class LearnerController { private final LearnerService learnerService; + private final LearnerMapper learnerMapper; - public LearnerController(LearnerService learnerService) { + public LearnerController(LearnerService learnerService, LearnerMapper learnerMapper) { this.learnerService = learnerService; + this.learnerMapper = learnerMapper; } @GetMapping public LearnerProfileResponse getMyProfile() { - return LearnerProfileResponse.from(learnerService.getProfile(SecurityUtils.currentUserId())); + return learnerMapper.toResponse(learnerService.getProfile(SecurityUtils.currentUserId())); } @PatchMapping public LearnerProfileResponse updateMyProfile(@Valid @RequestBody UpdateLearnerProfileRequest request) { - return LearnerProfileResponse.from( + return learnerMapper.toResponse( learnerService.updateDisplayName(SecurityUtils.currentUserId(), request.displayName())); } } diff --git a/src/main/java/alpl/backend/web/learner/application/dtos/LearnerProfileResponse.java b/src/main/java/alpl/backend/web/learner/application/dtos/LearnerProfileResponse.java new file mode 100644 index 0000000..f491cd1 --- /dev/null +++ b/src/main/java/alpl/backend/web/learner/application/dtos/LearnerProfileResponse.java @@ -0,0 +1,8 @@ +package aplp.backend.web.learner.application.dtos; + +public record LearnerProfileResponse( + Long id, + Long userId, + String displayName +) { +} diff --git a/src/main/java/com/aplp/backend/learner/api/UpdateLearnerProfileRequest.java b/src/main/java/alpl/backend/web/learner/application/dtos/UpdateLearnerProfileRequest.java similarity index 79% rename from src/main/java/com/aplp/backend/learner/api/UpdateLearnerProfileRequest.java rename to src/main/java/alpl/backend/web/learner/application/dtos/UpdateLearnerProfileRequest.java index da410d9..5dad7a9 100644 --- a/src/main/java/com/aplp/backend/learner/api/UpdateLearnerProfileRequest.java +++ b/src/main/java/alpl/backend/web/learner/application/dtos/UpdateLearnerProfileRequest.java @@ -1,4 +1,4 @@ -package com.aplp.backend.learner.api; +package aplp.backend.web.learner.application.dtos; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Size; diff --git a/src/main/java/alpl/backend/web/learner/application/mappers/LearnerMapper.java b/src/main/java/alpl/backend/web/learner/application/mappers/LearnerMapper.java new file mode 100644 index 0000000..041dd34 --- /dev/null +++ b/src/main/java/alpl/backend/web/learner/application/mappers/LearnerMapper.java @@ -0,0 +1,11 @@ +package aplp.backend.web.learner.application.mappers; + +import aplp.backend.web.learner.application.dtos.LearnerProfileResponse; +import aplp.backend.web.learner.domain.entities.Learner; +import org.mapstruct.Mapper; + +@Mapper(componentModel = "spring") +public interface LearnerMapper { + + LearnerProfileResponse toResponse(Learner learner); +} \ No newline at end of file diff --git a/src/main/java/com/aplp/backend/learner/application/LearnerProvisionerImpl.java b/src/main/java/alpl/backend/web/learner/application/services/LearnerProvisioner.java similarity index 56% rename from src/main/java/com/aplp/backend/learner/application/LearnerProvisionerImpl.java rename to src/main/java/alpl/backend/web/learner/application/services/LearnerProvisioner.java index 29da2c7..bfe9657 100644 --- a/src/main/java/com/aplp/backend/learner/application/LearnerProvisionerImpl.java +++ b/src/main/java/alpl/backend/web/learner/application/services/LearnerProvisioner.java @@ -1,27 +1,25 @@ -package com.aplp.backend.learner.application; +package aplp.backend.web.learner.application.services; -import com.aplp.backend.identity.application.LearnerProvisioner; -import com.aplp.backend.learner.domain.Learner; -import com.aplp.backend.learner.domain.LearnerRepository; +import aplp.backend.web.learner.domain.entities.Learner; +import aplp.backend.web.learner.domain.repositories.LearnerRepository; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.Clock; @Service -public class LearnerProvisionerImpl implements LearnerProvisioner { +public class LearnerProvisioner { private final LearnerRepository learnerRepository; private final Clock clock; - public LearnerProvisionerImpl(LearnerRepository learnerRepository, Clock clock) { + public LearnerProvisioner(LearnerRepository learnerRepository, Clock clock) { this.learnerRepository = learnerRepository; this.clock = clock; } - @Override @Transactional public void provision(Long userId, String displayName) { learnerRepository.save(Learner.create(userId, displayName, clock.instant())); } -} +} \ No newline at end of file diff --git a/src/main/java/com/aplp/backend/learner/application/LearnerService.java b/src/main/java/alpl/backend/web/learner/application/services/LearnerService.java similarity index 56% rename from src/main/java/com/aplp/backend/learner/application/LearnerService.java rename to src/main/java/alpl/backend/web/learner/application/services/LearnerService.java index 5e99231..71d12df 100644 --- a/src/main/java/com/aplp/backend/learner/application/LearnerService.java +++ b/src/main/java/alpl/backend/web/learner/application/services/LearnerService.java @@ -1,8 +1,8 @@ -package com.aplp.backend.learner.application; +package aplp.backend.web.learner.application.services; -import com.aplp.backend.learner.domain.Learner; -import com.aplp.backend.learner.domain.LearnerNotFoundException; -import com.aplp.backend.learner.domain.LearnerRepository; +import aplp.backend.web.learner.domain.entities.Learner; +import aplp.backend.web.learner.domain.exceptions.LearnerNotFoundException; +import aplp.backend.web.learner.domain.repositories.LearnerRepository; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -20,20 +20,15 @@ public class LearnerService { } @Transactional(readOnly = true) - public LearnerProfile getProfile(Long userId) { + public Learner getProfile(Long userId) { return learnerRepository.findByUserId(userId) - .map(LearnerService::toProfile) .orElseThrow(LearnerNotFoundException::new); } @Transactional - public LearnerProfile updateDisplayName(Long userId, String displayName) { + public Learner updateDisplayName(Long userId, String displayName) { Learner learner = learnerRepository.findByUserId(userId).orElseThrow(LearnerNotFoundException::new); learner.updateDisplayName(displayName, clock.instant()); - return toProfile(learnerRepository.save(learner)); - } - - private static LearnerProfile toProfile(Learner learner) { - return new LearnerProfile(learner.id(), learner.userId(), learner.displayName()); + return learnerRepository.save(learner); } } diff --git a/src/main/java/com/aplp/backend/learner/domain/Learner.java b/src/main/java/alpl/backend/web/learner/domain/entities/Learner.java similarity index 62% rename from src/main/java/com/aplp/backend/learner/domain/Learner.java rename to src/main/java/alpl/backend/web/learner/domain/entities/Learner.java index fcbbbe2..c31a4bc 100644 --- a/src/main/java/com/aplp/backend/learner/domain/Learner.java +++ b/src/main/java/alpl/backend/web/learner/domain/entities/Learner.java @@ -1,15 +1,39 @@ -package com.aplp.backend.learner.domain; +package aplp.backend.web.learner.domain.entities; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import lombok.Getter; import java.time.Instant; +@Getter +@Entity +@Table(name = "learner") public class Learner { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - private final Long userId; + + @Column(name = "user_id", nullable = false, unique = true) + private Long userId; + + @Column(name = "display_name", nullable = false, length = 100) private String displayName; - private final Instant createdAt; + + @Column(name = "created_at", nullable = false, updatable = false) + private Instant createdAt; + + @Column(name = "updated_at", nullable = false) private Instant updatedAt; + protected Learner() { + } + private Learner(Long id, Long userId, String displayName, Instant createdAt, Instant updatedAt) { this.id = id; this.userId = userId; @@ -50,4 +74,4 @@ public class Learner { public Instant updatedAt() { return updatedAt; } -} +} \ No newline at end of file diff --git a/src/main/java/com/aplp/backend/learner/domain/LearnerNotFoundException.java b/src/main/java/alpl/backend/web/learner/domain/exceptions/LearnerNotFoundException.java similarity index 53% rename from src/main/java/com/aplp/backend/learner/domain/LearnerNotFoundException.java rename to src/main/java/alpl/backend/web/learner/domain/exceptions/LearnerNotFoundException.java index 731ab78..d66539c 100644 --- a/src/main/java/com/aplp/backend/learner/domain/LearnerNotFoundException.java +++ b/src/main/java/alpl/backend/web/learner/domain/exceptions/LearnerNotFoundException.java @@ -1,7 +1,7 @@ -package com.aplp.backend.learner.domain; +package aplp.backend.web.learner.domain.exceptions; -import com.aplp.backend.common.api.ErrorCode; -import com.aplp.backend.common.error.DomainException; +import aplp.backend.core.common.exception.DomainException; +import aplp.backend.core.common.exception.ErrorCode; public class LearnerNotFoundException extends DomainException { diff --git a/src/main/java/com/aplp/backend/learner/domain/LearnerRepository.java b/src/main/java/alpl/backend/web/learner/domain/repositories/LearnerRepository.java similarity index 57% rename from src/main/java/com/aplp/backend/learner/domain/LearnerRepository.java rename to src/main/java/alpl/backend/web/learner/domain/repositories/LearnerRepository.java index 738815a..68ddf8f 100644 --- a/src/main/java/com/aplp/backend/learner/domain/LearnerRepository.java +++ b/src/main/java/alpl/backend/web/learner/domain/repositories/LearnerRepository.java @@ -1,4 +1,6 @@ -package com.aplp.backend.learner.domain; +package aplp.backend.web.learner.domain.repositories; + +import aplp.backend.web.learner.domain.entities.Learner; import java.util.Optional; diff --git a/src/main/java/alpl/backend/web/learner/infrastructure/persistence/LearnerJpaRepository.java b/src/main/java/alpl/backend/web/learner/infrastructure/persistence/LearnerJpaRepository.java new file mode 100644 index 0000000..f24f0b5 --- /dev/null +++ b/src/main/java/alpl/backend/web/learner/infrastructure/persistence/LearnerJpaRepository.java @@ -0,0 +1,11 @@ +package aplp.backend.web.learner.infrastructure.persistence; + +import aplp.backend.web.learner.domain.entities.Learner; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface LearnerJpaRepository extends JpaRepository { + + Optional findByUserId(Long userId); +} \ No newline at end of file diff --git a/src/main/java/alpl/backend/web/learner/infrastructure/persistence/LearnerRepositoryImpl.java b/src/main/java/alpl/backend/web/learner/infrastructure/persistence/LearnerRepositoryImpl.java new file mode 100644 index 0000000..7f5c53c --- /dev/null +++ b/src/main/java/alpl/backend/web/learner/infrastructure/persistence/LearnerRepositoryImpl.java @@ -0,0 +1,27 @@ +package aplp.backend.web.learner.infrastructure.persistence; + +import aplp.backend.web.learner.domain.entities.Learner; +import aplp.backend.web.learner.domain.repositories.LearnerRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public class LearnerRepositoryImpl implements LearnerRepository { + + private final LearnerJpaRepository jpaRepository; + + public LearnerRepositoryImpl(LearnerJpaRepository jpaRepository) { + this.jpaRepository = jpaRepository; + } + + @Override + public Optional findByUserId(Long userId) { + return jpaRepository.findByUserId(userId); + } + + @Override + public Learner save(Learner learner) { + return jpaRepository.save(learner); + } +} \ No newline at end of file diff --git a/src/main/java/com/aplp/backend/common/api/ApiError.java b/src/main/java/com/aplp/backend/common/api/ApiError.java deleted file mode 100644 index 85004cc..0000000 --- a/src/main/java/com/aplp/backend/common/api/ApiError.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.aplp.backend.common.api; - -import java.time.Instant; - -public record ApiError( - Instant timestamp, - int status, - String error, - String code, - String message, - String traceId -) { - - public static ApiError of(int status, String error, String code, String message, String traceId) { - return new ApiError(Instant.now(), status, error, code, message, traceId); - } -} diff --git a/src/main/java/com/aplp/backend/common/api/ErrorCode.java b/src/main/java/com/aplp/backend/common/api/ErrorCode.java deleted file mode 100644 index 47d074c..0000000 --- a/src/main/java/com/aplp/backend/common/api/ErrorCode.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.aplp.backend.common.api; - -import org.springframework.http.HttpStatus; - -public enum ErrorCode { - - INVALID_ARGUMENT(HttpStatus.BAD_REQUEST), - VALIDATION_FAILED(HttpStatus.BAD_REQUEST), - MALFORMED_REQUEST(HttpStatus.BAD_REQUEST), - UNAUTHENTICATED(HttpStatus.UNAUTHORIZED), - INVALID_CREDENTIALS(HttpStatus.UNAUTHORIZED), - INVALID_REFRESH_TOKEN(HttpStatus.UNAUTHORIZED), - ACCESS_DENIED(HttpStatus.FORBIDDEN), - EMAIL_ALREADY_EXISTS(HttpStatus.CONFLICT), - USER_NOT_FOUND(HttpStatus.NOT_FOUND), - LEARNER_NOT_FOUND(HttpStatus.NOT_FOUND), - INTERNAL_ERROR(HttpStatus.INTERNAL_SERVER_ERROR); - - private final HttpStatus httpStatus; - - ErrorCode(HttpStatus httpStatus) { - this.httpStatus = httpStatus; - } - - public HttpStatus httpStatus() { - return httpStatus; - } -} diff --git a/src/main/java/com/aplp/backend/common/error/DomainException.java b/src/main/java/com/aplp/backend/common/error/DomainException.java deleted file mode 100644 index adc3713..0000000 --- a/src/main/java/com/aplp/backend/common/error/DomainException.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.aplp.backend.common.error; - -import com.aplp.backend.common.api.ErrorCode; - -public class DomainException extends RuntimeException { - - private final ErrorCode code; - - public DomainException(ErrorCode code, String message) { - super(message); - this.code = code; - } - - public ErrorCode code() { - return code; - } -} diff --git a/src/main/java/com/aplp/backend/identity/api/AuthResponse.java b/src/main/java/com/aplp/backend/identity/api/AuthResponse.java deleted file mode 100644 index 9b6f9f2..0000000 --- a/src/main/java/com/aplp/backend/identity/api/AuthResponse.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.aplp.backend.identity.api; - -import com.aplp.backend.identity.application.AuthResult; - -public record AuthResponse( - String accessToken, - String refreshToken, - String tokenType, - long expiresIn, - UserDto user -) { - - public static AuthResponse from(AuthResult result) { - return new AuthResponse( - result.accessToken(), - result.refreshToken(), - "Bearer", - result.expiresInSeconds(), - new UserDto( - result.user().userId(), - result.user().email(), - result.user().displayName())); - } - - public record UserDto(Long id, String email, String displayName) { - } -} diff --git a/src/main/java/com/aplp/backend/identity/application/AuthResult.java b/src/main/java/com/aplp/backend/identity/application/AuthResult.java deleted file mode 100644 index 7f12c9d..0000000 --- a/src/main/java/com/aplp/backend/identity/application/AuthResult.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.aplp.backend.identity.application; - -import com.aplp.backend.common.security.AuthenticatedUser; - -public record AuthResult( - String accessToken, - String refreshToken, - long expiresInSeconds, - AuthenticatedUser user -) { -} diff --git a/src/main/java/com/aplp/backend/identity/application/LearnerProvisioner.java b/src/main/java/com/aplp/backend/identity/application/LearnerProvisioner.java deleted file mode 100644 index 90797bd..0000000 --- a/src/main/java/com/aplp/backend/identity/application/LearnerProvisioner.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.aplp.backend.identity.application; - -public interface LearnerProvisioner { - - void provision(Long userId, String displayName); -} diff --git a/src/main/java/com/aplp/backend/identity/application/TokenHasher.java b/src/main/java/com/aplp/backend/identity/application/TokenHasher.java deleted file mode 100644 index 9eea4ef..0000000 --- a/src/main/java/com/aplp/backend/identity/application/TokenHasher.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.aplp.backend.identity.application; - -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.HexFormat; - -final class TokenHasher { - - private TokenHasher() { - } - - static String sha256Hex(String value) { - try { - byte[] digest = MessageDigest.getInstance("SHA-256").digest(value.getBytes(java.nio.charset.StandardCharsets.UTF_8)); - return HexFormat.of().formatHex(digest); - } catch (NoSuchAlgorithmException e) { - throw new IllegalStateException("SHA-256 not available", e); - } - } -} diff --git a/src/main/java/com/aplp/backend/identity/persistence/RefreshTokenJpaEntity.java b/src/main/java/com/aplp/backend/identity/persistence/RefreshTokenJpaEntity.java deleted file mode 100644 index 85f3249..0000000 --- a/src/main/java/com/aplp/backend/identity/persistence/RefreshTokenJpaEntity.java +++ /dev/null @@ -1,95 +0,0 @@ -package com.aplp.backend.identity.persistence; - -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.Table; - -import java.time.Instant; - -@Entity -@Table(name = "refresh_token") -public class RefreshTokenJpaEntity { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @Column(name = "user_id", nullable = false) - private Long userId; - - @Column(name = "token_hash", nullable = false, unique = true, length = 64) - private String tokenHash; - - @Column(name = "expires_at", nullable = false) - private Instant expiresAt; - - @Column(name = "revoked_at") - private Instant revokedAt; - - @Column(name = "created_at", nullable = false, updatable = false) - private Instant createdAt; - - protected RefreshTokenJpaEntity() { - } - - public RefreshTokenJpaEntity(Long id, Long userId, String tokenHash, Instant expiresAt, - Instant revokedAt, Instant createdAt) { - this.id = id; - this.userId = userId; - this.tokenHash = tokenHash; - this.expiresAt = expiresAt; - this.revokedAt = revokedAt; - this.createdAt = createdAt; - } - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public Long getUserId() { - return userId; - } - - public void setUserId(Long userId) { - this.userId = userId; - } - - public String getTokenHash() { - return tokenHash; - } - - public void setTokenHash(String tokenHash) { - this.tokenHash = tokenHash; - } - - public Instant getExpiresAt() { - return expiresAt; - } - - public void setExpiresAt(Instant expiresAt) { - this.expiresAt = expiresAt; - } - - public Instant getRevokedAt() { - return revokedAt; - } - - public void setRevokedAt(Instant revokedAt) { - this.revokedAt = revokedAt; - } - - public Instant getCreatedAt() { - return createdAt; - } - - public void setCreatedAt(Instant createdAt) { - this.createdAt = createdAt; - } -} diff --git a/src/main/java/com/aplp/backend/identity/persistence/RefreshTokenJpaRepository.java b/src/main/java/com/aplp/backend/identity/persistence/RefreshTokenJpaRepository.java deleted file mode 100644 index c809593..0000000 --- a/src/main/java/com/aplp/backend/identity/persistence/RefreshTokenJpaRepository.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.aplp.backend.identity.persistence; - -import org.springframework.data.jpa.repository.JpaRepository; - -import java.util.List; -import java.util.Optional; - -public interface RefreshTokenJpaRepository extends JpaRepository { - - Optional findByTokenHash(String tokenHash); - - List findAllByUserId(Long userId); -} diff --git a/src/main/java/com/aplp/backend/identity/persistence/RefreshTokenRepositoryImpl.java b/src/main/java/com/aplp/backend/identity/persistence/RefreshTokenRepositoryImpl.java deleted file mode 100644 index 71571e0..0000000 --- a/src/main/java/com/aplp/backend/identity/persistence/RefreshTokenRepositoryImpl.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.aplp.backend.identity.persistence; - -import com.aplp.backend.identity.domain.RefreshToken; -import com.aplp.backend.identity.domain.RefreshTokenRepository; -import org.springframework.stereotype.Repository; - -import java.util.List; -import java.util.Optional; - -@Repository -public class RefreshTokenRepositoryImpl implements RefreshTokenRepository { - - private final RefreshTokenJpaRepository jpaRepository; - - public RefreshTokenRepositoryImpl(RefreshTokenJpaRepository jpaRepository) { - this.jpaRepository = jpaRepository; - } - - @Override - public Optional findByTokenHash(String tokenHash) { - return jpaRepository.findByTokenHash(tokenHash).map(RefreshTokenRepositoryImpl::toDomain); - } - - @Override - public List findAllByUserId(Long userId) { - return jpaRepository.findAllByUserId(userId).stream() - .map(RefreshTokenRepositoryImpl::toDomain) - .toList(); - } - - @Override - public RefreshToken save(RefreshToken token) { - RefreshTokenJpaEntity entity = toEntity(token); - RefreshTokenJpaEntity saved = jpaRepository.save(entity); - return toDomain(saved); - } - - private static RefreshTokenJpaEntity toEntity(RefreshToken token) { - return new RefreshTokenJpaEntity( - token.id(), - token.userId(), - token.tokenHash(), - token.expiresAt(), - token.revokedAt(), - token.createdAt()); - } - - private static RefreshToken toDomain(RefreshTokenJpaEntity entity) { - return RefreshToken.reconstruct( - entity.getId(), - entity.getUserId(), - entity.getTokenHash(), - entity.getExpiresAt(), - entity.getRevokedAt(), - entity.getCreatedAt()); - } -} diff --git a/src/main/java/com/aplp/backend/identity/persistence/UserJpaEntity.java b/src/main/java/com/aplp/backend/identity/persistence/UserJpaEntity.java deleted file mode 100644 index 5daff59..0000000 --- a/src/main/java/com/aplp/backend/identity/persistence/UserJpaEntity.java +++ /dev/null @@ -1,111 +0,0 @@ -package com.aplp.backend.identity.persistence; - -import com.aplp.backend.identity.domain.UserStatus; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.EnumType; -import jakarta.persistence.Enumerated; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.Table; - -import java.time.Instant; - -@Entity -@Table(name = "users") -public class UserJpaEntity { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @Column(nullable = false, unique = true, length = 320) - private String email; - - @Column(name = "password_hash", nullable = false) - private String passwordHash; - - @Column(name = "display_name", nullable = false, length = 100) - private String displayName; - - @Enumerated(EnumType.STRING) - @Column(nullable = false, length = 20) - private UserStatus status; - - @Column(name = "created_at", nullable = false, updatable = false) - private Instant createdAt; - - @Column(name = "updated_at", nullable = false) - private Instant updatedAt; - - protected UserJpaEntity() { - } - - public UserJpaEntity(Long id, String email, String passwordHash, String displayName, - UserStatus status, Instant createdAt, Instant updatedAt) { - this.id = id; - this.email = email; - this.passwordHash = passwordHash; - this.displayName = displayName; - this.status = status; - this.createdAt = createdAt; - this.updatedAt = updatedAt; - } - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getEmail() { - return email; - } - - public void setEmail(String email) { - this.email = email; - } - - public String getPasswordHash() { - return passwordHash; - } - - public void setPasswordHash(String passwordHash) { - this.passwordHash = passwordHash; - } - - public String getDisplayName() { - return displayName; - } - - public void setDisplayName(String displayName) { - this.displayName = displayName; - } - - public UserStatus getStatus() { - return status; - } - - public void setStatus(UserStatus status) { - this.status = status; - } - - public Instant getCreatedAt() { - return createdAt; - } - - public void setCreatedAt(Instant createdAt) { - this.createdAt = createdAt; - } - - public Instant getUpdatedAt() { - return updatedAt; - } - - public void setUpdatedAt(Instant updatedAt) { - this.updatedAt = updatedAt; - } -} diff --git a/src/main/java/com/aplp/backend/identity/persistence/UserJpaRepository.java b/src/main/java/com/aplp/backend/identity/persistence/UserJpaRepository.java deleted file mode 100644 index d4621e0..0000000 --- a/src/main/java/com/aplp/backend/identity/persistence/UserJpaRepository.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.aplp.backend.identity.persistence; - -import org.springframework.data.jpa.repository.JpaRepository; - -public interface UserJpaRepository extends JpaRepository { - - boolean existsByEmail(String email); - - java.util.Optional findByEmail(String email); -} diff --git a/src/main/java/com/aplp/backend/identity/persistence/UserRepositoryImpl.java b/src/main/java/com/aplp/backend/identity/persistence/UserRepositoryImpl.java deleted file mode 100644 index a562770..0000000 --- a/src/main/java/com/aplp/backend/identity/persistence/UserRepositoryImpl.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.aplp.backend.identity.persistence; - -import com.aplp.backend.identity.domain.User; -import com.aplp.backend.identity.domain.UserRepository; -import org.springframework.stereotype.Repository; - -import java.util.Optional; - -@Repository -public class UserRepositoryImpl implements UserRepository { - - private final UserJpaRepository jpaRepository; - - public UserRepositoryImpl(UserJpaRepository jpaRepository) { - this.jpaRepository = jpaRepository; - } - - @Override - public Optional findByEmail(String email) { - return jpaRepository.findByEmail(email).map(UserRepositoryImpl::toDomain); - } - - @Override - public Optional findById(Long id) { - return jpaRepository.findById(id).map(UserRepositoryImpl::toDomain); - } - - @Override - public boolean existsByEmail(String email) { - return jpaRepository.existsByEmail(email); - } - - @Override - public User save(User user) { - UserJpaEntity entity = toEntity(user); - UserJpaEntity saved = jpaRepository.save(entity); - return toDomain(saved); - } - - private static UserJpaEntity toEntity(User user) { - return new UserJpaEntity( - user.id(), - user.email(), - user.passwordHash(), - user.displayName(), - user.status(), - user.createdAt(), - user.updatedAt()); - } - - private static User toDomain(UserJpaEntity entity) { - return User.reconstruct( - entity.getId(), - entity.getEmail(), - entity.getPasswordHash(), - entity.getDisplayName(), - entity.getStatus(), - entity.getCreatedAt(), - entity.getUpdatedAt()); - } -} diff --git a/src/main/java/com/aplp/backend/learner/api/LearnerProfileResponse.java b/src/main/java/com/aplp/backend/learner/api/LearnerProfileResponse.java deleted file mode 100644 index b081936..0000000 --- a/src/main/java/com/aplp/backend/learner/api/LearnerProfileResponse.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.aplp.backend.learner.api; - -import com.aplp.backend.learner.application.LearnerProfile; - -public record LearnerProfileResponse( - Long id, - Long userId, - String displayName -) { - - public static LearnerProfileResponse from(LearnerProfile profile) { - return new LearnerProfileResponse(profile.id(), profile.userId(), profile.displayName()); - } -} diff --git a/src/main/java/com/aplp/backend/learner/application/LearnerProfile.java b/src/main/java/com/aplp/backend/learner/application/LearnerProfile.java deleted file mode 100644 index 7d214cb..0000000 --- a/src/main/java/com/aplp/backend/learner/application/LearnerProfile.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.aplp.backend.learner.application; - -public record LearnerProfile( - Long id, - Long userId, - String displayName -) { -} diff --git a/src/main/java/com/aplp/backend/learner/persistence/LearnerJpaEntity.java b/src/main/java/com/aplp/backend/learner/persistence/LearnerJpaEntity.java deleted file mode 100644 index 8a217ea..0000000 --- a/src/main/java/com/aplp/backend/learner/persistence/LearnerJpaEntity.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.aplp.backend.learner.persistence; - -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.Table; - -import java.time.Instant; - -@Entity -@Table(name = "learner") -public class LearnerJpaEntity { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @Column(name = "user_id", nullable = false, unique = true) - private Long userId; - - @Column(name = "display_name", nullable = false, length = 100) - private String displayName; - - @Column(name = "created_at", nullable = false, updatable = false) - private Instant createdAt; - - @Column(name = "updated_at", nullable = false) - private Instant updatedAt; - - protected LearnerJpaEntity() { - } - - public LearnerJpaEntity(Long id, Long userId, String displayName, Instant createdAt, Instant updatedAt) { - this.id = id; - this.userId = userId; - this.displayName = displayName; - this.createdAt = createdAt; - this.updatedAt = updatedAt; - } - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public Long getUserId() { - return userId; - } - - public void setUserId(Long userId) { - this.userId = userId; - } - - public String getDisplayName() { - return displayName; - } - - public void setDisplayName(String displayName) { - this.displayName = displayName; - } - - public Instant getCreatedAt() { - return createdAt; - } - - public void setCreatedAt(Instant createdAt) { - this.createdAt = createdAt; - } - - public Instant getUpdatedAt() { - return updatedAt; - } - - public void setUpdatedAt(Instant updatedAt) { - this.updatedAt = updatedAt; - } -} diff --git a/src/main/java/com/aplp/backend/learner/persistence/LearnerJpaRepository.java b/src/main/java/com/aplp/backend/learner/persistence/LearnerJpaRepository.java deleted file mode 100644 index 7e23491..0000000 --- a/src/main/java/com/aplp/backend/learner/persistence/LearnerJpaRepository.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.aplp.backend.learner.persistence; - -import org.springframework.data.jpa.repository.JpaRepository; - -import java.util.Optional; - -public interface LearnerJpaRepository extends JpaRepository { - - Optional findByUserId(Long userId); -} diff --git a/src/main/java/com/aplp/backend/learner/persistence/LearnerRepositoryImpl.java b/src/main/java/com/aplp/backend/learner/persistence/LearnerRepositoryImpl.java deleted file mode 100644 index 951d7d7..0000000 --- a/src/main/java/com/aplp/backend/learner/persistence/LearnerRepositoryImpl.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.aplp.backend.learner.persistence; - -import com.aplp.backend.learner.domain.Learner; -import com.aplp.backend.learner.domain.LearnerRepository; -import org.springframework.stereotype.Repository; - -import java.util.Optional; - -@Repository -public class LearnerRepositoryImpl implements LearnerRepository { - - private final LearnerJpaRepository jpaRepository; - - public LearnerRepositoryImpl(LearnerJpaRepository jpaRepository) { - this.jpaRepository = jpaRepository; - } - - @Override - public Optional findByUserId(Long userId) { - return jpaRepository.findByUserId(userId).map(LearnerRepositoryImpl::toDomain); - } - - @Override - public Learner save(Learner learner) { - LearnerJpaEntity entity = toEntity(learner); - return toDomain(jpaRepository.save(entity)); - } - - private static LearnerJpaEntity toEntity(Learner learner) { - return new LearnerJpaEntity( - learner.id(), - learner.userId(), - learner.displayName(), - learner.createdAt(), - learner.updatedAt()); - } - - private static Learner toDomain(LearnerJpaEntity entity) { - return Learner.reconstruct( - entity.getId(), - entity.getUserId(), - entity.getDisplayName(), - entity.getCreatedAt(), - entity.getUpdatedAt()); - } -} diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 4ed5fc5..ba84567 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -13,4 +13,4 @@ spring: logging: level: - com.aplp.backend: DEBUG + aplp.backend.web: DEBUG diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index 6d30af1..80b0a46 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -8,4 +8,4 @@ spring: logging: level: - com.aplp.backend: INFO + aplp.backend.web: INFO diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 7c672f4..0844323 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,6 +1,6 @@ spring: application: - name: aplp-backend + name: aplp-backend-web profiles: default: dev jpa: diff --git a/src/test/java/com/aplp/backend/AuthFlowIntegrationTest.java b/src/test/java/aplp/backend/web/AuthFlowIntegrationTest.java similarity index 97% rename from src/test/java/com/aplp/backend/AuthFlowIntegrationTest.java rename to src/test/java/aplp/backend/web/AuthFlowIntegrationTest.java index e7f91d9..74f914c 100644 --- a/src/test/java/com/aplp/backend/AuthFlowIntegrationTest.java +++ b/src/test/java/aplp/backend/web/AuthFlowIntegrationTest.java @@ -1,10 +1,10 @@ -package com.aplp.backend; +package aplp.backend.web; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; +import tools.jackson.databind.JsonNode; +import tools.jackson.databind.ObjectMapper; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.http.MediaType; import org.springframework.test.context.ActiveProfiles; diff --git a/src/test/java/com/aplp/backend/JwtTokenProviderTest.java b/src/test/java/aplp/backend/web/JwtTokenProviderTest.java similarity index 86% rename from src/test/java/com/aplp/backend/JwtTokenProviderTest.java rename to src/test/java/aplp/backend/web/JwtTokenProviderTest.java index ec89f7f..eae017f 100644 --- a/src/test/java/com/aplp/backend/JwtTokenProviderTest.java +++ b/src/test/java/aplp/backend/web/JwtTokenProviderTest.java @@ -1,6 +1,6 @@ -package com.aplp.backend; +package aplp.backend.web; -import com.aplp.backend.common.security.JwtTokenProvider; +import aplp.backend.web.common.security.JwtTokenProvider; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @@ -17,7 +17,7 @@ class JwtTokenProviderTest { @Test void createsAndParsesAccessToken() { - var user = new com.aplp.backend.common.security.AuthenticatedUser(42L, "a@b.c", "Nam"); + var user = new aplp.backend.web.common.security.AuthenticatedUser(42L, "a@b.c", "Nam"); String token = tokenProvider.createAccessToken(user); var claims = tokenProvider.parse(token);