Skip to content

Instantly share code, notes, and snippets.

@tobinbc
Last active January 23, 2019 15:06
Show Gist options
  • Save tobinbc/98a8c18832278be3f2e61dd94a771ee9 to your computer and use it in GitHub Desktop.
Save tobinbc/98a8c18832278be3f2e61dd94a771ee9 to your computer and use it in GitHub Desktop.
Keeps track of user's last activity on websocket for session (with websocket we would not have http requests resetting the user session timeout timer in Spring)
package com. .api.service;
import com. .api.domain.user.UserInfo;
import com. .api.service.message.MessageService;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @description Keeps track of user's last activity on websocket for session (instead of http requests resetting the timer)
* @author Tobin
*/
@Service
public class IdleTimeService {
@Autowired
private SessionService sessionService;
private class IdleTimer {
public IdleTimer(Integer maxIdleTime) {
this.maxIdleTime = maxIdleTime;
this.lastActivityTime = new Date();
}
private Date lastActivityTime;
private Integer maxIdleTime;
public Integer getMaxIdleTime() {
return maxIdleTime;
}
public void setMaxIdleTime(Integer maxIdleTime) {
this.maxIdleTime = maxIdleTime;
}
public Date getLastActivityTime() {
return lastActivityTime;
}
public void setLastActivityTime(Date lastActivityTime) {
this.lastActivityTime = lastActivityTime;
}
}
private final Map<String, IdleTimer> userIdleMap = new ConcurrentHashMap<>();
private IdleTimeService() {
}
public void userActivity(UserInfo userInfo, Date date) {
if (userIdleMap.containsKey(userInfo.getUsername())) {
//Update user's entry if it exists
userIdleMap.get(userInfo.getUsername()).setLastActivityTime(date);
} else {
//Create new entry
IdleTimer idleTimer = new IdleTimer(userInfo.getUserSettings().getAutoLogoutInactivityMinutes());
userIdleMap.put(userInfo.getUsername(), idleTimer);
}
}
//Called from CRON every minute
public void checkExpiry() {
Iterator<String> itr = userIdleMap.keySet().iterator();
while (itr.hasNext()) {
String username = itr.next();
IdleTimer idleTimer = userIdleMap.get(username);
//If current time is greater than the last activity time plus the max idle time, logout.
if (new Date().getTime() > idleTimer.getLastActivityTime().getTime() + idleTimer.getMaxIdleTime() * 1000 * 60) {
sendExpiry(username);
removeUser(username); //TODO make removal part of session service
}
}
}
private void sendExpiry(String username) {
sessionService.userIdleTimeout(username);
}
public void removeUser(String username) {
if (userIdleMap.containsKey(username)) {
userIdleMap.remove(username);
}
}
public void updateInactivityTime(UserInfo userInfo, Integer maxIdleTime) {
//if admin updates user and they are not logged in
if (userIdleMap.containsKey(userInfo.getUsername())) {
userIdleMap.get(userInfo.getUsername()).setMaxIdleTime(maxIdleTime);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment