diff --git a/inception/inception-log/pom.xml b/inception/inception-log/pom.xml
index cbdbe468c83..360911778b5 100644
--- a/inception/inception-log/pom.xml
+++ b/inception/inception-log/pom.xml
@@ -94,6 +94,10 @@
org.springframework.security
spring-security-core
+
+ org.springframework.security
+ spring-security-web
+
org.slf4j
@@ -131,6 +135,11 @@
javax.persistence
javax.persistence-api
+
+ javax.servlet
+ javax.servlet-api
+ provided
+
@@ -179,4 +188,21 @@
test
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+
+
+
+ javax.servlet:javax.servlet-api
+
+
+
+
+
+
diff --git a/inception/inception-log/src/main/java/de/tudarmstadt/ukp/inception/log/adapter/AuthenticationSuccessEventAdapter.java b/inception/inception-log/src/main/java/de/tudarmstadt/ukp/inception/log/adapter/AuthenticationSuccessEventAdapter.java
new file mode 100644
index 00000000000..81a64e44c97
--- /dev/null
+++ b/inception/inception-log/src/main/java/de/tudarmstadt/ukp/inception/log/adapter/AuthenticationSuccessEventAdapter.java
@@ -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
+{
+ @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;
+ }
+}
diff --git a/inception/inception-log/src/main/java/de/tudarmstadt/ukp/inception/log/adapter/EventLoggingAdapter.java b/inception/inception-log/src/main/java/de/tudarmstadt/ukp/inception/log/adapter/EventLoggingAdapter.java
index eca9806546d..c9dbf633af3 100644
--- a/inception/inception-log/src/main/java/de/tudarmstadt/ukp/inception/log/adapter/EventLoggingAdapter.java
+++ b/inception/inception-log/src/main/java/de/tudarmstadt/ukp/inception/log/adapter/EventLoggingAdapter.java
@@ -27,6 +27,9 @@
public interface EventLoggingAdapter
{
+ public static final String SYSTEM_USER = "";
+ public static final String ANONYMOUS_USER = "anonymousUser";
+
boolean accepts(Object aEvent);
default String getDetails(T aEvent) throws Exception
@@ -71,7 +74,7 @@ default String getUser(T aEvent)
return context.getAuthentication().getName();
}
else {
- return "";
+ return SYSTEM_USER;
}
}
diff --git a/inception/inception-log/src/main/java/de/tudarmstadt/ukp/inception/log/adapter/HttpSessionDestroyedEventAdapter.java b/inception/inception-log/src/main/java/de/tudarmstadt/ukp/inception/log/adapter/HttpSessionDestroyedEventAdapter.java
new file mode 100644
index 00000000000..05fc0dc7157
--- /dev/null
+++ b/inception/inception-log/src/main/java/de/tudarmstadt/ukp/inception/log/adapter/HttpSessionDestroyedEventAdapter.java
@@ -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
+{
+ private static final Set 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);
+ }
+}
diff --git a/inception/inception-log/src/main/java/de/tudarmstadt/ukp/inception/log/model/SessionDetails.java b/inception/inception-log/src/main/java/de/tudarmstadt/ukp/inception/log/model/SessionDetails.java
new file mode 100644
index 00000000000..042134e4d7c
--- /dev/null
+++ b/inception/inception-log/src/main/java/de/tudarmstadt/ukp/inception/log/model/SessionDetails.java
@@ -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;
+ }
+}