View Javadoc
1   package fr.tiogars.inception.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.inception.domains.auth.role.entities.Role;
15  import fr.tiogars.inception.domains.auth.role.entities.RoleEntity;
16  import fr.tiogars.inception.domains.auth.role.models.CreateRoleRequest;
17  import fr.tiogars.inception.domains.auth.role.models.UpdateRoleRequest;
18  import fr.tiogars.inception.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 ANONYMOUS = "ANONYMOUS";
25      public static final String ADMIN = "ADMIN";
26      public static final String USER = "USER";
27  
28      private static final Set<String> SYSTEM_ROLES = Set.of(ANONYMOUS, ADMIN, USER);
29  
30      private final Clock clock;
31      private final RoleRepository repository;
32  
33      @Autowired
34      public RoleService(RoleRepository repository) {
35          this(repository, Clock.systemUTC());
36      }
37  
38      RoleService(RoleRepository repository, Clock clock) {
39          this.repository = repository;
40          this.clock = clock;
41      }
42  
43      @Transactional
44      public Optional<Role> create(CreateRoleRequest request) {
45          if (repository.findByCode(request.code()).isPresent()) {
46              return Optional.empty();
47          }
48          Instant timestamp = currentTimestamp();
49          return Optional.of(toRecord(repository.save(new RoleEntity(request.code(), request.label(), timestamp, timestamp))));
50      }
51  
52      @Transactional
53      public Optional<Role> update(Long id, UpdateRoleRequest request) {
54          return repository.findById(id)
55                  .map(existing -> {
56                      existing.update(request.label(), currentTimestamp());
57                      return toRecord(repository.save(existing));
58                  });
59      }
60  
61      @Transactional
62      public boolean delete(Long id) {
63          return repository.findById(id)
64                  .filter(existing -> !SYSTEM_ROLES.contains(existing.getCode()))
65                  .map(existing -> {
66                      repository.delete(existing);
67                      return true;
68                  })
69                  .orElse(false);
70      }
71  
72      public List<Role> findAll() {
73          return repository.findAllByOrderByCodeAsc().stream()
74                  .map(RoleService::toRecord)
75                  .toList();
76      }
77  
78      public Optional<Role> findById(Long id) {
79          return repository.findById(id).map(RoleService::toRecord);
80      }
81  
82      public Optional<RoleEntity> findEntityByCode(String code) {
83          return repository.findByCode(code);
84      }
85  
86      @Transactional
87      public List<Role> seedDefaultRoles() {
88          return List.of(
89                  seedSystemRole(ANONYMOUS, "Anonymous"),
90                  seedSystemRole(ADMIN, "Administrator"),
91                  seedSystemRole(USER, "User"));
92      }
93  
94      private Role seedSystemRole(String code, String label) {
95          Instant timestamp = currentTimestamp();
96          RoleEntity entity = repository.findByCode(code)
97                  .map(existing -> {
98                      existing.update(label, timestamp);
99                      return existing;
100                 })
101                 .orElseGet(() -> new RoleEntity(code, label, timestamp, timestamp));
102         return toRecord(repository.save(entity));
103     }
104 
105     private Instant currentTimestamp() {
106         return Instant.now(clock).truncatedTo(ChronoUnit.MICROS);
107     }
108 
109     public static Role toRecord(RoleEntity entity) {
110         return new Role(entity.getId(), entity.getCode(), entity.getLabel(), entity.getCreatedDate(), entity.getLastModifiedDate());
111     }
112 }