From 909eec6585a8e30771cbfe4e8c5c2544e0226dcc Mon Sep 17 00:00:00 2001 From: gnaegi <none@none> Date: Tue, 14 Jan 2014 10:13:03 +0100 Subject: [PATCH] OO-922 refactored default tools in collab tools to be thread save, disable wiki run when sec setting, chelp and i18n for security module --- .../security/SecurityAdminController.java | 20 ++++--- .../olat/admin/security/_chelp/ced-sec.html | 13 ++++- .../security/_i18n/LocalStrings_de.properties | 21 ++++--- .../security/_i18n/LocalStrings_en.properties | 15 +++++ .../collaboration/CollaborationTools.java | 31 +--------- .../CollaborationToolsFactory.java | 56 +++++++++++++++++++ .../CollaborationToolsSettingsController.java | 25 +++++---- .../_spring/collaborationToolsContext.xml | 2 +- .../manager/BusinessGroupImportExport.java | 14 +++-- .../manager/BusinessGroupServiceImpl.java | 5 +- .../AbstractBusinessGroupListController.java | 2 +- .../run/BusinessGroupMainRunController.java | 4 +- .../wizard/BGConfigToolsStepController.java | 4 +- .../java/org/olat/modules/iq/IQManager.java | 17 ++---- .../OpenMeetingsConfigurationController.java | 5 +- .../ui/PortfolioAdminController.java | 3 + .../olat/repository/RepositoyUIFactory.java | 39 +++++++++++++ .../_i18n/LocalStrings_de.properties | 2 + .../_i18n/LocalStrings_en.properties | 2 + .../olat/repository/handlers/WikiHandler.java | 11 +++- .../group/LearningGroupWebService.java | 5 +- .../group/test/BusinessGroupServiceTest.java | 32 ++++++----- 22 files changed, 228 insertions(+), 100 deletions(-) create mode 100644 src/main/java/org/olat/admin/security/_i18n/LocalStrings_en.properties diff --git a/src/main/java/org/olat/admin/security/SecurityAdminController.java b/src/main/java/org/olat/admin/security/SecurityAdminController.java index eac71533ac6..85a484d0f46 100644 --- a/src/main/java/org/olat/admin/security/SecurityAdminController.java +++ b/src/main/java/org/olat/admin/security/SecurityAdminController.java @@ -20,6 +20,7 @@ package org.olat.admin.security; import org.olat.basesecurity.BaseSecurityModule; +import org.olat.collaboration.CollaborationToolsFactory; import org.olat.core.CoreSpringFactory; import org.olat.core.commons.modules.bc.FolderModule; import org.olat.core.gui.UserRequest; @@ -57,18 +58,21 @@ public class SecurityAdminController extends FormBasicController { setFormDescription("sec.description"); setFormContextHelp("org.olat.admin.security", "ced-sec.html", "help.hover.sec"); - String[] frameKeys = new String[]{ "on" }; - String[] frameValues = new String[]{ "" }; + String[] keys = new String[]{ "on" }; + String[] values = new String[]{ "" }; - topFrameEl = uifactory.addCheckboxesHorizontal("sec.topframe", "sec.topframe", formLayout, frameKeys, frameValues, null); + // on: force top top frame (more security); off: allow in frame (less security) + topFrameEl = uifactory.addCheckboxesHorizontal("sec.topframe", "sec.topframe", formLayout, keys, values, null); topFrameEl.select("on", securityModule.isForceTopFrame()); topFrameEl.addActionListener(this, FormEvent.ONCHANGE); - wikiEl = uifactory.addCheckboxesHorizontal("sec.wiki", "sec.wiki", formLayout, frameKeys, frameValues, null); - wikiEl.select("on", securityModule.isWikiEnabled()); + // on: block wiki (more security); off: do not block wiki (less security) + wikiEl = uifactory.addCheckboxesHorizontal("sec.wiki", "sec.wiki", formLayout, keys, values, null); + wikiEl.select("off", securityModule.isWikiEnabled()); wikiEl.addActionListener(this, FormEvent.ONCHANGE); - forceDownloadEl = uifactory.addCheckboxesHorizontal("sec.download", "sec.force.download", formLayout, frameKeys, frameValues, null); + // on: force file download in folder component (more security); off: allow execution of content (less security) + forceDownloadEl = uifactory.addCheckboxesHorizontal("sec.download", "sec.force.download", formLayout, keys, values, null); forceDownloadEl.select("on", folderModule.isForceDownload()); forceDownloadEl.addActionListener(this, FormEvent.ONCHANGE); } @@ -85,7 +89,9 @@ public class SecurityAdminController extends FormBasicController { securityModule.setForceTopFrame(enabled); } else if(wikiEl == source) { boolean enabled = wikiEl.isAtLeastSelected(1); - securityModule.setWikiEnabled(enabled); + securityModule.setWikiEnabled(!enabled); + // update collaboration tools list + CollaborationToolsFactory.getInstance().initAvailableTools(); } else if(forceDownloadEl == source) { boolean enabled = forceDownloadEl.isAtLeastSelected(1); folderModule.setForceDownload(enabled); diff --git a/src/main/java/org/olat/admin/security/_chelp/ced-sec.html b/src/main/java/org/olat/admin/security/_chelp/ced-sec.html index d8d2bace3d5..c0052b36082 100644 --- a/src/main/java/org/olat/admin/security/_chelp/ced-sec.html +++ b/src/main/java/org/olat/admin/security/_chelp/ced-sec.html @@ -1 +1,12 @@ -$r.translate("chelp.sec1") +<p> + $r.translate("chelp.sec.intro") +</p> +<p> + <b>$r.translate("sec.topframe")</b>: $r.translate("chelp.sec.topframe") +</p> +<p> + <b>$r.translate("sec.wiki")</b>: $r.translate("chelp.sec.wiki") +</p> +<p> + <b>$r.translate("sec.force.download")</b>: $r.translate("chelp.sec.force.download") +</p> diff --git a/src/main/java/org/olat/admin/security/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/admin/security/_i18n/LocalStrings_de.properties index 62315493b4d..652de9c2cfe 100644 --- a/src/main/java/org/olat/admin/security/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/admin/security/_i18n/LocalStrings_de.properties @@ -1,12 +1,15 @@ #Thu Aug 06 11:28:42 CEST 2009 admin.menu.title=Sicherheit -admin.menu.title.alt=Sicherheitsaspekten von OpenOLAT konfigurieren -chelp.sec1=Sicherheitsaspekten von OpenOLAT... -chelp.ced-sec.title=Sicherheitsaspekten von OpenOLAT -help.hover.sec=Hilfe zur Sicherheits in OpenOLAT konfigurieren -sec.title=Sicherheitsaspekten von OpenOLAT -sec.description=Sie k\u00F6nnen hier ein paar Sicherheitsentscheidung nehmen -sec.force.download=Datei herunterladen -sec.topframe=Enforce top frame -sec.wiki=Wiki +admin.menu.title.alt=Sicherheitseinstellungen anpassen +sec.title=Sicherheitseinstellungen +sec.description=Wählen Sie den notwendigen Sicherheitslevel je nach Anforderungen Ihrer Institution. Um die höchste Sicherheitsstufe zu erreichen müssen sämtliche untenstehenden Sicherheitsfunktionen eingeschaltet sein. +sec.force.download=Dateidownload in Ordner erzwingen +sec.topframe=Frame Einbettung verhindern +sec.wiki=Wiki Ressourcen blockieren +help.hover.sec=Hilfe zu den Sicherheitseinstellungen +chelp.ced-sec.title=Systemweite Sicherheitseinstellungen +chelp.sec.intro=Die Anforderungen an die Sicherheit können je nach Institution variieren. In den Sicherheitseinstellungen können Sie daher den notwendigen Level an Sicherheit einstellen unter Berücksichtigung der damit eingegangenen Risiken. +chelp.sec.topframe=Wählen Sie diese Sicherheitsfunktion um das Laden von OpenOLAT in einem Frame oder iFrame zu verhindern. Damit werden allfällige Cross-Frame-Scripting Attacken verhindert (XFS). Ist diese Funktion eingeschaltet können Sie OpenOLAT nicht in eine bestehende Webseite mittels Frames einbetten. +chelp.sec.wiki=Wählen Sie diese Sicherheitsfunktion um das Wiki Systemweit auszuschalten. Die Wiki Komponenten ist zur Zeit noch anfällig für Cross-Site-Scripting Attacken (XSS). Ist diese Funktion eingeschaltet, so kann die Wiki Funktion in OpenOLAT nicht mehr verwendet werden. Bei ausgeschalteter Funktion kann das Wiki mit dem Risiko einer XSS Attacke verwendet werden. Allerdings verfügt das Wiki über eine automatische Versionierung welche es Angreifern schwierig macht unerkannt zu bleiben. +chelp.sec.force.download=Wählen Sie diese Sicherheitsfunktion um in der Ordnerkomponente Dateien immer herunterzuladen und nie direkt im Browser zu öffnen. Damit werden allfällige Cross-Site-Scripting (XSS) Attacken verhindert. Ist diese Funktion eingeschaltet werden auch HTML Seiten welche in Ordnern abgelegt werden als Dateien heruntergeladen und nicht mehr direkt im Browser geöffnet. Der Kursbaustein "Einzelseite" ist von diesem Mechanismus nicht betroffen. diff --git a/src/main/java/org/olat/admin/security/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/admin/security/_i18n/LocalStrings_en.properties new file mode 100644 index 00000000000..1f642eab8a6 --- /dev/null +++ b/src/main/java/org/olat/admin/security/_i18n/LocalStrings_en.properties @@ -0,0 +1,15 @@ +#Thu Aug 06 11:28:42 CEST 2009 +admin.menu.title=Security +admin.menu.title.alt=Change security settings +sec.title=Security settings +sec.description=Choose the security level depending on the requirements of your instittion. The achive the highes security level all security features below have to be turned on. +sec.force.download=Force file download in folders +sec.topframe=Prevent embedding in frames +sec.wiki=Block wiki resources + +help.hover.sec=Help about security settings +chelp.ced-sec.title=System-wide security settings +chelp.sec.intro=Requirements towards security can vary greatly depending on the institution. Using the security the necessary security level can be configured taking into account the associated risk. +chelp.sec.topframe=Select this security feature to prevent OpenOLAT from being loaded in a HTML frame or iFrame. By doing this will prevent possible Cross-Frame-Scripting attacks (XFS). If you enable this feature it is no longer possible to embedd OpenOLAT in an existing website using frames. +chelp.sec.wiki=Select this security feature to disable the wiki resources system wide. At this time the wiki component is still prone to Cross-Site-Scripting attacks (XSS). When this feature is enabled, the wiki resources in OpenOLAT can no longer be used. When disabled, the wiki can be use with the risk of an XSS attack. However, since the wiki as an automatic revision mechanism it will be difficult for attackers to hide after an attack. +chelp.sec.force.download=Select this security setting to always dowload files from folders and never open them directly in the browser. This prevents possible Cross-Site-Scripting attacks (XSS). When this feature is enabled all documents are downloaded as files and will not be displayed in the browser directly, including HTML documents. This behavior does not apply to the course element "single page". diff --git a/src/main/java/org/olat/collaboration/CollaborationTools.java b/src/main/java/org/olat/collaboration/CollaborationTools.java index 8991b42a74a..1fd4c65a92f 100644 --- a/src/main/java/org/olat/collaboration/CollaborationTools.java +++ b/src/main/java/org/olat/collaboration/CollaborationTools.java @@ -58,7 +58,6 @@ import org.olat.core.id.context.ContextEntry; import org.olat.core.logging.AssertException; import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; -import org.olat.core.util.ArrayHelper; import org.olat.core.util.FileUtils; import org.olat.core.util.Util; import org.olat.core.util.ZipUtil; @@ -102,7 +101,6 @@ import org.olat.modules.wiki.WikiToZipUtils; import org.olat.portfolio.EPSecurityCallback; import org.olat.portfolio.EPSecurityCallbackImpl; import org.olat.portfolio.EPUIFactory; -import org.olat.portfolio.PortfolioModule; import org.olat.portfolio.manager.EPFrontendManager; import org.olat.portfolio.model.structel.PortfolioStructureMap; import org.olat.portfolio.ui.structel.EPCreateMapController; @@ -188,13 +186,6 @@ public class CollaborationTools implements Serializable { */ public final static String TOOL_OPENMEETINGS = "hasOpenMeetings"; - /** - * public for group test only, do not use otherwise convenience, helps - * iterating possible tools, i.e. in jUnit testCase, also for building up a - * tools choice - */ - public static String[] TOOLS; - /** * Only owners have write access to the calendar. */ @@ -237,27 +228,7 @@ public class CollaborationTools implements Serializable { CollaborationTools(CoordinatorManager coordinatorManager, BusinessGroup ores) { this.coordinatorManager = coordinatorManager; this.ores = ores; - cacheToolStates = new Hashtable<String, Boolean>(); - ArrayList<String> toolArr = new ArrayList<String>(); - toolArr.add(TOOL_NEWS); - toolArr.add(TOOL_CONTACT); - toolArr.add(TOOL_CALENDAR); - toolArr.add(TOOL_FOLDER); - toolArr.add(TOOL_FORUM); - if (CoreSpringFactory.getImpl(InstantMessagingModule.class).isEnabled()) { - toolArr.add(TOOL_CHAT); - } - toolArr.add(TOOL_WIKI); - PortfolioModule portfolioModule = (PortfolioModule) CoreSpringFactory.getBean("portfolioModule"); - if (portfolioModule.isEnabled()) { - toolArr.add(TOOL_PORTFOLIO); - } - OpenMeetingsModule openMeetingsModule = CoreSpringFactory.getImpl(OpenMeetingsModule.class); - if(openMeetingsModule.isEnabled()) { - toolArr.add(TOOL_OPENMEETINGS); - } - - TOOLS = ArrayHelper.toArray(toolArr); + this.cacheToolStates = new Hashtable<String, Boolean>(); } /** diff --git a/src/main/java/org/olat/collaboration/CollaborationToolsFactory.java b/src/main/java/org/olat/collaboration/CollaborationToolsFactory.java index 18e1ba86f9d..242a120017f 100644 --- a/src/main/java/org/olat/collaboration/CollaborationToolsFactory.java +++ b/src/main/java/org/olat/collaboration/CollaborationToolsFactory.java @@ -25,14 +25,22 @@ package org.olat.collaboration; +import java.util.ArrayList; + +import org.olat.basesecurity.BaseSecurityModule; +import org.olat.core.CoreSpringFactory; import org.olat.core.id.OLATResourceable; import org.olat.core.logging.AssertException; import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; +import org.olat.core.util.ArrayHelper; import org.olat.core.util.cache.CacheWrapper; import org.olat.core.util.coordinate.CoordinatorManager; import org.olat.core.util.coordinate.SyncerCallback; import org.olat.group.BusinessGroup; +import org.olat.instantMessaging.InstantMessagingModule; +import org.olat.modules.openmeetings.OpenMeetingsModule; +import org.olat.portfolio.PortfolioModule; /** * Description:<BR> @@ -49,6 +57,14 @@ public class CollaborationToolsFactory { private static CollaborationToolsFactory instance; private CacheWrapper<String,CollaborationTools> cache; private CoordinatorManager coordinatorManager; + + /** + * public for group test only, do not use otherwise convenience, helps + * iterating possible tools, i.e. in jUnit testCase, also for building up a + * tools choice + */ + public static String[] TOOLS; + /** * [used by spring] @@ -58,6 +74,46 @@ public class CollaborationToolsFactory { instance = this; } + /** + * Helper method to initialize the list of enabled tools based system wide + * configuration. + */ + public synchronized void initAvailableTools() { + ArrayList<String> toolArr = new ArrayList<String>(); + toolArr.add(CollaborationTools.TOOL_NEWS); + toolArr.add(CollaborationTools.TOOL_CONTACT); + toolArr.add(CollaborationTools.TOOL_CALENDAR); + toolArr.add(CollaborationTools.TOOL_FOLDER); + toolArr.add(CollaborationTools.TOOL_FORUM); + if (CoreSpringFactory.getImpl(InstantMessagingModule.class).isEnabled()) { + toolArr.add(CollaborationTools.TOOL_CHAT); + } + BaseSecurityModule securityModule = CoreSpringFactory.getImpl(BaseSecurityModule.class); + if (securityModule.isWikiEnabled()) { + toolArr.add(CollaborationTools.TOOL_WIKI); + } + PortfolioModule portfolioModule = (PortfolioModule) CoreSpringFactory.getBean("portfolioModule"); + if (portfolioModule.isEnabled()) { + toolArr.add(CollaborationTools.TOOL_PORTFOLIO); + } + OpenMeetingsModule openMeetingsModule = CoreSpringFactory.getImpl(OpenMeetingsModule.class); + if(openMeetingsModule.isEnabled()) { + toolArr.add(CollaborationTools.TOOL_OPENMEETINGS); + } + TOOLS = ArrayHelper.toArray(toolArr); + } + + /** + * Get the array of available (system wide enabled) collaboration tools + * @return + */ + public String[] getAvailableTools() { + if (TOOLS == null) { + initAvailableTools(); + } + return TOOLS; + } + /** * it is a singleton. * diff --git a/src/main/java/org/olat/collaboration/CollaborationToolsSettingsController.java b/src/main/java/org/olat/collaboration/CollaborationToolsSettingsController.java index 1a8f7da9607..5f1217346be 100644 --- a/src/main/java/org/olat/collaboration/CollaborationToolsSettingsController.java +++ b/src/main/java/org/olat/collaboration/CollaborationToolsSettingsController.java @@ -68,6 +68,7 @@ public class CollaborationToolsSettingsController extends BasicController { private boolean lastCalendarEnabledState; private Controller quotaCtr; + private final String[] availableTools; private final boolean managed; private final BusinessGroup businessGroup; @@ -79,11 +80,13 @@ public class CollaborationToolsSettingsController extends BasicController { super(ureq, wControl); this.businessGroup = businessGroup; managed = BusinessGroupManagedFlag.isManaged(businessGroup, BusinessGroupManagedFlag.tools); + // make copy to be independent, for during lifetime of controller + availableTools = CollaborationToolsFactory.getInstance().getAvailableTools().clone(); CollaborationTools collabTools = CollaborationToolsFactory.getInstance().getOrCreateCollaborationTools(businessGroup); vc_collabtools = createVelocityContainer ("collaborationtools"); - cots = new ChoiceOfToolsForm (ureq, wControl, collabTools); + cots = new ChoiceOfToolsForm (ureq, wControl, collabTools, availableTools); cots.setEnabled(!managed); listenTo(cots); vc_collabtools.put("choiceOfTools", cots.getInitialComponent()); @@ -170,11 +173,11 @@ public class CollaborationToolsSettingsController extends BasicController { if (source == cots && event.getCommand().equals("ONCHANGE")) { Set<String> set = cots.getSelected(); - for (int i = 0; i < CollaborationTools.TOOLS.length; i++) { + for (int i = 0; i < availableTools.length; i++) { // usually one should check which one changed but here // it is okay to set all of them because ctsm has a cache // and writes only when really necessary. - collabTools.setToolEnabled(CollaborationTools.TOOLS[i], set.contains(""+i)); + collabTools.setToolEnabled(availableTools[i], set.contains(""+i)); } //reload tools after a change collabTools = CollaborationToolsFactory.getInstance().getOrCreateCollaborationTools(businessGroup); @@ -267,19 +270,21 @@ public class CollaborationToolsSettingsController extends BasicController { } class ChoiceOfToolsForm extends FormBasicController { - CollaborationTools cts; MultipleSelectionElement ms; List <String>theKeys = new ArrayList<String>(); List <String>theValues = new ArrayList<String>(); + + final String[] availableTools; - public ChoiceOfToolsForm(UserRequest ureq, WindowControl wControl, CollaborationTools cts) { + public ChoiceOfToolsForm(UserRequest ureq, WindowControl wControl, CollaborationTools cts, final String[] availableTools) { super(ureq, wControl); this.cts = cts; + this.availableTools = availableTools; - for (int i=0; i<CollaborationTools.TOOLS.length; i++) { - String k = CollaborationTools.TOOLS[i]; + for (int i=0; i<availableTools.length; i++) { + String k = availableTools[i]; if (k.equals(CollaborationTools.TOOL_CHAT)) { InstantMessagingModule imModule = CoreSpringFactory.getImpl(InstantMessagingModule.class); if (!imModule.isEnabled() || !imModule.isGroupEnabled()) { @@ -287,7 +292,7 @@ class ChoiceOfToolsForm extends FormBasicController { } } theKeys.add(""+i); - theValues.add(translate("collabtools.named."+CollaborationTools.TOOLS[i])); + theValues.add(translate("collabtools.named."+availableTools[i])); } initForm(ureq); @@ -310,8 +315,8 @@ class ChoiceOfToolsForm extends FormBasicController { theValues.toArray(new String[theValues.size()]), null, 1 ); - for (int i=0; i<CollaborationTools.TOOLS.length; i++) { - ms.select(""+i, cts.isToolEnabled(CollaborationTools.TOOLS[i])); + for (int i=0; i<availableTools.length; i++) { + ms.select(""+i, cts.isToolEnabled(availableTools[i])); } ms.addActionListener(listener, FormEvent.ONCLICK); } diff --git a/src/main/java/org/olat/collaboration/_spring/collaborationToolsContext.xml b/src/main/java/org/olat/collaboration/_spring/collaborationToolsContext.xml index c1d72cce210..8ca42a13fbe 100644 --- a/src/main/java/org/olat/collaboration/_spring/collaborationToolsContext.xml +++ b/src/main/java/org/olat/collaboration/_spring/collaborationToolsContext.xml @@ -6,7 +6,7 @@ http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="collaborationToolsFactory" class="org.olat.collaboration.CollaborationToolsFactory" -depends-on="instantMessagingModule" > +depends-on="instantMessagingModule,baseSecurityModule,portfolioModule,openmeetingsModule"> <constructor-arg ref="coordinatorManager" /> </bean> diff --git a/src/main/java/org/olat/group/manager/BusinessGroupImportExport.java b/src/main/java/org/olat/group/manager/BusinessGroupImportExport.java index d8edbc95764..d278d2d0273 100644 --- a/src/main/java/org/olat/group/manager/BusinessGroupImportExport.java +++ b/src/main/java/org/olat/group/manager/BusinessGroupImportExport.java @@ -135,12 +135,13 @@ public class BusinessGroupImportExport { } // collab tools + String[] availableTools = CollaborationToolsFactory.getInstance().getAvailableTools().clone(); CollabTools toolsConfig = new CollabTools(); CollaborationTools ct = CollaborationToolsFactory.getInstance().getOrCreateCollaborationTools(group); - for (int i = 0; i < CollaborationTools.TOOLS.length; i++) { + for (int i = 0; i < availableTools.length; i++) { try { - Field field = toolsConfig.getClass().getField(CollaborationTools.TOOLS[i]); - field.setBoolean(toolsConfig, ct.isToolEnabled(CollaborationTools.TOOLS[i])); + Field field = toolsConfig.getClass().getField(availableTools[i]); + field.setBoolean(toolsConfig, ct.isToolEnabled(availableTools[i])); } catch (Exception e) { log.error("", e); } @@ -263,14 +264,15 @@ public class BusinessGroupImportExport { //map the group env.getGroups().add(new BusinessGroupReference(newGroup, group.key, group.name)); // get tools config + String[] availableTools = CollaborationToolsFactory.getInstance().getAvailableTools().clone(); CollabTools toolsConfig = group.tools; CollaborationTools ct = CollaborationToolsFactory.getInstance().getOrCreateCollaborationTools(newGroup); - for (int i = 0; i < CollaborationTools.TOOLS.length; i++) { + for (int i = 0; i < availableTools.length; i++) { try { - Field field = toolsConfig.getClass().getField(CollaborationTools.TOOLS[i]); + Field field = toolsConfig.getClass().getField(availableTools[i]); Boolean val = field.getBoolean(toolsConfig); if (val != null) { - ct.setToolEnabled(CollaborationTools.TOOLS[i], val); + ct.setToolEnabled(availableTools[i], val); } } catch (Exception e) { log.error("", e); diff --git a/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java b/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java index 4ebe2cbb67b..a24ae44455b 100644 --- a/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java +++ b/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java @@ -389,8 +389,9 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD CollaborationTools oldTools = toolsF.getOrCreateCollaborationTools(sourceBusinessGroup); CollaborationTools newTools = toolsF.getOrCreateCollaborationTools(newGroup); // copy the collab tools settings - for (int i = 0; i < CollaborationTools.TOOLS.length; i++) { - String tool = CollaborationTools.TOOLS[i]; + String[] availableTools = CollaborationToolsFactory.getInstance().getAvailableTools().clone(); + for (int i = 0; i < availableTools.length; i++) { + String tool = availableTools[i]; newTools.setToolEnabled(tool, oldTools.isToolEnabled(tool)); } String oldNews = oldTools.lookupNews(); diff --git a/src/main/java/org/olat/group/ui/main/AbstractBusinessGroupListController.java b/src/main/java/org/olat/group/ui/main/AbstractBusinessGroupListController.java index 525ab1ff414..8d11af4672c 100644 --- a/src/main/java/org/olat/group/ui/main/AbstractBusinessGroupListController.java +++ b/src/main/java/org/olat/group/ui/main/AbstractBusinessGroupListController.java @@ -562,7 +562,7 @@ public abstract class AbstractBusinessGroupListController extends BasicControlle if(groups.isEmpty()) { showWarning("msg.alleastone.editable.group"); return; - } else if(CollaborationTools.TOOLS == null) { + } else if(CollaborationToolsFactory.getInstance().getAvailableTools() == null) { //init the available tools CollaborationToolsFactory.getInstance().getOrCreateCollaborationTools(groups.get(0)); } diff --git a/src/main/java/org/olat/group/ui/run/BusinessGroupMainRunController.java b/src/main/java/org/olat/group/ui/run/BusinessGroupMainRunController.java index d3f63092289..470620e799d 100644 --- a/src/main/java/org/olat/group/ui/run/BusinessGroupMainRunController.java +++ b/src/main/java/org/olat/group/ui/run/BusinessGroupMainRunController.java @@ -32,6 +32,7 @@ import org.olat.NewControllerFactory; import org.olat.admin.securitygroup.gui.GroupController; import org.olat.basesecurity.BaseSecurity; import org.olat.basesecurity.BaseSecurityManager; +import org.olat.basesecurity.BaseSecurityModule; import org.olat.basesecurity.Constants; import org.olat.basesecurity.SecurityGroup; import org.olat.collaboration.CollaborationTools; @@ -1081,7 +1082,8 @@ public class BusinessGroupMainRunController extends MainLayoutBasicController im root.addChild(gtnChild); } - if (collabTools.isToolEnabled(CollaborationTools.TOOL_WIKI)) { + BaseSecurityModule securityModule = CoreSpringFactory.getImpl(BaseSecurityModule.class); + if (collabTools.isToolEnabled(CollaborationTools.TOOL_WIKI) && securityModule.isWikiEnabled()) { gtnChild = new GenericTreeNode(); gtnChild.setTitle(translate("menutree.wiki")); gtnChild.setUserObject(ACTIVITY_MENUSELECT_WIKI); diff --git a/src/main/java/org/olat/group/ui/wizard/BGConfigToolsStepController.java b/src/main/java/org/olat/group/ui/wizard/BGConfigToolsStepController.java index c5105d24b35..2ba6e21b2d3 100644 --- a/src/main/java/org/olat/group/ui/wizard/BGConfigToolsStepController.java +++ b/src/main/java/org/olat/group/ui/wizard/BGConfigToolsStepController.java @@ -24,6 +24,7 @@ import java.util.List; import org.olat.collaboration.CalendarToolSettingsController; import org.olat.collaboration.CollaborationTools; +import org.olat.collaboration.CollaborationToolsFactory; import org.olat.collaboration.CollaborationToolsSettingsController; import org.olat.collaboration.FolderToolSettingsController; import org.olat.core.gui.UserRequest; @@ -75,7 +76,8 @@ public class BGConfigToolsStepController extends StepFormBasicController { String containerPage = velocity_root + "/tool_config_container.html"; - for (String k : CollaborationTools.TOOLS) { + String[] availableTools = CollaborationToolsFactory.getInstance().getAvailableTools().clone(); + for (String k : availableTools) { if (k.equals(CollaborationTools.TOOL_CHAT) || k.equals(CollaborationTools.TOOL_NEWS)) { continue; } diff --git a/src/main/java/org/olat/modules/iq/IQManager.java b/src/main/java/org/olat/modules/iq/IQManager.java index 785902f61f6..80fc51a0248 100644 --- a/src/main/java/org/olat/modules/iq/IQManager.java +++ b/src/main/java/org/olat/modules/iq/IQManager.java @@ -50,7 +50,6 @@ import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.generic.layout.GenericMainController; import org.olat.core.gui.control.generic.layout.MainLayoutController; -import org.olat.core.gui.control.generic.messages.MessageController; import org.olat.core.gui.control.generic.messages.MessageUIFactory; import org.olat.core.gui.translator.Translator; import org.olat.core.id.Identity; @@ -188,7 +187,6 @@ public class IQManager extends BasicManager implements UserDataDeletable { // -- 99% of cases -- 2) qti is ready to be run as test/survey if (CoordinatorManager.getInstance().getCoordinator().getLocker().isLocked(res, null)){ GenericMainController glc = createLockedMessageController(ureq, wControl); - glc.init(ureq); return glc; }else{ Controller controller = new IQDisplayController(resolver, type, secCallback, ureq, wControl); @@ -199,22 +197,16 @@ public class IQManager extends BasicManager implements UserDataDeletable { } private GenericMainController createLockedMessageController(UserRequest ureq, WindowControl wControl) { - // //wrap simple message into mainLayout GenericMainController glc = new GenericMainController(ureq, wControl) { - - private MessageController contentCtr; - private Panel empty; - private LayoutMain3ColsController columnLayoutCtr; - @Override public void init(UserRequest ureq) { - empty = new Panel("empty"); Translator translator = Util.createPackageTranslator(this.getClass(), ureq.getLocale()); - contentCtr = MessageUIFactory.createInfoMessage(ureq, getWindowControl(), translator.translate("status.currently.locked.title"), translator.translate("status.currently.locked")); + Panel empty = new Panel("empty"); + setTranslator(Util.createPackageTranslator(this.getClass(), ureq.getLocale())); + Controller contentCtr = MessageUIFactory.createInfoMessage(ureq, getWindowControl(), translate("status.currently.locked.title"), translate("status.currently.locked")); listenTo(contentCtr); // auto dispose later Component resComp = contentCtr.getInitialComponent(); - - columnLayoutCtr = new LayoutMain3ColsController(ureq, getWindowControl(), empty, empty, resComp, /*do not save no prefs*/null); + LayoutMain3ColsController columnLayoutCtr = new LayoutMain3ColsController(ureq, getWindowControl(), empty, empty, resComp, /*do not save no prefs*/null); listenTo(columnLayoutCtr); // auto dispose later putInitialPanel(columnLayoutCtr.getInitialComponent()); } @@ -226,6 +218,7 @@ public class IQManager extends BasicManager implements UserDataDeletable { } }; + glc.init(ureq); return glc; } diff --git a/src/main/java/org/olat/modules/openmeetings/ui/OpenMeetingsConfigurationController.java b/src/main/java/org/olat/modules/openmeetings/ui/OpenMeetingsConfigurationController.java index 37aa6dd7134..c0f60cdc745 100644 --- a/src/main/java/org/olat/modules/openmeetings/ui/OpenMeetingsConfigurationController.java +++ b/src/main/java/org/olat/modules/openmeetings/ui/OpenMeetingsConfigurationController.java @@ -22,6 +22,7 @@ package org.olat.modules.openmeetings.ui; import java.net.URI; import java.net.URISyntaxException; +import org.olat.collaboration.CollaborationToolsFactory; import org.olat.core.CoreSpringFactory; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.FormItem; @@ -37,8 +38,8 @@ import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; import org.olat.core.util.StringHelper; import org.olat.modules.openmeetings.OpenMeetingsModule; -import org.olat.modules.openmeetings.manager.OpenMeetingsManager; import org.olat.modules.openmeetings.manager.OpenMeetingsException; +import org.olat.modules.openmeetings.manager.OpenMeetingsManager; /** * @@ -197,6 +198,8 @@ public class OpenMeetingsConfigurationController extends FormBasicController { if(source == moduleEnabled) { boolean enabled = moduleEnabled.isSelected(0); openMeetingsModule.setEnabled(enabled); + // update collaboration tools list + CollaborationToolsFactory.getInstance().initAvailableTools(); } else if(source == checkLink) { if(validateURL()) { checkConnection(); diff --git a/src/main/java/org/olat/portfolio/ui/PortfolioAdminController.java b/src/main/java/org/olat/portfolio/ui/PortfolioAdminController.java index 8090ecd8ddc..3923cc36c2c 100644 --- a/src/main/java/org/olat/portfolio/ui/PortfolioAdminController.java +++ b/src/main/java/org/olat/portfolio/ui/PortfolioAdminController.java @@ -22,6 +22,7 @@ package org.olat.portfolio.ui; import java.util.ArrayList; import java.util.List; +import org.olat.collaboration.CollaborationToolsFactory; import org.olat.core.CoreSpringFactory; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.FormItem; @@ -130,6 +131,8 @@ public class PortfolioAdminController extends FormBasicController { if(source == portfolioEnabled) { boolean enabled = portfolioEnabled.isSelected(0); portfolioModule.setEnabled(enabled); + // update collaboration tools list + CollaborationToolsFactory.getInstance().initAvailableTools(); showWarning("portfolio.module.change.warning"); } else if(handlersEnabled.contains(source)) { EPArtefactHandler<?> handler = (EPArtefactHandler<?>)source.getUserObject(); diff --git a/src/main/java/org/olat/repository/RepositoyUIFactory.java b/src/main/java/org/olat/repository/RepositoyUIFactory.java index 53d381449d0..0b785383d9e 100644 --- a/src/main/java/org/olat/repository/RepositoyUIFactory.java +++ b/src/main/java/org/olat/repository/RepositoyUIFactory.java @@ -26,9 +26,13 @@ package org.olat.repository; import org.olat.core.commons.fullWebApp.LayoutMain3ColsController; import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.Component; +import org.olat.core.gui.components.panel.Panel; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; +import org.olat.core.gui.control.generic.layout.GenericMainController; import org.olat.core.gui.control.generic.layout.MainLayoutController; +import org.olat.core.gui.control.generic.messages.MessageController; import org.olat.core.gui.control.generic.messages.MessageUIFactory; import org.olat.core.gui.translator.Translator; import org.olat.core.id.OLATResourceable; @@ -97,6 +101,41 @@ public class RepositoyUIFactory { } } + /** + * Create main controller that does nothing but displaying a message that + * this resource is disabled due to security constraints + * + * @param ureq + * @param wControl + * @return + */ + public static GenericMainController createRepoEntryDisabledDueToSecurityMessageController(UserRequest ureq, WindowControl wControl) { + //wrap simple message into mainLayout + GenericMainController glc = new GenericMainController(ureq, wControl) { + @Override + public void init(UserRequest ureq) { + Panel empty = new Panel("empty"); + setTranslator(Util.createPackageTranslator(this.getClass(), ureq.getLocale())); + MessageController contentCtr = MessageUIFactory.createInfoMessage(ureq, getWindowControl(), translate("security.disabled.title"), translate("security.disabled.info")); + listenTo(contentCtr); // auto dispose later + Component resComp = contentCtr.getInitialComponent(); + LayoutMain3ColsController columnLayoutCtr = new LayoutMain3ColsController(ureq, getWindowControl(), empty, empty, resComp, /*do not save no prefs*/null); + listenTo(columnLayoutCtr); // auto dispose later + putInitialPanel(columnLayoutCtr.getInitialComponent()); + } + + @Override + protected Controller handleOwnMenuTreeEvent(Object uobject, UserRequest ureq) { + //no menutree means no menu events. + return null; + } + + }; + glc.init(ureq); + return glc; + } + + public static Controller createLifecylceAdminController(UserRequest ureq, WindowControl wControl) { Controller ctrl = new LifecycleAdminController(ureq, wControl); return ctrl; diff --git a/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties index f0b7ab756a6..56a12b0a6df 100644 --- a/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties @@ -394,6 +394,8 @@ search.sharedfolder=Ressourcenordner search.survey=Fragebogen search.test=Tests search.wiki=Wikis +security.disabled.title=Lernressource nicht verfügbar +security.disabled.info=Diese Lernressourcen ist aus Sicherheitsgründen gesperrt. Weitere Informationen erhalten Sie von Ihrem Systemadministrator. sf.notconfigured=Kein Ressourcenordner ausgew\u00E4hlt sf.resourcetitle=Gew\u00E4hlter Ressourcenordner tab.accesscontrol=Access control diff --git a/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties index 28f670a9c0a..4b66ed1a4c7 100644 --- a/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties @@ -397,6 +397,8 @@ search.sharedfolder=Resource folder search.survey=Questionnaires search.test=Tests search.wiki=Wikis +security.disabled.title=Learning resource disabled +security.disabled.info=This learning resource is disabled on this system due to security constraints. Ask your system administrator for more information. sf.notconfigured=No resource folder selected sf.resourcetitle=Selected resource folder tab.accesscontrol=Access control diff --git a/src/main/java/org/olat/repository/handlers/WikiHandler.java b/src/main/java/org/olat/repository/handlers/WikiHandler.java index 157e57677c1..146eae7468a 100644 --- a/src/main/java/org/olat/repository/handlers/WikiHandler.java +++ b/src/main/java/org/olat/repository/handlers/WikiHandler.java @@ -33,6 +33,8 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import org.olat.basesecurity.BaseSecurityModule; +import org.olat.core.CoreSpringFactory; import org.olat.core.commons.fullWebApp.LayoutMain3ColsController; import org.olat.core.gui.UserRequest; import org.olat.core.gui.control.Controller; @@ -71,6 +73,7 @@ import org.olat.modules.wiki.WikiSecurityCallbackImpl; import org.olat.modules.wiki.WikiToZipUtils; import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryManager; +import org.olat.repository.RepositoyUIFactory; import org.olat.repository.controllers.AddFileResourceController; import org.olat.repository.controllers.IAddController; import org.olat.repository.controllers.RepositoryAddCallback; @@ -156,6 +159,12 @@ public class WikiHandler implements RepositoryHandler { * org.olat.core.gui.control.WindowControl) */ public MainLayoutController createLaunchController(OLATResourceable res, UserRequest ureq, WindowControl wControl) { + // first handle special case: disabled wiki for security (XSS Attacks) reasons + BaseSecurityModule securityModule = CoreSpringFactory.getImpl(BaseSecurityModule.class); + if (!securityModule.isWikiEnabled()) { + return RepositoyUIFactory.createRepoEntryDisabledDueToSecurityMessageController(ureq, wControl); + } + // proceed with standard case Controller controller = null; //check role @@ -349,5 +358,5 @@ public class WikiHandler implements RepositoryHandler { public WizardCloseResourceController createCloseResourceController(UserRequest ureq, WindowControl wControl, RepositoryEntry repositoryEntry) { throw new AssertException("not implemented"); } - + } diff --git a/src/main/java/org/olat/restapi/group/LearningGroupWebService.java b/src/main/java/org/olat/restapi/group/LearningGroupWebService.java index 70e80169f9f..bfc8abbbc8f 100644 --- a/src/main/java/org/olat/restapi/group/LearningGroupWebService.java +++ b/src/main/java/org/olat/restapi/group/LearningGroupWebService.java @@ -291,10 +291,11 @@ public class LearningGroupWebService { if(selectedTools == null) { selectedTools = new String[0]; } + String[] availableTools = CollaborationToolsFactory.getInstance().getAvailableTools().clone(); CollaborationTools tools = CollaborationToolsFactory.getInstance().getOrCreateCollaborationTools(bg); - for (int i=CollaborationTools.TOOLS.length; i-->0; ) { + for (int i=availableTools.length; i-->0; ) { boolean enable = false; - String tool = CollaborationTools.TOOLS[i]; + String tool = availableTools[i]; for(String selectedTool:selectedTools) { if(tool.equals(selectedTool)) { enable = true; diff --git a/src/test/java/org/olat/group/test/BusinessGroupServiceTest.java b/src/test/java/org/olat/group/test/BusinessGroupServiceTest.java index 3daafbd670a..839d049a82e 100644 --- a/src/test/java/org/olat/group/test/BusinessGroupServiceTest.java +++ b/src/test/java/org/olat/group/test/BusinessGroupServiceTest.java @@ -669,32 +669,33 @@ public class BusinessGroupServiceTest extends OlatTestCase { List<BusinessGroup> sqlRes = businessGroupService.findBusinessGroupsOwnedBy(id2, null); BusinessGroup found = (BusinessGroup) sqlRes.get(0); CollaborationTools myCTSMngr = CollaborationToolsFactory.getInstance().getOrCreateCollaborationTools(found); - for (int i = 0; i < CollaborationTools.TOOLS.length; i++) { - String msg = "Tool " + CollaborationTools.TOOLS[i] + " is enabled"; - boolean enabled = myCTSMngr.isToolEnabled(CollaborationTools.TOOLS[i]); + String[] availableTools = CollaborationToolsFactory.getInstance().getAvailableTools().clone(); + for (int i = 0; i < availableTools.length; i++) { + String msg = "Tool " + availableTools[i] + " is enabled"; + boolean enabled = myCTSMngr.isToolEnabled(availableTools[i]); // all tools are disabled by default exept the news tool assertTrue(msg, !enabled); } - for (int i = 0; i < CollaborationTools.TOOLS.length; i++) { - myCTSMngr.setToolEnabled(CollaborationTools.TOOLS[i], true); + for (int i = 0; i < availableTools.length; i++) { + myCTSMngr.setToolEnabled(availableTools[i], true); } - for (int i = 0; i < CollaborationTools.TOOLS.length; i++) { - String msg = "Tool " + CollaborationTools.TOOLS[i] + " is enabled"; - boolean enabled = myCTSMngr.isToolEnabled(CollaborationTools.TOOLS[i]); + for (int i = 0; i < availableTools.length; i++) { + String msg = "Tool " + availableTools[i] + " is enabled"; + boolean enabled = myCTSMngr.isToolEnabled(availableTools[i]); assertTrue(msg, enabled); } - for (int i = 0; i < CollaborationTools.TOOLS.length; i++) { - myCTSMngr.setToolEnabled(CollaborationTools.TOOLS[i], false); + for (int i = 0; i < availableTools.length; i++) { + myCTSMngr.setToolEnabled(availableTools[i], false); } - for (int i = 0; i < CollaborationTools.TOOLS.length; i++) { - String msg = "Tool " + CollaborationTools.TOOLS[i] + " is disabled"; - boolean enabled = myCTSMngr.isToolEnabled(CollaborationTools.TOOLS[i]); + for (int i = 0; i < availableTools.length; i++) { + String msg = "Tool " + availableTools[i] + " is disabled"; + boolean enabled = myCTSMngr.isToolEnabled(availableTools[i]); assertTrue(msg, !enabled); } } @@ -777,9 +778,10 @@ public class BusinessGroupServiceTest extends OlatTestCase { assertTrue("1 BuddyGroup owned by id2", sqlRes.size() == 1); BusinessGroup found = (BusinessGroup) sqlRes.get(0); CollaborationTools myCTSMngr = CollaborationToolsFactory.getInstance().getOrCreateCollaborationTools(found); + String[] availableTools = CollaborationToolsFactory.getInstance().getAvailableTools().clone(); - for (int i = 0; i < CollaborationTools.TOOLS.length; i++) { - myCTSMngr.setToolEnabled(CollaborationTools.TOOLS[i], true); + for (int i = 0; i < availableTools.length; i++) { + myCTSMngr.setToolEnabled(availableTools[i], true); } businessGroupService.deleteBusinessGroup(found); -- GitLab