Public Access
Implemented user service
This commit is contained in:
1 parent
3ee636253b
commit
afd71b82be
27 files changed
+332
-36
No files matched your search
@@ -34,6 +34,10 @@
|
|||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-webmvc</artifactId>
|
<artifactId>spring-boot-starter-webmvc</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-cache</artifactId>
|
||||||
|
</dependency>
|
||||||
<!-- Rest Caching -->
|
<!-- Rest Caching -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.ben-manes.caffeine</groupId>
|
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package auth_service.configuration;
|
||||||
|
|
||||||
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.cache.CacheManager;
|
||||||
|
import org.springframework.cache.annotation.EnableCaching;
|
||||||
|
import org.springframework.cache.caffeine.CaffeineCacheManager;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.Profile;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global configuration to enable Spring Boot caching (backed by Caffeine).
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@EnableCaching
|
||||||
|
@Profile("!dev")
|
||||||
|
@Slf4j
|
||||||
|
public class CacheConfig {
|
||||||
|
@Bean
|
||||||
|
public CacheManager cacheManager() {
|
||||||
|
log.info("########### Productive cache active ###########");
|
||||||
|
CaffeineCacheManager cacheManager = new CaffeineCacheManager("usersByEmail");
|
||||||
|
cacheManager.setCaffeine(caffeineCacheBuilder());
|
||||||
|
return cacheManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
Caffeine<Object, Object> caffeineCacheBuilder() {
|
||||||
|
return Caffeine.newBuilder()
|
||||||
|
.initialCapacity(100)
|
||||||
|
.maximumSize(500)
|
||||||
|
.expireAfterAccess(10, TimeUnit.MINUTES)
|
||||||
|
.recordStats();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package auth_service.configuration;
|
||||||
|
|
||||||
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.cache.CacheManager;
|
||||||
|
import org.springframework.cache.annotation.EnableCaching;
|
||||||
|
import org.springframework.cache.caffeine.CaffeineCacheManager;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.Profile;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global configuration to enable Spring Boot caching (backed by Caffeine).
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@EnableCaching
|
||||||
|
@Profile("dev")
|
||||||
|
@Slf4j
|
||||||
|
public class DevCacheConfig {
|
||||||
|
@Bean
|
||||||
|
public CacheManager cacheManager() {
|
||||||
|
log.error("########### DEVELOPMENT CACHE ACTIVE ###########");
|
||||||
|
CaffeineCacheManager cacheManager = new CaffeineCacheManager("usersByEmail");
|
||||||
|
cacheManager.setCaffeine(caffeineCacheBuilder());
|
||||||
|
return cacheManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
Caffeine<Object, Object> caffeineCacheBuilder() {
|
||||||
|
return Caffeine.newBuilder()
|
||||||
|
.initialCapacity(100)
|
||||||
|
.maximumSize(500)
|
||||||
|
.expireAfterAccess(1, TimeUnit.SECONDS)
|
||||||
|
.recordStats();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package auth_service.domain.login.controller;
|
package auth_service.domain.login.controller;
|
||||||
|
|
||||||
import auth_service.domain.login.controller.dtos.request.LoginRequest;
|
import auth_service.domain.login.controller.dto.request.LoginRequest;
|
||||||
import auth_service.domain.login.controller.dtos.response.LoginResponse;
|
import auth_service.domain.login.controller.dto.response.LoginResponse;
|
||||||
import auth_service.domain.login.controller.mapper.ApiMapper;
|
import auth_service.domain.login.controller.mapper.ApiMapper;
|
||||||
import auth_service.domain.login.service.LoginService;
|
import auth_service.domain.login.service.LoginService;
|
||||||
import io.micrometer.core.annotation.Timed;
|
import io.micrometer.core.annotation.Timed;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package auth_service.domain.login.controller;
|
package auth_service.domain.login.controller;
|
||||||
|
|
||||||
import auth_service.domain.login.controller.dtos.response.ErrorResponse;
|
import auth_service.domain.login.controller.dto.response.ErrorResponse;
|
||||||
import auth_service.domain.login.exception.InvalidCredentialsException;
|
import auth_service.domain.login.exception.InvalidCredentialsException;
|
||||||
import auth_service.domain.login.exception.UserNotFoundException;
|
import auth_service.domain.login.exception.UserNotFoundException;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package auth_service.domain.login.controller.dtos.request;
|
package auth_service.domain.login.controller.dto.request;
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package auth_service.domain.login.controller.dtos.response;
|
package auth_service.domain.login.controller.dto.response;
|
||||||
|
|
||||||
public record ErrorResponse(String code, String message) {
|
public record ErrorResponse(String code, String message) {
|
||||||
}
|
}
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package auth_service.domain.login.controller.dtos.response;
|
package auth_service.domain.login.controller.dto.response;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DTO representing the outgoing login response.
|
* DTO representing the outgoing login response.
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package auth_service.domain.login.controller.mapper;
|
package auth_service.domain.login.controller.mapper;
|
||||||
|
|
||||||
import auth_service.domain.login.controller.dtos.request.LoginRequest;
|
import auth_service.domain.login.controller.dto.request.LoginRequest;
|
||||||
import auth_service.domain.login.model.User;
|
import auth_service.domain.login.model.User;
|
||||||
|
|
||||||
public abstract class ApiMapper {
|
public abstract class ApiMapper {
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package auth_service.domain.login.persistence;
|
||||||
|
|
||||||
|
import auth_service.domain.login.model.User;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Repository for database operations regarding the User entity.
|
||||||
|
*/
|
||||||
|
public interface MinimalUserRepository {
|
||||||
|
/**
|
||||||
|
* Finds a user by their email address.
|
||||||
|
* * @param email The email to search for
|
||||||
|
*
|
||||||
|
* @return An Optional containing the user if found
|
||||||
|
*/
|
||||||
|
Optional<User> findByEmail(String email);
|
||||||
|
}
|
||||||
+7
-10
@@ -1,33 +1,30 @@
|
|||||||
package auth_service.domain.login.persistence;
|
package auth_service.domain.login.persistence;
|
||||||
|
|
||||||
import auth_service.domain.login.model.User;
|
import auth_service.domain.login.model.User;
|
||||||
import auth_service.domain.login.persistence.entities.UserEntity;
|
import auth_service.domain.login.persistence.entities.MinimalUserEntity;
|
||||||
import auth_service.domain.login.persistence.mapper.EntityMapper;
|
import auth_service.domain.login.persistence.mapper.EntityMapper;
|
||||||
import jakarta.persistence.EntityManager;
|
import jakarta.persistence.EntityManager;
|
||||||
import jakarta.persistence.PersistenceContext;
|
import jakarta.persistence.PersistenceContext;
|
||||||
import jakarta.persistence.TypedQuery;
|
import jakarta.persistence.TypedQuery;
|
||||||
import jakarta.persistence.criteria.CriteriaBuilder;
|
|
||||||
import jakarta.persistence.criteria.CriteriaQuery;
|
|
||||||
import jakarta.persistence.criteria.Root;
|
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
public class UserRepositoryImpl implements UserRepository {
|
public class MinimalUserRepositoryImpl implements MinimalUserRepository {
|
||||||
@PersistenceContext
|
@PersistenceContext
|
||||||
private EntityManager entityManager;
|
private EntityManager entityManager;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<User> findByEmail(String email) {
|
public Optional<User> findByEmail(String email) {
|
||||||
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
|
var criteriaBuilder = entityManager.getCriteriaBuilder();
|
||||||
CriteriaQuery<UserEntity> query = cb.createQuery(UserEntity.class);
|
var userEntityCriteriaQuery = criteriaBuilder.createQuery(MinimalUserEntity.class);
|
||||||
Root<UserEntity> user = query.from(UserEntity.class);
|
var userEntity = userEntityCriteriaQuery.from(MinimalUserEntity.class);
|
||||||
|
|
||||||
// Build the query: SELECT u FROM UserEntity u WHERE u.email = :email
|
// Build the query: SELECT u FROM UserEntity u WHERE u.email = :email
|
||||||
query.select(user).where(cb.equal(user.get("email"), email));
|
userEntityCriteriaQuery.select(userEntity).where(criteriaBuilder.equal(userEntity.get("email"), email));
|
||||||
|
|
||||||
TypedQuery<UserEntity> typedQuery = entityManager.createQuery(query);
|
TypedQuery<MinimalUserEntity> typedQuery = entityManager.createQuery(userEntityCriteriaQuery);
|
||||||
|
|
||||||
return typedQuery.getResultStream()
|
return typedQuery.getResultStream()
|
||||||
.findFirst()
|
.findFirst()
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package auth_service.domain.login.persistence.entities;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a user entity mapped to the 'users' table in PostgreSQL.
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Table(name = "users")
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Builder
|
||||||
|
public class MinimalUserEntity {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Column(unique = true, nullable = false)
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private boolean enabled;
|
||||||
|
}
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
package auth_service.domain.login.persistence.mapper;
|
package auth_service.domain.login.persistence.mapper;
|
||||||
|
|
||||||
import auth_service.domain.login.model.User;
|
import auth_service.domain.login.model.User;
|
||||||
import auth_service.domain.login.persistence.entities.UserEntity;
|
import auth_service.domain.login.persistence.entities.MinimalUserEntity;
|
||||||
|
|
||||||
public abstract class EntityMapper {
|
public abstract class EntityMapper {
|
||||||
|
|
||||||
private EntityMapper() {
|
private EntityMapper() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static User mapToModel(UserEntity entity) {
|
public static User mapToModel(MinimalUserEntity entity) {
|
||||||
User model = User.builder().build();
|
User model = User.builder().build();
|
||||||
|
|
||||||
if (entity != null) {
|
if (entity != null) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import auth_service.configuration.security.JwtService;
|
|||||||
import auth_service.domain.login.exception.InvalidCredentialsException;
|
import auth_service.domain.login.exception.InvalidCredentialsException;
|
||||||
import auth_service.domain.login.exception.UserNotFoundException;
|
import auth_service.domain.login.exception.UserNotFoundException;
|
||||||
import auth_service.domain.login.model.User;
|
import auth_service.domain.login.model.User;
|
||||||
import auth_service.domain.login.persistence.UserRepository;
|
import auth_service.domain.login.persistence.MinimalUserRepository;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
@@ -14,12 +14,12 @@ import org.springframework.stereotype.Service;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class LoginService {
|
public class LoginService {
|
||||||
private final UserRepository userRepository;
|
private final MinimalUserRepository minimalUserRepository;
|
||||||
private final PasswordEncoder passwordEncoder;
|
private final PasswordEncoder passwordEncoder;
|
||||||
private final JwtService jwtService;
|
private final JwtService jwtService;
|
||||||
|
|
||||||
public String login(User userToLogin) {
|
public String login(User userToLogin) {
|
||||||
var userEntity = userRepository.findByEmail(userToLogin.getEmail()).orElseThrow(() -> new UserNotFoundException("User not found with given email"));
|
var userEntity = minimalUserRepository.findByEmail(userToLogin.getEmail()).orElseThrow(() -> new UserNotFoundException("User not found with given email"));
|
||||||
|
|
||||||
log.info("Login attempt for user {}", passwordEncoder.encode(userToLogin.getEncryptedPassword()) + " " + userEntity.getEncryptedPassword());
|
log.info("Login attempt for user {}", passwordEncoder.encode(userToLogin.getEncryptedPassword()) + " " + userEntity.getEncryptedPassword());
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
package auth_service.domain.user.controller;
|
package auth_service.domain.user.controller;
|
||||||
|
|
||||||
|
import auth_service.domain.user.controller.dto.response.UserProfileResponse;
|
||||||
|
import auth_service.domain.user.controller.mapper.ApiMapper;
|
||||||
|
import auth_service.domain.user.service.UserService;
|
||||||
import io.micrometer.core.annotation.Timed;
|
import io.micrometer.core.annotation.Timed;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
@@ -13,8 +17,11 @@ import java.security.Principal;
|
|||||||
*/
|
*/
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/users")
|
@RequestMapping("/api/users")
|
||||||
|
@RequiredArgsConstructor
|
||||||
public class UserController {
|
public class UserController {
|
||||||
|
|
||||||
|
private final UserService userService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Version 1 of the 'me' endpoint, accessed via /api/users/me?v=1
|
* Version 1 of the 'me' endpoint, accessed via /api/users/me?v=1
|
||||||
* * @return The user's dashboard data
|
* * @return The user's dashboard data
|
||||||
@@ -23,16 +30,9 @@ public class UserController {
|
|||||||
@Timed(value = "user.me.v1.requests.time", description = "Time taken to process v1 user profile requests")
|
@Timed(value = "user.me.v1.requests.time", description = "Time taken to process v1 user profile requests")
|
||||||
public ResponseEntity<UserProfileResponse> getCurrentUserV1(Principal principal) {
|
public ResponseEntity<UserProfileResponse> getCurrentUserV1(Principal principal) {
|
||||||
|
|
||||||
// principal.getName() enthält die E-Mail, die der Türsteher aus dem Token gelesen hat!
|
// this is the email from the login, if a user is not authenticated, it will not even come to this point.
|
||||||
String authenticatedEmail = principal.getName();
|
var authenticatedEmail = principal.getName();
|
||||||
|
var profileResponse = this.userService.getUserByEmail(authenticatedEmail);
|
||||||
return ResponseEntity.ok(new UserProfileResponse(
|
return ResponseEntity.ok(ApiMapper.toApi(profileResponse));
|
||||||
authenticatedEmail,
|
|
||||||
"USER",
|
|
||||||
"Welcome to the v1 Dashboard, " + authenticatedEmail + "!"
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
public record UserProfileResponse(String email, String role, String dashboardMessage) {
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package auth_service.domain.user.controller;
|
||||||
|
|
||||||
|
import auth_service.domain.user.controller.dto.response.ErrorResponse;
|
||||||
|
import auth_service.domain.user.exception.UserNotFoundException;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
|
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||||
|
|
||||||
|
@RestControllerAdvice
|
||||||
|
@Order(value = 1)
|
||||||
|
@Slf4j
|
||||||
|
public class UserExceptionController {
|
||||||
|
private static @NonNull ResponseEntity<ErrorResponse> response500(ErrorResponse body) {
|
||||||
|
log.error(body.message(), body.code());
|
||||||
|
return ResponseEntity.status(500)
|
||||||
|
.contentType(org.springframework.http.MediaType.APPLICATION_JSON)
|
||||||
|
.body(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static @NonNull ResponseEntity<ErrorResponse> response400(ErrorResponse body) {
|
||||||
|
return ResponseEntity.status(400)
|
||||||
|
.contentType(org.springframework.http.MediaType.APPLICATION_JSON)
|
||||||
|
.body(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
######## CLIENT ERRORS (500-599)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
######## CLIENT ERRORS (400-499)
|
||||||
|
*/
|
||||||
|
@ExceptionHandler(UserNotFoundException.class)
|
||||||
|
public ResponseEntity<ErrorResponse> clientError(UserNotFoundException ex) {
|
||||||
|
var body = new ErrorResponse("USER_NOT_FOUND", ex.getMessage());
|
||||||
|
return response400(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
package auth_service.domain.user.controller.dto.response;
|
||||||
|
|
||||||
|
public record ErrorResponse(String code, String message) {
|
||||||
|
}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
package auth_service.domain.user.controller.dto.response;
|
||||||
|
|
||||||
|
import lombok.Builder;
|
||||||
|
|
||||||
|
@Builder
|
||||||
|
public record UserProfileResponse(long id, String email, String role) {
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package auth_service.domain.user.controller.mapper;
|
||||||
|
|
||||||
|
|
||||||
|
import auth_service.domain.user.controller.dto.response.UserProfileResponse;
|
||||||
|
import auth_service.domain.user.model.User;
|
||||||
|
|
||||||
|
public abstract class ApiMapper {
|
||||||
|
private ApiMapper() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UserProfileResponse toApi(User user) {
|
||||||
|
return UserProfileResponse.builder()
|
||||||
|
.id(user.getId())
|
||||||
|
.email(user.getEmail())
|
||||||
|
.role("USER").build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package auth_service.domain.user.exception;
|
||||||
|
|
||||||
|
public class UserNotFoundException extends RuntimeException {
|
||||||
|
public UserNotFoundException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package auth_service.domain.user.model;
|
||||||
|
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Builder
|
||||||
|
@Data
|
||||||
|
public class User {
|
||||||
|
private long id;
|
||||||
|
private String email;
|
||||||
|
private String encryptedPassword;
|
||||||
|
}
|
||||||
+3
-2
@@ -1,6 +1,7 @@
|
|||||||
package auth_service.domain.login.persistence;
|
package auth_service.domain.user.persistence;
|
||||||
|
|
||||||
import auth_service.domain.login.model.User;
|
|
||||||
|
import auth_service.domain.user.model.User;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package auth_service.domain.user.persistence;
|
||||||
|
|
||||||
|
import auth_service.domain.user.model.User;
|
||||||
|
import auth_service.domain.user.persistence.entities.UserEntity;
|
||||||
|
import auth_service.domain.user.persistence.mapper.EntityMapper;
|
||||||
|
import jakarta.persistence.EntityManager;
|
||||||
|
import jakarta.persistence.PersistenceContext;
|
||||||
|
import jakarta.persistence.TypedQuery;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public class UserRepositoryImpl implements UserRepository {
|
||||||
|
@PersistenceContext
|
||||||
|
private EntityManager entityManager;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<User> findByEmail(String email) {
|
||||||
|
var criteriaBuilder = entityManager.getCriteriaBuilder();
|
||||||
|
var userEntityCriteriaQuery = criteriaBuilder.createQuery(UserEntity.class);
|
||||||
|
var userEntity = userEntityCriteriaQuery.from(UserEntity.class);
|
||||||
|
|
||||||
|
// Build the query: SELECT u FROM UserEntity u WHERE u.email = :email
|
||||||
|
userEntityCriteriaQuery.select(userEntity).where(criteriaBuilder.equal(userEntity.get("email"), email));
|
||||||
|
|
||||||
|
TypedQuery<UserEntity> typedQuery = entityManager.createQuery(userEntityCriteriaQuery);
|
||||||
|
|
||||||
|
return typedQuery.getResultStream()
|
||||||
|
.findFirst()
|
||||||
|
.map(EntityMapper::mapToModel);
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package auth_service.domain.login.persistence.entities;
|
package auth_service.domain.user.persistence.entities;
|
||||||
|
|
||||||
import jakarta.persistence.*;
|
import jakarta.persistence.*;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package auth_service.domain.user.persistence.mapper;
|
||||||
|
|
||||||
|
import auth_service.domain.user.model.User;
|
||||||
|
import auth_service.domain.user.persistence.entities.UserEntity;
|
||||||
|
|
||||||
|
public abstract class EntityMapper {
|
||||||
|
|
||||||
|
private EntityMapper() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static User mapToModel(UserEntity entity) {
|
||||||
|
User model = User.builder().build();
|
||||||
|
|
||||||
|
if (entity != null) {
|
||||||
|
model.setId(entity.getId());
|
||||||
|
model.setEmail(entity.getEmail());
|
||||||
|
model.setEncryptedPassword(entity.getPassword());
|
||||||
|
}
|
||||||
|
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package auth_service.domain.user.service;
|
||||||
|
|
||||||
|
import auth_service.domain.user.exception.UserNotFoundException;
|
||||||
|
import auth_service.domain.user.model.User;
|
||||||
|
import auth_service.domain.user.persistence.UserRepository;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.cache.annotation.Cacheable;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class UserService {
|
||||||
|
|
||||||
|
private final UserRepository userRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches the user by email. Results are cached to ensure blazing-fast UI rendering.
|
||||||
|
*
|
||||||
|
* @param email The authenticated user's email
|
||||||
|
* @return Optional containing the User model if found
|
||||||
|
*/
|
||||||
|
@Cacheable(value = "usersByEmail", key = "#email")
|
||||||
|
public User getUserByEmail(String email) {
|
||||||
|
return userRepository.findByEmail(email).orElseThrow(() -> new UserNotFoundException("Could not find user with email " + email));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,6 +6,8 @@ spring:
|
|||||||
name: tbp-auth-service
|
name: tbp-auth-service
|
||||||
profiles:
|
profiles:
|
||||||
active: dev # Default profile for local startup
|
active: dev # Default profile for local startup
|
||||||
|
jpa:
|
||||||
|
open-in-view: false
|
||||||
flyway:
|
flyway:
|
||||||
# Force Flyway to be enabled
|
# Force Flyway to be enabled
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|||||||
Reference in new issue
Block a user