Done logic for getting online users and their last active time

This commit is contained in:
Rohan Sircar 2019-11-12 10:56:50 +05:30
parent 8824678682
commit 14843cd8f0
14 changed files with 327 additions and 8 deletions

View File

@ -1,6 +1,7 @@
package org.ros.chatto; package org.ros.chatto;
import org.modelmapper.ModelMapper; import org.modelmapper.ModelMapper;
import org.ros.chatto.logged.ActiveUserStore;
import org.ros.chatto.security.AuthenticationSuccessHandlerImpl; import org.ros.chatto.security.AuthenticationSuccessHandlerImpl;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.MessageSource; import org.springframework.context.MessageSource;
@ -44,6 +45,11 @@ public class BeanConfigurations {
return messageSource; return messageSource;
} }
@Bean
ActiveUserStore activeUserStore() {
return new ActiveUserStore();
}
// @Bean // @Bean
// public Connection connection() throws SQLException // public Connection connection() throws SQLException
// { // {

View File

@ -1,14 +1,14 @@
package org.ros.chatto; package org.ros.chatto;
import org.ros.chatto.logged.MyLogoutSuccessHandler;
import org.ros.chatto.logged.MySimpleUrlAuthenticationSuccessHandler;
import org.ros.chatto.security.MyUserDetailsService; import org.ros.chatto.security.MyUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order; import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider; import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@ -17,8 +17,7 @@ import org.springframework.security.core.userdetails.UserCache;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer; import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
@Configuration @Configuration
@EnableWebSecurity @EnableWebSecurity
@ -96,8 +95,13 @@ public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Configuration @Configuration
@Order(2) @Order(2)
public static class FormWebSecurity extends WebSecurityConfigurerAdapter { public static class FormWebSecurity extends WebSecurityConfigurerAdapter {
@Override @Autowired
private MySimpleUrlAuthenticationSuccessHandler mySimpleUrlAuthenticationSuccessHandler;
@Autowired
private MyLogoutSuccessHandler myLogoutSuccessHandler;
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception { protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.authorizeRequests() httpSecurity.authorizeRequests()
// .antMatchers(HttpMethod.POST, "/api/**").permitAll() // .antMatchers(HttpMethod.POST, "/api/**").permitAll()
@ -115,7 +119,9 @@ public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
.and() .and()
.formLogin().loginPage("/login").permitAll().loginProcessingUrl("/perform_login") .formLogin().loginPage("/login").permitAll().loginProcessingUrl("/perform_login")
// .successHandler(authenticationSuccessHandler) .successHandler(mySimpleUrlAuthenticationSuccessHandler)
.and()
.logout().logoutSuccessHandler(myLogoutSuccessHandler)
// .failureUrl("/?login_error") // .failureUrl("/?login_error")
// .and() // .and()
// .logout().invalidateHttpSession(true) // .logout().invalidateHttpSession(true)

View File

@ -6,6 +6,8 @@ import java.util.List;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.ros.chatto.dto.ActiveUserDTO;
import org.ros.chatto.logged.ActiveUserStore;
import org.ros.chatto.model.ChatMessage; import org.ros.chatto.model.ChatMessage;
import org.ros.chatto.model.ChatUser; import org.ros.chatto.model.ChatUser;
import org.ros.chatto.model.MessageCipher; import org.ros.chatto.model.MessageCipher;
@ -16,6 +18,7 @@ import org.ros.chatto.repository.RoleRepository;
import org.ros.chatto.repository.UserRepository; import org.ros.chatto.repository.UserRepository;
import org.ros.chatto.repository.UserRepositoryCustom; import org.ros.chatto.repository.UserRepositoryCustom;
import org.ros.chatto.repository.UserRoleRepository; import org.ros.chatto.repository.UserRoleRepository;
import org.ros.chatto.service.UserService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
@ -47,7 +50,10 @@ public class DemoRestController {
MessageCipherRepository messageCipherRepository; MessageCipherRepository messageCipherRepository;
@Autowired @Autowired
ChatMessageRepository chatMessageRepository; ChatMessageRepository chatMessageRepository;
@Autowired
ActiveUserStore activeUserStore;
@Autowired
private UserService userService;
@GetMapping("/users") @GetMapping("/users")
public List<ChatUser> getAllUsers() { public List<ChatUser> getAllUsers() {
return userRepository.findAll(); return userRepository.findAll();
@ -122,4 +128,14 @@ public class DemoRestController {
return "redirect:/users"; return "redirect:/users";
} }
@GetMapping(value = "/loggedUsers")
public ActiveUserStore getActiveUsers() {
return activeUserStore;
}
@GetMapping(value = "/loggedUsers2")
public List<ActiveUserDTO> getOtherActiveUsers(Principal principal)
{
return userService.getOtherActiveUsers(principal.getName());
}
} }

View File

@ -0,0 +1,12 @@
package org.ros.chatto.dto;
import java.time.Instant;
import lombok.Data;
@Data
public class ActiveUserDTO {
private String userName;
private Boolean online;
private Instant lastActive;
}

View File

@ -0,0 +1,11 @@
package org.ros.chatto.logged;
import java.time.Instant;
import lombok.Data;
@Data
public class ActiveUser {
private String userName;
private Instant lastActive;
}

View File

@ -0,0 +1,20 @@
package org.ros.chatto.logged;
import java.util.ArrayList;
import java.util.List;
import lombok.Getter;
import lombok.Setter;
@Getter @Setter
public class ActiveUserStore {
public List<String> users;
public List<ActiveUser> activeUsers;
public ActiveUserStore() {
users = new ArrayList<String>();
activeUsers = new ArrayList<>();
}
}

View File

@ -0,0 +1,96 @@
package org.ros.chatto.logged;
import java.time.Instant;
import java.util.List;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import javax.servlet.http.HttpSessionEvent;
import org.ros.chatto.model.ChatUser;
import org.ros.chatto.model.UserSession;
import org.ros.chatto.repository.UserSessionRepository;
import org.ros.chatto.service.UserService;
import org.springframework.stereotype.Component;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import lombok.Getter;
import lombok.Setter;
@Component
@Getter
@Setter
public class LoggedUser implements HttpSessionBindingListener {
private String username;
private ActiveUserStore activeUserStore;
public LoggedUser(String username, ActiveUserStore activeUserStore) {
this.username = username;
this.activeUserStore = activeUserStore;
}
public LoggedUser() {
}
@Override
public void valueBound(HttpSessionBindingEvent event) {
UserService userService = getUserService(event);
UserSessionRepository userSessionRepository = getUserSessionRepository(event);
List<String> users = activeUserStore.getUsers();
List<ActiveUser> activeUsers = activeUserStore.getActiveUsers();
LoggedUser user = (LoggedUser) event.getValue();
if (!users.contains(user.getUsername())) {
users.add(user.getUsername());
}
Instant instant = Instant.now();
boolean found = activeUsers.stream().anyMatch(au -> au.getUserName().equals(user.getUsername()));
if (!found) {
System.out.println("Test found ");
ActiveUser activeUser = new ActiveUser();
activeUser.setUserName(user.getUsername());
activeUser.setLastActive(instant);
activeUsers.add(activeUser);
}
ChatUser chatUser = userService.findByUserName(user.getUsername());
UserSession userSession = userSessionRepository.findByUserName(user.getUsername());
if(userSession == null)
{
userSession = new UserSession();
}
userSession.setUser(chatUser);
userSession.setTimeStamp(instant);
userSessionRepository.save(userSession);
}
@Override
public void valueUnbound(HttpSessionBindingEvent event) {
List<String> users = activeUserStore.getUsers();
LoggedUser user = (LoggedUser) event.getValue();
List<ActiveUser> activeUsers = activeUserStore.getActiveUsers();
if (users.contains(user.getUsername())) {
users.remove(user.getUsername());
}
activeUsers.removeIf(au -> au.getUserName().equals(user.getUsername()));
}
private UserService getUserService(HttpSessionEvent se) {
WebApplicationContext context = WebApplicationContextUtils
.getWebApplicationContext(se.getSession().getServletContext());
return (UserService) context.getBean(UserService.class);
}
private UserSessionRepository getUserSessionRepository(HttpSessionEvent se) {
WebApplicationContext context = WebApplicationContextUtils
.getWebApplicationContext(se.getSession().getServletContext());
return (UserSessionRepository) context.getBean(UserSessionRepository.class);
}
}

View File

@ -0,0 +1,26 @@
package org.ros.chatto.logged;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.stereotype.Component;
@Component("myLogoutSuccessHandler")
public class MyLogoutSuccessHandler implements LogoutSuccessHandler{
@Override
public void onLogoutSuccess(HttpServletRequest request,
HttpServletResponse response, Authentication authentication)
throws IOException, ServletException {
HttpSession session = request.getSession();
if (session != null){
session.removeAttribute("user");
}
response.sendRedirect("/login?logout");
}
}

View File

@ -0,0 +1,31 @@
package org.ros.chatto.logged;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
@Component("myAuthenticationSuccessHandler")
public class MySimpleUrlAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
@Autowired
ActiveUserStore activeUserStore;
@Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response, Authentication authentication)
throws IOException {
HttpSession session = request.getSession(false);
if (session != null) {
LoggedUser user = new LoggedUser(authentication.getName(), activeUserStore);
session.setAttribute("user", user);
}
response.sendRedirect("/chat");
}
}

View File

@ -0,0 +1,30 @@
package org.ros.chatto.model;
import java.time.Instant;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import org.ros.chatto.model.ChatUser;
import lombok.Data;
@Data
@Entity
@Table(name = "user_sessions")
public class UserSession {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
// private String sessionId;
@OneToOne
@JoinColumn(name = "user_id")
private ChatUser user;
// private Boolean loggedIn;
private Instant timeStamp;
}

View File

@ -2,9 +2,11 @@ package org.ros.chatto.repository;
import org.ros.chatto.model.ChatUser; import org.ros.chatto.model.ChatUser;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
@Repository @Repository
public interface UserRepository extends JpaRepository<ChatUser, Long>{ public interface UserRepository extends JpaRepository<ChatUser, Long>{
@Query("select cu from ChatUser cu where cu.userName = ?1")
public ChatUser findByUserName(String userName); public ChatUser findByUserName(String userName);
} }

View File

@ -0,0 +1,12 @@
package org.ros.chatto.repository;
import org.ros.chatto.model.UserSession;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
@Repository
public interface UserSessionRepository extends JpaRepository<UserSession, Long> {
@Query("select us from UserSession us where us.user.userName = ?1 ")
public UserSession findByUserName(String userName);
}

View File

@ -2,6 +2,7 @@ package org.ros.chatto.service;
import java.util.List; import java.util.List;
import org.ros.chatto.dto.ActiveUserDTO;
import org.ros.chatto.dto.UserRegistrationDTO; import org.ros.chatto.dto.UserRegistrationDTO;
import org.ros.chatto.model.ChatUser; import org.ros.chatto.model.ChatUser;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -12,4 +13,6 @@ public interface UserService {
public List<String> findAllOtherUsers(String userName); public List<String> findAllOtherUsers(String userName);
public void registerUser(UserRegistrationDTO userRegistrationDTO); public void registerUser(UserRegistrationDTO userRegistrationDTO);
public List<String> getAllRegularUsers(); public List<String> getAllRegularUsers();
public ChatUser findByUserName(String userName);
public List<ActiveUserDTO> getOtherActiveUsers(String userName);
} }

