@@ -0,0 +1,3418 @@
+package stroom.security.server;%0A%0Aimport com.google.common.collect.HashMultimap;%0Aimport com.google.common.collect.SetMultimap;%0Aimport com.google.gwt.user.client.Window;%0Aimport org.springframework.stereotype.Component;%0Aimport stroom.apiclients.AuthenticationServiceClient;%0Aimport stroom.auth.service.ApiException;%0Aimport stroom.security.SecurityContext;%0A%0Aimport javax.inject.Inject;%0Aimport java.util.HashMap;%0Aimport java.util.List;%0Aimport java.util.Map;%0Aimport java.util.stream.Collectors;%0A%0A/**%0A * Manages user sessions.%0A *%0A * Sessions here are associated with sessions in the AuthenticationService and at the User Agent.%0A *%0A * Because of the authentication flow, the user might leave Stroom to authenticate elsewhere,%0A * or perform some other action. When they return they will have a new jSessionId,%0A * which is how Stroom manages it's internal sessions. But actually this jSessionId%0A * is part of the larger session. So this records the mappings of jSessionIds against%0A * sessions, as well as providing recall for sessions.%0A */%0A@Component%0Apublic class SessionManager %7B%0A    private static final org.slf4j.Logger LOGGER = org.slf4j.LoggerFactory.getLogger(SessionManager.class);%0A%0A    SetMultimap%3CString, String%3E sessionIdToJSessionId = HashMultimap.create();%0A    Map%3CString, String%3E jSessionIdToSessionId = new HashMap%3C%3E();%0A    private SecurityContext securityContext;%0A%0A    private AuthenticationServiceClient authenticationServiceClient;%0A    private final AuthenticationService authenticationService;%0A%0A    @Inject%0A    public SessionManager(%0A            SecurityContext securityContext,%0A            AuthenticationService authenticationService,%0A            AuthenticationServiceClient authenticationServiceClient)%7B%0A        this.securityContext = securityContext;%0A        this.authenticationService = authenticationService;%0A        this.authenticationServiceClient = authenticationServiceClient;%0A    %7D%0A%0A    public void add(String sessionId, String jSessionId) %7B%0A        //The jSessionId might be suffixed with 'node%3Cx%3E'. We don't want this.%0A        String plainJSessionId = jSessionId.split(%22%5C%5C.%22)%5B0%5D;%0A        sessionIdToJSessionId.put(sessionId, plainJSessionId);%0A        jSessionIdToSessionId.put(plainJSessionId, sessionId);%0A    %7D%0A%0A    public void forget(String sessionId)%7B%0A        sessionIdToJSessionId.removeAll(sessionId);%0A        List%3CString%3E jSessionIdsToRemove = jSessionIdToSessionId.entrySet().stream()%0A                .filter(entry -%3E entry.getValue().equals(sessionId))%0A                .map(entry -%3E entry.getKey())%0A                .collect(Collectors.toList());%0A        jSessionIdsToRemove.forEach(jSessionIdToRemove -%3E jSessionIdToSessionId.remove(jSessionIdToRemove));%0A    %7D%0A%0A    public String getSession(String jSessionId)%7B%0A        return jSessionIdToSessionId.get(jSessionId);%0A    %7D%0A%0A    public void logout() %7B%0A        // We need to let the AuthenticationService know that a logout has been initiated.%0A        // We don't need to call %60authenticationService.logout()%60 here because this will%0A        // be called by the call to AuthenticationService.%0A        LOGGER.info(%22Logging out user.%22);%0A        String jSessionId = securityContext.getJSessionId();%0A        String sessionId = getSession(jSessionId);%0A        try %7B%0A            authenticationServiceClient.getAuthServiceApi().logout(sessionId);%0A        %7D catch (ApiException e) %7B%0A            LOGGER.error(%22Unable to log user out!%22);%0A        %7D%0A    %7D%0A%7D%0A

Add session manager