I have the following classes. I wonder if this structure makes sense in any terms especially the usage of the UserDetails class from Spring. Should I use loadbyusername method to create and remove methods in account service or is it okay? Then where should we use loadbyusername method?
Base class to cover fundamental properties like id, createdAt, etc.
@Accessors(chain = true)
@Data
@MappedSuperclass
public class Base {
@Id
private String id = UUID.randomUUID().toString();
@CreatedDate
private Date createdAt;
@LastModifiedDate
private Date updatedAt;
}
Account class
@Entity
@JsonIgnoreProperties(value = {"createdAt", "updatedAt"})
@Data
public class Account extends Base {
@NotNull
private String username;
@NotNull
private String password;
@NotNull
@Email
private String email;
@NotNull
private Role role;
}
Account details class implementing userdetails
public class AccountDetails implements UserDetails {
private Account account;
public AccountDetails(Account account) {
this.account = account;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return null;
}
@Override
public String getPassword() {
return account.getPassword();
}
@Override
public String getUsername() {
return account.getUsername();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
Account service
@Service
public class AccountService {
@Autowired
AccountRepository accountRepository;
@Autowired
BCryptPasswordEncoder bCryptPasswordEncoder;
@Autowired
ModelMapper modelMapper;
public boolean create(AccountDTO accountDTO) {
if (usernameExists(accountDTO.getUsername())) {
throw new UsernameExistsException();
}
Account account = modelMapper.map(accountDTO, Account.class);
account.setPassword(bCryptPasswordEncoder.encode(account.getPassword()));
account.setId(UUID.randomUUID().toString());
account.setRole(Role.USER);
if (accountRepository.save(account) != null) {
return true;
} else {
throw new RuntimeException();
}
}
public boolean remove(AccountDTO accountDTO) {
if (!usernameExists(accountDTO.getUsername())) {
throw new UsernameNotFoundException("Account named " + accountDTO.getUsername() + " not found");
}
Optional<Account> account = accountRepository.findByUsername(accountDTO.getUsername());
accountRepository.delete(account.get());
if (!usernameExists(accountDTO.getUsername())) {
return true;
}
return false;
}
public boolean usernameExists(String username) {
return accountRepository.findByUsername(username).isPresent();
}
}
AccountDetailsService implementing userdetailsservice
@Service
public class AccountDetailsService implements UserDetailsService {
@Autowired
AccountRepository accountRepository;
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
Optional<Account> optionalAccount = accountRepository.findByUsername(s);
if (!optionalAccount.isPresent()) {
throw new UsernameNotFoundException("Account named " + s + " not found");
}
return new AccountDetails(optionalAccount.get());
}
}