From 1ca1aa74cc3797638e990c0abe127bec0661ec9c Mon Sep 17 00:00:00 2001 From: srosse <none@none> Date: Fri, 16 Nov 2012 10:59:20 +0100 Subject: [PATCH] OO-271: refactor the user session management, move the the logic in its own manager, persist the time out values, make the admin GUI a bit better --- .../bps/course/nodes/vc/_spring/vcContext.xml | 7 +- .../java/org/olat/NewControllerFactory.java | 6 +- src/main/java/org/olat/admin/AdminModule.java | 16 +- .../org/olat/admin/AdminModuleDispatcher.java | 7 +- .../admin/_i18n/LocalStrings_de.properties | 4 + .../datasources/ThreadAndControllerInfo.java | 5 +- .../admin/sysinfo/MRTGStatsDispatcher.java | 10 +- .../olat/admin/sysinfo/SessionAdminForm.java | 92 --- .../SessionAdminOldestSessionForm.java | 78 --- .../SessionAdministrationController.java | 216 ------ .../olat/admin/sysinfo/SysinfoController.java | 16 - .../sysinfo/UserSessionAdminController.java | 110 +++ .../UserSessionConfigAdminController.java | 192 +++++ .../admin/sysinfo/UserSessionController.java | 82 ++- .../sysinfo/UserSessionDetailsController.java | 114 +++ .../UserSessionInformationsController.java | 106 +++ .../admin/sysinfo/UserSessionTableModel.java | 15 +- .../sysinfo/_content/usersession_admin.html | 7 + .../sysinfo/_content/usersession_infos.html | 2 + .../sysinfo/_i18n/LocalStrings_de.properties | 3 + .../org/olat/basesecurity/AuthHelper.java | 17 +- .../_spring/baseSecurityContext.xml | 6 +- .../commons/servlets/WebDAVManagerImpl.java | 18 +- .../servlets/_spring/webdavManagerContext.xml | 1 + .../ContextHelpFilePathHandler.java | 19 +- .../org/olat/core/_spring/mainCorecontext.xml | 1 - .../_spring/contextHelpCorecontext.xml | 7 +- .../fullWebApp/DefaultFooterController.java | 5 +- .../fullWebApp/DefaultTopNavController.java | 4 +- .../util/_spring/StickyMessageCorecontext.xml | 6 +- .../glossary/_spring/glossaryCorecontext.xml | 7 +- .../services/_spring/servicesCorecontext.xml | 1 - .../_spring/taskExecutorCorecontext.xml | 7 +- .../java/org/olat/core/gui/UserRequest.java | 4 +- .../org/olat/core/gui/components/Window.java | 2 - .../components/util/UserLoggedInCounter.java | 7 +- .../core/gui/control/DefaultController.java | 5 +- .../generic/layout/GenericMainController.java | 16 + .../org/olat/core/gui/media/ServletUtil.java | 7 +- .../java/org/olat/core/logging/Tracing.java | 6 +- .../activity/UserActivityLoggerImpl.java | 4 +- .../org/olat/core/util/SignOnOffEvent.java | 2 + .../java/org/olat/core/util/UserSession.java | 660 ++---------------- .../core/util/_spring/utilCorecontext.xml | 25 + .../org/olat/core/util/i18n/I18nManager.java | 4 +- .../util/i18n/_spring/i18nCorecontext.xml | 6 +- .../core/util/session/UserSessionManager.java | 605 ++++++++++++++++ .../core/util/session/UserSessionModule.java | 85 +++ .../version/_spring/versioningCorecontext.xml | 7 +- .../assessment/_spring/assessmentContext.xml | 3 +- .../nodes/_spring/buildingblockContext.xml | 1 - .../dispatcher/AuthenticatedDispatcher.java | 4 +- .../org/olat/dispatcher/DMZDispatcher.java | 6 +- .../org/olat/dispatcher/RESTDispatcher.java | 3 +- .../RedirectToAutoGuestLoginDispatcher.java | 11 +- .../group/_spring/businessGroupContext.xml | 1 - .../org/olat/ims/qti/QTIStaticsHandler.java | 5 +- .../_spring/instantMessagingContext.xml | 1 - .../rosterandchat/ChangePresenceJob.java | 12 +- .../ui/ConnectedUsersLocal.java | 10 +- .../olat/modules/_spring/modulesContext.xml | 1 - .../_spring/openmeetingsContext.xml | 1 - .../modules/vitero/_spring/viteroContext.xml | 1 - .../accesscontrol/_spring/acContext.xml | 1 - .../provider/paypal/ui/PaypalMapper.java | 4 +- .../restapi/security/RestApiLoginFilter.java | 11 +- .../system/OpenOLATStatisticsWebService.java | 7 +- .../ShibbolethRegistrationController.java | 8 +- .../olat/upgrade/_spring/upgradeContext.xml | 1 - .../org/olat/user/ChangePrefsController.java | 15 +- .../resources/serviceconfig/olat.properties | 4 + .../org/olat/_spring/extensionContext.xml | 41 +- .../dispatcher/mapper/MapperServiceTest.java | 5 +- src/test/java/org/olat/test/OlatTestCase.java | 1 + 74 files changed, 1608 insertions(+), 1182 deletions(-) delete mode 100644 src/main/java/org/olat/admin/sysinfo/SessionAdminForm.java delete mode 100644 src/main/java/org/olat/admin/sysinfo/SessionAdminOldestSessionForm.java delete mode 100644 src/main/java/org/olat/admin/sysinfo/SessionAdministrationController.java create mode 100644 src/main/java/org/olat/admin/sysinfo/UserSessionAdminController.java create mode 100644 src/main/java/org/olat/admin/sysinfo/UserSessionConfigAdminController.java create mode 100644 src/main/java/org/olat/admin/sysinfo/UserSessionDetailsController.java create mode 100644 src/main/java/org/olat/admin/sysinfo/UserSessionInformationsController.java create mode 100644 src/main/java/org/olat/admin/sysinfo/_content/usersession_admin.html create mode 100644 src/main/java/org/olat/admin/sysinfo/_content/usersession_infos.html create mode 100644 src/main/java/org/olat/core/util/session/UserSessionManager.java create mode 100644 src/main/java/org/olat/core/util/session/UserSessionModule.java diff --git a/src/main/java/de/bps/course/nodes/vc/_spring/vcContext.xml b/src/main/java/de/bps/course/nodes/vc/_spring/vcContext.xml index d21ccb56525..55cccb7c9f3 100644 --- a/src/main/java/de/bps/course/nodes/vc/_spring/vcContext.xml +++ b/src/main/java/de/bps/course/nodes/vc/_spring/vcContext.xml @@ -1,14 +1,9 @@ <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans - http://www.springframework.org/schema/beans/spring-beans-3.0.xsd - http://www.springframework.org/schema/context - http://www.springframework.org/schema/context/spring-context-3.0.xsd"> - -<context:annotation-config /> + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <!-- ####################################### --> <!-- # VIRTUAL CLASSROOM SERVICE PROVIDERS # --> diff --git a/src/main/java/org/olat/NewControllerFactory.java b/src/main/java/org/olat/NewControllerFactory.java index a248af842a8..04ad67dfbc7 100644 --- a/src/main/java/org/olat/NewControllerFactory.java +++ b/src/main/java/org/olat/NewControllerFactory.java @@ -48,6 +48,7 @@ import org.olat.core.id.context.ContextEntryControllerCreator; import org.olat.core.id.context.TabContext; import org.olat.core.logging.AssertException; import org.olat.core.logging.LogDelegator; +import org.olat.core.util.UserSession; import org.olat.core.util.resource.OresHelper; import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryManager; @@ -163,7 +164,8 @@ public class NewControllerFactory extends LogDelegator { } // was brasato:: DTabs dts = wControl.getDTabs(); - Window window = Windows.getWindows(ureq.getUserSession()).getWindow(ureq); + UserSession usess = ureq.getUserSession(); + Window window = Windows.getWindows(usess).getWindow(ureq); if (window == null) { logDebug("Found no window for jumpin => take WindowBackOffice", null); @@ -230,7 +232,7 @@ public class NewControllerFactory extends LogDelegator { return false; } else { WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(bc, dt.getWindowControl()); - ureq.getUserSession().addToHistory(ureq, bc); + usess.addToHistory(ureq, bc); Controller launchC = typeHandler.createController(mainCe, ureq, bwControl); if (launchC == null) { throw new AssertException("ControllerFactory could not create a controller to be launched. Please validate businesspath " diff --git a/src/main/java/org/olat/admin/AdminModule.java b/src/main/java/org/olat/admin/AdminModule.java index 4ee6f59e2a0..2f8e0a11f34 100644 --- a/src/main/java/org/olat/admin/AdminModule.java +++ b/src/main/java/org/olat/admin/AdminModule.java @@ -33,6 +33,7 @@ import org.olat.NewControllerFactory; import org.olat.admin.site.AdminSite; import org.olat.admin.user.UserAdminContextEntryControllerCreator; import org.olat.basesecurity.AuthHelper; +import org.olat.core.CoreSpringFactory; import org.olat.core.commons.fullWebApp.util.GlobalStickyMessage; import org.olat.core.commons.persistence.DBFactory; import org.olat.core.configuration.AbstractOLATModule; @@ -40,7 +41,7 @@ import org.olat.core.configuration.PersistedProperties; import org.olat.core.id.User; import org.olat.core.id.context.SiteContextEntryControllerCreator; import org.olat.core.logging.Tracing; -import org.olat.core.util.UserSession; +import org.olat.core.util.session.UserSessionManager; import org.olat.instantMessaging.rosterandchat.ChangePresenceJob; import org.olat.properties.Property; import org.olat.properties.PropertyManager; @@ -172,9 +173,9 @@ public class AdminModule extends AbstractOLATModule { * Invalidated all session except administrator-sessions. * @return Number of invalidated sessions */ - public static int invalidateAllSessions() { + public static int invalidateAllSessionsDepr() { Tracing.logAudit("Session administration: Invalidate all sessions.", AdminModule.class); - return UserSession.invalidateAllSessions(); + return CoreSpringFactory.getImpl(UserSessionManager.class).invalidateAllSessions(); } /** @@ -182,19 +183,20 @@ public class AdminModule extends AbstractOLATModule { * @param nbrSessions * @return Number of invalidated sessions */ - public static int invalidateOldestSessions(int nbrSessions) { + public static int invalidateOldestSessionsDepr(int nbrSessions) { Tracing.logAudit("Session administration: Invalidate oldest sessions Nbr-Sessions=" + nbrSessions, AdminModule.class); - return UserSession.invalidateOldestSessions(nbrSessions); + return CoreSpringFactory.getImpl(UserSessionManager.class).invalidateOldestSessions(nbrSessions); } /** * Set global session timeout in msec. * @param sessionTimeout */ - public static void setSessionTimeout(int sessionTimeout) { + public static void setSessionTimeoutDepr(int sessionTimeout) { Tracing.logAudit("Session administration: Set session-timeout=" + sessionTimeout, AdminModule.class); //in seconds - UserSession.setGlobalSessionTimeout(sessionTimeout); + + CoreSpringFactory.getImpl(UserSessionManager.class).setGlobalSessionTimeout(sessionTimeout); //in milliseconds for presence job ChangePresenceJob.setAutoLogOutCutTimeValue(sessionTimeout*1000); } diff --git a/src/main/java/org/olat/admin/AdminModuleDispatcher.java b/src/main/java/org/olat/admin/AdminModuleDispatcher.java index b2ba812bc97..d4e226e1e1e 100644 --- a/src/main/java/org/olat/admin/AdminModuleDispatcher.java +++ b/src/main/java/org/olat/admin/AdminModuleDispatcher.java @@ -33,6 +33,7 @@ import org.olat.core.CoreSpringFactory; import org.olat.core.dispatcher.Dispatcher; import org.olat.core.dispatcher.DispatcherAction; import org.olat.core.gui.media.ServletUtil; +import org.olat.core.util.session.UserSessionManager; /** * @@ -92,7 +93,7 @@ public class AdminModuleDispatcher implements Dispatcher { }else if (cmd.equalsIgnoreCase(CMD_SET_MAX_SESSIONS)) { handleSetMaxSessions(request, response); }else if (cmd.equalsIgnoreCase(CMD_INVALIDATE_ALL_SESSIONS)) { - AdminModule.invalidateAllSessions(); + CoreSpringFactory.getImpl(UserSessionManager.class).invalidateAllSessions(); ServletUtil.serveStringResource(request, response, "Ok, Invalidated all sessions"); }else if (cmd.equalsIgnoreCase(CMD_INVALIDATE_OLDEST_SESSIONS)) { handleInvidateOldestSessions(request, response); @@ -130,7 +131,7 @@ public class AdminModuleDispatcher implements Dispatcher { } else { try { int sessionTimeout = Integer.parseInt(paramStr); - AdminModule.setSessionTimeout(sessionTimeout); + CoreSpringFactory.getImpl(UserSessionManager.class).setGlobalSessionTimeout(sessionTimeout); ServletUtil.serveStringResource(request, response, "Ok, sessiontimeout=" + sessionTimeout); } catch (NumberFormatException nbrException) { ServletUtil.serveStringResource(request, response, "NOT_OK, parameter " + PARAMETER_SESSIONTIMEOUT + " must be a number"); @@ -151,7 +152,7 @@ public class AdminModuleDispatcher implements Dispatcher { } else { try { int nbrSessions = Integer.parseInt(nbrSessionsString); - AdminModule.invalidateOldestSessions(nbrSessions); + CoreSpringFactory.getImpl(UserSessionManager.class).invalidateOldestSessions(nbrSessions); ServletUtil.serveStringResource(request, response, "Ok, Invalidated oldest sessions, nbrSessions=" + nbrSessions); } catch (NumberFormatException nbrException) { ServletUtil.serveStringResource(request, response, "NOT_OK, parameter " + PARAMETER_NBR_SESSIONS + " must be a number"); diff --git a/src/main/java/org/olat/admin/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/admin/_i18n/LocalStrings_de.properties index 7426cb15518..c204660df94 100644 --- a/src/main/java/org/olat/admin/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/admin/_i18n/LocalStrings_de.properties @@ -72,6 +72,10 @@ menu.statistics=Statistiken menu.statistics.alt=Logfile Statistiken menu.sysinfo=System Informationen menu.sysinfo.alt=System Informationen +menu.system=System +menu.system.alt=System +menu.session=Benutzersessions +menu.session.alt=Benutzersessions menu.ucreate=Benutzer erstellen menu.ucreate.alt=Benutzer erstellen menu.umgmt=Benutzerverwaltung diff --git a/src/main/java/org/olat/admin/jmx/datasources/ThreadAndControllerInfo.java b/src/main/java/org/olat/admin/jmx/datasources/ThreadAndControllerInfo.java index 9a1b9f5c5a5..1d9f6e12bcc 100644 --- a/src/main/java/org/olat/admin/jmx/datasources/ThreadAndControllerInfo.java +++ b/src/main/java/org/olat/admin/jmx/datasources/ThreadAndControllerInfo.java @@ -27,9 +27,10 @@ package org.olat.admin.jmx.datasources; import java.lang.management.ManagementFactory; import java.lang.management.MemoryMXBean; +import org.olat.core.CoreSpringFactory; import org.olat.core.dispatcher.DispatcherAction; import org.olat.core.gui.control.DefaultController; -import org.olat.core.util.UserSession; +import org.olat.core.util.session.UserSessionManager; /** * Description:<br> @@ -51,7 +52,7 @@ public class ThreadAndControllerInfo { } public int getAuthenticatedNodeUsersCount() { - return UserSession.getAuthenticatedUserSessions().size(); + return CoreSpringFactory.getImpl(UserSessionManager.class).getNumberOfAuthenticatedUserSessions(); } public long getMemoryHeapUsageKB() { diff --git a/src/main/java/org/olat/admin/sysinfo/MRTGStatsDispatcher.java b/src/main/java/org/olat/admin/sysinfo/MRTGStatsDispatcher.java index b9068897ab2..446dd67bf4d 100644 --- a/src/main/java/org/olat/admin/sysinfo/MRTGStatsDispatcher.java +++ b/src/main/java/org/olat/admin/sysinfo/MRTGStatsDispatcher.java @@ -35,8 +35,8 @@ import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; -import java.util.Set; import java.util.Map.Entry; +import java.util.Set; import java.util.logging.Level; import javax.servlet.http.HttpServletRequest; @@ -48,6 +48,7 @@ import org.olat.basesecurity.Constants; import org.olat.basesecurity.SecurityGroup; import org.olat.commons.coordinate.cluster.jms.ClusterEventBus; import org.olat.commons.coordinate.cluster.jms.SimpleProbe; +import org.olat.core.CoreSpringFactory; import org.olat.core.commons.persistence.DBQueryImpl; import org.olat.core.dispatcher.Dispatcher; import org.olat.core.dispatcher.DispatcherAction; @@ -58,6 +59,7 @@ import org.olat.core.logging.Tracing; import org.olat.core.util.SessionInfo; import org.olat.core.util.UserSession; import org.olat.core.util.coordinate.CoordinatorManager; +import org.olat.core.util.session.UserSessionManager; import org.olat.course.CourseModule; import org.olat.instantMessaging.InstantMessagingModule; import org.olat.repository.RepositoryEntry; @@ -169,7 +171,8 @@ public class MRTGStatsDispatcher implements Dispatcher { int httpsCount = 0; int activeSessionCnt = 0; if (command.equals("users")) { // get user stats of (authenticated) usersessions - Set<UserSession> userSessions = UserSession.getAuthenticatedUserSessions(); + UserSessionManager sessionManager = CoreSpringFactory.getImpl(UserSessionManager.class); + Set<UserSession> userSessions = sessionManager.getAuthenticatedUserSessions(); for (Iterator<UserSession> it_usess = userSessions.iterator(); it_usess.hasNext();) { UserSession usess = (UserSession) it_usess.next(); activeSessionCnt++; @@ -182,7 +185,8 @@ public class MRTGStatsDispatcher implements Dispatcher { result.append("\n0\n"); result.append(instanceId); } else if (command.equals("webdav")) { // get webdav stats of (authenticated) usersessions - Set<UserSession> userSessions = UserSession.getAuthenticatedUserSessions(); + UserSessionManager sessionManager = CoreSpringFactory.getImpl(UserSessionManager.class); + Set<UserSession> userSessions = sessionManager.getAuthenticatedUserSessions(); int webdavcount = 0; int securewebdavcount = 0; for (Iterator<UserSession> it_usess = userSessions.iterator(); it_usess.hasNext();) { diff --git a/src/main/java/org/olat/admin/sysinfo/SessionAdminForm.java b/src/main/java/org/olat/admin/sysinfo/SessionAdminForm.java deleted file mode 100644 index 903530526e6..00000000000 --- a/src/main/java/org/olat/admin/sysinfo/SessionAdminForm.java +++ /dev/null @@ -1,92 +0,0 @@ -/** -* OLAT - Online Learning and Training<br> -* http://www.olat.org -* <p> -* Licensed under the Apache License, Version 2.0 (the "License"); <br> -* you may not use this file except in compliance with the License.<br> -* You may obtain a copy of the License at -* <p> -* http://www.apache.org/licenses/LICENSE-2.0 -* <p> -* Unless required by applicable law or agreed to in writing,<br> -* software distributed under the License is distributed on an "AS IS" BASIS, <br> -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> -* See the License for the specific language governing permissions and <br> -* limitations under the License. -* <p> -* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br> -* University of Zurich, Switzerland. -* <hr> -* <a href="http://www.openolat.org"> -* OpenOLAT - Online Learning and Training</a><br> -* This file has been modified by the OpenOLAT community. Changes are licensed -* under the Apache 2.0 license as the original file. -*/ - -package org.olat.admin.sysinfo; - -import org.olat.core.gui.UserRequest; -import org.olat.core.gui.components.form.flexible.FormItemContainer; -import org.olat.core.gui.components.form.flexible.elements.IntegerElement; -import org.olat.core.gui.components.form.flexible.elements.Submit; -import org.olat.core.gui.components.form.flexible.impl.FormBasicController; -import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer; -import org.olat.core.gui.components.form.flexible.impl.elements.FormSubmit; -import org.olat.core.gui.control.Controller; -import org.olat.core.gui.control.Event; -import org.olat.core.gui.control.WindowControl; -import org.olat.core.gui.translator.Translator; - -public class SessionAdminForm extends FormBasicController { - private IntegerElement sessionTimeout; - private IntegerElement maxSessions; - private int initialSessionTimeoutInSec; - private int initialMaxSessions; - - public SessionAdminForm(UserRequest ureq, WindowControl wControl, Translator translator, int initialSessionTimeoutInSec, int initialMaxSessions) { - super(ureq, wControl); - setTranslator(translator); - this.initialSessionTimeoutInSec = initialSessionTimeoutInSec; - this.initialMaxSessions = initialMaxSessions; - initForm(ureq); - } - - @Override - protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { - FormLayoutContainer verticalL = FormLayoutContainer.createVerticalFormLayout("verticalL", getTranslator()); - formLayout.add(verticalL); - sessionTimeout = uifactory.addIntegerElement("session.timeout", "session.timeout.label", initialSessionTimeoutInSec, verticalL); - maxSessions = uifactory.addIntegerElement("max.sessions", "max.sessions.label", initialMaxSessions, verticalL); - Submit saveButton = new FormSubmit("save","save"); - formLayout.add(saveButton); - } - - @Override - protected void doDispose() { - //empty - } - - @Override - protected void formOK(UserRequest ureq) { - fireEvent(ureq, Event.DONE_EVENT); - } - - @Override - protected void formResetted(UserRequest ureq) { - fireEvent(ureq, Event.CANCELLED_EVENT); - } - - /** - * sessiontimout in seconds - * @return - */ - public int getSessionTimeout() { - return sessionTimeout.getIntValue(); - } - - public int getMaxSessions() { - return maxSessions.getIntValue(); - } - -} - diff --git a/src/main/java/org/olat/admin/sysinfo/SessionAdminOldestSessionForm.java b/src/main/java/org/olat/admin/sysinfo/SessionAdminOldestSessionForm.java deleted file mode 100644 index 147b3c87be8..00000000000 --- a/src/main/java/org/olat/admin/sysinfo/SessionAdminOldestSessionForm.java +++ /dev/null @@ -1,78 +0,0 @@ -/** -* OLAT - Online Learning and Training<br> -* http://www.olat.org -* <p> -* Licensed under the Apache License, Version 2.0 (the "License"); <br> -* you may not use this file except in compliance with the License.<br> -* You may obtain a copy of the License at -* <p> -* http://www.apache.org/licenses/LICENSE-2.0 -* <p> -* Unless required by applicable law or agreed to in writing,<br> -* software distributed under the License is distributed on an "AS IS" BASIS, <br> -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> -* See the License for the specific language governing permissions and <br> -* limitations under the License. -* <p> -* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br> -* University of Zurich, Switzerland. -* <hr> -* <a href="http://www.openolat.org"> -* OpenOLAT - Online Learning and Training</a><br> -* This file has been modified by the OpenOLAT community. Changes are licensed -* under the Apache 2.0 license as the original file. -*/ - -package org.olat.admin.sysinfo; - -import org.olat.core.gui.UserRequest; -import org.olat.core.gui.components.form.flexible.FormItemContainer; -import org.olat.core.gui.components.form.flexible.elements.IntegerElement; -import org.olat.core.gui.components.form.flexible.elements.Submit; -import org.olat.core.gui.components.form.flexible.impl.FormBasicController; -import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer; -import org.olat.core.gui.components.form.flexible.impl.elements.FormSubmit; -import org.olat.core.gui.control.Controller; -import org.olat.core.gui.control.Event; -import org.olat.core.gui.control.WindowControl; -import org.olat.core.gui.translator.Translator; - -public class SessionAdminOldestSessionForm extends FormBasicController { - private IntegerElement nbrSessions; - - public SessionAdminOldestSessionForm(UserRequest ureq, WindowControl wControl, Translator translator) { - super(ureq, wControl); - setTranslator(translator); - initForm(ureq); - } - - @Override - protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { - FormLayoutContainer verticalL = FormLayoutContainer.createVerticalFormLayout("verticalL", getTranslator()); - formLayout.add(verticalL); - nbrSessions = uifactory.addIntegerElement("nbr.session", "nbr.session.label", 0, verticalL); - Submit oldestSessionButton = new FormSubmit("save","oldest.session.button"); - formLayout.add(oldestSessionButton); - } - - @Override - protected void doDispose() { - //empty - } - - @Override - protected void formOK(UserRequest ureq) { - fireEvent(ureq, Event.DONE_EVENT); - } - - @Override - protected void formResetted(UserRequest ureq) { - fireEvent(ureq, Event.CANCELLED_EVENT); - } - - public int getNbrSessions() { - return nbrSessions.getIntValue(); - } - -} - diff --git a/src/main/java/org/olat/admin/sysinfo/SessionAdministrationController.java b/src/main/java/org/olat/admin/sysinfo/SessionAdministrationController.java deleted file mode 100644 index 216637a2c11..00000000000 --- a/src/main/java/org/olat/admin/sysinfo/SessionAdministrationController.java +++ /dev/null @@ -1,216 +0,0 @@ -/** -* OLAT - Online Learning and Training<br> -* http://www.olat.org -* <p> -* Licensed under the Apache License, Version 2.0 (the "License"); <br> -* you may not use this file except in compliance with the License.<br> -* You may obtain a copy of the License at -* <p> -* http://www.apache.org/licenses/LICENSE-2.0 -* <p> -* Unless required by applicable law or agreed to in writing,<br> -* software distributed under the License is distributed on an "AS IS" BASIS, <br> -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> -* See the License for the specific language governing permissions and <br> -* limitations under the License. -* <p> -* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br> -* University of Zurich, Switzerland. -* <hr> -* <a href="http://www.openolat.org"> -* OpenOLAT - Online Learning and Training</a><br> -* This file has been modified by the OpenOLAT community. Changes are licensed -* under the Apache 2.0 license as the original file. -*/ - -package org.olat.admin.sysinfo; - -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.util.Iterator; -import java.util.Set; - -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.olat.admin.AdminModule; -import org.olat.basesecurity.AuthHelper; -import org.olat.core.gui.UserRequest; -import org.olat.core.gui.Windows; -import org.olat.core.gui.components.Component; -import org.olat.core.gui.components.Window; -import org.olat.core.gui.components.link.Link; -import org.olat.core.gui.components.link.LinkFactory; -import org.olat.core.gui.components.text.TextFactory; -import org.olat.core.gui.components.velocity.VelocityContainer; -import org.olat.core.gui.control.Controller; -import org.olat.core.gui.control.DefaultController; -import org.olat.core.gui.control.Event; -import org.olat.core.gui.control.WindowControl; -import org.olat.core.gui.control.controller.BasicController; -import org.olat.core.gui.control.generic.modal.DialogBoxController; -import org.olat.core.gui.control.generic.modal.DialogBoxUIFactory; -import org.olat.core.id.Identity; -import org.olat.core.logging.OLog; -import org.olat.core.logging.Tracing; -import org.olat.core.util.Formatter; -import org.olat.core.util.UserSession; -import org.olat.core.util.Util; -import org.olat.core.util.WebappHelper; -import org.olat.core.util.coordinate.CoordinatorManager; -import org.olat.properties.Property; -import org.olat.properties.PropertyManager; - -/** - * @author Christian Guretzki - */ - -public class SessionAdministrationController extends BasicController { - - OLog log = Tracing.createLoggerFor(this.getClass()); - private static final String VELOCITY_ROOT = Util.getPackageVelocityRoot(SysinfoController.class); - - private VelocityContainer myContent; - private Link invalidateAllSsssionLink; - private DialogBoxController invalidateAllConfirmController; - private Link blockLoginLink; - private Link allowLoginLink; - private DialogBoxController blockLoginConfirmController; - private Link rejectDMZReuqestsLink; - private Link allowDMZRequestsLink; - private DialogBoxController rejectDMZRequestsConfirmController; - private SessionAdminForm sessionAdminForm; - private SessionAdminOldestSessionForm sessionAdminOldestSessionForm; - - /** - * Controlls user session in admin view. - * - * @param ureq - * @param wControl - */ - public SessionAdministrationController(UserRequest ureq, WindowControl wControl) { - super(ureq, wControl); - - myContent = createVelocityContainer("sessionadministration"); - - invalidateAllSsssionLink = LinkFactory.createButton("session.admin.invalidate.all.link", myContent, this); - myContent.contextPut("loginBlocked", AdminModule.isLoginBlocked()); - blockLoginLink = LinkFactory.createButton("session.admin.block.login.link", myContent, this); - - boolean showRejectLink = CoordinatorManager.getInstance().getCoordinator().isClusterMode(); - myContent.contextPut("showRejectDMZRequestsLink", showRejectLink); - if (showRejectLink) { - myContent.contextPut("rejectingDMZRequests", AuthHelper.isRejectDMZRequests()); - - TextFactory.createTextComponentFromI18nKey("session.admin.reject.dmz.requests.intro", "session.admin.reject.dmz.requests.intro", - getTranslator(), null, true, myContent); - TextFactory.createTextComponentFromI18nKey("session.admin.allow.dmz.requests.intro", "session.admin.allow.dmz.requests.intro", - getTranslator(), null, true, myContent); - rejectDMZReuqestsLink = LinkFactory.createButton("session.admin.reject.dmz.requests.link", myContent, this); - allowDMZRequestsLink = LinkFactory.createButton("session.admin.allow.dmz.requests.link", myContent, this); - } - PropertyManager pm = PropertyManager.getInstance(); - Property p = pm.findProperty(null, null, null, AdminModule.SYSTEM_PROPERTY_CATEGORY, AdminModule.PROPERTY_SESSION_ADMINISTRATION); - String sessionToken = (p == null ? "" : p.getStringValue()); - myContent.contextPut("sessionToken", sessionToken); - allowLoginLink = LinkFactory.createButton("session.admin.allow.login.link", myContent, this); - sessionAdminOldestSessionForm = new SessionAdminOldestSessionForm(ureq, wControl, getTranslator()); - listenTo(sessionAdminOldestSessionForm); - myContent.put("session.admin.oldest.session.form", sessionAdminOldestSessionForm.getInitialComponent()); - sessionAdminForm = new SessionAdminForm(ureq, wControl, getTranslator(), AdminModule.getSessionTimeout(), AdminModule.getMaxSessions() ); - listenTo(sessionAdminForm); - myContent.put("session.admin.form", sessionAdminForm.getInitialComponent()); - myContent.contextPut("usersessions", getUsersSessionAsString(ureq)); - putInitialPanel(myContent); - } - - - /** - * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest, - * org.olat.core.gui.components.Component, org.olat.core.gui.control.Event) - */ - public void event(UserRequest ureq, Component source, Event event) { - if (source == invalidateAllSsssionLink){ - invalidateAllConfirmController = activateYesNoDialog(ureq, null, translate("invalidate.all.sure"), invalidateAllConfirmController); - return; - } else if(source == blockLoginLink) { - blockLoginConfirmController = activateYesNoDialog(ureq, null, translate("block.login.sure"), invalidateAllConfirmController); - } else if(source == rejectDMZReuqestsLink) { - rejectDMZRequestsConfirmController = activateYesNoDialog(ureq, null, translate("reject.dmz.requests.sure"), rejectDMZRequestsConfirmController); - } else if(source == allowDMZRequestsLink) { - AdminModule.setRejectDMZRequests(false); - myContent.contextPut("rejectingDMZRequests", AdminModule.isRejectDMZRequests()); - showInfo("allow.dmz.requests.done"); - } else if(source == allowLoginLink) { - AdminModule.setLoginBlocked(false); - myContent.contextPut("loginBlocked", Boolean.FALSE); - showInfo("allow.login.done"); - } - } - - /** - * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest, - * org.olat.core.gui.control.Controller, org.olat.core.gui.control.Event) - */ - public void event(UserRequest ureq, Controller source, Event event) { - if (source == invalidateAllConfirmController) { - if (DialogBoxUIFactory.isYesEvent(event)) { - int nbrOfInvalidatedSessions = AdminModule.invalidateAllSessions(); - showInfo("invalidate.session.done", Integer.toString(nbrOfInvalidatedSessions)); - } - } else if (source == blockLoginConfirmController) { - if (DialogBoxUIFactory.isYesEvent(event)) { - AdminModule.setLoginBlocked(true); - myContent.contextPut("loginBlocked", Boolean.TRUE); - showInfo("block.login.done"); - } - } else if (source == rejectDMZRequestsConfirmController) { - if (DialogBoxUIFactory.isYesEvent(event)) { - AdminModule.setRejectDMZRequests(true); - myContent.contextPut("rejectingDMZRequests", AuthHelper.isRejectDMZRequests()); - showInfo("reject.dmz.requests.done"); - } - } else if (source == sessionAdminOldestSessionForm) { - int nbrOfInvalidatedSessions = AdminModule.invalidateOldestSessions(sessionAdminOldestSessionForm.getNbrSessions()); - showInfo("invalidate.session.done", Integer.toString(nbrOfInvalidatedSessions)); - } else if (source == sessionAdminForm && event == event.DONE_EVENT) { - AdminModule.setSessionTimeout(sessionAdminForm.getSessionTimeout()); - AdminModule.setMaxSessions(sessionAdminForm.getMaxSessions()); - } - - } - - protected void doDispose() { - // DialogBoxController and TableController get disposed by BasicController - } - - private String getUsersSessionAsString(UserRequest ureq) { - StringBuilder sb = new StringBuilder(); - int ucCnt = UserSession.getUserSessionsCnt(); - Set usesss = UserSession.getAuthenticatedUserSessions(); - int contcnt = DefaultController.getControllerCount(); - sb.append("total usersessions (auth and non auth): "+ucCnt+"<br />auth usersessions: "+usesss.size()+"<br />Total Controllers (active, not disposed) of all users:"+contcnt+"<br /><br />"); - Formatter f = Formatter.getInstance(ureq.getLocale()); - for (Iterator iter = usesss.iterator(); iter.hasNext();) { - UserSession usess = (UserSession) iter.next(); - Identity iden = usess.getIdentity(); - sb.append("authusersession (").append(usess.hashCode()).append(") of "); - if (iden != null) { - sb.append(iden.getName()).append(" ").append(iden.getKey()); - } - else { - sb.append(" - "); - } - sb.append("<br />"); - Windows ws = Windows.getWindows(usess); - for (Iterator iterator = ws.getWindowIterator(); iterator.hasNext(); ) { - Window window = (Window) iterator.next(); - sb.append("- window ").append(window.getDispatchID()).append(" ").append(window.getLatestDispatchComponentInfo()).append("<br />"); - } - sb.append("<br />"); - } - return sb.toString(); - } - -} \ No newline at end of file diff --git a/src/main/java/org/olat/admin/sysinfo/SysinfoController.java b/src/main/java/org/olat/admin/sysinfo/SysinfoController.java index 60f6118afa8..8025cddb6ac 100644 --- a/src/main/java/org/olat/admin/sysinfo/SysinfoController.java +++ b/src/main/java/org/olat/admin/sysinfo/SysinfoController.java @@ -50,7 +50,6 @@ import org.olat.admin.cache.AllCachesController; import org.olat.basesecurity.BaseSecurity; import org.olat.basesecurity.BaseSecurityManager; import org.olat.basesecurity.Constants; -import org.olat.basesecurity.SecurityGroup; import org.olat.core.CoreSpringFactory; import org.olat.core.commons.chiefcontrollers.BaseChiefController; import org.olat.core.commons.persistence.DBFactory; @@ -107,9 +106,7 @@ public class SysinfoController extends BasicController implements Activateable2 private VelocityContainer mySessions, mySnoop, myErrors, myLoglevels, mySysinfo, myMultiUserEvents,myHibernateInfo; private Panel cachePanel; - private UserSessionController usessC; private LockController lockController; - private SessionAdministrationController sessionAdministrationController; private TabbedPane tabbedPane; private RequestLoglevelController requestLoglevelController; @@ -146,7 +143,6 @@ public class SysinfoController extends BasicController implements Activateable2 OresHelper.lookupType(this.getClass()))) throw new OLATSecurityException("Insufficient permissions to access SysinfoController"); - usessC = new UserSessionController(ureq, getWindowControl()); lockController = new LockController(ureq, getWindowControl()); myErrors = createVelocityContainer("errors"); myLoglevels = createVelocityContainer("loglevels"); @@ -165,7 +161,6 @@ public class SysinfoController extends BasicController implements Activateable2 disableHibernateStatisticsButton = LinkFactory.createButton("disable.hibernate.statistics", myHibernateInfo, this); clearHibernateStatisticsButton = LinkFactory.createButton("clear.hibernate.statistics", myHibernateInfo, this); - sessionAdministrationController = new SessionAdministrationController(ureq, getWindowControl() ); requestLoglevelController = new RequestLoglevelController(ureq, getWindowControl()); myMultiUserEvents = createVelocityContainer("multiuserevents"); @@ -174,7 +169,6 @@ public class SysinfoController extends BasicController implements Activateable2 infoMsgCtrl = InfoMgr.getInfoMessageController(ureq, getWindowControl()); tabbedPane = new TabbedPane("tp", ureq.getLocale()); - tabbedPane.addTab(ACTION_SESSIONS, usessC.getInitialComponent()); tabbedPane.addTab(ACTION_INFOMSG,infoMsgCtrl.getInitialComponent()); tabbedPane.addTab(ACTION_ERRORS, myErrors); //fxdiff: FXOLAT-79 check fxadmin-rights @@ -182,7 +176,6 @@ public class SysinfoController extends BasicController implements Activateable2 tabbedPane.addTab(ACTION_SYSINFO, mySysinfo); tabbedPane.addTab(ACTION_SNOOP, mySnoop); tabbedPane.addTab("requestloglevel", requestLoglevelController.getInitialComponent()); - tabbedPane.addTab("usersessions", sessionAdministrationController.getInitialComponent()); tabbedPane.addTab(ACTION_LOCKS, lockController.getInitialComponent()); // fxdiff: not usable: tabbedPane.addTab(getTranslator().translate("sess.multiuserevents"), myMultiUserEvents); tabbedPane.addTab(ACTION_HIBERNATEINFO, myHibernateInfo); @@ -344,9 +337,6 @@ public class SysinfoController extends BasicController implements Activateable2 mySysinfo.contextPut("threads",getThreadsInfo()); mySysinfo.contextPut("javaenv", getJavaenv()); - } - else if (newComponent == usessC.getInitialComponent()) { - usessC.reset(); } else if (newComponent == lockController.getInitialComponent()) { lockController.resetTableModel(); @@ -379,8 +369,6 @@ public class SysinfoController extends BasicController implements Activateable2 */ sb.append(" <a href=\"http://bugs.olat.org/jira/browse/OLAT-3681\">OLAT-3681</a> "); myMultiUserEvents.contextPut("info", sb.toString()); - } - else if (newComponent == sessionAdministrationController.getInitialComponent()) { } else if (newComponent == myHibernateInfo) { myHibernateInfo.contextPut("isStatisticsEnabled", DBFactory.getInstance(false).getStatistics().isStatisticsEnabled()); @@ -631,10 +619,6 @@ public class SysinfoController extends BasicController implements Activateable2 * @see org.olat.core.gui.control.DefaultController#doDispose(boolean) */ protected void doDispose() { - if (usessC != null) { - usessC.dispose(); - usessC = null; - } if (cacheController != null) { cacheController.dispose(); cacheController = null; diff --git a/src/main/java/org/olat/admin/sysinfo/UserSessionAdminController.java b/src/main/java/org/olat/admin/sysinfo/UserSessionAdminController.java new file mode 100644 index 00000000000..5089de3298b --- /dev/null +++ b/src/main/java/org/olat/admin/sysinfo/UserSessionAdminController.java @@ -0,0 +1,110 @@ +package org.olat.admin.sysinfo; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.Component; +import org.olat.core.gui.components.link.Link; +import org.olat.core.gui.components.link.LinkFactory; +import org.olat.core.gui.components.segmentedview.SegmentViewComponent; +import org.olat.core.gui.components.segmentedview.SegmentViewEvent; +import org.olat.core.gui.components.segmentedview.SegmentViewFactory; +import org.olat.core.gui.components.stack.StackedController; +import org.olat.core.gui.components.stack.StackedControllerAware; +import org.olat.core.gui.components.velocity.VelocityContainer; +import org.olat.core.gui.control.Event; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.gui.control.controller.BasicController; + +/** + * + * Initial date: 15.11.2012<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class UserSessionAdminController extends BasicController implements StackedControllerAware { + + private final Link sessionsLink, configLink, infosLink; + private final SegmentViewComponent segmentView; + + private final VelocityContainer mainVC; + + private UserSessionController sessionListCtrl; + private UserSessionConfigAdminController configCtrl; + private UserSessionInformationsController infoCtrl; + private StackedController stackedController; + + public UserSessionAdminController(UserRequest ureq, WindowControl wControl) { + super(ureq, wControl); + + mainVC = createVelocityContainer("usersession_admin"); + + segmentView = SegmentViewFactory.createSegmentView("segments", mainVC, this); + sessionsLink = LinkFactory.createLink("session.list", mainVC, this); + segmentView.addSegment(sessionsLink, true); + + configLink = LinkFactory.createLink("session.configuration", mainVC, this); + segmentView.addSegment(configLink, false); + + infosLink = LinkFactory.createLink("sess.details", mainVC, this); + segmentView.addSegment(infosLink, false); + + mainVC.put("segments", segmentView); + doOpenSessionList(ureq); + putInitialPanel(mainVC); + } + + @Override + public void setStackedController(StackedController stackPanel) { + this.stackedController = stackPanel; + if(sessionListCtrl != null) { + sessionListCtrl.setStackedController(stackedController); + } + } + + @Override + protected void doDispose() { + this.stackedController = null; + } + + @Override + protected void event(UserRequest ureq, Component source, Event event) { + if(source == segmentView) { + if(event instanceof SegmentViewEvent) { + SegmentViewEvent sve = (SegmentViewEvent)event; + String segmentCName = sve.getComponentName(); + Component clickedLink = mainVC.getComponent(segmentCName); + if (clickedLink == sessionsLink) { + doOpenSessionList(ureq); + } else if (clickedLink == configLink) { + doOpenConfiguration(ureq); + } else if (clickedLink == infosLink) { + doOpenInformations(ureq); + } + } + } + } + + private void doOpenSessionList(UserRequest ureq) { + if(sessionListCtrl == null) { + sessionListCtrl = new UserSessionController(ureq, getWindowControl()); + sessionListCtrl.setStackedController(stackedController); + listenTo(sessionListCtrl); + } + mainVC.put("segmentCmp", sessionListCtrl.getInitialComponent()); + } + + private void doOpenConfiguration(UserRequest ureq) { + if(configCtrl == null) { + configCtrl = new UserSessionConfigAdminController(ureq, getWindowControl()); + listenTo(configCtrl); + } + mainVC.put("segmentCmp", configCtrl.getInitialComponent()); + } + + private void doOpenInformations(UserRequest ureq) { + if(infoCtrl == null) { + infoCtrl = new UserSessionInformationsController(ureq, getWindowControl()); + listenTo(infoCtrl); + } + mainVC.put("segmentCmp", infoCtrl.getInitialComponent()); + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/admin/sysinfo/UserSessionConfigAdminController.java b/src/main/java/org/olat/admin/sysinfo/UserSessionConfigAdminController.java new file mode 100644 index 00000000000..a3a090a1ede --- /dev/null +++ b/src/main/java/org/olat/admin/sysinfo/UserSessionConfigAdminController.java @@ -0,0 +1,192 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br> +* University of Zurich, Switzerland. +* <hr> +* <a href="http://www.openolat.org"> +* OpenOLAT - Online Learning and Training</a><br> +* This file has been modified by the OpenOLAT community. Changes are licensed +* under the Apache 2.0 license as the original file. +*/ + +package org.olat.admin.sysinfo; + +import org.olat.admin.AdminModule; +import org.olat.basesecurity.AuthHelper; +import org.olat.core.CoreSpringFactory; +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.form.flexible.FormItem; +import org.olat.core.gui.components.form.flexible.FormItemContainer; +import org.olat.core.gui.components.form.flexible.elements.FormLink; +import org.olat.core.gui.components.form.flexible.elements.IntegerElement; +import org.olat.core.gui.components.form.flexible.impl.FormBasicController; +import org.olat.core.gui.components.form.flexible.impl.FormEvent; +import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer; +import org.olat.core.gui.components.link.Link; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.Event; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.gui.control.generic.modal.DialogBoxController; +import org.olat.core.gui.control.generic.modal.DialogBoxUIFactory; +import org.olat.core.util.coordinate.CoordinatorManager; +import org.olat.core.util.session.UserSessionManager; +import org.olat.core.util.session.UserSessionModule; + +/** + * + * Initial date: 15.11.2012<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class UserSessionConfigAdminController extends FormBasicController { + private IntegerElement sessionTimeoutEl; + private IntegerElement sessionTimeoutAuthEl; + private IntegerElement maxSessionsEl; + private IntegerElement nbrSessionsEl; + + private DialogBoxController invalidateAllConfirmController; + private DialogBoxController blockLoginConfirmController; + private DialogBoxController rejectDMZRequestsConfirmController; + + private FormLink saveLink, invalidateOldSessionLink, invalidateAllSessionLink; + private FormLink allowLoginLink, blockLoginLink; + private FormLink rejectDMZRequestsLink, allowDMZRequestsLink; + + private final UserSessionModule sessionModule; + private final UserSessionManager sessionManager; + + public UserSessionConfigAdminController(UserRequest ureq, WindowControl wControl) { + super(ureq, wControl); + + sessionModule = CoreSpringFactory.getImpl(UserSessionModule.class); + sessionManager = CoreSpringFactory.getImpl(UserSessionManager.class); + + initForm(ureq); + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + int sessionTimeout = sessionModule.getSessionTimeout(); + sessionTimeoutEl = uifactory.addIntegerElement("session.timeout", "session.timeout.label", sessionTimeout, formLayout); + int initialSessionAuth = sessionModule.getSessionTimeoutAuthenticated(); + sessionTimeoutAuthEl = uifactory.addIntegerElement("session.timeout.auth", "session.timeout.auth.label", initialSessionAuth, formLayout); + int maxSessions = AdminModule.getMaxSessions(); + maxSessionsEl = uifactory.addIntegerElement("max.sessions", "max.sessions.label", maxSessions, formLayout); + + FormLayoutContainer buttonsLayout = FormLayoutContainer.createButtonLayout("buttons", getTranslator()); + formLayout.add(buttonsLayout); + saveLink = uifactory.addFormLink("save", "save", null, buttonsLayout, Link.BUTTON); + + uifactory.addSpacerElement("spacer-1", formLayout, false); + + nbrSessionsEl = uifactory.addIntegerElement("nbr.session", "nbr.session.label", 0, formLayout); + FormLayoutContainer buttonsLayout2 = FormLayoutContainer.createButtonLayout("buttons2", getTranslator()); + formLayout.add(buttonsLayout2); + invalidateOldSessionLink = uifactory.addFormLink("kill.old", "oldest.session.button", null, buttonsLayout2, Link.BUTTON); + invalidateAllSessionLink = uifactory.addFormLink("kill.all", "session.admin.invalidate.all.link", null, buttonsLayout2, Link.BUTTON); + + uifactory.addSpacerElement("spacer-2", formLayout, false); + + FormLayoutContainer buttonsLayout3 = FormLayoutContainer.createButtonLayout("buttons3", getTranslator()); + formLayout.add(buttonsLayout3); + blockLoginLink = uifactory.addFormLink("block.login.all", "session.admin.block.login.link", null, buttonsLayout3, Link.BUTTON); + allowLoginLink = uifactory.addFormLink("allow.login.all", "session.admin.allow.login.link", null, buttonsLayout3, Link.BUTTON); + updateLoginBlock(); + + @SuppressWarnings("deprecation") + boolean clusterMode = CoordinatorManager.getInstance().getCoordinator().isClusterMode(); + if (clusterMode) { + rejectDMZRequestsLink = uifactory.addFormLink("block.dmz.node", "session.admin.reject.dmz.requests.link", null, buttonsLayout3, Link.BUTTON); + allowDMZRequestsLink = uifactory.addFormLink("allow.dmz.node", "session.admin.allow.dmz.requests.link", null, buttonsLayout3, Link.BUTTON); + updateDmzBlock(); + } + } + + private void updateDmzBlock() { + rejectDMZRequestsLink.setVisible(!AuthHelper.isRejectDMZRequests()); + allowDMZRequestsLink.setVisible(AuthHelper.isRejectDMZRequests()); + } + + private void updateLoginBlock() { + blockLoginLink.setVisible(!AdminModule.isLoginBlocked()); + allowLoginLink.setVisible(AdminModule.isLoginBlocked()); + } + + @Override + protected void doDispose() { + //empty + } + + @Override + protected void formOK(UserRequest ureq) { + // + } + + @Override + protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { + if(source == saveLink) { + int sessionTimeout = sessionTimeoutEl.getIntValue(); + sessionModule.setSessionTimeout(sessionTimeout); + int sessionTimeoutAuth = sessionTimeoutAuthEl.getIntValue(); + sessionModule.setSessionTimeoutAuthenticated(sessionTimeoutAuth); + int maxSessions = maxSessionsEl.getIntValue(); + AdminModule.setMaxSessions(maxSessions); + sessionManager.setGlobalSessionTimeout(sessionTimeoutAuth); + } else if(source == invalidateOldSessionLink) { + int nbrSessions = nbrSessionsEl.getIntValue(); + int nbrOfInvalidatedSessions = sessionManager.invalidateOldestSessions(nbrSessions); + showInfo("invalidate.session.done", Integer.toString(nbrOfInvalidatedSessions)); + } else if(source == invalidateAllSessionLink) { + invalidateAllConfirmController = activateYesNoDialog(ureq, null, translate("invalidate.all.sure"), invalidateAllConfirmController); + } else if(source == blockLoginLink) { + blockLoginConfirmController = activateYesNoDialog(ureq, null, translate("block.login.sure"), blockLoginConfirmController); + } else if(source == allowLoginLink) { + AdminModule.setLoginBlocked(false); + updateLoginBlock(); + } else if(source == rejectDMZRequestsLink) { + rejectDMZRequestsConfirmController = activateYesNoDialog(ureq, null, translate("reject.dmz.requests.sure"), rejectDMZRequestsConfirmController); + } else if(source == allowDMZRequestsLink) { + AdminModule.setRejectDMZRequests(false); + updateDmzBlock(); + showInfo("allow.dmz.requests.done"); + } else { + super.formInnerEvent(ureq, source, event); + } + } + + @Override + public void event(UserRequest ureq, Controller source, Event event) { + if (source == invalidateAllConfirmController) { + if (DialogBoxUIFactory.isYesEvent(event)) { + int nbrOfInvalidatedSessions = sessionManager.invalidateAllSessions(); + showInfo("invalidate.session.done", Integer.toString(nbrOfInvalidatedSessions)); + } + } else if (source == blockLoginConfirmController) { + if (DialogBoxUIFactory.isYesEvent(event)) { + AdminModule.setLoginBlocked(true); + showInfo("block.login.done"); + } + updateLoginBlock(); + } else if (source == rejectDMZRequestsConfirmController) { + if (DialogBoxUIFactory.isYesEvent(event)) { + AdminModule.setRejectDMZRequests(true); + showInfo("reject.dmz.requests.done"); + } + updateDmzBlock(); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/admin/sysinfo/UserSessionController.java b/src/main/java/org/olat/admin/sysinfo/UserSessionController.java index a7f3be29e92..631c44e53c3 100644 --- a/src/main/java/org/olat/admin/sysinfo/UserSessionController.java +++ b/src/main/java/org/olat/admin/sysinfo/UserSessionController.java @@ -26,19 +26,16 @@ package org.olat.admin.sysinfo; import java.util.ArrayList; -import java.util.Date; -import java.util.Iterator; import java.util.List; -import javax.servlet.http.HttpSession; - +import org.olat.core.CoreSpringFactory; import org.olat.core.gui.UserRequest; -import org.olat.core.gui.Windows; import org.olat.core.gui.components.Component; -import org.olat.core.gui.components.Window; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.components.link.LinkFactory; import org.olat.core.gui.components.panel.Panel; +import org.olat.core.gui.components.stack.StackedController; +import org.olat.core.gui.components.stack.StackedControllerAware; import org.olat.core.gui.components.table.DefaultColumnDescriptor; import org.olat.core.gui.components.table.StaticColumnDescriptor; import org.olat.core.gui.components.table.Table; @@ -52,29 +49,29 @@ import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.controller.BasicController; import org.olat.core.gui.control.generic.modal.DialogBoxController; import org.olat.core.gui.control.generic.modal.DialogBoxUIFactory; -import org.olat.core.util.Formatter; -import org.olat.core.util.SessionInfo; import org.olat.core.util.UserSession; -import org.olat.core.util.coordinate.CoordinatorManager; -import org.olat.core.util.coordinate.LockEntry; +import org.olat.core.util.session.UserSessionManager; +import org.olat.user.UserManager; /** * Initial Date: 01.09.2004 * @author Mike Stock */ -public class UserSessionController extends BasicController { +public class UserSessionController extends BasicController implements StackedControllerAware { private VelocityContainer myContent; private TableController tableCtr; - private Formatter f; + //private Formatter f; private UserSessionTableModel usessTableModel; private DialogBoxController dialogController; - private int selRow; - private Link backLink; - private Link sessKillButton; + //private int selRow; + private Link backLink, sessKillButton; private Panel myPanel; + private final UserSessionManager sessionManager; + private StackedController stackController; + /** * Timeframe in minutes is needed to calculate the last klicks from users in OLAT. */ @@ -88,8 +85,10 @@ public class UserSessionController extends BasicController { */ public UserSessionController(UserRequest ureq, WindowControl wControl) { super(ureq, wControl); + + sessionManager = CoreSpringFactory.getImpl(UserSessionManager.class); - f = Formatter.getInstance(ureq.getLocale()); + //f = Formatter.getInstance(ureq.getLocale()); myContent = createVelocityContainer("sessions"); @@ -113,19 +112,23 @@ public class UserSessionController extends BasicController { myPanel = putInitialPanel(myContent); } + @Override + public void setStackedController(StackedController stackPanel) { + this.stackController = stackPanel; + } + /** * Re-initialize this controller. Fetches sessions again. */ public void reset() { - List<UserSession> authUserSessions = new ArrayList<UserSession>(UserSession.getAuthenticatedUserSessions()); - usessTableModel = new UserSessionTableModel(authUserSessions, getTranslator()); + List<UserSession> authUserSessions = new ArrayList<UserSession>(sessionManager.getAuthenticatedUserSessions()); + usessTableModel = new UserSessionTableModel(authUserSessions); tableCtr.setTableDataModel(usessTableModel); // view number of user - lastKlick <= LAST_KLICK_TIMEFRAME min long now = System.currentTimeMillis(); int counter = 0; for (UserSession usess : authUserSessions) { - - long lastklick = usess.getSessionInfo().getLastClickTime(); + long lastklick = usess.getSessionInfo() == null ? -1 : usess.getSessionInfo().getLastClickTime(); if ((now - lastklick) <= DIFF) { counter++; } @@ -142,10 +145,8 @@ public class UserSessionController extends BasicController { if (source == backLink){ myPanel.popContent(); reset(); - } - else if (source == sessKillButton){ + } else if (source == sessKillButton){ dialogController = activateYesNoDialog(ureq, null, translate("sess.kill.sure"), dialogController); - return; } } @@ -156,7 +157,7 @@ public class UserSessionController extends BasicController { public void event(UserRequest ureq, Controller source, Event event) { if (source == dialogController) { if (DialogBoxUIFactory.isYesEvent(event)) { - UserSession usess = (UserSession) usessTableModel.getObject(selRow); + /*UserSession usess = (UserSession) usessTableModel.getObject(selRow); SessionInfo sessInfo = usess.getSessionInfo(); if (usess.isAuthenticated()) { HttpSession session = sessInfo.getSession(); @@ -168,19 +169,35 @@ public class UserSessionController extends BasicController { } } showInfo("sess.kill.done", sessInfo.getLogin() ); - } + }*/ reset(); } } else if (source == tableCtr) { if (event.getCommand().equals(Table.COMMANDLINK_ROWACTION_CLICKED)) { - TableEvent te = (TableEvent) event; - selRow = te.getRowId(); + TableEvent te = (TableEvent)event; + int selRow = te.getRowId(); // session info (we only have authenticated sessions here - UserSession usess = (UserSession) usessTableModel.getObject(selRow); + UserSession usess = (UserSession) tableCtr.getTableDataModel().getObject(selRow); + UserSessionDetailsController detailsCtrl = new UserSessionDetailsController(ureq, getWindowControl(), usess); + listenTo(detailsCtrl); + + String username = usess.getIdentity() == null ? "-" + : UserManager.getInstance().getUserDisplayName(usess.getIdentity().getUser()); + stackController.pushController(username, detailsCtrl); + + //if (!usess.isAuthenticated()) throw new AssertException("usersession was not authenticated!?"); - VelocityContainer sesDetails = createVelocityContainer("sessionDetails"); + + + + + + + + + /*VelocityContainer sesDetails = createVelocityContainer("sessionDetails"); sesDetails.contextPut("us", usess); SessionInfo sessInfo = usess.getSessionInfo(); sesDetails.contextPut("si", sessInfo); @@ -213,7 +230,7 @@ public class UserSessionController extends BasicController { if (success) { // lock information String username = sessInfo.getLogin(); - ArrayList lockList = new ArrayList(); + List<String> lockList = new ArrayList<String>(); List<LockEntry> locks = CoordinatorManager.getInstance().getCoordinator().getLocker().adminOnlyGetLockEntries(); Formatter f = Formatter.getInstance(ureq.getLocale()); for (LockEntry entry : locks) { @@ -229,8 +246,8 @@ public class UserSessionController extends BasicController { // GUI statistics Windows ws = Windows.getWindows(usess); StringBuilder sb = new StringBuilder(); - for (Iterator iterator = ws.getWindowIterator(); iterator.hasNext();) { - Window window = (Window) iterator.next(); + for (Iterator<Window> iterator = ws.getWindowIterator(); iterator.hasNext();) { + Window window = iterator.next(); sb.append("- Window ").append(window.getDispatchID()).append(" dispatch info: ").append(window.getLatestDispatchComponentInfo()).append("<br />"); } sb.append("<br />"); @@ -240,6 +257,7 @@ public class UserSessionController extends BasicController { sesDetails.put("sess.kill", sessKillButton); myPanel.pushContent(sesDetails); + */ } } } diff --git a/src/main/java/org/olat/admin/sysinfo/UserSessionDetailsController.java b/src/main/java/org/olat/admin/sysinfo/UserSessionDetailsController.java new file mode 100644 index 00000000000..90f45aab901 --- /dev/null +++ b/src/main/java/org/olat/admin/sysinfo/UserSessionDetailsController.java @@ -0,0 +1,114 @@ +package org.olat.admin.sysinfo; + +import java.util.ArrayList; +import java.util.Date; +import java.util.Iterator; +import java.util.List; + +import javax.servlet.http.HttpSession; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.Windows; +import org.olat.core.gui.components.Component; +import org.olat.core.gui.components.Window; +import org.olat.core.gui.components.velocity.VelocityContainer; +import org.olat.core.gui.control.Event; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.gui.control.controller.BasicController; +import org.olat.core.util.Formatter; +import org.olat.core.util.SessionInfo; +import org.olat.core.util.UserSession; +import org.olat.core.util.coordinate.CoordinatorManager; +import org.olat.core.util.coordinate.LockEntry; + +/** + * + * Initial date: 15.11.2012<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class UserSessionDetailsController extends BasicController { + + private final VelocityContainer sesDetails; + + public UserSessionDetailsController(UserRequest ureq, WindowControl wControl, UserSession usess) { + super(ureq, wControl); + + sesDetails = createVelocityContainer("sessionDetails"); + sesDetails.contextPut("us", usess); + SessionInfo sessInfo = usess.getSessionInfo(); + sesDetails.contextPut("si", sessInfo); + boolean isAuth = usess.isAuthenticated(); + sesDetails.contextPut("isauth", isAuth? "yes" : "-- NOT AUTHENTICATED!"); + + long creatTime = -1; + long lastAccessTime = -1; + + boolean success = false; + if (isAuth) { + try { + HttpSession se = sessInfo.getSession(); + creatTime = se.getCreationTime(); + lastAccessTime = se.getLastAccessedTime(); + success = true; + } catch (Exception ise) { + // nothing to do + } + } + + if (success) { + Formatter f = Formatter.getInstance(ureq.getLocale()); + sesDetails.contextPut("created", f.formatDateAndTime(new Date(creatTime))); + sesDetails.contextPut("lastaccess", f.formatDateAndTime(new Date(lastAccessTime))); + } else { + sesDetails.contextPut("created", " -- this session has been invalidated --"); + sesDetails.contextPut("lastaccess", " -- this session has been invalidated --"); + } + + if (success) { + // lock information + String username = sessInfo.getLogin(); + List<String> lockList = new ArrayList<String>(); + List<LockEntry> locks = CoordinatorManager.getInstance().getCoordinator().getLocker().adminOnlyGetLockEntries(); + Formatter f = Formatter.getInstance(ureq.getLocale()); + for (LockEntry entry : locks) { + if (entry.getOwner().getName().equals(username)) { + lockList.add(entry.getKey()+" "+f.formatDateAndTime(new Date(entry.getLockAquiredTime()))); + } + } + sesDetails.contextPut("locklist", lockList); + + // user environment + sesDetails.contextPut("env", usess.getIdentityEnvironment()); + + // GUI statistics + Windows ws = Windows.getWindows(usess); + StringBuilder sb = new StringBuilder(); + for (Iterator<Window> iterator = ws.getWindowIterator(); iterator.hasNext();) { + Window window = iterator.next(); + sb.append("- Window ").append(window.getDispatchID()).append(" dispatch info: ").append(window.getLatestDispatchComponentInfo()).append("<br />"); + } + sb.append("<br />"); + sesDetails.contextPut("guistats", sb.toString()); + } + //TODO sesDetails.put("sess.kill", sessKillButton); + + + } + + @Override + protected void doDispose() { + // + } + + @Override + protected void event(UserRequest ureq, Component source, Event event) { + // + } + + + + + + +} diff --git a/src/main/java/org/olat/admin/sysinfo/UserSessionInformationsController.java b/src/main/java/org/olat/admin/sysinfo/UserSessionInformationsController.java new file mode 100644 index 00000000000..d3fccdbb44d --- /dev/null +++ b/src/main/java/org/olat/admin/sysinfo/UserSessionInformationsController.java @@ -0,0 +1,106 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br> +* University of Zurich, Switzerland. +* <hr> +* <a href="http://www.openolat.org"> +* OpenOLAT - Online Learning and Training</a><br> +* This file has been modified by the OpenOLAT community. Changes are licensed +* under the Apache 2.0 license as the original file. +*/ + +package org.olat.admin.sysinfo; + +import java.util.Iterator; +import java.util.Set; + +import org.olat.core.CoreSpringFactory; +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.Windows; +import org.olat.core.gui.components.Component; +import org.olat.core.gui.components.Window; +import org.olat.core.gui.components.velocity.VelocityContainer; +import org.olat.core.gui.control.DefaultController; +import org.olat.core.gui.control.Event; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.gui.control.controller.BasicController; +import org.olat.core.id.Identity; +import org.olat.core.util.UserSession; +import org.olat.core.util.session.UserSessionManager; + +/** + * + * Initial date: 15.11.2012<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class UserSessionInformationsController extends BasicController { + + private final VelocityContainer myContent; + private final UserSessionManager sessionManager; + + /** + * Controlls user session in admin view. + * + * @param ureq + * @param wControl + */ + public UserSessionInformationsController(UserRequest ureq, WindowControl wControl) { + super(ureq, wControl); + sessionManager = CoreSpringFactory.getImpl(UserSessionManager.class); + + myContent = createVelocityContainer("usersession_infos"); + myContent.contextPut("usersessions", getUsersSessionAsString(ureq)); + putInitialPanel(myContent); + } + + public void event(UserRequest ureq, Component source, Event event) { + // + } + + + protected void doDispose() { + // + } + + private String getUsersSessionAsString(UserRequest ureq) { + StringBuilder sb = new StringBuilder(); + int ucCnt = sessionManager.getUserSessionsCnt(); + Set<UserSession> usesss = sessionManager.getAuthenticatedUserSessions(); + int contcnt = DefaultController.getControllerCount(); + sb.append("total usersessions (auth and non auth): "+ucCnt+"<br />auth usersessions: "+usesss.size()+"<br />Total Controllers (active, not disposed) of all users:"+contcnt+"<br /><br />"); + + for (Iterator<UserSession> iter = usesss.iterator(); iter.hasNext();) { + UserSession usess = iter.next(); + Identity iden = usess.getIdentity(); + sb.append("authusersession (").append(usess.hashCode()).append(") of "); + if (iden != null) { + sb.append(iden.getName()).append(" ").append(iden.getKey()); + } else { + sb.append(" - "); + } + sb.append("<br />"); + Windows ws = Windows.getWindows(usess); + for (Iterator<Window> iterator = ws.getWindowIterator(); iterator.hasNext(); ) { + Window window = iterator.next(); + sb.append("- window ").append(window.getDispatchID()).append(" ").append(window.getLatestDispatchComponentInfo()).append("<br />"); + } + sb.append("<br />"); + } + return sb.toString(); + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/admin/sysinfo/UserSessionTableModel.java b/src/main/java/org/olat/admin/sysinfo/UserSessionTableModel.java index 73585f173fe..3558bdcc56c 100644 --- a/src/main/java/org/olat/admin/sysinfo/UserSessionTableModel.java +++ b/src/main/java/org/olat/admin/sysinfo/UserSessionTableModel.java @@ -29,7 +29,6 @@ import java.util.Date; import java.util.List; import org.olat.core.gui.components.table.DefaultTableDataModel; -import org.olat.core.gui.translator.Translator; import org.olat.core.util.SessionInfo; import org.olat.core.util.UserSession; @@ -39,14 +38,13 @@ import org.olat.core.util.UserSession; * @author Mike Stock */ -public class UserSessionTableModel extends DefaultTableDataModel { - private Translator trans; +public class UserSessionTableModel extends DefaultTableDataModel<UserSession> { + /** * @param userSessions */ - public UserSessionTableModel(List userSessions, Translator trans) { + public UserSessionTableModel(List<UserSession> userSessions) { super(userSessions); - this.trans = trans; } /** @@ -91,16 +89,13 @@ public class UserSessionTableModel extends DefaultTableDataModel { } default: return "Error"; } - } - else { // not signed on + } else { // not signed on switch (col) { case 5: return null; case 6: return null; case 7: return null; default: return "-"; } - } - + } } - } diff --git a/src/main/java/org/olat/admin/sysinfo/_content/usersession_admin.html b/src/main/java/org/olat/admin/sysinfo/_content/usersession_admin.html new file mode 100644 index 00000000000..3d776f93825 --- /dev/null +++ b/src/main/java/org/olat/admin/sysinfo/_content/usersession_admin.html @@ -0,0 +1,7 @@ +<div class="b_clearfix"> + $r.render("segments") <br/> + + #if($r.available("segmentCmp")) + $r.render("segmentCmp") + #end +</div> \ No newline at end of file diff --git a/src/main/java/org/olat/admin/sysinfo/_content/usersession_infos.html b/src/main/java/org/olat/admin/sysinfo/_content/usersession_infos.html new file mode 100644 index 00000000000..587532300e2 --- /dev/null +++ b/src/main/java/org/olat/admin/sysinfo/_content/usersession_infos.html @@ -0,0 +1,2 @@ +<h4>$r.translate("usersession.title")</h4> +$usersessions diff --git a/src/main/java/org/olat/admin/sysinfo/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/admin/sysinfo/_i18n/LocalStrings_de.properties index 631cdebe800..e7f875bf9bf 100644 --- a/src/main/java/org/olat/admin/sysinfo/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/admin/sysinfo/_i18n/LocalStrings_de.properties @@ -68,6 +68,8 @@ sess.roles=Rollen sess.secure=Verschl\u00FCsseltes Einloggen sess.title=Aktive Benutzer-Sessions sess.webMode=Web Modus +session.list=Benutzersessions +session.configuration=Konfiguration session.admin.allow.login.link=Loginsperrung aufheben session.admin.block.login.link=Neue Logins sperren session.admin.reject.dmz.requests.intro=Alle Requests auf DMZ auf andere in mod_jk verfügbare Nodes umleiten - ausgenommen Admin Benutzer via Cluster-tab 'Wechseln zu Node' @@ -79,6 +81,7 @@ reject.dmz.requests.done=Alle Requests auf DMZ werden ab jetzt auf andere Nodes allow.dmz.requests.done=Alle Requests auf DMZ werden ab jetzt wieder zugelassen session.admin.invalidate.all.link=Alle Sessions invalidieren session.timeout.label=Session timeout in sec +session.timeout.auth.label=Authenticated session timeout in sec sessionadministration.title=Session Administration sessions=Sessions snoop=Snoop diff --git a/src/main/java/org/olat/basesecurity/AuthHelper.java b/src/main/java/org/olat/basesecurity/AuthHelper.java index 205ae0adb3d..83cf66bcd7f 100644 --- a/src/main/java/org/olat/basesecurity/AuthHelper.java +++ b/src/main/java/org/olat/basesecurity/AuthHelper.java @@ -38,6 +38,7 @@ import javax.servlet.http.Cookie; import javax.servlet.http.HttpSession; import org.olat.commons.rss.RSSUtil; +import org.olat.core.CoreSpringFactory; import org.olat.core.commons.chiefcontrollers.BaseChiefControllerCreator; import org.olat.core.commons.fullWebApp.BaseFullWebappController; import org.olat.core.commons.fullWebApp.BaseFullWebappControllerParts; @@ -71,6 +72,7 @@ import org.olat.core.util.WebappHelper; import org.olat.core.util.i18n.I18nManager; import org.olat.core.util.i18n.I18nModule; import org.olat.core.util.prefs.Preferences; +import org.olat.core.util.session.UserSessionManager; import org.olat.login.AuthBFWCParts; import org.olat.login.GuestBFWCParts; import org.olat.user.UserManager; @@ -306,22 +308,23 @@ public class AuthHelper { log.audit("was denied login"); return LOGIN_DENIED; } + UserSessionManager sessionManager = CoreSpringFactory.getImpl(UserSessionManager.class); // if the user sending the cookie did not log out and we are logging in // again, then we need to make sure everything is cleaned up. we cleanup in all cases. UserSession usess = ureq.getUserSession(); // prepare for a new user: clear all the instance vars of the userSession // note: does not invalidate the session, since it is reused - usess.signOffAndClear(); + sessionManager.signOffAndClear(usess); // init the UserSession for the new User // we can set the identity and finish the log in process usess.setIdentity(identity); setRolesFor(identity, usess); - + // check if loginDenied or maxSession (only for non-admin) if ( (loginBlocked && !usess.getRoles().isOLATAdmin()) - || ( ((maxSessions != MAX_SESSION_NO_LIMIT) && (UserSession.getUserSessionsCnt() >= maxSessions)) && !usess.getRoles().isOLATAdmin() ) ) { - log.audit("Login was blocked for username=" + usess.getIdentity().getName() + ", loginBlocked=" + loginBlocked + " NbrOfSessions=" + UserSession.getUserSessionsCnt()); - usess.signOffAndClear(); + || ( ((maxSessions != MAX_SESSION_NO_LIMIT) && (sessionManager.getUserSessionsCnt() >= maxSessions)) && !usess.getRoles().isOLATAdmin() ) ) { + log.audit("Login was blocked for username=" + usess.getIdentity().getName() + ", loginBlocked=" + loginBlocked + " NbrOfSessions=" + sessionManager.getUserSessionsCnt()); + sessionManager.signOffAndClear(usess); return LOGIN_NOTAVAILABLE; } @@ -337,11 +340,11 @@ public class AuthHelper { // calculate session info and attach it to the user session setSessionInfoFor(identity, authProvider, ureq, rest); //confirm signedOn - usess.signOn(); + sessionManager.signOn(usess); // set users web delivery mode setAjaxModeFor(ureq); // update web delivery mode in session info - ureq.getUserSession().getSessionInfo().setWebModeFromUreq(ureq); + usess.getSessionInfo().setWebModeFromUreq(ureq); return LOGIN_OK; } diff --git a/src/main/java/org/olat/basesecurity/_spring/baseSecurityContext.xml b/src/main/java/org/olat/basesecurity/_spring/baseSecurityContext.xml index 2f4a9dd6cd1..29f9354774e 100644 --- a/src/main/java/org/olat/basesecurity/_spring/baseSecurityContext.xml +++ b/src/main/java/org/olat/basesecurity/_spring/baseSecurityContext.xml @@ -1,14 +1,10 @@ <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans - http://www.springframework.org/schema/beans/spring-beans-3.0.xsd - http://www.springframework.org/schema/context - http://www.springframework.org/schema/context/spring-context-3.0.xsd"> + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> -<context:annotation-config /> <!-- manager --> <bean id="baseSecurityManager" class="org.olat.basesecurity.BaseSecurityManager" init-method="init" diff --git a/src/main/java/org/olat/commons/servlets/WebDAVManagerImpl.java b/src/main/java/org/olat/commons/servlets/WebDAVManagerImpl.java index 330bdaecf48..b209d96d635 100644 --- a/src/main/java/org/olat/commons/servlets/WebDAVManagerImpl.java +++ b/src/main/java/org/olat/commons/servlets/WebDAVManagerImpl.java @@ -35,6 +35,7 @@ import javax.servlet.http.HttpServletResponse; import org.olat.admin.user.delete.service.UserDeletionManager; import org.olat.basesecurity.BaseSecurityManager; import org.olat.basesecurity.BaseSecurityModule; +import org.olat.core.CoreSpringFactory; import org.olat.core.id.Identity; import org.olat.core.id.Roles; import org.olat.core.id.User; @@ -45,6 +46,7 @@ import org.olat.core.util.SessionInfo; import org.olat.core.util.UserSession; import org.olat.core.util.cache.n.CacheWrapper; import org.olat.core.util.coordinate.CoordinatorManager; +import org.olat.core.util.session.UserSessionManager; import org.olat.login.auth.WebDAVAuthManager; import com.oreilly.servlet.Base64Decoder; @@ -65,6 +67,7 @@ public class WebDAVManagerImpl extends WebDAVManager { private CoordinatorManager coordinatorManager; private CacheWrapper timedSessionCache; + private UserSessionManager sessionManager; /** * [spring] @@ -74,6 +77,14 @@ public class WebDAVManagerImpl extends WebDAVManager { INSTANCE = this; } + /** + * [used by Spring] + * @param sessionManager + */ + public void setSessionManager(UserSessionManager sessionManager) { + this.sessionManager = sessionManager; + } + /** * @see org.olat.commons.servlets.WebDAVManager#handleAuthentication(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) */ @@ -163,14 +174,14 @@ public class WebDAVManagerImpl extends WebDAVManager { // that neither field is blank Identity identity = WebDAVAuthManager.authenticate(userID, password); if (identity != null) { - UserSession usess = UserSession.getUserSession(request); + UserSession usess = sessionManager.getUserSession(request); synchronized(usess) { //double check to prevent severals concurrent login if(usess.isAuthenticated()) { return usess; } - usess.signOffAndClear(); + sessionManager.signOffAndClear(usess); usess.setIdentity(identity); UserDeletionManager.getInstance().setIdentityAsActiv(identity); // set the roles (admin, author, guest) @@ -200,7 +211,7 @@ public class WebDAVManagerImpl extends WebDAVManager { // set session info for this session usess.setSessionInfo(sinfo); // - usess.signOn(); + sessionManager.signOn(usess); return usess; } } @@ -208,7 +219,6 @@ public class WebDAVManagerImpl extends WebDAVManager { return null; } - /** * @see org.olat.core.servlets.WebDAVManager#isEnabled() */ diff --git a/src/main/java/org/olat/commons/servlets/_spring/webdavManagerContext.xml b/src/main/java/org/olat/commons/servlets/_spring/webdavManagerContext.xml index 89b80108b2b..b804d742ea9 100644 --- a/src/main/java/org/olat/commons/servlets/_spring/webdavManagerContext.xml +++ b/src/main/java/org/olat/commons/servlets/_spring/webdavManagerContext.xml @@ -9,6 +9,7 @@ <constructor-arg ref="coordinatorManager"/> <!-- set to false to disable the WebDAV support and remove the WebDAV Link from the GUI --> <property name="enabled" value="${webdav.links.enabled}" /> + <property name="sessionManager" ref="userSessionManager" /> </bean> </beans> diff --git a/src/main/java/org/olat/commons/servlets/pathhandlers/ContextHelpFilePathHandler.java b/src/main/java/org/olat/commons/servlets/pathhandlers/ContextHelpFilePathHandler.java index 53cbcfc0b9b..c6f122f854b 100644 --- a/src/main/java/org/olat/commons/servlets/pathhandlers/ContextHelpFilePathHandler.java +++ b/src/main/java/org/olat/commons/servlets/pathhandlers/ContextHelpFilePathHandler.java @@ -29,13 +29,10 @@ import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; -import java.util.Locale; import javax.servlet.http.HttpServletRequest; import org.olat.commons.servlets.util.ResourceDescriptor; -import org.olat.core.logging.StartupException; -import org.olat.core.util.UserSession; import org.olat.core.util.WebappHelper; @@ -64,15 +61,16 @@ public class ContextHelpFilePathHandler implements PathHandler { * @see org.olat.commons.servlets.pathhandlers.PathHandler#init(com.anthonyeden.lib.config.Configuration) */ public void init(String path) { - if (path == null) return; - if (path != null) { + if (path == null) { + return; + } else { File f = new File(path); if (f.isAbsolute()) { setRoot(path); } else { setRoot(WebappHelper.getContextRoot() + "/" + path); } - } else throw new StartupException("ContextHelpFilePathHandler did not find mandatory <root> element:" + path); + } } /** @@ -96,14 +94,7 @@ public class ContextHelpFilePathHandler implements PathHandler { try { File f = new File(root + relPath); if (f.isDirectory()) return null; - - if (!f.exists()) { // file not found -> - int i = 1; - i ++; - } - //FIXME:fj: handle appropriately - Locale loc = UserSession.getUserSession(request).getLocale(); - + ResourceDescriptor rd = new ResourceDescriptor(relPath); rd.setLastModified(f.lastModified()); rd.setSize(f.length()); diff --git a/src/main/java/org/olat/core/_spring/mainCorecontext.xml b/src/main/java/org/olat/core/_spring/mainCorecontext.xml index da2a1724b4f..207a089ead8 100644 --- a/src/main/java/org/olat/core/_spring/mainCorecontext.xml +++ b/src/main/java/org/olat/core/_spring/mainCorecontext.xml @@ -11,7 +11,6 @@ http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> - <context:annotation-config /> <context:component-scan base-package="org.olat.core.dispatcher.mapper" /> <tx:annotation-driven transaction-manager="txManager"/> diff --git a/src/main/java/org/olat/core/commons/contextHelp/_spring/contextHelpCorecontext.xml b/src/main/java/org/olat/core/commons/contextHelp/_spring/contextHelpCorecontext.xml index a659ee6ae48..af50e3e4e79 100644 --- a/src/main/java/org/olat/core/commons/contextHelp/_spring/contextHelpCorecontext.xml +++ b/src/main/java/org/olat/core/commons/contextHelp/_spring/contextHelpCorecontext.xml @@ -1,14 +1,9 @@ <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans - http://www.springframework.org/schema/beans/spring-beans-3.0.xsd - http://www.springframework.org/schema/context - http://www.springframework.org/schema/context/spring-context-3.0.xsd"> - -<context:annotation-config /> + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="contextHelpManager" class="org.olat.core.commons.contextHelp.ContextHelpManager" > <constructor-arg ref="coordinatorManager" /> diff --git a/src/main/java/org/olat/core/commons/fullWebApp/DefaultFooterController.java b/src/main/java/org/olat/core/commons/fullWebApp/DefaultFooterController.java index d6949c27c48..a0aa9977069 100644 --- a/src/main/java/org/olat/core/commons/fullWebApp/DefaultFooterController.java +++ b/src/main/java/org/olat/core/commons/fullWebApp/DefaultFooterController.java @@ -19,6 +19,7 @@ */ package org.olat.core.commons.fullWebApp; +import org.olat.core.CoreSpringFactory; import org.olat.core.defaults.dispatcher.ClassPathStaticDispatcher; import org.olat.core.gui.UserRequest; import org.olat.core.gui.Windows; @@ -28,7 +29,7 @@ import org.olat.core.gui.control.Event; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.controller.BasicController; import org.olat.core.helpers.Settings; -import org.olat.core.util.UserSession; +import org.olat.core.util.session.UserSessionManager; /** * <h3>Description:</h3> @@ -70,7 +71,7 @@ public class DefaultFooterController extends BasicController { // Push information about logged in users footerVC - .contextPut("userSessionsCnt", UserSession.getUserSessionsCnt()); + .contextPut("userSessionsCnt", CoreSpringFactory.getImpl(UserSessionManager.class).getUserSessionsCnt()); // Push information about user if (ureq.getUserSession().isAuthenticated()) { diff --git a/src/main/java/org/olat/core/commons/fullWebApp/DefaultTopNavController.java b/src/main/java/org/olat/core/commons/fullWebApp/DefaultTopNavController.java index 3a4afc379e2..ef1d359f09e 100644 --- a/src/main/java/org/olat/core/commons/fullWebApp/DefaultTopNavController.java +++ b/src/main/java/org/olat/core/commons/fullWebApp/DefaultTopNavController.java @@ -19,6 +19,7 @@ */ package org.olat.core.commons.fullWebApp; +import org.olat.core.CoreSpringFactory; import org.olat.core.dispatcher.DispatcherAction; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.Component; @@ -26,6 +27,7 @@ import org.olat.core.gui.components.velocity.VelocityContainer; import org.olat.core.gui.control.Event; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.controller.BasicController; +import org.olat.core.util.session.UserSessionManager; /** * <h3>Description:</h3> @@ -62,7 +64,7 @@ public class DefaultTopNavController extends BasicController { String command = event.getCommand(); if (source == topNavVC) { if (command.equals("logout")) { - ureq.getUserSession().signOffAndClear(); + CoreSpringFactory.getImpl(UserSessionManager.class).signOffAndClear(ureq.getUserSession()); } else if (command.equals("login")) { DispatcherAction .redirectToDefaultDispatcher(ureq.getHttpResp()); diff --git a/src/main/java/org/olat/core/commons/fullWebApp/util/_spring/StickyMessageCorecontext.xml b/src/main/java/org/olat/core/commons/fullWebApp/util/_spring/StickyMessageCorecontext.xml index 7d91c2c103a..0be6085b0de 100644 --- a/src/main/java/org/olat/core/commons/fullWebApp/util/_spring/StickyMessageCorecontext.xml +++ b/src/main/java/org/olat/core/commons/fullWebApp/util/_spring/StickyMessageCorecontext.xml @@ -1,14 +1,10 @@ <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans - http://www.springframework.org/schema/beans/spring-beans-3.0.xsd - http://www.springframework.org/schema/context - http://www.springframework.org/schema/context/spring-context-3.0.xsd"> + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> -<context:annotation-config /> <!-- manager --> <bean id="globalStickyMessage" class="org.olat.core.commons.fullWebApp.util.GlobalStickyMessage" init-method="init" > diff --git a/src/main/java/org/olat/core/commons/modules/glossary/_spring/glossaryCorecontext.xml b/src/main/java/org/olat/core/commons/modules/glossary/_spring/glossaryCorecontext.xml index f07b680ba85..04942299059 100644 --- a/src/main/java/org/olat/core/commons/modules/glossary/_spring/glossaryCorecontext.xml +++ b/src/main/java/org/olat/core/commons/modules/glossary/_spring/glossaryCorecontext.xml @@ -1,14 +1,9 @@ <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans - http://www.springframework.org/schema/beans/spring-beans-3.0.xsd - http://www.springframework.org/schema/context - http://www.springframework.org/schema/context/spring-context-3.0.xsd"> - -<context:annotation-config /> + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <!-- ***************************************** diff --git a/src/main/java/org/olat/core/commons/services/_spring/servicesCorecontext.xml b/src/main/java/org/olat/core/commons/services/_spring/servicesCorecontext.xml index fd7c39ecf35..90b29f9721e 100644 --- a/src/main/java/org/olat/core/commons/services/_spring/servicesCorecontext.xml +++ b/src/main/java/org/olat/core/commons/services/_spring/servicesCorecontext.xml @@ -8,7 +8,6 @@ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> -<context:annotation-config /> <context:component-scan base-package="org.olat.core.commons.services" /> </beans> \ No newline at end of file diff --git a/src/main/java/org/olat/core/commons/taskExecutor/_spring/taskExecutorCorecontext.xml b/src/main/java/org/olat/core/commons/taskExecutor/_spring/taskExecutorCorecontext.xml index 6e76b2d6a95..8f2f6173410 100644 --- a/src/main/java/org/olat/core/commons/taskExecutor/_spring/taskExecutorCorecontext.xml +++ b/src/main/java/org/olat/core/commons/taskExecutor/_spring/taskExecutorCorecontext.xml @@ -1,14 +1,9 @@ <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans - http://www.springframework.org/schema/beans/spring-beans-3.0.xsd - http://www.springframework.org/schema/context - http://www.springframework.org/schema/context/spring-context-3.0.xsd"> - -<context:annotation-config /> + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="taskExecutorManager" class="org.olat.core.commons.taskExecutor.TaskExecutorManager" destroy-method="destroy"> <constructor-arg index="0"> diff --git a/src/main/java/org/olat/core/gui/UserRequest.java b/src/main/java/org/olat/core/gui/UserRequest.java index be352794b4b..26a9671bbc4 100644 --- a/src/main/java/org/olat/core/gui/UserRequest.java +++ b/src/main/java/org/olat/core/gui/UserRequest.java @@ -40,11 +40,13 @@ import java.util.StringTokenizer; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.olat.core.CoreSpringFactory; import org.olat.core.gui.control.DispatchResult; import org.olat.core.id.Identity; import org.olat.core.logging.AssertException; import org.olat.core.logging.Tracing; import org.olat.core.util.UserSession; +import org.olat.core.util.session.UserSessionManager; /** * is the "thing" generated by one user-click. It contains mainly the servlet @@ -137,7 +139,7 @@ public class UserRequest { */ public UserSession getUserSession() { //FIXME:fj:b cache usersession here - UserSession result = UserSession.getUserSession(getHttpReq()); + UserSession result = CoreSpringFactory.getImpl(UserSessionManager.class).getUserSession(getHttpReq()); if (result==null) { Tracing.logWarn("getUserSession: null, this="+this, new RuntimeException("getUserSession"), UserSession.class); } diff --git a/src/main/java/org/olat/core/gui/components/Window.java b/src/main/java/org/olat/core/gui/components/Window.java index b5c2f56acd1..77aba129760 100644 --- a/src/main/java/org/olat/core/gui/components/Window.java +++ b/src/main/java/org/olat/core/gui/components/Window.java @@ -27,7 +27,6 @@ package org.olat.core.gui.components; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -41,7 +40,6 @@ import org.json.JSONException; import org.json.JSONObject; import org.olat.core.CoreSpringFactory; import org.olat.core.commons.persistence.DBFactory; -import org.olat.core.dispatcher.mapper.MapperDispatcher; import org.olat.core.dispatcher.mapper.MapperService; import org.olat.core.gui.GUIInterna; import org.olat.core.gui.GlobalSettings; diff --git a/src/main/java/org/olat/core/gui/components/util/UserLoggedInCounter.java b/src/main/java/org/olat/core/gui/components/util/UserLoggedInCounter.java index 5ffb79b7799..930419dcc3c 100644 --- a/src/main/java/org/olat/core/gui/components/util/UserLoggedInCounter.java +++ b/src/main/java/org/olat/core/gui/components/util/UserLoggedInCounter.java @@ -21,10 +21,11 @@ package org.olat.core.gui.components.util; +import org.olat.core.CoreSpringFactory; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.Component; import org.olat.core.gui.components.ComponentRenderer; -import org.olat.core.util.UserSession; +import org.olat.core.util.session.UserSessionManager; /** * <h3>Description:</h3> @@ -45,7 +46,7 @@ public class UserLoggedInCounter extends Component { */ public UserLoggedInCounter() { super("UserCounter"); - this.currentCount = UserSession.getUserSessionWebCounter(); + this.currentCount = CoreSpringFactory.getImpl(UserSessionManager.class).getUserSessionWebCounter(); this.setSpanAsDomReplaceable(true); } @@ -55,7 +56,7 @@ public class UserLoggedInCounter extends Component { @Override public boolean isDirty() { int lastCount = currentCount; - currentCount = UserSession.getUserSessionWebCounter(); + currentCount = CoreSpringFactory.getImpl(UserSessionManager.class).getUserSessionWebCounter(); return (currentCount != lastCount); } diff --git a/src/main/java/org/olat/core/gui/control/DefaultController.java b/src/main/java/org/olat/core/gui/control/DefaultController.java index 4e1d4f82310..165aa55208e 100644 --- a/src/main/java/org/olat/core/gui/control/DefaultController.java +++ b/src/main/java/org/olat/core/gui/control/DefaultController.java @@ -32,6 +32,7 @@ import java.util.List; import java.util.Locale; import java.util.concurrent.atomic.AtomicInteger; +import org.olat.core.CoreSpringFactory; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.Component; import org.olat.core.gui.components.panel.Panel; @@ -48,9 +49,9 @@ import org.olat.core.logging.activity.IUserActivityLogger; import org.olat.core.logging.activity.ThreadLocalUserActivityLoggerInstaller; import org.olat.core.logging.activity.UserActivityLoggerImpl; import org.olat.core.util.RunnableWithException; -import org.olat.core.util.UserSession; import org.olat.core.util.Util; import org.olat.core.util.i18n.I18nModule; +import org.olat.core.util.session.UserSessionManager; /** * Description: <br> @@ -327,7 +328,7 @@ public abstract class DefaultController implements Controller, ControllerEventLi // throw this in the unlikely odd still throw new IllegalStateException("no logger set"); } - logger.frameworkSetSession(UserSession.getUserSessionIfAlreadySet(req.getHttpReq())); + logger.frameworkSetSession(CoreSpringFactory.getImpl(UserSessionManager.class).getUserSessionIfAlreadySet(req.getHttpReq())); } /** diff --git a/src/main/java/org/olat/core/gui/control/generic/layout/GenericMainController.java b/src/main/java/org/olat/core/gui/control/generic/layout/GenericMainController.java index 9a4b1b1278f..031ddf790b7 100644 --- a/src/main/java/org/olat/core/gui/control/generic/layout/GenericMainController.java +++ b/src/main/java/org/olat/core/gui/control/generic/layout/GenericMainController.java @@ -77,6 +77,8 @@ public abstract class GenericMainController extends MainLayoutBasicController im private static final String GMCMT = "GMCMenuTree"; + + private Link backLink; private MenuTree olatMenuTree; private Panel content; private VelocityContainer stackVC; @@ -125,6 +127,13 @@ public abstract class GenericMainController extends MainLayoutBasicController im String stackPage = Util.getPackageVelocityRoot(StackedController.class) + "/stack.html"; stackVC = new VelocityContainer(null, "vc_stack", stackPage, getTranslator(), this); stackVC.put("content", columnLayoutCtr.getInitialComponent()); + //back link + backLink = LinkFactory.createCustomLink("back", "back", null, Link.NONTRANSLATED + Link.LINK_CUSTOM_CSS, stackVC, this); + backLink.setCustomEnabledLinkCSS("b_breadcumb_back"); + backLink.setCustomDisplayText("\u25C4"); // unicode back arrow (black left pointer symbol) + backLink.setTitle(translate("back")); + backLink.setAccessKey("b"); // allow navigation using keyboard + stackVC.put("back", backLink); //add the root Link link = LinkFactory.createLink("gcrumb_root", stackVC, this); link.setCustomDisplayText(firstNode.getTitle()); @@ -318,6 +327,13 @@ public abstract class GenericMainController extends MainLayoutBasicController im @Override protected void event(UserRequest ureq, Component source, Event event) { + if (source.equals(backLink)) { + if (stack.size() > 1) { + // back means to one level down, change source to the stack item one below current + source = stack.get(stack.size()-2); + // now continue as if user manually pressed a stack item in the list + } + } if(stack.contains(source)) { int index = stack.indexOf(source); if(index < (stack.size() - 1)) { diff --git a/src/main/java/org/olat/core/gui/media/ServletUtil.java b/src/main/java/org/olat/core/gui/media/ServletUtil.java index 9a0ce76b562..f0e0ba0c36e 100644 --- a/src/main/java/org/olat/core/gui/media/ServletUtil.java +++ b/src/main/java/org/olat/core/gui/media/ServletUtil.java @@ -40,6 +40,7 @@ import java.util.StringTokenizer; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.olat.core.CoreSpringFactory; import org.olat.core.gui.Windows; import org.olat.core.gui.util.bandwidth.SlowBandWidthSimulator; import org.olat.core.helpers.Settings; @@ -47,7 +48,7 @@ import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; import org.olat.core.util.FileUtils; import org.olat.core.util.StringHelper; -import org.olat.core.util.UserSession; +import org.olat.core.util.session.UserSessionManager; /** * @author Felix Jost @@ -144,7 +145,7 @@ public class ServletUtil { } if (Settings.isDebuging()) { - SlowBandWidthSimulator sbs = Windows.getWindows(UserSession.getUserSession(httpReq)).getSlowBandWidthSimulator(); + SlowBandWidthSimulator sbs = Windows.getWindows(CoreSpringFactory.getImpl(UserSessionManager.class).getUserSession(httpReq)).getSlowBandWidthSimulator(); out = sbs.wrapOutputStream(httpResp.getOutputStream()); } else { out = httpResp.getOutputStream(); @@ -446,7 +447,7 @@ public class ServletUtil { OutputStream os; if (Settings.isDebuging()) { - SlowBandWidthSimulator sbs = Windows.getWindows(UserSession.getUserSession(httpReq)).getSlowBandWidthSimulator(); + SlowBandWidthSimulator sbs = Windows.getWindows(CoreSpringFactory.getImpl(UserSessionManager.class).getUserSession(httpReq)).getSlowBandWidthSimulator(); os = sbs.wrapOutputStream(response.getOutputStream()); } else { os = response.getOutputStream(); diff --git a/src/main/java/org/olat/core/logging/Tracing.java b/src/main/java/org/olat/core/logging/Tracing.java index 1ef345ac6eb..6962bea0e97 100644 --- a/src/main/java/org/olat/core/logging/Tracing.java +++ b/src/main/java/org/olat/core/logging/Tracing.java @@ -38,10 +38,12 @@ import javax.servlet.http.HttpServletRequest; import org.apache.log4j.Level; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; +import org.olat.core.CoreSpringFactory; import org.olat.core.helpers.Settings; import org.olat.core.id.Identity; import org.olat.core.util.UserSession; import org.olat.core.util.WebappHelper; +import org.olat.core.util.session.UserSessionManager; /** * This is the central place where all log information should pass. @@ -356,7 +358,7 @@ public class Tracing { String userAgent = null; String referer = null; if (ureq != null) { - usess = UserSession.getUserSessionIfAlreadySet(ureq); + usess = CoreSpringFactory.getImpl(UserSessionManager.class).getUserSessionIfAlreadySet(ureq); if (usess != null) { identity = usess.getIdentity(); remoteIp = ureq.getRemoteAddr(); @@ -415,7 +417,7 @@ public class Tracing { String userAgent = null; String referer = null; if (ureq != null) { - usess = UserSession.getUserSession(ureq); + usess = CoreSpringFactory.getImpl(UserSessionManager.class).getUserSession(ureq); identity = usess.getIdentity(); remoteIp = ureq.getRemoteAddr(); userAgent = ureq.getHeader("User-Agent"); diff --git a/src/main/java/org/olat/core/logging/activity/UserActivityLoggerImpl.java b/src/main/java/org/olat/core/logging/activity/UserActivityLoggerImpl.java index 234dee71003..8f9eff9191c 100644 --- a/src/main/java/org/olat/core/logging/activity/UserActivityLoggerImpl.java +++ b/src/main/java/org/olat/core/logging/activity/UserActivityLoggerImpl.java @@ -40,6 +40,7 @@ import java.util.Set; import javax.servlet.http.HttpServletRequest; +import org.olat.core.CoreSpringFactory; import org.olat.core.commons.persistence.DB; import org.olat.core.commons.persistence.DBFactory; import org.olat.core.gui.control.Controller; @@ -51,6 +52,7 @@ import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; import org.olat.core.util.UserSession; import org.olat.core.util.i18n.I18nManager; +import org.olat.core.util.session.UserSessionManager; /** * Default implementation of the IUserActivityLogger which logs into @@ -195,7 +197,7 @@ public class UserActivityLoggerImpl implements IUserActivityLogger { throw new IllegalArgumentException("hReq must not be null"); } - session_ = UserSession.getUserSessionIfAlreadySet(hReq); + session_ = CoreSpringFactory.getImpl(UserSessionManager.class).getUserSessionIfAlreadySet(hReq); if (session_!=null) { identity_ = session_.getIdentity(); } diff --git a/src/main/java/org/olat/core/util/SignOnOffEvent.java b/src/main/java/org/olat/core/util/SignOnOffEvent.java index d2f2aeeacfb..1ba58ea1164 100644 --- a/src/main/java/org/olat/core/util/SignOnOffEvent.java +++ b/src/main/java/org/olat/core/util/SignOnOffEvent.java @@ -35,6 +35,8 @@ import org.olat.core.util.event.MultiUserEvent; */ public class SignOnOffEvent extends MultiUserEvent { + private static final long serialVersionUID = 5721212429245547948L; + private String identityName; private boolean signOn; /** diff --git a/src/main/java/org/olat/core/util/UserSession.java b/src/main/java/org/olat/core/util/UserSession.java index c0cb376ae25..1ababad2d81 100644 --- a/src/main/java/org/olat/core/util/UserSession.java +++ b/src/main/java/org/olat/core/util/UserSession.java @@ -27,27 +27,19 @@ package org.olat.core.util; import java.io.Serializable; -import java.util.ArrayList; -import java.util.Comparator; import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.Set; import java.util.Stack; -import java.util.TreeSet; -import java.util.concurrent.atomic.AtomicInteger; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSessionBindingEvent; import javax.servlet.http.HttpSessionBindingListener; +import org.olat.core.CoreSpringFactory; import org.olat.core.commons.persistence.DBFactory; import org.olat.core.gui.UserRequest; -import org.olat.core.gui.control.Disposable; import org.olat.core.gui.control.Event; import org.olat.core.id.Identity; import org.olat.core.id.IdentityEnvironment; @@ -55,22 +47,18 @@ import org.olat.core.id.OLATResourceable; import org.olat.core.id.Roles; import org.olat.core.id.context.BusinessControl; import org.olat.core.id.context.ContextEntry; -import org.olat.core.id.context.HistoryManager; import org.olat.core.id.context.HistoryPoint; import org.olat.core.id.context.HistoryPointImpl; -import org.olat.core.logging.AssertException; +import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; -import org.olat.core.logging.activity.CoreLoggingResourceable; -import org.olat.core.logging.activity.OlatLoggingAction; -import org.olat.core.logging.activity.ThreadLocalUserActivityLogger; import org.olat.core.logging.activity.ThreadLocalUserActivityLoggerInstaller; -import org.olat.core.logging.activity.UserActivityLoggerImpl; import org.olat.core.util.coordinate.CoordinatorManager; import org.olat.core.util.event.EventBus; import org.olat.core.util.event.GenericEventListener; import org.olat.core.util.prefs.Preferences; import org.olat.core.util.prefs.PreferencesFactory; import org.olat.core.util.resource.OresHelper; +import org.olat.core.util.session.UserSessionManager; /** * Description: <BR/>the httpsession contains an instance of this class. the @@ -81,50 +69,27 @@ import org.olat.core.util.resource.OresHelper; */ public class UserSession implements HttpSessionBindingListener, GenericEventListener, Serializable { + private static final OLog log = Tracing.createLoggerFor(UserSession.class); private static final long serialVersionUID = 1975177605776990868L; - - private static final String USERSESSIONKEY = UserSession.class.getName(); - public static final OLATResourceable ORES_USERSESSION = OresHelper.createOLATResourceableType(UserSession.class); - public static final String STORE_KEY_KILLED_EXISTING_SESSION = "killedExistingSession"; - - //clusterNOK cache ?? - private static final Set<UserSession> authUserSessions = new HashSet<UserSession>(101); - private static final Set<String> userNameToIdentity = new HashSet<String>(101); - private static int sessionTimeoutInSec = 300; - private static int sessionTimeoutAuthInSec = 7200; - private static final Set<String> authUsersNamesOtherNodes = new HashSet<String>(101); - - // things to put into that should not be clear when signing on (e.g. remember - // url for a direct jump) - private Map<String,Object> nonClearedStore = new HashMap<String,Object>(); // the environment (identity, locale, ..) of the identity private IdentityEnvironment identityEnvironment; private SessionInfo sessionInfo; private Map<String,Object> store; + /** + * things to put into that should not be clear when signing on (e.g. remember url for a direct jump) + */ + private Map<String,Object> nonClearedStore = new HashMap<String,Object>(); private boolean authenticated = false; - private boolean registeredWithBus = false; private Preferences guiPreferences; private EventBus singleUserSystemBus; - //fxdiff BAKS-7 Resume function private Stack<HistoryPoint> history = new Stack<HistoryPoint>(); - // counters to count numbers of sessions - private static final AtomicInteger sessionCountWeb = new AtomicInteger(); - private static final AtomicInteger sessionCountRest = new AtomicInteger(); - private static final AtomicInteger sessionCountDav = new AtomicInteger(); - - private UserSession() { + public UserSession() { init(); - //usersession is listening for SignOnOffEvents from other clusternodes - CoordinatorManager.getInstance().getCoordinator().getEventBus().registerFor(this, null, ORES_USERSESSION); - registeredWithBus = true; } - /** - * - */ - private void init() { + public void init() { store = new HashMap<String,Object>(4); identityEnvironment = new IdentityEnvironment(); singleUserSystemBus = CoordinatorManager.getInstance().getCoordinator().createSingleUserInstance(); @@ -133,65 +98,18 @@ public class UserSession implements HttpSessionBindingListener, GenericEventList } /** - * @param session - * @return associated user session - */ - public static UserSession getUserSession(HttpSession session) { - UserSession us; - synchronized (session) {//o_clusterOK by:fj - us = (UserSession) session.getAttribute(USERSESSIONKEY); - if (us == null) { - us = new UserSession(); - session.setAttribute(USERSESSIONKEY, us); // triggers the - // valueBoundEvent -> nothing - // more to do here - } - } - //set a possible changed session timeout interval - if(us.isAuthenticated()) { - session.setMaxInactiveInterval(UserSession.sessionTimeoutAuthInSec); - } else { - session.setMaxInactiveInterval(UserSession.sessionTimeoutInSec); - } - return us; - } - - /** - * @param hreq - * @return associated user session + * @return true if is authenticated */ - public static UserSession getUserSession(HttpServletRequest hreq) { - // get existing or create new session - return getUserSession(hreq.getSession(true)); + public boolean isAuthenticated() { + return authenticated; } - /** - * Return the UserSession of the given request if it is already set or null otherwise - * @param hreq - * @return - */ - public static UserSession getUserSessionIfAlreadySet(HttpServletRequest hreq) { - HttpSession session = hreq.getSession(false); - if (session==null) { - return null; - } - - synchronized (session) {//o_clusterOK by:se - UserSession us = (UserSession) session.getAttribute(USERSESSIONKEY); - if(us != null && us.isAuthenticated()) { - session.setMaxInactiveInterval(UserSession.sessionTimeoutAuthInSec); - } else { - session.setMaxInactiveInterval(UserSession.sessionTimeoutInSec); - } - return us; - } + public void setAuthenticated(boolean authenticated) { + this.authenticated = authenticated; } - /** - * @return true if is authenticated - */ - public boolean isAuthenticated() { - return authenticated; + public Map<String,Object> getStore() { + return store; } /** @@ -246,8 +164,7 @@ public class UserSession implements HttpSessionBindingListener, GenericEventList * @return Locale */ public Locale getLocale() { - Locale locale = identityEnvironment.getLocale(); - return locale; + return identityEnvironment.getLocale(); } /** @@ -286,8 +203,8 @@ public class UserSession implements HttpSessionBindingListener, GenericEventList */ public Roles getRoles() { Roles result = identityEnvironment.getRoles(); - if (result==null) { - Tracing.logWarn("getRoles: null, this="+this, new RuntimeException("getRoles"), UserSession.class); + if (result == null) { + log.warn("getRoles: null, this="+this, new RuntimeException("getRoles")); } return result; } @@ -300,8 +217,52 @@ public class UserSession implements HttpSessionBindingListener, GenericEventList public void setRoles(Roles roles) { identityEnvironment.setRoles(roles); } + + /** + * @return identity environment + */ + public IdentityEnvironment getIdentityEnvironment() { + return identityEnvironment; + } + + /** + * may be null + * <p> + * @return session info object + */ + public SessionInfo getSessionInfo() { + return sessionInfo; + } + + /** + * @param sessionInfo + */ + public void setSessionInfo(SessionInfo sessionInfo) { + this.sessionInfo = sessionInfo; + } + + /** + * @return Returns the guiPreferences. + */ + public Preferences getGuiPreferences() { + return guiPreferences; + } + + public void reloadPreferences() { + Identity identity = identityEnvironment.getIdentity(); + guiPreferences = PreferencesFactory.getInstance().getPreferencesFor(identity, identityEnvironment.getRoles().isGuestOnly()); + } + + /** + * This is the olatsystembus to broadcast event amongst controllers of a single user only + * (the one whom this usersession belongs to) + * + * @return the olatsystembus for the local user + */ + public EventBus getSingleUserEventCenter() { + return singleUserSystemBus; + } - //fxdiff BAKS-7 Resume function public List<HistoryPoint> getHistoryStack() { return history; } @@ -313,7 +274,6 @@ public class UserSession implements HttpSessionBindingListener, GenericEventList return history.lastElement(); } - //fxdiff BAKS-7 Resume function public HistoryPoint popLastHistoryEntry() { if(history.isEmpty()) return null; history.pop();//current point @@ -321,14 +281,12 @@ public class UserSession implements HttpSessionBindingListener, GenericEventList return history.pop();//remove last point from history } - //fxdiff BAKS-7 Resume function public void addToHistory(UserRequest ureq, HistoryPoint point) { if(point == null) return; //System.out.println(ureq.getUuid() + " Add point to history: " + point.getBusinessPath()); history.add(new HistoryPointImpl(ureq.getUuid(), point.getBusinessPath(), point.getEntries())); } - //fxdiff BAKS-7 Resume function public void addToHistory(UserRequest ureq, BusinessControl businessControl) { List<ContextEntry> entries = businessControl.getEntries(); String businessPath = businessControl.getAsString(); @@ -365,8 +323,8 @@ public class UserSession implements HttpSessionBindingListener, GenericEventList * @see javax.servlet.http.HttpSessionBindingListener#valueBound(javax.servlet.http.HttpSessionBindingEvent) */ public void valueBound(HttpSessionBindingEvent be) { - if (Tracing.isDebugEnabled(UserSession.class)) { - Tracing.logDebug("Opened UserSession:" + this.toString(), UserSession.class); + if (log.isDebug()) { + log.debug("Opened UserSession:" + toString()); } } @@ -380,9 +338,9 @@ public class UserSession implements HttpSessionBindingListener, GenericEventList // the identity can be null if an loginscreen only session gets invalidated // (no user was authenticated yet but a tomcat session was created) Identity ident = identityEnvironment.getIdentity(); - signOffAndClear(); - if (Tracing.isDebugEnabled(UserSession.class)) { - Tracing.logDebug("Closed UserSession: identity = " + (ident == null ? "n/a":ident.getName()), UserSession.class); + CoreSpringFactory.getImpl(UserSessionManager.class).signOffAndClear(this); + if (log.isDebug()) { + log.debug("Closed UserSession: identity = " + (ident == null ? "n/a":ident.getName())); } //we do not have a request in the null case (app. server triggered) and user not yet logged in //-> in this case we use the special empty activity logger @@ -390,9 +348,7 @@ public class UserSession implements HttpSessionBindingListener, GenericEventList ThreadLocalUserActivityLoggerInstaller.initEmptyUserActivityLogger(); } } catch (Exception e) { - // safely retrieve - Identity ident = identityEnvironment.getIdentity(); - Tracing.logError("exception while session was unbound!", e, UserSession.class); + log.error("exception while session was unbound!", e); } // called by tomcat's timer thread -> we need to close!! since the next unbound will be called from the same tomcat-thread finally { @@ -402,482 +358,20 @@ public class UserSession implements HttpSessionBindingListener, GenericEventList } /** - * called from signOffAndClear() - * called from event -> MUEvent - * the real work to do during sign off but without sending the multiuserevent - * this is used in case the user logs in to node1 and was logged in on node2 => - * node2 catches the sign on event and invalidates the user on node2 "silently", e.g. - * without firing an event. - */ - private void signOffAndClearWithout(){ - Tracing.logDebug("signOffAndClearWithout() START", getClass()); - final Identity ident = identityEnvironment.getIdentity(); - //System.out.println("signOffAndClearWithout, ident="+ident+", hash="+this.hashCode()+", identityenv "+identityEnvironment.hashCode()); - // handle safely - boolean isDebug = Tracing.isDebugEnabled(UserSession.class); - if (isDebug) { - Tracing.logDebug("UserSession:::logging off: " + sessionInfo, this.getClass()); - } - //fxdiff BAKS-7 Resume function - if(isAuthenticated() && getLastHistoryPoint() != null && !getRoles().isGuestOnly()) { - HistoryManager.getInstance().persistHistoryPoint(ident, getLastHistoryPoint()); - } - - /** - * use not RunnableWithException, as exceptionHandlng is inside the run - */ - Runnable run = new Runnable() { - public void run() { - Object obj = null; - try { - - // do logging - if (ident != null) { - ThreadLocalUserActivityLogger.log(OlatLoggingAction.OLAT_LOGOUT, UserSession.class, CoreLoggingResourceable.wrap(ident)); - } else { - //System.out.println("identity is null!!!!!!!!!!!!!!!!!!!!!"); - } - // notify all variables in the store (the values) about the disposal - // if - // Disposable - - for (Iterator<Object> it_storevals = new ArrayList<Object>(store.values()).iterator(); it_storevals.hasNext();) { - obj = it_storevals.next(); - if (obj instanceof Disposable) { - // synchronous, since triggered by tomcat session timeout or user - // click and - // asynchronous, if kicked out by administrator. - // we assume synchronous - // !!!! - // As a reminder, this .dispose() calls dispose on - // DefaultController which is synchronized. - // (Windows/WindowManagerImpl/WindowBackOfficeImpl/BaseChiefController/../ - // dispose() - // !!!! was important for bug OLAT-3390 - - ((Disposable) obj).dispose(); - } - } - } catch (Exception e) { - - String objtostr = "n/a"; - try { - objtostr = obj.toString(); - } catch (Exception ee) { - // ignore - } - Tracing.logError("exception in signOffAndClear: while disposing object:" + objtostr, e, UserSession.class); - } - } - }; - - ThreadLocalUserActivityLoggerInstaller.runWithUserActivityLogger(run, UserActivityLoggerImpl.newLoggerForValueUnbound(this)); - - synchronized (authUserSessions) { //o_clusterOK by:fj - if(authUserSessions.remove(this)){ - //remove only from identityEnvironment if found in sessions. - //see also SIDEEFFECT!! line in signOn(..) - Identity previousSignedOn = identityEnvironment.getIdentity(); - if (previousSignedOn != null) { - Tracing.logDebug("signOffAndClearWithout() removing from userNameToIdentity: "+previousSignedOn.getName().toLowerCase(), getClass()); - userNameToIdentity.remove(previousSignedOn.getName().toLowerCase()); - } - }else{ - if (isDebug) { - Tracing.logInfo("UserSession already removed! for ["+ident+"]", UserSession.class); - } - } - } - // update logged in users counters - if (sessionInfo != null) { - if (sessionInfo.isREST()) { - sessionCountRest.decrementAndGet(); - } else if (sessionInfo.isWebDAV()) { - sessionCountDav.decrementAndGet(); - } else { - sessionCountWeb.decrementAndGet(); - } - } - - Tracing.logDebug("signOffAndClearWithout() END", getClass()); - } - - - /** - * called to make sure the current authenticated user (if there is one at all) - * is cleared and signed off. This method is firing the SignOnOffEvent Multiuserevent. - */ - public synchronized void signOffAndClear() { //o_clusterOK by:fj - Tracing.logDebug("signOffAndClear() START", getClass()); - // - signOffAndClearWithout(); - // handle safely - try { - if (isAuthenticated()) { - Identity identity = identityEnvironment.getIdentity(); - Tracing.logAudit("Logged off: " + sessionInfo, this.getClass()); - CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(new SignOnOffEvent(identity, false), ORES_USERSESSION); - Tracing.logDebug("signOffAndClear() deregistering usersession from eventbus, id="+sessionInfo, getClass()); - CoordinatorManager.getInstance().getCoordinator().getEventBus().deregisterFor(this, ORES_USERSESSION); - //fxdiff FXOLAT-231: event on GUI Preferences extern changes - OLATResourceable ores = OresHelper.createOLATResourceableInstance(Preferences.class, identity.getKey()); - CoordinatorManager.getInstance().getCoordinator().getEventBus().deregisterFor(this, ores); - registeredWithBus = false; - } - } catch (Exception e) { - Tracing.logError("exception in signOffAndClear: while sending signonoffevent!", e, UserSession.class); - } - // clear all instance variables, set authenticated to false - init(); - Tracing.logDebug("signOffAndClear() END", getClass()); - } - - /** - * prior to calling this method, all instance vars must be set. - */ - public synchronized void signOn() { - // ^^^^^^^^^^^^ Added synchronized to be symmetric with sign off and to - // fix a possible dead-lock see also OLAT-3390 - Tracing.logDebug("signOn() START", getClass()); - if (isAuthenticated()) throw new AssertException("sign on: already signed on!"); - Identity identity = identityEnvironment.getIdentity(); - if (identity == null) throw new AssertException("identity is null in identityEnvironment!"); - if (sessionInfo == null) throw new AssertException("sessionInfo was null for identity " + identity); - //String login = identity.getName(); - authenticated = true; - - if (sessionInfo.isWebDAV()) { - // load user prefs - guiPreferences = PreferencesFactory.getInstance().getPreferencesFor(identity, identityEnvironment.getRoles().isGuestOnly()); - - synchronized (authUserSessions) { //o_clusterOK by:se - // we're only adding this webdav session to the authUserSessions - not to the userNameToIdentity. - // userNameToIdentity is only needed for IM which can't do anything with a webdav session - authUserSessions.add(this); - } - Tracing.logAudit("Logged on [via webdav]: " + sessionInfo.toString(), this.getClass()); - return; - } - - Tracing.logDebug("signOn() authUsersNamesOtherNodes.contains "+identity.getName()+": "+authUsersNamesOtherNodes.contains(identity.getName()), getClass()); - - UserSession invalidatedSession = null; - synchronized (authUserSessions) { //o_clusterOK by:fj - // check if already a session exist for this user - if ( (userNameToIdentity.contains(identity.getName().toLowerCase()) || authUsersNamesOtherNodes.contains(identity.getName()) ) - && !sessionInfo.isWebDAV() && !sessionInfo.isREST() && !getRoles().isGuestOnly()) { - Tracing.logInfo("Loggin-process II: User has already a session => signOffAndClear existing session", this.getClass()); - - invalidatedSession = getUserSessionFor(identity.getName().toLowerCase()); - //remove session to be invalidated - //SIDEEFFECT!! to signOffAndClear - //if invalidatedSession is removed from authUserSessions - //signOffAndClear does not remove the identity.getName().toLowerCase() from the userNameToIdentity - // - authUserSessions.remove(invalidatedSession); - } - authUserSessions.add(this); - // user can choose upercase letters in identity name, but this has no effect on the - // database queries, the login form or the IM account. IM works only with lowercase - // characters -> map stores values as such - Tracing.logDebug("signOn() adding to userNameToIdentity: "+identity.getName().toLowerCase(), getClass()); - userNameToIdentity.add(identity.getName().toLowerCase()); - } - // load user prefs - guiPreferences = PreferencesFactory.getInstance().getPreferencesFor(identity, identityEnvironment.getRoles().isGuestOnly()); - - if (!registeredWithBus) { - // OLAT-3706 - CoordinatorManager.getInstance().getCoordinator().getEventBus().registerFor(this, null, ORES_USERSESSION); - } - - Tracing.logAudit("Logged on: " + sessionInfo.toString(), this.getClass()); - CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(new SignOnOffEvent(identity, true), ORES_USERSESSION); - - - // THE FOLLOWING CHECK MUST BE PLACED HERE NOT TO PRODUCE A DEAD-LOCK WITH SIGNOFFANDCLEAR - // check if a session from any browser was invalidated (IE has a cookie set per Browserinstance!!) - if (invalidatedSession != null || authUsersNamesOtherNodes.contains(identity.getName())) { - // put flag killed-existing-session into session-store to show info-message 'only one session for each user' on user-home screen - this.putEntry(STORE_KEY_KILLED_EXISTING_SESSION, Boolean.TRUE); - Tracing.logDebug("signOn() removing from authUsersNamesOtherNodes: "+identity.getName(), getClass()); - authUsersNamesOtherNodes.remove(identity.getName()); - //OLAT-3381 & OLAT-3382 - if(invalidatedSession != null) invalidatedSession.signOffAndClear(); - } - - // update logged in users counters - if (sessionInfo.isREST()) { - sessionCountRest.incrementAndGet(); - } else if (sessionInfo.isWebDAV()) { - sessionCountDav.incrementAndGet(); - } else { - sessionCountWeb.incrementAndGet(); - } - - Tracing.logDebug("signOn() END", getClass()); - } - - - /** - * Lookup non-webdav, non-REST UserSession for username. - * @param userName - * @return user-session or null when no session was founded. - */ - private UserSession getUserSessionFor(String userName) { - //do not call from somewhere else then signOffAndClear!! - Set<UserSession> authUserSessionsCopy = new HashSet<UserSession>(authUserSessions); - for (Iterator<UserSession> iterator = authUserSessionsCopy.iterator(); iterator.hasNext();) { - UserSession userSession = (UserSession) iterator.next(); - if (userName.equalsIgnoreCase(userSession.getIdentity().getName()) && userSession.getSessionInfo()!=null - && !userSession.getSessionInfo().isWebDAV() && !userSession.getSessionInfo().isREST() ) { - return userSession; - } - } - return null; - } - - - - /** - * @param userName - * @return the identity or null if no user with userName is currently logged - * on - */ - public static boolean isSignedOnIdentity(String userName) { - synchronized (authUserSessions) { //o_clusterOK by:fj - return userNameToIdentity.contains(userName.toLowerCase()); - } - } - - /** - * @return set of authenticated active user sessions - */ - public static Set<UserSession> getAuthenticatedUserSessions() { - Set<UserSession> copy; - synchronized (authUserSessions) { //o_clusterOK by:fj - copy = new HashSet<UserSession>(authUserSessions); - } - return copy; - } - - /** - * @see java.lang.Object#toString() - */ - public String toString() { - return "Session of " + identityEnvironment + ", " + super.toString(); - } - - /** - * @return identity environment - */ - public IdentityEnvironment getIdentityEnvironment() { - return identityEnvironment; - } - - /** - * may be null - * <p> - * @return session info object - */ - public SessionInfo getSessionInfo() { - return sessionInfo; - } - - /** - * @param sessionInfo - */ - public void setSessionInfo(SessionInfo sessionInfo) { - this.sessionInfo = sessionInfo; - } - - /** - * @return Returns the userSessionsCnt (Web, WebDAV, REST) from this VM - */ - public static int getUserSessionsCnt() { - //clusterNOK ?? return only number of locale sessions ? - return authUserSessions.size(); - } - - /** - * @return The number of users currently logged in using the web interface - * (guests and authenticated users). Note that currently this only - * returns the users from this VM as the synchronization of user - * between cluster node is not correctly. In the long run we return - * all users here. - */ - public static int getUserSessionWebCounter() { - // clusterNOK ?? return only number of locale sessions ? - return sessionCountWeb.get(); - } - - /** - * @return The number of users currently logged in using a WebDAV client. - * Note that currently this only returns the users from this VM as - * the synchronization of user between cluster node is not - * correctly. In the long run we return all users here. - */ - public static int getUserSessionDavCounter() { - // clusterNOK ?? return only number of locale sessions ? - return sessionCountDav.get(); - } - - /** - * @return The number of users currently logged in using the REST API. Note - * that currently this only returns the users from this VM as the - * synchronization of user between cluster node is not correctly. In - * the long run we return all users here. - */ - public static int getUserSessionRestCounter() { - // clusterNOK ?? return only number of locale sessions ? - return sessionCountRest.get(); - } - - /** - * @return Returns the guiPreferences. - */ - public Preferences getGuiPreferences() { - return guiPreferences; - } - - /** - * This is the olatsystembus to broadcast event amongst controllers of a single user only - * (the one whom this usersession belongs to) - * - * @return the olatsystembus for the local user - */ - public EventBus getSingleUserEventCenter() { - return singleUserSystemBus; - } - - - /** - * only for SignOffEvents - * - Usersession keeps book about usernames - * - WindowManager responsible to dispose controller chain - * @see org.olat.core.util.event.GenericEventListener#event(org.olat.core.gui.control.Event) + * only for preference changed event */ public void event(Event event) { //fxdiff FXOLAT-231: event on GUI Preferences extern changes if("preferences.changed".equals(event.getCommand())) { - Identity identity = identityEnvironment.getIdentity(); - guiPreferences = PreferencesFactory.getInstance().getPreferencesFor(identity, identityEnvironment.getRoles().isGuestOnly()); - return; - } - - Tracing.logDebug("event() START", getClass()); - SignOnOffEvent se = (SignOnOffEvent) event; - Tracing.logDebug("event() is SignOnOffEvent. isSignOn="+se.isSignOn(), getClass()); - if (!se.isEventOnThisNode()) { - // - signOnOff from other node - // - Single OLAT Instance is never passing by here. - if (se.isSignOn()) { - // it is a logged on event - // -> remember other nodes logged usernames - Tracing.logDebug("event() adding to authUsersNamesOtherNodes: "+se.getIdentityName(), getClass()); - authUsersNamesOtherNodes.add(se.getIdentityName()); - if (sessionInfo != null && se.getIdentityName().equals(sessionInfo.getLogin()) && !sessionInfo.isWebDAV() - && !this.getRoles().isGuestOnly()) { - // if this listening UserSession instance is from the same user - // and it is not a WebDAV Session, and it is not GuestSession - // => log user off on this node - this.signOffAndClearWithout(); - Tracing.logDebug("event() deregistering usersession from eventbus, id="+se.getIdentityName(), getClass()); - CoordinatorManager.getInstance().getCoordinator().getEventBus().deregisterFor(this, ORES_USERSESSION); - registeredWithBus = false; - init(); - } - } else { - // it is logged off event - // -> remove from other nodes logged on list. - Tracing.logDebug("event() removing from authUsersNamesOtherNodes: "+se.getIdentityName(), getClass()); - authUsersNamesOtherNodes.remove(se.getIdentityName()); - } + reloadPreferences(); } - Tracing.logDebug("event() END", getClass()); - } - - /** - * Invalidate all sessions except admin-sessions. - * @return Number of invalidated sessions. - */ - public static int invalidateAllSessions() { - Tracing.logDebug("invalidateAllSessions() START", UserSession.class); - int invalidateCounter = 0; - Tracing.logAudit("All sessions were invalidated by an administrator", UserSession.class); - //clusterNOK ?? invalidate only locale sessions ? - Set<UserSession> iterCopy = new HashSet<UserSession>(authUserSessions); - for (Iterator<UserSession> iterator = iterCopy.iterator(); iterator.hasNext();) { - UserSession userSession = (UserSession) iterator.next(); - Roles userRoles = userSession != null ? userSession.getRoles() : null; - if (userRoles != null && !userRoles.isOLATAdmin()) { - //do not logout administrators - try { - userSession.signOffAndClear(); - if(userSession.getSessionInfo() != null && userSession.getSessionInfo().getSession() != null) { - userSession.getSessionInfo().getSession().invalidate(); - } - invalidateCounter++; - } catch(Exception ex) { - // Session already signed off => do nothing and continues - } - } - } - Tracing.logDebug("invalidateAllSessions() END", UserSession.class); - return invalidateCounter; - } - - /** - * Invalidate a given number of oldest (last-click-time) sessions except admin-sessions. - * @param nbrSessions number of sessions whisch will be invalidated - * @return Number of invalidated sessions. - */ - public static int invalidateOldestSessions(int nbrSessions) { - int invalidateCounter = 0; - // 1. Copy authUserSessions in sorted TreeMap - // This is the Comparator that will be used to sort the TreeSet: - Comparator<UserSession> sessionComparator = new Comparator<UserSession>() { - public int compare(UserSession o1, UserSession o2) { - Long long1 = new Long((o1).getSessionInfo().getLastClickTime()); - Long long2 = new Long((o2).getSessionInfo().getLastClickTime()); - return long1.compareTo(long2); - } - }; - // clusterNOK ?? invalidate only locale sessions ? - TreeSet<UserSession> sortedSet = new TreeSet<UserSession>(sessionComparator); - sortedSet.addAll(authUserSessions); - int i = 0; - for (Iterator<UserSession> iterator = sortedSet.iterator(); iterator.hasNext() && i++<nbrSessions;) { - try { - UserSession userSession = (UserSession) iterator.next(); - if (!userSession.getRoles().isOLATAdmin() && !userSession.getSessionInfo().isWebDAV()) { - userSession.signOffAndClear(); - invalidateCounter++; - } - } catch (Throwable th) { - Tracing.logWarn("Error signOffAndClear ", th, UserSession.class); - } - } - return invalidateCounter; } /** - * set session timeout on http session - - * @param sessionTimeoutInSec + * @see java.lang.Object#toString() */ - public static void setGlobalSessionTimeout(int sessionTimeoutInSec) { - UserSession.sessionTimeoutAuthInSec = sessionTimeoutInSec; - Set<UserSession> sessionSnapShot = new HashSet<UserSession>(authUserSessions); - for (UserSession session : sessionSnapShot) { - try{ - SessionInfo sessionInfo2 = session.getSessionInfo(); - if(sessionInfo2 != null){ - sessionInfo2.getSession().setMaxInactiveInterval(sessionTimeoutInSec); - } - }catch(Throwable th){ - Tracing.logError("error setting sesssionTimeout", th, UserSession.class); - } - } + @Override + public String toString() { + return "Session of " + identityEnvironment + ", " + super.toString(); } - } \ No newline at end of file diff --git a/src/main/java/org/olat/core/util/_spring/utilCorecontext.xml b/src/main/java/org/olat/core/util/_spring/utilCorecontext.xml index 2d3765a5705..65fa87b0279 100644 --- a/src/main/java/org/olat/core/util/_spring/utilCorecontext.xml +++ b/src/main/java/org/olat/core/util/_spring/utilCorecontext.xml @@ -7,6 +7,8 @@ http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> + + <context:component-scan base-package="org.olat.core.util.session" /> <bean id="codeHelper" class="org.olat.core.util.CodeHelper" > <constructor-arg value="${node.id}" /> @@ -21,4 +23,27 @@ <bean id="imageHelperServiceProvider_java" class="org.olat.core.util.image.spi.ImageHelperImpl" /> <bean id="imageHelperServiceProvider_magick" class="org.olat.core.util.image.spi.ImageMagickHelper" /> + + <!-- Definition of the providers --> + <bean id="userSessionModule" class="org.olat.core.util.session.UserSessionModule"> + <property name="persistedProperties"> + <bean class="org.olat.core.configuration.PersistedProperties" scope="prototype" init-method="init" destroy-method="destroy" + depends-on="coordinatorManager,org.olat.core.util.WebappHelper"> + <constructor-arg index="0" ref="coordinatorManager"/> + <constructor-arg index="1" ref="userSessionModule" /> + </bean> + </property> + </bean> + + <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> + <property name="targetObject" ref="userSessionModule" /> + <property name="targetMethod" value="init" /> + <property name="arguments"> + <value> + session.timeout=${session.timeout} + </value> + </property> + </bean> + + </beans> diff --git a/src/main/java/org/olat/core/util/i18n/I18nManager.java b/src/main/java/org/olat/core/util/i18n/I18nManager.java index 31a1b3b0344..8dc2ee4ae76 100644 --- a/src/main/java/org/olat/core/util/i18n/I18nManager.java +++ b/src/main/java/org/olat/core/util/i18n/I18nManager.java @@ -59,6 +59,7 @@ import java.util.regex.Pattern; import javax.servlet.http.HttpServletRequest; +import org.olat.core.CoreSpringFactory; import org.olat.core.helpers.Settings; import org.olat.core.logging.AssertException; import org.olat.core.logging.OLATRuntimeException; @@ -74,6 +75,7 @@ import org.olat.core.util.SortedProperties; import org.olat.core.util.StringHelper; import org.olat.core.util.UserSession; import org.olat.core.util.WebappHelper; +import org.olat.core.util.session.UserSessionManager; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; @@ -1273,7 +1275,7 @@ public class I18nManager extends BasicManager { * @param hreq The http servlet request */ public static void attachI18nInfoToThread(HttpServletRequest hreq) { - UserSession usess = UserSession.getUserSession(hreq); + UserSession usess = CoreSpringFactory.getImpl(UserSessionManager.class).getUserSession(hreq); if (threadLocalLocale == null) { I18nManager.getInstance().logError("can't attach i18n info to thread: threadLocalLocale is null", null); } else { diff --git a/src/main/java/org/olat/core/util/i18n/_spring/i18nCorecontext.xml b/src/main/java/org/olat/core/util/i18n/_spring/i18nCorecontext.xml index 78ee4463fe8..0a8c43c01b3 100644 --- a/src/main/java/org/olat/core/util/i18n/_spring/i18nCorecontext.xml +++ b/src/main/java/org/olat/core/util/i18n/_spring/i18nCorecontext.xml @@ -4,11 +4,7 @@ xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans - http://www.springframework.org/schema/beans/spring-beans-3.0.xsd - http://www.springframework.org/schema/context - http://www.springframework.org/schema/context/spring-context-3.0.xsd"> - -<context:annotation-config /> + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="I18nManager" class="org.olat.core.util.i18n.I18nManager" /> diff --git a/src/main/java/org/olat/core/util/session/UserSessionManager.java b/src/main/java/org/olat/core/util/session/UserSessionManager.java new file mode 100644 index 00000000000..d2eb5b12ffc --- /dev/null +++ b/src/main/java/org/olat/core/util/session/UserSessionManager.java @@ -0,0 +1,605 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.core.util.session; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; +import java.util.concurrent.atomic.AtomicInteger; + +import javax.annotation.PostConstruct; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +import org.olat.core.gui.control.Disposable; +import org.olat.core.gui.control.Event; +import org.olat.core.id.Identity; +import org.olat.core.id.IdentityEnvironment; +import org.olat.core.id.OLATResourceable; +import org.olat.core.id.Roles; +import org.olat.core.id.context.HistoryManager; +import org.olat.core.logging.AssertException; +import org.olat.core.logging.OLog; +import org.olat.core.logging.Tracing; +import org.olat.core.logging.activity.CoreLoggingResourceable; +import org.olat.core.logging.activity.OlatLoggingAction; +import org.olat.core.logging.activity.ThreadLocalUserActivityLogger; +import org.olat.core.logging.activity.ThreadLocalUserActivityLoggerInstaller; +import org.olat.core.logging.activity.UserActivityLoggerImpl; +import org.olat.core.util.SessionInfo; +import org.olat.core.util.SignOnOffEvent; +import org.olat.core.util.StringHelper; +import org.olat.core.util.UserSession; +import org.olat.core.util.coordinate.CoordinatorManager; +import org.olat.core.util.event.GenericEventListener; +import org.olat.core.util.prefs.Preferences; +import org.olat.core.util.resource.OresHelper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * + * Initial date: 15.11.2012<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +@Service +public class UserSessionManager implements GenericEventListener { + + private static final OLog log = Tracing.createLoggerFor(UserSessionManager.class); + private static final String USERSESSIONKEY = UserSession.class.getName(); + + public static final OLATResourceable ORES_USERSESSION = OresHelper.createOLATResourceableType(UserSession.class); + public static final String STORE_KEY_KILLED_EXISTING_SESSION = "killedExistingSession"; + + //clusterNOK cache ?? + private static final Set<UserSession> authUserSessions = new HashSet<UserSession>(101); + private static final Set<String> userNameToIdentity = new HashSet<String>(101); + private static final Set<String> authUsersNamesOtherNodes = new HashSet<String>(101); + + private static final AtomicInteger sessionCountWeb = new AtomicInteger(); + private static final AtomicInteger sessionCountRest = new AtomicInteger(); + private static final AtomicInteger sessionCountDav = new AtomicInteger(); + + @Autowired + private UserSessionModule sessionModule; + @Autowired + private CoordinatorManager coordinator; + @Autowired + private HistoryManager historyManager; + + @PostConstruct + public void initBean() { + coordinator.getCoordinator().getEventBus().registerFor(this, null, ORES_USERSESSION); + } + + /** + * @param session + * @return associated user session + */ + public UserSession getUserSession(HttpSession session) { + UserSession us; + synchronized (session) {//o_clusterOK by:fj + us = (UserSession) session.getAttribute(USERSESSIONKEY); + if (us == null) { + us = new UserSession(); + session.setAttribute(USERSESSIONKEY, us); // triggers the + // valueBoundEvent -> nothing + // more to do here + } + } + //set a possible changed session timeout interval + if(us.isAuthenticated()) { + session.setMaxInactiveInterval(sessionModule.getSessionTimeoutAuthenticated()); + } else { + session.setMaxInactiveInterval(sessionModule.getSessionTimeout()); + } + return us; + } + + /** + * @param hreq + * @return associated user session + */ + public UserSession getUserSession(HttpServletRequest hreq) { + // get existing or create new session + HttpSession httpSession = hreq.getSession(true); + UserSession usess = getUserSession(httpSession); + return usess; + } + + /** + * Return the UserSession of the given request if it is already set or null otherwise + * @param hreq + * @return + */ + public UserSession getUserSessionIfAlreadySet(HttpServletRequest hreq) { + HttpSession session = hreq.getSession(false); + if (session==null) { + return null; + } + + synchronized (session) {//o_clusterOK by:se + UserSession us = (UserSession) session.getAttribute(USERSESSIONKEY); + if(us != null && us.isAuthenticated()) { + session.setMaxInactiveInterval(sessionModule.getSessionTimeoutAuthenticated()); + } else { + session.setMaxInactiveInterval(sessionModule.getSessionTimeout()); + } + return us; + } + } + + /** + * @param userName + * @return the identity or null if no user with userName is currently logged + * on + */ + public boolean isSignedOnIdentity(String userName) { + synchronized (authUserSessions) { //o_clusterOK by:fj + return userNameToIdentity.contains(userName.toLowerCase()); + } + } + + /** + * @return set of authenticated active user sessions + */ + public Set<UserSession> getAuthenticatedUserSessions() { + Set<UserSession> copy; + synchronized (authUserSessions) { //o_clusterOK by:fj + copy = new HashSet<UserSession>(authUserSessions); + } + return copy; + } + + public int getNumberOfAuthenticatedUserSessions() { + synchronized(authUserSessions) { + return authUserSessions.size(); + } + } + + /** + * @return Returns the userSessionsCnt (Web, WebDAV, REST) from this VM + */ + public int getUserSessionsCnt() { + //clusterNOK ?? return only number of locale sessions ? + synchronized(authUserSessions) { + return authUserSessions.size(); + } + } + + /** + * @return The number of users currently logged in using the web interface + * (guests and authenticated users). Note that currently this only + * returns the users from this VM as the synchronization of user + * between cluster node is not correctly. In the long run we return + * all users here. + */ + public int getUserSessionWebCounter() { + // clusterNOK ?? return only number of locale sessions ? + return sessionCountWeb.get(); + } + + /** + * @return The number of users currently logged in using a WebDAV client. + * Note that currently this only returns the users from this VM as + * the synchronization of user between cluster node is not + * correctly. In the long run we return all users here. + */ + public int getUserSessionDavCounter() { + // clusterNOK ?? return only number of locale sessions ? + return sessionCountDav.get(); + } + + /** + * @return The number of users currently logged in using the REST API. Note + * that currently this only returns the users from this VM as the + * synchronization of user between cluster node is not correctly. In + * the long run we return all users here. + */ + public int getUserSessionRestCounter() { + // clusterNOK ?? return only number of locale sessions ? + return sessionCountRest.get(); + } + + + + /** + * prior to calling this method, all instance vars must be set. + */ + public synchronized void signOn(UserSession usess) { + // ^^^^^^^^^^^^ Added synchronized to be symmetric with sign off and to + // fix a possible dead-lock see also OLAT-3390 + + boolean isDebug = log.isDebug(); + if(isDebug) log.debug("signOn() START"); + if (usess.isAuthenticated()) { + throw new AssertException("sign on: already signed on!"); + } + + IdentityEnvironment identityEnvironment = usess.getIdentityEnvironment(); + Identity identity = identityEnvironment.getIdentity(); + if (identity == null) { + throw new AssertException("identity is null in identityEnvironment!"); + } + SessionInfo sessionInfo = usess.getSessionInfo(); + if (sessionInfo == null) { + throw new AssertException("sessionInfo was null for identity " + identity); + } + //String login = identity.getName(); + usess.setAuthenticated(true); + + if (sessionInfo.isWebDAV()) { + // load user prefs + usess.reloadPreferences(); + synchronized (authUserSessions) { //o_clusterOK by:se + // we're only adding this webdav session to the authUserSessions - not to the userNameToIdentity. + // userNameToIdentity is only needed for IM which can't do anything with a webdav session + authUserSessions.add(usess); + } + log.audit("Logged on [via webdav]: " + sessionInfo.toString()); + } else { + + if(isDebug) log.debug("signOn() authUsersNamesOtherNodes.contains "+identity.getName()+": "+authUsersNamesOtherNodes.contains(identity.getName())); + + UserSession invalidatedSession = null; + synchronized (authUserSessions) { //o_clusterOK by:fj + // check if already a session exist for this user + if ( (userNameToIdentity.contains(identity.getName().toLowerCase()) || authUsersNamesOtherNodes.contains(identity.getName()) ) + && !sessionInfo.isWebDAV() && !sessionInfo.isREST() && !usess.getRoles().isGuestOnly()) { + log.info("Loggin-process II: User has already a session => signOffAndClear existing session"); + + invalidatedSession = getUserSessionForGui(identity.getName().toLowerCase()); + //remove session to be invalidated + //SIDEEFFECT!! to signOffAndClear + //if invalidatedSession is removed from authUserSessions + //signOffAndClear does not remove the identity.getName().toLowerCase() from the userNameToIdentity + // + authUserSessions.remove(invalidatedSession); + } + authUserSessions.add(usess); + // user can choose upercase letters in identity name, but this has no effect on the + // database queries, the login form or the IM account. IM works only with lowercase + // characters -> map stores values as such + if(isDebug) log.debug("signOn() adding to userNameToIdentity: "+identity.getName().toLowerCase()); + userNameToIdentity.add(identity.getName().toLowerCase()); + } + + //reload user prefs + usess.reloadPreferences(); + + log.audit("Logged on: " + sessionInfo.toString()); + CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(new SignOnOffEvent(identity, true), ORES_USERSESSION); + + // THE FOLLOWING CHECK MUST BE PLACED HERE NOT TO PRODUCE A DEAD-LOCK WITH SIGNOFFANDCLEAR + // check if a session from any browser was invalidated (IE has a cookie set per Browserinstance!!) + if (invalidatedSession != null || authUsersNamesOtherNodes.contains(identity.getName())) { + // put flag killed-existing-session into session-store to show info-message 'only one session for each user' on user-home screen + usess.putEntry(STORE_KEY_KILLED_EXISTING_SESSION, Boolean.TRUE); + if(isDebug) log.debug("signOn() removing from authUsersNamesOtherNodes: "+identity.getName()); + authUsersNamesOtherNodes.remove(identity.getName()); + //OLAT-3381 & OLAT-3382 + if(invalidatedSession != null) { + signOffAndClear(invalidatedSession); + } + } + + if(isDebug) log.debug("signOn() END"); + } + + // update logged in users counters + if (sessionInfo.isREST()) { + sessionCountRest.incrementAndGet(); + } else if (sessionInfo.isWebDAV()) { + sessionCountDav.incrementAndGet(); + } else { + sessionCountWeb.incrementAndGet(); + } + } + + /** + * called to make sure the current authenticated user (if there is one at all) + * is cleared and signed off. This method is firing the SignOnOffEvent Multiuserevent. + */ + public synchronized void signOffAndClear(UserSession usess) { //o_clusterOK by:fj + boolean isDebug = log.isDebug(); + if(isDebug) log.debug("signOffAndClear() START"); + // + + signOffAndClearWithout(usess); + // handle safely + try { + if (usess.isAuthenticated()) { + SessionInfo sessionInfo = usess.getSessionInfo(); + IdentityEnvironment identityEnvironment = usess.getIdentityEnvironment(); + Identity identity = identityEnvironment.getIdentity(); + log.audit("Logged off: " + sessionInfo); + CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(new SignOnOffEvent(identity, false), ORES_USERSESSION); + if(isDebug) log.debug("signOffAndClear() deregistering usersession from eventbus, id="+sessionInfo); + //fxdiff FXOLAT-231: event on GUI Preferences extern changes + OLATResourceable ores = OresHelper.createOLATResourceableInstance(Preferences.class, identity.getKey()); + CoordinatorManager.getInstance().getCoordinator().getEventBus().deregisterFor(usess, ores); + } + } catch (Exception e) { + log.error("exception in signOffAndClear: while sending signonoffevent!", e); + } + // clear all instance variables, set authenticated to false + usess.init(); + if(isDebug) log.debug("signOffAndClear() END"); + } + + + /** + * called from signOffAndClear() + * called from event -> MUEvent + * the real work to do during sign off but without sending the multiuserevent + * this is used in case the user logs in to node1 and was logged in on node2 => + * node2 catches the sign on event and invalidates the user on node2 "silently", e.g. + * without firing an event. + */ + public void signOffAndClearWithout(final UserSession usess) { + boolean isDebug = log.isDebug(); + if(isDebug) log.debug("signOffAndClearWithout() START"); + + final IdentityEnvironment identityEnvironment = usess.getIdentityEnvironment(); + final SessionInfo sessionInfo = usess.getSessionInfo(); + final Identity ident = identityEnvironment.getIdentity(); + if (isDebug) log.debug("UserSession:::logging off: " + sessionInfo); + + //fxdiff BAKS-7 Resume function + if(usess.isAuthenticated() && usess.getLastHistoryPoint() != null && !usess.getRoles().isGuestOnly()) { + historyManager.persistHistoryPoint(ident, usess.getLastHistoryPoint()); + } + + /** + * use not RunnableWithException, as exceptionHandlng is inside the run + */ + Runnable run = new Runnable() { + public void run() { + Object obj = null; + try { + // do logging + if (ident != null) { + ThreadLocalUserActivityLogger.log(OlatLoggingAction.OLAT_LOGOUT, UserSession.class, CoreLoggingResourceable.wrap(ident)); + } else { + //System.out.println("identity is null!!!!!!!!!!!!!!!!!!!!!"); + } + // notify all variables in the store (the values) about the disposal + // if + // Disposable + List<Object> storeList = new ArrayList<Object>(usess.getStore().values()); + + for (Iterator<Object> it_storevals = storeList.iterator(); it_storevals.hasNext();) { + obj = it_storevals.next(); + if (obj instanceof Disposable) { + // synchronous, since triggered by tomcat session timeout or user + // click and + // asynchronous, if kicked out by administrator. + // we assume synchronous + // !!!! + // As a reminder, this .dispose() calls dispose on + // DefaultController which is synchronized. + // (Windows/WindowManagerImpl/WindowBackOfficeImpl/BaseChiefController/../ + // dispose() + // !!!! was important for bug OLAT-3390 + + ((Disposable) obj).dispose(); + } + } + } catch (Exception e) { + + String objtostr = "n/a"; + try { + objtostr = obj.toString(); + } catch (Exception ee) { + // ignore + } + log.error("exception in signOffAndClear: while disposing object:" + objtostr, e); + } + } + }; + + ThreadLocalUserActivityLoggerInstaller.runWithUserActivityLogger(run, UserActivityLoggerImpl.newLoggerForValueUnbound(usess)); + + synchronized (authUserSessions) { //o_clusterOK by:fj + if(authUserSessions.remove(usess)){ + //remove only from identityEnvironment if found in sessions. + //see also SIDEEFFECT!! line in signOn(..) + Identity previousSignedOn = identityEnvironment.getIdentity(); + if (previousSignedOn != null) { + if(isDebug) log.debug("signOffAndClearWithout() removing from userNameToIdentity: "+previousSignedOn.getName().toLowerCase()); + userNameToIdentity.remove(previousSignedOn.getName().toLowerCase()); + } + } else if (isDebug) { + log.info("UserSession already removed! for ["+ident+"]"); + } + } + // update logged in users counters + if (sessionInfo != null) { + if (sessionInfo.isREST()) { + sessionCountRest.decrementAndGet(); + } else if (sessionInfo.isWebDAV()) { + sessionCountDav.decrementAndGet(); + } else { + sessionCountWeb.decrementAndGet(); + } + } + + if (isDebug) log.debug("signOffAndClearWithout() END"); + } + + /** + * only for SignOffEvents + * - Usersession keeps book about usernames + * - WindowManager responsible to dispose controller chain + * @see org.olat.core.util.event.GenericEventListener#event(org.olat.core.gui.control.Event) + */ + public void event(Event event) { + if(event instanceof SignOnOffEvent) { + SignOnOffEvent se = (SignOnOffEvent) event; + processSignOnOffEvent(se); + } + } + + private void processSignOnOffEvent(SignOnOffEvent se) { + try { + boolean debug = log.isDebug(); + if(debug) log.debug("event() START"); + if(debug) log.debug("event() is SignOnOffEvent. isSignOn="+se.isSignOn()); + if (!se.isEventOnThisNode()) { + // - signOnOff from other node + // - Single OLAT Instance is never passing by here. + if (se.isSignOn()) { + // it is a logged on event + // -> remember other nodes logged usernames + if(debug) log.debug("event() adding to authUsersNamesOtherNodes: "+se.getIdentityName()); + authUsersNamesOtherNodes.add(se.getIdentityName()); + UserSession usess = getUserSessionForGui(se.getIdentityName()); + if (usess.getSessionInfo() != null && se.getIdentityName().equals(usess.getSessionInfo().getLogin()) + && !usess.getSessionInfo().isWebDAV() && !usess.getRoles().isGuestOnly()) { + + // if this listening UserSession instance is from the same user + // and it is not a WebDAV Session, and it is not GuestSession + // => log user off on this node + signOffAndClearWithout(usess); + usess.init(); + } + } else { + // it is logged off event + // -> remove from other nodes logged on list. + if(debug) log.debug("event() removing from authUsersNamesOtherNodes: "+se.getIdentityName()); + authUsersNamesOtherNodes.remove(se.getIdentityName()); + } + } + if(debug) log.debug("event() END"); + } catch (Exception e) { + log.error("", e); + } + } + + /** + * Invalidate all sessions except admin-sessions. + * @return Number of invalidated sessions. + */ + public int invalidateAllSessions() { + log.debug("invalidateAllSessions() START"); + int invalidateCounter = 0; + log.audit("All sessions were invalidated by an administrator"); + //clusterNOK ?? invalidate only locale sessions ? + Set<UserSession> iterCopy = getAuthenticatedUserSessions(); + for (Iterator<UserSession> iterator = iterCopy.iterator(); iterator.hasNext();) { + UserSession userSession = iterator.next(); + Roles userRoles = userSession != null ? userSession.getRoles() : null; + if (userRoles != null && !userRoles.isOLATAdmin()) { + //do not logout administrators + try { + signOffAndClear(userSession); + if(userSession.getSessionInfo() != null && userSession.getSessionInfo().getSession() != null) { + userSession.getSessionInfo().getSession().invalidate(); + } + invalidateCounter++; + } catch(Exception ex) { + // Session already signed off => do nothing and continues + } + } + } + log.debug("invalidateAllSessions() END"); + return invalidateCounter; + } + + /** + * Invalidate a given number of oldest (last-click-time) sessions except admin-sessions. + * @param nbrSessions number of sessions whisch will be invalidated + * @return Number of invalidated sessions. + */ + public int invalidateOldestSessions(int nbrSessions) { + int invalidateCounter = 0; + // 1. Copy authUserSessions in sorted TreeMap + // This is the Comparator that will be used to sort the TreeSet: + Comparator<UserSession> sessionComparator = new Comparator<UserSession>() { + public int compare(UserSession o1, UserSession o2) { + Long long1 = new Long((o1).getSessionInfo().getLastClickTime()); + Long long2 = new Long((o2).getSessionInfo().getLastClickTime()); + return long1.compareTo(long2); + } + }; + // clusterNOK ?? invalidate only locale sessions ? + TreeSet<UserSession> sortedSet = new TreeSet<UserSession>(sessionComparator); + sortedSet.addAll(authUserSessions); + int i = 0; + for (Iterator<UserSession> iterator = sortedSet.iterator(); iterator.hasNext() && i++<nbrSessions;) { + try { + UserSession userSession = (UserSession) iterator.next(); + if (!userSession.getRoles().isOLATAdmin() && !userSession.getSessionInfo().isWebDAV()) { + signOffAndClear(userSession); + invalidateCounter++; + } + } catch (Throwable th) { + log.warn("Error signOffAndClear ", th); + } + } + return invalidateCounter; + } + + /** + * set session timeout on http session - + * @param sessionTimeoutInSec + */ + public void setGlobalSessionTimeout(int sessionTimeoutInSec) { + Collection<UserSession> sessionSnapShot = getAuthenticatedUserSessions(); + for (UserSession session : sessionSnapShot) { + try{ + SessionInfo sessionInfo = session.getSessionInfo(); + if(sessionInfo != null && sessionInfo.getSession() != null) { + sessionInfo.getSession().setMaxInactiveInterval(sessionTimeoutInSec); + } + } catch(Throwable th){ + log.error("error setting sesssionTimeout", th); + } + } + } + + /** + * Lookup non-webdav, non-REST UserSession for username. + * @param userName + * @return user-session or null when no session was founded. + */ + private UserSession getUserSessionForGui(String userName) { + if(StringHelper.containsNonWhitespace(userName)) { + //do not call from somewhere else then signOffAndClear!! + Collection<UserSession> authUserSessionsCopy = getAuthenticatedUserSessions(); + for (UserSession userSession : authUserSessionsCopy) { + Identity identity = userSession.getIdentity(); + if (identity != null && userName.equalsIgnoreCase(identity.getName()) + && userSession.getSessionInfo() != null + && !userSession.getSessionInfo().isWebDAV() + && !userSession.getSessionInfo().isREST()) { + return userSession; + } + } + } + return null; + } +} diff --git a/src/main/java/org/olat/core/util/session/UserSessionModule.java b/src/main/java/org/olat/core/util/session/UserSessionModule.java new file mode 100644 index 00000000000..6294d0e6c60 --- /dev/null +++ b/src/main/java/org/olat/core/util/session/UserSessionModule.java @@ -0,0 +1,85 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.core.util.session; + +import org.olat.core.configuration.AbstractOLATModule; +import org.olat.core.configuration.PersistedProperties; +import org.olat.core.util.StringHelper; + +/** + * + * Initial date: 15.11.2012<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class UserSessionModule extends AbstractOLATModule { + + + private static final String SESSION_TIMEOUT = "session.timeout"; + private static final String SESSION_TIMEOUT_AUTH = "session.timeout.authenticated"; + + private int sessionTimeout; + private int sessionTimeoutAuthenticated; + + @Override + public void init() { + String timeoutObj = getStringPropertyValue(SESSION_TIMEOUT, true); + if(StringHelper.isLong(timeoutObj)) { + sessionTimeout = Integer.parseInt(timeoutObj); + } + + String timeoutAuthObj = getStringPropertyValue(SESSION_TIMEOUT_AUTH, true); + if(StringHelper.isLong(timeoutAuthObj)) { + sessionTimeoutAuthenticated = Integer.parseInt(timeoutAuthObj); + } + } + + @Override + protected void initDefaultProperties() { + sessionTimeout = getIntConfigParameter(SESSION_TIMEOUT, 7200); + sessionTimeoutAuthenticated = getIntConfigParameter(SESSION_TIMEOUT_AUTH, 300); + } + + @Override + protected void initFromChangedProperties() { + init(); + } + + @Override + public void setPersistedProperties(PersistedProperties persistedProperties) { + this.moduleConfigProperties = persistedProperties; + } + + public int getSessionTimeout() { + return sessionTimeout; + } + + public void setSessionTimeout(int timeout) { + setStringProperty(SESSION_TIMEOUT, Integer.toString(timeout), true); + } + + public int getSessionTimeoutAuthenticated() { + return sessionTimeoutAuthenticated; + } + + public void setSessionTimeoutAuthenticated(int timeout) { + setStringProperty(SESSION_TIMEOUT_AUTH, Integer.toString(timeout), true); + } +} diff --git a/src/main/java/org/olat/core/util/vfs/version/_spring/versioningCorecontext.xml b/src/main/java/org/olat/core/util/vfs/version/_spring/versioningCorecontext.xml index c432fde1c62..8a98892bab6 100644 --- a/src/main/java/org/olat/core/util/vfs/version/_spring/versioningCorecontext.xml +++ b/src/main/java/org/olat/core/util/vfs/version/_spring/versioningCorecontext.xml @@ -1,14 +1,9 @@ <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans - http://www.springframework.org/schema/beans/spring-beans-3.0.xsd - http://www.springframework.org/schema/context - http://www.springframework.org/schema/context/spring-context-3.0.xsd"> - -<context:annotation-config /> + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="versionsManager" class="org.olat.core.util.vfs.version.VersionsFileManager" init-method="init"/> diff --git a/src/main/java/org/olat/course/assessment/_spring/assessmentContext.xml b/src/main/java/org/olat/course/assessment/_spring/assessmentContext.xml index 4ae1eaae9fc..dd912adf960 100644 --- a/src/main/java/org/olat/course/assessment/_spring/assessmentContext.xml +++ b/src/main/java/org/olat/course/assessment/_spring/assessmentContext.xml @@ -7,8 +7,7 @@ http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> - - <context:annotation-config /> + <context:component-scan base-package="org.olat.course.assessment.manager" /> <bean id="assessmentModule" class="org.olat.course.assessment.AssessmentModule" init-method="init" destroy-method="destroy" > diff --git a/src/main/java/org/olat/course/nodes/_spring/buildingblockContext.xml b/src/main/java/org/olat/course/nodes/_spring/buildingblockContext.xml index 9f3b10fd03d..e6f97e846bc 100644 --- a/src/main/java/org/olat/course/nodes/_spring/buildingblockContext.xml +++ b/src/main/java/org/olat/course/nodes/_spring/buildingblockContext.xml @@ -8,7 +8,6 @@ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> - <context:annotation-config /> <context:component-scan base-package="org.olat.course.nodes.en" /> <!-- Course node spring config: Course Nodes are searched on the whole classpath, just place your CourceNodeConfiguration somewhere diff --git a/src/main/java/org/olat/dispatcher/AuthenticatedDispatcher.java b/src/main/java/org/olat/dispatcher/AuthenticatedDispatcher.java index 4a6774b159e..9261ee87523 100644 --- a/src/main/java/org/olat/dispatcher/AuthenticatedDispatcher.java +++ b/src/main/java/org/olat/dispatcher/AuthenticatedDispatcher.java @@ -33,6 +33,7 @@ import javax.servlet.http.HttpSession; import org.olat.NewControllerFactory; import org.olat.basesecurity.AuthHelper; +import org.olat.core.CoreSpringFactory; import org.olat.core.dispatcher.Dispatcher; import org.olat.core.dispatcher.DispatcherAction; import org.olat.core.gui.UserRequest; @@ -50,6 +51,7 @@ import org.olat.core.util.URIHelper; import org.olat.core.util.UserSession; import org.olat.core.util.i18n.I18nManager; import org.olat.core.util.i18n.I18nModule; +import org.olat.core.util.session.UserSessionManager; import org.olat.core.util.threadlog.UserBasedLogLevelManager; import org.olat.login.LoginModule; @@ -89,7 +91,7 @@ public class AuthenticatedDispatcher implements Dispatcher { if ( log.isDebug() ) { startExecute = System.currentTimeMillis(); } - UserSession usess = UserSession.getUserSession(request); + UserSession usess = CoreSpringFactory.getImpl(UserSessionManager.class).getUserSession(request); UserRequest ureq = null; try{ //upon creation URL is checked for diff --git a/src/main/java/org/olat/dispatcher/DMZDispatcher.java b/src/main/java/org/olat/dispatcher/DMZDispatcher.java index 38c7888f07e..7244e8cfe8c 100644 --- a/src/main/java/org/olat/dispatcher/DMZDispatcher.java +++ b/src/main/java/org/olat/dispatcher/DMZDispatcher.java @@ -33,6 +33,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.olat.basesecurity.AuthHelper; +import org.olat.core.CoreSpringFactory; import org.olat.core.dispatcher.Dispatcher; import org.olat.core.dispatcher.DispatcherAction; import org.olat.core.gui.UserRequest; @@ -48,6 +49,7 @@ import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; import org.olat.core.util.UserSession; import org.olat.core.util.i18n.I18nManager; +import org.olat.core.util.session.UserSessionManager; /** * Initial Date: 28.11.2003 @@ -268,7 +270,7 @@ public class DMZDispatcher implements Dispatcher { // the log-in link in the -same- browser window -> // -> there is no window -> create a new one window = null; - usess.signOffAndClear(); + CoreSpringFactory.getImpl(UserSessionManager.class).signOffAndClear(usess); usess.setLocale(LocaleNegotiator.getPreferedLocale(ureq)); I18nManager.updateLocaleInfoToThread(usess);//update locale infos @@ -280,7 +282,7 @@ public class DMZDispatcher implements Dispatcher { } else { // e.g. /dmz/ -> start screen, clear previous session data window = null; - usess.signOffAndClear(); + CoreSpringFactory.getImpl(UserSessionManager.class).signOffAndClear(usess); usess.setLocale(LocaleNegotiator.getPreferedLocale(ureq)); I18nManager.updateLocaleInfoToThread(usess);//update locale infos // request new windows since it is a new usersession, the old one was purged diff --git a/src/main/java/org/olat/dispatcher/RESTDispatcher.java b/src/main/java/org/olat/dispatcher/RESTDispatcher.java index 1afa78dda67..954b2efe309 100644 --- a/src/main/java/org/olat/dispatcher/RESTDispatcher.java +++ b/src/main/java/org/olat/dispatcher/RESTDispatcher.java @@ -52,6 +52,7 @@ import org.olat.core.util.UserSession; import org.olat.core.util.WebappHelper; import org.olat.core.util.i18n.I18nManager; import org.olat.core.util.i18n.I18nModule; +import org.olat.core.util.session.UserSessionManager; import org.olat.login.LoginModule; import org.olat.restapi.security.RestSecurityBean; import org.olat.restapi.security.RestSecurityHelper; @@ -133,7 +134,7 @@ public class RESTDispatcher implements Dispatcher { // // create the olat ureq and get an associated main window to spawn the "tab" // - UserSession usess = UserSession.getUserSession(request); + UserSession usess = CoreSpringFactory.getImpl(UserSessionManager.class).getUserSession(request); UserRequest ureq = null; try { //upon creation URL is checked for diff --git a/src/main/java/org/olat/dispatcher/RedirectToAutoGuestLoginDispatcher.java b/src/main/java/org/olat/dispatcher/RedirectToAutoGuestLoginDispatcher.java index 85813fa24c4..ae2f006fdae 100644 --- a/src/main/java/org/olat/dispatcher/RedirectToAutoGuestLoginDispatcher.java +++ b/src/main/java/org/olat/dispatcher/RedirectToAutoGuestLoginDispatcher.java @@ -28,6 +28,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.olat.basesecurity.AuthHelper; +import org.olat.core.CoreSpringFactory; import org.olat.core.dispatcher.Dispatcher; import org.olat.core.dispatcher.DispatcherAction; import org.olat.core.gui.UserRequest; @@ -35,9 +36,11 @@ import org.olat.core.gui.Windows; import org.olat.core.gui.components.Window; import org.olat.core.gui.control.ChiefController; import org.olat.core.logging.AssertException; +import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; import org.olat.core.util.UserSession; import org.olat.core.util.i18n.I18nManager; +import org.olat.core.util.session.UserSessionManager; /** * Description:<br> @@ -53,12 +56,14 @@ import org.olat.core.util.i18n.I18nManager; * @author Lars Eberle (<a href="http://www.bps-system.de/">BPS Bildungsportal Sachsen GmbH</a>) */ public class RedirectToAutoGuestLoginDispatcher implements Dispatcher { + + private static final OLog log = Tracing.createLoggerFor(RedirectToAutoGuestLoginDispatcher.class); /** * @see org.olat.core.dispatcher.Dispatcher#execute(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.String) */ public void execute(HttpServletRequest request, HttpServletResponse response, String uriPrefix) { - UserSession usess = UserSession.getUserSession(request); + UserSession usess = CoreSpringFactory.getImpl(UserSessionManager.class).getUserSession(request); UserRequest ureq = null; try{ //upon creation URL is checked for @@ -70,8 +75,8 @@ public class RedirectToAutoGuestLoginDispatcher implements Dispatcher { //or authors copy-pasted links to the content. //showing redscreens for non valid URL is wrong instead //a 404 message must be shown -> e.g. robots correct their links. - if(Tracing.isDebugEnabled(RedirectToAutoGuestLoginDispatcher.class)){ - Tracing.logDebug("Bad Request "+request.getPathInfo(), this.getClass()); + if(log.isDebug()){ + log.debug("Bad Request "+request.getPathInfo()); } DispatcherAction.sendBadRequest(request.getPathInfo(), response); return; diff --git a/src/main/java/org/olat/group/_spring/businessGroupContext.xml b/src/main/java/org/olat/group/_spring/businessGroupContext.xml index 8d904c4e4f1..ff939db14e6 100644 --- a/src/main/java/org/olat/group/_spring/businessGroupContext.xml +++ b/src/main/java/org/olat/group/_spring/businessGroupContext.xml @@ -11,7 +11,6 @@ http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> - <context:annotation-config /> <context:component-scan base-package="org.olat.group.manager,org.olat.group.area,org.olat.group.right" /> <tx:annotation-driven transaction-manager="txManager"/> diff --git a/src/main/java/org/olat/ims/qti/QTIStaticsHandler.java b/src/main/java/org/olat/ims/qti/QTIStaticsHandler.java index f7043ead309..7ab53f153d9 100644 --- a/src/main/java/org/olat/ims/qti/QTIStaticsHandler.java +++ b/src/main/java/org/olat/ims/qti/QTIStaticsHandler.java @@ -31,8 +31,9 @@ import javax.servlet.http.HttpServletRequest; import org.olat.commons.servlets.pathhandlers.FilePathHandler; import org.olat.commons.servlets.util.ResourceDescriptor; +import org.olat.core.CoreSpringFactory; import org.olat.core.commons.modules.bc.FolderConfig; -import org.olat.core.util.UserSession; +import org.olat.core.util.session.UserSessionManager; /** * Initial Date: 16.06.2003 @@ -61,7 +62,7 @@ public class QTIStaticsHandler extends FilePathHandler { } public ResourceDescriptor getResourceDescriptor(HttpServletRequest request, String relPath) { - if (UserSession.getUserSession(request).isAuthenticated()) { + if (CoreSpringFactory.getImpl(UserSessionManager.class).getUserSession(request).isAuthenticated()) { if (relPath.endsWith("qti.xml")) return null; return super.getResourceDescriptor(request, relPath); } else diff --git a/src/main/java/org/olat/instantMessaging/_spring/instantMessagingContext.xml b/src/main/java/org/olat/instantMessaging/_spring/instantMessagingContext.xml index 35929316a69..035d5b30fb0 100644 --- a/src/main/java/org/olat/instantMessaging/_spring/instantMessagingContext.xml +++ b/src/main/java/org/olat/instantMessaging/_spring/instantMessagingContext.xml @@ -8,7 +8,6 @@ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> -<context:annotation-config /> <context:component-scan base-package="org.olat.instantMessaging" /> <bean id="instantMessagingModule" class="org.olat.instantMessaging.InstantMessagingModule" diff --git a/src/main/java/org/olat/instantMessaging/rosterandchat/ChangePresenceJob.java b/src/main/java/org/olat/instantMessaging/rosterandchat/ChangePresenceJob.java index a522d161fe4..3d1b478ee37 100644 --- a/src/main/java/org/olat/instantMessaging/rosterandchat/ChangePresenceJob.java +++ b/src/main/java/org/olat/instantMessaging/rosterandchat/ChangePresenceJob.java @@ -25,16 +25,17 @@ */ package org.olat.instantMessaging.rosterandchat; -import java.util.ArrayList; +import java.util.Collection; import java.util.Iterator; -import java.util.List; import javax.servlet.http.HttpSession; import org.jivesoftware.smack.packet.Presence; +import org.olat.core.CoreSpringFactory; import org.olat.core.commons.scheduler.JobWithDB; import org.olat.core.util.SessionInfo; import org.olat.core.util.UserSession; +import org.olat.core.util.session.UserSessionManager; import org.olat.instantMessaging.ClientManager; import org.olat.instantMessaging.InstantMessagingClient; import org.olat.instantMessaging.InstantMessagingModule; @@ -65,8 +66,8 @@ public class ChangePresenceJob extends JobWithDB { try{ Long timeNow = System.currentTimeMillis(); - List<UserSession> authUserSessions = new ArrayList<UserSession>(UserSession.getAuthenticatedUserSessions()); - + UserSessionManager sessionManager = CoreSpringFactory.getImpl(UserSessionManager.class); + Collection<UserSession> authUserSessions = sessionManager.getAuthenticatedUserSessions(); for (Iterator<UserSession> iter = authUserSessions.iterator(); iter.hasNext();) { UserSession session = iter.next(); long lastAccessTime = 0; @@ -184,9 +185,6 @@ public class ChangePresenceJob extends JobWithDB { // Initialize static value only once because setInitialAutoLogOutCutTime is called at each ChangePresenceJob-run if (!initializedAutoLogOutCutTime) { autoLogOutCutTime = initialAutoLogOutCutTime; - // init GlobalSessionTimeout used by tomcat for session-timeout - int sessionTimeoutSeconds = Math.round((ChangePresenceJob.getAutoLogOutCutTimeValue() / 1000)); - UserSession.setGlobalSessionTimeout(sessionTimeoutSeconds); initializedAutoLogOutCutTime = true; } } diff --git a/src/main/java/org/olat/instantMessaging/ui/ConnectedUsersLocal.java b/src/main/java/org/olat/instantMessaging/ui/ConnectedUsersLocal.java index b554d915492..09efdcd31f4 100644 --- a/src/main/java/org/olat/instantMessaging/ui/ConnectedUsersLocal.java +++ b/src/main/java/org/olat/instantMessaging/ui/ConnectedUsersLocal.java @@ -32,6 +32,7 @@ import java.util.Map; import java.util.Set; import org.olat.basesecurity.BaseSecurityManager; +import org.olat.core.CoreSpringFactory; import org.olat.core.id.Identity; import org.olat.core.id.UserConstants; import org.olat.core.logging.AssertException; @@ -40,6 +41,7 @@ import org.olat.core.logging.Tracing; import org.olat.core.util.UserSession; import org.olat.core.util.cache.n.CacheWrapper; import org.olat.core.util.coordinate.CoordinatorManager; +import org.olat.core.util.session.UserSessionManager; import org.olat.instantMessaging.ClientHelper; import org.olat.instantMessaging.ImPreferences; import org.olat.instantMessaging.ImPrefsManager; @@ -56,7 +58,7 @@ import org.olat.instantMessaging.syncservice.InstantMessagingSessionItems; */ public class ConnectedUsersLocal implements InstantMessagingSessionItems { - OLog log = Tracing.createLoggerFor(this.getClass()); + private static final OLog log = Tracing.createLoggerFor(ConnectedUsersLocal.class); private CacheWrapper sessionItemsCache; private ImPrefsManager imPrefsManager; @@ -85,10 +87,12 @@ public class ConnectedUsersLocal implements InstantMessagingSessionItems { } } + UserSessionManager sessionManager = CoreSpringFactory.getImpl(UserSessionManager.class); + List<ConnectedUsersListEntry> entries = new ArrayList<ConnectedUsersListEntry>(); Map<String, Long> lastActivity = new HashMap<String, Long>(); Set<String> usernames = InstantMessagingModule.getAdapter().getUsernamesFromConnectedUsers(); - Set<UserSession> authSessions = UserSession.getAuthenticatedUserSessions(); + Set<UserSession> authSessions = sessionManager.getAuthenticatedUserSessions(); for (Iterator<UserSession> iter = authSessions.iterator(); iter.hasNext();) { UserSession userSession = iter.next(); long lastAccTime = 0; @@ -113,7 +117,7 @@ public class ConnectedUsersLocal implements InstantMessagingSessionItems { } else { //item not in cache - if (UserSession.isSignedOnIdentity(olatusername)) { + if (sessionManager.isSignedOnIdentity(olatusername)) { Identity identity = (Identity)BaseSecurityManager.getInstance().findIdentityByName(olatusername); try { ImPreferences imPrefs = imPrefsManager.loadOrCreatePropertiesFor(identity); diff --git a/src/main/java/org/olat/modules/_spring/modulesContext.xml b/src/main/java/org/olat/modules/_spring/modulesContext.xml index 692bd7b7a0e..f692e52196c 100644 --- a/src/main/java/org/olat/modules/_spring/modulesContext.xml +++ b/src/main/java/org/olat/modules/_spring/modulesContext.xml @@ -8,7 +8,6 @@ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> -<context:annotation-config /> <context:component-scan base-package="org.olat.modules" /> </beans> \ No newline at end of file diff --git a/src/main/java/org/olat/modules/openmeetings/_spring/openmeetingsContext.xml b/src/main/java/org/olat/modules/openmeetings/_spring/openmeetingsContext.xml index 03a68d2c1a4..12b6d4b6e31 100644 --- a/src/main/java/org/olat/modules/openmeetings/_spring/openmeetingsContext.xml +++ b/src/main/java/org/olat/modules/openmeetings/_spring/openmeetingsContext.xml @@ -8,7 +8,6 @@ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> - <context:annotation-config /> <context:component-scan base-package="org.olat.modules.openmeetings" /> <!-- Definition of the providers --> diff --git a/src/main/java/org/olat/modules/vitero/_spring/viteroContext.xml b/src/main/java/org/olat/modules/vitero/_spring/viteroContext.xml index 030d85e263b..ba56bf2cd65 100644 --- a/src/main/java/org/olat/modules/vitero/_spring/viteroContext.xml +++ b/src/main/java/org/olat/modules/vitero/_spring/viteroContext.xml @@ -8,7 +8,6 @@ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> - <context:annotation-config /> <context:component-scan base-package="org.olat.modules.vitero" /> <!-- Definition of the providers --> diff --git a/src/main/java/org/olat/resource/accesscontrol/_spring/acContext.xml b/src/main/java/org/olat/resource/accesscontrol/_spring/acContext.xml index 09aa3ba915f..4c4303e5219 100644 --- a/src/main/java/org/olat/resource/accesscontrol/_spring/acContext.xml +++ b/src/main/java/org/olat/resource/accesscontrol/_spring/acContext.xml @@ -10,7 +10,6 @@ http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> - <context:annotation-config /> <context:component-scan base-package="org.olat.resource.accesscontrol" /> <bean id="acModule" class="org.olat.resource.accesscontrol.AccessControlModule" depends-on="org.olat.core.util.WebappHelper"> diff --git a/src/main/java/org/olat/resource/accesscontrol/provider/paypal/ui/PaypalMapper.java b/src/main/java/org/olat/resource/accesscontrol/provider/paypal/ui/PaypalMapper.java index 6395759377a..96909b02fd2 100644 --- a/src/main/java/org/olat/resource/accesscontrol/provider/paypal/ui/PaypalMapper.java +++ b/src/main/java/org/olat/resource/accesscontrol/provider/paypal/ui/PaypalMapper.java @@ -24,6 +24,7 @@ import java.util.List; import javax.servlet.http.HttpServletRequest; +import org.olat.core.CoreSpringFactory; import org.olat.core.dispatcher.mapper.Mapper; import org.olat.core.gui.media.MediaResource; import org.olat.core.gui.media.RedirectMediaResource; @@ -33,6 +34,7 @@ import org.olat.core.id.context.ContextEntry; import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; import org.olat.core.util.UserSession; +import org.olat.core.util.session.UserSessionManager; import org.olat.resource.accesscontrol.provider.paypal.manager.PaypalManager; /** @@ -59,7 +61,7 @@ public class PaypalMapper implements Mapper { @Override public MediaResource handle(String relPath, HttpServletRequest request) { List<ContextEntry> entries = null; - UserSession usess = UserSession.getUserSession(request); + UserSession usess = CoreSpringFactory.getImpl(UserSessionManager.class).getUserSession(request); try { entries = BusinessControlFactory.getInstance().createCEListFromString(businessPath); if(relPath.indexOf(';') > 0) { diff --git a/src/main/java/org/olat/restapi/security/RestApiLoginFilter.java b/src/main/java/org/olat/restapi/security/RestApiLoginFilter.java index 50bbd9f5870..a273947d1b3 100644 --- a/src/main/java/org/olat/restapi/security/RestApiLoginFilter.java +++ b/src/main/java/org/olat/restapi/security/RestApiLoginFilter.java @@ -49,6 +49,7 @@ import org.olat.core.util.StringHelper; import org.olat.core.util.UserSession; import org.olat.core.util.WebappHelper; import org.olat.core.util.i18n.I18nManager; +import org.olat.core.util.session.UserSessionManager; import org.olat.login.OLATAuthenticationController; import org.olat.restapi.RestModule; @@ -108,7 +109,7 @@ public class RestApiLoginFilter implements Filter { I18nManager.attachI18nInfoToThread(httpRequest); ThreadLocalUserActivityLoggerInstaller.initUserActivityLogger(httpRequest); - UserSession uress = UserSession.getUserSessionIfAlreadySet(httpRequest); + UserSession uress = CoreSpringFactory.getImpl(UserSessionManager.class).getUserSessionIfAlreadySet(httpRequest); if(uress != null && uress.isAuthenticated()) { //use the available session followSession(httpRequest, httpResponse, chain); @@ -212,7 +213,7 @@ public class RestApiLoginFilter implements Filter { throws IOException, ServletException { //create a session for login without security check if(uress == null) { - uress = UserSession.getUserSession(request); + uress = CoreSpringFactory.getImpl(UserSessionManager.class).getUserSession(request); } UserRequest ureq = null; try{ @@ -229,7 +230,7 @@ public class RestApiLoginFilter implements Filter { private void followWithoutAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { - UserSession uress = UserSession.getUserSessionIfAlreadySet(request); + UserSession uress = CoreSpringFactory.getImpl(UserSessionManager.class).getUserSessionIfAlreadySet(request); if(uress != null && uress.isAuthenticated()) { //is authenticated by session cookie, follow its current session followSession(request, response, chain); @@ -263,7 +264,7 @@ public class RestApiLoginFilter implements Filter { throws IOException, ServletException { HttpSession session = request.getSession(true); session.setMaxInactiveInterval(TOKEN_BASED_SESSION_TIMEOUT); - UserSession uress = UserSession.getUserSession(session); + UserSession uress = CoreSpringFactory.getImpl(UserSessionManager.class).getUserSession(session); if(uress != null) { UserRequest ureq = null; try{ @@ -290,7 +291,7 @@ public class RestApiLoginFilter implements Filter { private void followSession(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { - UserSession uress = UserSession.getUserSessionIfAlreadySet(request); + UserSession uress = CoreSpringFactory.getImpl(UserSessionManager.class).getUserSessionIfAlreadySet(request); if(uress != null && uress.isAuthenticated()) { UserRequest ureq = null; try{ diff --git a/src/main/java/org/olat/restapi/system/OpenOLATStatisticsWebService.java b/src/main/java/org/olat/restapi/system/OpenOLATStatisticsWebService.java index 47449d0f665..553deac27c4 100644 --- a/src/main/java/org/olat/restapi/system/OpenOLATStatisticsWebService.java +++ b/src/main/java/org/olat/restapi/system/OpenOLATStatisticsWebService.java @@ -34,6 +34,7 @@ import org.olat.core.CoreSpringFactory; import org.olat.core.commons.services.search.SearchServiceStatus; import org.olat.core.util.SessionInfo; import org.olat.core.util.UserSession; +import org.olat.core.util.session.UserSessionManager; import org.olat.course.CourseModule; import org.olat.group.BusinessGroupService; import org.olat.instantMessaging.InstantMessagingModule; @@ -194,9 +195,11 @@ public class OpenOLATStatisticsWebService { private SessionsVO getSessionsVO() { SessionsVO vo = new SessionsVO(); - vo.setCount(UserSession.getUserSessionsCnt()); - Set<UserSession> userSessions = UserSession.getAuthenticatedUserSessions(); + UserSessionManager sessionManager = CoreSpringFactory.getImpl(UserSessionManager.class); + vo.setCount(sessionManager.getUserSessionsCnt()); + + Set<UserSession> userSessions = sessionManager.getAuthenticatedUserSessions(); int webdavcount = 0; int secureWebdavCount = 0; int authenticatedcount = 0; diff --git a/src/main/java/org/olat/shibboleth/ShibbolethRegistrationController.java b/src/main/java/org/olat/shibboleth/ShibbolethRegistrationController.java index 4badc1fc5b8..572e754fdf1 100644 --- a/src/main/java/org/olat/shibboleth/ShibbolethRegistrationController.java +++ b/src/main/java/org/olat/shibboleth/ShibbolethRegistrationController.java @@ -37,6 +37,7 @@ import org.olat.basesecurity.BaseSecurityManager; import org.olat.basesecurity.BaseSecurityModule; import org.olat.basesecurity.Constants; import org.olat.basesecurity.SecurityGroup; +import org.olat.core.CoreSpringFactory; import org.olat.core.commons.chiefcontrollers.LanguageChangedEvent; import org.olat.core.commons.fullWebApp.LayoutMain3ColsController; import org.olat.core.dispatcher.DispatcherAction; @@ -56,17 +57,16 @@ import org.olat.core.id.Identity; import org.olat.core.id.User; import org.olat.core.id.UserConstants; import org.olat.core.logging.AssertException; -import org.olat.core.util.UserSession; import org.olat.core.util.Util; import org.olat.core.util.WebappHelper; import org.olat.core.util.i18n.I18nManager; +import org.olat.core.util.session.UserSessionManager; import org.olat.dispatcher.LocaleNegotiator; import org.olat.registration.DisclaimerController; import org.olat.registration.LanguageChooserController; import org.olat.registration.RegistrationManager; import org.olat.registration.RegistrationModule; import org.olat.registration.UserNameCreationInterceptor; -import org.olat.shibboleth.util.ShibbolethAttribute; import org.olat.shibboleth.util.ShibbolethHelper; import org.olat.user.UserManager; @@ -224,7 +224,7 @@ public class ShibbolethRegistrationController extends DefaultController implemen * @param attributes */ public static final void putShibAttributes(HttpServletRequest req, Map<String,String> attributes) { - UserSession.getUserSession(req).putEntry(KEY_SHIBATTRIBUTES, attributes); + CoreSpringFactory.getImpl(UserSessionManager.class).getUserSession(req).putEntry(KEY_SHIBATTRIBUTES, attributes); } /** @@ -233,7 +233,7 @@ public class ShibbolethRegistrationController extends DefaultController implemen * @param uniqueID */ public static final void putShibUniqueID(HttpServletRequest req, String uniqueID) { - UserSession.getUserSession(req).putEntry(KEY_SHIBUNIQUEID, uniqueID); + CoreSpringFactory.getImpl(UserSessionManager.class).getUserSession(req).putEntry(KEY_SHIBUNIQUEID, uniqueID); } /** diff --git a/src/main/java/org/olat/upgrade/_spring/upgradeContext.xml b/src/main/java/org/olat/upgrade/_spring/upgradeContext.xml index 1eab4eaf8ed..e329df9dfdd 100644 --- a/src/main/java/org/olat/upgrade/_spring/upgradeContext.xml +++ b/src/main/java/org/olat/upgrade/_spring/upgradeContext.xml @@ -8,7 +8,6 @@ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> -<context:annotation-config /> <context:component-scan base-package="org.olat.upgrade" /> <bean id="olatUpgradeManager.enabled" class="org.olat.upgrade.UpgradeManagerImpl" lazy-init="true" init-method="init" depends-on="folderModule"> diff --git a/src/main/java/org/olat/user/ChangePrefsController.java b/src/main/java/org/olat/user/ChangePrefsController.java index 5468bff64c5..e5ebc1457b3 100644 --- a/src/main/java/org/olat/user/ChangePrefsController.java +++ b/src/main/java/org/olat/user/ChangePrefsController.java @@ -43,15 +43,16 @@ import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.controller.BasicController; import org.olat.core.gui.media.RedirectMediaResource; import org.olat.core.id.Identity; -import org.olat.core.util.WebappHelper; import org.olat.core.id.User; import org.olat.core.id.context.HistoryManager; import org.olat.core.id.context.HistoryModule; import org.olat.core.util.StringHelper; import org.olat.core.util.UserSession; +import org.olat.core.util.WebappHelper; import org.olat.core.util.i18n.I18nManager; import org.olat.core.util.prefs.Preferences; import org.olat.core.util.prefs.PreferencesFactory; +import org.olat.core.util.session.UserSessionManager; import org.olat.properties.PropertyManager; @@ -160,9 +161,12 @@ class SpecialPrefsForm extends FormBasicController { /** The keys for yes/no back. */ private String[] yesNoKeys; private String[] yesNoValues; + + private final UserSessionManager sessionManager; public SpecialPrefsForm(final UserRequest ureq, final WindowControl wControl, final Identity changeableIdentity) { super(ureq, wControl); + sessionManager = CoreSpringFactory.getImpl(UserSessionManager.class); tobeChangedIdentity = changeableIdentity; // OLAT-6429 load GUI prefs from user session for myself, load it from factory for other users (as user manager) @@ -202,7 +206,7 @@ class SpecialPrefsForm extends FormBasicController { protected void formOK(UserRequest ureq) { // OLAT-6429 don't change another users GUI prefs when he is logged in if (!ureq.getIdentity().equalsByPersistableKey(tobeChangedIdentity)) { - if (UserSession.isSignedOnIdentity(tobeChangedIdentity.getName())) { + if (sessionManager.isSignedOnIdentity(tobeChangedIdentity.getName())) { showError("error.user.logged.in", tobeChangedIdentity.getName()); prefsElement.reset(); return; @@ -314,9 +318,12 @@ class UserPrefsResetForm extends FormBasicController { private Identity tobeChangedIdentity; private MultipleSelectionElement resetElements; private String[] keys, values; + + private final UserSessionManager sessionManager; public UserPrefsResetForm(UserRequest ureq, WindowControl wControl, Identity changeableIdentity) { super(ureq, wControl); + sessionManager = CoreSpringFactory.getImpl(UserSessionManager.class); tobeChangedIdentity = changeableIdentity; initForm(ureq); } @@ -343,11 +350,11 @@ class UserPrefsResetForm extends FormBasicController { if (resetElements.isAtLeastSelected(1)) { // Log out user first if logged in boolean logout = false; - Set<UserSession> sessions = UserSession.getAuthenticatedUserSessions(); + Set<UserSession> sessions = sessionManager.getAuthenticatedUserSessions(); for (UserSession session : sessions) { Identity ident = session.getIdentity(); if (ident != null && tobeChangedIdentity.equalsByPersistableKey(ident)) { - session.signOffAndClear(); + sessionManager.signOffAndClear(session); logout = true; break; } diff --git a/src/main/resources/serviceconfig/olat.properties b/src/main/resources/serviceconfig/olat.properties index 40965e11915..e1f81fd9381 100644 --- a/src/main/resources/serviceconfig/olat.properties +++ b/src/main/resources/serviceconfig/olat.properties @@ -93,6 +93,10 @@ history.back.enabled.default=true history.resume.enabled.default=ondemand history.resume.enabled.default.values=none,auto,ondemand +#session timeout in seconds +session.timeout=7200 + + ######################################################################## # SMTP (mail) settings ######################################################################## diff --git a/src/main/resources/serviceconfig/org/olat/_spring/extensionContext.xml b/src/main/resources/serviceconfig/org/olat/_spring/extensionContext.xml index 1d3fd15c021..66b7b9ba1cf 100644 --- a/src/main/resources/serviceconfig/org/olat/_spring/extensionContext.xml +++ b/src/main/resources/serviceconfig/org/olat/_spring/extensionContext.xml @@ -13,15 +13,31 @@ <!-- SYSADMIN extension for admin site for OLAT setup --> - <!-- the sysinfo menu-entry --> + + <!-- The system menu point --> + <bean class="org.olat.core.extensions.action.GenericActionExtension" init-method="initExtensionPoints"> + <property name="order" value="7100" /> + <property name="navigationKey" value="system" /> + <property name="nodeIdentifierIfParent" value="systemParent" /> + <property name="translationPackage" value="org.olat.admin" /> + <property name="i18nActionKey" value="menu.system" /> + <property name="i18nDescriptionKey" value="menu.system.alt" /> + <property name="extensionPoints"> + <list> + <value>org.olat.admin.SystemAdminMainController</value> + </list> + </property> + </bean> + <bean class="org.olat.core.extensions.action.GenericActionExtension" init-method="initExtensionPoints"> - <property name="order" value="7100" /> + <property name="order" value="7110" /> <property name="actionController"> <bean class="org.olat.core.gui.control.creator.AutoCreator" scope="prototype"> <property name="className" value="org.olat.admin.sysinfo.SysinfoController"/> </bean> </property> <property name="navigationKey" value="sysinfo" /> + <property name="parentTreeNodeIdentifier" value="systemParent" /> <property name="translationPackage" value="org.olat.admin"/> <property name="i18nActionKey" value="menu.sysinfo"/> <property name="i18nDescriptionKey" value="menu.sysinfo.alt"/> @@ -31,6 +47,27 @@ </list> </property> </bean> + + <bean class="org.olat.core.extensions.action.GenericActionExtension" init-method="initExtensionPoints"> + <property name="order" value="7120" /> + <property name="actionController"> + <bean class="org.olat.core.gui.control.creator.AutoCreator" scope="prototype"> + <property name="className" value="org.olat.admin.sysinfo.UserSessionAdminController"/> + </bean> + </property> + <property name="navigationKey" value="sessions" /> + <property name="parentTreeNodeIdentifier" value="systemParent" /> + <property name="translationPackage" value="org.olat.admin"/> + <property name="i18nActionKey" value="menu.session"/> + <property name="i18nDescriptionKey" value="menu.session.alt"/> + <property name="extensionPoints"> + <list> + <value>org.olat.admin.SystemAdminMainController</value> + </list> + </property> + </bean> + + <!-- the "systemconfig" parent node --> <bean class="org.olat.core.extensions.action.GenericActionExtension" init-method="initExtensionPoints"> diff --git a/src/test/java/org/olat/core/dispatcher/mapper/MapperServiceTest.java b/src/test/java/org/olat/core/dispatcher/mapper/MapperServiceTest.java index 8afded127bb..1d465b9cb0b 100644 --- a/src/test/java/org/olat/core/dispatcher/mapper/MapperServiceTest.java +++ b/src/test/java/org/olat/core/dispatcher/mapper/MapperServiceTest.java @@ -33,6 +33,7 @@ import org.olat.core.dispatcher.mapper.manager.MapperDAO; import org.olat.core.gui.media.MediaResource; import org.olat.core.util.SessionInfo; import org.olat.core.util.UserSession; +import org.olat.core.util.session.UserSessionManager; import org.olat.test.OlatTestCase; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.mock.web.MockHttpSession; @@ -49,6 +50,8 @@ public class MapperServiceTest extends OlatTestCase { private MapperService mapperService; @Autowired private DB dbInstance; + @Autowired + private UserSessionManager sessionManager; @Test public void should_service_present() { @@ -179,7 +182,7 @@ public class MapperServiceTest extends OlatTestCase { private UserSession createUserSession() { HttpSession httpSession = new MockHttpSession(); - UserSession userSession = UserSession.getUserSession(httpSession); + UserSession userSession = sessionManager.getUserSession(httpSession); SessionInfo infos = new SessionInfo(UUID.randomUUID().toString(), httpSession); userSession.setSessionInfo(infos); //check if our mocked HTTP session makes what we want diff --git a/src/test/java/org/olat/test/OlatTestCase.java b/src/test/java/org/olat/test/OlatTestCase.java index b79b648b518..54c47a5fcce 100644 --- a/src/test/java/org/olat/test/OlatTestCase.java +++ b/src/test/java/org/olat/test/OlatTestCase.java @@ -54,6 +54,7 @@ import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests; "classpath:/org/olat/core/util/_spring/utilCorecontext.xml", "classpath:/org/olat/core/util/i18n/devtools/_spring/devtoolsCorecontext.xml", "classpath:/org/olat/core/util/event/_spring/frameworkStartedEventCorecontext.xml", + "classpath:/org/olat/core/id/context/_spring/historyCorecontext.xml", "classpath:/org/olat/core/commons/persistence/_spring/databaseCorecontext.xml", "classpath:/org/olat/core/commons/taskExecutor/_spring/taskExecutorCorecontext.xml", -- GitLab