Public Access
Refactor package structure: domain -> modules
Move domain packages into a new modules.* hierarchy and rename controller packages to api.* across login, registration, and user modules. Update package declarations and imports (including shared.api DTOs and JwtService -> modules login TokenGenerator), adjust tests and persistence/mapper paths accordingly, and apply minor formatting fixes (missing EOF newlines). This reorganizes the project to better separate API surface and module boundaries.
This commit is contained in:
1 parent
815347325a
commit
fd390ac072
60 files changed
+192
-187
No files matched your search
@@ -19,20 +19,20 @@ The project strictly follows a Domain-Driven / Clean Architecture (Ports & Adapt
|
||||
|
||||
### Layer Breakdown
|
||||
|
||||
1. **Controller / Web Layer (`controller`)**
|
||||
1. **API / Web Layer (`api`)**
|
||||
* Contains REST endpoints, DTOs (`Request`/`Response` records), and Global Exception Handlers.
|
||||
* Uses `ApiMapper` to map between DTOs and Domain Models.
|
||||
* **Rule:** This layer delegates to the Service layer and never accesses persistence directly.
|
||||
|
||||
2. **Domain / Core Layer (`model`, `service`, `exception`)**
|
||||
2. **Business / Core Layer (`model`, `service`, `exception`)**
|
||||
* The heart of the application. Contains pure Java classes (Models) and Business Logic (Services).
|
||||
* Throws specific business exceptions (e.g., `InvalidCredentialsException`).
|
||||
* **Rule:** This layer has **no dependencies** on the Controller or Persistence layer. It defines interfaces that the persistence layer must implement.
|
||||
* **Rule:** This layer has **no dependencies** on the API or Persistence layer. It defines interfaces that the persistence layer must implement.
|
||||
|
||||
3. **Persistence Layer (`persistence`)**
|
||||
* Handles database operations. Contains JPA Entities (`UserEntity`), Spring Data Repositories, and the `EntityMapper`.
|
||||
* Implements the interfaces defined in the Domain layer.
|
||||
* **Rule:** Entities never leak into the Controller layer.
|
||||
* **Rule:** Entities never leak into the API layer.
|
||||
|
||||
*Note: Future implementations will include ArchUnit tests to automatically enforce these architectural boundaries during the CI pipeline.*
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package auth_service.configuration.security;
|
||||
|
||||
import auth_service.domain.login.service.TokenGenerator;
|
||||
import auth_service.modules.login.service.TokenGenerator;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.security.Keys;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
+6
-6
@@ -1,9 +1,9 @@
|
||||
package auth_service.domain.login.controller;
|
||||
package auth_service.modules.login.api;
|
||||
|
||||
import auth_service.domain.login.controller.dto.request.LoginRequest;
|
||||
import auth_service.domain.login.controller.dto.response.LoginResponse;
|
||||
import auth_service.domain.login.controller.mapper.ApiMapper;
|
||||
import auth_service.domain.login.service.LoginService;
|
||||
import auth_service.modules.login.api.dto.request.LoginRequest;
|
||||
import auth_service.modules.login.api.dto.response.LoginResponse;
|
||||
import auth_service.modules.login.api.mapper.ApiMapper;
|
||||
import auth_service.modules.login.service.LoginService;
|
||||
import io.micrometer.core.annotation.Timed;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@@ -13,7 +13,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* Controller handling authentication requests.
|
||||
* API handling authentication requests.
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/auth")
|
||||
+4
-4
@@ -1,8 +1,8 @@
|
||||
package auth_service.domain.login.controller;
|
||||
package auth_service.modules.login.api;
|
||||
|
||||
import auth_service.shared.controller.dto.response.ErrorResponse;
|
||||
import auth_service.domain.login.exception.InvalidCredentialsException;
|
||||
import auth_service.domain.login.exception.UserNotFoundException;
|
||||
import auth_service.shared.api.dto.response.ErrorResponse;
|
||||
import auth_service.modules.login.exception.InvalidCredentialsException;
|
||||
import auth_service.modules.login.exception.UserNotFoundException;
|
||||
import lombok.NonNull;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.core.annotation.Order;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package auth_service.domain.login.controller.dto.request;
|
||||
package auth_service.modules.login.api.dto.request;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package auth_service.domain.login.controller.dto.response;
|
||||
package auth_service.modules.login.api.dto.response;
|
||||
|
||||
/**
|
||||
* DTO representing the outgoing login response.
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
package auth_service.domain.login.controller.mapper;
|
||||
package auth_service.modules.login.api.mapper;
|
||||
|
||||
import auth_service.domain.login.controller.dto.request.LoginRequest;
|
||||
import auth_service.domain.login.model.User;
|
||||
import auth_service.modules.login.api.dto.request.LoginRequest;
|
||||
import auth_service.modules.login.model.User;
|
||||
|
||||
public abstract class ApiMapper {
|
||||
private ApiMapper() {
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package auth_service.domain.login.exception;
|
||||
package auth_service.modules.login.exception;
|
||||
|
||||
public class InvalidCredentialsException extends RuntimeException {
|
||||
public InvalidCredentialsException(String message) {
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package auth_service.domain.login.exception;
|
||||
package auth_service.modules.login.exception;
|
||||
|
||||
public class UserNotFoundException extends RuntimeException {
|
||||
public UserNotFoundException(String message) {
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package auth_service.domain.login.model;
|
||||
package auth_service.modules.login.model;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
package auth_service.domain.login.persistence;
|
||||
package auth_service.modules.login.persistence;
|
||||
|
||||
import auth_service.domain.login.model.User;
|
||||
import auth_service.modules.login.model.User;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
+4
-4
@@ -1,8 +1,8 @@
|
||||
package auth_service.domain.login.persistence;
|
||||
package auth_service.modules.login.persistence;
|
||||
|
||||
import auth_service.domain.login.model.User;
|
||||
import auth_service.domain.login.persistence.entities.MinimalUserEntity;
|
||||
import auth_service.domain.login.persistence.mapper.EntityMapper;
|
||||
import auth_service.modules.login.model.User;
|
||||
import auth_service.modules.login.persistence.entities.MinimalUserEntity;
|
||||
import auth_service.modules.login.persistence.mapper.EntityMapper;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.PersistenceContext;
|
||||
import jakarta.persistence.TypedQuery;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package auth_service.domain.login.persistence.entities;
|
||||
package auth_service.modules.login.persistence.entities;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
package auth_service.domain.login.persistence.mapper;
|
||||
package auth_service.modules.login.persistence.mapper;
|
||||
|
||||
import auth_service.domain.login.model.User;
|
||||
import auth_service.domain.login.persistence.entities.MinimalUserEntity;
|
||||
import auth_service.modules.login.model.User;
|
||||
import auth_service.modules.login.persistence.entities.MinimalUserEntity;
|
||||
|
||||
public abstract class EntityMapper {
|
||||
|
||||
+5
-5
@@ -1,9 +1,9 @@
|
||||
package auth_service.domain.login.service;
|
||||
package auth_service.modules.login.service;
|
||||
|
||||
import auth_service.domain.login.exception.InvalidCredentialsException;
|
||||
import auth_service.domain.login.exception.UserNotFoundException;
|
||||
import auth_service.domain.login.model.User;
|
||||
import auth_service.domain.login.persistence.MinimalUserRepository;
|
||||
import auth_service.modules.login.exception.InvalidCredentialsException;
|
||||
import auth_service.modules.login.exception.UserNotFoundException;
|
||||
import auth_service.modules.login.model.User;
|
||||
import auth_service.modules.login.persistence.MinimalUserRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
+2
-1
@@ -1,4 +1,4 @@
|
||||
package auth_service.domain.login.service;
|
||||
package auth_service.modules.login.service;
|
||||
|
||||
/**
|
||||
* Port interface for token generation.
|
||||
@@ -14,3 +14,4 @@ public interface TokenGenerator {
|
||||
*/
|
||||
String generateToken(String userId, String email);
|
||||
}
|
||||
|
||||
+5
-5
@@ -1,9 +1,9 @@
|
||||
package auth_service.domain.registration.controller;
|
||||
package auth_service.modules.registration.api;
|
||||
|
||||
import auth_service.domain.registration.controller.dto.mapper.ApiMapper;
|
||||
import auth_service.domain.registration.controller.dto.request.RegistrationRequest;
|
||||
import auth_service.domain.registration.controller.dto.response.RegistrationResponse;
|
||||
import auth_service.domain.registration.service.RegistrationService;
|
||||
import auth_service.modules.registration.api.dto.mapper.ApiMapper;
|
||||
import auth_service.modules.registration.api.dto.request.RegistrationRequest;
|
||||
import auth_service.modules.registration.api.dto.response.RegistrationResponse;
|
||||
import auth_service.modules.registration.service.RegistrationService;
|
||||
import io.micrometer.core.annotation.Timed;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
+5
-5
@@ -1,9 +1,9 @@
|
||||
package auth_service.domain.registration.controller;
|
||||
package auth_service.modules.registration.api;
|
||||
|
||||
import auth_service.shared.controller.dto.response.ErrorResponse;
|
||||
import auth_service.domain.registration.exception.EmailAlreadyInUseException;
|
||||
import auth_service.domain.registration.exception.InvalidInvitationCodeException;
|
||||
import auth_service.domain.registration.exception.SteamIdAlreadyRegisteredException;
|
||||
import auth_service.shared.api.dto.response.ErrorResponse;
|
||||
import auth_service.modules.registration.exception.EmailAlreadyInUseException;
|
||||
import auth_service.modules.registration.exception.InvalidInvitationCodeException;
|
||||
import auth_service.modules.registration.exception.SteamIdAlreadyRegisteredException;
|
||||
import lombok.NonNull;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.core.annotation.Order;
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
package auth_service.domain.registration.controller.dto.mapper;
|
||||
package auth_service.modules.registration.api.dto.mapper;
|
||||
|
||||
import auth_service.domain.registration.controller.dto.request.RegistrationRequest;
|
||||
import auth_service.domain.registration.model.Registration;
|
||||
import auth_service.modules.registration.api.dto.request.RegistrationRequest;
|
||||
import auth_service.modules.registration.model.Registration;
|
||||
|
||||
public abstract class ApiMapper {
|
||||
private ApiMapper() {
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package auth_service.domain.registration.controller.dto.request;
|
||||
package auth_service.modules.registration.api.dto.request;
|
||||
|
||||
import lombok.Builder;
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package auth_service.domain.registration.controller.dto.response;
|
||||
package auth_service.modules.registration.api.dto.response;
|
||||
|
||||
import lombok.Builder;
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package auth_service.domain.registration.exception;
|
||||
package auth_service.modules.registration.exception;
|
||||
|
||||
public class EmailAlreadyInUseException extends RuntimeException {
|
||||
public EmailAlreadyInUseException(String message) {
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package auth_service.domain.registration.exception;
|
||||
package auth_service.modules.registration.exception;
|
||||
|
||||
public class InvalidInvitationCodeException extends RuntimeException {
|
||||
public InvalidInvitationCodeException(String message) {
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package auth_service.domain.registration.exception;
|
||||
package auth_service.modules.registration.exception;
|
||||
|
||||
public class SteamIdAlreadyRegisteredException extends RuntimeException {
|
||||
public SteamIdAlreadyRegisteredException(String message) {
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package auth_service.domain.registration.model;
|
||||
package auth_service.modules.registration.model;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
package auth_service.domain.registration.persistence;
|
||||
package auth_service.modules.registration.persistence;
|
||||
|
||||
import auth_service.domain.registration.model.Registration;
|
||||
import auth_service.modules.registration.model.Registration;
|
||||
|
||||
public interface RegisteredUserRepository {
|
||||
boolean existsByEmail(String email);
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
package auth_service.domain.registration.persistence;
|
||||
package auth_service.modules.registration.persistence;
|
||||
|
||||
import auth_service.domain.registration.model.Registration;
|
||||
import auth_service.domain.registration.persistence.mapper.EntityMapper;
|
||||
import auth_service.modules.registration.model.Registration;
|
||||
import auth_service.modules.registration.persistence.mapper.EntityMapper;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.PersistenceContext;
|
||||
import jakarta.transaction.Transactional;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package auth_service.domain.registration.persistence.entities;
|
||||
package auth_service.modules.registration.persistence.entities;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
package auth_service.domain.registration.persistence.mapper;
|
||||
package auth_service.modules.registration.persistence.mapper;
|
||||
|
||||
import auth_service.domain.registration.model.Registration;
|
||||
import auth_service.domain.registration.persistence.entities.RegisteredUserEntity;
|
||||
import auth_service.modules.registration.model.Registration;
|
||||
import auth_service.modules.registration.persistence.entities.RegisteredUserEntity;
|
||||
|
||||
import java.time.Clock;
|
||||
import java.time.LocalDateTime;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package auth_service.domain.registration.service;
|
||||
package auth_service.modules.registration.service;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
+6
-6
@@ -1,10 +1,10 @@
|
||||
package auth_service.domain.registration.service;
|
||||
package auth_service.modules.registration.service;
|
||||
|
||||
import auth_service.domain.registration.exception.EmailAlreadyInUseException;
|
||||
import auth_service.domain.registration.exception.InvalidInvitationCodeException;
|
||||
import auth_service.domain.registration.exception.SteamIdAlreadyRegisteredException;
|
||||
import auth_service.domain.registration.model.Registration;
|
||||
import auth_service.domain.registration.persistence.RegisteredUserRepository;
|
||||
import auth_service.modules.registration.exception.EmailAlreadyInUseException;
|
||||
import auth_service.modules.registration.exception.InvalidInvitationCodeException;
|
||||
import auth_service.modules.registration.exception.SteamIdAlreadyRegisteredException;
|
||||
import auth_service.modules.registration.model.Registration;
|
||||
import auth_service.modules.registration.persistence.RegisteredUserRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
+6
-6
@@ -1,10 +1,10 @@
|
||||
package auth_service.domain.user.controller;
|
||||
package auth_service.modules.user.api;
|
||||
|
||||
import auth_service.shared.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 auth_service.modules.user.api.dto.request.UserSettingsRequest;
|
||||
import auth_service.modules.user.api.dto.response.UserProfileResponse;
|
||||
import auth_service.modules.user.api.mapper.ApiMapper;
|
||||
import auth_service.modules.user.service.UserService;
|
||||
import io.micrometer.core.annotation.Timed;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@@ -12,7 +12,7 @@ import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/**
|
||||
* Controller handling user profile operations for the dashboard.
|
||||
* API handling user profile operations for the dashboard.
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/users")
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
package auth_service.domain.user.controller;
|
||||
package auth_service.modules.user.api;
|
||||
|
||||
import auth_service.shared.controller.dto.response.ErrorResponse;
|
||||
import auth_service.domain.user.exception.UserNotFoundException;
|
||||
import auth_service.shared.api.dto.response.ErrorResponse;
|
||||
import auth_service.modules.user.exception.UserNotFoundException;
|
||||
import lombok.NonNull;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.core.annotation.Order;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package auth_service.domain.user.controller.dto.request;
|
||||
package auth_service.modules.user.api.dto.request;
|
||||
|
||||
public record UserSettingsRequest(boolean useDarkTheme, String language, long steamId) {
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package auth_service.domain.user.controller.dto.response;
|
||||
package auth_service.modules.user.api.dto.response;
|
||||
|
||||
import lombok.Builder;
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package auth_service.domain.user.controller.dto.response;
|
||||
package auth_service.modules.user.api.dto.response;
|
||||
|
||||
import lombok.Builder;
|
||||
|
||||
+6
-6
@@ -1,11 +1,11 @@
|
||||
package auth_service.domain.user.controller.mapper;
|
||||
package auth_service.modules.user.api.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;
|
||||
import auth_service.modules.user.api.dto.request.UserSettingsRequest;
|
||||
import auth_service.modules.user.api.dto.response.SettingsResponse;
|
||||
import auth_service.modules.user.api.dto.response.UserProfileResponse;
|
||||
import auth_service.modules.user.model.User;
|
||||
import auth_service.modules.user.model.UserSettings;
|
||||
|
||||
public abstract class ApiMapper {
|
||||
private ApiMapper() {
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package auth_service.domain.user.exception;
|
||||
package auth_service.modules.user.exception;
|
||||
|
||||
public class UserNotFoundException extends RuntimeException {
|
||||
public UserNotFoundException(String message) {
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package auth_service.domain.user.model;
|
||||
package auth_service.modules.user.model;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package auth_service.domain.user.model;
|
||||
package auth_service.modules.user.model;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
package auth_service.domain.user.persistence;
|
||||
package auth_service.modules.user.persistence;
|
||||
|
||||
|
||||
import auth_service.domain.user.model.User;
|
||||
import auth_service.domain.user.model.UserSettings;
|
||||
import auth_service.modules.user.model.User;
|
||||
import auth_service.modules.user.model.UserSettings;
|
||||
import jakarta.transaction.Transactional;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
+6
-6
@@ -1,10 +1,10 @@
|
||||
package auth_service.domain.user.persistence;
|
||||
package auth_service.modules.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 auth_service.modules.user.model.User;
|
||||
import auth_service.modules.user.model.UserSettings;
|
||||
import auth_service.modules.user.persistence.entities.UserEntity;
|
||||
import auth_service.modules.user.persistence.entities.UserSettingsEntity;
|
||||
import auth_service.modules.user.persistence.mapper.EntityMapper;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.PersistenceContext;
|
||||
import jakarta.persistence.TypedQuery;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package auth_service.domain.user.persistence.entities;
|
||||
package auth_service.modules.user.persistence.entities;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package auth_service.domain.user.persistence.entities;
|
||||
package auth_service.modules.user.persistence.entities;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
+5
-5
@@ -1,9 +1,9 @@
|
||||
package auth_service.domain.user.persistence.mapper;
|
||||
package auth_service.modules.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;
|
||||
import auth_service.modules.user.model.User;
|
||||
import auth_service.modules.user.model.UserSettings;
|
||||
import auth_service.modules.user.persistence.entities.UserEntity;
|
||||
import auth_service.modules.user.persistence.entities.UserSettingsEntity;
|
||||
|
||||
public abstract class EntityMapper {
|
||||
|
||||
+5
-5
@@ -1,9 +1,9 @@
|
||||
package auth_service.domain.user.service;
|
||||
package auth_service.modules.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 auth_service.modules.user.exception.UserNotFoundException;
|
||||
import auth_service.modules.user.model.User;
|
||||
import auth_service.modules.user.model.UserSettings;
|
||||
import auth_service.modules.user.persistence.UserRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
+3
-2
@@ -1,12 +1,13 @@
|
||||
package auth_service.shared.controller.dto.response;
|
||||
package auth_service.shared.api.dto.response;
|
||||
|
||||
import org.jspecify.annotations.NonNull;
|
||||
|
||||
/**
|
||||
* Shared error response record for all domains.
|
||||
* Shared error response record for all modules.
|
||||
*
|
||||
* @param code A machine-readable error code.
|
||||
* @param message A human-readable error message.
|
||||
*/
|
||||
public record ErrorResponse(@NonNull String code, @NonNull String message) {
|
||||
}
|
||||
|
||||
@@ -11,31 +11,31 @@ import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes;
|
||||
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;
|
||||
|
||||
/**
|
||||
* ArchUnit tests to enforce Clean Architecture and package boundaries.
|
||||
* ArchUnit tests to enforce Hexagonal Architecture and package boundaries.
|
||||
* Analyzes all classes in the 'auth_service' package, ignoring test classes.
|
||||
*/
|
||||
@AnalyzeClasses(packages = "auth_service", importOptions = ImportOption.DoNotIncludeTests.class)
|
||||
class ArchitectureTest extends AbstractArchitectureTest {
|
||||
|
||||
// ===================================================================================
|
||||
// 1. DOMAIN INDEPENDENCE (Slices)
|
||||
// 1. MODULE INDEPENDENCE (Slices)
|
||||
// ===================================================================================
|
||||
|
||||
@ArchTest
|
||||
static final ArchRule domains_should_not_depend_on_each_other = SlicesRuleDefinition.slices()
|
||||
.matching("auth_service.domain.(*)..")
|
||||
static final ArchRule modules_should_not_depend_on_each_other = SlicesRuleDefinition.slices()
|
||||
.matching("auth_service.modules.(*)..")
|
||||
.should().notDependOnEachOther()
|
||||
.because("Domains (e.g. login, user) should be strictly isolated and independent.");
|
||||
.because("Modules (e.g. login, user) should be strictly isolated and independent.");
|
||||
|
||||
// ===================================================================================
|
||||
// 2. CLEAN ARCHITECTURE DEPENDENCY DIRECTION (Inside out)
|
||||
// 2. HEXAGONAL ARCHITECTURE DEPENDENCY DIRECTION (Inside out)
|
||||
// ===================================================================================
|
||||
|
||||
@ArchTest
|
||||
static final ArchRule domain_core_should_not_depend_on_outside = noClasses()
|
||||
.that().resideInAnyPackage("..model..", "..service..")
|
||||
.should().dependOnClassesThat().resideInAnyPackage("..controller..", "..persistence.entities..", "..persistence.mapper..")
|
||||
.because("Domain core (Models, Services) must not depend on Web/Controller or Persistence details.");
|
||||
.should().dependOnClassesThat().resideInAnyPackage("..api..", "..persistence.entities..", "..persistence.mapper..")
|
||||
.because("Domain core (Models, Services) must not depend on API or Persistence details.");
|
||||
|
||||
@ArchTest
|
||||
static final ArchRule persistence_interfaces_belong_to_domain = classes()
|
||||
@@ -49,16 +49,16 @@ class ArchitectureTest extends AbstractArchitectureTest {
|
||||
// ===================================================================================
|
||||
|
||||
@ArchTest
|
||||
static final ArchRule dtos_should_only_be_used_in_controllers = classes()
|
||||
.that().resideInAPackage("..controller.dto..")
|
||||
.should().onlyBeAccessed().byAnyPackage("..controller..")
|
||||
.because("DTOs are Web/API concerns and must not leak into Services or Persistence.");
|
||||
static final ArchRule dtos_should_only_be_used_in_api = classes()
|
||||
.that().resideInAPackage("..api.dto..")
|
||||
.should().onlyBeAccessed().byAnyPackage("..api..")
|
||||
.because("DTOs are API concerns and must not leak into Services or Persistence.");
|
||||
|
||||
@ArchTest
|
||||
static final ArchRule entities_should_only_be_used_in_persistence = classes()
|
||||
.that().resideInAPackage("..persistence.entities..")
|
||||
.should().onlyBeAccessed().byAnyPackage("..persistence..")
|
||||
.because("Database Entities must not leak into the Domain Core or Controllers.");
|
||||
.because("Database Entities must not leak into the Domain Core or APIs.");
|
||||
|
||||
// ===================================================================================
|
||||
// 4. ADDITIONAL BEST PRACTICES
|
||||
@@ -71,28 +71,28 @@ class ArchitectureTest extends AbstractArchitectureTest {
|
||||
.because("Cyclic dependencies make the code unmaintainable and tightly coupled.");
|
||||
|
||||
@ArchTest
|
||||
static final ArchRule controllers_should_only_call_services = noClasses()
|
||||
.that().resideInAPackage("..controller..")
|
||||
static final ArchRule apis_should_only_call_services = noClasses()
|
||||
.that().resideInAPackage("..api..")
|
||||
.should().dependOnClassesThat().resideInAPackage("..persistence..")
|
||||
.because("Controllers must delegate to Services and should not access Persistence directly.");
|
||||
.because("APIs must delegate to Services and should not access Persistence directly.");
|
||||
|
||||
@ArchTest
|
||||
static final ArchRule persistence_should_not_depend_on_controllers = noClasses()
|
||||
static final ArchRule persistence_should_not_depend_on_apis = noClasses()
|
||||
.that().resideInAPackage("..persistence..")
|
||||
.should().dependOnClassesThat().resideInAPackage("..controller..")
|
||||
.because("Persistence layer must be independent of the Web/Controller layer.");
|
||||
.should().dependOnClassesThat().resideInAPackage("..api..")
|
||||
.because("Persistence layer must be independent of the API layer.");
|
||||
|
||||
@ArchTest
|
||||
static final ArchRule exceptions_should_be_isolated = noClasses()
|
||||
.that().resideInAPackage("..exception..")
|
||||
.should().dependOnClassesThat().resideInAnyPackage("..controller..", "..persistence.entities..")
|
||||
.should().dependOnClassesThat().resideInAnyPackage("..api..", "..persistence.entities..")
|
||||
.because("Exceptions should be part of the domain core and independent of infrastructure details.");
|
||||
|
||||
@ArchTest
|
||||
static final ArchRule configuration_should_not_be_accessed_by_domain = noClasses()
|
||||
.that().resideInAnyPackage("..domain..")
|
||||
static final ArchRule configuration_should_not_be_accessed_by_modules = noClasses()
|
||||
.that().resideInAnyPackage("..modules..")
|
||||
.should().dependOnClassesThat().resideInAPackage("auth_service.configuration..")
|
||||
.because("Domain logic should not depend on Spring configuration classes.");
|
||||
.because("Module logic should not depend on global Spring configuration classes.");
|
||||
|
||||
@ArchTest
|
||||
static final ArchRule services_should_be_annotated = classes()
|
||||
@@ -106,17 +106,17 @@ class ArchitectureTest extends AbstractArchitectureTest {
|
||||
// ===================================================================================
|
||||
|
||||
@ArchTest
|
||||
static final ArchRule shared_should_not_depend_on_domains = noClasses()
|
||||
static final ArchRule shared_should_not_depend_on_modules = noClasses()
|
||||
.that().resideInAPackage("auth_service.shared..")
|
||||
.should().dependOnClassesThat().resideInAPackage("auth_service.domain..")
|
||||
.because("Shared classes should be independent of specific domains.");
|
||||
.should().dependOnClassesThat().resideInAPackage("auth_service.modules..")
|
||||
.because("Shared classes should be independent of specific modules.");
|
||||
|
||||
@ArchTest
|
||||
static final ArchRule controllers_should_be_annotated = classes()
|
||||
.that().resideInAPackage("..controller..")
|
||||
static final ArchRule apis_should_be_annotated = classes()
|
||||
.that().resideInAPackage("..api..")
|
||||
.and().haveSimpleNameEndingWith("Controller")
|
||||
.should().beAnnotatedWith(org.springframework.web.bind.annotation.RestController.class)
|
||||
.orShould().beAnnotatedWith(org.springframework.web.bind.annotation.ControllerAdvice.class)
|
||||
.orShould().beAnnotatedWith(org.springframework.web.bind.annotation.RestControllerAdvice.class)
|
||||
.because("Classes named *Controller should be registered as Spring @RestController or @ControllerAdvice or @RestControllerAdvice beans.");
|
||||
.because("Classes in 'api' package should be registered as Spring @RestController or @ControllerAdvice or @RestControllerAdvice beans.");
|
||||
}
|
||||
+5
-5
@@ -1,10 +1,10 @@
|
||||
package auth_service.domain.login.controller;
|
||||
package auth_service.modules.login.api;
|
||||
|
||||
import auth_service.configuration.security.JwtAuthenticationFilter;
|
||||
import auth_service.domain.login.controller.dto.request.LoginRequest;
|
||||
import auth_service.domain.login.exception.InvalidCredentialsException;
|
||||
import auth_service.domain.login.model.User;
|
||||
import auth_service.domain.login.service.LoginService;
|
||||
import auth_service.modules.login.api.dto.request.LoginRequest;
|
||||
import auth_service.modules.login.exception.InvalidCredentialsException;
|
||||
import auth_service.modules.login.model.User;
|
||||
import auth_service.modules.login.service.LoginService;
|
||||
import auth_service.shared.test.AbstractWebMvcTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
package auth_service.domain.login.persistence;
|
||||
package auth_service.modules.login.persistence;
|
||||
|
||||
import auth_service.domain.login.persistence.entities.MinimalUserEntity;
|
||||
import auth_service.modules.login.persistence.entities.MinimalUserEntity;
|
||||
import auth_service.shared.test.AbstractPersistenceTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
+5
-5
@@ -1,9 +1,9 @@
|
||||
package auth_service.domain.login.service;
|
||||
package auth_service.modules.login.service;
|
||||
|
||||
import auth_service.domain.login.exception.InvalidCredentialsException;
|
||||
import auth_service.domain.login.exception.UserNotFoundException;
|
||||
import auth_service.domain.login.model.User;
|
||||
import auth_service.domain.login.persistence.MinimalUserRepository;
|
||||
import auth_service.modules.login.exception.InvalidCredentialsException;
|
||||
import auth_service.modules.login.exception.UserNotFoundException;
|
||||
import auth_service.modules.login.model.User;
|
||||
import auth_service.modules.login.persistence.MinimalUserRepository;
|
||||
import auth_service.shared.test.AbstractUnitTest;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
+5
-5
@@ -1,11 +1,11 @@
|
||||
package auth_service.domain.registration.controller;
|
||||
package auth_service.modules.registration.api;
|
||||
|
||||
import auth_service.configuration.security.JwtAuthenticationFilter;
|
||||
import auth_service.configuration.security.JwtService;
|
||||
import auth_service.domain.registration.controller.dto.request.RegistrationRequest;
|
||||
import auth_service.domain.registration.exception.EmailAlreadyInUseException;
|
||||
import auth_service.domain.registration.model.Registration;
|
||||
import auth_service.domain.registration.service.RegistrationService;
|
||||
import auth_service.modules.registration.api.dto.request.RegistrationRequest;
|
||||
import auth_service.modules.registration.exception.EmailAlreadyInUseException;
|
||||
import auth_service.modules.registration.model.Registration;
|
||||
import auth_service.modules.registration.service.RegistrationService;
|
||||
import auth_service.shared.test.AbstractWebMvcTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
package auth_service.domain.registration.persistence;
|
||||
package auth_service.modules.registration.persistence;
|
||||
|
||||
import auth_service.domain.registration.model.Registration;
|
||||
import auth_service.domain.registration.persistence.entities.RegisteredUserEntity;
|
||||
import auth_service.modules.registration.model.Registration;
|
||||
import auth_service.modules.registration.persistence.entities.RegisteredUserEntity;
|
||||
import auth_service.shared.test.AbstractPersistenceTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
+6
-6
@@ -1,10 +1,10 @@
|
||||
package auth_service.domain.registration.service;
|
||||
package auth_service.modules.registration.service;
|
||||
|
||||
import auth_service.domain.registration.exception.EmailAlreadyInUseException;
|
||||
import auth_service.domain.registration.exception.InvalidInvitationCodeException;
|
||||
import auth_service.domain.registration.exception.SteamIdAlreadyRegisteredException;
|
||||
import auth_service.domain.registration.model.Registration;
|
||||
import auth_service.domain.registration.persistence.RegisteredUserRepository;
|
||||
import auth_service.modules.registration.exception.EmailAlreadyInUseException;
|
||||
import auth_service.modules.registration.exception.InvalidInvitationCodeException;
|
||||
import auth_service.modules.registration.exception.SteamIdAlreadyRegisteredException;
|
||||
import auth_service.modules.registration.model.Registration;
|
||||
import auth_service.modules.registration.persistence.RegisteredUserRepository;
|
||||
import auth_service.shared.test.AbstractUnitTest;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
+6
-6
@@ -1,13 +1,13 @@
|
||||
package auth_service.domain.user.controller;
|
||||
package auth_service.modules.user.api;
|
||||
|
||||
import auth_service.configuration.security.JwtAuthenticationFilter;
|
||||
import auth_service.configuration.security.JwtService;
|
||||
import auth_service.shared.security.UserPrincipal;
|
||||
import auth_service.domain.user.controller.dto.request.UserSettingsRequest;
|
||||
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.service.UserService;
|
||||
import auth_service.modules.user.api.dto.request.UserSettingsRequest;
|
||||
import auth_service.modules.user.exception.UserNotFoundException;
|
||||
import auth_service.modules.user.model.User;
|
||||
import auth_service.modules.user.model.UserSettings;
|
||||
import auth_service.modules.user.service.UserService;
|
||||
import auth_service.shared.test.AbstractWebMvcTest;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
package auth_service.domain.user.persistence;
|
||||
package auth_service.modules.user.persistence;
|
||||
|
||||
import auth_service.domain.user.model.UserSettings;
|
||||
import auth_service.domain.user.persistence.entities.UserEntity;
|
||||
import auth_service.modules.user.model.UserSettings;
|
||||
import auth_service.modules.user.persistence.entities.UserEntity;
|
||||
import auth_service.shared.test.AbstractPersistenceTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
+5
-5
@@ -1,9 +1,9 @@
|
||||
package auth_service.domain.user.service;
|
||||
package auth_service.modules.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 auth_service.modules.user.exception.UserNotFoundException;
|
||||
import auth_service.modules.user.model.User;
|
||||
import auth_service.modules.user.model.UserSettings;
|
||||
import auth_service.modules.user.persistence.UserRepository;
|
||||
import auth_service.shared.test.AbstractUnitTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.InjectMocks;
|
||||
@@ -8,3 +8,4 @@ import org.junit.jupiter.api.Tag;
|
||||
@Tag("ArchitectureTest")
|
||||
public abstract class AbstractArchitectureTest {
|
||||
}
|
||||
|
||||
@@ -22,3 +22,4 @@ public abstract class AbstractIntegrationTest {
|
||||
@ServiceConnection
|
||||
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:17-alpine");
|
||||
}
|
||||
|
||||
@@ -12,3 +12,4 @@ import org.mockito.junit.jupiter.MockitoExtension;
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public abstract class AbstractUnitTest {
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user