diff --git a/src/main/java/org/olat/admin/user/UsermanagerUserSearchForm.java b/src/main/java/org/olat/admin/user/UsermanagerUserSearchForm.java index 4fd7d81ca08dcc7e44306a859ad5a8b9a68fad39..9609293badc35fccf259d85d5b0047a8687c59f1 100644 --- a/src/main/java/org/olat/admin/user/UsermanagerUserSearchForm.java +++ b/src/main/java/org/olat/admin/user/UsermanagerUserSearchForm.java @@ -58,6 +58,7 @@ import org.olat.login.LoginModule; import org.olat.login.auth.AuthenticationProvider; import org.olat.login.oauth.OAuthLoginModule; import org.olat.login.oauth.OAuthSPI; +import org.olat.shibboleth.ShibbolethDispatcher; import org.olat.user.UserManager; import org.olat.user.propertyhandlers.EmailProperty; import org.olat.user.propertyhandlers.UserPropertyHandler; @@ -326,6 +327,9 @@ public class UsermanagerUserSearchForm extends FormBasicController { for(OAuthSPI spi:spis) { apl.add(spi.getProviderName()); } + } else if("ShibGeneric".equals(authKey)) { + apl.add(ShibbolethDispatcher.PROVIDER_SHIB); + apl.add(authKey); } else { apl.add(authKey); } diff --git a/src/main/java/org/olat/core/commons/services/pdf/dispatcher/PdfDeliveryDispatcher.java b/src/main/java/org/olat/core/commons/services/pdf/dispatcher/PdfDeliveryDispatcher.java index 0664b12053fa78c0de7c0696ecab9c2ef6ad6267..8301ddfd6a3a01e7059f9f4f0304830809071538 100644 --- a/src/main/java/org/olat/core/commons/services/pdf/dispatcher/PdfDeliveryDispatcher.java +++ b/src/main/java/org/olat/core/commons/services/pdf/dispatcher/PdfDeliveryDispatcher.java @@ -28,6 +28,7 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.apache.logging.log4j.Logger; import org.olat.core.commons.services.pdf.PdfModule; import org.olat.core.commons.services.pdf.PdfService; import org.olat.core.commons.services.pdf.model.PdfDelivery; @@ -39,7 +40,6 @@ import org.olat.core.gui.components.Window; import org.olat.core.gui.control.creator.ControllerCreator; import org.olat.core.gui.control.generic.popup.PopupBrowserWindow; import org.olat.core.id.Roles; -import org.apache.logging.log4j.Logger; import org.olat.core.logging.Tracing; import org.olat.core.util.FileUtils; import org.olat.core.util.UserSession; @@ -77,32 +77,38 @@ public class PdfDeliveryDispatcher implements Dispatcher { response.sendError(HttpServletResponse.SC_FORBIDDEN); return; } - - String uriPrefix = DispatcherModule.getLegacyUriPrefix(request); - final String origUri = request.getRequestURI(); - String uuid = origUri.substring(uriPrefix.length()); - int indexSuffix = uuid.indexOf('/'); - - String key = null; - String filename = null; - if(indexSuffix > 0) { - key = uuid.substring(0, indexSuffix); - filename = uuid.substring(indexSuffix + 1); - } - - PdfDelivery delivery = cache.get(key); - if(delivery == null) { - response.sendError(HttpServletResponse.SC_NOT_FOUND); - } else if(delivery.getDirectory() != null) { - renderFile(delivery, filename, response); - } else if(delivery.getControllerCreator() != null) { - renderController(delivery, request, response); - } else { - response.sendError(HttpServletResponse.SC_BAD_REQUEST); + + try { + String uriPrefix = DispatcherModule.getLegacyUriPrefix(request); + final String origUri = request.getRequestURI(); + String uuid = origUri.substring(uriPrefix.length()); + int indexSuffix = uuid.indexOf('/'); + + String key = null; + String filename = null; + if(indexSuffix > 0) { + key = uuid.substring(0, indexSuffix); + filename = uuid.substring(indexSuffix + 1); + } + + PdfDelivery delivery = cache.get(key); + if(delivery == null) { + response.sendError(HttpServletResponse.SC_NOT_FOUND); + } else if(origUri.contains("close-window")) { + response.setStatus(HttpServletResponse.SC_OK); + } else if(delivery.getDirectory() != null) { + renderFile(delivery, filename, response); + } else if(delivery.getControllerCreator() != null) { + renderController(delivery, request, response); + } else { + response.sendError(HttpServletResponse.SC_BAD_REQUEST); + } + } catch (IOException e) { + log.error("", e); } } - private void renderController(PdfDelivery delivery, HttpServletRequest request, HttpServletResponse response) { + private synchronized void renderController(PdfDelivery delivery, HttpServletRequest request, HttpServletResponse response) { ControllerCreator creator = delivery.getControllerCreator(); UserRequest ureq = new UserRequestImpl("pdfd", request, response); UserSession usess = ureq.getUserSession(); @@ -113,9 +119,16 @@ public class PdfDeliveryDispatcher implements Dispatcher { usess.setRoles(Roles.userRoles()); } - PopupBrowserWindow pbw = delivery.getWindowControl().getWindowBackOffice() - .getWindowManager().createNewPopupBrowserWindowFor(ureq, creator); - Window window = pbw.getPopupWindowControl().getWindowBackOffice().getWindow(); + Window window; + if(delivery.getWindow() == null) { + PopupBrowserWindow pbw = delivery.getWindowControl().getWindowBackOffice() + .getWindowManager().createNewPopupBrowserWindowFor(ureq, creator); + window = pbw.getPopupWindowControl().getWindowBackOffice().getWindow(); + delivery.setWindow(window); + delivery.setBrowserWindow(pbw); + } else { + window = delivery.getWindow(); + } window.dispatchRequest(ureq, true); } diff --git a/src/main/java/org/olat/core/commons/services/pdf/manager/AthenaPdfSPI.java b/src/main/java/org/olat/core/commons/services/pdf/manager/AthenaPdfSPI.java index 24b2fd50293ef37bd61a57a624f1794a262c2c88..909b1e20ff1db4bdb64897e77a709f32cd69c8e1 100644 --- a/src/main/java/org/olat/core/commons/services/pdf/manager/AthenaPdfSPI.java +++ b/src/main/java/org/olat/core/commons/services/pdf/manager/AthenaPdfSPI.java @@ -41,6 +41,7 @@ import org.olat.core.commons.services.pdf.ui.AthenaPdfSettingsController; import org.olat.core.configuration.AbstractSpringModule; import org.olat.core.gui.UserRequest; import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.Disposable; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.creator.ControllerCreator; import org.olat.core.helpers.Settings; @@ -143,6 +144,9 @@ public class AthenaPdfSPI extends AbstractSpringModule implements PdfSPI { cache.put(key, delivery); render(key, "index.html", out); cache.remove(key); + if(delivery.getBrowserWindow() instanceof Disposable) { + ((Disposable)delivery.getBrowserWindow()).dispose(); + } } private void render(String key, String rootFilename, OutputStream out) { @@ -184,7 +188,7 @@ public class AthenaPdfSPI extends AbstractSpringModule implements PdfSPI { if(response.getStatusLine().getStatusCode() == 200) { copyResponse(response, out); } else { - log.error("Cannot renderer PDF: " + response.getStatusLine().getStatusCode()); + log.error("Cannot renderer PDF: {}", response.getStatusLine().getStatusCode()); EntityUtils.consume(response.getEntity()); } } catch(IOException e) { diff --git a/src/main/java/org/olat/core/commons/services/pdf/model/PdfDelivery.java b/src/main/java/org/olat/core/commons/services/pdf/model/PdfDelivery.java index 6b028050d49b7b896e1a315f43407e86c884326c..3f002124733e6747730dff8f25842f658f07590e 100644 --- a/src/main/java/org/olat/core/commons/services/pdf/model/PdfDelivery.java +++ b/src/main/java/org/olat/core/commons/services/pdf/model/PdfDelivery.java @@ -21,8 +21,10 @@ package org.olat.core.commons.services.pdf.model; import java.io.Serializable; +import org.olat.core.gui.components.Window; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.creator.ControllerCreator; +import org.olat.core.gui.control.generic.popup.PopupBrowserWindow; import org.olat.core.id.Identity; /** @@ -37,8 +39,11 @@ public class PdfDelivery implements Serializable { private final String key; private String directory; private Identity identity; - private ControllerCreator controllerCreator; + + private Window window; private WindowControl windowControl; + private PopupBrowserWindow browserWindow; + private ControllerCreator controllerCreator; public PdfDelivery(String key) { this.key = key; @@ -64,6 +69,14 @@ public class PdfDelivery implements Serializable { this.identity = identity; } + public Window getWindow() { + return window; + } + + public void setWindow(Window window) { + this.window = window; + } + public WindowControl getWindowControl() { return windowControl; } @@ -80,6 +93,14 @@ public class PdfDelivery implements Serializable { this.controllerCreator = controllerCreator; } + public PopupBrowserWindow getBrowserWindow() { + return browserWindow; + } + + public void setBrowserWindow(PopupBrowserWindow browserWindow) { + this.browserWindow = browserWindow; + } + @Override public int hashCode() { return key.hashCode(); diff --git a/src/main/java/org/olat/course/learningpath/ui/_i18n/LocalStrings_it.properties b/src/main/java/org/olat/course/learningpath/ui/_i18n/LocalStrings_it.properties new file mode 100644 index 0000000000000000000000000000000000000000..c919bb513345c51843167e4e5a793243a9c735b3 --- /dev/null +++ b/src/main/java/org/olat/course/learningpath/ui/_i18n/LocalStrings_it.properties @@ -0,0 +1,4 @@ +access.provider.name=Percorso +identities.list.title=Percorsi +identity.list.title=Percorso +pane.tab.learning.path=Percorso diff --git a/src/main/java/org/olat/course/nodes/opencast/ui/OpencastConfigController.java b/src/main/java/org/olat/course/nodes/opencast/ui/OpencastConfigController.java index b21826094da16d49f72c6ade713d81b462e2ee9a..28acd200702ff5d855872d8e7a4156eaf1e9fe91 100644 --- a/src/main/java/org/olat/course/nodes/opencast/ui/OpencastConfigController.java +++ b/src/main/java/org/olat/course/nodes/opencast/ui/OpencastConfigController.java @@ -37,8 +37,11 @@ import org.olat.core.util.StringHelper; import org.olat.course.editor.NodeEditController; import org.olat.course.nodes.OpencastCourseNode; import org.olat.modules.ModuleConfiguration; +import org.olat.modules.opencast.AuthDelegate; import org.olat.modules.opencast.OpencastEventProvider; import org.olat.modules.opencast.OpencastSeriesProvider; +import org.olat.modules.opencast.OpencastService; +import org.springframework.beans.factory.annotation.Autowired; /** * @@ -63,6 +66,9 @@ public class OpencastConfigController extends FormBasicController { private final ModuleConfiguration config; + @Autowired + private OpencastService opncastService; + public OpencastConfigController(UserRequest ureq, WindowControl wControl, OpencastCourseNode courseNode) { super(ureq, wControl); config = courseNode.getModuleConfiguration(); @@ -73,6 +79,8 @@ public class OpencastConfigController extends FormBasicController { @Override protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + setFormTranslatedDescription(getFormDescription()); + displayEl = uifactory.addRadiosVertical("config.display", formLayout, DISPLAY_KEYS, translateAll(getTranslator(), DISPLAY_KEYS)); displayEl.addActionListener(FormEvent.ONCHANGE); String selectedKey = config.has(OpencastCourseNode.CONFIG_EVENT_IDENTIFIER)? DISPLAY_KEY_EVENT: DISPLAY_KEY_SERIES; @@ -110,6 +118,18 @@ public class OpencastConfigController extends FormBasicController { formLayout.add(buttonsCont); uifactory.addFormSubmitButton("save", buttonsCont); } + + private String getFormDescription() { + StringBuilder sb = new StringBuilder(); + sb.append(translate("config.desc.select")); + AuthDelegate authDelegate = opncastService.getAuthDelegate(getIdentity()); + if (AuthDelegate.Type.User == authDelegate.getType()) { + sb.append(" ").append(translate("config.desc.user", new String[] {authDelegate.getValue()})); + } else if (AuthDelegate.Type.Roles == authDelegate.getType()) { + sb.append(" ").append(translate("config.desc.roles", new String[] {authDelegate.getValue()})); + } + return sb.toString(); + } private void updateUI() { boolean seriesSelected = displayEl.isOneSelected() && displayEl.getSelectedKey().equals(DISPLAY_KEY_SERIES); diff --git a/src/main/java/org/olat/course/nodes/opencast/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/nodes/opencast/ui/_i18n/LocalStrings_de.properties index 9a822269ad59ec04f68eb17dce31445770974660..ec18426e0831abafcaf0814cf156be39d05b167a 100644 --- a/src/main/java/org/olat/course/nodes/opencast/ui/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/course/nodes/opencast/ui/_i18n/LocalStrings_de.properties @@ -1,3 +1,6 @@ +config.desc.roles=Sie erhalten alle Serien/Videos der Rollen '{0}'. +config.desc.select=W\u00e4hlen Sie eine Serie oder ein Video aus, indem sie im Feld unten nach seinem Titel suchen. +config.desc.user=Sie erhalten alle Serien/Videos f\u00fcr den Benutzer '{0}'. config.display=Anzeige config.display.event=Video config.display.series=Serie diff --git a/src/main/java/org/olat/course/nodes/opencast/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/nodes/opencast/ui/_i18n/LocalStrings_en.properties index f80c77daa657fba31d1f4d7e34b8014d6dca6847..2e16549c2d909bdca831bba1820bcba53d850e0a 100644 --- a/src/main/java/org/olat/course/nodes/opencast/ui/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/course/nodes/opencast/ui/_i18n/LocalStrings_en.properties @@ -1,3 +1,6 @@ +config.desc.roles=You will get all series/videos of roles '{0}'. +config.desc.select=Select a series or a video by searching for its title in the field below. +config.desc.user=You will get all series/videos of user '{0}'. config.display=Display config.display.event=Video config.display.series=Series diff --git a/src/main/java/org/olat/course/run/_i18n/LocalStrings_it.properties b/src/main/java/org/olat/course/run/_i18n/LocalStrings_it.properties index dcc1e09f127e391588de8ae292b95e03976a79af..e4d5a223fe54672669a40a9d43182b1e6d9c00e5 100644 --- a/src/main/java/org/olat/course/run/_i18n/LocalStrings_it.properties +++ b/src/main/java/org/olat/course/run/_i18n/LocalStrings_it.properties @@ -12,6 +12,7 @@ command.coursechatlog=Registro chat command.courseconfig=Visione dettagliata command.coursefolder=Cartella di deposito command.coursesearch=Ricerca nel corso +command.documents=Documenti command.efficiencystatement=Attestato di efficienza command.glossary=Glossario command.glossary.off=disattivato @@ -20,6 +21,8 @@ command.glossary.on=attivato command.glossary.on.alt=Mostrare termini nel contenuto didattico command.glossary.open=Aprire il glossario in una nuova finestra command.layout=Layout +command.learning.path=Percorso +command.learning.paths=Percorso command.next=Vai alla pagina seguente command.openarchiver=Archiviazione dati command.openassessment=Strumento di valutazione @@ -34,6 +37,7 @@ command.openteststatistic=Statistiche dei test command.options=Opzioni command.options.certificates=Attestato di efficienza command.options.reminders=Promemoria +command.participant.info=Info partecipanti command.personalnote=Appunti command.previous=Vai alla pagina precedente command.reminders=Promemoria @@ -56,6 +60,7 @@ error.editoralreadylocked=Il corso viene attualmente editato da {0}. error.editoralreadylocked.same.user=$\:error.editoralreadylocked $org.olat.core\:lock.same.user.different.window error.invalid.group=Lei \u00E8 stata/o disiscritta/o da questo gruppo. Il gruppo non pu\u00F2 pi\u00F9 essere visualizzato. error.noglossary=Il glossario non \u00E8 attualmente disponibile +header.tools=Amministrazione header.tools.general=Generale header.tools.mycourse=Il mio corso header.tools.ownerGroups=Gruppi con tutorato diff --git a/src/main/java/org/olat/ims/qti21/ui/QTI21AssessmentDetailsController.java b/src/main/java/org/olat/ims/qti21/ui/QTI21AssessmentDetailsController.java index bfe631325f178e21f4db3feeec12816b4b7fc317..f762eb9e9e8fc5757d00a020c42fe451868cc707 100644 --- a/src/main/java/org/olat/ims/qti21/ui/QTI21AssessmentDetailsController.java +++ b/src/main/java/org/olat/ims/qti21/ui/QTI21AssessmentDetailsController.java @@ -286,9 +286,11 @@ public class QTI21AssessmentDetailsController extends FormBasicController { } infos.add(forgeDetailsRow(sessionStatistics)); } - correctionCol.setAlwaysVisible(manualCorrections); - correctionCol.setDefaultVisible(manualCorrections); - tableEl.setColumnModelVisible(correctionCol, manualCorrections); + if(correctionCol != null) { + correctionCol.setAlwaysVisible(manualCorrections); + correctionCol.setDefaultVisible(manualCorrections); + tableEl.setColumnModelVisible(correctionCol, manualCorrections); + } Collections.sort(infos, new AssessmentTestSessionDetailsComparator()); tableModel.setObjects(infos); diff --git a/src/main/java/org/olat/modules/bigbluebutton/manager/BigBlueButtonManagerImpl.java b/src/main/java/org/olat/modules/bigbluebutton/manager/BigBlueButtonManagerImpl.java index 8214923b3fd069cb5e6ac1a374767ee93d367dc3..1d03d94f84948f1a50806b4a631feb03636d3818 100644 --- a/src/main/java/org/olat/modules/bigbluebutton/manager/BigBlueButtonManagerImpl.java +++ b/src/main/java/org/olat/modules/bigbluebutton/manager/BigBlueButtonManagerImpl.java @@ -796,9 +796,6 @@ public class BigBlueButtonManagerImpl implements BigBlueButtonManager, .optionalParameter("userdata-bbb_auto_share_webcam", "true") .optionalParameter("userdata-bbb_show_participants_on_login", "false"); } - - getRecordingsHandler().appendMetadata(uriBuilder, meeting); - return uriBuilder .build() .toString(); @@ -911,6 +908,9 @@ public class BigBlueButtonManagerImpl implements BigBlueButtonManager, .optionalParameter("guestPolicy", GuestPolicyEnum.ALWAYS_ACCEPT.name()); } + // metadata + getRecordingsHandler().appendMetadata(uriBuilder, meeting); + Document doc = sendRequest(uriBuilder, errors); return BigBlueButtonUtils.checkSuccess(doc, errors); } diff --git a/src/main/java/org/olat/modules/bigbluebutton/manager/BigBlueButtonOpenCastRecordingsHandler.java b/src/main/java/org/olat/modules/bigbluebutton/manager/BigBlueButtonOpenCastRecordingsHandler.java index 9bc6c77da867e0c00fcedc6bc67d0fa2eceb369b..b88fe774c722216d9ca8518f2943e06ff6c873f8 100644 --- a/src/main/java/org/olat/modules/bigbluebutton/manager/BigBlueButtonOpenCastRecordingsHandler.java +++ b/src/main/java/org/olat/modules/bigbluebutton/manager/BigBlueButtonOpenCastRecordingsHandler.java @@ -130,9 +130,9 @@ public class BigBlueButtonOpenCastRecordingsHandler implements BigBlueButtonReco Date meetingCreation = (meeting.getStartDate() != null ? meeting.getStartDate() : meeting.getCreationDate()); // Title of the episode - uriBuilder.optionalParameter("meta_dc-title", Formatter.formatDateFilesystemSave(meetingCreation) + " - " + meeting.getName()); + uriBuilder.optionalParameter("meta_opencast-dc-title", Formatter.formatDateFilesystemSave(meetingCreation) + " - " + meeting.getName()); // Media package and event identifier - uriBuilder.optionalParameter("meta_dc-identifier", meeting.getMeetingId()); + uriBuilder.optionalParameter("meta_opencast-dc-identifier", meeting.getMeetingId()); User creator = null; if(meeting.getCreator() != null) { @@ -140,7 +140,7 @@ public class BigBlueButtonOpenCastRecordingsHandler implements BigBlueButtonReco String creatorFirstLastName = creatorFirstLastName(creator); if(StringHelper.containsNonWhitespace(creatorFirstLastName)) { - uriBuilder.optionalParameter("meta_dc-creator", creatorFirstLastName); + uriBuilder.optionalParameter("meta_opencast-dc-creator", creatorFirstLastName); } String username; @@ -150,8 +150,9 @@ public class BigBlueButtonOpenCastRecordingsHandler implements BigBlueButtonReco username = meeting.getCreator().getName(); } if(StringHelper.containsNonWhitespace(username)) { - uriBuilder.optionalParameter("meta_dc-rightsHolder", username); - uriBuilder.optionalParameter("meta_opencast-acl-read-roles", "ROLE_OAUTH_USER ROLE_USER_" + username); + uriBuilder.optionalParameter("meta_opencast-dc-rightsHolder", username); + uriBuilder.optionalParameter("meta_opencast-acl-read-roles", "ROLE_USER_" + username.toUpperCase()); + uriBuilder.optionalParameter("meta_opencast-acl-write-roles", "ROLE_USER_" + username.toUpperCase()); } } @@ -178,19 +179,19 @@ public class BigBlueButtonOpenCastRecordingsHandler implements BigBlueButtonReco } } } - uriBuilder.optionalParameter("meta_dc-isPartOf", context); + uriBuilder.optionalParameter("meta_opencast-dc-isPartOf", context); // The primary language if (re != null && StringHelper.containsNonWhitespace(re.getMainLanguage())) { - uriBuilder.optionalParameter("meta_dc-language", re.getMainLanguage().trim()); + uriBuilder.optionalParameter("meta_opencast-dc-language", re.getMainLanguage().trim().toUpperCase()); } // Location of the event - uriBuilder.optionalParameter("meta_dc-spatial", "Olat-BigBlueButton"); + uriBuilder.optionalParameter("meta_opencast-dc-spatial", "OpenOlat-BigBlueButton"); // Date of the event - uriBuilder.optionalParameter("meta_dc-created", Formatter.formatDatetime(meetingCreation)); + uriBuilder.optionalParameter("meta_opencast-dc-created", Formatter.formatDatetime(meetingCreation)); - uriBuilder.optionalParameter("meta_opencast-series-dc-title", seriesTitle); + uriBuilder.optionalParameter("meta_opencast-meta_series-dc-title", seriesTitle); } private String creatorFirstLastName(User creator) { diff --git a/src/main/java/org/olat/modules/bigbluebutton/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/bigbluebutton/ui/_i18n/LocalStrings_de.properties index 05ca5de9c2ddf10fbbedfadf194df1a9661309c7..93900a5ccdf442aadf1c6bd47454295b25afdf33 100644 --- a/src/main/java/org/olat/modules/bigbluebutton/ui/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/modules/bigbluebutton/ui/_i18n/LocalStrings_de.properties @@ -119,7 +119,7 @@ option.enabled.server=Server aktivieren option.recordingurl=Aufzeichnung URL publish.recording=Publizieren publish.to=Publizieren -publish.to.all=Alle Teilnehmer des Meetings (aussen G\u00E4ste) +publish.to.all=Alle Teilnehmer des Meetings (ausser G\u00e4ste) publish.to.guest=G\u00e4ste publish.to.list=Publizieren f\u00fcr: publish.to.coach=Besitzer / Betreuer diff --git a/src/main/java/org/olat/modules/ceditor/ui/ImageRunController.java b/src/main/java/org/olat/modules/ceditor/ui/ImageRunController.java index 257560519ef8717672f950506d70f07f1c12f3a6..42d888faf5893f7973c2aa78b8686cb6cfa8569c 100644 --- a/src/main/java/org/olat/modules/ceditor/ui/ImageRunController.java +++ b/src/main/java/org/olat/modules/ceditor/ui/ImageRunController.java @@ -180,6 +180,8 @@ public class ImageRunController extends BasicController implements PageRunElemen @Override protected void doDispose() { - // + if(imageCmp != null) { + imageCmp.dispose(); + } } } diff --git a/src/main/java/org/olat/modules/ceditor/ui/PageController.java b/src/main/java/org/olat/modules/ceditor/ui/PageController.java index 15d202253bc1c7b510f2770ad0823f022887d168..065c30919e6c6f94e343c132206315e0ea69c1b5 100644 --- a/src/main/java/org/olat/modules/ceditor/ui/PageController.java +++ b/src/main/java/org/olat/modules/ceditor/ui/PageController.java @@ -72,7 +72,7 @@ public class PageController extends BasicController { @Override protected void doDispose() { - // + fragmentsCmp.dispose(); } public boolean validateElements(UserRequest ureq, List<ValidationMessage> messages) { diff --git a/src/main/java/org/olat/modules/ceditor/ui/PageRunControllerElement.java b/src/main/java/org/olat/modules/ceditor/ui/PageRunControllerElement.java index 227c4cb5223e689bb8cf81e8626392dbffaf80ab..5f712b52c107c1b8455e30f16e43cd596578909d 100644 --- a/src/main/java/org/olat/modules/ceditor/ui/PageRunControllerElement.java +++ b/src/main/java/org/olat/modules/ceditor/ui/PageRunControllerElement.java @@ -24,6 +24,7 @@ import java.util.List; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.Component; import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.Disposable; import org.olat.modules.ceditor.PageRunElement; import org.olat.modules.ceditor.ValidatingController; @@ -33,13 +34,20 @@ import org.olat.modules.ceditor.ValidatingController; * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com * */ -public class PageRunControllerElement implements PageRunElement { +public class PageRunControllerElement implements PageRunElement, Disposable { private Controller controller; public PageRunControllerElement(Controller controller) { this.controller = controller; } + + @Override + public void dispose() { + if(controller != null) { + controller.dispose(); + } + } @Override public Component getComponent() { diff --git a/src/main/java/org/olat/modules/ceditor/ui/component/PageFragmentsComponent.java b/src/main/java/org/olat/modules/ceditor/ui/component/PageFragmentsComponent.java index 820099af2dd87dc66612f0946737ad0737994f58..0521cb6d5c72cb7041ba19a169cbacfb6bf19d56 100644 --- a/src/main/java/org/olat/modules/ceditor/ui/component/PageFragmentsComponent.java +++ b/src/main/java/org/olat/modules/ceditor/ui/component/PageFragmentsComponent.java @@ -27,6 +27,7 @@ import org.olat.core.gui.components.AbstractComponent; import org.olat.core.gui.components.Component; import org.olat.core.gui.components.ComponentCollection; import org.olat.core.gui.components.ComponentRenderer; +import org.olat.core.gui.control.Disposable; import org.olat.modules.ceditor.ui.ValidationMessage; import org.olat.modules.ceditor.ui.model.PageFragment; @@ -36,7 +37,7 @@ import org.olat.modules.ceditor.ui.model.PageFragment; * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com * */ -public class PageFragmentsComponent extends AbstractComponent implements ComponentCollection { +public class PageFragmentsComponent extends AbstractComponent implements ComponentCollection, Disposable { private static final PageFragmentsComponentRenderer RENDERER = new PageFragmentsComponentRenderer(); @@ -79,6 +80,19 @@ public class PageFragmentsComponent extends AbstractComponent implements Compone return components; } + @Override + public void dispose() { + List<PageFragment> fragmentList = getFragments(); + for(PageFragment fragment:fragmentList) { + if(fragment.getPageRunElement() instanceof Disposable) { + ((Disposable)fragment.getPageRunElement()).dispose(); + } + if(fragment.getPageElement() instanceof Disposable) { + ((Disposable)fragment.getPageElement()).dispose(); + } + } + } + public boolean validateElements(UserRequest ureq, List<ValidationMessage> messages) { boolean allOk = true; List<PageFragment> fragmentList = getFragments(); diff --git a/src/main/java/org/olat/modules/portfolio/ui/media/VideoMediaController.java b/src/main/java/org/olat/modules/portfolio/ui/media/VideoMediaController.java index a11031dab8cd74389ad80784967c772efba0ebbe..e5a67901f90ffbb75f2af5ec37def263da64d3f2 100644 --- a/src/main/java/org/olat/modules/portfolio/ui/media/VideoMediaController.java +++ b/src/main/java/org/olat/modules/portfolio/ui/media/VideoMediaController.java @@ -42,6 +42,8 @@ import org.olat.modules.portfolio.ui.MediaMetadataController; */ public class VideoMediaController extends BasicController { + private final ImageComponent videoCmp; + public VideoMediaController(UserRequest ureq, WindowControl wControl, Media media, MediaRenderingHints hints) { super(ureq, wControl); @@ -49,7 +51,7 @@ public class VideoMediaController extends BasicController { File mediaDir = new File(FolderConfig.getCanonicalRoot(), media.getStoragePath()); File mediaFile = new File(mediaDir, media.getRootFilename()); - ImageComponent videoCmp = new ImageComponent(ureq.getUserSession(), "image"); + videoCmp = new ImageComponent(ureq.getUserSession(), "image"); videoCmp.setMedia(mediaFile); mainVC.put("video", videoCmp); mainVC.contextPut("pdf", hints.isToPdf()); @@ -77,6 +79,6 @@ public class VideoMediaController extends BasicController { @Override protected void doDispose() { - // + videoCmp.dispose(); } } diff --git a/src/main/java/org/olat/modules/quality/generator/manager/QualityGeneratorServiceImpl.java b/src/main/java/org/olat/modules/quality/generator/manager/QualityGeneratorServiceImpl.java index 6a41bed7af9f37631b0b5fecf0472fcee343106f..7ecb87b7782725a6334ef789fbff4761c82aa0c2 100644 --- a/src/main/java/org/olat/modules/quality/generator/manager/QualityGeneratorServiceImpl.java +++ b/src/main/java/org/olat/modules/quality/generator/manager/QualityGeneratorServiceImpl.java @@ -222,8 +222,9 @@ public class QualityGeneratorServiceImpl implements QualityGeneratorService { Date now = new Date(); List<QualityDataCollection> dataCollections = provider.generate(generator, configs, generator.getLastRun(), now); copyReportAccess(generator, dataCollections); - generator.setLastRun(now); - generatorDao.save(generator); + QualityGenerator reloadedGenerator = generatorDao.loadByKey(generator); + reloadedGenerator.setLastRun(now); + generatorDao.save(reloadedGenerator); if (!dataCollections.isEmpty()) { log.info(dataCollections.size() + " data collections created by generator " + generator.toString()); } diff --git a/src/main/java/org/olat/modules/quality/generator/provider/courselectures/CourseLecturesFollowUpProvider.java b/src/main/java/org/olat/modules/quality/generator/provider/courselectures/CourseLecturesFollowUpProvider.java index 7b39cecea07495e5103e070c5b421ea082b0a79e..1e2b37e91f6f898005fb9c8bb4f0715da88504b9 100644 --- a/src/main/java/org/olat/modules/quality/generator/provider/courselectures/CourseLecturesFollowUpProvider.java +++ b/src/main/java/org/olat/modules/quality/generator/provider/courselectures/CourseLecturesFollowUpProvider.java @@ -31,7 +31,9 @@ import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Locale; +import java.util.function.Predicate; +import org.apache.logging.log4j.Logger; import org.olat.basesecurity.BaseSecurityManager; import org.olat.basesecurity.GroupRoles; import org.olat.core.gui.UserRequest; @@ -43,6 +45,7 @@ import org.olat.core.gui.translator.Translator; import org.olat.core.id.Identity; import org.olat.core.id.Organisation; import org.olat.core.id.OrganisationRef; +import org.olat.core.logging.Tracing; import org.olat.core.util.StringHelper; import org.olat.core.util.Util; import org.olat.modules.forms.EvaluationFormManager; @@ -88,6 +91,8 @@ import org.springframework.stereotype.Service; @Service public class CourseLecturesFollowUpProvider implements QualityGeneratorProvider { + private static final Logger log = Tracing.createLoggerFor(CourseLecturesFollowUpProvider.class); + public static final String CONFIG_KEY_DURATION_DAYS = "duration.days"; public static final String CONFIG_KEY_GRADE_TOTAL_LIMIT = "grade.total.limit"; public static final String CONFIG_KEY_GRADE_TOTAL_CHECK_KEY = "grade.total.check.key"; @@ -148,7 +153,7 @@ public class CourseLecturesFollowUpProvider implements QualityGeneratorProvider SearchParameters searchParams = getSeachParameters(generator, configs, organisations, fromDate, toDate, previousGeneratorRef, previosGeneratorConfigs); - List<LectureBlockInfo> lectureBlockInfos = providerDao.loadLectureBlockInfo(searchParams); + List<LectureBlockInfo> lectureBlockInfos = loadLectureBlockInfo(generator, configs, searchParams); lectureBlockInfos.removeIf(lb -> gradeIsSufficient(lb, configs, previousGeneratorRef, previosGeneratorConfigs)); int count = lectureBlockInfos.size(); @@ -190,7 +195,7 @@ public class CourseLecturesFollowUpProvider implements QualityGeneratorProvider SearchParameters searchParams = getSeachParameters(generator, configs, organisations, fromDate, toDate, previousGeneratorRef, previosGeneratorConfigs); - List<LectureBlockInfo> lectureBlockInfos = providerDao.loadLectureBlockInfo(searchParams); + List<LectureBlockInfo> lectureBlockInfos = loadLectureBlockInfo(generator, configs, searchParams); lectureBlockInfos.removeIf(lb -> gradeIsSufficient(lb, configs, previousGeneratorRef, previosGeneratorConfigs)); List<QualityDataCollection> dataCollections = new ArrayList<>(); @@ -201,6 +206,22 @@ public class CourseLecturesFollowUpProvider implements QualityGeneratorProvider } return dataCollections; } + + private List<LectureBlockInfo> loadLectureBlockInfo(QualityGenerator generator, QualityGeneratorConfigs configs, + SearchParameters searchParams) { + log.debug("Generator {} searches with {}", generator, searchParams); + + List<LectureBlockInfo> blockInfos = providerDao.loadLectureBlockInfo(searchParams); + log.debug("Generator {} found {} entries", generator, blockInfos.size()); + + String minutesBeforeEnd = configs.getValue(CONFIG_KEY_MINUTES_BEFORE_END); + String duration = configs.getValue(CONFIG_KEY_DURATION_DAYS); + Predicate<? super LectureBlockInfo> deadlineIsInPast = new DeadlineIsInPast(minutesBeforeEnd, duration); + blockInfos.removeIf(deadlineIsInPast); + log.debug("Generator {} has {} entries after removal of entries with deadline in past.", generator, blockInfos.size()); + + return blockInfos; + } private QualityDataCollection generateDataCollection(QualityGenerator generator, QualityGeneratorConfigs configs, List<Organisation> organisations, LectureBlockInfo lectureBlockInfo, diff --git a/src/main/java/org/olat/modules/quality/generator/provider/courselectures/CourseLecturesProvider.java b/src/main/java/org/olat/modules/quality/generator/provider/courselectures/CourseLecturesProvider.java index 6bca758878fb6e2ce414aef1f43e4c240166b0f2..50e4563e33c518c7c0995737fbc473124be2292b 100644 --- a/src/main/java/org/olat/modules/quality/generator/provider/courselectures/CourseLecturesProvider.java +++ b/src/main/java/org/olat/modules/quality/generator/provider/courselectures/CourseLecturesProvider.java @@ -30,6 +30,7 @@ import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Locale; +import java.util.function.Predicate; import org.apache.logging.log4j.Logger; import org.olat.basesecurity.BaseSecurityManager; @@ -141,19 +142,11 @@ public class CourseLecturesProvider implements QualityGeneratorProvider { List<Organisation> organisations = generatorService.loadGeneratorOrganisations(generator); SearchParameters searchParams = getSeachParameters(generator, configs, organisations, fromDate, toDate); - Long count = loadLectureBlockCount(generator, searchParams); + int count = loadLectureBlockInfo(generator, configs, searchParams).size(); return translator.translate("generate.info", new String[] { String.valueOf(count)}); } - private Long loadLectureBlockCount(QualityGenerator generator, SearchParameters searchParams) { - if(log.isDebugEnabled()) log.debug("Generator " + generator + " searches with " + searchParams); - - Long count = providerDao.loadLectureBlockCount(searchParams); - if(log.isDebugEnabled()) log.debug("Generator " + generator + " found " + count + " entries"); - return count; - } - @Override public boolean hasWhiteListController() { return true; @@ -183,7 +176,7 @@ public class CourseLecturesProvider implements QualityGeneratorProvider { Date fromDate, Date toDate) { List<Organisation> organisations = generatorService.loadGeneratorOrganisations(generator); SearchParameters searchParams = getSeachParameters(generator, configs, organisations, fromDate, toDate); - List<LectureBlockInfo> infos = loadLectureBlockInfo(generator, searchParams); + List<LectureBlockInfo> infos = loadLectureBlockInfo(generator, configs, searchParams); List<QualityDataCollection> dataCollections = new ArrayList<>(); for (LectureBlockInfo lectureBlockInfo: infos) { @@ -193,11 +186,19 @@ public class CourseLecturesProvider implements QualityGeneratorProvider { return dataCollections; } - private List<LectureBlockInfo> loadLectureBlockInfo(QualityGenerator generator, SearchParameters searchParams) { - if(log.isDebugEnabled()) log.debug("Generator " + generator + " searches with " + searchParams); + private List<LectureBlockInfo> loadLectureBlockInfo(QualityGenerator generator, QualityGeneratorConfigs configs, + SearchParameters searchParams) { + log.debug("Generator {} searches with {}", generator, searchParams); List<LectureBlockInfo> blockInfos = providerDao.loadLectureBlockInfo(searchParams); - if(log.isDebugEnabled()) log.debug("Generator " + generator + " found " + blockInfos.size() + " entries"); + log.debug("Generator {} found {} entries", generator, blockInfos.size()); + + String minutesBeforeEnd = configs.getValue(CONFIG_KEY_MINUTES_BEFORE_END); + String duration = configs.getValue(CONFIG_KEY_DURATION_DAYS); + Predicate<? super LectureBlockInfo> deadlineIsInPast = new DeadlineIsInPast(minutesBeforeEnd, duration); + blockInfos.removeIf(deadlineIsInPast); + log.debug("Generator {} has {} entries after removal of entries with deadline in past..", generator, blockInfos.size()); + return blockInfos; } @@ -210,18 +211,17 @@ public class CourseLecturesProvider implements QualityGeneratorProvider { Identity teacher = securityManager.loadIdentityByKey(lectureBlockInfo.getTeacherKey()); String topicKey = getTopicKey(configs); - // create data collection + // create data collection Long generatorProviderKey = CONFIG_KEY_TOPIC_COACH.equals(topicKey)? course.getKey(): teacher.getKey(); QualityDataCollection dataCollection = qualityService.createDataCollection(courseOrganisations, formEntry, generator, generatorProviderKey); // fill in data collection attributes Date dcStart = lectureBlockInfo.getLectureEndDate(); + dataCollection.setStart(dcStart); String minutesBeforeEnd = configs.getValue(CONFIG_KEY_MINUTES_BEFORE_END); minutesBeforeEnd = StringHelper.containsNonWhitespace(minutesBeforeEnd)? minutesBeforeEnd: "0"; dcStart = addMinutes(dcStart, "-" + minutesBeforeEnd); - dataCollection.setStart(dcStart); - String duration = configs.getValue(CONFIG_KEY_DURATION_DAYS); Date deadline = addDays(dcStart, duration); dataCollection.setDeadline(deadline); diff --git a/src/main/java/org/olat/modules/quality/generator/provider/courselectures/DeadlineIsInPast.java b/src/main/java/org/olat/modules/quality/generator/provider/courselectures/DeadlineIsInPast.java new file mode 100644 index 0000000000000000000000000000000000000000..97e6c9184499a16c5b8c00048d0685e3674f8ffc --- /dev/null +++ b/src/main/java/org/olat/modules/quality/generator/provider/courselectures/DeadlineIsInPast.java @@ -0,0 +1,59 @@ +/** + * <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.modules.quality.generator.provider.courselectures; + +import static org.olat.modules.quality.generator.ProviderHelper.addDays; +import static org.olat.modules.quality.generator.ProviderHelper.addMinutes; + +import java.util.Date; +import java.util.function.Predicate; + +import org.olat.core.util.StringHelper; +import org.olat.modules.quality.generator.provider.courselectures.manager.LectureBlockInfo; + +/** + * + * Initial date: 17 Aug 2020<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +public class DeadlineIsInPast implements Predicate<LectureBlockInfo> { + + private final String minutesBeforeEnd; + private final String duration; + private final Date now; + + DeadlineIsInPast(String minutesBeforeEnd, String duration) { + this.minutesBeforeEnd = minutesBeforeEnd; + this.duration = duration; + this.now = new Date(); + } + + @Override + public boolean test(LectureBlockInfo lectureBlockInfo) { + // calculate start and deadline + Date dcStart = lectureBlockInfo.getLectureEndDate(); + String realMinutesBeforeEnd = StringHelper.containsNonWhitespace(minutesBeforeEnd)? minutesBeforeEnd: "0"; + dcStart = addMinutes(dcStart, "-" + realMinutesBeforeEnd); + Date deadline = addDays(dcStart, duration); + return deadline.before(now); + } + +} diff --git a/src/main/java/org/olat/modules/quality/generator/ui/GeneratorController.java b/src/main/java/org/olat/modules/quality/generator/ui/GeneratorController.java index e5ff1659143d00cc0cb4e9f2c065f9e07290efda..fd5a32a8c4cd33ade7ac14031819f43030200c4e 100644 --- a/src/main/java/org/olat/modules/quality/generator/ui/GeneratorController.java +++ b/src/main/java/org/olat/modules/quality/generator/ui/GeneratorController.java @@ -22,6 +22,7 @@ package org.olat.modules.quality.generator.ui; import java.util.Date; import java.util.List; +import org.apache.logging.log4j.Logger; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.Component; import org.olat.core.gui.components.dropdown.Dropdown; @@ -45,6 +46,7 @@ import org.olat.core.gui.control.generic.dtabs.Activateable2; import org.olat.core.id.Organisation; import org.olat.core.id.context.ContextEntry; import org.olat.core.id.context.StateEntry; +import org.olat.core.logging.Tracing; import org.olat.modules.quality.generator.QualityGenerator; import org.olat.modules.quality.generator.QualityGeneratorService; import org.olat.modules.quality.ui.GeneratorReportAccessController; @@ -60,6 +62,8 @@ import org.springframework.beans.factory.annotation.Autowired; */ public class GeneratorController extends BasicController implements TooledController, Activateable2 { + private static final Logger log = Tracing.createLoggerFor(GeneratorController.class); + private Dropdown enableDropdown; private Link enableLink; private Link disableLink; @@ -280,6 +284,7 @@ public class GeneratorController extends BasicController implements TooledContro generator.setEnabled(true); generator.setLastRun(fromDate); generator = generatorService.updateGenerator(generator); + log.info("Generator {} enabled by {}", generator, getIdentity()); updateUI(ureq); } diff --git a/src/main/java/org/olat/modules/quality/manager/QualityReportAccessDAO.java b/src/main/java/org/olat/modules/quality/manager/QualityReportAccessDAO.java index 027528c0d1de69b6e1150567358295f115d2cf6c..0accb4db96c49b691903f4e4161f8ff702bb7c43 100644 --- a/src/main/java/org/olat/modules/quality/manager/QualityReportAccessDAO.java +++ b/src/main/java/org/olat/modules/quality/manager/QualityReportAccessDAO.java @@ -241,15 +241,15 @@ class QualityReportAccessDAO { private List<Identity> loadRecipientsOfGroupRoles(QualityReportAccess reportAccess) { QueryBuilder sb = new QueryBuilder(); sb.append("select membership.identity"); - sb.append(" from qualityreportaccess as ra"); - sb.append(" , qualitydatacollection as collection"); - sb.append(" , qualitycontext as context"); - sb.append(" , repoentrytogroup as rel"); - sb.append(" , bgroupmember as membership"); - sb.and().append("ra.dataCollection.key = context.dataCollection.key"); - sb.and().append("rel.entry.key = context.audienceRepositoryEntry.key"); - sb.and().append("rel.group.key = membership.group.key"); - sb.and().append("membership.role = ra.role"); + sb.append(" from qualitycontext as context"); + sb.append(" join context.dataCollection as collection"); + sb.append(" join qualityreportaccess as ra"); + sb.append(" on ra.dataCollection.key = context.dataCollection.key"); + sb.append(" join repoentrytogroup as rel"); + sb.append(" on rel.entry.key = context.audienceRepositoryEntry.key"); + sb.append(" join bgroupmember as membership"); + sb.append(" on membership.group.key = rel.group.key"); + sb.append(" and membership.role = ra.role"); sb.and().append("ra.key = :reportAccessKey"); List<Identity> coureseMembers = dbInstance.getCurrentEntityManager() @@ -259,15 +259,15 @@ class QualityReportAccessDAO { QueryBuilder sbEle = new QueryBuilder(); sbEle.append("select membership.identity"); - sbEle.append(" from qualityreportaccess as ra"); - sbEle.append(" , qualitydatacollection as collection"); - sbEle.append(" , qualitycontext as context"); - sbEle.append(" , curriculumelement as ele"); - sbEle.append(" , bgroupmember as membership"); - sbEle.and().append("ra.dataCollection.key = context.dataCollection.key"); - sbEle.and().append("ele.key = context.audienceCurriculumElement.key"); - sbEle.and().append("ele.group.key = membership.group.key"); - sbEle.and().append("membership.role = ra.role"); + sbEle.append(" from qualitycontext as context"); + sbEle.append(" join context.dataCollection as collection"); + sbEle.append(" join qualityreportaccess as ra"); + sbEle.append(" on ra.dataCollection.key = context.dataCollection.key"); + sbEle.append(" join curriculumelement as ele"); + sbEle.append(" on ele.key = context.audienceCurriculumElement.key"); + sbEle.append(" join bgroupmember as membership"); + sbEle.append(" on membership.group.key = ele.group.key"); + sbEle.append(" and membership.role = ra.role"); sbEle.and().append("ra.key = :reportAccessKey"); List<Identity> curriculumElementMembers = dbInstance.getCurrentEntityManager() @@ -302,8 +302,8 @@ class QualityReportAccessDAO { QueryBuilder sb = new QueryBuilder(); sb.append("select membership.identity"); sb.append(" from qualityreportaccess as ra"); - sb.append(" , bgroupmember as membership"); - sb.and().append("ra.group.key = membership.group.key"); + sb.append(" join bgroupmember as membership"); + sb.append(" on membership.group.key = ra.group.key"); sb.and().append("ra.key = :reportAccessKey"); return dbInstance.getCurrentEntityManager() diff --git a/src/main/java/org/olat/registration/PwChangeController.java b/src/main/java/org/olat/registration/PwChangeController.java index 63d1acb38bb282dcd25cfa18eef2b61d2926ae96..a924eca3676b7e3446b5d1e79450d3b9157d548b 100644 --- a/src/main/java/org/olat/registration/PwChangeController.java +++ b/src/main/java/org/olat/registration/PwChangeController.java @@ -27,6 +27,7 @@ package org.olat.registration; import java.text.DateFormat; import java.util.Date; +import java.util.List; import java.util.Locale; import org.olat.basesecurity.BaseSecurity; @@ -323,6 +324,12 @@ public class PwChangeController extends BasicController { // Try fallback with email, maybe user used his email address instead identity = userManager.findUniqueIdentityByEmail(emailOrUsername); } + if (identity == null) { + List<Identity> identities = userManager.findIdentitiesWithProperty(UserConstants.NICKNAME, emailOrUsername); + if(identities != null && identities.size() == 1) { + identity = identities.get(0); + } + } return identity; } diff --git a/src/main/java/org/olat/user/UserModule.java b/src/main/java/org/olat/user/UserModule.java index 4f2ef079f9af168dca41553325ab72d3ee20b5ef..0cb94df959f00336185f0af4e0ddf9e54eafe8cc 100644 --- a/src/main/java/org/olat/user/UserModule.java +++ b/src/main/java/org/olat/user/UserModule.java @@ -350,6 +350,10 @@ public class UserModule extends AbstractSpringModule { return pwdchangeallowed; } + public boolean isPasswordChangeWithoutAuthenticationAllowed() { + return pwdChangeWithoutAuthenticationAllowed; + } + public boolean isLogoByProfileEnabled() { return "enabled".equals(enabledLogoByProfile); } diff --git a/src/main/java/org/olat/user/restapi/UserWebService.java b/src/main/java/org/olat/user/restapi/UserWebService.java index a1b2e1905c45a1abb46cb7d18305f79017480f93..4af8f77074b57ae12eda32b2c3a73656fbc80586 100644 --- a/src/main/java/org/olat/user/restapi/UserWebService.java +++ b/src/main/java/org/olat/user/restapi/UserWebService.java @@ -338,9 +338,10 @@ public class UserWebService { User newUser = userManager.createUser(user.getFirstName(), user.getLastName(), user.getEmail()); String identityName = securityModule.isIdentityNameAutoGenerated() ? null : user.getLogin(); + String provider = StringHelper.containsNonWhitespace(user.getPassword()) ? BaseSecurityModule.getDefaultAuthProviderIdentifier() : null; Identity id = securityManager .createAndPersistIdentityAndUserWithOrganisation(identityName, user.getLogin(), user.getExternalId(), newUser, - BaseSecurityModule.getDefaultAuthProviderIdentifier(), user.getLogin(), user.getPassword(), null); + provider, user.getLogin(), user.getPassword(), null); post(newUser, user, getLocale(request)); userManager.updateUser(newUser); return Response.ok(get(id)).build(); diff --git a/src/test/java/org/olat/modules/quality/generator/provider/courselectures/CourseLecturesProviderTest.java b/src/test/java/org/olat/modules/quality/generator/provider/courselectures/CourseLecturesProviderTest.java index 02fc936475c2613f54160c8fff458a9d9c124d40..31a5ce76984b16cb1d143a11f2753bcaf37c8259 100644 --- a/src/test/java/org/olat/modules/quality/generator/provider/courselectures/CourseLecturesProviderTest.java +++ b/src/test/java/org/olat/modules/quality/generator/provider/courselectures/CourseLecturesProviderTest.java @@ -25,7 +25,6 @@ import static org.olat.test.JunitTestHelper.random; import java.util.Collection; import java.util.Collections; import java.util.Date; -import java.util.GregorianCalendar; import java.util.List; import org.assertj.core.api.SoftAssertions; @@ -84,9 +83,9 @@ public class CourseLecturesProviderTest extends OlatTestCase { @Test public void shouldCopyOrganisationsOfCourseToDataCollection() { - Date startDate = new GregorianCalendar(2010, 6, 3).getTime(); - Date startEnd = new GregorianCalendar(2010, 6, 4).getTime(); - RepositoryEntry courseEntry = createCourseWithThreeLectures(startDate, startEnd); + Date startDate = DateUtils.addDays(new Date(), -2); + Date startEnd = DateUtils.addDays(new Date(), -1); + RepositoryEntry courseEntry = createCourseWithLecture(startDate, startEnd); Organisation defaultOrganisation = organisationService.getDefaultOrganisation(); repositoryService.removeOrganisation(courseEntry, defaultOrganisation); Organisation courseOrganisation1 = createOrganisation(defaultOrganisation); @@ -98,10 +97,10 @@ public class CourseLecturesProviderTest extends OlatTestCase { QualityGenerator generator = createGeneratorInDefaultOrganisation(); String durationDays = "10"; - QualityGeneratorConfigs configs = createAfterSecondLectureConfigs(generator, durationDays, element); + QualityGeneratorConfigs configs = createConfigs(generator, durationDays, element); - Date lastRun = new GregorianCalendar(2010, 6, 1).getTime(); - Date now = new GregorianCalendar(2010, 6, 13).getTime(); + Date lastRun = DateUtils.addDays(new Date(), -2); + Date now = new Date(); List<QualityDataCollection> generated = sut.generate(generator, configs, lastRun, now); dbInstance.commitAndCloseSession(); @@ -113,18 +112,61 @@ public class CourseLecturesProviderTest extends OlatTestCase { .doesNotContain(defaultOrganisation); } + @Test + public void shouldCreateDataCollectionIfDeadlineIsInFuture() { + Date startDate = DateUtils.addDays(new Date(), -2); + Date startEnd = DateUtils.addDays(new Date(), -1); + RepositoryEntry courseEntry = createCourseWithLecture(startDate, startEnd); + CurriculumElement element = createCurriculumElement(); + curriculumService.addRepositoryEntry(element, courseEntry, false); + + QualityGenerator generator = createGeneratorInDefaultOrganisation(); + String durationDays = "10"; + QualityGeneratorConfigs configs = createConfigs(generator, durationDays, element); + + Date lastRun = DateUtils.addDays(new Date(), -2); + Date now = new Date(); + + List<QualityDataCollection> generated = sut.generate(generator, configs, lastRun, now); + dbInstance.commitAndCloseSession(); + + assertThat(generated).hasSize(1); + } + + @Test + public void shouldNotCreateDataCollectionIfDeadlineIsInPast() { + Date startDate = DateUtils.addDays(new Date(), -12); + Date startEnd = DateUtils.addDays(new Date(), -11); + RepositoryEntry courseEntry = createCourseWithLecture(startDate, startEnd); + CurriculumElement element = createCurriculumElement(); + curriculumService.addRepositoryEntry(element, courseEntry, false); + + QualityGenerator generator = createGeneratorInDefaultOrganisation(); + String durationDays = "10"; + QualityGeneratorConfigs configs = createConfigs(generator, durationDays, element); + + Date lastRun = DateUtils.addDays(new Date(), -20); + Date now = new Date(); + + List<QualityDataCollection> generated = sut.generate(generator, configs, lastRun, now); + dbInstance.commitAndCloseSession(); + + assertThat(generated).isEmpty(); + + } + @Test public void shouldGenerateWithAnnouncementForwards() { Date now = new Date(); Date startDate = DateUtils.addDays(now, 3); Date startEnd = DateUtils.addDays(now, 4); - RepositoryEntry courseEntry = createCourseWithThreeLectures(startDate, startEnd); + RepositoryEntry courseEntry = createCourseWithLecture(startDate, startEnd); CurriculumElement element = createCurriculumElement(); curriculumService.addRepositoryEntry(element, courseEntry, false); QualityGenerator generator = createGeneratorInDefaultOrganisation(); String durationDays = "10"; - QualityGeneratorConfigs configs = createAfterSecondLectureConfigs(generator, durationDays, element); + QualityGeneratorConfigs configs = createConfigs(generator, durationDays, element); configs.setValue(CourseLecturesProvider.CONFIG_KEY_ANNOUNCEMENT_COACH_DAYS, "5"); Date lastRun = DateUtils.addDays(now, -9); @@ -149,13 +191,13 @@ public class CourseLecturesProviderTest extends OlatTestCase { Date now = new Date(); Date startDate = DateUtils.addDays(now,-2); Date startEnd = DateUtils.addDays(now, -1); - RepositoryEntry courseEntry = createCourseWithThreeLectures(startDate, startEnd); + RepositoryEntry courseEntry = createCourseWithLecture(startDate, startEnd); CurriculumElement element = createCurriculumElement(); curriculumService.addRepositoryEntry(element, courseEntry, false); QualityGenerator generator = createGeneratorInDefaultOrganisation(); String durationDays = "10"; - QualityGeneratorConfigs configs = createAfterSecondLectureConfigs(generator, durationDays, element); + QualityGeneratorConfigs configs = createConfigs(generator, durationDays, element); configs.setValue(CourseLecturesProvider.CONFIG_KEY_ANNOUNCEMENT_COACH_DAYS, "2"); Date lastRun = DateUtils.addDays(now, -9); @@ -169,13 +211,13 @@ public class CourseLecturesProviderTest extends OlatTestCase { assertThat(reminder).isNull(); } - private RepositoryEntry createCourseWithThreeLectures(Date startDate, Date endDate) { + private RepositoryEntry createCourseWithLecture(Date lectureStartDate, Date lectureEndDate) { Identity initialAuthor = JunitTestHelper.createAndPersistIdentityAsAuthor(JunitTestHelper.random()); RepositoryEntry courseEntry = JunitTestHelper.deployBasicCourse(initialAuthor); LectureBlock lectureBlock = lectureService.createLectureBlock(courseEntry); lectureBlock.setPlannedLecturesNumber(3); - lectureBlock.setStartDate(startDate); - lectureBlock.setEndDate(endDate); + lectureBlock.setStartDate(lectureStartDate); + lectureBlock.setEndDate(lectureEndDate); lectureService.save(lectureBlock, null); lectureService.addTeacher(lectureBlock, initialAuthor); @@ -183,7 +225,7 @@ public class CourseLecturesProviderTest extends OlatTestCase { return courseEntry; } - private QualityGeneratorConfigs createAfterSecondLectureConfigs(QualityGenerator generator, String durationDays, + private QualityGeneratorConfigs createConfigs(QualityGenerator generator, String durationDays, CurriculumElementRef curriculumElementRef) { QualityGeneratorConfigs configs = new QualityGeneratorConfigsImpl(generator); configs.setValue(CourseLecturesProvider.CONFIG_KEY_TITLE, "DATA_COLLECTION_TITLE"); diff --git a/src/test/java/org/olat/modules/quality/generator/provider/courselectures/manager/CourseLecturesProviderDAOTest.java b/src/test/java/org/olat/modules/quality/generator/provider/courselectures/manager/CourseLecturesProviderDAOTest.java index aa30cacb39cb3692743409dfedd6dda36254b6c2..a91902ca1c5d111e07d789835cf8553248041077 100644 --- a/src/test/java/org/olat/modules/quality/generator/provider/courselectures/manager/CourseLecturesProviderDAOTest.java +++ b/src/test/java/org/olat/modules/quality/generator/provider/courselectures/manager/CourseLecturesProviderDAOTest.java @@ -597,21 +597,6 @@ public class CourseLecturesProviderDAOTest extends OlatTestCase { .doesNotContain(deleted.getKey(), trashed.getKey()); } - @Test - public void shouldLoadLectureBlockCount() { - RepositoryEntry course = JunitTestHelper.createAndPersistRepositoryEntry(); - Identity teacher = JunitTestHelper.createAndPersistIdentityAsRndUser(""); - createLectureBlock(course, teacher, 1); - createLectureBlock(course, teacher, 1); - dbInstance.commitAndCloseSession(); - - SearchParameters searchParams = new SearchParameters(); - searchParams.setTeacherRef(teacher); - Long count = sut.loadLectureBlockCount(searchParams); - - assertThat(count).isEqualTo(2); - } - private LectureBlock createLectureBlock(RepositoryEntry course, Identity teacher, int numLectures) { return createLectureBlock(course, teacher, numLectures, nextHour(), nextHour()); }