1 package fr.tiogars.inception.settings.user.services;
2
3 import java.time.Clock;
4 import java.time.Instant;
5 import java.time.temporal.ChronoUnit;
6 import java.util.Optional;
7
8 import org.springframework.beans.factory.annotation.Autowired;
9 import org.springframework.stereotype.Service;
10 import org.springframework.transaction.annotation.Transactional;
11
12 import fr.tiogars.inception.domains.auth.role.services.RoleService;
13 import fr.tiogars.inception.domains.auth.user.entities.UserEntity;
14 import fr.tiogars.inception.domains.auth.user.repositories.UserRepository;
15 import fr.tiogars.inception.settings.user.entities.UserSettings;
16 import fr.tiogars.inception.settings.user.entities.UserSettingsEntity;
17 import fr.tiogars.inception.settings.user.models.UpdateUserSettingsRequest;
18 import fr.tiogars.inception.settings.user.repositories.UserSettingsRepository;
19
20
21 @Service
22 public class UserSettingsService {
23
24 public static final String DEFAULT_VIEW_MODE = "system";
25
26 private final Clock clock;
27 private final UserRepository userRepository;
28 private final UserSettingsRepository repository;
29
30 @Autowired
31 public UserSettingsService(UserSettingsRepository repository, UserRepository userRepository) {
32 this(repository, userRepository, Clock.systemUTC());
33 }
34
35 UserSettingsService(UserSettingsRepository repository, UserRepository userRepository, Clock clock) {
36 this.repository = repository;
37 this.userRepository = userRepository;
38 this.clock = clock;
39 }
40
41
42 @Transactional(readOnly = true)
43 public Optional<UserSettings> findByUsername(String username) {
44 return userRepository.findByUsername(username).map(this::readUserSettings);
45 }
46
47
48 @Transactional
49 public Optional<UserSettings> updateByUsername(String username, UpdateUserSettingsRequest request) {
50 return userRepository.findByUsername(username).map(user -> writeUserSettings(user, request));
51 }
52
53
54 @Transactional(readOnly = true)
55 public Optional<UserSettings> findByUserId(Long userId) {
56 return findManagedUser(userId).map(this::readUserSettings);
57 }
58
59
60 @Transactional
61 public Optional<UserSettings> updateByUserId(Long userId, UpdateUserSettingsRequest request) {
62 return findManagedUser(userId).map(user -> writeUserSettings(user, request));
63 }
64
65 @Transactional(readOnly = true)
66 public UserSettings findAnonymous() {
67 return repository.findByRoleCode(RoleService.ANONYMOUS)
68 .map(UserSettingsService::toRecord)
69 .orElseGet(() -> defaults(null, RoleService.ANONYMOUS));
70 }
71
72 @Transactional
73 public UserSettings updateAnonymous(UpdateUserSettingsRequest request) {
74 Instant timestamp = currentTimestamp();
75 UserSettingsEntity entity = repository.findByRoleCode(RoleService.ANONYMOUS)
76 .map(existing -> {
77 existing.update(request.viewMode(), timestamp);
78 return existing;
79 })
80 .orElseGet(() -> UserSettingsEntity.forRole(RoleService.ANONYMOUS, request.viewMode(), timestamp));
81 return toRecord(repository.save(entity));
82 }
83
84 private Optional<UserEntity> findManagedUser(Long userId) {
85 return userRepository.findById(userId)
86 .filter(user -> user.getRoles().stream().anyMatch(role -> RoleService.USER.equals(role.getCode())));
87 }
88
89 private UserSettings readUserSettings(UserEntity user) {
90 return repository.findByUserId(user.getId())
91 .map(UserSettingsService::toRecord)
92 .orElseGet(() -> defaults(user.getId(), null));
93 }
94
95 private UserSettings writeUserSettings(UserEntity user, UpdateUserSettingsRequest request) {
96 Instant timestamp = currentTimestamp();
97 UserSettingsEntity entity = repository.findByUserId(user.getId())
98 .map(existing -> {
99 existing.update(request.viewMode(), timestamp);
100 return existing;
101 })
102 .orElseGet(() -> UserSettingsEntity.forUser(user, request.viewMode(), timestamp));
103 return toRecord(repository.save(entity));
104 }
105
106 private Instant currentTimestamp() {
107 return Instant.now(clock).truncatedTo(ChronoUnit.MICROS);
108 }
109
110 private static UserSettings defaults(Long userId, String roleCode) {
111 return new UserSettings(userId, roleCode, DEFAULT_VIEW_MODE, null, null);
112 }
113
114 public static UserSettings toRecord(UserSettingsEntity entity) {
115 return new UserSettings(
116 entity.getUser() == null ? null : entity.getUser().getId(),
117 entity.getRoleCode(),
118 entity.getViewMode(),
119 entity.getCreatedDate(),
120 entity.getLastModifiedDate());
121 }
122 }