diff --git a/pom.xml b/pom.xml index 290ea1521ca8ce7ac521d57d3d7b54ef69020dc8..9f07ccfc7bcb65b63a13e514d5e372d5e664128c 100644 --- a/pom.xml +++ b/pom.xml @@ -1647,7 +1647,7 @@ <dependency> <groupId>org.openolat.jamwiki</groupId> <artifactId>jamwiki-core</artifactId> - <version>1.0.1</version> + <version>1.0.2</version> </dependency> <dependency> <groupId>org.openolat</groupId> diff --git a/src/main/java/org/olat/admin/user/bulkChange/UserBulkChangeManager.java b/src/main/java/org/olat/admin/user/bulkChange/UserBulkChangeManager.java index 3a8ffb6224f3ee8560229e48473e538de0044b11..b3ae1611b8769fb2cec5f57cfb66c1dde4a449c7 100644 --- a/src/main/java/org/olat/admin/user/bulkChange/UserBulkChangeManager.java +++ b/src/main/java/org/olat/admin/user/bulkChange/UserBulkChangeManager.java @@ -41,6 +41,8 @@ import org.olat.core.gui.components.form.ValidationError; import org.olat.core.gui.translator.Translator; import org.olat.core.helpers.Settings; import org.olat.core.id.Identity; +import org.olat.core.id.Organisation; +import org.olat.core.id.OrganisationRef; import org.olat.core.id.Preferences; import org.olat.core.id.Roles; import org.olat.core.id.User; @@ -121,12 +123,7 @@ public class UserBulkChangeManager implements InitializingBean { notUpdatedIdentities.clear(); List<Identity> changedIdentities = new ArrayList<>(); List<UserPropertyHandler> userPropertyHandlers = userManager.getUserPropertyHandlersFor(usageIdentifyer, isAdministrativeUser); - OrganisationRoles[] organisationRoles = { - OrganisationRoles.usermanager, OrganisationRoles.groupmanager, - OrganisationRoles.author, OrganisationRoles.administrator, - OrganisationRoles.poolmanager, OrganisationRoles.learnresourcemanager - }; - + Map<String,String> attributeChangeMap = userBulkChanges.getAttributeChangeMap(); // loop over users to be edited: for (Identity identity : selIdentities) { @@ -209,25 +206,29 @@ public class UserBulkChangeManager implements InitializingBean { } } - } // for (propertyHandlers) + } // for property handlers // set roles for identity // loop over securityGroups defined above Map<OrganisationRoles,String> roleChangeMap = userBulkChanges.getRoleChangeMap(); - for (OrganisationRoles organisationRole : organisationRoles) { - boolean isInGroup = organisationService.hasRole(identity, organisationRole); - String thisRoleAction = ""; - if (roleChangeMap.containsKey(organisationRole)) { - thisRoleAction = roleChangeMap.get(organisationRole); - // user not anymore in security group, remove him - if (isInGroup && thisRoleAction.equals("remove")) { - organisationService.removeMember(identity, organisationRole); - log.info(Tracing.M_AUDIT, "User::" + actingIdentity.getKey() + " removed system role::" + organisationRole + " from user::" + identity.getKey()); - } - // user not yet in security group, add him - if (!isInGroup && thisRoleAction.equals("add")) { - organisationService.addMember(identity, organisationRole); - log.info(Tracing.M_AUDIT, "User::" + actingIdentity.getKey() + " added system role::" + organisationRole + " to user::" + identity.getKey()); + if(!roleChangeMap.isEmpty()) { + OrganisationRef organisationRef = userBulkChanges.getOrganisation(); + Organisation organisation = organisationRef == null + ? organisationService.getDefaultOrganisation() : organisationService.getOrganisation(organisationRef); + for (OrganisationRoles organisationRole : OrganisationRoles.values()) { + if (roleChangeMap.containsKey(organisationRole)) { + boolean isInGroup = organisationService.hasRole(identity, organisation, organisationRole); + String thisRoleAction = roleChangeMap.get(organisationRole); + // user not anymore in security group, remove him + if (isInGroup && thisRoleAction.equals("remove")) { + organisationService.removeMember(organisation, identity, organisationRole, false); + log.info(Tracing.M_AUDIT, "User::{} removed system role::{} from user:: {}", actingIdentity.getKey(), organisationRole, identity); + } + // user not yet in security group, add him + if (!isInGroup && thisRoleAction.equals("add")) { + organisationService.addMember(organisation, identity, organisationRole); + log.info(Tracing.M_AUDIT, "User::{} added system role::{} to user::{}", actingIdentity.getKey(), organisationRole, identity); + } } } } @@ -243,19 +244,21 @@ public class UserBulkChangeManager implements InitializingBean { sendLoginDeniedEmail(identity); } identity = securityManager.saveIdentityStatus(identity, status, actingIdentity); - log.info(Tracing.M_AUDIT, "User::" + actingIdentity.getKey() + " changed account status for user::" + identity.getKey() + " from::" + oldStatusText + " to::" + newStatusText); + log.info(Tracing.M_AUDIT, "User::{} changed account status for user::{} from::{} to::{}", + actingIdentity.getKey(), identity.getKey(), oldStatusText, newStatusText); } // persist changes: if (updateError) { String errorOutput = identity.getKey() + ": " + errorDesc; - log.debug("error during bulkChange of users, following user could not be updated: " + errorOutput); + log.debug("error during bulkChange of users, following user could not be updated: {}", errorOutput); notUpdatedIdentities.add(errorOutput); } else { userManager.updateUserFromIdentity(identity); securityManager.deleteInvalidAuthenticationsByEmail(oldEmail); changedIdentities.add(identity); - log.info(Tracing.M_AUDIT, "User::" + actingIdentity.getKey() + " successfully changed account data for user::" + identity.getKey() + " in bulk change"); + log.info(Tracing.M_AUDIT, "User::{} successfully changed account data for user::{} in bulk change", + actingIdentity.getKey(), identity.getKey()); } // commit changes for this user diff --git a/src/main/java/org/olat/admin/user/bulkChange/UserBulkChangeStep01.java b/src/main/java/org/olat/admin/user/bulkChange/UserBulkChangeStep01.java index 707ba3d5c0d41be6ca9fff42a0fc530d8de7cd4e..9a297e84112d4ab026ddda911428cc86c3fc52c9 100644 --- a/src/main/java/org/olat/admin/user/bulkChange/UserBulkChangeStep01.java +++ b/src/main/java/org/olat/admin/user/bulkChange/UserBulkChangeStep01.java @@ -25,6 +25,8 @@ import java.util.Map; import org.olat.admin.user.SystemRolesAndRightsController; import org.olat.basesecurity.OrganisationRoles; +import org.olat.basesecurity.OrganisationService; +import org.olat.basesecurity.model.OrganisationRefImpl; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.FormItem; import org.olat.core.gui.components.form.flexible.FormItemContainer; @@ -33,6 +35,7 @@ import org.olat.core.gui.components.form.flexible.elements.SingleSelection; import org.olat.core.gui.components.form.flexible.impl.Form; 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.util.KeyValues; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.generic.wizard.BasicStep; @@ -42,11 +45,15 @@ import org.olat.core.gui.control.generic.wizard.StepFormController; import org.olat.core.gui.control.generic.wizard.StepsEvent; import org.olat.core.gui.control.generic.wizard.StepsRunContext; import org.olat.core.id.Identity; +import org.olat.core.id.Organisation; +import org.olat.core.id.OrganisationNameComparator; import org.olat.core.id.Roles; import org.olat.core.util.Util; import org.olat.user.UserManager; import org.springframework.beans.factory.annotation.Autowired; +import edu.emory.mathcs.backport.java.util.Collections; + /** * Description:<br> * first step: select attributes, which should be changed @@ -85,6 +92,7 @@ class UserBulkChangeStep01 extends BasicStep { private final class UserBulkChangeStepForm01 extends StepFormBasicController { private SingleSelection setStatus; + private SingleSelection organisationEl; private MultipleSelectionElement chkStatus; private MultipleSelectionElement sendLoginDeniedEmail; private final List<RoleChange> roleChanges = new ArrayList<>(); @@ -95,6 +103,8 @@ class UserBulkChangeStep01 extends BasicStep { @Autowired private UserManager userManager; + @Autowired + private OrganisationService organisationService; public UserBulkChangeStepForm01(UserRequest ureq, WindowControl control, Form rootForm, StepsRunContext runContext) { super(ureq, control, rootForm, runContext, LAYOUT_VERTICAL, null); @@ -123,8 +133,13 @@ class UserBulkChangeStep01 extends BasicStep { validChange = true; } } + + if(organisationEl != null && organisationEl.isOneSelected()) { + Long organisationkey = Long.valueOf(organisationEl.getSelectedKey()); + userBulkChanges.setOrganisation(new OrganisationRefImpl(organisationkey)); + } - if (chkStatus!=null && chkStatus.isAtLeastSelected(1)) { + if (chkStatus != null && chkStatus.isAtLeastSelected(1)) { userBulkChanges.setStatus(Integer.parseInt(setStatus.getSelectedKey())); // also check dependent send-email checkbox if (sendLoginDeniedEmail != null) { @@ -159,32 +174,39 @@ class UserBulkChangeStep01 extends BasicStep { } private void initRole(OrganisationRoles role, FormItemContainer formLayout) { - MultipleSelectionElement chkAuthor = uifactory.addCheckboxesHorizontal("rolechk_" + (++counter), "table.role." + role.name(), formLayout, onKeys, onValues); - chkAuthor.select("Author", false); - - chkAuthor.addActionListener(FormEvent.ONCLICK); + MultipleSelectionElement chkRole = uifactory.addCheckboxesHorizontal("rolechk_" + (++counter), "table.role." + role.name(), formLayout, onKeys, onValues); + chkRole.addActionListener(FormEvent.ONCLICK); - SingleSelection setAuthor = uifactory.addDropdownSingleselect("roleset_" + (++counter), null, formLayout, addremove, addremoveTranslated, null); - setAuthor.setVisible(false); + SingleSelection setRole = uifactory.addDropdownSingleselect("roleset_" + (++counter), null, formLayout, addremove, addremoveTranslated, null); + setRole.setVisible(false); - RoleChange change = new RoleChange(chkAuthor, setAuthor, OrganisationRoles.author); + RoleChange change = new RoleChange(chkRole, setRole, role); roleChanges.add(change); - chkAuthor.setUserObject(change); + chkRole.setUserObject(change); } @Override protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { setFormTitle("step1.title"); - FormLayoutContainer textContainer = FormLayoutContainer.createCustomFormLayout("index", getTranslator(), this.velocity_root + "/step1.html"); + FormLayoutContainer textContainer = FormLayoutContainer.createCustomFormLayout("index", getTranslator(), velocity_root + "/step1.html"); formLayout.add(textContainer); - // Main layout is a vertical layout without left side padding. To format // the checkboxes properly we need a default layout for the remaining form // elements FormItemContainer innerFormLayout = FormLayoutContainer.createDefaultFormLayout("innerFormLayout", getTranslator()); formLayout.add(innerFormLayout); + + if(userBulkChanges.getOrganisation() == null) { + KeyValues orgKeyValues = getOrganisationKeyValues(ureq); + if(!orgKeyValues.isEmpty()) { + String[] keys = orgKeyValues.keys(); + organisationEl = uifactory.addDropdownSingleselect("organisations", "organisations", innerFormLayout, + keys, orgKeyValues.values()); + organisationEl.select(keys[0], true); + } + } // check user rights: Roles roles = ureq.getUserSession().getRoles(); @@ -200,7 +222,7 @@ class UserBulkChangeStep01 extends BasicStep { OrganisationRoles.linemanager, OrganisationRoles.principal, OrganisationRoles.administrator }; - + for(OrganisationRoles role:roleArr) { initRole(role, innerFormLayout); } @@ -238,6 +260,20 @@ class UserBulkChangeStep01 extends BasicStep { sendLoginDeniedEmail.setVisible(false); } } + + private KeyValues getOrganisationKeyValues(UserRequest ureq) { + Roles roles = ureq.getUserSession().getRoles(); + List<Organisation> organisations = organisationService.getOrganisations(getIdentity(), roles, + OrganisationRoles.administrator, OrganisationRoles.usermanager, OrganisationRoles.rolesmanager); + if(organisations.size() > 1) { + Collections.sort(organisations, new OrganisationNameComparator(getLocale())); + } + KeyValues organisationKeyValues = new KeyValues(); + for(Organisation organisation:organisations) { + organisationKeyValues.add(KeyValues.entry(organisation.getKey().toString(), organisation.getDisplayName())); + } + return organisationKeyValues; + } } private static final class RoleChange { diff --git a/src/main/java/org/olat/admin/user/bulkChange/UserBulkChanges.java b/src/main/java/org/olat/admin/user/bulkChange/UserBulkChanges.java index 6d1080cf3056a2dc2e35c1b86fe74ad492e533f9..b0203dadcafd6d7ab286d07985fea7ad0d1c9a7a 100644 --- a/src/main/java/org/olat/admin/user/bulkChange/UserBulkChanges.java +++ b/src/main/java/org/olat/admin/user/bulkChange/UserBulkChanges.java @@ -27,6 +27,7 @@ import java.util.Map; import org.olat.admin.user.groups.GroupChanges; import org.olat.basesecurity.OrganisationRoles; import org.olat.core.id.Identity; +import org.olat.core.id.OrganisationRef; /** * @@ -46,6 +47,20 @@ public class UserBulkChanges extends GroupChanges { private Integer status; private boolean sendLoginDeniedEmail; + private OrganisationRef organisation; + + public UserBulkChanges(OrganisationRef organisation) { + this.organisation = organisation; + } + + public OrganisationRef getOrganisation() { + return organisation; + } + + public void setOrganisation(OrganisationRef organisation) { + this.organisation = organisation; + } + public Map<OrganisationRoles, String> getRoleChangeMap() { return roleChangeMap; } diff --git a/src/main/java/org/olat/admin/user/bulkChange/_content/step0.html b/src/main/java/org/olat/admin/user/bulkChange/_content/step0.html index 5a4c2d8c24d83b197cbae1ba6c52b54407362320..94b266d501da74d0ab64961f90095827f6d1bfe4 100644 --- a/src/main/java/org/olat/admin/user/bulkChange/_content/step0.html +++ b/src/main/java/org/olat/admin/user/bulkChange/_content/step0.html @@ -1,17 +1,11 @@ -$r.translate("step0.content") -<p>$r.translate("step.notmandatory")</p> -<br /> +<div class="o_desc"><p>$r.translate("step0.content")<br>$r.translate("step.notmandatory")</p></div> #o_togglebox_start("o_usermanagement_bulkChange" "$r.translate('step0.formatexplanation.link')") $r.translate('step0.formatexplanation.text') <table class="table table-bordered"><tbody> #foreach( $propertyHandler in $userPropertyHandlers ) <tr> - <td> - <label> - $r.translate($propertyHandler.i18nFormElementLabelKey()) - </label> - </td> + <th scope="row">$r.translate($propertyHandler.i18nFormElementLabelKey())</th> <td> #set($so='{') #set($sc='}') diff --git a/src/main/java/org/olat/admin/user/bulkChange/_content/step1.html b/src/main/java/org/olat/admin/user/bulkChange/_content/step1.html index 458c08323b31422cf3ea9ed6c00287ae198c88ed..f64f4ad8a3678744534a9648716454b83fb91afa 100644 --- a/src/main/java/org/olat/admin/user/bulkChange/_content/step1.html +++ b/src/main/java/org/olat/admin/user/bulkChange/_content/step1.html @@ -1,2 +1 @@ -$r.translate("step1.content") -<p>$r.translate("step.notmandatory")</p> \ No newline at end of file +<div class="o_desc"><p>$r.translate("step1.content")<br>$r.translate("step.notmandatory")</p></div> \ No newline at end of file diff --git a/src/main/java/org/olat/admin/user/bulkChange/_content/step2.html b/src/main/java/org/olat/admin/user/bulkChange/_content/step2.html index a4b8fde73e0112a8ccace426781d7a02a3b93205..53a57cc98e9d3f9f8d691ec9487279ded3e51fa3 100644 --- a/src/main/java/org/olat/admin/user/bulkChange/_content/step2.html +++ b/src/main/java/org/olat/admin/user/bulkChange/_content/step2.html @@ -1,5 +1,5 @@ #if($validChange=="true") - $r.translate("step2.content") + <div class="o_desc">$r.translate("step2.content")</div> #else - $r.translate("step2.novalidChanges") + <div class="o_error" role="alert">$r.translate("step2.novalidChanges")</div> #end diff --git a/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_de.properties index 44325d35344aeb8c7396fc7ad717a2913595d780..2c65ff15b893100dd665c2f3a6c4b3c3fe415813 100644 --- a/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_de.properties @@ -2,6 +2,7 @@ error.password=$org.olat.user\:error.password.invalid form.name.language=Sprache form.name.pwd=Passwort +organisations=Organisation role.add=hinzuf\u00FCgen role.remove=entfernen step.notmandatory=Dieser Schritt kann \u00FCbersprungen werden, sofern Sie in andernorts \u00C4nderungen vornehmen. diff --git a/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_en.properties index 4100e7dd8d383a274fccdb2968aad12aa2a5c5bd..bad73e76e93a7b949ff6177b65be58a7d68e0d06 100644 --- a/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_en.properties @@ -10,6 +10,7 @@ form.name.language=Language form.name.pwd=Password main.menu.title=OLAT password main.menu.title.alt=Bulk modification of OLAT password +organisations=Organisation role.add=Add role.remove=Remove step.notmandatory=This step is not mandatory provided that there are modifications elsewhere. diff --git a/src/main/java/org/olat/core/util/filter/impl/OpenOLATPolicy.java b/src/main/java/org/olat/core/util/filter/impl/OpenOLATPolicy.java index 35a7c9f80440f195f925ff2d0eb24067dd69b68c..7260236861f1fe3d845ff0a5a0180b729de363fd 100644 --- a/src/main/java/org/olat/core/util/filter/impl/OpenOLATPolicy.java +++ b/src/main/java/org/olat/core/util/filter/impl/OpenOLATPolicy.java @@ -45,11 +45,12 @@ public class OpenOLATPolicy { private static final String MEDIA_HOST = "http://my" + CodeHelper.getForeverUniqueID() + "localhost:8123/"; private static final Pattern PARAGRAPH = Pattern.compile("([\\p{L}\\p{N},'\\.\\s\\-_\\(\\)]|&[0-9]{2};)*"); - private static final Pattern COLORNAME = Pattern.compile("(aqua|black|blue|fuchsia|gray|grey|green|lime|maroon|navy|olive|purple|red|silver|teal|white|yellow)"); + private static final Pattern COLORNAME = Pattern.compile("(aqua|black|blue|fuchsia|gray|grey|green|lime|maroon|navy|olive|rebeccapurple|purple|red|silver|teal|white|yellow)"); private static final Pattern OFFSITEURL = Pattern.compile("(\\s)*((ht)tp(s?)://|mailto:)[\\p{L}\\p{N}]+[\\p{L}\\p{N}\\p{Zs}\\.\\#@\\$%\\+&;:\\-_~,\\?=/!\\(\\)]*(\\s)*"); private static final Pattern HTMLCLASS = Pattern.compile("[a-zA-Z0-9\\s,-_]+"); private static final Pattern ANYTHING = Pattern.compile(".*"); private static final Pattern ONSITEURL = Pattern.compile("([\\p{L}\\p{N}\\p{Zs}/\\.\\?=&\\-~_]|ccrep:)+"); + private static final Pattern ANCHOR = Pattern.compile("#[a-zA-Z0-9_]*"); private static final Pattern NUMBER = Pattern.compile("[0-9]+"); private static final Pattern HTMLTITLE = Pattern.compile("[a-zA-Z0-9\\s-_',:\\[\\]!\\./\\\\\\(\\)%&;\\+#]*"); private static final Pattern OLATINTERNALURL = Pattern.compile("javascript:parent\\.gotonode\\(\\d+\\)"); @@ -156,7 +157,7 @@ public class OpenOLATPolicy { .allowAttributes("rel") .matching(false,"nofollow").onElements("a") .allowAttributes("href") - .matching(new Patterns(ONSITEURL, OFFSITEURL, OLATINTERNALURL)) + .matching(new Patterns(ONSITEURL, OFFSITEURL, OLATINTERNALURL, ANCHOR)) .onElements("a") .allowAttributes("onclick") .matching(new OnClickValues()) @@ -363,22 +364,29 @@ public class OpenOLATPolicy { private final Pattern a; private final Pattern b; private final Pattern c; + private final Pattern d; public Patterns(Pattern a, Pattern b) { this(a, b, null); } public Patterns(Pattern a, Pattern b, Pattern c) { + this(a, b ,c , null); + } + + public Patterns(Pattern a, Pattern b, Pattern c, Pattern d) { this.a = a; this.b = b; this.c = c; + this.d = d; } @Override public boolean apply(String s) { return a.matcher(s).matches() || b.matcher(s).matches() - || c == null || c.matcher(s).matches(); + || c == null || c.matcher(s).matches() + || d == null || d.matcher(s).matches(); } // Needed for Java8 compat with later Guava that extends diff --git a/src/main/java/org/olat/course/assessment/manager/AssessmentModeManagerImpl.java b/src/main/java/org/olat/course/assessment/manager/AssessmentModeManagerImpl.java index af458d05f2883b1a75b26fe25b35c490a75cbc37..7cf3ca98e05ccfb25b5abe643017afe45c71ffc1 100644 --- a/src/main/java/org/olat/course/assessment/manager/AssessmentModeManagerImpl.java +++ b/src/main/java/org/olat/course/assessment/manager/AssessmentModeManagerImpl.java @@ -469,7 +469,6 @@ public class AssessmentModeManagerImpl implements AssessmentModeManager { @Override public boolean isSafelyAllowed(HttpServletRequest request, String safeExamBrowserKeys) { boolean safe = false; - boolean debug = log.isDebugEnabled(); if(StringHelper.containsNonWhitespace(safeExamBrowserKeys)) { String safeExamHash = request.getHeader("x-safeexambrowser-requesthash"); String url = request.getRequestURL().toString(); @@ -488,12 +487,13 @@ public class AssessmentModeManagerImpl implements AssessmentModeManager { } } - if(debug) { - if(safeExamHash == null) { - log.debug("Failed safeexambrowser request hash is null for URL: " + url + " and key: " + safeExamBrowserKey); - } else { - log.debug((safeExamHash.equals(hash) ? "Success" : "Failed") + " : " + safeExamHash +" (Header) " + hash + " (Calculated) for URL: " + url + " and key: " + safeExamBrowserKey); + if(safeExamHash == null) { + log.warn("Failed safeexambrowser request hash is null for URL: {} and key: {}", url, safeExamBrowserKey); + } else { + if(!safe) { + log.warn("Failed safeexambrowser check: {} (Header) {} (Calculated) for URL: {}", safeExamHash, hash, url); } + log.debug("safeexambrowser {} : {} (Header) {} (Calculated) for URL: {} and key: {}", (safeExamHash.equals(hash) ? "Success" : "Failed") , safeExamHash, hash, url, safeExamBrowserKey); } } } else { diff --git a/src/main/java/org/olat/modules/qpool/ui/AbstractItemListController.java b/src/main/java/org/olat/modules/qpool/ui/AbstractItemListController.java index 3bfc3dd9557a75d10c823e8b5e2770e75548af40..dacf1d0100b68a839e59dddc3196444fdc1bd569 100644 --- a/src/main/java/org/olat/modules/qpool/ui/AbstractItemListController.java +++ b/src/main/java/org/olat/modules/qpool/ui/AbstractItemListController.java @@ -190,8 +190,8 @@ public abstract class AbstractItemListController extends FormBasicController columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.coverage)); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.additionalInfos)); if (getSecurityCallback().canUseTaxonomy()) { - columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.taxnonomyLevel)); - columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.taxnonomyPath)); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.taxonomyLevel)); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.taxonomyPath)); } columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.difficulty)); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.stdevDifficulty)); diff --git a/src/main/java/org/olat/modules/qpool/ui/QuestionItemDataModel.java b/src/main/java/org/olat/modules/qpool/ui/QuestionItemDataModel.java index 2acc9a15676d1b7adb6183c06594ce92be913290..7f3943518f53591a46efa25dda125bffc565bac1 100644 --- a/src/main/java/org/olat/modules/qpool/ui/QuestionItemDataModel.java +++ b/src/main/java/org/olat/modules/qpool/ui/QuestionItemDataModel.java @@ -88,8 +88,8 @@ public class QuestionItemDataModel extends DefaultFlexiTableDataSourceModel<Item case additionalInfos: return item.getAdditionalInformations(); case creationDate: return item.getCreationDate(); case lastModified: return item.getLastModified(); - case taxnonomyLevel: return item.getTaxonomyLevelName(); - case taxnonomyPath: return item.getTaxonomicPath(); + case taxonomyLevel: return item.getTaxonomyLevelName(); + case taxonomyPath: return item.getTaxonomicPath(); case difficulty: return MetaUIFactory.bigDToString(item.getDifficulty()); case stdevDifficulty: return MetaUIFactory.bigDToString(item.getStdevDifficulty()); case differentiation: return MetaUIFactory.bigDToString(item.getDifferentiation()); @@ -133,8 +133,8 @@ public class QuestionItemDataModel extends DefaultFlexiTableDataSourceModel<Item additionalInfos("general.additional.informations"), creationDate("technical.creation"), lastModified("technical.lastModified"), - taxnonomyLevel("classification.taxonomy.level"), - taxnonomyPath("classification.taxonomic.path"), + taxonomyLevel("classification.taxonomy.level"), + taxonomyPath("classification.taxonomic.path"), difficulty("question.difficulty"), stdevDifficulty("question.stdevDifficulty"), differentiation("question.differentiation"), diff --git a/src/main/java/org/olat/user/ui/admin/UserSearchTableController.java b/src/main/java/org/olat/user/ui/admin/UserSearchTableController.java index c4eeba18add2e79bb2e9aa9e8ee5431d86ab617b..057f3504cdebfe7289cb2c5b5a808c30b418e6cc 100644 --- a/src/main/java/org/olat/user/ui/admin/UserSearchTableController.java +++ b/src/main/java/org/olat/user/ui/admin/UserSearchTableController.java @@ -70,6 +70,7 @@ import org.olat.core.gui.control.generic.wizard.StepsMainRunController; import org.olat.core.id.Identity; import org.olat.core.id.OLATResourceable; import org.olat.core.id.Organisation; +import org.olat.core.id.OrganisationRef; import org.olat.core.id.Roles; import org.olat.core.id.context.ContextEntry; import org.olat.core.id.context.StateEntry; @@ -434,9 +435,15 @@ public class UserSearchTableController extends FormBasicController implements Ac if(identities.isEmpty()) { return; } + + OrganisationRef selectedOrganisation = null; + if(currentSearchParams != null && currentSearchParams.getOrganisations() != null + && currentSearchParams.getOrganisations().size() == 1) { + selectedOrganisation = currentSearchParams.getOrganisations().get(0); + } // valid selection: load in wizard - final UserBulkChanges userBulkChanges = new UserBulkChanges(); + final UserBulkChanges userBulkChanges = new UserBulkChanges(selectedOrganisation); Step start = new UserBulkChangeStep00(ureq, identities, userBulkChanges); // callback executed in case wizard is finished. StepRunnerCallback finish = (uureq, wwControl, runContext) -> { diff --git a/src/test/java/org/olat/core/util/filter/impl/XSSFilterParamTest.java b/src/test/java/org/olat/core/util/filter/impl/XSSFilterParamTest.java index da04872777d86315424f56f20e754bbd06f33f0e..a8c8d968de69deb6315fc6afe453e6d18b678230 100644 --- a/src/test/java/org/olat/core/util/filter/impl/XSSFilterParamTest.java +++ b/src/test/java/org/olat/core/util/filter/impl/XSSFilterParamTest.java @@ -188,7 +188,12 @@ public class XSSFilterParamTest { { "<a href=\"media/LTT ZUJ SCM 09.09.2019.pdf\">doc</a>", "<a href=\"media/LTT%20ZUJ%20SCM%2009.09.2019.pdf\">doc</a>" }, { "<a href=\"media/LTT%20ZUJ%20SCM%2009.09.2019.pdf\">doc</a>", "<a href=\"media/LTT%20ZUJ%20SCM%2009.09.2019.pdf\">doc</a>" }, { "<p><img class=\"b_float_left\" src=\"media/IMG 1484.jpg\" width=\"74\" height=\"74\" /></p>", "<p><img class=\"b_float_left\" src=\"media/IMG%201484.jpg\" width=\"74\" height=\"74\" /></p>" }, - { null, "" } // be tolerant + // link with anchor + { "<a href=\"#Summary\">Summary</a>", "<a href=\"#Summary\">Summary</a>" }, + { "<a href=\"#Title_1\">Title 1</a>", "<a href=\"#Title_1\">Title 1</a>" }, + { "<a href=\"#Title 1\">Title with space</a>", "<a>Title with space</a>" }, + { "<a href=\"#Title#1\">Title with #</a>", "<a>Title with #</a>" }, + { null, "" } // be tolerant }); } diff --git a/src/test/java/org/olat/course/assessment/manager/AssessmentModeManagerTest.java b/src/test/java/org/olat/course/assessment/manager/AssessmentModeManagerTest.java index 9518c66d33798e96bf0eeb6d5c7d4f07b45a1942..f7bfd3619670dda056283a4173b4125d4795720a 100644 --- a/src/test/java/org/olat/course/assessment/manager/AssessmentModeManagerTest.java +++ b/src/test/java/org/olat/course/assessment/manager/AssessmentModeManagerTest.java @@ -1257,6 +1257,19 @@ public class AssessmentModeManagerTest extends OlatTestCase { boolean allowed = assessmentModeMgr.isSafelyAllowed(request, safeExamBrowserKey); Assert.assertFalse(allowed); } + + @Test + public void isSafelyAllowed_missingHeader() { + String safeExamBrowserKey = "gdfkhjsduzezrutuzsf"; + + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setServerName("localhost"); + request.setScheme("http"); + request.setRequestURI("/unauthorized/url"); + + boolean allowed = assessmentModeMgr.isSafelyAllowed(request, safeExamBrowserKey); + Assert.assertFalse(allowed); + } /** * Create a minimal assessment mode which start one hour before now