Skip to content

Commit

Permalink
Merge pull request #4283 from inception-project/feature/4282-Capture-…
Browse files Browse the repository at this point in the history
…start-and-end-of-user-session-in-event-log

#4282 - Capture start and end of user session in event log
  • Loading branch information
reckart authored Nov 7, 2023
2 parents f9c0425 + 771144f commit a2f9291
Show file tree
Hide file tree
Showing 5 changed files with 258 additions and 1 deletion.
26 changes: 26 additions & 0 deletions inception/inception-log/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
Expand Down Expand Up @@ -131,6 +135,11 @@
<groupId>javax.persistence</groupId>
<artifactId>javax.persistence-api</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>

<!-- DEPENDENCIES FOR TESTING -->
<dependency>
Expand Down Expand Up @@ -179,4 +188,21 @@
<scope>test</scope>
</dependency>
</dependencies>

<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<configuration>
<ignoredDependencies>
<!-- Servlet API needed but dependency plugin does not get it -->
<ignoredDependency>javax.servlet:javax.servlet-api</ignoredDependency>
</ignoredDependencies>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Licensed to the Technische Universität Darmstadt under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The Technische Universität Darmstadt
* licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.tudarmstadt.ukp.inception.log.adapter;

import java.io.IOException;

import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;

import de.tudarmstadt.ukp.clarin.webanno.support.JSONUtil;
import de.tudarmstadt.ukp.inception.log.model.SessionDetails;

@Component
public class AuthenticationSuccessEventAdapter
implements EventLoggingAdapter<AuthenticationSuccessEvent>
{
@Override
public boolean accepts(Object aEvent)
{
return aEvent instanceof AuthenticationSuccessEvent;
}

@Override
public String getEvent(AuthenticationSuccessEvent aEvent)
{
return "UserSessionStartedEvent";
}

@Override
public String getUser(AuthenticationSuccessEvent aEvent)
{
return aEvent.getAuthentication().getName();
}

@Override
public String getDetails(AuthenticationSuccessEvent aEvent) throws IOException
{
String sessionId;

try {
sessionId = RequestContextHolder.currentRequestAttributes().getSessionId();

SessionDetails details = new SessionDetails(sessionId);

return JSONUtil.toJsonString(details);
}
catch (Exception e) {
// Ignore
}

return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@

public interface EventLoggingAdapter<T>
{
public static final String SYSTEM_USER = "<SYSTEM>";
public static final String ANONYMOUS_USER = "anonymousUser";

boolean accepts(Object aEvent);

default String getDetails(T aEvent) throws Exception
Expand Down Expand Up @@ -71,7 +74,7 @@ default String getUser(T aEvent)
return context.getAuthentication().getName();
}
else {
return "<SYSTEM>";
return SYSTEM_USER;
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Licensed to the Technische Universität Darmstadt under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The Technische Universität Darmstadt
* licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.tudarmstadt.ukp.inception.log.adapter;

import java.io.IOException;
import java.util.Set;

import org.springframework.security.web.session.HttpSessionDestroyedEvent;
import org.springframework.stereotype.Component;

import de.tudarmstadt.ukp.clarin.webanno.support.JSONUtil;
import de.tudarmstadt.ukp.inception.log.model.SessionDetails;

@Component
public class HttpSessionDestroyedEventAdapter
implements EventLoggingAdapter<HttpSessionDestroyedEvent>
{
private static final Set<String> IGNORE_USERS = Set.of(ANONYMOUS_USER, SYSTEM_USER);

@Override
public boolean accepts(Object aEvent)
{
if (!(aEvent instanceof HttpSessionDestroyedEvent)) {
return false;
}

var user = getUser((HttpSessionDestroyedEvent) aEvent);
if (IGNORE_USERS.contains(user)) {
return false;
}

return true;
}

@Override
public String getEvent(HttpSessionDestroyedEvent aEvent)
{
return "UserSessionEndedEvent";
}

@Override
public String getUser(HttpSessionDestroyedEvent aEvent)
{
if (aEvent.getSecurityContexts().isEmpty()) {
return EventLoggingAdapter.super.getUser(aEvent);
}

return aEvent.getSecurityContexts().get(0).getAuthentication().getName();
}

@Override
public String getDetails(HttpSessionDestroyedEvent aEvent) throws IOException
{
var age = (System.currentTimeMillis() - aEvent.getSession().getLastAccessedTime()) / 1000;

var details = new SessionDetails(aEvent.getId());
details.setDuration(
aEvent.getSession().getLastAccessedTime() - aEvent.getSession().getCreationTime());
if (age > aEvent.getSession().getMaxInactiveInterval()) {
details.setExpiredAfterInactivity(age * 1000);
}

return JSONUtil.toJsonString(details);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Licensed to the Technische Universität Darmstadt under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The Technische Universität Darmstadt
* licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.tudarmstadt.ukp.inception.log.model;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;

@JsonInclude(Include.NON_NULL)
public class SessionDetails
{
private String sessionId;

@JsonInclude(Include.NON_DEFAULT)
private long expiredAfterInactivity;

@JsonInclude(Include.NON_DEFAULT)
private long duration;

public SessionDetails()
{
// Nothing to do
}

public SessionDetails(String aId)
{
sessionId = aId;
}

public String getSessionId()
{
return sessionId;
}

public void setSessionId(String aSessionId)
{
sessionId = aSessionId;
}

/**
* @return expired after milliseconds of inactivity
*/
public long getExpiredAfterInactivity()
{
return expiredAfterInactivity;
}

public void setExpiredAfterInactivity(long aExpiredAfterInactivity)
{
expiredAfterInactivity = aExpiredAfterInactivity;
}

/**
* @return duration of the session in milliseconds.
*/
public long getDuration()
{
return duration;
}

public void setDuration(long aDuration)
{
duration = aDuration;
}
}

0 comments on commit a2f9291

Please sign in to comment.