A self hosted chat application with end-to-end encrypted messaging.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

203 lines
6.1 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  1. package org.ros.chatto.service;
  2. import java.time.Duration;
  3. import java.time.Instant;
  4. import java.util.ArrayList;
  5. import java.util.HashMap;
  6. import java.util.List;
  7. import java.util.Map;
  8. import java.util.Optional;
  9. import java.util.Set;
  10. import java.util.stream.Collectors;
  11. import org.ros.chatto.dto.ActiveUserDTO;
  12. import org.ros.chatto.dto.UserRegistrationDTO;
  13. import org.ros.chatto.logged.TokenCacheUtil;
  14. import org.ros.chatto.model.ChatUser;
  15. import org.ros.chatto.model.Role;
  16. import org.ros.chatto.model.UserRole;
  17. import org.ros.chatto.model.UserSession;
  18. import org.ros.chatto.repository.RoleRepository;
  19. import org.ros.chatto.repository.UserRepository;
  20. import org.ros.chatto.repository.UserRoleRepository;
  21. import org.ros.chatto.repository.UserSessionRepository;
  22. import org.springframework.security.authentication.InternalAuthenticationServiceException;
  23. import org.springframework.security.crypto.password.PasswordEncoder;
  24. import org.springframework.stereotype.Service;
  25. import org.springframework.transaction.annotation.Transactional;
  26. import lombok.RequiredArgsConstructor;
  27. import lombok.extern.slf4j.Slf4j;
  28. @Transactional
  29. @Service
  30. @RequiredArgsConstructor
  31. @Slf4j
  32. public class UserServiceImpl implements UserService {
  33. private final UserRepository userRepository;
  34. private final UserRoleRepository userRoleRepository;
  35. private final PasswordEncoder passwordEncoder;
  36. private final RoleRepository roleRepository;
  37. private final UserSessionRepository userSessionRepository;
  38. private final UserTokenService userTokenService;
  39. @Override
  40. public ChatUser createUser(final UserRegistrationDTO userRegistrationDTO) {
  41. final ChatUser user = new ChatUser();
  42. user.setUserName(userRegistrationDTO.getUserName());
  43. user.setPassword(
  44. passwordEncoder.encode(userRegistrationDTO.getPassword()));
  45. final ChatUser changedUser = userRepository.save(user);
  46. final UserRole userRole = new UserRole();
  47. final Role role = roleRepository.findByName("USER");
  48. userRole.setRole(role);
  49. userRole.setUser(changedUser);
  50. return userRoleRepository.save(userRole).getUser();
  51. }
  52. @Override
  53. @Transactional(readOnly = true)
  54. public List<String> findAllOtherUsers(final String userName) {
  55. return userRepository.findAllOtherUserNames(userName);
  56. }
  57. @Transactional(readOnly = true)
  58. @Override
  59. public List<String> getAllRegularUsers() {
  60. return userRoleRepository.getAllRegularUser();
  61. }
  62. @Transactional(readOnly = true)
  63. public List<ActiveUserDTO> getOtherActiveUsers(final String userName) {
  64. final List<String> userList = findAllOtherUsers(userName);
  65. final List<UserSession> userSessionsList = userSessionRepository
  66. .findAllUserSessions();
  67. final Map<String, UserSession> lastActiveMap = convertToMap(
  68. userSessionsList);
  69. final List<ActiveUserDTO> activeUserDTOs = new ArrayList<ActiveUserDTO>();
  70. userList.forEach(u -> {
  71. final ActiveUserDTO activeUserDTO = new ActiveUserDTO();
  72. final UserSession us = lastActiveMap.get(u);
  73. activeUserDTO.setUserName(u);
  74. activeUserDTO.setOnline(false);
  75. activeUserDTO.setLastActive(null);
  76. if (us != null) {
  77. activeUserDTO.setOnline(us.isOnline());
  78. activeUserDTO.setLastActive(us.getTimeStamp());
  79. }
  80. activeUserDTOs.add(activeUserDTO);
  81. });
  82. return activeUserDTOs;
  83. }
  84. @Transactional(readOnly = true)
  85. @Override
  86. public Optional<ChatUser> getUser(final String userName) {
  87. return userRepository.findByUserName(userName);
  88. }
  89. private Map<String, UserSession> convertToMap(
  90. final List<UserSession> userSessionList) {
  91. final Map<String, UserSession> userMap = new HashMap<>();
  92. userSessionList.forEach(us -> {
  93. userMap.put(us.getUser().getUserName(), us);
  94. });
  95. return userMap;
  96. }
  97. private String toLastActiveString(final Instant lastActive) {
  98. if (lastActive == null)
  99. return null;
  100. final Duration duration = Duration.between(lastActive, Instant.now());
  101. final long hours = duration.toHours();
  102. final long minutes = duration.toMinutes();
  103. final long days = duration.toDays();
  104. if (minutes < 60) {
  105. return String.format("%d minutes ago", minutes);
  106. } else {
  107. if (hours < 24) {
  108. return String.format("%d hours ago", hours);
  109. } else {
  110. if (days < 30) {
  111. return String.format("%d days ago", days);
  112. } else if (days < 366) {
  113. return String.format("%d months ago", days / 30);
  114. } else {
  115. return String.format("%d years ago", days / 365);
  116. }
  117. }
  118. }
  119. }
  120. @Override
  121. @Transactional(readOnly = true)
  122. public ChatUser getUserWithRole(final String userName) {
  123. return userRepository.findByUserNameWithRole(userName);
  124. }
  125. @Override
  126. public void incrementUserSession(final String userName) {
  127. final Optional<ChatUser> chatUser = getUser(userName);
  128. final Instant instant = Instant.now();
  129. chatUser.ifPresent(cu -> {
  130. UserSession userSession = userSessionRepository
  131. .findByUserName(userName);
  132. if (userSession == null) {
  133. userSession = new UserSession();
  134. }
  135. userSession.setUser(cu);
  136. userSession.setTimeStamp(instant);
  137. userSession.setOnline(true);
  138. userSession.setNumSessions(userSession.getNumSessions() + 1);
  139. userSessionRepository.save(userSession);
  140. });
  141. }
  142. @Override
  143. public UserSession decrementUserSession(final String userName) {
  144. final UserSession userSession = userSessionRepository
  145. .findByUserName(userName);
  146. final Instant instant = Instant.now();
  147. if (userSession == null) {
  148. log.error("User session is somehow null for user: " + userName);
  149. throw new InternalAuthenticationServiceException(
  150. "User session not found");
  151. }
  152. final ChatUser chatUser = userSession.getUser();
  153. int numSessions = userSession.getNumSessions();
  154. if (--numSessions == 0) {
  155. log.info("Num sessions is 0 so setting user to offline");
  156. log.info("Deleting token and evicting cache for user: "
  157. + chatUser.getUserName());
  158. userSession.setOnline(false);
  159. userTokenService.deleteToken(chatUser.getUserName());
  160. TokenCacheUtil.evictSingleTokenValue(chatUser.getUserName());
  161. }
  162. userSession.setNumSessions(numSessions);
  163. userSession.setTimeStamp(instant);
  164. return userSessionRepository.save(userSession);
  165. }
  166. @Override
  167. public Set<Role> getRoles(final ChatUser user) {
  168. return user.getUserRoles().stream().map(ur -> ur.getRole())
  169. .collect(Collectors.toSet());
  170. }
  171. }