diff --git a/src/main/java/org/olat/basesecurity/BaseSecurityManager.java b/src/main/java/org/olat/basesecurity/BaseSecurityManager.java index c3a897b7637e373a2b15618cd2092bfdb1a8994e..862547f78e82ecc8e9cb7f1afdc7d62d4c5805d7 100644 --- a/src/main/java/org/olat/basesecurity/BaseSecurityManager.java +++ b/src/main/java/org/olat/basesecurity/BaseSecurityManager.java @@ -359,7 +359,6 @@ public class BaseSecurityManager implements BaseSecurity, UserDataDeletable { IdentityImpl iimpl = new IdentityImpl(); iimpl.setUser(user); iimpl.setName(username); - iimpl.setLastLogin(new Date()); iimpl.setExternalId(externalId); iimpl.setStatus(Identity.STATUS_ACTIV); ((UserImpl)user).setIdentity(iimpl); diff --git a/src/main/java/org/olat/core/dispatcher/DispatcherModule.java b/src/main/java/org/olat/core/dispatcher/DispatcherModule.java index e5a9f3530db623c3a822c2590a81541cd01dd11e..4a7b19393dcf01eded1e4702c1bd57c703af705d 100644 --- a/src/main/java/org/olat/core/dispatcher/DispatcherModule.java +++ b/src/main/java/org/olat/core/dispatcher/DispatcherModule.java @@ -136,10 +136,6 @@ public class DispatcherModule { public static final void redirectToDefaultDispatcher(HttpServletResponse response) { redirectTo(response, WebappHelper.getServletContextPath() + PATH_DEFAULT); } - - public static final void redirectToMobile(HttpServletResponse response) { - redirectTo(response, WebappHelper.getServletContextPath() + WebappHelper.getMobileContext()); - } /** * Generic redirect method. diff --git a/src/main/java/org/olat/ldap/ui/LDAPAuthenticationController.java b/src/main/java/org/olat/ldap/ui/LDAPAuthenticationController.java index 3611692916e3bc9aa811eabfc3827f729a14d71b..2217ebe4ea58af7659c41779ea4a277185b330e8 100644 --- a/src/main/java/org/olat/ldap/ui/LDAPAuthenticationController.java +++ b/src/main/java/org/olat/ldap/ui/LDAPAuthenticationController.java @@ -227,7 +227,7 @@ public class LDAPAuthenticationController extends AuthenticationController imple // accept disclaimer first removeAsListenerAndDispose(disclaimerCtr); - disclaimerCtr = new DisclaimerController(ureq, getWindowControl()); + disclaimerCtr = new DisclaimerController(ureq, getWindowControl(), authenticatedIdentity, false); listenTo(disclaimerCtr); removeAsListenerAndDispose(cmc); diff --git a/src/main/java/org/olat/login/OLATAuthenticationController.java b/src/main/java/org/olat/login/OLATAuthenticationController.java index 8279840daa8fd83816e8adcc16db3d2d19cdc27a..240b85a7bc068863f3850d782554668b262dc031 100644 --- a/src/main/java/org/olat/login/OLATAuthenticationController.java +++ b/src/main/java/org/olat/login/OLATAuthenticationController.java @@ -175,9 +175,6 @@ public class OLATAuthenticationController extends AuthenticationController imple cmc.activate(); } - /** - * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest, org.olat.core.gui.control.Controller, org.olat.core.gui.control.Event) - */ @Override public void event(UserRequest ureq, Controller source, Event event) { if (source == loginForm && event == Event.DONE_EVENT) { @@ -218,7 +215,7 @@ public class OLATAuthenticationController extends AuthenticationController imple // accept disclaimer first removeAsListenerAndDispose(disclaimerCtr); - disclaimerCtr = new DisclaimerController(ureq, getWindowControl()); + disclaimerCtr = new DisclaimerController(ureq, getWindowControl(), authenticatedIdentity, false); listenTo(disclaimerCtr); removeAsListenerAndDispose(cmc); diff --git a/src/main/java/org/olat/login/oauth/ui/OAuthDisclaimerController.java b/src/main/java/org/olat/login/oauth/ui/OAuthDisclaimerController.java index 564624601032c75adb5bff61c5d2c2474c340ac6..835ade37a290bf1c0d15620a4fc748d40b46a00e 100644 --- a/src/main/java/org/olat/login/oauth/ui/OAuthDisclaimerController.java +++ b/src/main/java/org/olat/login/oauth/ui/OAuthDisclaimerController.java @@ -80,7 +80,7 @@ public class OAuthDisclaimerController extends FormBasicController implements Ac @Override public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) { - disclaimerController = new DisclaimerController(ureq, getWindowControl()); + disclaimerController = new DisclaimerController(ureq, getWindowControl(), null, false); listenTo(disclaimerController); cmc = new CloseableModalController(getWindowControl(), translate("close"), disclaimerController.getInitialComponent(), diff --git a/src/main/java/org/olat/login/oauth/ui/OAuthRegistrationController.java b/src/main/java/org/olat/login/oauth/ui/OAuthRegistrationController.java index 0df609b858e91339f512a6e22b36889f29a4cd12..7ec37f240c8c17758ad9a9975ee9d3f352021e4e 100644 --- a/src/main/java/org/olat/login/oauth/ui/OAuthRegistrationController.java +++ b/src/main/java/org/olat/login/oauth/ui/OAuthRegistrationController.java @@ -228,7 +228,7 @@ public class OAuthRegistrationController extends FormBasicController { //open disclaimer removeAsListenerAndDispose(disclaimerController); - disclaimerController = new DisclaimerController(ureq, getWindowControl()); + disclaimerController = new DisclaimerController(ureq, getWindowControl(), authenticatedIdentity, false); listenTo(disclaimerController); cmc = new CloseableModalController(getWindowControl(), translate("close"), disclaimerController.getInitialComponent(), diff --git a/src/main/java/org/olat/registration/DisclaimerController.java b/src/main/java/org/olat/registration/DisclaimerController.java index 5b474cfdc30ebddda8800e5d51ecaf87255b423f..826425fbb2d9640302f455ba87a4bd9dfd6b26e3 100644 --- a/src/main/java/org/olat/registration/DisclaimerController.java +++ b/src/main/java/org/olat/registration/DisclaimerController.java @@ -28,6 +28,7 @@ package org.olat.registration; import java.io.File; import java.util.Locale; +import org.olat.admin.user.delete.service.UserDeletionManager; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.Component; import org.olat.core.gui.components.link.Link; @@ -37,11 +38,18 @@ import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.Event; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.controller.BasicController; +import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController; +import org.olat.core.id.Identity; +import org.olat.core.id.UserConstants; import org.olat.core.util.WebappHelper; +import org.olat.core.util.mail.ContactList; +import org.olat.core.util.mail.ContactMessage; import org.olat.core.util.vfs.LocalFolderImpl; import org.olat.core.util.vfs.VFSContainer; import org.olat.core.util.vfs.VFSLeaf; import org.olat.core.util.vfs.VFSMediaResource; +import org.olat.modules.co.ContactFormController; +import org.olat.user.UserModule; import org.springframework.beans.factory.annotation.Autowired; /** @@ -69,31 +77,52 @@ public class DisclaimerController extends BasicController { private static final String SR_ERROR_DISCLAIMER_CHECKBOX = "sr.error.disclaimer.checkbox"; private static final String SR_ERROR_DISCLAIMER_CHECKBOXES = "sr.error.disclaimer.checkboxes"; - private VelocityContainer main; - private DisclaimerFormController disclaimerFormController; private Link downloadLink; private VFSLeaf downloadFile; + private VelocityContainer main; + + private CloseableModalController cmc; + private ContactFormController contactCtrl; + private DisclaimerFormController disclaimerFormController; + private RequestAccountDeletionController requestAccountDeletetionCtrl; + private RequestAccountDataDeletetionController requestAccountDataDeletetionCtrl; + + private Identity identity; + @Autowired + private UserModule userModule; @Autowired private RegistrationModule registrationModule; - + @Autowired + private UserDeletionManager userDeletionManager; + /** - * Display a disclaimer which can be accepted or denied. + * Display the disclaimer in a read only view to the current user. + * * @param ureq * @param wControl */ public DisclaimerController(UserRequest ureq, WindowControl wControl) { - this(ureq, wControl, false); + this(ureq, wControl, ureq.getIdentity(), true); + + if(userModule.isAllowRequestToDeleteAccount() && ureq.getIdentity() != null) { + requestAccountDeletetionCtrl = new RequestAccountDeletionController(ureq, getWindowControl()); + listenTo(requestAccountDeletetionCtrl); + main.put("radform", requestAccountDeletetionCtrl.getInitialComponent()); + } } /** * Display a disclaimer which can be accepted or denied or in a read only manner - * @param ureq - * @param wControl + * @param ureq The user request + * @param wControl The window control + * @param identity The identity which need to accept the disclaimer (or null if it doesn't exist now) * @param readOnly true: show only read only; false: allow user to accept */ - public DisclaimerController(UserRequest ureq, WindowControl wControl, boolean readOnly) { + public DisclaimerController(UserRequest ureq, WindowControl wControl, Identity identity, boolean readOnly) { super(ureq, wControl); + + this.identity = identity; disclaimerFormController = new DisclaimerFormController(ureq, wControl, readOnly); listenTo(disclaimerFormController); @@ -122,6 +151,7 @@ public class DisclaimerController extends BasicController { } } } + putInitialPanel(main); } @@ -138,30 +168,64 @@ public class DisclaimerController extends BasicController { protected void event(UserRequest ureq, Controller source, Event event) { if (source == disclaimerFormController) { if (event == Event.CANCELLED_EVENT) { - fireEvent(ureq, Event.CANCELLED_EVENT); + doCancel(ureq); } else if (event == Event.DONE_EVENT) { - // Verify that, if the additional checkbox is configured to be visible, it is checked as well - boolean accepted = (disclaimerFormController.acceptCheckbox != null) ? (disclaimerFormController.acceptCheckbox.isSelected(0)) : false; - // configure additional checkbox, see class comments in DisclaimerFormController - if (accepted && registrationModule.isDisclaimerAdditionalCheckbox()) { - accepted = (disclaimerFormController.additionalCheckbox != null) ? (disclaimerFormController.additionalCheckbox.isSelected(0)) : false; - if (accepted && registrationModule.isDisclaimerAdditionalCheckbox2()) { - accepted = (disclaimerFormController.additionalCheckbox2 != null) ? (disclaimerFormController.additionalCheckbox2.isSelected(0)) : false; - } - } - if (accepted) { - fireEvent(ureq, Event.DONE_EVENT); - } else if (registrationModule.isDisclaimerAdditionalCheckbox()) { - // error handling case multiple checkboxes enabled - showError(SR_ERROR_DISCLAIMER_CHECKBOXES); - } else { - // error handling case single checkboxe enabled - showError(SR_ERROR_DISCLAIMER_CHECKBOX); - } + acceptDisclaimer(ureq); + } + } else if(requestAccountDeletetionCtrl == source) { + if (event == Event.DONE_EVENT) { + fireEvent(ureq, Event.CANCELLED_EVENT); + } + } else if(requestAccountDataDeletetionCtrl == source) { + if(event == Event.CANCELLED_EVENT) { + fireEvent(ureq, Event.CANCELLED_EVENT); + } + cmc.deactivate(); + cleanUp(); + if(event == Event.DONE_EVENT) { + doDeleteData(ureq); } + } else if(contactCtrl == source) { + cmc.deactivate(); + cleanUp(); + fireEvent(ureq, Event.CANCELLED_EVENT); + if(event == Event.DONE_EVENT) { + showInfo("request.delete.account.sent"); + } + } else if(cmc == source) { + cleanUp(); + } + } + + private void cleanUp() { + removeAsListenerAndDispose(requestAccountDataDeletetionCtrl); + removeAsListenerAndDispose(contactCtrl); + removeAsListenerAndDispose(cmc); + requestAccountDataDeletetionCtrl = null; + contactCtrl = null; + cmc = null; + } + + private void acceptDisclaimer(UserRequest ureq) { + // Verify that, if the additional checkbox is configured to be visible, it is checked as well + boolean accepted = (disclaimerFormController.acceptCheckbox != null) ? (disclaimerFormController.acceptCheckbox.isSelected(0)) : false; + // configure additional checkbox, see class comments in DisclaimerFormController + if (accepted && registrationModule.isDisclaimerAdditionalCheckbox()) { + accepted = (disclaimerFormController.additionalCheckbox != null) ? (disclaimerFormController.additionalCheckbox.isSelected(0)) : false; + if (accepted && registrationModule.isDisclaimerAdditionalCheckbox2()) { + accepted = (disclaimerFormController.additionalCheckbox2 != null) ? (disclaimerFormController.additionalCheckbox2.isSelected(0)) : false; + } + } + if (accepted) { + fireEvent(ureq, Event.DONE_EVENT); + } else if (registrationModule.isDisclaimerAdditionalCheckbox()) { + // error handling case multiple checkboxes enabled + showError(SR_ERROR_DISCLAIMER_CHECKBOXES); + } else { + // error handling case single checkboxe enabled + showError(SR_ERROR_DISCLAIMER_CHECKBOX); } } - /** * Change the locale of this controller. @@ -172,6 +236,57 @@ public class DisclaimerController extends BasicController { main.put("dclform", this.disclaimerFormController.getInitialComponent()); } + private void doDeleteData(UserRequest ureq) { + if(identity.getLastLogin() == null) { + userDeletionManager.deleteIdentity(identity, identity); + fireEvent(ureq, Event.CANCELLED_EVENT); + } else { + doOpenContactForm(ureq); + } + } + + private void doOpenContactForm(UserRequest ureq) { + if(contactCtrl != null) return; + + String[] args = new String[] { + identity.getKey().toString(), // 0 + identity.getName(), // 1 + identity.getUser().getProperty(UserConstants.FIRSTNAME, getLocale()), // 2 + identity.getUser().getProperty(UserConstants.LASTNAME, getLocale()) // 3 + }; + ContactMessage contactMessage = new ContactMessage(identity); + contactMessage.setSubject(translate("request.delete.account.subject", args)); + contactMessage.setBodyText(translate("request.delete.account.body", args)); + + String mailAddress = userModule.getMailToRequestAccountDeletion(); + ContactList contact = new ContactList(mailAddress); + contact.add(mailAddress); + contactMessage.addEmailTo(contact); + + contactCtrl = new ContactFormController(ureq, getWindowControl(), true, false, false, contactMessage); + listenTo(contactCtrl); + + String title = translate("request.delete.account"); + cmc = new CloseableModalController(getWindowControl(), "c", contactCtrl.getInitialComponent(), true, title); + listenTo(cmc); + cmc.activate(); + } + + private void doCancel(UserRequest ureq) { + if(identity == null || !userModule.isAllowRequestToDeleteAccountDisclaimer()) { + fireEvent(ureq, Event.CANCELLED_EVENT); + return; + } + + requestAccountDataDeletetionCtrl = new RequestAccountDataDeletetionController(ureq, getWindowControl()); + listenTo(requestAccountDataDeletetionCtrl); + + String title = translate("request.data.deletion.title"); + cmc = new CloseableModalController(getWindowControl(), "c", requestAccountDataDeletetionCtrl.getInitialComponent(), true, title); + listenTo(cmc); + cmc.activate(); + } + @Override protected void doDispose() { // diff --git a/src/main/java/org/olat/registration/RegistrationController.java b/src/main/java/org/olat/registration/RegistrationController.java index bc4d5fd1f37c9495a5cb340f323812e93922f213..11b0e7b1661fe5fd825b8120cd9b47f6fdccb68a 100644 --- a/src/main/java/org/olat/registration/RegistrationController.java +++ b/src/main/java/org/olat/registration/RegistrationController.java @@ -308,7 +308,7 @@ public class RegistrationController extends BasicController implements Activatea myContent.contextPut("text", translate("step4.reg.text")); removeAsListenerAndDispose(disclaimerController); - disclaimerController = new DisclaimerController(ureq, getWindowControl()); + disclaimerController = new DisclaimerController(ureq, getWindowControl(), null, false); listenTo(disclaimerController); regarea.setContent(disclaimerController.getInitialComponent()); diff --git a/src/main/java/org/olat/registration/RegistrationManager.java b/src/main/java/org/olat/registration/RegistrationManager.java index e3960797af69c4a75f19b56ce0b4da1cc449f0cc..e3ebd4120e34e3b9be4fce419babbb9948c89c0c 100644 --- a/src/main/java/org/olat/registration/RegistrationManager.java +++ b/src/main/java/org/olat/registration/RegistrationManager.java @@ -538,6 +538,13 @@ public class RegistrationManager implements UserDataDeletable, UserDataExportabl Property disclaimerProperty = propertyManager.createUserPropertyInstance(identity, "user", "dislaimer_accepted", null, 1l, null, null); propertyManager.saveProperty(disclaimerProperty); } + + public Date getDisclaimerConfirmationDate(Identity identity) { + if(identity == null) return null; + + List<Property> disclaimerProperties = propertyManager.listProperties(identity, null, null, "user", "dislaimer_accepted"); + return disclaimerProperties.isEmpty() ? null : disclaimerProperties.get(0).getLastModified(); + } /** * Remove all disclaimer confirmations. This means that every user on the diff --git a/src/main/java/org/olat/registration/RequestAccountDataDeletetionController.java b/src/main/java/org/olat/registration/RequestAccountDataDeletetionController.java new file mode 100644 index 0000000000000000000000000000000000000000..7ed5dbb6926d16cc0d7583d3de0b55cacfd55062 --- /dev/null +++ b/src/main/java/org/olat/registration/RequestAccountDataDeletetionController.java @@ -0,0 +1,84 @@ +/** + * <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.registration; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.form.flexible.FormItemContainer; +import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement; +import org.olat.core.gui.components.form.flexible.impl.FormBasicController; +import org.olat.core.gui.components.form.flexible.impl.elements.FormCancel; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.Event; +import org.olat.core.gui.control.WindowControl; + +/** + * + * Initial date: 4 févr. 2019<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class RequestAccountDataDeletetionController extends FormBasicController { + + private MultipleSelectionElement confirmEl; + + public RequestAccountDataDeletetionController(UserRequest ureq, WindowControl wControl) { + super(ureq, wControl, "request_delete_data"); + initForm(ureq); + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + String[] keys = new String[] { "on" }; + String[] values = new String[] { translate("request.data.deletion.confirm.text") }; + confirmEl = uifactory.addCheckboxesHorizontal("request.data.deletion.confirm", formLayout, keys, values); + + FormCancel cancel = uifactory.addFormCancelButton("no", formLayout, ureq, getWindowControl()); + cancel.setI18nKey("no"); + uifactory.addFormSubmitButton("yes", formLayout); + } + + @Override + protected void doDispose() { + // + } + + @Override + protected boolean validateFormLogic(UserRequest ureq) { + boolean allOk = super.validateFormLogic(ureq); + + confirmEl.clearError(); + if(!confirmEl.isAtLeastSelected(1)) { + confirmEl.setErrorKey("request.data.deletion.confirm.error", null); + allOk &= false; + } + + return allOk; + } + + @Override + protected void formOK(UserRequest ureq) { + fireEvent(ureq, Event.DONE_EVENT); + } + + @Override + protected void formCancelled(UserRequest ureq) { + fireEvent(ureq, Event.CANCELLED_EVENT); + } +} diff --git a/src/main/java/org/olat/registration/RequestAccountDeletionController.java b/src/main/java/org/olat/registration/RequestAccountDeletionController.java new file mode 100644 index 0000000000000000000000000000000000000000..da3dbc0a82df5a5d8edd508b70c04d7cf360e027 --- /dev/null +++ b/src/main/java/org/olat/registration/RequestAccountDeletionController.java @@ -0,0 +1,157 @@ +/** + * <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.registration; + +import java.util.Date; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.form.flexible.FormItem; +import org.olat.core.gui.components.form.flexible.FormItemContainer; +import org.olat.core.gui.components.form.flexible.elements.FormLink; +import org.olat.core.gui.components.form.flexible.impl.FormBasicController; +import org.olat.core.gui.components.form.flexible.impl.FormEvent; +import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer; +import org.olat.core.gui.components.link.Link; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.Event; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController; +import org.olat.core.id.Identity; +import org.olat.core.id.UserConstants; +import org.olat.core.util.Formatter; +import org.olat.core.util.mail.ContactList; +import org.olat.core.util.mail.ContactMessage; +import org.olat.modules.co.ContactFormController; +import org.olat.user.UserModule; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * The panel to request per E-mail the deletion of it's account. + * + * + * Initial date: 4 févr. 2019<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class RequestAccountDeletionController extends FormBasicController { + + private FormLink requestButton; + + private CloseableModalController cmc; + private ContactFormController contactCtrl; + + @Autowired + private UserModule userModule; + @Autowired + private RegistrationManager registrationManager; + + public RequestAccountDeletionController(UserRequest ureq, WindowControl wControl) { + super(ureq, wControl, "request_delete"); + initForm(ureq); + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + if(formLayout instanceof FormLayoutContainer) { + FormLayoutContainer layoutCont = (FormLayoutContainer)formLayout; + Date confirmationDate = registrationManager.getDisclaimerConfirmationDate(getIdentity()); + if(confirmationDate != null) { + String date = Formatter.getInstance(getLocale()).formatDate(confirmationDate); + String time = Formatter.getInstance(getLocale()).formatTimeShort(confirmationDate); + layoutCont.contextPut("title", translate("request.delete.account.title.date", new String[] { date, time })); + } + layoutCont.contextPut("text", translate("request.delete.account.text")); + } + + requestButton = uifactory.addFormLink("request.delete.account", formLayout, Link.BUTTON); + } + + @Override + protected void doDispose() { + // + } + + @Override + protected void event(UserRequest ureq, Controller source, Event event) { + if(contactCtrl == source) { + cmc.deactivate(); + cleanUp(); + if(event == Event.DONE_EVENT) { + fireEvent(ureq, Event.DONE_EVENT); + showInfo("request.delete.account.sent"); + } + } else if(cmc == source) { + cleanUp(); + } + super.event(ureq, source, event); + } + + private void cleanUp() { + removeAsListenerAndDispose(contactCtrl); + removeAsListenerAndDispose(cmc); + contactCtrl = null; + cmc = null; + } + + @Override + protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { + if(requestButton == source) { + doRequestDeletion(ureq); + } + super.formInnerEvent(ureq, source, event); + } + + @Override + protected void formOK(UserRequest ureq) { + // + } + + private void doRequestDeletion(UserRequest ureq) { + doOpenContactForm(ureq); + } + + private void doOpenContactForm(UserRequest ureq) { + if(contactCtrl != null) return; + + Identity identity = getIdentity(); + String[] args = new String[] { + identity.getKey().toString(), // 0 + identity.getName(), // 1 + identity.getUser().getProperty(UserConstants.FIRSTNAME, getLocale()), // 2 + identity.getUser().getProperty(UserConstants.LASTNAME, getLocale()) // 3 + }; + ContactMessage contactMessage = new ContactMessage(identity); + contactMessage.setSubject(translate("request.delete.account.subject", args)); + contactMessage.setBodyText(translate("request.delete.account.body", args)); + + String mailAddress = userModule.getMailToRequestAccountDeletion(); + ContactList contact = new ContactList(mailAddress); + contact.add(mailAddress); + contactMessage.addEmailTo(contact); + + contactCtrl = new ContactFormController(ureq, getWindowControl(), true, false, false, contactMessage); + listenTo(contactCtrl); + + String title = translate("request.delete.account"); + cmc = new CloseableModalController(getWindowControl(), "c", contactCtrl.getInitialComponent(), true, title); + listenTo(cmc); + cmc.activate(); + } +} diff --git a/src/main/java/org/olat/registration/_content/disclaimer.html b/src/main/java/org/olat/registration/_content/disclaimer.html index dc5e47dd516361942563a2dbc330cdfb9475a884..5202edaf2864aef415b89313bfa7c037023a2c79 100644 --- a/src/main/java/org/olat/registration/_content/disclaimer.html +++ b/src/main/java/org/olat/registration/_content/disclaimer.html @@ -11,4 +11,7 @@ <p>$r.render("disclaimer.additionallinktext")</p> #end $r.render("dclform") + #if($r.available("radform")) + $r.render("radform") + #end </fieldset> diff --git a/src/main/java/org/olat/registration/_content/request_delete.html b/src/main/java/org/olat/registration/_content/request_delete.html new file mode 100644 index 0000000000000000000000000000000000000000..d8384b45662f31ff0cc76843baab9b198ce53676 --- /dev/null +++ b/src/main/java/org/olat/registration/_content/request_delete.html @@ -0,0 +1,9 @@ +<div class="o_info"> + #if($r.isNotEmpty($title)) + <h5>$title</h5> + #end + <p>$text</p> + <div class="o_button_group"> + $r.render("request.delete.account") + </div> +</div> \ No newline at end of file diff --git a/src/main/java/org/olat/registration/_content/request_delete_data.html b/src/main/java/org/olat/registration/_content/request_delete_data.html new file mode 100644 index 0000000000000000000000000000000000000000..3e666aadaac7432fef97e023f374983ee659c754 --- /dev/null +++ b/src/main/java/org/olat/registration/_content/request_delete_data.html @@ -0,0 +1,11 @@ +<div class="o_info"> + $r.translate("request.data.deletion.text") + $r.render("request.data.deletion.confirm") + #if($f.hasError("request.data.deletion.confirm")) + <div class="">$r.render("request.data.deletion.confirm_ERROR")</div> + #end +</div> +<div class="o_button_group"> + $r.render("no") + $r.render("yes") +</div> \ No newline at end of file diff --git a/src/main/java/org/olat/registration/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/registration/_i18n/LocalStrings_de.properties index ad014c705e48d658bdd419a50efe7c731e6b7538..e68e642b76d06769d8549f8260c1fdf21deb3283 100644 --- a/src/main/java/org/olat/registration/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/registration/_i18n/LocalStrings_de.properties @@ -110,6 +110,17 @@ registration.pending.status.pending.props=H\u00E4ngig, wenn eines der folgenden regkey.missing=Der Registrierungsschl\u00FCssel fehlt. Fordern Sie bitte einen neuen an. regkey.missingentry=Dieser Registrierungsschl\u00FCssel existiert nicht. Bitte fordern Sie einen neuen an. remote.login.title=Loginformular in externe Webseite/CMS einbinden +request.data.deletion.title=Daten l\u00F6schen +request.data.deletion.text=Wollen Sie dass ihre Daten <strong>komplett</strong> und <strong>definitve</strong> von dem OpenOLAT System? +request.data.deletion.confirm=Best\u00E4tigung +request.data.deletion.confirm.error=Sie m\u00FCssen best\u00E4gigen dass Sie die Konzequence verstehen. +request.data.deletion.confirm.text=Ich verstehe dass alle meine Daten werden definitive gel\u00F6scht und k\u00F6nnen nicht mehr zur\u00FCcksetzt werden. +request.delete.account=Konto l\u00F6schen beantragen +request.delete.account.subject=Konto "{0}" l\u00F6schen beantragen +request.delete.account.body=Ich m\u00F6chte meinem Benutzerkonto l\u00F6schen.<br>Konto ID: {0}<br>Benutzername: {1}<br>Name: {2} {3}<br><br>Mit freundlichen Gr\u00FCsse +request.delete.account.title.date=Die Zustimmung erflogte am {0} um {1} +request.delete.account.text=Falls sie den Nutzungsbedingungen nicht mehr zustimmen k\u00F6nnen Sie die L\u00F6schung Ihres Benutzerkonto beantragen. +request.delete.account.sent=Die Anfrage wurde erfolgreich abgeschickt. select.language=Sprache select.language.description=W\u00E4hlen Sie die Sprache f\u00FCr die OpenOLAT Registrierung und Ihr Benutzerkonto. Sie k\u00F6nnen die Sprache sp\u00E4ter in Ihrem Benutzerprofil jederzeit anpassen. Anschliessend werden Sie durch den Registrationprozess gef\u00FChrt. sr.error.disclaimer.checkbox=Sie m\u00FCssen durch Anklicken des K\u00E4stchens best\u00E4tigen, dass Sie die Nutzungsbedingungen gelesen und verstanden haben und diese akzeptieren. diff --git a/src/main/java/org/olat/registration/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/registration/_i18n/LocalStrings_en.properties index 00ab19974a19af697d60c12355704cfd44dd4623..473b8a0ff7b4f647ef40e7ba42c6a9dff55fa7e0 100644 --- a/src/main/java/org/olat/registration/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/registration/_i18n/LocalStrings_en.properties @@ -109,6 +109,17 @@ registration.pending.status.pending=Pending registration.pending.status.pending.props=Pending if one of the following user properties matches regkey.missing=Registration key missing. Please ask for a new one. regkey.missingentry=This registration key does not exist. Please ask for another one. +request.data.deletion.title=Delete data +request.data.deletion.text=Do you want that your data be <strong>completely</strong> and <strong>definitively</strong> deleted? +request.data.deletion.confirm=Confirmation +request.data.deletion.confirm.error=You must confirm that you understand the consequences. +request.data.deletion.confirm.text=I understand that my data will be definitively deleted and that they cannot be restored. +request.delete.account=Ask to delete your account +request.delete.account.subject=Ask to delete account "{0}" +request.delete.account.body=I want to delete my user account.<br>Account ID: {0}<br>Username: {1}<br>Name: {2} {3}<br><br>Best regards +request.delete.account.title.date=The consent came at {0} {1} +request.delete.account.text=If you no longer agree to the terms of use, you can request the deletion of your user account. +request.delete.account.sent=The request was sent successfully. remote.login.title=Embed login form into external website/CMS select.language=Language select.language.description=Please select a language for your OpenOLAT registration and user account. Later on you can adapt your choice in your user profile at any time. You will then be guided through the registration process. diff --git a/src/main/java/org/olat/shibboleth/ShibDisclaimerController.java b/src/main/java/org/olat/shibboleth/ShibDisclaimerController.java index fe451d2bb4249fcc9a5ff95a4d94c191f91d9ee9..f301086a265a6fbbbfda7e2e73f977726f21ca46 100644 --- a/src/main/java/org/olat/shibboleth/ShibDisclaimerController.java +++ b/src/main/java/org/olat/shibboleth/ShibDisclaimerController.java @@ -69,7 +69,7 @@ public class ShibDisclaimerController extends FormBasicController implements Act @Override public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) { - disclaimerController = new DisclaimerController(ureq, getWindowControl()); + disclaimerController = new DisclaimerController(ureq, getWindowControl(), null, false); listenTo(disclaimerController); cmc = new CloseableModalController(getWindowControl(), translate("close"), disclaimerController.getInitialComponent(), diff --git a/src/main/java/org/olat/shibboleth/ShibbolethRegistrationController.java b/src/main/java/org/olat/shibboleth/ShibbolethRegistrationController.java index 40ad6666a52c8a4b994061ac59da18f194022ac6..cee7eed57466bea393415c1874e7eb9b786e8585 100644 --- a/src/main/java/org/olat/shibboleth/ShibbolethRegistrationController.java +++ b/src/main/java/org/olat/shibboleth/ShibbolethRegistrationController.java @@ -194,7 +194,7 @@ public class ShibbolethRegistrationController extends DefaultController implemen setRegistrationForm(ureq, wControl, null); } - dclController = new DisclaimerController(ureq, getWindowControl()); + dclController = new DisclaimerController(ureq, getWindowControl(), null, false); dclController.addControllerListener(this); mainContainer.put("dclComp", dclController.getInitialComponent()); @@ -368,15 +368,10 @@ public class ShibbolethRegistrationController extends DefaultController implemen private void doLogin(Identity identity, UserRequest ureq) { int loginStatus = AuthHelper.doLogin(identity, ShibbolethDispatcher.PROVIDER_SHIB, ureq); if (loginStatus != AuthHelper.LOGIN_OK) { - //REVIEW:2010-01-11:revisited:pb: do not redirect if already MediaResource is set before - //ureq.getDispatchResult().setResultingMediaResource(resultingMediaResource); - //instead set the media resource accordingly - //pb -> provide a DispatcherAction.getDefaultDispatcherRedirectMediaresource(); - //to be used here. (and some more places like CatalogController. DispatcherModule.redirectToDefaultDispatcher(ureq.getHttpResp()); // error, redirect to login screen return; } - // successfull login + // successful login ureq.getUserSession().getIdentityEnvironment().addAttributes( shibbolethModule.getAttributeTranslator().translateAttributesMap(shibbolethAttributes.toMap())); } diff --git a/src/main/java/org/olat/user/UserModule.java b/src/main/java/org/olat/user/UserModule.java index 0e45fe6a9c5c6c8143d1197f9230ad3f7b509d4b..f9bcf4bcb1b964e9563cd41df6fc8de5688ff1e6 100644 --- a/src/main/java/org/olat/user/UserModule.java +++ b/src/main/java/org/olat/user/UserModule.java @@ -67,6 +67,9 @@ public class UserModule extends AbstractSpringModule { private static final String USER_EMAIL_MANDATORY = "userEmailMandatory"; private static final String USER_EMAIL_UNIQUE = "userEmailUnique"; + private static final String ALLOW_REQUEST_DELETE_ACCOUNT = "allow.request.delete.account"; + 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"; @Autowired @Qualifier("loginBlacklist") private ArrayList<String> loginBlacklist; @@ -76,6 +79,13 @@ public class UserModule extends AbstractSpringModule { private boolean pwdchangeallowed; @Value("${password.change.allowed.without.authentications:false}") private boolean pwdChangeWithoutAuthenticationAllowed; + + @Value("${allow.request.delete.account:false}") + private boolean allowRequestToDeleteAccount; + @Value("${allow.request.delete.account.disclaimer:false}") + private boolean allowRequestToDeleteAccountDisclaimer; + @Value("${request.delete.account.mail}") + private String mailToRequestAccountDeletion; private String adminUserName = "administrator"; @Value("${user.logoByProfile:disabled}") @@ -108,17 +118,8 @@ public class UserModule extends AbstractSpringModule { } log.info("Successfully added " + count + " entries to login blacklist."); - - String userEmailOptionalValue = getStringPropertyValue(USER_EMAIL_MANDATORY, false); - if(StringHelper.containsNonWhitespace(userEmailOptionalValue)) { - isEmailMandatory = "true".equalsIgnoreCase(userEmailOptionalValue); - } - - String userEmailUniquenessOptionalValue = getStringPropertyValue(USER_EMAIL_UNIQUE, false); - if(StringHelper.containsNonWhitespace(userEmailUniquenessOptionalValue)) { - isEmailUnique = "true".equalsIgnoreCase(userEmailUniquenessOptionalValue); - } - + updateProperties(); + // Check if user manager is configured properly and has user property // handlers for the mandatory user properties used in OLAT checkMandatoryUserProperty(UserConstants.FIRSTNAME); @@ -142,7 +143,31 @@ public class UserModule extends AbstractSpringModule { @Override protected void initFromChangedProperties() { - // + updateProperties(); + } + + private void updateProperties() { + String userEmailOptionalValue = getStringPropertyValue(USER_EMAIL_MANDATORY, false); + if(StringHelper.containsNonWhitespace(userEmailOptionalValue)) { + isEmailMandatory = "true".equalsIgnoreCase(userEmailOptionalValue); + } + String userEmailUniquenessOptionalValue = getStringPropertyValue(USER_EMAIL_UNIQUE, false); + if(StringHelper.containsNonWhitespace(userEmailUniquenessOptionalValue)) { + isEmailUnique = "true".equalsIgnoreCase(userEmailUniquenessOptionalValue); + } + + String allowRequestDeleteObj = getStringPropertyValue(ALLOW_REQUEST_DELETE_ACCOUNT, false); + if(StringHelper.containsNonWhitespace(allowRequestDeleteObj)) { + allowRequestToDeleteAccount = "true".equalsIgnoreCase(allowRequestDeleteObj); + } + String allowRequestDeleteDisclaimerObj = getStringPropertyValue(ALLOW_REQUEST_DELETE_ACCOUNT_DISCLAIMER, false); + if(StringHelper.containsNonWhitespace(allowRequestDeleteDisclaimerObj)) { + allowRequestToDeleteAccountDisclaimer = "true".equalsIgnoreCase(allowRequestDeleteDisclaimerObj); + } + String mailRequestDeleteObj = getStringPropertyValue(MAIL_REQUEST_DELETE_ACCOUNT, false); + if(StringHelper.containsNonWhitespace(mailRequestDeleteObj)) { + mailToRequestAccountDeletion = mailRequestDeleteObj; + } } private void checkMandatoryUserProperty(String userPropertyIdentifyer) { @@ -262,4 +287,32 @@ public class UserModule extends AbstractSpringModule { setStringProperty(USER_EMAIL_UNIQUE, isEmailUniqueStr, true); } + public boolean isAllowRequestToDeleteAccount() { + return allowRequestToDeleteAccount; + } + + public void setAllowRequestToDeleteAccount(boolean allowRequestToDeleteAccount) { + this.allowRequestToDeleteAccount = allowRequestToDeleteAccount; + String allowed = allowRequestToDeleteAccount ? "true" : "false"; + setStringProperty(ALLOW_REQUEST_DELETE_ACCOUNT, allowed, true); + } + + public boolean isAllowRequestToDeleteAccountDisclaimer() { + return allowRequestToDeleteAccountDisclaimer; + } + + public void setAllowRequestToDeleteAccountDisclaimer(boolean allowRequestToDeleteAccountDisclaimer) { + this.allowRequestToDeleteAccountDisclaimer = allowRequestToDeleteAccountDisclaimer; + String allowed = allowRequestToDeleteAccountDisclaimer ? "true" : "false"; + setStringProperty(ALLOW_REQUEST_DELETE_ACCOUNT_DISCLAIMER, allowed, true); + } + + public String getMailToRequestAccountDeletion() { + return mailToRequestAccountDeletion; + } + + public void setMailToRequestAccountDeletion(String mailToRequestAccountDeletion) { + this.mailToRequestAccountDeletion = mailToRequestAccountDeletion; + setStringProperty(MAIL_REQUEST_DELETE_ACCOUNT, mailToRequestAccountDeletion, true); + } } \ No newline at end of file diff --git a/src/main/java/org/olat/user/UserSettingsController.java b/src/main/java/org/olat/user/UserSettingsController.java index 51f49e17a27dc4693e3a7a34d6b5b046549b0a6b..0b33b8ec76e8ebb4ef1387ae5a5a5f2b1f83b74e 100644 --- a/src/main/java/org/olat/user/UserSettingsController.java +++ b/src/main/java/org/olat/user/UserSettingsController.java @@ -202,7 +202,7 @@ public class UserSettingsController extends BasicController implements Activatea if(disclaimerCtrl == null) { OLATResourceable ores = OresHelper.createOLATResourceableInstance("Disclaimer", 0l); WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(ores, null, getWindowControl()); - disclaimerCtrl = new DisclaimerController(ureq, bwControl, true); + disclaimerCtrl = new DisclaimerController(ureq, bwControl); listenTo(disclaimerCtrl); } mainVC.put("segmentCmp", disclaimerCtrl.getInitialComponent()); diff --git a/src/main/java/org/olat/user/_spring/userContext.xml b/src/main/java/org/olat/user/_spring/userContext.xml index f7a3b5bcf73fbd9bf03a5d9304ae2f9f5a25b9f8..ea993cc035b2a192bab2d8d065f223f35fd4047d 100644 --- a/src/main/java/org/olat/user/_spring/userContext.xml +++ b/src/main/java/org/olat/user/_spring/userContext.xml @@ -331,6 +331,26 @@ <property name="order" value="7411" /> </bean> + <!-- User request to delete account --> + <bean class="org.olat.core.extensions.action.GenericActionExtension" init-method="initExtensionPoints"> + <property name="order" value="9014" /> + <property name="actionController"> + <bean class="org.olat.core.gui.control.creator.AutoCreator" scope="prototype"> + <property name="className" value="org.olat.user.ui.admin.UserAccountDeletionSettingsController"/> + </bean> + </property> + <property name="navigationKey" value="requestdeleteaccount" /> + <property name="parentTreeNodeIdentifier" value="modulesParent" /> + <property name="i18nActionKey" value="admin.menu.title.request"/> + <property name="i18nDescriptionKey" value="admin.menu.title.request.alt"/> + <property name="translationPackage" value="org.olat.user.ui.admin"/> + <property name="extensionPoints"> + <list> + <value>org.olat.admin.SystemAdminMainController</value> + </list> + </property> + </bean> + <!-- Delete old user data export job --> <bean id="deleteUserDataExportTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> <property name="jobDetail" ref="deleteUserDataExportJob.${cluster.singleton.services}" /> diff --git a/src/main/java/org/olat/user/ui/admin/UserAccountDeletionSettingsController.java b/src/main/java/org/olat/user/ui/admin/UserAccountDeletionSettingsController.java new file mode 100644 index 0000000000000000000000000000000000000000..e951ea144cdf078fad3ec037fcff21782fa82540 --- /dev/null +++ b/src/main/java/org/olat/user/ui/admin/UserAccountDeletionSettingsController.java @@ -0,0 +1,124 @@ +/** + * <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.user.ui.admin; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.form.flexible.FormItem; +import org.olat.core.gui.components.form.flexible.FormItemContainer; +import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement; +import org.olat.core.gui.components.form.flexible.elements.TextElement; +import org.olat.core.gui.components.form.flexible.impl.FormBasicController; +import org.olat.core.gui.components.form.flexible.impl.FormEvent; +import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.util.StringHelper; +import org.olat.core.util.mail.MailHelper; +import org.olat.user.UserModule; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * Initial date: 4 févr. 2019<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class UserAccountDeletionSettingsController extends FormBasicController { + + private MultipleSelectionElement requestDeleteEl; + private TextElement emailEl; + + @Autowired + private UserModule userModule; + + public UserAccountDeletionSettingsController(UserRequest ureq, WindowControl wControl) { + super(ureq, wControl); + + initForm(ureq); + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + setFormTitle("allow.request.delete.account.time"); + + String[] deleteKeys = new String[] { "anytime", "disclaimer" }; + String[] deleteValues = new String[] { translate("allow.request.delete.account.anytime"), translate("allow.request.delete.account.disclaimer") }; + + requestDeleteEl = uifactory.addCheckboxesVertical("allow.request.delete.account", formLayout, deleteKeys, deleteValues, 1); + requestDeleteEl.addActionListener(FormEvent.ONCHANGE); + if(userModule.isAllowRequestToDeleteAccount()) { + requestDeleteEl.select(deleteKeys[0], true); + } + if(userModule.isAllowRequestToDeleteAccountDisclaimer()) { + requestDeleteEl.select(deleteKeys[1], true); + } + + String email = userModule.getMailToRequestAccountDeletion(); + emailEl = uifactory.addTextElement("allow.request.delete.account.mail", 256, email, formLayout); + emailEl.setVisible(requestDeleteEl.isAtLeastSelected(1)); + + FormLayoutContainer layoutCont = FormLayoutContainer.createButtonLayout("buttons", getTranslator()); + formLayout.add(layoutCont); + uifactory.addFormSubmitButton("save", layoutCont); + } + + @Override + protected boolean validateFormLogic(UserRequest ureq) { + boolean allOk = super.validateFormLogic(ureq); + + emailEl.clearError(); + requestDeleteEl.clearError(); + if(requestDeleteEl.isAtLeastSelected(1)) { + if(!StringHelper.containsNonWhitespace(emailEl.getValue())) { + emailEl.setErrorKey("form.legende.mandatory", null); + allOk &= false; + } else if(!MailHelper.isValidEmailAddress(emailEl.getValue())) { + emailEl.setErrorKey("error.mail.not.valid", null); + allOk &= false; + } + } + + return allOk; + } + + @Override + protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { + if(requestDeleteEl == source) { + emailEl.setVisible(requestDeleteEl.isAtLeastSelected(1)); + } + super.formInnerEvent(ureq, source, event); + } + + @Override + protected void formOK(UserRequest ureq) { + userModule.setAllowRequestToDeleteAccount(requestDeleteEl.isSelected(0)); + userModule.setAllowRequestToDeleteAccountDisclaimer(requestDeleteEl.isSelected(1)); + if(requestDeleteEl.isAtLeastSelected(1)) { + userModule.setMailToRequestAccountDeletion(emailEl.getValue()); + } else { + userModule.setMailToRequestAccountDeletion(""); + } + } + + @Override + protected void doDispose() { + // + } +} diff --git a/src/main/java/org/olat/user/ui/admin/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/user/ui/admin/_i18n/LocalStrings_de.properties index 79232c021377300c30e2aeee3768994003e74e7c..26480f5ee4e7e681145651387eaa5428161a9fdb 100644 --- a/src/main/java/org/olat/user/ui/admin/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/user/ui/admin/_i18n/LocalStrings_de.properties @@ -1,6 +1,14 @@ #Fri Mar 23 15:13:55 CET 2018 +admin.menu.title.request=Anfrage Konto l\u00F6schen +admin.menu.title.request.alt=Anfrage Benutzerkonto l\u00F6schen +allow.request.delete.account=Erlaubt anfragen Benutzerkonto zu l\u00F6schen +allow.request.delete.account.anytime=Jederzeit +allow.request.delete.account.disclaimer=Wenn der Benutzer den Nutzungbedingungen nicht akkzeptiert +allow.request.delete.account.mail=Email f\u00FCr Anfrage +allow.request.delete.account.time=Benutzerkonto l\u00F6schen anfragen command.next=Weiter zur n\u00E4chsten Benutzer command.previous=Zur\u00FCck zur letzten Benutzer +error.mail.not.valid=Der Email Adresse ist nicht g\u00FCltig. menu.admingroup=Administratoren menu.admingroup.alt=Administratoren verwalten menu.anonymousgroup=Anonyme Benutzer / G\u00E4ste diff --git a/src/main/java/org/olat/user/ui/admin/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/user/ui/admin/_i18n/LocalStrings_en.properties index c28c40b57bd9d9151457a823ceb3a0417dd82045..d47e409e60d552ca002edf65e523405b8338a9b5 100644 --- a/src/main/java/org/olat/user/ui/admin/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/user/ui/admin/_i18n/LocalStrings_en.properties @@ -1,4 +1,12 @@ #Fri Mar 23 15:13:55 CET 2018 +admin.menu.title.request=Request account deletion +admin.menu.title.request.alt=Request user account deletion +allow.request.delete.account=Allow request to delete user account +allow.request.delete.account.anytime=Anytime +allow.request.delete.account.disclaimer=If the user doesn't accept the disclaimers +allow.request.delete.account.mail=E-mail for requests +allow.request.delete.account.time=Request user account deletion +error.mail.not.valid=The E-mail addresse is not valid. command.next=Go to next user command.previous=Go to previous user menu.admingroup=Administrators diff --git a/src/main/resources/serviceconfig/olat.properties b/src/main/resources/serviceconfig/olat.properties index a0be8ed84e98a69e71eedf41d6f4e22806fa83d9..8e708154083b04e9872f90bfaef62e677d3e5554 100644 --- a/src/main/resources/serviceconfig/olat.properties +++ b/src/main/resources/serviceconfig/olat.properties @@ -250,6 +250,11 @@ notification.interval.default.values=never,monthly,weekly,daily,half-daily,four- #notification cron job notification.cronjob.expression=0 10 */2 * * ? +# Request to delete account +allow.request.delete.account=false +allow.request.delete.account.disclaimer=false +request.delete.account.mail= + #################################################### # Groups #################################################### diff --git a/src/test/java/org/olat/basesecurity/BaseSecurityManagerTest.java b/src/test/java/org/olat/basesecurity/BaseSecurityManagerTest.java index e4f4cab25f0e61cda9e6aa0e16cf0cebddc4fa14..a03ee79e295b8a3055b541faa933d3a8a6e7aeb5 100644 --- a/src/test/java/org/olat/basesecurity/BaseSecurityManagerTest.java +++ b/src/test/java/org/olat/basesecurity/BaseSecurityManagerTest.java @@ -270,7 +270,7 @@ public class BaseSecurityManagerTest extends OlatTestCase { @Test public void loadIdentityShortByKey() { //create a user it - String idName = "find-me-short-1-" + UUID.randomUUID().toString(); + String idName = "find-me-short-1-" + UUID.randomUUID(); Identity id = JunitTestHelper.createAndPersistIdentityAsUser(idName); dbInstance.commitAndCloseSession(); @@ -282,19 +282,19 @@ public class BaseSecurityManagerTest extends OlatTestCase { Assert.assertEquals(id.getUser().getEmail(), foundId.getEmail()); Assert.assertEquals(id.getUser().getFirstName(), foundId.getFirstName()); Assert.assertEquals(id.getUser().getLastName(), foundId.getLastName()); - Assert.assertNotNull(foundId.getLastLogin()); + Assert.assertNull(foundId.getLastLogin());// no login, no last login date Assert.assertEquals(id.getUser().getKey(), foundId.getUserKey()); Assert.assertTrue(foundId.getStatus() < Identity.STATUS_VISIBLE_LIMIT); } @Test public void testLoadIdentityByKeys() { - //create a security group with 2 identites - Identity id1 = JunitTestHelper.createAndPersistIdentityAsUser( "load-1-sec-" + UUID.randomUUID().toString()); - Identity id2 = JunitTestHelper.createAndPersistIdentityAsUser( "load-2-sec-" + UUID.randomUUID().toString()); + //create a security group with 2 identities + Identity id1 = JunitTestHelper.createAndPersistIdentityAsRndUser( "load-1-sec-"); + Identity id2 = JunitTestHelper.createAndPersistIdentityAsRndUser( "load-2-sec-"); dbInstance.commitAndCloseSession(); - List<Long> keys = new ArrayList<Long>(2); + List<Long> keys = new ArrayList<>(2); keys.add(id1.getKey()); keys.add(id2.getKey()); List<Identity> identities = securityManager.loadIdentityByKeys(keys);