/** * <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.ArrayList; import java.util.List; import org.olat.basesecurity.OrganisationService; import org.olat.basesecurity.OrganisationStatus; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.ValidationError; 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.SingleSelection; 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.gui.translator.Translator; import org.olat.core.helpers.Settings; import org.olat.core.id.Organisation; import org.olat.core.id.UserConstants; import org.olat.core.util.StringHelper; import org.olat.core.util.mail.MailHelper; import org.olat.user.UserPropertiesConfig; import org.olat.user.propertyhandlers.Generic127CharTextPropertyHandler; import org.olat.user.propertyhandlers.UserPropertyHandler; import org.springframework.beans.factory.annotation.Autowired; /** * Admin panel to configure the registration settings: should link appear on the login page... * * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com */ public class RegistrationAdminController extends FormBasicController { private SingleSelection organisationsEl; private MultipleSelectionElement registrationElement; private MultipleSelectionElement registrationLinkElement; private MultipleSelectionElement registrationLoginElement; private MultipleSelectionElement staticPropElement; private SingleSelection propertyElement; private SingleSelection pendingRegistrationStatusEl; private TextElement pendingRegistrationNotificationEl; private PropertyNameValueElements pendingProperty1Els; private PropertyNameValueElements pendingProperty2Els; private PropertyNameValueElements pendingProperty3Els; private PropertyNameValueElements pendingProperty4Els; private PropertyNameValueElements pendingProperty5Els; private TextElement propertyValueElement; private TextElement exampleElement; private TextElement domainListElement; private TextElement validUntilGuiEl; private TextElement validUntilRestEl; private FormLayoutContainer domainsContainer; private FormLayoutContainer pendingPropContainer; private FormLayoutContainer staticPropContainer; private static final String[] pendingRegistrationKeys = new String[] { RegistrationPendingStatus.active.name(), RegistrationPendingStatus.pending.name(), RegistrationPendingStatus.pendingMatchingProperties.name() }; private static final String[] enableRegistrationKeys = new String[]{ "on" }; private final String[] propertyKeys; private final String[] propertyValues; private final String[] pendingPropertyKeys; private final String[] pendingPropertyValues; @Autowired private RegistrationModule registrationModule; @Autowired private RegistrationManager registrationManager; @Autowired private OrganisationService organisationService; @Autowired private UserPropertiesConfig userPropertiesConfig; private final Translator userPropTranslator; public RegistrationAdminController(UserRequest ureq, WindowControl wControl) { super(ureq, wControl, "admin"); //decorate the translator userPropTranslator = userPropertiesConfig.getTranslator(getTranslator()); List<UserPropertyHandler> allPropertyHandlers = userPropertiesConfig.getAllUserPropertyHandlers(); List<UserPropertyHandler> propertyHandlers = new ArrayList<>(allPropertyHandlers.size()); for(UserPropertyHandler handler:allPropertyHandlers) { if(handler instanceof Generic127CharTextPropertyHandler && !UserConstants.USERNAME.equals(handler.getName())) { propertyHandlers.add(handler); } } propertyKeys = new String[propertyHandlers.size() + 1]; propertyValues = new String[propertyHandlers.size() + 1]; int count = 0; propertyKeys[0] = "-"; propertyValues[0] = ""; for(UserPropertyHandler propertyHandler:propertyHandlers) { propertyKeys[1 + count] = propertyHandler.getName(); propertyValues[1 + count++] = userPropTranslator.translate(propertyHandler.i18nFormElementLabelKey()); } pendingPropertyKeys = new String[allPropertyHandlers.size() + 1]; pendingPropertyValues = new String[allPropertyHandlers.size() + 1]; count = 0; pendingPropertyKeys[0] = "-"; pendingPropertyValues[0] = ""; for(UserPropertyHandler propertyHandler:allPropertyHandlers) { pendingPropertyKeys[1 + count] = propertyHandler.getName(); pendingPropertyValues[1 + count++] = userPropTranslator.translate(propertyHandler.i18nFormElementLabelKey()); } initForm(ureq); } @Override protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { String[] enableRegistrationValues = new String[] { translate("admin.enableRegistration.on") }; //settings FormLayoutContainer settingsContainer = FormLayoutContainer.createDefaultFormLayout("settings", getTranslator()); settingsContainer.setRootForm(mainForm); settingsContainer.setFormTitle(translate("admin.registration.title")); formLayout.add(settingsContainer); registrationElement = uifactory.addCheckboxesHorizontal("enable.self.registration", "admin.enableRegistration", settingsContainer, enableRegistrationKeys, enableRegistrationValues); registrationElement.addActionListener(FormEvent.ONCHANGE); registrationElement.select("on", registrationModule.isSelfRegistrationEnabled()); registrationLoginElement = uifactory.addCheckboxesHorizontal("enable.registration.login", "admin.enableRegistrationLogin", settingsContainer, enableRegistrationKeys, enableRegistrationValues); registrationLoginElement.addActionListener(FormEvent.ONCHANGE); registrationLoginElement.select("on", registrationModule.isSelfRegistrationLoginEnabled()); registrationLinkElement = uifactory.addCheckboxesHorizontal("enable.registration.link", "admin.enableRegistrationLink", settingsContainer, enableRegistrationKeys, enableRegistrationValues); registrationLinkElement.addActionListener(FormEvent.ONCHANGE); registrationLinkElement.select("on", registrationModule.isSelfRegistrationLinkEnabled()); initOrganisationsEl(settingsContainer); validUntilGuiEl = uifactory.addTextElement("admin.registration.valid.until.gui", 20, registrationModule.getValidUntilHoursGui().toString(), settingsContainer); validUntilGuiEl.setMandatory(true); validUntilRestEl = uifactory.addTextElement("admin.registration.valid.until.rest", 20, registrationModule.getValidUntilHoursRest().toString(), settingsContainer); validUntilRestEl.setMandatory(true); String example = generateExampleCode(); exampleElement = uifactory.addTextAreaElement("registration.link.example", "admin.registrationLinkExample", 64000, 4, 65, true, false, example, settingsContainer); // pedning status initPendingPropForm(formLayout); //domain configuration initDomainForm(formLayout); //static property initStaticPropForm(formLayout, enableRegistrationValues); //static property initRemoteLogin(formLayout); FormLayoutContainer buttonGroupLayout = FormLayoutContainer.createButtonLayout("buttons", getTranslator()); buttonGroupLayout.setRootForm(mainForm); uifactory.addFormSubmitButton("save", buttonGroupLayout); formLayout.add(buttonGroupLayout); updateUI(); } private void initDomainForm(FormItemContainer formLayout) { domainsContainer = FormLayoutContainer.createDefaultFormLayout("domains", getTranslator()); domainsContainer.setRootForm(mainForm); domainsContainer.setFormTitle(translate("admin.registration.domains.title")); formLayout.add(domainsContainer); uifactory.addStaticTextElement("admin.registration.domains.error", null, translate("admin.registration.domains.desc"), domainsContainer); String domainsList = registrationModule.getDomainListRaw(); domainListElement = uifactory.addTextAreaElement("registration.domain.list", "admin.registration.domains", 64000, 10, 65, true, false, domainsList, domainsContainer); } private void initPendingPropForm(FormItemContainer formLayout) { pendingPropContainer = FormLayoutContainer.createDefaultFormLayout("propertiespending", getTranslator()); pendingPropContainer.setRootForm(mainForm); pendingPropContainer.setFormTitle(translate("admin.registration.pending.status")); formLayout.add(pendingPropContainer); String[] pendingRegistrationValues = new String[] { translate("registration.pending.status.active"), translate("registration.pending.status.pending"), translate("registration.pending.status.pending.props") }; pendingRegistrationStatusEl = uifactory.addDropdownSingleselect("registration.pending.status", pendingPropContainer, pendingRegistrationKeys, pendingRegistrationValues); pendingRegistrationStatusEl.select(registrationModule.getRegistrationPendingStatus().name(), true); pendingRegistrationStatusEl.addActionListener(FormEvent.ONCHANGE); pendingProperty1Els = initPendingProperty(1, registrationModule.getRegistrationPendingPropertyName1(), registrationModule.getRegistrationPendingPropertyValue1(), pendingPropContainer); pendingProperty2Els = initPendingProperty(2, registrationModule.getRegistrationPendingPropertyName2(), registrationModule.getRegistrationPendingPropertyValue2(), pendingPropContainer); pendingProperty3Els = initPendingProperty(3, registrationModule.getRegistrationPendingPropertyName3(), registrationModule.getRegistrationPendingPropertyValue3(), pendingPropContainer); pendingProperty4Els = initPendingProperty(4, registrationModule.getRegistrationPendingPropertyName4(), registrationModule.getRegistrationPendingPropertyValue4(), pendingPropContainer); pendingProperty5Els = initPendingProperty(5, registrationModule.getRegistrationPendingPropertyName5(), registrationModule.getRegistrationPendingPropertyValue5(), pendingPropContainer); String email = ""; if(registrationModule.isRegistrationNotificationEmailEnabled()) { email = registrationModule.getRegistrationNotificationEmail(); } pendingRegistrationNotificationEl = uifactory.addTextElement("registration.pending.notification.mail", 2048, email, pendingPropContainer); } private PropertyNameValueElements initPendingProperty(int pos, String propName, String propValue, FormLayoutContainer formLayout) { SingleSelection pendingPropertyNameEl = uifactory.addDropdownSingleselect("registration.pending.prop.name" + pos, formLayout, pendingPropertyKeys, pendingPropertyValues); boolean found = false; for(int i=pendingPropertyKeys.length; i-->0; ) { if(pendingPropertyKeys[i].equals(propName)) { pendingPropertyNameEl.select(pendingPropertyKeys[i], true); found = true; break; } } if(!found) { pendingPropertyNameEl.select(pendingPropertyKeys[0], true); } TextElement pendingPropertyValueEl = uifactory.addTextElement("registration.pending.prop.value" + pos, 2048, propValue, formLayout); return new PropertyNameValueElements(pendingPropertyNameEl, pendingPropertyValueEl); } private void initStaticPropForm(FormItemContainer formLayout, String[] enableRegistrationValues) { staticPropContainer = FormLayoutContainer.createDefaultFormLayout("propertiesmapping", getTranslator()); staticPropContainer.setRootForm(mainForm); staticPropContainer.setFormTitle(translate("admin.registration.staticprop.title")); formLayout.add(staticPropContainer); uifactory.addStaticTextElement("admin.registration.staticprop.error", null, translate("admin.registration.staticprop.desc"), staticPropContainer); staticPropElement = uifactory.addCheckboxesHorizontal("enable.staticprop", "admin.enableStaticProp", staticPropContainer, enableRegistrationKeys, enableRegistrationValues); staticPropElement.addActionListener(FormEvent.ONCHANGE); staticPropElement.select("on", registrationModule.isStaticPropertyMappingEnabled()); propertyElement = uifactory.addDropdownSingleselect("property", "admin.registration.property", staticPropContainer, propertyKeys, propertyValues, null); String propertyName = registrationModule.getStaticPropertyMappingName(); UserPropertyHandler handler = userPropertiesConfig.getPropertyHandler(propertyName); if(handler != null) { propertyElement.select(handler.getName(), true); } propertyElement.addActionListener(FormEvent.ONCHANGE); String propertyValue = registrationModule.getStaticPropertyMappingValue(); propertyValueElement = uifactory.addTextElement("admin.registration.prop.value", "admin.registration.propertyValue", 255, propertyValue, staticPropContainer); } private void initRemoteLogin(FormItemContainer formLayout) { FormLayoutContainer remoteLoginContainerContainer = FormLayoutContainer.createDefaultFormLayout("remotelogin", getTranslator()); remoteLoginContainerContainer.setRootForm(mainForm); remoteLoginContainerContainer.setFormTitle(translate("remote.login.title")); formLayout.add(remoteLoginContainerContainer); String remoteExample = generateRemoteLoginExampleCode(); uifactory.addTextAreaElement("remotelogin.example", "admin.registrationLinkExample", 64000, 4, 65, true, false, remoteExample, remoteLoginContainerContainer); } private void initOrganisationsEl(FormLayoutContainer formLayout) { List<Organisation> organisations = organisationService.getOrganisations(OrganisationStatus.notDelete()); Organisation registrationOrg = registrationManager.getOrganisationForRegistration(); String registrationOrgKey = registrationOrg.getKey().toString(); String[] theKeys = new String[organisations.size()]; String[] theValues = new String[organisations.size()]; for(int i=organisations.size(); i-->0; ) { Organisation organisation = organisations.get(i); theKeys[i] = organisation.getKey().toString(); theValues[i] = organisation.getDisplayName(); } organisationsEl = uifactory.addDropdownSingleselect("organisations", "admin.registrationOrganisation", formLayout, theKeys, theValues); for(int i=theKeys.length; i-->0; ) { if(theKeys[i].equals(registrationOrgKey)) { organisationsEl.select(theKeys[i], true); break; } } } @Override protected void doDispose() { // } @Override protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { if(source == registrationElement) { boolean enable = registrationElement.isSelected(0); registrationModule.setSelfRegistrationEnabled(enable); updateUI(); } else if(source == registrationLinkElement) { registrationModule.setSelfRegistrationLinkEnabled(registrationLinkElement.isSelected(0)); updateUI(); } else if(source == registrationLoginElement) { registrationModule.setSelfRegistrationLoginEnabled(registrationLoginElement.isSelected(0)); updateUI(); } else if (source == staticPropElement) { registrationModule.setStaticPropertyMappingEnabled(staticPropElement.isSelected(0)); updateUI(); } else if(source == pendingRegistrationStatusEl) { updateUI(); } super.formInnerEvent(ureq, source, event); } private void updateUI() { boolean enableMain = registrationElement.isSelected(0); registrationLinkElement.setEnabled(enableMain); registrationLoginElement.setEnabled(enableMain); organisationsEl.setEnabled(enableMain); boolean example = enableMain && registrationLinkElement.isSelected(0); exampleElement.setVisible(example); boolean enableDomains = enableMain && (registrationLinkElement.isSelected(0) || registrationLoginElement.isSelected(0)); domainsContainer.setVisible(enableDomains); pendingPropContainer.setVisible(enableMain); if(enableMain) { String selectedStatus = pendingRegistrationStatusEl.getSelectedKey(); boolean useProps = RegistrationPendingStatus.pendingMatchingProperties.name().equals(selectedStatus); pendingProperty1Els.setVisible(useProps); pendingProperty2Els.setVisible(useProps); pendingProperty3Els.setVisible(useProps); pendingProperty4Els.setVisible(useProps); pendingProperty5Els.setVisible(useProps); boolean mail = RegistrationPendingStatus.pendingMatchingProperties.name().equals(selectedStatus) || RegistrationPendingStatus.pending.name().equals(selectedStatus); pendingRegistrationNotificationEl.setVisible(mail); } //static prop boolean enableProps = enableMain && (registrationLinkElement.isSelected(0) || registrationLoginElement.isSelected(0)); staticPropContainer.setVisible(enableProps); boolean enabledProp = staticPropElement.isSelected(0); propertyElement.setVisible(enableProps && enabledProp); propertyValueElement.setVisible(enableProps && enabledProp); } @Override protected boolean validateFormLogic(UserRequest ureq) { boolean allOk = super.validateFormLogic(ureq); allOk &= validateInteger(validUntilGuiEl, 1); allOk &= validateInteger(validUntilRestEl, 1); allOk &= validatePropertyNameValuePair(pendingProperty1Els); allOk &= validatePropertyNameValuePair(pendingProperty2Els); allOk &= validatePropertyNameValuePair(pendingProperty3Els); allOk &= validatePropertyNameValuePair(pendingProperty4Els); allOk &= validatePropertyNameValuePair(pendingProperty5Els); allOk &= validateEmail(pendingRegistrationNotificationEl); String whiteList = domainListElement.getValue(); domainListElement.clearError(); if(StringHelper.containsNonWhitespace(whiteList)) { List<String> normalizedList = registrationModule.getDomainList(whiteList); List<String> errors = registrationManager.validateWhiteList(normalizedList); if(!errors.isEmpty()) { StringBuilder sb = new StringBuilder(); for(String error:errors) { if(sb.length() > 0) sb.append(" ,"); sb.append(error); } domainListElement.setErrorKey("admin.registration.domains.error", new String[]{sb.toString()}); allOk &= false; } } if(staticPropElement.isSelected(0)) { if(propertyElement.isOneSelected()) { String propertyName = propertyElement.getSelectedKey(); String value = propertyValueElement.getValue(); UserPropertyHandler handler = userPropertiesConfig.getPropertyHandler(propertyName); if(handler != null) { ValidationError validationError = new ValidationError(); boolean valid = handler.isValidValue(null, value, validationError, getLocale()); if(!valid) { propertyValueElement.setErrorKey("admin.registration.propertyValue.error", null); allOk &= false; } } } } organisationsEl.clearError(); if(organisationsEl.isEnabled() && !organisationsEl.isOneSelected()) { organisationsEl.setErrorKey("form.legende.mandatory", null); allOk &= false; } return allOk; } private boolean validateEmail(TextElement el) { boolean allOk = true; el.clearError(); if(StringHelper.containsNonWhitespace(el.getValue())) { String[] emails = el.getValue().split("[,]"); for(String email:emails) { if(!MailHelper.isValidEmailAddress(email)) { el.setErrorKey("email.address.notregular", null); allOk &= false; break; } } } return allOk; } private boolean validatePropertyNameValuePair(PropertyNameValueElements nameValueEls) { boolean allOk = true; SingleSelection nameEl = nameValueEls.getPropertyNameEl(); TextElement valueEl = nameValueEls.getPropertyValueEl(); nameEl.clearError(); valueEl.clearError(); if(!nameEl.isOneSelected()) { nameEl.setErrorKey("form.legende.mandatory", null); allOk &= false; } else if(!nameEl.getSelectedKey().equals(propertyKeys[0]) && !StringHelper.containsNonWhitespace(valueEl.getValue())) { valueEl.setErrorKey("form.legende.mandatory", null); allOk &= false; } return allOk; } private boolean validateInteger(TextElement el, int min) { boolean allOk = true; el.clearError(); String val = el.getValue(); if(StringHelper.containsNonWhitespace(val)) { try { double value = Integer.parseInt(val); if(min > value) { el.setErrorKey("error.wrong.int", null); allOk = false; } } catch (NumberFormatException e) { el.setErrorKey("error.wrong.int", null); allOk = false; } } else { el.setErrorKey("error.wrong.int", null); allOk = false; } return allOk; } @Override protected void formOK(UserRequest ureq) { registrationModule.setSelfRegistrationEnabled(registrationElement.isSelected(0)); registrationModule.setSelfRegistrationLinkEnabled(registrationLinkElement.isSelected(0)); registrationModule.setSelfRegistrationLoginEnabled(registrationLoginElement.isSelected(0)); if(organisationsEl.isOneSelected()) { registrationModule.setselfRegistrationOrganisationKey(organisationsEl.getSelectedKey()); } if(pendingRegistrationStatusEl.isOneSelected()) { registrationModule.setRegistrationPendingStatus(RegistrationPendingStatus.valueOf(pendingRegistrationStatusEl.getSelectedKey())); } registrationModule.setRegistrationPendingProperty1(pendingProperty1Els.getName(), pendingProperty1Els.getValue()); registrationModule.setRegistrationPendingProperty2(pendingProperty2Els.getName(), pendingProperty2Els.getValue()); registrationModule.setRegistrationPendingProperty3(pendingProperty3Els.getName(), pendingProperty3Els.getValue()); registrationModule.setRegistrationPendingProperty4(pendingProperty4Els.getName(), pendingProperty4Els.getValue()); registrationModule.setRegistrationPendingProperty5(pendingProperty5Els.getName(), pendingProperty5Els.getValue()); String notificationEmail = pendingRegistrationNotificationEl.getValue(); if(StringHelper.containsNonWhitespace(notificationEmail)) { registrationModule.setRegistrationNotificationEmailEnabled(true); registrationModule.setRegistrationNotificationEmail(notificationEmail); } else { registrationModule.setRegistrationNotificationEmailEnabled(false); } Integer validUntilHoursGui = Integer.parseInt(validUntilGuiEl.getValue()); registrationModule.setValidUntilHoursGui(validUntilHoursGui); Integer validUntilHoursRest = Integer.parseInt(validUntilRestEl.getValue()); registrationModule.setValidUntilHoursRest(validUntilHoursRest); String domains = domainListElement.getValue(); registrationModule.setDomainListRaw(domains); registrationModule.setStaticPropertyMappingEnabled(staticPropElement.isSelected(0)); if(propertyElement.isOneSelected()) { registrationModule.setStaticPropertyMappingName(propertyElement.getSelectedKey()); } else { registrationModule.setStaticPropertyMappingName("-"); } registrationModule.setStaticPropertyMappingValue(propertyValueElement.getValue()); } private String generateExampleCode() { StringBuilder code = new StringBuilder(); code.append("<form name=\"openolatregistration\" action=\"") .append(Settings.getServerContextPathURI()).append("/url/registration/0") .append("\" method=\"post\" target=\"OpenOLAT\" onsubmit=\"var openolat=window.open('','OpenOLAT',''); openolat.focus();\">\n") .append(" <input type=\"submit\" value=\"Go to registration\">\n") .append("</form>"); return code.toString(); } private String generateRemoteLoginExampleCode() { StringBuilder code = new StringBuilder(); code.append("<form name=\"olatremotelogin\" action=\"") .append(Settings.getServerContextPathURI()).append("/remotelogin/") .append("\" method=\"post\" target=\"OpenOLAT\" onsubmit=\"var openolat=window.open('','OpenOLAT', 'location=no,menubar=no,resizable=yes,toolbar=no,statusbar=no,scrollbars=yes'); openolat.focus();\">\n") .append(" Benutzername <input type=\"text\" name=\"username\">") .append(" Passwort <input type=\"password\" name=\"pwd\">") .append(" <input type=\"submit\" value=\"Login\">\n") .append("</form>"); return code.toString(); } public class PropertyNameValueElements { private final SingleSelection propertyNameEl; private final TextElement propertyValueEl; public PropertyNameValueElements(SingleSelection propertyNameEl, TextElement propertyValueEl) { this.propertyNameEl = propertyNameEl; this.propertyValueEl = propertyValueEl; } public SingleSelection getPropertyNameEl() { return propertyNameEl; } public TextElement getPropertyValueEl() { return propertyValueEl; } public void setVisible(boolean visible) { propertyNameEl.setVisible(visible); propertyValueEl.setVisible(visible); } public String getName() { String key = propertyNameEl.getSelectedKey(); if(propertyKeys[0].equals(key)) { key = ""; } return key; } public String getValue() { return propertyValueEl.getValue(); } } }