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 index 9f1fa38e6f35529364f493eb1f6e498b333f141e..315156cacbaca6407aadc8fd27f1eb3c7e2c0652 100644 --- a/src/main/java/org/olat/admin/security/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/admin/security/_i18n/LocalStrings_en.properties @@ -1,4 +1,4 @@ -#Mon Mar 12 18:22:03 CET 2018 +#Fri Sep 04 07:37:15 CEST 2020 admin.menu.title=Security admin.menu.title.alt=Change security settings sec.content.security.policy=Content Security Policy (CSP) @@ -15,8 +15,9 @@ sec.csp.object.src=object-src sec.csp.plugin.type=plugin-type sec.csp.script.src=script-src sec.csp.style.src=style-src +sec.csrf=Cross-Site Request Forgery (CSRF) protectection sec.description=Choose the security level depending on the requirements of your institution. To achieve the highest security level, all of the security features listed below have to be activated. -sec.description.csp=Warning! This configuration can block or break content like LTI course elements, external pages and HTML pages. The following course elements are currently not supported: card2brain, edubase, edubook, GoToTraining, openmeeting, vitero and Paypal. You will find more informations about content security policy under <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy" target="_blank">Content-Security-Policy</a>. +sec.description.csp=Warning\! This configuration can block or break content like LTI course elements, external pages and HTML pages. The following course elements are currently not supported\: card2brain, edubase, edubook, GoToTraining, openmeeting, vitero and Paypal. You will find more informations about content security policy under <a href\="https\://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy" target\="_blank">Content-Security-Policy</a>. sec.description.csrf=This option add protection against forged requests. sec.description.headers=These headers prevents insecure behavior. sec.force.download=Force file download in folders diff --git a/src/main/java/org/olat/admin/user/UserSearchController.java b/src/main/java/org/olat/admin/user/UserSearchController.java index 2836932a88c805124ecda3a961bfb3087f019c34..32ba1630ae28f5d2bc1bb7bb459604ca81c7c630 100644 --- a/src/main/java/org/olat/admin/user/UserSearchController.java +++ b/src/main/java/org/olat/admin/user/UserSearchController.java @@ -295,13 +295,15 @@ public class UserSearchController extends BasicController { for (UserPropertyHandler userPropertyHandler : searchform.userPropertyHandlers) { if (userPropertyHandler == null) continue; FormItem ui = searchform.propFormItems.get(userPropertyHandler.getName()); - String uiValue = userPropertyHandler.getStringValue(ui); - if(userPropertyHandler.getName().startsWith("genericCheckboxProperty")) { - if(!"false".equals(uiValue)) { + if(ui != null) { + String uiValue = userPropertyHandler.getStringValue(ui); + if(userPropertyHandler.getName().startsWith("genericCheckboxProperty")) { + if(!"false".equals(uiValue)) { + userPropertiesSearch.put(userPropertyHandler.getName(), uiValue); + } + } else if (StringHelper.containsNonWhitespace(uiValue)) { userPropertiesSearch.put(userPropertyHandler.getName(), uiValue); } - } else if (StringHelper.containsNonWhitespace(uiValue)) { - userPropertiesSearch.put(userPropertyHandler.getName(), uiValue); } } if (userPropertiesSearch.isEmpty()) { diff --git a/src/main/java/org/olat/admin/user/UserSearchForm.java b/src/main/java/org/olat/admin/user/UserSearchForm.java index eaac2c44869fb5f7842164923b01d9b4fecfe199..09fc1f82a64117e1d79a66d65602b911b13de100 100644 --- a/src/main/java/org/olat/admin/user/UserSearchForm.java +++ b/src/main/java/org/olat/admin/user/UserSearchForm.java @@ -36,6 +36,7 @@ import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.Event; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.translator.Translator; +import org.olat.core.id.UserConstants; import org.olat.core.util.StringHelper; import org.olat.core.util.UserSession; import org.olat.core.util.Util; @@ -156,17 +157,20 @@ public class UserSearchForm extends FormBasicController { Translator tr = Util.createPackageTranslator(UserPropertyHandler.class, getLocale(), getTranslator()); for (UserPropertyHandler userPropertyHandler : userPropertyHandlers) { - if (userPropertyHandler == null) continue; + if (userPropertyHandler == null || (userPropertyHandler.getName().equals(UserConstants.NICKNAME) && isAdminProps)) { + continue; + } FormItem fi = userPropertyHandler.addFormItem(getLocale(), null, getClass().getCanonicalName(), false, formLayout); fi.setTranslator(tr); // DO NOT validate email field => see OLAT-3324, OO-155, OO-222 - if (userPropertyHandler instanceof EmailProperty && fi instanceof TextElement) { + if ((userPropertyHandler instanceof EmailProperty || userPropertyHandler.getName().equals(UserConstants.NICKNAME)) + && fi instanceof TextElement) { TextElement textElement = (TextElement)fi; textElement.setItemValidatorProvider(null); } - + fi.setElementCssClass("o_sel_user_search_".concat(userPropertyHandler.getName().toLowerCase())); propFormItems.put(userPropertyHandler.getName(), fi); } diff --git a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_en.properties index a95cf05b5cc03f1eada7030c622337db5d89e98b..0abd707398232444f1b9f1dae2f7afef70daa71e 100644 --- a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_en.properties @@ -1,4 +1,4 @@ -#Fri Jun 05 14:09:50 CEST 2020 +#Fri Sep 04 07:37:30 CEST 2020 action.bulkedit=Edit these users' attributes action.choose=Choose action.choose.finish=Choose and finish @@ -25,6 +25,7 @@ content.usermgmt.title=User management content.usermgmt.userfound=Manage user settings delete.pending.registration.confirmation=There is a pending self-registration for the email address "{0}". Do you want to delete this self-registration? delete.pending.registration.confirmation.title=Delete self registration +delete.user.data.title=Delete user "{0}" deleted.user.list=List of deleted users deselectall=$org.olat.core.gui.components.table\:uncheckall edit.uauth=Authentications diff --git a/src/main/java/org/olat/basesecurity/manager/AuthenticationDAO.java b/src/main/java/org/olat/basesecurity/manager/AuthenticationDAO.java index 1520bb42dd69ef67c40860a00c8c40de32c3e4dc..2e3e22199cd733a0d3dbcb7e6a0c38094b9188a1 100644 --- a/src/main/java/org/olat/basesecurity/manager/AuthenticationDAO.java +++ b/src/main/java/org/olat/basesecurity/manager/AuthenticationDAO.java @@ -53,12 +53,12 @@ public class AuthenticationDAO { sb.append("select auth from ").append(AuthenticationImpl.class.getName()).append(" as auth") .append(" inner join fetch auth.identity ident") .append(" inner join fetch ident.user identUser") - .append(" where auth.provider=:provider and auth.authusername=:authusername"); + .append(" where auth.provider=:provider and lower(auth.authusername)=:authusername"); List<Authentication> results = dbInstance.getCurrentEntityManager() .createQuery(sb.toString(), Authentication.class) .setParameter("provider", provider) - .setParameter("authusername", authusername) + .setParameter("authusername", authusername.toLowerCase()) .getResultList(); if (results.isEmpty()) return null; if (results.size() != 1) { @@ -72,11 +72,11 @@ public class AuthenticationDAO { sb.append("select auth from ").append(AuthenticationImpl.class.getName()).append(" as auth") .append(" inner join fetch auth.identity ident") .append(" inner join fetch ident.user identUser") - .append(" where auth.authusername=:authusername"); + .append(" where lower(auth.authusername)=:authusername"); return dbInstance.getCurrentEntityManager() .createQuery(sb.toString(), Authentication.class) - .setParameter("authusername", authusername) + .setParameter("authusername", authusername.toLowerCase()) .getResultList(); } @@ -85,11 +85,11 @@ public class AuthenticationDAO { sb.append("select auth from ").append(AuthenticationImpl.class.getName()).append(" as auth") .append(" inner join fetch auth.identity ident") .append(" inner join fetch ident.user identUser") - .append(" where auth.authusername=:authusername and auth.provider in (:providers)"); + .append(" where lower(auth.authusername)=:authusername and auth.provider in (:providers)"); return dbInstance.getCurrentEntityManager() .createQuery(sb.toString(), Authentication.class) - .setParameter("authusername", authusername) + .setParameter("authusername", authusername.toLowerCase()) .setParameter("providers", providers) .getResultList(); } @@ -104,10 +104,10 @@ public class AuthenticationDAO { sb.append("select ident from ").append(AuthenticationImpl.class.getName()).append(" as auth") .append(" inner join auth.identity as ident") .append(" inner join ident.user as user") - .append(" where auth.authusername=:login"); + .append(" where lower(auth.authusername)=:login"); return dbInstance.getCurrentEntityManager() .createQuery(sb.toString(), Identity.class) - .setParameter("login", login) + .setParameter("login", login.toLowerCase()) .getResultList(); } @@ -185,10 +185,10 @@ public class AuthenticationDAO { sb.append("select auth from ").append(AuthenticationImpl.class.getName()).append(" as auth") .append(" inner join auth.identity as ident") .append(" inner join ident.user as user") - .append(" where auth.authusername=:authUsername and auth.provider=:provider"); + .append(" where lower(auth.authusername)=:authUsername and auth.provider=:provider"); List<Authentication> authentications = dbInstance.getCurrentEntityManager() .createQuery(sb.toString(), Authentication.class) - .setParameter("authUsername", authUsername) + .setParameter("authUsername", authUsername.toLowerCase()) .setParameter("provider", provider) .setFirstResult(0) .setMaxResults(1) diff --git a/src/main/java/org/olat/basesecurity/model/IdentityLastLoginImpl.java b/src/main/java/org/olat/basesecurity/model/IdentityLastLoginImpl.java index 2e5ca8515161cc02361ce78321dc9679a2e4cebc..f623e8279b5c99602fe3ac5bd2a003e8927e1e3d 100644 --- a/src/main/java/org/olat/basesecurity/model/IdentityLastLoginImpl.java +++ b/src/main/java/org/olat/basesecurity/model/IdentityLastLoginImpl.java @@ -42,7 +42,7 @@ import org.olat.core.id.Persistable; */ @Entity(name="bidentitylastlogin") @Table(name="o_bs_identity") -@NamedQuery(name="updateIdentityLastLogin", query="update bidentitylastlogin set lastLogin=:now where key=:identityKey") +@NamedQuery(name="updateIdentityLastLogin", query="update bidentitylastlogin set lastLogin=:now, inactivationEmailDate=null where key=:identityKey") public class IdentityLastLoginImpl implements Persistable, IdentityRef { private static final long serialVersionUID = 2090002193918262648L; @@ -56,6 +56,10 @@ public class IdentityLastLoginImpl implements Persistable, IdentityRef { @Column(name="lastlogin", nullable=false, insertable=true, updatable=true) private Date lastLogin; + @Temporal(TemporalType.TIMESTAMP) + @Column(name="inactivationemaildate", nullable=false, insertable=true, updatable=true) + private Date inactivationEmailDate; + public IdentityLastLoginImpl() { // } diff --git a/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_en.properties index ed7e71677443494cbf686da132d69fd67b769faa..a84de166afa17f71045abbdb7c2fab32ee3b0974 100644 --- a/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_en.properties @@ -1,38 +1,39 @@ -#Fri Jan 21 11:22:00 CET 2011 +#Fri Sep 04 07:32:27 CEST 2020 assessment.reset.desc=Do you want to recalculate the calculated assessments? This can take a while. assessment.reset.discard=Discard changes -assessment.reset.recalculate.all=recalculate -assessment.reset.recalculate.all.label=Course assessment and efficiency statements assessment.reset.overriden=reset assessment.reset.overriden.label=Manually set "passed" assessment.reset.passed=reset assessment.reset.passed.label=Calculated "passed" +assessment.reset.recalculate.all=recalculate +assessment.reset.recalculate.all.label=Course assessment and efficiency statements assessment.reset.title=Save settings blog.not.selected=No blog selected blog.open={0} blog.replace=Replace blog.select=Select -blog.select.button={0} blog.select.blog=Select blog +blog.select.button={0} +blog.select.title=Select blog chkbx.blog.onoff=Blog +chkbx.breadcrumb.onoff=Bread-crumb navigation chkbx.calendar.onoff=Course calendar chkbx.chat.onoff=Course chat -chkbx.search.onoff=Course search chkbx.documents.onoff=Documents +chkbx.efficency.onoff=Use evidence of achievement chkbx.email.onoff=E-mail chkbx.forum.onoff=Forum -chkbx.efficency.onoff=Use evidence of achievement chkbx.glossary.explain=The glossary need to be configured under "Options". chkbx.glossary.inverse.explain=Glossary menu in toolbar is configured under "Toolbar". chkbx.glossary.onoff=Glossary chkbx.menu.onoff=Menu visible for participants and coaches chkbx.participantinfo.onoff=Participant infos chkbx.participantlist.onoff=Participant list -chkbx.toolbar.explain=Activate tools in toolbar: -chkbx.toolbar.onoff=Toolbar visible for participants +chkbx.search.onoff=Course search +chkbx.toolbar.explain=Activate tools in toolbar\: chkbx.toolbar.off.warning=If you disable the toolbar, the individual tools are also no longer available. +chkbx.toolbar.onoff=Toolbar visible for participants chkbx.wiki.onoff=Wiki -chkbx.breadcrumb.onoff=Bread-crumb navigation command.choose=Choose command.glossary.add=Select glossary command.glossary.remove=Delete selection @@ -72,9 +73,9 @@ options.score.title=Assessment settings selectfile=Choose file sf.changesfresource=Replace sf.notconfigured=<i>No resource folder selected</i> +sf.resource.readonly=Read only sf.resourcetitle=Selected resource folder sf.resourcetitle.helptext=The files stored there can be found in the storage folder of your course when selecting the sub-folder "_sharedfolder". -sf.resource.readonly=Read only sf.selectsfresource=Select sf.unselectsfresource=Deselect tab.calendar.title=Settings @@ -85,12 +86,13 @@ tab.layout.title=Layout tab.sharedfolder.title=Settings warning.change.todisabled=All evidences of achievement already existing will no longer be available for course participants. Do you want to proceed? warning.change.toenable=By selecting this option evidences of achievement will be created for the entire course. This will take a while. Do you want to proceed? -warning.folderRef.title=Attention! warning.folderRef=This resource folder is referenced by at least one folder course node. Removing this resource folder will lead to an inconsistent folder configuration. Do you wish to proceed nevertheless? +warning.folderRef.title=Attention\! warning.folderRefAdd=This resource folder is referenced by at least one folder course node. Changing this resource folder will lead to an inconsistent folder configuration. Do you wish to proceed nevertheless? wiki.not.selected=No wiki selected wiki.open={0} wiki.replace=Replace wiki.select=Select wiki.select.button={0} -wiki.select.wiki=Select wiki \ No newline at end of file +wiki.select.title=Select wiki +wiki.select.wiki=Select wiki diff --git a/src/main/java/org/olat/course/editor/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/editor/_i18n/LocalStrings_en.properties index dd5589280c893787687933068e635523d2c9429c..e800a35d55efb5d3aa5ac48d452d5ec40321b71f 100644 --- a/src/main/java/org/olat/course/editor/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/course/editor/_i18n/LocalStrings_en.properties @@ -1,4 +1,4 @@ -#Wed Dec 17 17:29:34 CET 2014 +#Fri Sep 04 07:32:32 CEST 2020 access.form.label=Access to entire course have access.legend=Modify access to entire course alternative=Search for an alternative course element @@ -12,327 +12,6 @@ bulk.general=$\:pane.tab.general bulk.learning.path=$org.olat.course.learningpath.ui\:pane.tab.learning.path checkall=Select all checklist.wizard=Checklist set - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - cif.access=$org.olat.repository\:cif.access cif.access.membersonly=$org.olat.repository\:cif.access.membersonly cif.access.owners=$org.olat.repository\:cif.access.owners\t\t\t @@ -353,6 +32,7 @@ command.multi.checklist=Multiple checklists command.multi.sps=Multiple single pages command.overview=Configuration overview command.publish=Publish +condition.accessibility.title=Access condition.noAccessExplanation.title=Information if visible and no access condition.visibility.title=Visibility content=Knowledge transfer @@ -381,11 +61,6 @@ form.noAccessExplanation.default=This course element is not accessible. header.insertnodes=Insert course elements header.insertnodes.desc=Select a course element from the following list to add it to your course, based on your didactical concept. The course elements are ordered into functional groups to facilitate selection. header.tools=Editor tools - - - - - ignore=ignore ignore.in.course.assessment=$org.olat.course.nodes.ms\:ignore.in.course.assessment insert.course.element.title=Insert course element @@ -489,11 +164,11 @@ table.header.learning.objectives=$\:nodeConfigForm.learningobjectives table.header.long.title=$\:nodeConfigForm.displaytitle table.header.new=New table.header.node=Course element -table.header.passed.cut=$org.olat.course.nodes.ms\:form.cut table.header.passed=$org.olat.course.nodes.ms\:form.passed +table.header.passed.cut=$org.olat.course.nodes.ms\:form.cut +table.header.score=$org.olat.course.nodes.ms\:form.score table.header.score.max=$org.olat.course.nodes.ms\:form.max table.header.score.min=$org.olat.course.nodes.ms\:form.min -table.header.score=$org.olat.course.nodes.ms\:form.score table.header.short.title=$\:nodeConfigForm.menutitle target.node.child=Subordinate target.node.first.node=Beginning diff --git a/src/main/java/org/olat/course/nodes/en/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/nodes/en/_i18n/LocalStrings_en.properties index 34e18941046d3166a592783ff3f0614f760d8756..499731a14d47df21c49b9b5a321786cdd6d8850a 100644 --- a/src/main/java/org/olat/course/nodes/en/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/course/nodes/en/_i18n/LocalStrings_en.properties @@ -1,32 +1,18 @@ -#Fri Jan 21 14:14:02 CET 2011 - - - - - - - - - - - - - - - +#Fri Sep 04 07:32:37 CEST 2020 cmd.enroll.in.group=Enrol cmd.enrolled.cancel=Cancel config.header1=Enrolment in learning groups and learning areas -engroupedit.table.up=Up engroupedit.table.description=Description engroupedit.table.down=Down +engroupedit.table.enrolled=Enrolled engroupedit.table.groupName=Groupname +engroupedit.table.key=ID engroupedit.table.maxPart=Max. participants engroupedit.table.minPart=Min. participants -engroupedit.table.enrolled=Enrolled +engroupedit.table.remove=Remove +engroupedit.table.up=Up engroupedit.table.waitinglist=Waitinglist engroupedit.table.waitinglistParticipants=Participants on waitinglist -engroupedit.table.remove=Remove enroll.explain=Choose one of the learning groups below to enrol. enrolled.explain=You have already enroled for the learning groups mentioned below. To cancel your enrolment please click on the button below (if available). <b>Attention\:</b> Your enrolment concerns only the groups selected in the corresponding OpenOlat course. enrolled.group.desc=Description @@ -34,19 +20,19 @@ enrolled.group.name=Names of learning groups enrolled.waitinglist.name=Names of waiting lists error.group.already.enrolled=You are already a registered member of this group. error.group.full=In the meantime this group is complete. Please select another one. +error.multipleEnroll=The Value must be 1 or higher error.nogroupdefined.long=There must be at least one learning group or one learning area selected for "{0}" from the section group management. error.nogroupdefined.short=Learning group or learning area missing for "{0}". -error.multipleEnroll=The Value must be 1 or higher form.allowGroupSort=Allow custom order +form.allowMultiEnroll=Allow multiple enrolments form.areanames=Learning areas form.areanames.example=(Example\: Study trips) form.areanames.wrong=Enter names of learning areas separated by commas or leave this field empty. form.enableCancelEnroll=Delisting permitted -form.allowMultiEnroll=Allow multiple enrolments -form.multipleEnrollCount=Number of groups form.groupnames=Learning groups form.groupnames.example=(Example\: Green,Red,Blue) form.groupnames.wrong=Enter names of learning groups separated by commas or leave this field empty. +form.multipleEnrollCount=Number of groups form.noGroupsOrAreas=There must be at least one learning group or one learning area defined fully.assessed.trigger.status.done=Enrollment done grouplist.no.groups=There are no learning groups you can enrol for. @@ -67,7 +53,8 @@ grouplist.table.state.notEnrolled=Not enroled grouplist.table.state.onPartipiciantList=<b>enroled</b> grouplist.table.state.onWaitingList=<b>On waiting list ({0})</b> grouplist.table.waitingList=Taken on<br />waiting list - +multiple.select.hint=Choose from the learning groups below to enrol. You are allowed to enrol to a total of <b>{0}</b> groups. +multiple.select.hint.outstanding=You have enroled to <b>{0}</b> Group. You can enrol to <b>{1}</b> more groups. notification.mail.added.self.body=*** This is an automated message, please do not reply *** \r\n\r\nYou have enroled for an OpenOlat learning group\: \r\n\r\nGroup name\: {0}\r\nDescription\: {1} notification.mail.added.self.subject=OpenOlat learning group {0} notification.mail.error=This e-mail could not be sent. @@ -85,5 +72,3 @@ popupchooseareas=Select learning areas from group management popupchoosegroups=Select groups from group management title_en=Enrolment waitinglist.explain=You are on the waiting list of the learning group mentioned below. Click 'Cancel enrolment' in order to delist. -multiple.select.hint=Choose from the learning groups below to enrol. You are allowed to enrol to a total of <b>{0}</b> groups. -multiple.select.hint.outstanding=You have enroled to <b>{0}</b> Group. You can enrol to <b>{1}</b> more groups. diff --git a/src/main/java/org/olat/course/nodes/fo/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/nodes/fo/_i18n/LocalStrings_en.properties index a6341deb19824d7a0d4636e481dfa8a57bfaea49..24f391754fe97fc91c8b815274aa4dd323d5dd06 100644 --- a/src/main/java/org/olat/course/nodes/fo/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/course/nodes/fo/_i18n/LocalStrings_en.properties @@ -1,6 +1,7 @@ -#Wed Jan 26 19:01:16 CET 2011 +#Fri Sep 04 07:33:23 CEST 2020 allow.guest.post=Allow guests to post allow.pseudonym.post=Allow posts using an alias +anonymous.title=Alias anymous.title=Aliases command.closefo=Close view command.show=Display forum diff --git a/src/main/java/org/olat/course/nodes/ms/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/nodes/ms/_i18n/LocalStrings_en.properties index 8bce2a1543a40146f2f58461f3df6eeb413666b3..ac22b4d767645666498c82f85d308fe8f7a84cda 100644 --- a/src/main/java/org/olat/course/nodes/ms/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/course/nodes/ms/_i18n/LocalStrings_en.properties @@ -1,14 +1,15 @@ -#Sun Jan 23 12:26:04 CET 2011 +#Fri Sep 04 07:34:05 CEST 2020 assessment.documents.title=Assessment documents breadcrumb.users=Users comment.nocomment=No comments available comment.title=Comments -error.fully.assessed.passed=$org.olat.course.learningpath.ui:\error.fully.assessed.passed -error.fully.assessed.score=$org.olat.course.learningpath.ui:\error.fully.assessed.score +condition.accessibility.title=Access +error.fully.assessed.passed=$org.olat.course.learningpath.ui\:error.fully.assessed.passed +error.fully.assessed.score=$org.olat.course.learningpath.ui\:error.fully.assessed.score error.missingconfig.long=Please open the tab "Assessment" in order to complete the configuration of "{0}". error.missingconfig.short=The assessment for "{0}" is not correctly configured. -error.no.role.title=No access error.no.role.message=You do not have access to this course element. +error.no.role.title=No access error.repo.entry.missing=This survey was deleted in the meantime.. error.repo.entry.not.replaceable=The questionnaire can not be replaced anymore. evaluation.execution.reopen=Reopen @@ -21,12 +22,11 @@ form.error.cutOutOfRange=Cut value not between minimum and maximum score form.error.minGreaterThanMax=Minumum score greater than maximum score form.error.wrongFloat=Wrong numerical format. Examples\: 15.0, 5.5, 10 form.evaluation=Rubric questionnaire -form.evaluation.choose=Choose, create or import +form.evaluation.choose=Choose questionnaire form.evaluation.edit=Edit form.evaluation.enabled=Rubric assessment form.evaluation.not.choosen=No rubric questionnaire chosen form.evaluation.replace=Replace -form.evaluation.choose=Choose questionnaire form.individual.assessment.docs=Individual assessment documents form.infotext.coach=Notice for coaches form.infotext.user=Notice for all users @@ -66,8 +66,8 @@ score.noscore=Information not available score.title=Summary of score score.yourscore=Your score scoring.config.enable.button=Modify -scoring.overwriting=There are already some assessments existing. Do you really want to modify your assessment configuration? All (even completed) calculated assessments are done again! -scoring.overwriting.note=Please note\: you are modifying the assessment configuration although there are already some assessments existing. All (even completed) calculated assessments are done again! +scoring.overwriting=There are already some assessments existing. Do you really want to modify your assessment configuration? All (even completed) calculated assessments are done again\! +scoring.overwriting.note=Please note\: you are modifying the assessment configuration although there are already some assessments existing. All (even completed) calculated assessments are done again\! table.header.details.ms=Rubric tool.reset.data=Reset all data tool.reset.data.confirm.button=Reset data diff --git a/src/main/java/org/olat/home/UserSearchAndInfoController.java b/src/main/java/org/olat/home/UserSearchAndInfoController.java index b448d3de46550e04a997bcb3e5ecab934e706e99..9a0191c1520cb4262d4178317161fa23172e0502 100644 --- a/src/main/java/org/olat/home/UserSearchAndInfoController.java +++ b/src/main/java/org/olat/home/UserSearchAndInfoController.java @@ -72,17 +72,11 @@ public class UserSearchAndInfoController extends BasicController { } } - /** - * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest, org.olat.core.gui.components.Component, org.olat.core.gui.control.Event) - */ @Override protected void event(UserRequest ureq, Component source, Event event) { // } - /** - * @see org.olat.core.gui.control.DefaultController#doDispose() - */ @Override protected void doDispose() { // diff --git a/src/main/java/org/olat/ims/qti/editor/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/ims/qti/editor/_i18n/LocalStrings_en.properties index d4a7af1a8a9b385dd5b021904f348a2cd6d1d508..7fdffa2e277aa915c2311d161a728a59dea6b2bd 100644 --- a/src/main/java/org/olat/ims/qti/editor/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/ims/qti/editor/_i18n/LocalStrings_en.properties @@ -1,4 +1,4 @@ -#Sat Jan 22 17:01:28 CET 2011 +#Fri Sep 04 07:37:05 CEST 2020 add_answer=Add new answer add_blank=Add new blank add_text=Add new text fragment @@ -26,6 +26,7 @@ error.lock=This test/questionnaire is being edited by user {0} at the moment and error.move.atleastoneitem=Question cannot be moved. A section must contain at least one question. error.preview=An error has occurred while creating the preview. error.qti.deprecated=This version of QTI is deprecated. Please consider to convert your test to QTI 2.1. +error.qti.deprecated.no.conversion=This version of QTI will not be supported. error.rows=Height format invalid. error.save=This document could not be saved. error.title.empty=The question's title is mandatory. @@ -42,6 +43,7 @@ exit.header=Close/save editor exit.message=Please press "Save" to save your modifications. They will not be saved if you click "Discard". If you would like to end this process and return to the editor, press "Cancel". exit.save=Save exit.save.tooltip=Save modifications and close editor +export.qpool.successful={0} questions have been exported successfully feedback_submit=Save changes feedbackswitch=Show feedback fieldset.legend.answers=Answers @@ -53,6 +55,10 @@ fieldset.legend.metadata=Meta data fieldset.legend.preview=Preview fieldset.legend.question=Question fieldset.legend.sectionsettings=Settings +form.assessment.order_type=Order of sections +form.assessment.order_type.hover=Determine the order in which the selected sections should be displayed for the user. +form.assessment.selection_pre=Number of sections in this assessment +form.assessment.selection_pre.hover=Select whether all or just a random selection of the sections should be displayed for the user form.chngmsg.info=You have modified a resource referenced by other authors. Please enter a message to be sent along with the automatically generated change log. You have to send this message; otherwise, your modifications will not come into effect. form.chngmsg.infolabel=Information form.chngmsg.informlearners=Learners should see change log as well @@ -90,43 +96,13 @@ form.metadata.timerestriction=Time limit for entire test form.metadata.title=Title form.metadata.type=Type form.section.durationswitch=Time limit for entire section -form.assessment.order_type=Order of sections -form.assessment.order_type.hover=Determine the order in which the selected sections should be displayed for the user. -form.assessment.selection_pre=Number of sections in this assessment -form.assessment.selection_pre.hover=Select whether all or just a random selection of the sections should be displayed for the user form.section.order_type=Order of questions form.section.order_type.random=Random order form.section.order_type.sequential=Fixed order -form.section.shuffle=Random order of questions? form.section.selection_all=All form.section.selection_pre=Number of questions in this section form.section.selection_pre.hover=Select whether all or just a specified number of questions should be displayed in the test. - - - - - - - - - - - - - - - - - - - - - - - - - - +form.section.shuffle=Random order of questions? info.alien.test=This test cannot be edited by means of the OLAT Editor. info.alienitem=This question type cannot be processed with the OLAT editor. info.resumed=The test/questionnaire was not saved to learning resources during the last session. Please use "Close/save editor" in order to save your modifications. @@ -217,13 +193,6 @@ title.add=Add element title.convert.qti21=Convert to QTI 2.1 title.copy=Copy element title.move=Move element -tools.convert.qti21=Convert to QTI 2.1 -tools.import.qpool=Import questions from pool -tools.import.table=Import questions from Excel -tools.export.header=Export -tools.export.qpool=Export to pool -tools.export.docx=Export to Word -export.qpool.successful={0} questions have been exported successfully tools.add.cloze=Gap text tools.add.freetext=Text tools.add.header=Add @@ -235,6 +204,12 @@ tools.change.copy=Copy tools.change.delete=Delete tools.change.header=Change tools.change.move=Move +tools.convert.qti21=Convert to QTI 2.1 +tools.export.docx=Export to Word +tools.export.header=Export +tools.export.qpool=Export to pool +tools.import.qpool=Import questions from pool +tools.import.table=Import questions from Excel tools.matedit.back=Back tools.matedit.header=Editor tools tools.material.back=Back @@ -246,4 +221,3 @@ valuation_method_multi=Score per answer valuation_method_single=All correct answers warning.essay.test=This question muss be manually corrected. warning.test.with.essay=This test contains question of type essay. The essay has to be corrected manually and the final score after the test does not reflect the correction of the essay type and might be adjusted manually later. - diff --git a/src/main/java/org/olat/ims/qti21/ui/report/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/ims/qti21/ui/report/_i18n/LocalStrings_en.properties index 43dabce57308d76405c1198f6c706aedbdaf20f3..c1e2907d81018447ee67cdba2dc61175ec085539 100644 --- a/src/main/java/org/olat/ims/qti21/ui/report/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/ims/qti21/ui/report/_i18n/LocalStrings_en.properties @@ -1,33 +1,32 @@ -#Thu Dec 07 19:13:19 CET 2017 +#Fri Sep 04 07:30:18 CEST 2020 admin.menu.report.question.title=Questions to tests admin.menu.report.question.title.alt=Questions to tests report.course.displayname=Course title report.course.externalref=Course reference report.course.id=Course ID -report.explain=Report: selected tests including all contained questions -report.question.title=Question's title +report.explain=Report\: selected tests including all contained questions report.question.author=Question's creator (owner) +report.question.context=Level report.question.correction.time=$org.olat.modules.qpool.ui\:question.correctionTime report.question.identifier=Question ID report.question.keywords=Keywords report.question.license=$org.olat.modules.qpool.ui\:rights.license +report.question.master.author=Creator (owner master ID) +report.question.master.identifier=Question master ID +report.question.master.keywords=Keywords (question master ID) report.question.taxonomy.level=Subject report.question.taxonomy.path=Subject path +report.question.title=Question's title +report.question.to.course=Report questions report.question.topic=Topic -report.question.context=Level report.question.type=Type -report.question.master.identifier=Question master ID -report.question.master.author=Creator (owner master ID) -report.question.master.keywords=Keywords (question master ID) -report.question.to.course=Report questions -report.test.id=Test ID (learn resource) +report.test.author=Test creator (owner) report.test.displayname=Title of the learn resource test report.test.externalref=Test reference -report.test.author=Test creator (owner) +report.test.id=Test ID (learn resource) search=Search +search.author=Author / owner search.empty=No tests were found that met your criteria. search.text=Title / Ext. Ref. / ID -search.author=Author / owner warning.at.least.one.meeting=You must select at least one test. - - +warning.at.least.one.test=You must choose at least one test. diff --git a/src/main/java/org/olat/repository/manager/RepositoryEntryStatisticsDAO.java b/src/main/java/org/olat/repository/manager/RepositoryEntryStatisticsDAO.java index 99440c7093a173a00b7420aad75d8312b851722a..8cd327ed0e5ecb94ac32e6d3617f77107e768f11 100644 --- a/src/main/java/org/olat/repository/manager/RepositoryEntryStatisticsDAO.java +++ b/src/main/java/org/olat/repository/manager/RepositoryEntryStatisticsDAO.java @@ -21,6 +21,7 @@ package org.olat.repository.manager; import java.util.Calendar; import java.util.Date; +import java.util.List; import javax.annotation.PostConstruct; import javax.persistence.LockModeType; @@ -132,15 +133,16 @@ public class RepositoryEntryStatisticsDAO implements UserRatingsDelegate, UserCo dbInstance.getCurrentEntityManager().detach(re.getStatistics()); } - StringBuilder sb = new StringBuilder(); + StringBuilder sb = new StringBuilder(256); sb.append("select stats from ").append(RepositoryEntryStatistics.class.getName()).append(" as stats") .append(" where stats.key in (select v.statistics.key from ").append(RepositoryEntry.class.getName()).append(" as v where v.key=:key)"); - return dbInstance.getCurrentEntityManager() + List<RepositoryEntryStatistics> statistics = dbInstance.getCurrentEntityManager() .createQuery(sb.toString(), RepositoryEntryStatistics.class) .setParameter("key", repositoryEntryRes.getResourceableId()) .setLockMode(LockModeType.PESSIMISTIC_WRITE) - .getSingleResult(); + .getResultList(); + return statistics == null || statistics.isEmpty() ? null : statistics.get(0); } @Override diff --git a/src/main/java/org/olat/repository/ui/admin/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/repository/ui/admin/_i18n/LocalStrings_fr.properties index ffb91577c708572d82e09a8b1c670d28f9b4b954..2dc8107b69307dcd119fd428fd87e789128a0b89 100644 --- a/src/main/java/org/olat/repository/ui/admin/_i18n/LocalStrings_fr.properties +++ b/src/main/java/org/olat/repository/ui/admin/_i18n/LocalStrings_fr.properties @@ -1,10 +1,17 @@ -#Mon May 04 20:00:49 CEST 2020 +#Fri Sep 04 07:25:07 CEST 2020 admin.catalog.settings=Configuration du catalogue admin.menu.title=Catalogue admin.menu.title.alt=Catalogue +catalog.add.category.position=Ajouter une nouvelle cat\u00E9gorie +catalog.add.entry.position=Ajouter des ressources didactiques +catalog.add.multiple.entries=Ajouter plusieurs ressources \u00E0 la fois +catalog.add.position.alphabetical=Alphab\u00E9tique +catalog.add.position.bottom=\u00C0 la fin +catalog.add.position.top=Au d\u00E9but catalog.addposition=Ajouter de nouvelles entr\u00E9es catalog.addposition.bottom=\u00C0 la fin catalog.addposition.top=Au d\u00E9but catalog.browsing=Catalogue dans "Cours" catalog.enable=Activer le catalogue catalog.site=Catalogue dans son propre site +catalog.sort.completely=Ordonn\u00E9 tout le catalogue alphab\u00E9tiquement diff --git a/src/main/java/org/olat/repository/ui/catalog/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/repository/ui/catalog/_i18n/LocalStrings_en.properties index 4788b953df76a38ca8b0f530635cc75c068243bd..e0cf17ab0f9b94ad9abc0b7386428a6b8ef2ed8c 100644 --- a/src/main/java/org/olat/repository/ui/catalog/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/repository/ui/catalog/_i18n/LocalStrings_en.properties @@ -1,7 +1,8 @@ -#Tue Dec 16 09:07:21 CET 2014 -add.default=Default +#Fri Sep 04 07:36:46 CEST 2020 add.alphabetically=Automatic - Alphabetical order add.bottom=Manual - New items at last +add.default=Default +add.new.entries=Add new entries add.top=Manual - New items on top admin.catalog.settings=Catalog settings admin.menu.title=Catalog @@ -15,16 +16,16 @@ catalog.courses=My courses catalog.locked.by=Cannot start action at this time because this catalog is currently being edited by user {0} catalog.locked.by.same.user=$\:catalog.locked.by $org.olat.core\:lock.same.user.different.window catalog.new=Catalog in own site -catalog.order.info=Here you can change the display order of categories and entries.<br>Manual sorting is only possible if automatic sorting is not activated.<br>You can adjust these settings in the menu under \u0022Modify data\u0022. +catalog.order.info=Here you can change the display order of categories and entries.<br>Manual sorting is only possible if automatic sorting is not activated.<br>You can adjust these settings in the menu under "Modify data". catalog.popup.edit.shorttitle.desc=Add a short title for tiles view. -catalog.popup.position.error.number.format=Only numeric inputs -catalog.popup.position.error.number=Only values from {0} to {1} -catalog.popup.position.bigger=\u003E +catalog.popup.position.bigger=> catalog.popup.position.biggest=\u226B +catalog.popup.position.error.number=Only values from {0} to {1} +catalog.popup.position.error.number.format=Only numeric inputs catalog.popup.position.save=Save -catalog.popup.position.smaller=\u003C +catalog.popup.position.smaller=< catalog.popup.position.smallest=\u226A -catalog.position.deactivated=Please add more elements to customize the order! +catalog.position.deactivated=Please add more elements to customize the order\! catalog.tree.add.already.exists=The learning resource {0} is already attached to this catalog category catalog.tree.add.intro=Select a catalog category to which you want to move the learning resource {0} catalog.tree.add.title=Add learning resource "{0}" to catalog @@ -52,8 +53,8 @@ move=Move no.leaves=No learning resources assigned to this category repo.nocategories=This learning resource is not yet added to the catalog sort.alphabetically=Sort alphabetically -sort.nodes=Sorting of categories sort.entries=Sorting of entries +sort.nodes=Sorting of categories style=Style tiles=Tiles title.categories=Sub-categories @@ -71,7 +72,7 @@ tools.edit.header=Category tools.move.catalog.entry=Move tools.move.catalog.entry.failed=An error occurred. This element could not be moved. tools.move.catalog.entry.success=Catalog entry "{0}" successfully moved -tools.order.catalog=Ordering tools.new.catalog.categoryrequest=Contact administrator +tools.order.catalog=Ordering tools.pastestructure=Insert structure tools.set.catalog.position=Modifiy position diff --git a/src/main/java/org/olat/repository/ui/catalog/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/repository/ui/catalog/_i18n/LocalStrings_fr.properties index d30883360a6889fe7df3cee640353abf469baf59..9e7bff2aba66a4fdf429c06efd56827c6894e707 100644 --- a/src/main/java/org/olat/repository/ui/catalog/_i18n/LocalStrings_fr.properties +++ b/src/main/java/org/olat/repository/ui/catalog/_i18n/LocalStrings_fr.properties @@ -1,4 +1,9 @@ -#Fri Jul 03 11:06:20 CEST 2020 +#Fri Sep 04 07:41:59 CEST 2020 +add.alphabetically=Automatique - ordre alphab\u00E9tique +add.bottom=Manuel - nouvelles entr\u00E9es en dernier +add.default=D\u00E9fault +add.new.entries=Ajouter de nouvelles ressources\: +add.top=Manuel - nouvelles ressources en premier admin.catalog.settings=Configuration du catalogue admin.menu.title=Catalogue admin.menu.title.alt=Catalogue @@ -11,6 +16,7 @@ catalog.courses=Mes cours catalog.locked.by=Cette action ne peut pas \u00EAtre d\u00E9marr\u00E9 en ce moment, car le catalogue est \u00E9dit\u00E9 par l'utilisateur {0} catalog.locked.by.same.user=$\:catalog.locked.by $org.olat.core\:lock.same.user.different.window catalog.new=Catalogue dans son propre site +catalog.order.info=Ci-dessous, vous pouvez adapter l'ordonnance des cat\u00E9gories et des ressources didactiques.<br>L'ordonnance manuelle n'est possible que si l'ordonnance automatique n'est pas activ\u00E9e.<br>Vous pouvez changez cette option dans le menu "Modifier les donn\u00E9es". catalog.popup.edit.shorttitle.desc=Ajouter un titre court pour la vue en tuiles. catalog.popup.position.bigger=> catalog.popup.position.biggest=\u226B @@ -46,6 +52,8 @@ list.compact=Liste compacte move=D\u00E9placer no.leaves=Aucune ressource didactique n'est affect\u00E9e \u00E0 cette cat\u00E9gorie repo.nocategories=Cette ressource didactique n'est pas encore int\u00E9gr\u00E9e dans le catalogue. +sort.entries=Ordonnance des ressources didactiques +sort.nodes=Ordonnance des cat\u00E9gories style=Style tiles=Carrelage title.categories=Sous-cat\u00E9gories diff --git a/src/main/java/org/olat/search/service/document/IdentityDocument.java b/src/main/java/org/olat/search/service/document/IdentityDocument.java index 26a3fb333d3a90b4de9aa38fd5173f1215948cdf..a1a42a14ddf39f097b44da3fff2ef78eb5d9c7ef 100644 --- a/src/main/java/org/olat/search/service/document/IdentityDocument.java +++ b/src/main/java/org/olat/search/service/document/IdentityDocument.java @@ -36,6 +36,7 @@ import org.olat.search.service.SearchResourceContext; import org.olat.user.HomePageConfig; import org.olat.user.HomePageConfigManager; import org.olat.user.UserManager; +import org.olat.user.UserModule; import org.olat.user.propertyhandlers.UserPropertyHandler; /** @@ -61,6 +62,7 @@ public class IdentityDocument extends OlatDocument { */ public static Document createDocument(SearchResourceContext searchResourceContext, Identity identity) { + UserModule userModule = CoreSpringFactory.getImpl(UserModule.class); UserManager userMgr = CoreSpringFactory.getImpl(UserManager.class); HomePageConfigManager homepageMgr = CoreSpringFactory.getImpl(HomePageConfigManager.class); HomePageConfig publishConfig = homepageMgr.loadConfigFor(identity); @@ -84,10 +86,12 @@ public class IdentityDocument extends OlatDocument { } } // user text - String text = publishConfig.getTextAboutMe(); - if (StringHelper.containsNonWhitespace(text)) { - text = FilterFactory.getHtmlTagsFilter().filter(text); - content.append(text).append(' '); + if(userModule.isUserAboutMeEnabled()) { + String text = publishConfig.getTextAboutMe(); + if (StringHelper.containsNonWhitespace(text)) { + text = FilterFactory.getHtmlTagsFilter().filter(text); + content.append(text).append(' '); + } } // finally use the properties as the content for this identity if (content.length() > 0) { diff --git a/src/main/java/org/olat/user/HomePageDisplayController.java b/src/main/java/org/olat/user/HomePageDisplayController.java index 6e919a64001b5d3300630fc69fea66076cd8c8b8..3e3f776b6504c52fe71c8e6f5491136560d28d8b 100644 --- a/src/main/java/org/olat/user/HomePageDisplayController.java +++ b/src/main/java/org/olat/user/HomePageDisplayController.java @@ -125,7 +125,11 @@ public class HomePageDisplayController extends BasicController { mainVC.contextPut("userPropertyHandlers", userPropertyHandlers); mainVC.contextPut("userSearchedInterestsHandler", userSearchedInterestsHandler); - mainVC.contextPut("homepageConfig", hpc); + + if(userModule.isUserAboutMeEnabled()) { + String aboutMe = hpc.getTextAboutMe(); + mainVC.contextPut("aboutMe", aboutMe); + } // Add external link to visiting card StringBuilder extLink = new StringBuilder(); diff --git a/src/main/java/org/olat/user/ProfileFormController.java b/src/main/java/org/olat/user/ProfileFormController.java index c333774488fc8c098c2b72fa93ebb15bdba3f0d5..bdab597cc2d18eb0104a8bd3f094aeb2a3025f1d 100644 --- a/src/main/java/org/olat/user/ProfileFormController.java +++ b/src/main/java/org/olat/user/ProfileFormController.java @@ -235,20 +235,22 @@ public class ProfileFormController extends FormBasicController { } // add the "about me" text field. - FormLayoutContainer groupContainer = FormLayoutContainer.createDefaultFormLayout("group.about", getTranslator()); - groupContainer.setFormTitle(translate("form.group.about")); - groupContainer.setElementCssClass("o_user_aboutme"); - formLayout.add(groupContainer); + FormLayoutContainer aboutMeContainer = FormLayoutContainer.createDefaultFormLayout("group.about", getTranslator()); + aboutMeContainer.setFormTitle(translate("form.group.about")); + aboutMeContainer.setElementCssClass("o_user_aboutme"); + aboutMeContainer.setVisible(userModule.isUserAboutMeEnabled()); + formLayout.add(aboutMeContainer); HomePageConfig conf = hpcm.loadConfigFor(identityToModify); textAboutMe = uifactory.addRichTextElementForStringData("form.text", "form.text", - conf.getTextAboutMe(), 10, -1, false, null, null, groupContainer, + conf.getTextAboutMe(), 10, -1, false, null, null, aboutMeContainer, ureq.getUserSession(), getWindowControl()); + textAboutMe.setVisible(userModule.isUserAboutMeEnabled()); textAboutMe.setEnabled(canModify); textAboutMe.setMaxLength(10000); //upload image - groupContainer = FormLayoutContainer.createDefaultFormLayout("portraitupload", getTranslator()); + FormLayoutContainer groupContainer = FormLayoutContainer.createDefaultFormLayout("portraitupload", getTranslator()); groupContainer.setFormTitle(translate("ul.header")); formLayout.add(groupContainer); diff --git a/src/main/java/org/olat/user/UserModule.java b/src/main/java/org/olat/user/UserModule.java index 0cb94df959f00336185f0af4e0ddf9e54eafe8cc..a091d0f12c6ac1d8045fe067ee415d32a3d320ae 100644 --- a/src/main/java/org/olat/user/UserModule.java +++ b/src/main/java/org/olat/user/UserModule.java @@ -72,6 +72,7 @@ public class UserModule extends AbstractSpringModule { private static final String ALLOW_REQUEST_DELETE_ACCOUNT_DISCLAIMER = "allow.request.delete.account.disclaimer"; private static final String MAIL_REQUEST_DELETE_ACCOUNT = "request.delete.account.mail"; private static final String PORTRAIT_MANAGED = "user.portrait.managed"; + private static final String ABOUT_ME_ENABLED = "user.about.me"; private static final String USER_AUTOMATIC_DEACTIVATION = "user.automatic.deactivation"; private static final String USER_AUTOMATIC_DELETION = "user.automatic.deletion"; @@ -114,6 +115,9 @@ public class UserModule extends AbstractSpringModule { @Value("${user.portrait.managed:false}") private boolean portraitManaged; + @Value("${user.about.me:true}") + private boolean userAboutMeEnabled; + @Value("${user.automatic.deactivation:false}") private boolean userAutomaticDeactivation; @Value("${user.days.before.deactivation:720}") @@ -421,6 +425,15 @@ public class UserModule extends AbstractSpringModule { setStringProperty(PORTRAIT_MANAGED, Boolean.toString(portraitManaged), true); } + public boolean isUserAboutMeEnabled() { + return userAboutMeEnabled; + } + + public void setUserAboutMeEnabled(boolean enabled) { + this.userAboutMeEnabled = enabled; + setStringProperty(ABOUT_ME_ENABLED, Boolean.toString(enabled), true); + } + public boolean isUserAutomaticDeactivation() { return userAutomaticDeactivation; } diff --git a/src/main/java/org/olat/user/WebDAVPasswordController.java b/src/main/java/org/olat/user/WebDAVPasswordController.java index ff43c3db988f345b05ca48f0a076ae4c92c12b4e..ab2b4b9a4c673e3f1df9b14c94de00bf3413e236 100644 --- a/src/main/java/org/olat/user/WebDAVPasswordController.java +++ b/src/main/java/org/olat/user/WebDAVPasswordController.java @@ -161,17 +161,7 @@ public class WebDAVPasswordController extends FormBasicController { } private String getUsernames(List<Authentication> authentications) { - StringBuilder sb = new StringBuilder(); - sb.append(getIdentity().getName()); - if(userModule.isEmailUnique()) { - if(StringHelper.containsNonWhitespace(getIdentity().getUser().getEmail())) { - sb.append(", ").append(getIdentity().getUser().getEmail()); - } - if(StringHelper.containsNonWhitespace(getIdentity().getUser().getInstitutionalEmail())) { - sb.append(", ").append(getIdentity().getUser().getInstitutionalEmail()); - } - } - + StringBuilder sb = new StringBuilder(64); for(Authentication auth : authentications) { if(WebDAVAuthManager.PROVIDER_WEBDAV.equals(auth.getProvider()) || WebDAVAuthManager.PROVIDER_WEBDAV_EMAIL.equals(auth.getProvider()) @@ -179,9 +169,12 @@ public class WebDAVPasswordController extends FormBasicController { || WebDAVAuthManager.PROVIDER_HA1.equals(auth.getProvider()) || WebDAVAuthManager.PROVIDER_HA1_EMAIL.equals(auth.getProvider()) || WebDAVAuthManager.PROVIDER_HA1_INSTITUTIONAL_EMAIL.equals(auth.getProvider())) { - String authUsername = auth.getAuthusername(); - if(sb.indexOf(authUsername) < 0) { - sb.append(", ").append(authUsername); + appendUsername(auth.getAuthusername(), sb); + } else if(BaseSecurityModule.getDefaultAuthProviderIdentifier().equals(auth.getProvider())) { + appendUsername(auth.getAuthusername(), sb); + if(userModule.isEmailUnique()) { + appendUsername(getIdentity().getUser().getEmail(), sb); + appendUsername(getIdentity().getUser().getInstitutionalEmail(), sb); } } } @@ -189,6 +182,13 @@ public class WebDAVPasswordController extends FormBasicController { return sb.toString(); } + private void appendUsername(String authUsername, StringBuilder sb) { + if(StringHelper.containsNonWhitespace(authUsername) && sb.indexOf(authUsername) < 0) { + if(sb.length() > 0) sb.append(", "); + sb.append(authUsername); + } + } + @Override protected void doDispose() { //auto-disposed diff --git a/src/main/java/org/olat/user/_content/homepagedisplay.html b/src/main/java/org/olat/user/_content/homepagedisplay.html index fe56566d8f9a6b85edfe67f81238969a4d17af37..7b6c1ce529c950b2986ab70811336e420a156b07 100644 --- a/src/main/java/org/olat/user/_content/homepagedisplay.html +++ b/src/main/java/org/olat/user/_content/homepagedisplay.html @@ -18,17 +18,17 @@ <table class="table table-condensed table-striped"> #if($r.available("im.link")) <tr class="o_im_status"> - <th>$r.translate("status")</th> + <th scope="row">$r.translate("status")</th> <td colspan="3"><div id="o_im_buddy">$r.render("im.link")</div></td> </tr> #end #foreach($propertyHandler in $userPropertyHandlers ) <tr> - <th>$r.translate($propertyHandler.i18nFormElementLabelKey()) </th> + <th scope="row">$r.translate($propertyHandler.i18nFormElementLabelKey()) </th> #if($propertyHandler.name == "userInterests" && $userSearchedInterestsHandler) <td>$!propertyHandler.getUserPropertyAsHTML($user, $locale)</td> - <th>$r.translate($userSearchedInterestsHandler.i18nFormElementLabelKey())</th> + <th scope="row">$r.translate($userSearchedInterestsHandler.i18nFormElementLabelKey())</th> <td>$!userSearchedInterestsHandler.getUserPropertyAsHTML($user, $locale)</td> #else <td colspan="3">$!propertyHandler.getUserPropertyAsHTML($user, $locale)</td> @@ -38,7 +38,7 @@ #if($r.isNotEmpty($organisations)) <tr valign="top" class="o_usser_organisations"> - <th>$r.translate("form.organisations")</th> + <th scope="row">$r.translate("form.organisations")</th> <td colspan="3"><ul class="list-unstyled"> #foreach($organisation in $organisations) <li>$r.escapeHtml($organisation)</li> @@ -46,10 +46,10 @@ </ul></td> </tr> #end - #if( $homepageConfig.getTextAboutMe() && ($homepageConfig.getTextAboutMe() != "") ) + #if($r.isNotEmpty($aboutMe)) <tr valign="top" class="o_user_aboutme"> - <th>$r.translate("form.text")</th> - <td colspan="3">$!r.formatLatexFormulas($homepageConfig.getTextAboutMe())</td> + <th scope="row">$r.translate("form.text")</th> + <td colspan="3">$!r.formatLatexFormulas($aboutMe)</td> </tr> #end </table> @@ -63,11 +63,9 @@ <div class="o_copy_code o_nowrap"> <a href="javascript:;" id="o_extlink" data-original-title="" title=""><i class="o_icon o_icon-lg o_icon-fw o_icon_qrcode"> </i></a><input type="text" value="$extLink" onclick="this.select()"/> <script> - /* <![CDATA[ */ - jQuery(function() { - o_QRCodePopup('o_extlink', '$extLink', 'right'); - }); - /* ]]> */ + jQuery(function() { + o_QRCodePopup('o_extlink', '$extLink', 'right'); + }); </script> </div> </div> diff --git a/src/main/java/org/olat/user/manager/lifecycle/UserLifecycleManagerImpl.java b/src/main/java/org/olat/user/manager/lifecycle/UserLifecycleManagerImpl.java index ebe71bedace150bc6883c0dee6a8b80a8a8657ba..585c9678e1414f1bffe3b0e0aa5eb4e427a0b847 100644 --- a/src/main/java/org/olat/user/manager/lifecycle/UserLifecycleManagerImpl.java +++ b/src/main/java/org/olat/user/manager/lifecycle/UserLifecycleManagerImpl.java @@ -199,10 +199,10 @@ public class UserLifecycleManagerImpl implements UserLifecycleManager { Date lastLoginDate = getDate(numOfDaysBeforeDeactivation); List<Identity> identities; if(sendMailBeforeDeactivation) { - identities = getIdentitiesToInactivate(lastLoginDate, null); - } else { Date emailBeforeDate = getDate(numOfDaysBeforeEmail); identities = getIdentitiesToInactivate(lastLoginDate, emailBeforeDate); + } else { + identities = getIdentitiesToInactivate(lastLoginDate, null); } for(Identity identity:identities) { diff --git a/src/main/java/org/olat/user/ui/admin/authentication/_content/authentications.html b/src/main/java/org/olat/user/ui/admin/authentication/_content/authentications.html index 18c1e1c8173f7cedd353c6deaad38ee9a26228e4..a22e3c2dde8663b29a6056999843e8d958fd13e4 100644 --- a/src/main/java/org/olat/user/ui/admin/authentication/_content/authentications.html +++ b/src/main/java/org/olat/user/ui/admin/authentication/_content/authentications.html @@ -1,6 +1,11 @@ -<div class="form-group $f.getElementCssClass($item) o_user_edit_username clearfix"> - $r.render("username_LABEL", $f.getItemId("username"), "col-sm-3") - <div class="col-sm-3 form-inline">$r.render("username") $r.render("edit")</div> -</div> - -$r.render("table") \ No newline at end of file +<fieldset> + <legend>$r.translate("change.username.title")</legend> + <div class="form-group $f.getElementCssClass($item) o_user_edit_username clearfix"> + $r.render("username_LABEL", $f.getItemId("username"), "col-sm-3") + <div class="col-sm-3 form-inline">$r.render("username") $r.render("edit")</div> + </div> +</fieldset> +<fieldset> + <legend>$r.translate("authentications.title")</legend> + $r.render("table") +</fieldset> diff --git a/src/main/java/org/olat/user/ui/admin/authentication/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/user/ui/admin/authentication/_i18n/LocalStrings_de.properties index c4ecc5a54e15ccb05c0d6cae6515fdc1d0ec5ea4..acb06002e7f4248a0beae6944e17adf0265a9402 100644 --- a/src/main/java/org/olat/user/ui/admin/authentication/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/user/ui/admin/authentication/_i18n/LocalStrings_de.properties @@ -1,8 +1,11 @@ #Fri Jun 05 15:17:38 CEST 2020 +authentications.title=Authentifizierungen change.providers=Login change.providers.on=Login Name adaptieren +change.username.title=Benutzername \u00E4ndern edit.title=Bearbeiten general.error.unique=$org.olat.user.propertyhandlers\:general.error.unique login=$org.olat.admin.user\:table.auth.login provider=$org.olat.admin.user\:table.auth.provider +table.auth.login=Loginname username=$org.olat.admin.user\:form.username \ No newline at end of file diff --git a/src/main/java/org/olat/user/ui/admin/authentication/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/user/ui/admin/authentication/_i18n/LocalStrings_en.properties index 86f6323c03b930f09d24bcb8743ca1de446fd1ac..64f70a6ba522ace295876d8c676f54c2c9aebbdb 100644 --- a/src/main/java/org/olat/user/ui/admin/authentication/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/user/ui/admin/authentication/_i18n/LocalStrings_en.properties @@ -1,8 +1,11 @@ #Fri Jun 05 15:17:38 CEST 2020 +authentications.title=Authentications change.providers=Login change.providers.on=adapt login names +change.username.title=Change user name edit.title=Edit general.error.unique=$org.olat.user.propertyhandlers\:general.error.unique login=$org.olat.admin.user\:table.auth.login provider=$org.olat.admin.user\:table.auth.provider +table.auth.login=Login name username=$org.olat.admin.user\:form.username \ No newline at end of file diff --git a/src/main/java/org/olat/user/ui/admin/authentication/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/user/ui/admin/authentication/_i18n/LocalStrings_fr.properties index ecb3f6b98edd4428ef0eda5035096ff1b9b16eb0..40caf3b1d222fc013cb07802d6b50b9d94f03ed2 100644 --- a/src/main/java/org/olat/user/ui/admin/authentication/_i18n/LocalStrings_fr.properties +++ b/src/main/java/org/olat/user/ui/admin/authentication/_i18n/LocalStrings_fr.properties @@ -1,6 +1,11 @@ -#Wed Aug 12 07:19:24 CEST 2020 +#Fri Sep 04 07:28:11 CEST 2020 +authentications.title=Authentifications change.providers=Login +change.providers.on=adapter les identifiants +change.username.title=Changer le nom d'utilisateur edit.title=\u00C9diter +general.error.unique=$org.olat.user.propertyhandlers\:general.error.unique login=$org.olat.admin.user\:table.auth.login provider=$org.olat.admin.user\:table.auth.provider +table.auth.login=Identifiant username=$org.olat.admin.user\:form.username diff --git a/src/main/java/org/olat/user/ui/admin/lifecycle/UserAdminLifecycleConfigurationController.java b/src/main/java/org/olat/user/ui/admin/lifecycle/UserAdminLifecycleConfigurationController.java index 11c36b02e5124039ced9665c88544fb56f6f2334..2fa12a9ae8c8ab0354487a93aedbf9834059df96 100644 --- a/src/main/java/org/olat/user/ui/admin/lifecycle/UserAdminLifecycleConfigurationController.java +++ b/src/main/java/org/olat/user/ui/admin/lifecycle/UserAdminLifecycleConfigurationController.java @@ -92,7 +92,6 @@ public class UserAdminLifecycleConfigurationController extends FormBasicControll formLayout.add(buttonsLayout); uifactory.addFormSubmitButton("save", buttonsLayout); } - protected void initDeactivationForm(FormItemContainer formLayout) { String[] onValues = new String[] { translate("enabled") }; @@ -116,8 +115,8 @@ public class UserAdminLifecycleConfigurationController extends FormBasicControll initDays(numberOfDayBeforeDeactivationMailEl); // subject + content mail - TranslationBundle beforeBundleSubject = initForm("mail.before.deactivation.subject.label", "mail.before.deactivation.subject", formLayout); - TranslationBundle beforeBundle = initForm("mail.before.deactivation.body.label", "mail.before.deactivation.body", formLayout); + TranslationBundle beforeBundleSubject = initForm("mail.before.deactivation.subject.label", "mail.before.deactivation.subject", false, formLayout); + TranslationBundle beforeBundle = initForm("mail.before.deactivation.body.label", "mail.before.deactivation.body", true, formLayout); mailBeforeDeactivationBundles = new TranslationBundles(beforeBundleSubject, beforeBundle); // enable mail after @@ -126,8 +125,8 @@ public class UserAdminLifecycleConfigurationController extends FormBasicControll enableMailAfterDeactivationEl.select(onKeys[0], userModule.isMailAfterDeactivation()); // subject + content mail - TranslationBundle afterBundleSubject = initForm("mail.after.deactivation.subject.label", "mail.after.deactivation.subject", formLayout); - TranslationBundle afterBundle = initForm("mail.after.deactivation.body.label", "mail.after.deactivation.body", formLayout); + TranslationBundle afterBundleSubject = initForm("mail.after.deactivation.subject.label", "mail.after.deactivation.subject", false, formLayout); + TranslationBundle afterBundle = initForm("mail.after.deactivation.body.label", "mail.after.deactivation.body", true, formLayout); mailAfterDeactivationBundles = new TranslationBundles(afterBundleSubject, afterBundle); } @@ -152,8 +151,8 @@ public class UserAdminLifecycleConfigurationController extends FormBasicControll initDays(numberOfDayBeforeDeletionMailEl); // subject + content mail - TranslationBundle beforeBundleSubject = initForm("mail.before.deletion.subject.label", "mail.before.deletion.subject", formLayout); - TranslationBundle beforeBundle = initForm("mail.before.deletion.body.label", "mail.before.deletion.body", formLayout); + TranslationBundle beforeBundleSubject = initForm("mail.before.deletion.subject.label", "mail.before.deletion.subject", false, formLayout); + TranslationBundle beforeBundle = initForm("mail.before.deletion.body.label", "mail.before.deletion.body", true, formLayout); mailBeforeDeletionBundles = new TranslationBundles(beforeBundleSubject, beforeBundle); // enable mail after @@ -162,17 +161,17 @@ public class UserAdminLifecycleConfigurationController extends FormBasicControll enableMailAfterDeletionEl.select(onKeys[0], userModule.isMailAfterDeletion()); // subject + content mail - TranslationBundle afterBundleSubject = initForm("mail.after.deletion.subject.label", "mail.after.deletion.subject", formLayout); - TranslationBundle afterBundle = initForm("mail.after.deletion.body.label", "mail.after.deletion.body", formLayout); + TranslationBundle afterBundleSubject = initForm("mail.after.deletion.subject.label", "mail.after.deletion.subject", false, formLayout); + TranslationBundle afterBundle = initForm("mail.after.deletion.body.label", "mail.after.deletion.body", true, formLayout); mailAfterDeletionBundles = new TranslationBundles(afterBundleSubject, afterBundle); } - private TranslationBundle initForm(String labelI18nKey, String textI18nKey, FormItemContainer formLayout) { + private TranslationBundle initForm(String labelI18nKey, String textI18nKey, boolean textArea, FormItemContainer formLayout) { String text = translate(textI18nKey); StaticTextElement viewEl = uifactory.addStaticTextElement("view." + counter++, labelI18nKey, text, formLayout); FormLink translationLink = uifactory.addFormLink("translate." + counter++, "translation.edit", null, formLayout, Link.LINK); - TranslationBundle bundle = new TranslationBundle(textI18nKey, labelI18nKey, viewEl, translationLink); + TranslationBundle bundle = new TranslationBundle(textI18nKey, labelI18nKey, viewEl, translationLink, textArea); translationLink.setUserObject(bundle); return bundle; } @@ -310,7 +309,7 @@ public class UserAdminLifecycleConfigurationController extends FormBasicControll if(guardModalController(translatorCtrl)) return; translatorCtrl = new SingleKeyTranslatorController(ureq, getWindowControl(), bundle.getI18nKey(), - UserAdminLifecycleConfigurationController.class); + UserAdminLifecycleConfigurationController.class, bundle.isTextArea()); translatorCtrl.setUserObject(bundle); listenTo(translatorCtrl); @@ -326,12 +325,14 @@ public class UserAdminLifecycleConfigurationController extends FormBasicControll private static class TranslationBundle { + private final boolean textArea; private final String i18nKey; private final String labelI18nKey; private final StaticTextElement viewEl; private final FormLink translationLink; - public TranslationBundle(String i18nKey, String labelI18nKey, StaticTextElement viewEl, FormLink translationLink) { + public TranslationBundle(String i18nKey, String labelI18nKey, StaticTextElement viewEl, FormLink translationLink, boolean textArea) { + this.textArea = textArea; this.i18nKey = i18nKey; this.viewEl = viewEl; this.labelI18nKey = labelI18nKey; @@ -341,6 +342,10 @@ public class UserAdminLifecycleConfigurationController extends FormBasicControll public StaticTextElement getViewEl() { return viewEl; } + + public boolean isTextArea() { + return textArea; + } public String getI18nKey() { return i18nKey; diff --git a/src/main/java/org/olat/user/ui/admin/lifecycle/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/user/ui/admin/lifecycle/_i18n/LocalStrings_en.properties index 91e6d033147065696d7a176eaf037f59d4aa2118..c89355479052d494a8d9f0bc2a1e98d9b8ae6b3b 100644 --- a/src/main/java/org/olat/user/ui/admin/lifecycle/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/user/ui/admin/lifecycle/_i18n/LocalStrings_en.properties @@ -1,4 +1,4 @@ -#Fri Jun 05 15:17:38 CEST 2020 +#Fri Sep 04 07:38:48 CEST 2020 admin.configuration.title=Automatic life-cycle management admin.menu.title.lifecycle=User Life-cycle admin.menu.title.lifecycle.alt=Automatic user life-cycle management @@ -37,9 +37,10 @@ overview.inactive.user=Deactivated users overview.ready.to.delete.user=Ready to delete overview.ready.to.inactivate.user=Users with no activity readyToDelete.delete.confirm=The selected user accounts "<strong>{0}</strong>" (along with personal data) will be deleted unrecoverably. -readyToDelete.delete.confirm.singlle=The selected user account "<strong>{0}</strong>" (along with personal data) will be deleted unrecoverably. readyToDelete.delete.confirm.check=All files will be permanently removed and cannot be recovered. readyToDelete.delete.confirm.check.label=Confirmation +readyToDelete.delete.confirm.single=The selected user account "<strong>{0}</strong>" (with the personal data) will be deleted and you will not be able to restore it. +readyToDelete.delete.confirm.singlle=The selected user account "<strong>{0}</strong>" (along with personal data) will be deleted unrecoverably. table.identity.deleted.name=Del_User name table.identity.deletedby=Deleted by table.identity.deleteddate=Deleted diff --git a/src/main/resources/database/postgresql/alter_15_2_x_to_15_2_2.sql b/src/main/resources/database/postgresql/alter_15_2_x_to_15_2_2.sql index c5c25c2ee6f2501c500432af0f1771c5937de64b..0cbcce3a59f74938c127500ac4f8f512b3c1f607 100644 --- a/src/main/resources/database/postgresql/alter_15_2_x_to_15_2_2.sql +++ b/src/main/resources/database/postgresql/alter_15_2_x_to_15_2_2.sql @@ -1,2 +1,6 @@ alter table o_catentry add column add_entry_position int; -alter table o_catentry add column add_category_position int; \ No newline at end of file +alter table o_catentry add column add_category_position int; + + +-- Authentication +create index low_authusername_idx on o_bs_authentication (lower(authusername)); \ No newline at end of file diff --git a/src/main/resources/database/postgresql/setupDatabase.sql b/src/main/resources/database/postgresql/setupDatabase.sql index 2ad1e0eb33ead552c049abda645aabdb0a6c9222..9d2df9787ff2f995b89e5d8a287b60448f12f175 100644 --- a/src/main/resources/database/postgresql/setupDatabase.sql +++ b/src/main/resources/database/postgresql/setupDatabase.sql @@ -3379,6 +3379,7 @@ create index idx_auth_ident_idx on o_bs_authentication (identity_fk); create index provider_idx on o_bs_authentication (provider); create index credential_idx on o_bs_authentication (credential); create index authusername_idx on o_bs_authentication (authusername); +create index low_authusername_idx on o_bs_authentication (lower(authusername)); alter table o_bs_authentication_history add constraint auth_hist_to_ident_idx foreign key (fk_identity) references o_bs_identity (id); create index idx_auth_hist_to_ident_idx on o_bs_authentication_history (fk_identity); diff --git a/src/main/resources/serviceconfig/olat.properties b/src/main/resources/serviceconfig/olat.properties index c3b05af268db8bfe718bddc482fe5599e12dd8e7..219535067a8eccfcf74f5bd0d26ef2607a3b6dc6 100644 --- a/src/main/resources/serviceconfig/olat.properties +++ b/src/main/resources/serviceconfig/olat.properties @@ -866,6 +866,8 @@ user.email.unique=true # Set to false to make user portrait / avatar image read-only # Does not apply to users with administrator role in user management user.portrait.managed=false +# Enable or disable the text field "About me" +user.about.me=true # Enable the automatic process to deactivate users user.automatic.deactivation=false diff --git a/src/test/java/org/olat/basesecurity/BaseSecurityManagerTest.java b/src/test/java/org/olat/basesecurity/BaseSecurityManagerTest.java index c40ba89973afbf01bc90c304f3b73863c64117c5..c83ec0d3c85828857159a384da22dc60c1a582d3 100644 --- a/src/test/java/org/olat/basesecurity/BaseSecurityManagerTest.java +++ b/src/test/java/org/olat/basesecurity/BaseSecurityManagerTest.java @@ -722,6 +722,29 @@ public class BaseSecurityManagerTest extends OlatTestCase { Assert.assertNotNull(lastLogin); } + @Test + public void updateLastLoginAndInactivationDate() { + Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("last-login-0"); + ((IdentityImpl)id).setInactivationEmailDate(new Date()); + id = dbInstance.getCurrentEntityManager().merge(id); + dbInstance.commitAndCloseSession(); + + id = securityManager.loadIdentityByKey(id.getKey()); + Date mergedInactivationDate = ((IdentityImpl)id).getInactivationEmailDate(); + Assert.assertNotNull(mergedInactivationDate); + dbInstance.commitAndCloseSession(); + + securityManager.setIdentityLastLogin(id); + dbInstance.commitAndCloseSession(); + + id = securityManager.loadIdentityByKey(id.getKey()); + Date lastLogin = id.getLastLogin(); + Assert.assertNotNull(lastLogin); + Date inactivationDate = ((IdentityImpl)id).getInactivationEmailDate(); + Assert.assertNull(inactivationDate); + } + + @Test public void countUniqueUserLoginsSince() { Calendar cal = Calendar.getInstance(); diff --git a/src/test/java/org/olat/basesecurity/manager/AuthenticationDAOTest.java b/src/test/java/org/olat/basesecurity/manager/AuthenticationDAOTest.java index 0b1e91a053fdfa0356f0f706041b169219f1c80e..9263b7a175e3d3bdbe59c3ac07b47baa2ced5c45 100644 --- a/src/test/java/org/olat/basesecurity/manager/AuthenticationDAOTest.java +++ b/src/test/java/org/olat/basesecurity/manager/AuthenticationDAOTest.java @@ -121,6 +121,25 @@ public class AuthenticationDAOTest extends OlatTestCase { Assert.assertEquals(ident.getIdentity(), identities.get(0)); } + @Test + public void getIdentitiesWithCamelCaseLogin() { + String token = UUID.randomUUID().toString(); + IdentityWithLogin ident = JunitTestHelper.createAndPersistRndUser("authdao-2-"); + Authentication auth = securityManager.createAndPersistAuthentication(ident.getIdentity(), "OLAT", ident.getLogin(), token, null); + dbInstance.commitAndCloseSession(); + Assert.assertNotNull(auth); + + List<Identity> lowerIdentities = authenticationDao.getIdentitiesWithLogin(ident.getLogin().toLowerCase()); + Assert.assertNotNull(lowerIdentities); + Assert.assertEquals(1, lowerIdentities.size()); + Assert.assertEquals(ident.getIdentity(), lowerIdentities.get(0)); + + List<Identity> upperIdentities = authenticationDao.getIdentitiesWithLogin(ident.getLogin().toUpperCase()); + Assert.assertNotNull(upperIdentities); + Assert.assertEquals(1, upperIdentities.size()); + Assert.assertEquals(ident.getIdentity(), upperIdentities.get(0)); + } + @Test public void getAuthentication() { String token = UUID.randomUUID().toString(); @@ -153,6 +172,23 @@ public class AuthenticationDAOTest extends OlatTestCase { Assert.assertNull(ldapAuthentication); } + @Test + public void getAuthenticationByAuthusernameCamelCase() { + String token = UUID.randomUUID().toString(); + IdentityWithLogin ident = JunitTestHelper.createAndPersistRndUser("authdao-2low-"); + Authentication auth = securityManager.createAndPersistAuthentication(ident.getIdentity(), "OLAT", ident.getLogin(), token, null); + dbInstance.commitAndCloseSession(); + Assert.assertNotNull(auth); + + Authentication lowerAuthentication = authenticationDao.getAuthenticationByAuthusername(ident.getLogin().toLowerCase(), "OLAT"); + Assert.assertNotNull(lowerAuthentication); + Assert.assertEquals(ident.getIdentity(), lowerAuthentication.getIdentity()); + + Authentication upperAuthentication = authenticationDao.getAuthenticationByAuthusername(ident.getLogin().toUpperCase(), "OLAT"); + Assert.assertNotNull(upperAuthentication); + Assert.assertEquals(ident.getIdentity(), upperAuthentication.getIdentity()); + } + @Test public void getAuthenticationsByAuthusername() { String token = UUID.randomUUID().toString(); @@ -167,6 +203,25 @@ public class AuthenticationDAOTest extends OlatTestCase { Assert.assertEquals(ident.getIdentity(), olatAuthentications.get(0).getIdentity()); } + @Test + public void getAuthenticationsByAuthusernameCamelCase() { + String token = UUID.randomUUID().toString(); + IdentityWithLogin ident = JunitTestHelper.createAndPersistRndUser("authdao-2-"); + Authentication auth = securityManager.createAndPersistAuthentication(ident.getIdentity(), "OLAT", ident.getLogin(), token, null); + dbInstance.commitAndCloseSession(); + Assert.assertNotNull(auth); + + List<Authentication> lowerAuthentications = authenticationDao.getAuthenticationsByAuthusername(ident.getLogin().toLowerCase()); + Assert.assertNotNull(lowerAuthentications); + Assert.assertEquals(1, lowerAuthentications.size()); + Assert.assertEquals(ident.getIdentity(), lowerAuthentications.get(0).getIdentity()); + + List<Authentication> upperAuthentications = authenticationDao.getAuthenticationsByAuthusername(ident.getLogin().toUpperCase()); + Assert.assertNotNull(upperAuthentications); + Assert.assertEquals(1, upperAuthentications.size()); + Assert.assertEquals(ident.getIdentity(), upperAuthentications.get(0).getIdentity()); + } + @Test public void getAuthenticationsByProvider() { IdentityWithLogin ident = JunitTestHelper.createAndPersistRndUser("authdao-2-"); @@ -201,6 +256,27 @@ public class AuthenticationDAOTest extends OlatTestCase { Assert.assertTrue(ldapAuthentications.isEmpty()); } + @Test + public void getAuthenticationsByAuthusername_providersCamelList() { + String token = UUID.randomUUID().toString(); + IdentityWithLogin ident = JunitTestHelper.createAndPersistRndUser("authdao-2-"); + Authentication auth = securityManager.createAndPersistAuthentication(ident.getIdentity(), "OLAT", ident.getLogin(), token, null); + dbInstance.commitAndCloseSession(); + Assert.assertNotNull(auth); + + List<String> providerList = Collections.singletonList("OLAT"); + List<Authentication> lowerAuthentications = authenticationDao.getAuthenticationsByAuthusername(ident.getLogin().toLowerCase(), providerList); + Assert.assertNotNull(lowerAuthentications); + Assert.assertEquals(1, lowerAuthentications.size()); + Assert.assertEquals(ident.getIdentity(), lowerAuthentications.get(0).getIdentity()); + + // negative test + List<Authentication> upperAuthentications = authenticationDao.getAuthenticationsByAuthusername(ident.getLogin().toUpperCase(), providerList); + Assert.assertNotNull(upperAuthentications); + Assert.assertEquals(1, upperAuthentications.size()); + Assert.assertEquals(ident.getIdentity(), upperAuthentications.get(0).getIdentity()); + } + @Test public void getAuthentications() { String token = UUID.randomUUID().toString(); diff --git a/src/test/java/org/olat/repository/manager/RepositoryEntryStatisticsDAOTest.java b/src/test/java/org/olat/repository/manager/RepositoryEntryStatisticsDAOTest.java index d48521f50b614b507113118f6929185d6734e315..f2f16b199043c830afca4568e7dd8a0c4fc31af8 100644 --- a/src/test/java/org/olat/repository/manager/RepositoryEntryStatisticsDAOTest.java +++ b/src/test/java/org/olat/repository/manager/RepositoryEntryStatisticsDAOTest.java @@ -41,6 +41,7 @@ import org.olat.core.id.OLATResourceable; import org.olat.core.id.Organisation; import org.apache.logging.log4j.Logger; import org.olat.core.logging.Tracing; +import org.olat.core.util.resource.OresHelper; import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryEntryStatusEnum; import org.olat.repository.RepositoryManager; @@ -133,6 +134,14 @@ public class RepositoryEntryStatisticsDAOTest extends OlatTestCase { Assert.assertEquals(1, stats.getNumOfComments()); } + @Test + public void updateCommentsStatisticsOfGhostResource() { + OLATResourceable ores = OresHelper.createOLATResourceableInstance("LifeIsBeautiful", 42l); + boolean updated = reStatisticsDao.update(ores, "apath", 3); + Assert.assertFalse(updated); + dbInstance.commit();// ensure the session is viable + } + @Test public void incrementLaunchCounter() { Organisation defOrganisation = organisationService.getDefaultOrganisation(); diff --git a/src/test/java/org/olat/user/manager/lifecycle/UserLifecycleManagerTest.java b/src/test/java/org/olat/user/manager/lifecycle/UserLifecycleManagerTest.java index fab1608f7ddbd6326777abce7719d943f57f216e..8d4bf63e759698edac59c3196d672c38d1618933 100644 --- a/src/test/java/org/olat/user/manager/lifecycle/UserLifecycleManagerTest.java +++ b/src/test/java/org/olat/user/manager/lifecycle/UserLifecycleManagerTest.java @@ -206,13 +206,16 @@ public class UserLifecycleManagerTest extends OlatTestCase { @Test public void inactivateIdentities() { Assert.assertTrue(userModule.isUserAutomaticDeactivation()); + userModule.setMailBeforeDeactivation(true); + userModule.setNumberOfInactiveDayBeforeDeactivation(720); + userModule.setNumberOfDayBeforeDeactivationMail(30); Identity id1 = JunitTestHelper.createAndPersistIdentityAsRndUser("lifecycle-9"); identityDao.setIdentityLastLogin(id1, DateUtils.addDays(new Date(), -1205)); id1 = securityManager.saveIdentityStatus(id1, Identity.STATUS_ACTIV, null); Identity id2 = JunitTestHelper.createAndPersistIdentityAsRndUser("lifecycle-10"); - identityDao.setIdentityLastLogin(id2, DateUtils.addDays(new Date(), -1308)); + identityDao.setIdentityLastLogin(id2, DateUtils.addDays(new Date(), -708)); id2 = securityManager.saveIdentityStatus(id2, Identity.STATUS_PENDING, null); dbInstance.commitAndCloseSession(); @@ -236,16 +239,17 @@ public class UserLifecycleManagerTest extends OlatTestCase { Assert.assertEquals(Identity.STATUS_PENDING, informedId2.getStatus()); Assert.assertNotNull(((IdentityImpl)informedId2).getInactivationEmailDate()); + // check mails sent + List<SmtpMessage> messages = getSmtpServer().getReceivedEmails(); + Assert.assertTrue(hasTo(informedId1.getUser().getEmail(), messages)); + Assert.assertTrue(hasTo(informedId2.getUser().getEmail(), messages)); + getSmtpServer().reset(); + // Artificially mail in past ((IdentityImpl)informedId1).setInactivationEmailDate(DateUtils.addDays(new Date(), -31)); informedId1 = identityDao.saveIdentity(informedId1); - ((IdentityImpl)informedId2).setInactivationEmailDate(DateUtils.addDays(new Date(), -31)); + ((IdentityImpl)informedId2).setInactivationEmailDate(DateUtils.addDays(new Date(), -21)); informedId2 = identityDao.saveIdentity(informedId2); - - // check mails sent - List<SmtpMessage> messages = getSmtpServer().getReceivedEmails(); - Assert.assertTrue(messages.size() >= 2); - getSmtpServer().reset(); Set<Identity> vetoed2 = new HashSet<>(); lifecycleManager.inactivateIdentities(vetoed2); @@ -263,7 +267,18 @@ public class UserLifecycleManagerTest extends OlatTestCase { // check mails sent List<SmtpMessage> inactivedMessages = getSmtpServer().getReceivedEmails(); - Assert.assertTrue(inactivedMessages.size() >= 2); + Assert.assertTrue(hasTo(informedId1.getUser().getEmail(), inactivedMessages)); + Assert.assertFalse(hasTo(informedId2.getUser().getEmail(), inactivedMessages)); + getSmtpServer().reset(); + } + + private boolean hasTo(String to, List<SmtpMessage> messages) { + for(SmtpMessage message:messages) { + if(message.getHeaderValue("To").contains(to)) { + return true; + } + } + return false; } @Test