View Javadoc
1   package fr.tiogars.domaintemplate.domains.auth.role.services;
2   
3   import java.time.Clock;
4   import java.time.Instant;
5   import java.time.temporal.ChronoUnit;
6   import java.util.List;
7   import java.util.Optional;
8   import java.util.Set;
9   
10  import org.springframework.beans.factory.annotation.Autowired;
11  import org.springframework.stereotype.Service;
12  import org.springframework.transaction.annotation.Transactional;
13  
14  import fr.tiogars.domaintemplate.domains.auth.role.entities.Role;
15  import fr.tiogars.domaintemplate.domains.auth.role.entities.RoleEntity;
16  import fr.tiogars.domaintemplate.domains.auth.role.models.CreateRoleRequest;
17  import fr.tiogars.domaintemplate.domains.auth.role.models.UpdateRoleRequest;
18  import fr.tiogars.domaintemplate.domains.auth.role.repositories.RoleRepository;
19  
20  /** Coordinates role persistence and default role seeding. */
21  @Service
22  public class RoleService {
23  
24      public static final String ADMIN = "ADMIN";
25      public static final String USER = "USER";
26  
27      private static final Set<String> SYSTEM_ROLES = Set.of(ADMIN, USER);
28  
29      private final Clock clock;
30      private final RoleRepository repository;
31  
32      @Autowired
33      public RoleService(RoleRepository repository) {
34          this(repository, Clock.systemUTC());
35      }
36  
37      RoleService(RoleRepository repository, Clock clock) {
38          this.repository = repository;
39          this.clock = clock;
40      }
41  
42      @Transactional
43      public Optional<Role> create(CreateRoleRequest request) {
44          if (repository.findByCode(request.code()).isPresent()) {
45              return Optional.empty();
46          }
47          Instant timestamp = currentTimestamp();
48          return Optional.of(toRecord(repository.save(new RoleEntity(request.code(), request.label(), timestamp, timestamp))));
49      }
50  
51      @Transactional
52      public Optional<Role> update(Long id, UpdateRoleRequest request) {
53          return repository.findById(id)
54                  .map(existing -> {
55                      existing.update(request.label(), currentTimestamp());
56                      return toRecord(repository.save(existing));
57                  });
58      }
59  
60      @Transactional
61      public boolean delete(Long id) {
62          return repository.findById(id)
63                  .filter(existing -> !SYSTEM_ROLES.contains(existing.getCode()))
64                  .map(existing -> {
65                      repository.delete(existing);
66                      return true;
67                  })
68                  .orElse(false);
69      }
70  
71      public List<Role> findAll() {
72          return repository.findAllByOrderByCodeAsc().stream()
73                  .map(RoleService::toRecord)
74                  .toList();
75      }
76  
77      public Optional<Role> findById(Long id) {
78          return repository.findById(id).map(RoleService::toRecord);
79      }
80  
81      public Optional<RoleEntity> findEntityByCode(String code) {
82          return repository.findByCode(code);
83      }
84  
85      @Transactional
86      public List<Role> seedDefaultRoles() {
87          return List.of(
88                  seedSystemRole(ADMIN, "Administrator"),
89                  seedSystemRole(USER, "User"));
90      }
91  
92      private Role seedSystemRole(String code, String label) {
93          Instant timestamp = currentTimestamp();
94          RoleEntity entity = repository.findByCode(code)
95                  .map(existing -> {
96                      existing.update(label, timestamp);
97                      return existing;
98                  })
99                  .orElseGet(() -> new RoleEntity(code, label, timestamp, timestamp));
100         return toRecord(repository.save(entity));
101     }
102 
103     private Instant currentTimestamp() {
104         return Instant.now(clock).truncatedTo(ChronoUnit.MICROS);
105     }
106 
107     public static Role toRecord(RoleEntity entity) {
108         return new Role(entity.getId(), entity.getCode(), entity.getLabel(), entity.getCreatedDate(), entity.getLastModifiedDate());
109     }
110 }