View File

@ -1,16 +1,24 @@
package org.ros.chatto.service; package org.ros.chatto.service;
import java.time.Instant;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import javax.transaction.Transactional; import javax.transaction.Transactional;
import org.ros.chatto.dto.ActiveUserDTO;
import org.ros.chatto.dto.UserRegistrationDTO; import org.ros.chatto.dto.UserRegistrationDTO;
import org.ros.chatto.logged.ActiveUserStore;
import org.ros.chatto.model.ChatUser; import org.ros.chatto.model.ChatUser;
import org.ros.chatto.model.Role; import org.ros.chatto.model.Role;
import org.ros.chatto.model.UserRole; import org.ros.chatto.model.UserRole;
import org.ros.chatto.model.UserSession;
import org.ros.chatto.repository.UserRepository; import org.ros.chatto.repository.UserRepository;
import org.ros.chatto.repository.UserRepositoryCustom; import org.ros.chatto.repository.UserRepositoryCustom;
import org.ros.chatto.repository.UserRoleRepository; import org.ros.chatto.repository.UserRoleRepository;
import org.ros.chatto.repository.UserSessionRepository;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -32,6 +40,12 @@ public class UserServiceImpl implements UserService{
@Autowired @Autowired
UserRepositoryCustom userRepositoryCustom; UserRepositoryCustom userRepositoryCustom;
@Autowired
private UserSessionRepository userSessionRepository;
@Autowired
private ActiveUserStore activeUserStore;
@Override @Override
@Transactional @Transactional
public void saveChatUser(ChatUser user) { public void saveChatUser(ChatUser user) {
@ -72,4 +86,38 @@ public class UserServiceImpl implements UserService{
return userRoleRepository.getAllRegularUser(); return userRoleRepository.getAllRegularUser();
} }
public List<ActiveUserDTO> getOtherActiveUsers(String userName) {
List<String> userList = findAllOtherUsers(userName);
List<String> onlineUsers = activeUserStore.getUsers();
List<ActiveUserDTO> activeUserDTOs = new ArrayList<ActiveUserDTO>();
Map<String, Instant> lastActiveMap = convertToMap(userSessionRepository.findAll());
userList.forEach(u -> {
ActiveUserDTO activeUserDTO = new ActiveUserDTO();
activeUserDTO.setUserName(u);
activeUserDTO.setOnline(false);
activeUserDTO.setLastActive(lastActiveMap.get(u));
if(onlineUsers.contains(u))
{
activeUserDTO.setOnline(true);
}
activeUserDTOs.add(activeUserDTO);
});
return activeUserDTOs;
}
@Override
public ChatUser findByUserName(String userName) {
// TODO Auto-generated method stub
return userRepository.findByUserName(userName);
}
private Map<String, Instant> convertToMap(List<UserSession> userSessionList)
{
Map<String, Instant> userMap = new HashMap<>();
userSessionList.forEach(us -> {
userMap.put(us.getUser().getUserName(), us.getTimeStamp());
});
return userMap;
}
} }