From 84908f97631741cfbd6145cb9c828c53206d4a66 Mon Sep 17 00:00:00 2001 From: srosse <none@none> Date: Tue, 7 Feb 2017 15:18:08 +0100 Subject: [PATCH] OO-2452: implement reset of password with SMS confirmation / authentication --- .../bps/olat/user/ChangeEMailController.java | 4 +- .../delete/service/UserDeletionManager.java | 4 +- .../services/_spring/servicesCorecontext.xml | 2 + .../core/commons/services/sms/MessageLog.java | 70 ++++ .../commons/services/sms/MessagesSPI.java | 38 +++ .../services/sms/SimpleMessageException.java | 28 ++ .../services/sms/SimpleMessageModule.java | 132 ++++++++ .../services/sms/SimpleMessageService.java | 76 +++++ .../services/sms/_spring/smsCorecontext.xml | 58 ++++ .../services/sms/manager/MessageLogDAO.java | 123 +++++++ .../sms/manager/SimpleMessageServiceImpl.java | 166 ++++++++++ .../services/sms/model/MessageLogImpl.java | 159 +++++++++ .../services/sms/model/MessageStatistics.java | 34 ++ .../services/sms/spi/WebSMSProvider.java | 168 ++++++++++ .../sms/ui/MessageStatisticsDataModel.java | 86 +++++ .../sms/ui/MessagesStatisticsController.java | 88 +++++ .../services/sms/ui/MonthCellRenderer.java | 35 ++ .../services/sms/ui/SMSPhoneController.java | 157 +++++++++ ...geServiceAdminConfigurationController.java | 140 ++++++++ .../SimpleMessageServiceAdminController.java | 102 ++++++ .../services/sms/ui/YearCellRenderer.java | 30 ++ .../services/sms/ui/_content/admin.html | 4 + .../services/sms/ui/_content/statistics.html | 1 + .../sms/ui/_i18n/LocalStrings_de.properties | 25 ++ .../sms/ui/_i18n/LocalStrings_en.properties | 25 ++ .../sms/ui/_i18n/LocalStrings_fr.properties | 1 + .../java/org/olat/core/id/UserConstants.java | 2 + .../ui/CheckboxAssessmentDataModelSorter.java | 19 ++ .../ldap/ui/LDAPAuthenticationController.java | 4 +- .../login/LoginAuthprovidersController.java | 2 +- .../org/olat/login/auth/OLATAuthManager.java | 8 +- .../registration/ConfirmTokenController.java | 91 +++++ .../olat/registration/PwChangeController.java | 312 +++++++++++------- .../org/olat/registration/PwChangeForm.java | 52 ++- .../registration/RegistrationController.java | 2 +- .../registration/RegistrationManager.java | 75 ++--- .../registration/SendMessageController.java | 89 +++++ .../org/olat/registration/TemporaryKey.java | 23 +- .../registration/TemporaryKeyImpl.hbm.xml | 45 --- .../olat/registration/TemporaryKeyImpl.java | 154 +++++---- .../olat/registration/_content/pwchange.html | 4 +- .../registration/_content/send_message.html | 5 + .../_i18n/LocalStrings_de.properties | 54 +-- .../_i18n/LocalStrings_en.properties | 35 +- .../org/olat/user/ProfileFormController.java | 5 +- src/main/java/org/olat/user/UserImpl.java | 4 + .../SmsPhonePropertyHandler.java | 64 ++++ .../UserInterestsElement.java | 6 - .../UserPropertyUsageContext.java | 10 + .../_i18n/LocalStrings_de.properties | 73 ++-- .../_i18n/LocalStrings_en.properties | 17 +- .../_spring/userPropertiesContext.xml | 1 + .../userPropertriesHandlersContext.xml | 6 + .../ui/SmsPhoneComponent.java | 50 +++ .../ui/SmsPhoneComponentRenderer.java | 64 ++++ .../ui/SmsPhoneConfirmController.java | 85 +++++ .../ui/SmsPhoneController.java | 90 +++++ .../propertyhandlers/ui/SmsPhoneElement.java | 167 ++++++++++ .../ui/SmsPhoneSendController.java | 131 ++++++++ .../ui/_content/edit_sms.html | 1 + .../ui/_i18n/LocalStrings_de.properties | 14 +- .../ui/_i18n/LocalStrings_en.properties | 17 +- src/main/resources/META-INF/persistence.xml | 3 +- .../database/mysql/alter_11_2_x_to_11_3_0.sql | 22 +- .../database/mysql/setupDatabase.sql | 18 +- .../oracle/alter_11_2_x_to_11_3_0.sql | 19 +- .../database/oracle/setupDatabase.sql | 17 + .../postgresql/alter_11_2_x_to_11_3_0.sql | 28 +- .../database/postgresql/setupDatabase.sql | 24 +- .../resources/serviceconfig/olat.properties | 14 + .../sms/manager/MessageLogDAOTest.java | 87 +++++ .../services/sms/spi/WebSMSProviderTest.java | 48 +++ .../registration/RegistrationManagerTest.java | 103 +++--- .../java/org/olat/test/AllTestsJunit4.java | 1 + 74 files changed, 3451 insertions(+), 470 deletions(-) create mode 100644 src/main/java/org/olat/core/commons/services/sms/MessageLog.java create mode 100644 src/main/java/org/olat/core/commons/services/sms/MessagesSPI.java create mode 100644 src/main/java/org/olat/core/commons/services/sms/SimpleMessageException.java create mode 100644 src/main/java/org/olat/core/commons/services/sms/SimpleMessageModule.java create mode 100644 src/main/java/org/olat/core/commons/services/sms/SimpleMessageService.java create mode 100644 src/main/java/org/olat/core/commons/services/sms/_spring/smsCorecontext.xml create mode 100644 src/main/java/org/olat/core/commons/services/sms/manager/MessageLogDAO.java create mode 100644 src/main/java/org/olat/core/commons/services/sms/manager/SimpleMessageServiceImpl.java create mode 100644 src/main/java/org/olat/core/commons/services/sms/model/MessageLogImpl.java create mode 100644 src/main/java/org/olat/core/commons/services/sms/model/MessageStatistics.java create mode 100644 src/main/java/org/olat/core/commons/services/sms/spi/WebSMSProvider.java create mode 100644 src/main/java/org/olat/core/commons/services/sms/ui/MessageStatisticsDataModel.java create mode 100644 src/main/java/org/olat/core/commons/services/sms/ui/MessagesStatisticsController.java create mode 100644 src/main/java/org/olat/core/commons/services/sms/ui/MonthCellRenderer.java create mode 100644 src/main/java/org/olat/core/commons/services/sms/ui/SMSPhoneController.java create mode 100644 src/main/java/org/olat/core/commons/services/sms/ui/SimpleMessageServiceAdminConfigurationController.java create mode 100644 src/main/java/org/olat/core/commons/services/sms/ui/SimpleMessageServiceAdminController.java create mode 100644 src/main/java/org/olat/core/commons/services/sms/ui/YearCellRenderer.java create mode 100644 src/main/java/org/olat/core/commons/services/sms/ui/_content/admin.html create mode 100644 src/main/java/org/olat/core/commons/services/sms/ui/_content/statistics.html create mode 100644 src/main/java/org/olat/core/commons/services/sms/ui/_i18n/LocalStrings_de.properties create mode 100644 src/main/java/org/olat/core/commons/services/sms/ui/_i18n/LocalStrings_en.properties create mode 100644 src/main/java/org/olat/core/commons/services/sms/ui/_i18n/LocalStrings_fr.properties create mode 100644 src/main/java/org/olat/registration/ConfirmTokenController.java create mode 100644 src/main/java/org/olat/registration/SendMessageController.java delete mode 100644 src/main/java/org/olat/registration/TemporaryKeyImpl.hbm.xml create mode 100644 src/main/java/org/olat/registration/_content/send_message.html create mode 100644 src/main/java/org/olat/user/propertyhandlers/SmsPhonePropertyHandler.java create mode 100644 src/main/java/org/olat/user/propertyhandlers/ui/SmsPhoneComponent.java create mode 100644 src/main/java/org/olat/user/propertyhandlers/ui/SmsPhoneComponentRenderer.java create mode 100644 src/main/java/org/olat/user/propertyhandlers/ui/SmsPhoneConfirmController.java create mode 100644 src/main/java/org/olat/user/propertyhandlers/ui/SmsPhoneController.java create mode 100644 src/main/java/org/olat/user/propertyhandlers/ui/SmsPhoneElement.java create mode 100644 src/main/java/org/olat/user/propertyhandlers/ui/SmsPhoneSendController.java create mode 100644 src/main/java/org/olat/user/propertyhandlers/ui/_content/edit_sms.html create mode 100644 src/test/java/org/olat/core/commons/services/sms/manager/MessageLogDAOTest.java create mode 100644 src/test/java/org/olat/core/commons/services/sms/spi/WebSMSProviderTest.java diff --git a/src/main/java/de/bps/olat/user/ChangeEMailController.java b/src/main/java/de/bps/olat/user/ChangeEMailController.java index 85cc03d43b3..0b054aeb0d1 100644 --- a/src/main/java/de/bps/olat/user/ChangeEMailController.java +++ b/src/main/java/de/bps/olat/user/ChangeEMailController.java @@ -34,7 +34,7 @@ import org.olat.core.id.Identity; import org.olat.core.id.User; import org.olat.core.util.Util; import org.olat.registration.RegistrationManager; -import org.olat.registration.TemporaryKeyImpl; +import org.olat.registration.TemporaryKey; import org.olat.user.ProfileAndHomePageEditController; import org.olat.user.UserManager; import org.springframework.beans.factory.annotation.Autowired; @@ -56,7 +56,7 @@ public class ChangeEMailController extends DefaultController { protected Translator pT; protected String emKey; - protected TemporaryKeyImpl tempKey; + protected TemporaryKey tempKey; protected UserRequest userRequest; @Autowired diff --git a/src/main/java/org/olat/admin/user/delete/service/UserDeletionManager.java b/src/main/java/org/olat/admin/user/delete/service/UserDeletionManager.java index 926b8414772..ed590c78572 100644 --- a/src/main/java/org/olat/admin/user/delete/service/UserDeletionManager.java +++ b/src/main/java/org/olat/admin/user/delete/service/UserDeletionManager.java @@ -65,7 +65,7 @@ import org.olat.core.util.mail.MailerResult; import org.olat.properties.Property; import org.olat.properties.PropertyManager; import org.olat.registration.RegistrationManager; -import org.olat.registration.TemporaryKeyImpl; +import org.olat.registration.TemporaryKey; import org.olat.repository.RepositoryDeletionModule; import org.olat.user.UserDataDeletable; import org.olat.user.UserManager; @@ -294,7 +294,7 @@ public class UserDeletionManager extends BasicManager { groupDao.removeMemberships(identity); String key = identity.getUser().getProperty("emchangeKey", null); - TemporaryKeyImpl tempKey = registrationManager.loadTemporaryKeyByRegistrationKey(key); + TemporaryKey tempKey = registrationManager.loadTemporaryKeyByRegistrationKey(key); if (tempKey != null) { registrationManager.deleteTemporaryKey(tempKey); } diff --git a/src/main/java/org/olat/core/commons/services/_spring/servicesCorecontext.xml b/src/main/java/org/olat/core/commons/services/_spring/servicesCorecontext.xml index fb01bf8cefd..2c74e196d1b 100644 --- a/src/main/java/org/olat/core/commons/services/_spring/servicesCorecontext.xml +++ b/src/main/java/org/olat/core/commons/services/_spring/servicesCorecontext.xml @@ -12,6 +12,7 @@ <import resource="classpath:/org/olat/core/commons/services/scheduler/_spring/schedulerContext.xml"/> <import resource="classpath:/org/olat/core/commons/services/taskexecutor/_spring/taskExecutorCorecontext.xml"/> <import resource="classpath:/org/olat/core/commons/services/notifications/_spring/notificationsContext.xml"/> + <import resource="classpath:/org/olat/core/commons/services/sms/_spring/smsCorecontext.xml"/> <bean id="imageHelper" class="org.olat.core.commons.services.image.ImageHelperBean"> <property name="imageHelperServiceProvider" ref="imageHelperServiceProvider_${thumbnail.provider}"/> @@ -34,4 +35,5 @@ </list> </property> </bean> + </beans> \ No newline at end of file diff --git a/src/main/java/org/olat/core/commons/services/sms/MessageLog.java b/src/main/java/org/olat/core/commons/services/sms/MessageLog.java new file mode 100644 index 00000000000..f6bfdd5899c --- /dev/null +++ b/src/main/java/org/olat/core/commons/services/sms/MessageLog.java @@ -0,0 +1,70 @@ +/** + * <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.core.commons.services.sms; + +import java.util.Date; + +import org.olat.core.id.Identity; + +/** + * + * Initial date: 3 févr. 2017<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public interface MessageLog { + + public Long getKey(); + + public Date getCreationDate(); + + /** + * The unique identifier of this message. + * + * @return The uuid + */ + public String getMessageUuid(); + + /** + * The ID of the service provider. + * + * @return The Id of the service provider + */ + public String getServiceId(); + + public void setServiceId(String serviceId); + + /** + * Informations about the status of the message sent. + * + * @return A string + */ + public String getServerResponse(); + + public void setServerResponse(String response); + + /** + * The recipient of the message. + * + * @return + */ + public Identity getRecipient(); + +} diff --git a/src/main/java/org/olat/core/commons/services/sms/MessagesSPI.java b/src/main/java/org/olat/core/commons/services/sms/MessagesSPI.java new file mode 100644 index 00000000000..eb01136e15c --- /dev/null +++ b/src/main/java/org/olat/core/commons/services/sms/MessagesSPI.java @@ -0,0 +1,38 @@ +/** + * <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.core.commons.services.sms; + +/** + * + * Initial date: 3 févr. 2017<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public interface MessagesSPI { + + public String getId(); + + public String getName(); + + public boolean isValid(); + + public boolean send(String messageId, String text, String recipient) throws SimpleMessageException; + +} diff --git a/src/main/java/org/olat/core/commons/services/sms/SimpleMessageException.java b/src/main/java/org/olat/core/commons/services/sms/SimpleMessageException.java new file mode 100644 index 00000000000..08ec3c3c1d1 --- /dev/null +++ b/src/main/java/org/olat/core/commons/services/sms/SimpleMessageException.java @@ -0,0 +1,28 @@ +package org.olat.core.commons.services.sms; + +/** + * + * Initial date: 7 févr. 2017<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class SimpleMessageException extends Exception { + + private static final long serialVersionUID = 787789477989775426L; + + private final ErrorCode code; + + public SimpleMessageException(Exception cause, ErrorCode code) { + super(cause); + this.code = code; + } + + public ErrorCode getErrorCode() { + return code; + } + + public enum ErrorCode { + numberNotValid, + + } +} diff --git a/src/main/java/org/olat/core/commons/services/sms/SimpleMessageModule.java b/src/main/java/org/olat/core/commons/services/sms/SimpleMessageModule.java new file mode 100644 index 00000000000..f351063650f --- /dev/null +++ b/src/main/java/org/olat/core/commons/services/sms/SimpleMessageModule.java @@ -0,0 +1,132 @@ +/** + * <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.core.commons.services.sms; + +import java.util.List; + +import org.olat.core.configuration.AbstractSpringModule; +import org.olat.core.configuration.ConfigOnOff; +import org.olat.core.id.UserConstants; +import org.olat.core.util.StringHelper; +import org.olat.core.util.coordinate.CoordinatorManager; +import org.olat.user.propertyhandlers.UserPropertyHandler; +import org.olat.user.propertyhandlers.UserPropertyUsageContext; +import org.olat.user.propertyhandlers.ui.UsrPropCfgManager; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +/** + * + * Initial date: 3 févr. 2017<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +@Service +public class SimpleMessageModule extends AbstractSpringModule implements ConfigOnOff { + + public static final String SMS_ENABLED = "message.enabled"; + public static final String RESET_PASSWORD_ENABLED = "message.reset.password.enabled"; + + @Value("${message.enabled:false}") + private boolean enabled; + @Value("${message.reset.password.enabled:true}") + private boolean resetPassword; + + + @Autowired + private UsrPropCfgManager usrPropCfgMng; + + @Autowired + public SimpleMessageModule(CoordinatorManager coordinatorManager) { + super(coordinatorManager); + } + + @Override + public void init() { + String enabledObj = getStringPropertyValue(SMS_ENABLED, true); + if(StringHelper.containsNonWhitespace(enabledObj)) { + enabled = "true".equals(enabledObj); + } + + String resetPasswordEnabledObj = getStringPropertyValue(RESET_PASSWORD_ENABLED, true); + if(StringHelper.containsNonWhitespace(resetPasswordEnabledObj)) { + resetPassword = "true".equals(resetPasswordEnabledObj); + } + + if(enabled) {//check + enableSmsUserProperty(); + } + } + + @Override + protected void initFromChangedProperties() { + init(); + } + + @Override + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + setStringProperty(SMS_ENABLED, Boolean.toString(enabled), true); + } + + private void enableSmsUserProperty() { + List<UserPropertyHandler> handlers = usrPropCfgMng.getUserPropertiesConfigObject().getPropertyHandlers(); + + UserPropertyHandler smsHandler = null; + UserPropertyHandler mobileHandler = null; + for(UserPropertyHandler handler:handlers) { + if(UserConstants.SMSTELMOBILE.equals(handler.getName())) { + smsHandler = handler; + } else if(UserConstants.TELMOBILE.equals(handler.getName())) { + mobileHandler = handler; + } + } + + if(smsHandler != null) { + UserPropertyUsageContext context = usrPropCfgMng.getUserPropertiesConfigObject() + .getUsageContexts().get("org.olat.user.ProfileFormController"); + if(!context.contains(smsHandler)) { + if(mobileHandler == null) { + context.addPropertyHandler(smsHandler); + } else { + int index = context.getPropertyHandlers().indexOf(mobileHandler); + context.addPropertyHandler(index + 1, smsHandler); + } + } + } + } + + public boolean isResetPasswordEnabled() { + return resetPassword; + } + + public void setResetPasswordEnabled(boolean resetPassword) { + this.resetPassword = resetPassword; + setStringProperty(RESET_PASSWORD_ENABLED, Boolean.toString(resetPassword), true); + } + + + +} diff --git a/src/main/java/org/olat/core/commons/services/sms/SimpleMessageService.java b/src/main/java/org/olat/core/commons/services/sms/SimpleMessageService.java new file mode 100644 index 00000000000..548a3111ac2 --- /dev/null +++ b/src/main/java/org/olat/core/commons/services/sms/SimpleMessageService.java @@ -0,0 +1,76 @@ +/** + * <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.core.commons.services.sms; + +import java.util.List; + +import org.olat.core.commons.services.sms.model.MessageStatistics; +import org.olat.core.id.Identity; + +/** + * + * Initial date: 3 févr. 2017<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public interface SimpleMessageService { + + /** + * @return A six digits token random generated. + */ + public String generateToken(); + + /** + * A method to validate the phone number. + * + * @param number The phone number + * @return true if the service can send a message with the specified number. + */ + public boolean validate(String number); + + /** + * The list of service providers registered in the system. + * + * @return A list of service providers. + */ + public List<MessagesSPI> getMessagesSpiList(); + + /** + * Return the active messages service provider. + * + * @return A message service provider + */ + public MessagesSPI getMessagesSpi(); + + /** + * Return the message service provider identified by its id. + * + * @param serviceId The id of the desired service provider. + * @return A message service provider or null + */ + public MessagesSPI getMessagesSpi(String serviceId); + + public void sendMessage(String text, Identity recipient) throws SimpleMessageException; + + public void sendMessage(String text, String phone, Identity recipient) throws SimpleMessageException; + + public List<MessageStatistics> getStatisticsPerMonth(); + +} diff --git a/src/main/java/org/olat/core/commons/services/sms/_spring/smsCorecontext.xml b/src/main/java/org/olat/core/commons/services/sms/_spring/smsCorecontext.xml new file mode 100644 index 00000000000..bce3275ef7a --- /dev/null +++ b/src/main/java/org/olat/core/commons/services/sms/_spring/smsCorecontext.xml @@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation=" + http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/context + http://www.springframework.org/schema/context/spring-context.xsd"> + + <bean id="smsTelMobile.AfterLogin.Injection" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> + <property name="targetObject" ref="afterLoginInterceptionManager" /> + <property name="targetMethod" value="addAfterLoginControllerConfig" /> + <property name="arguments"> + <ref bean="smsTelMobile.AfterLoginConfig"/> + </property> + </bean> + + <bean id="smsTelMobile.AfterLoginConfig" class="org.olat.login.AfterLoginConfig"> + <property name="afterLoginControllerList"> + <list> + <map> + <entry key="controller"> + <bean class="org.olat.core.gui.control.creator.AutoCreator" scope="prototype"> + <property name="className" value="org.olat.core.commons.services.sms.ui.SMSPhoneController"/> + </bean> + </entry> + <entry key="forceUser"><value>false</value></entry> + <entry key="redoTimeout"><value>0</value></entry> + <entry key="i18nIntro"><value>org.olat.core.commons.services.sms.ui:confirm.sms.phone</value></entry> + <entry key="order"><value>0</value></entry> + <!-- 31536000 = 60 * 60 * 24 * 365 (or a year in seconds) --> + <entry key="redoTimeout"><value>31536000</value></entry> + </map> + </list> + </property> + </bean> + + <bean class="org.olat.core.extensions.action.GenericActionExtension" init-method="initExtensionPoints"> + <property name="order" value="8835" /> + <property name="actionController"> + <bean class="org.olat.core.gui.control.creator.AutoCreator" scope="prototype"> + <property name="className" value="org.olat.core.commons.services.sms.ui.SimpleMessageServiceAdminController"/> + </bean> + </property> + <property name="navigationKey" value="smsAdmin" /> + <property name="i18nActionKey" value="admin.menu.title"/> + <property name="i18nDescriptionKey" value="admin.menu.title.alt"/> + <property name="translationPackage" value="org.olat.core.commons.services.sms.ui"/> + <property name="parentTreeNodeIdentifier" value="loginAndSecurityParent" /> + <property name="extensionPoints"> + <list> + <value>org.olat.admin.SystemAdminMainController</value> + </list> + </property> + </bean> + +</beans> \ No newline at end of file diff --git a/src/main/java/org/olat/core/commons/services/sms/manager/MessageLogDAO.java b/src/main/java/org/olat/core/commons/services/sms/manager/MessageLogDAO.java new file mode 100644 index 00000000000..9e2fe351998 --- /dev/null +++ b/src/main/java/org/olat/core/commons/services/sms/manager/MessageLogDAO.java @@ -0,0 +1,123 @@ +/** + * <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.core.commons.services.sms.manager; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.UUID; + +import org.olat.core.commons.persistence.DB; +import org.olat.core.commons.persistence.PersistenceHelper; +import org.olat.core.commons.services.sms.MessageLog; +import org.olat.core.commons.services.sms.model.MessageLogImpl; +import org.olat.core.commons.services.sms.model.MessageStatistics; +import org.olat.core.id.Identity; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * + * Initial date: 3 févr. 2017<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +@Service +public class MessageLogDAO { + + @Autowired + private DB dbInstance; + + /** + * Create a transient log entry. + * + * @param recipient + * @return The log entry + */ + public MessageLog create(Identity recipient, String serviceId) { + MessageLogImpl log = new MessageLogImpl(); + log.setCreationDate(new Date()); + log.setLastModified(log.getCreationDate()); + log.setMessageUuid(UUID.randomUUID().toString()); + log.setServiceId(serviceId); + log.setRecipient(recipient); + dbInstance.getCurrentEntityManager().persist(log); + return log; + } + + public MessageLog save(MessageLog log) { + MessageLog mergedLog; + if(log.getKey() == null) { + dbInstance.getCurrentEntityManager().persist(log); + mergedLog = log; + } else { + ((MessageLogImpl)log).setLastModified(new Date()); + mergedLog = dbInstance.getCurrentEntityManager().merge(log); + } + return mergedLog; + } + + public MessageLog loadMessageByKey(Long key) { + StringBuilder sb = new StringBuilder(); + sb.append("select mlog from smsmessagelog mlog where mlog.key=:messageKey"); + + List<MessageLog> mLogs = dbInstance.getCurrentEntityManager() + .createQuery(sb.toString(), MessageLog.class) + .setParameter("messageKey", key) + .getResultList(); + return mLogs == null || mLogs.isEmpty() ? null : mLogs.get(0); + } + + public List<MessageStatistics> getStatisticsPerMonth(String serviceId) { + StringBuilder sb = new StringBuilder(); + sb.append("select count(mlog.key) as numOfMessages, month(mlog.creationDate) as month, year(mlog.creationDate) as year") + .append(" from smsmessagelog mlog") + .append(" where mlog.serviceId=:serviceId") + .append(" group by month(mlog.creationDate), year(mlog.creationDate)"); + + List<Object[]> objects = dbInstance.getCurrentEntityManager() + .createQuery(sb.toString(), Object[].class) + .setParameter("serviceId", serviceId) + .getResultList(); + + Calendar cal = Calendar.getInstance(); + List<MessageStatistics> stats = new ArrayList<>(objects.size()); + for(Object[] object:objects) { + int pos = 0; + Long numOfMessages = PersistenceHelper.extractLong(object, pos++); + Long month = PersistenceHelper.extractLong(object, pos++); + Long year = PersistenceHelper.extractLong(object, pos++); + if(numOfMessages != null) { + cal.set(Calendar.YEAR, year.intValue()); + cal.set(Calendar.MONTH, month.intValue() - 1); + cal.set(Calendar.DAY_OF_MONTH, 1); + cal.set(Calendar.HOUR_OF_DAY, 0); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MILLISECOND, 0); + + Date date = cal.getTime(); + stats.add(new MessageStatistics(serviceId, date, numOfMessages)); + } + } + return stats; + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/core/commons/services/sms/manager/SimpleMessageServiceImpl.java b/src/main/java/org/olat/core/commons/services/sms/manager/SimpleMessageServiceImpl.java new file mode 100644 index 00000000000..32276f77005 --- /dev/null +++ b/src/main/java/org/olat/core/commons/services/sms/manager/SimpleMessageServiceImpl.java @@ -0,0 +1,166 @@ +/** + * <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.core.commons.services.sms.manager; + + +import java.util.List; +import java.util.Random; + +import org.olat.core.commons.services.sms.MessageLog; +import org.olat.core.commons.services.sms.MessagesSPI; +import org.olat.core.commons.services.sms.SimpleMessageException; +import org.olat.core.commons.services.sms.SimpleMessageModule; +import org.olat.core.commons.services.sms.SimpleMessageService; +import org.olat.core.commons.services.sms.model.MessageStatistics; +import org.olat.core.helpers.Settings; +import org.olat.core.id.Identity; +import org.olat.core.id.UserConstants; +import org.olat.core.logging.OLog; +import org.olat.core.logging.Tracing; +import org.olat.core.util.StringHelper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * + * Initial date: 3 févr. 2017<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +@Service +public class SimpleMessageServiceImpl implements SimpleMessageService { + + private static final OLog log = Tracing.createLoggerFor(SimpleMessageServiceImpl.class); + private static final Random rnd = new Random(); + + @Autowired + private MessageLogDAO messageLogDao; + + @Autowired + private SimpleMessageModule messageModule; + @Autowired + private List<MessagesSPI> messagesSpiList; + + @Override + public List<MessagesSPI> getMessagesSpiList() { + return messagesSpiList; + } + + @Override + public String generateToken() { + StringBuilder sb = new StringBuilder(); + for(int i=0; i<6; i++) { + int n = Math.round(rnd.nextFloat() * 9.0f); + if(n < 0) { + n = 0; + } else if(n > 9) { + n = 9; + } + sb.append(n); + } + return sb.toString(); + } + + @Override + public boolean validate(String number) { + if(!StringHelper.containsNonWhitespace(number)) return false; + number = number.replace("+", "").replace(" ", ""); + if(StringHelper.isLong(number)) { + try { + Long phone = new Long(number); + return phone > 0; + } catch (NumberFormatException e) { + // + } + } + return false; + } + + @Override + public void sendMessage(String text, Identity recipient) throws SimpleMessageException { + String telNumber = recipient.getUser().getProperty(UserConstants.SMSTELMOBILE, null); + sendMessage(text, telNumber, recipient); + } + + @Override + public void sendMessage(String text, String telNumber, Identity recipient) throws SimpleMessageException { + MessagesSPI spi = getMessagesSpi(); + MessageLog mLog = messageLogDao.create(recipient, spi.getId()); + boolean allOk = spi.send(mLog.getMessageUuid(), text, telNumber); + mLog.setServerResponse(Boolean.toString(allOk)); + messageLogDao.save(mLog); + log.audit("SMS send: " + allOk + " to " + recipient + " with number: " + telNumber); + } + + @Override + public List<MessageStatistics> getStatisticsPerMonth() { + MessagesSPI selectedSpi = getMessagesSpi(); + return messageLogDao.getStatisticsPerMonth(selectedSpi.getId()); + } + + @Override + public MessagesSPI getMessagesSpi(String serviceId) { + MessagesSPI spi = null; + if("devnull".equals(serviceId)) { + spi = new DevNullProvider(); + } else if(messagesSpiList != null) { + for(MessagesSPI mSpi:messagesSpiList) { + if(mSpi.getId().equals(serviceId)) { + spi = mSpi; + } + } + } + return spi; + } + + @Override + public MessagesSPI getMessagesSpi() { + if(Settings.isDebuging()) return new DevNullProvider(); + + if(messageModule.isEnabled() && messagesSpiList.size() > 0) { + return messagesSpiList.get(0); + } + return new DevNullProvider(); + } + + private static class DevNullProvider implements MessagesSPI { + + @Override + public String getId() { + return "devnull"; + } + + @Override + public String getName() { + return "/dev/null"; + } + + @Override + public boolean isValid() { + return true; + } + + @Override + public boolean send(String messageId, String text, String recipient) { + log.info("Send: " + text); + return true; + } + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/core/commons/services/sms/model/MessageLogImpl.java b/src/main/java/org/olat/core/commons/services/sms/model/MessageLogImpl.java new file mode 100644 index 00000000000..8a680cb0045 --- /dev/null +++ b/src/main/java/org/olat/core/commons/services/sms/model/MessageLogImpl.java @@ -0,0 +1,159 @@ +/** + * <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.core.commons.services.sms.model; + +import java.util.Date; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; + +import org.olat.basesecurity.IdentityImpl; +import org.olat.core.commons.services.sms.MessageLog; +import org.olat.core.id.CreateInfo; +import org.olat.core.id.Identity; +import org.olat.core.id.ModifiedInfo; +import org.olat.core.id.Persistable; + +/** + * + * Initial date: 3 févr. 2017<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +@Entity(name="smsmessagelog") +@Table(name="o_sms_message_log") +public class MessageLogImpl implements Persistable, ModifiedInfo, CreateInfo, MessageLog { + + private static final long serialVersionUID = 2605977680881759364L; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name="id", nullable=false, unique=true, insertable=true, updatable=false) + private Long key; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="creationdate", nullable=false, insertable=true, updatable=false) + private Date creationDate; + @Temporal(TemporalType.TIMESTAMP) + @Column(name="lastmodified", nullable=false, insertable=true, updatable=true) + private Date lastModified; + + @Column(name="s_message_uuid", nullable=false, insertable=true, updatable=false) + private String messageUuid; + @Column(name="s_server_response", nullable=true, insertable=true, updatable=false) + private String serverResponse; + @Column(name="s_service_id", nullable=false, insertable=true, updatable=false) + private String serviceId; + + @ManyToOne(targetEntity=IdentityImpl.class,fetch=FetchType.LAZY,optional=false) + @JoinColumn(name="fk_identity", nullable=true, insertable=true, updatable=false) + private Identity recipient; + + @Override + public Long getKey() { + return key; + } + + public void setKey(Long key) { + this.key = key; + } + + @Override + public Date getCreationDate() { + return creationDate; + } + + public void setCreationDate(Date creationDate) { + this.creationDate = creationDate; + } + + @Override + public Date getLastModified() { + return lastModified; + } + + @Override + public void setLastModified(Date date) { + lastModified = date; + } + + public String getMessageUuid() { + return messageUuid; + } + + public void setMessageUuid(String messageUuid) { + this.messageUuid = messageUuid; + } + + public String getServerResponse() { + return serverResponse; + } + + public void setServerResponse(String serverResponse) { + this.serverResponse = serverResponse; + } + + public String getServiceId() { + return serviceId; + } + + public void setServiceId(String serviceId) { + this.serviceId = serviceId; + } + + public Identity getRecipient() { + return recipient; + } + + public void setRecipient(Identity recipient) { + this.recipient = recipient; + } + + @Override + public int hashCode() { + return key == null ? 349857 : key.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if(obj == this) { + return true; + } + if(obj instanceof MessageLogImpl) { + MessageLogImpl log = (MessageLogImpl)obj; + return key != null && key.equals(log.key); + } + return false; + } + + @Override + public boolean equalsByPersistableKey(Persistable persistable) { + return equals(persistable); + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/core/commons/services/sms/model/MessageStatistics.java b/src/main/java/org/olat/core/commons/services/sms/model/MessageStatistics.java new file mode 100644 index 00000000000..e5305e63ef7 --- /dev/null +++ b/src/main/java/org/olat/core/commons/services/sms/model/MessageStatistics.java @@ -0,0 +1,34 @@ +package org.olat.core.commons.services.sms.model; + +import java.util.Date; + +/** + * + * Initial date: 7 févr. 2017<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class MessageStatistics { + + private final Date date; + private final String service; + private final long numOfMessages; + + public MessageStatistics(String service, Date date, long numOfMessages) { + this.service = service; + this.date = date; + this.numOfMessages = numOfMessages; + } + + public Date getDate() { + return date; + } + + public String getService() { + return service; + } + + public long getNumOfMessages() { + return numOfMessages; + } +} diff --git a/src/main/java/org/olat/core/commons/services/sms/spi/WebSMSProvider.java b/src/main/java/org/olat/core/commons/services/sms/spi/WebSMSProvider.java new file mode 100644 index 00000000000..4c922d29314 --- /dev/null +++ b/src/main/java/org/olat/core/commons/services/sms/spi/WebSMSProvider.java @@ -0,0 +1,168 @@ +/** + * <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.core.commons.services.sms.spi; + +import org.apache.http.HttpEntity; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.util.EntityUtils; +import org.json.JSONArray; +import org.json.JSONObject; +import org.olat.core.commons.services.sms.MessagesSPI; +import org.olat.core.logging.OLog; +import org.olat.core.logging.Tracing; +import org.olat.core.util.StringHelper; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +/** + * Implementation for https://websms.ch + * + * Initial date: 3 févr. 2017<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +@Service("messagesSpiWebSMS") +public class WebSMSProvider implements MessagesSPI, InitializingBean { + + private static final OLog log = Tracing.createLoggerFor(WebSMSProvider.class); + private final BasicCredentialsProvider provider = new BasicCredentialsProvider(); + + @Value("${websms.url:https://api.websms.com/rest/smsmessaging/text}") + private String url; + + @Value("${websms.username:}") + private String username; + @Value("${websms.password:}") + private String password; + + private boolean test = false; + + /** + * Method means for unit tests. The changes are not persisted. + * + * @param username + * @param password + */ + protected void setCredentials(String username, String password) { + this.username = username; + this.password = password; + provider.setCredentials(new AuthScope("api.websms.com", 443), + new UsernamePasswordCredentials(username, password)); + } + + protected void setTest(boolean test) { + this.test = test; + } + + @Override + public String getId() { + return "websms"; + } + + @Override + public String getName() { + return "WebSMS"; + } + + @Override + public boolean isValid() { + return StringHelper.containsNonWhitespace(username) && StringHelper.containsNonWhitespace(password); + } + + @Override + public void afterPropertiesSet() throws Exception { + provider.setCredentials(new AuthScope("api.websms.com", 443), + new UsernamePasswordCredentials(username, password)); + } + + @Override + public boolean send(String messageId, String text, String recipient) { + HttpPost send = new HttpPost(url); + try(CloseableHttpClient httpclient = HttpClientBuilder.create() + .setDefaultCredentialsProvider(provider) + .build()) { + + String phone = recipient.replace("+", "").replace(" ", ""); + String objectStr = jsonPayload(messageId, text, new Long(phone)); + HttpEntity smsEntity = new StringEntity(objectStr, ContentType.APPLICATION_JSON); + send.setEntity(smsEntity); + CloseableHttpResponse response = httpclient.execute(send); + int returnCode = response.getStatusLine().getStatusCode(); + String responseString = EntityUtils.toString(response.getEntity()); + if(returnCode == 200 || returnCode >= 2000) { + return true; + } + log.error("WebSMS return an error code " + returnCode + ": " + responseString); + return false; + } catch(Exception e) { + log.error("", e); + return false; + } + } + + /** + * { + * "userDataHeaderPresent" : false, + * "messageContent" : [ "...", ... ], + * "test" : false, + * "recipientAddressList" : [ ..., ... ], + * "senderAddress" : "...", + * "senderAddressType" : "national", + * "sendAsFlashSms" : false, + * "notificationCallbackUrl" : "...", + * "clientMessageId" : "...", + * "priority" : ..., + * } + * @param obj + * @return + */ + private String jsonPayload(String messageId, String text, Long recipient) { + try { + JSONObject message = new JSONObject(); + message.put("userDataHeaderPresent", false); + message.put("messageContent", text); + message.put("test", test); + + JSONArray recipients = new JSONArray(); + recipients.put(recipient); + message.put("recipientAddressList", recipients);//arrsx + //optional message.put("senderAddress", ""); + //optional message.put("senderAddressType", "national"); + //optional message.put("sendAsFlashSms", false); + //optional message.put("senderAddress", "");//national international shortcode alphanumeric + //optional message.put("notificationCallbackUrl", ""); + message.put("clientMessageId", messageId); + //optional message.put("priority", false); + return message.toString(); + } catch (Exception e) { + log.error("", e); + return null; + } + } +} diff --git a/src/main/java/org/olat/core/commons/services/sms/ui/MessageStatisticsDataModel.java b/src/main/java/org/olat/core/commons/services/sms/ui/MessageStatisticsDataModel.java new file mode 100644 index 00000000000..b2e25aa90dd --- /dev/null +++ b/src/main/java/org/olat/core/commons/services/sms/ui/MessageStatisticsDataModel.java @@ -0,0 +1,86 @@ +package org.olat.core.commons.services.sms.ui; + +import java.util.List; +import java.util.Locale; + +import org.olat.core.commons.persistence.SortKey; +import org.olat.core.commons.services.sms.model.MessageStatistics; +import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiTableDataModel; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiSortableColumnDef; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel; +import org.olat.core.gui.components.form.flexible.impl.elements.table.SortableFlexiTableDataModel; +import org.olat.core.gui.components.form.flexible.impl.elements.table.SortableFlexiTableModelDelegate; + +/** + * + * Initial date: 7 févr. 2017<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class MessageStatisticsDataModel extends DefaultFlexiTableDataModel<MessageStatistics> + implements SortableFlexiTableDataModel<MessageStatistics> { + + private final Locale locale; + + public MessageStatisticsDataModel(FlexiTableColumnModel columnModel, Locale locale) { + super(columnModel); + this.locale = locale; + } + + @Override + public void sort(SortKey orderBy) { + if(orderBy != null) { + SortableFlexiTableModelDelegate<MessageStatistics> sorter = new SortableFlexiTableModelDelegate<>(orderBy, this, locale); + List<MessageStatistics> stats = sorter.sort(); + super.setObjects(stats); + } + } + + @Override + public Object getValueAt(int row, int col) { + MessageStatistics infos = getObject(row); + return getValueAt(infos, col); + } + + @Override + public Object getValueAt(MessageStatistics row, int col) { + switch(MLogStatsCols.values()[col]) { + case year: + case month: return row.getDate(); + case numOfMessages: return row.getNumOfMessages(); + default: return null; + } + } + + @Override + public DefaultFlexiTableDataModel<MessageStatistics> createCopyWithEmptyList() { + return new MessageStatisticsDataModel(getTableColumnModel(), locale); + } + + public enum MLogStatsCols implements FlexiSortableColumnDef { + year("table.header.year"), + month("table.header.month"), + numOfMessages("table.header.numOfMessages"); + + private final String i18nKey; + + private MLogStatsCols(String i18nKey) { + this.i18nKey = i18nKey; + } + + @Override + public String i18nHeaderKey() { + return i18nKey; + } + + @Override + public boolean sortable() { + return true; + } + + @Override + public String sortKey() { + return name(); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/core/commons/services/sms/ui/MessagesStatisticsController.java b/src/main/java/org/olat/core/commons/services/sms/ui/MessagesStatisticsController.java new file mode 100644 index 00000000000..668bb1da120 --- /dev/null +++ b/src/main/java/org/olat/core/commons/services/sms/ui/MessagesStatisticsController.java @@ -0,0 +1,88 @@ +/** + * <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.core.commons.services.sms.ui; + +import java.util.List; + +import org.olat.core.commons.services.sms.SimpleMessageService; +import org.olat.core.commons.services.sms.model.MessageStatistics; +import org.olat.core.commons.services.sms.ui.MessageStatisticsDataModel.MLogStatsCols; +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.form.flexible.FormItemContainer; +import org.olat.core.gui.components.form.flexible.elements.FlexiTableElement; +import org.olat.core.gui.components.form.flexible.impl.FormBasicController; +import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiColumnModel; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.WindowControl; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * Initial date: 3 févr. 2017<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class MessagesStatisticsController extends FormBasicController { + + private FlexiTableElement tableEl; + private MessageStatisticsDataModel model; + + @Autowired + private SimpleMessageService messageService; + + public MessagesStatisticsController(UserRequest ureq, WindowControl wControl) { + super(ureq, wControl, "statistics"); + initForm(ureq); + loadModel(); + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel(); + DefaultFlexiColumnModel yearColumn = new DefaultFlexiColumnModel(MLogStatsCols.year, new YearCellRenderer()); + yearColumn.setExportable(false); + columnsModel.addFlexiColumnModel(yearColumn); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(MLogStatsCols.month, new MonthCellRenderer(getLocale()))); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(MLogStatsCols.numOfMessages)); + + model = new MessageStatisticsDataModel(columnsModel, getLocale()); + tableEl = uifactory.addTableElement(getWindowControl(), "stats", model, 50, false, getTranslator(), formLayout); + tableEl.setCustomizeColumns(false); + tableEl.setExportEnabled(true); + } + + private void loadModel() { + List<MessageStatistics> stats = messageService.getStatisticsPerMonth(); + model.setObjects(stats); + tableEl.reset(true, true, true); + } + + @Override + protected void doDispose() { + // + } + + @Override + protected void formOK(UserRequest ureq) { + // + } +} diff --git a/src/main/java/org/olat/core/commons/services/sms/ui/MonthCellRenderer.java b/src/main/java/org/olat/core/commons/services/sms/ui/MonthCellRenderer.java new file mode 100644 index 00000000000..3328d92e84c --- /dev/null +++ b/src/main/java/org/olat/core/commons/services/sms/ui/MonthCellRenderer.java @@ -0,0 +1,35 @@ +package org.olat.core.commons.services.sms.ui; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiCellRenderer; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableComponent; +import org.olat.core.gui.render.Renderer; +import org.olat.core.gui.render.StringOutput; +import org.olat.core.gui.render.URLBuilder; +import org.olat.core.gui.translator.Translator; + +/** + * + * Initial date: 7 févr. 2017<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class MonthCellRenderer implements FlexiCellRenderer { + + private final SimpleDateFormat format; + + public MonthCellRenderer(Locale locale) { + format = new SimpleDateFormat("MMMM", locale); + } + + @Override + public void render(Renderer renderer, StringOutput target, Object cellValue, int row, FlexiTableComponent source, + URLBuilder ubu, Translator translator) { + if(cellValue instanceof Date) { + target.append(format.format((Date)cellValue)); + } + } +} diff --git a/src/main/java/org/olat/core/commons/services/sms/ui/SMSPhoneController.java b/src/main/java/org/olat/core/commons/services/sms/ui/SMSPhoneController.java new file mode 100644 index 00000000000..d09ba49fab3 --- /dev/null +++ b/src/main/java/org/olat/core/commons/services/sms/ui/SMSPhoneController.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.core.commons.services.sms.ui; + +import org.olat.core.commons.services.sms.SimpleMessageException; +import org.olat.core.commons.services.sms.SimpleMessageModule; +import org.olat.core.commons.services.sms.SimpleMessageService; +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.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.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.id.User; +import org.olat.core.id.UserConstants; +import org.olat.core.util.StringHelper; +import org.olat.login.SupportsAfterLoginInterceptor; +import org.olat.user.UserManager; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * Initial date: 3 févr. 2017<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class SMSPhoneController extends FormBasicController implements SupportsAfterLoginInterceptor { + + private FormLink dontActivateButton; + private TextElement phoneEl, tokenEl; + + private String sentToken; + + @Autowired + private UserManager userManager; + @Autowired + private SimpleMessageModule messageModule; + @Autowired + private SimpleMessageService messageService; + + public SMSPhoneController(UserRequest ureq, WindowControl wControl) { + super(ureq, wControl); + + initForm(ureq); + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + phoneEl = uifactory.addTextElement("sms.phone.number", "sms.phone.number", 32, "", formLayout); + phoneEl.setPlaceholderKey("sms.phone.number.hint", null); + + tokenEl = uifactory.addTextElement("sms.token.number", "sms.token.number", 16, "", formLayout); + tokenEl.setExampleKey("sms.token.number.explain", null); + tokenEl.setVisible(false); + + FormLayoutContainer buttonsCont = FormLayoutContainer.createButtonLayout("buttons", getTranslator()); + formLayout.add(buttonsCont); + uifactory.addFormSubmitButton("save", buttonsCont); + dontActivateButton = uifactory.addFormLink("dont.activate", buttonsCont, Link.BUTTON); + } + + @Override + protected void doDispose() { + // + } + + @Override + public boolean isUserInteractionRequired(UserRequest ureq) { + return messageModule.isEnabled() && messageModule.isResetPasswordEnabled() + && !ureq.getUserSession().getRoles().isGuestOnly() + && !messageService.validate(ureq.getIdentity().getUser().getProperty(UserConstants.SMSTELMOBILE, getLocale())); + } + + @Override + protected boolean validateFormLogic(UserRequest ureq) { + boolean allOk = true; + + phoneEl.clearError(); + if(phoneEl.isVisible()) { + if(!StringHelper.containsNonWhitespace(phoneEl.getValue())) { + phoneEl.setErrorKey("form.legende.mandatory", null); + allOk &= false; + } else if(!messageService.validate(phoneEl.getValue())) { + phoneEl.setErrorKey("error.phone.invalid", null); + allOk &= false; + } + } + + tokenEl.clearError(); + if(tokenEl.isVisible()) { + String tokenValue = tokenEl.getValue(); + if(!StringHelper.containsNonWhitespace(tokenValue)) { + tokenEl.setErrorKey("form.legende.mandatory", null); + allOk &= false; + } else if(sentToken == null || !sentToken.equals(tokenValue)) { + tokenEl.setErrorKey("error.invalid.token", null); + allOk &= false; + } + } + + return allOk &= super.validateFormLogic(ureq); + } + + @Override + protected void formOK(UserRequest ureq) { + if(phoneEl.isVisible()) { + try { + phoneEl.setVisible(false); + tokenEl.setVisible(true); + + sentToken = messageService.generateToken(); + String msg = translate("sms.token", new String[]{ sentToken }); + messageService.sendMessage(msg, phoneEl.getValue(), getIdentity()); + } catch (SimpleMessageException e) { + phoneEl.setVisible(true); + tokenEl.setVisible(false); + phoneEl.setErrorKey("error.phone.invalid", null); + } + } else if(tokenEl.isVisible()) { + User user = getIdentity().getUser(); + user.setProperty(UserConstants.SMSTELMOBILE, phoneEl.getValue()); + userManager.updateUserFromIdentity(getIdentity()); + fireEvent(ureq, Event.DONE_EVENT); + } + } + + @Override + protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { + if(source == dontActivateButton) { + fireEvent(ureq, Event.DONE_EVENT); + } + super.formInnerEvent(ureq, source, event); + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/core/commons/services/sms/ui/SimpleMessageServiceAdminConfigurationController.java b/src/main/java/org/olat/core/commons/services/sms/ui/SimpleMessageServiceAdminConfigurationController.java new file mode 100644 index 00000000000..cd0545bbf92 --- /dev/null +++ b/src/main/java/org/olat/core/commons/services/sms/ui/SimpleMessageServiceAdminConfigurationController.java @@ -0,0 +1,140 @@ +/** + * <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.core.commons.services.sms.ui; + +import java.util.List; + +import org.olat.core.commons.services.sms.MessagesSPI; +import org.olat.core.commons.services.sms.SimpleMessageModule; +import org.olat.core.commons.services.sms.SimpleMessageService; +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.SingleSelection; +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.control.Controller; +import org.olat.core.gui.control.WindowControl; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * Initial date: 3 févr. 2017<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class SimpleMessageServiceAdminConfigurationController extends FormBasicController { + + private static final String[] onKeys = new String[]{ "on" }; + + private SingleSelection serviceEl; + private MultipleSelectionElement enableEl; + private MultipleSelectionElement resetPasswordEl; + + @Autowired + private SimpleMessageModule messageModule; + @Autowired + private SimpleMessageService messagesService; + + public SimpleMessageServiceAdminConfigurationController(UserRequest ureq, WindowControl wControl) { + super(ureq, wControl); + + initForm(ureq); + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + setFormTitle("admin.configuration.title"); + setFormDescription("admin.configuration.description"); + + String[] onValues = new String[]{ translate("on") }; + enableEl = uifactory.addCheckboxesHorizontal("enable", "admin.enable", formLayout, onKeys, onValues); + enableEl.addActionListener(FormEvent.ONCHANGE); + if(messageModule.isEnabled()) { + enableEl.select(onKeys[0], true); + } + + List<MessagesSPI> spies = messagesService.getMessagesSpiList(); + String[] serviceKeys = new String[spies.size()]; + String[] serviceValues = new String[spies.size()]; + for(int i=spies.size(); i-->0; ) { + serviceKeys[i] = spies.get(i).getId(); + serviceValues[i] = spies.get(i).getName(); + } + serviceEl = uifactory.addDropdownSingleselect("service", "service", formLayout, serviceKeys, serviceValues, null); + if(messagesService.getMessagesSpi() != null) { + String activeServiceId = messagesService.getMessagesSpi().getId(); + for(int i=serviceKeys.length; i-->0; ) { + if(serviceKeys[i].equals(activeServiceId)) { + serviceEl.select(serviceKeys[i], true); + } + } + } + + String[] resetPasswordValues = new String[]{ translate("on.sms") }; + resetPasswordEl = uifactory.addCheckboxesHorizontal("reset.password", "reset.password", formLayout, onKeys, resetPasswordValues); + resetPasswordEl.addActionListener(FormEvent.ONCHANGE); + if(messageModule.isResetPasswordEnabled()) { + resetPasswordEl.select(onKeys[0], true); + } + updateEnableDisable(); + } + + private void updateEnableDisable() { + boolean enabled = enableEl.isAtLeastSelected(1); + serviceEl.setVisible(enabled); + resetPasswordEl.setVisible(enabled); + + serviceEl.clearError(); + if(serviceEl.isOneSelected()) { + String serviceId = serviceEl.getSelectedKey(); + MessagesSPI spi = messagesService.getMessagesSpi(serviceId); + if(spi != null && !spi.isValid()) { + serviceEl.setErrorKey("warning.spi.not.configured", new String[]{ spi.getName() }); + } + } + } + + @Override + protected void doDispose() { + // + } + + @Override + protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { + if(enableEl == source) { + updateEnableDisable(); + messageModule.setEnabled(enableEl.isAtLeastSelected(1)); + } else if(resetPasswordEl == source) { + messageModule.setResetPasswordEnabled(resetPasswordEl.isAtLeastSelected(1)); + } + super.formInnerEvent(ureq, source, event); + } + + @Override + protected void formOK(UserRequest ureq) { + // + } + + + + +} diff --git a/src/main/java/org/olat/core/commons/services/sms/ui/SimpleMessageServiceAdminController.java b/src/main/java/org/olat/core/commons/services/sms/ui/SimpleMessageServiceAdminController.java new file mode 100644 index 00000000000..ed8f1511d78 --- /dev/null +++ b/src/main/java/org/olat/core/commons/services/sms/ui/SimpleMessageServiceAdminController.java @@ -0,0 +1,102 @@ +/** + * <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.core.commons.services.sms.ui; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.Component; +import org.olat.core.gui.components.link.Link; +import org.olat.core.gui.components.link.LinkFactory; +import org.olat.core.gui.components.segmentedview.SegmentViewComponent; +import org.olat.core.gui.components.segmentedview.SegmentViewEvent; +import org.olat.core.gui.components.segmentedview.SegmentViewFactory; +import org.olat.core.gui.components.velocity.VelocityContainer; +import org.olat.core.gui.control.Event; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.gui.control.controller.BasicController; + +/** + * + * Initial date: 3 févr. 2017<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class SimpleMessageServiceAdminController extends BasicController { + + private final VelocityContainer mainVC; + private final SegmentViewComponent segmentView; + private final Link configurationLink, statisticsLink; + + private MessagesStatisticsController statisticsCtrl; + private SimpleMessageServiceAdminConfigurationController configCtrl; + + public SimpleMessageServiceAdminController(UserRequest ureq, WindowControl wControl) { + super(ureq, wControl); + + mainVC = createVelocityContainer("admin"); + + segmentView = SegmentViewFactory.createSegmentView("segments", mainVC, this); + segmentView.setReselect(true); + + configurationLink = LinkFactory.createLink("admin.settings", mainVC, this); + segmentView.addSegment(configurationLink, true); + statisticsLink = LinkFactory.createLink("admin.statistics", mainVC, this); + segmentView.addSegment(statisticsLink, false); + + doOpenConfiguration(ureq); + putInitialPanel(mainVC); + } + + @Override + protected void doDispose() { + // + } + + @Override + protected void event(UserRequest ureq, Component source, Event event) { + if(source == segmentView) { + if(event instanceof SegmentViewEvent) { + SegmentViewEvent sve = (SegmentViewEvent)event; + String segmentCName = sve.getComponentName(); + Component clickedLink = mainVC.getComponent(segmentCName); + if (clickedLink == configurationLink) { + doOpenConfiguration(ureq); + } else if (clickedLink == statisticsLink) { + doOpenStatistics(ureq); + } + } + } + } + + private void doOpenStatistics(UserRequest ureq) { + if(statisticsCtrl == null) { + statisticsCtrl = new MessagesStatisticsController(ureq, getWindowControl()); + listenTo(statisticsCtrl); + } + mainVC.put("segmentCmp", statisticsCtrl.getInitialComponent()); + } + + private void doOpenConfiguration(UserRequest ureq) { + if(configCtrl == null) { + configCtrl = new SimpleMessageServiceAdminConfigurationController(ureq, getWindowControl()); + listenTo(configCtrl); + } + mainVC.put("segmentCmp", configCtrl.getInitialComponent()); + } +} diff --git a/src/main/java/org/olat/core/commons/services/sms/ui/YearCellRenderer.java b/src/main/java/org/olat/core/commons/services/sms/ui/YearCellRenderer.java new file mode 100644 index 00000000000..70bbf4e5567 --- /dev/null +++ b/src/main/java/org/olat/core/commons/services/sms/ui/YearCellRenderer.java @@ -0,0 +1,30 @@ +package org.olat.core.commons.services.sms.ui; + +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiCellRenderer; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableComponent; +import org.olat.core.gui.render.Renderer; +import org.olat.core.gui.render.StringOutput; +import org.olat.core.gui.render.URLBuilder; +import org.olat.core.gui.translator.Translator; + +/** + * + * Initial date: 7 févr. 2017<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class YearCellRenderer implements FlexiCellRenderer { + + private static final SimpleDateFormat format = new SimpleDateFormat("yyyy"); + + @Override + public void render(Renderer renderer, StringOutput target, Object cellValue, int row, FlexiTableComponent source, + URLBuilder ubu, Translator translator) { + if(cellValue instanceof Date) { + target.append(format.format((Date)cellValue)); + } + } +} diff --git a/src/main/java/org/olat/core/commons/services/sms/ui/_content/admin.html b/src/main/java/org/olat/core/commons/services/sms/ui/_content/admin.html new file mode 100644 index 00000000000..c0fa0f020aa --- /dev/null +++ b/src/main/java/org/olat/core/commons/services/sms/ui/_content/admin.html @@ -0,0 +1,4 @@ +$r.render("segments") +<div class="o_segments_content clearfix"> + $r.render("segmentCmp") +</div> \ No newline at end of file diff --git a/src/main/java/org/olat/core/commons/services/sms/ui/_content/statistics.html b/src/main/java/org/olat/core/commons/services/sms/ui/_content/statistics.html new file mode 100644 index 00000000000..9701851200f --- /dev/null +++ b/src/main/java/org/olat/core/commons/services/sms/ui/_content/statistics.html @@ -0,0 +1 @@ +$r.render("stats") \ No newline at end of file diff --git a/src/main/java/org/olat/core/commons/services/sms/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/core/commons/services/sms/ui/_i18n/LocalStrings_de.properties new file mode 100644 index 00000000000..d804ec7e955 --- /dev/null +++ b/src/main/java/org/olat/core/commons/services/sms/ui/_i18n/LocalStrings_de.properties @@ -0,0 +1,25 @@ +#Tue Feb 07 13:58:37 CET 2017 +admin.configuration.description=<p>Benarchitugung per SMS ist eine optionale Komponente.</p><p>Achtung\: durch das Versenden von SMS entstehen Kosten pro SMS\!</p> +admin.configuration.title=SMS Konfiguration +admin.enable=SMS Versand +admin.menu.title=SMS +admin.menu.title.alt=SMS Konfiguration udn Statistik +admin.settings=SMS Dienst Konfiguration +admin.statistics=SMS Versand +confirm.sms.phone=<h3>SMS Authentifizierung</h3><p>Das System erm\u00F6glicht eine Authentifizierung \u00FCber SMS um ein verlorenes Passwort zur\u00FCcksetzen. Bitte geben Sie Ihre Mobile telefonnummer an um diesen Dienst zu aktivieren</p> +dont.activate=Nicht aktivieren +error.invalid.token=Token stimmt nicht\! +error.phone.invalid=Das Nummer ist nicht valid (z.B. +41 12 345 67 89) +on=ein +on.sms=mit SMS Code +reset.password=Password zur\u00FCcksetzen +service=Dienst +sms.phone.number=Telephon Mobil +sms.phone.number.hint=+41 12 345 67 89 +sms.token=Ihr Token ist {0} +sms.token.number=Token +sms.token.number.explain=Bitte geben Sie den 6 stellige Nummer ein dass Sie per SMS bekommen haben. +table.header.month=Monat +table.header.numOfMessages=SMS +table.header.year=Jahr +warning.spi.not.configured=Dienst ist nicht konfiguriert diff --git a/src/main/java/org/olat/core/commons/services/sms/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/core/commons/services/sms/ui/_i18n/LocalStrings_en.properties new file mode 100644 index 00000000000..5e77f2caa27 --- /dev/null +++ b/src/main/java/org/olat/core/commons/services/sms/ui/_i18n/LocalStrings_en.properties @@ -0,0 +1,25 @@ +#Tue Feb 07 13:47:28 CET 2017 +admin.configuration.description=<p>Notification with SMS is an optional component.</p><p>Warning\: SMS costs iccurend per SMS\!</p> +admin.configuration.title=SMS configuration +admin.enable=SMS distribution +admin.menu.title=SMS +admin.menu.title.alt=SMS configuration and statistics +admin.settings=SMS service configuration +admin.statistics=SMS distribution +confirm.sms.phone=<h3>SMS Authentication</h3><p>The system allows to authenticate via SMS to reset a lost password. Please enter your mobile phone number to activate this service.</p> +dont.activate=Don't activate +error.invalid.token=The code is not valid. +error.phone.invalid=The number is not a valid phone number (e.g. +41 12 345 67 89) +on=on +on.sms=with SMS code +reset.password=Reset password +service=Service +sms.phone.number=Mobile telefon +sms.phone.number.hint=+41 12 345 67 89 +sms.token=Your token is {0} +sms.token.number=Code +sms.token.number.explain=Please enter the 6 digit number that you received by SMS. +table.header.month=Month +table.header.numOfMessages=SMS +table.header.year=Year +warning.spi.not.configured=The service is not configured. diff --git a/src/main/java/org/olat/core/commons/services/sms/ui/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/core/commons/services/sms/ui/_i18n/LocalStrings_fr.properties new file mode 100644 index 00000000000..ba90e09bcb5 --- /dev/null +++ b/src/main/java/org/olat/core/commons/services/sms/ui/_i18n/LocalStrings_fr.properties @@ -0,0 +1 @@ +#Sun Sep 05 15:41:48 CEST 2010 diff --git a/src/main/java/org/olat/core/id/UserConstants.java b/src/main/java/org/olat/core/id/UserConstants.java index 271f211ef56..e9399883c8e 100644 --- a/src/main/java/org/olat/core/id/UserConstants.java +++ b/src/main/java/org/olat/core/id/UserConstants.java @@ -44,6 +44,8 @@ public class UserConstants { public static final String TELOFFICE = "telOffice"; /** TELPRIVATE user field identifier. */ public static final String TELPRIVATE = "telPrivate"; + /** TELMOBILE user field identifier. */ + public static final String SMSTELMOBILE = "smsTelMobile"; /** SKYPE user field identifier. */ public static final String SKYPE = "skype"; /** HOMEPAGE user field identifier. */ diff --git a/src/main/java/org/olat/course/nodes/cl/ui/CheckboxAssessmentDataModelSorter.java b/src/main/java/org/olat/course/nodes/cl/ui/CheckboxAssessmentDataModelSorter.java index 657ca3acb19..c4764e12b20 100644 --- a/src/main/java/org/olat/course/nodes/cl/ui/CheckboxAssessmentDataModelSorter.java +++ b/src/main/java/org/olat/course/nodes/cl/ui/CheckboxAssessmentDataModelSorter.java @@ -1,3 +1,22 @@ +/** + * <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.course.nodes.cl.ui; import java.util.Collections; diff --git a/src/main/java/org/olat/ldap/ui/LDAPAuthenticationController.java b/src/main/java/org/olat/ldap/ui/LDAPAuthenticationController.java index dccad37ca9f..c7a0c5008e0 100644 --- a/src/main/java/org/olat/ldap/ui/LDAPAuthenticationController.java +++ b/src/main/java/org/olat/ldap/ui/LDAPAuthenticationController.java @@ -100,11 +100,11 @@ public class LDAPAuthenticationController extends AuthenticationController imple loginComp = createVelocityContainer("ldaplogin"); if(userModule.isAnyPasswordChangeAllowed() && ldapLoginModule.isPropagatePasswordChangedOnLdapServer()) { - Link link = LinkFactory.createLink("_olat_login_change_pwd", "menu.pw", loginComp, this); + Link link = LinkFactory.createLink("_ldap_login_change_pwd", "menu.pw", loginComp, this); link.setElementCssClass("o_login_pwd"); pwLink = link; } else if(StringHelper.containsNonWhitespace(ldapLoginModule.getChangePasswordUrl())) { - ExternalLink link = new ExternalLink("_olat_login_change_pwd", "menu.pw"); + ExternalLink link = new ExternalLink("_ldap_login_change_pwd", "menu.pw"); link.setElementCssClass("o_login_pwd"); link.setName(translate("menu.pw")); link.setUrl(ldapLoginModule.getChangePasswordUrl()); diff --git a/src/main/java/org/olat/login/LoginAuthprovidersController.java b/src/main/java/org/olat/login/LoginAuthprovidersController.java index 8c75e4a99f7..08a57b79b85 100644 --- a/src/main/java/org/olat/login/LoginAuthprovidersController.java +++ b/src/main/java/org/olat/login/LoginAuthprovidersController.java @@ -166,7 +166,7 @@ public class LoginAuthprovidersController extends MainLayoutBasicController impl contentBorn.put("loginComp", authController.getInitialComponent()); contentBorn.contextPut("currentProvider", authProvider.getName()); Collection<AuthenticationProvider> providers = loginModule.getAuthenticationProviders(); - List<AuthenticationProvider> providerSet = new ArrayList<AuthenticationProvider>(providers.size()); + List<AuthenticationProvider> providerSet = new ArrayList<>(providers.size()); int count = 0; for (AuthenticationProvider prov : providers) { if (prov.isEnabled()) { diff --git a/src/main/java/org/olat/login/auth/OLATAuthManager.java b/src/main/java/org/olat/login/auth/OLATAuthManager.java index 0be2fda87cc..28a048251eb 100644 --- a/src/main/java/org/olat/login/auth/OLATAuthManager.java +++ b/src/main/java/org/olat/login/auth/OLATAuthManager.java @@ -31,7 +31,6 @@ import java.util.Map; import org.olat.basesecurity.Authentication; import org.olat.basesecurity.BaseSecurity; -import org.olat.core.CoreSpringFactory; import org.olat.core.commons.services.webdav.manager.WebDAVAuthManager; import org.olat.core.gui.translator.Translator; import org.olat.core.id.Identity; @@ -75,7 +74,7 @@ import com.thoughtworks.xstream.XStream; @Service("olatAuthenticationSpi") public class OLATAuthManager extends BasicManager implements AuthenticationSPI { - private static OLog log = Tracing.createLoggerFor(OLATAuthManager.class); + private static final OLog log = Tracing.createLoggerFor(OLATAuthManager.class); @Autowired private UserManager userManager; @@ -90,6 +89,8 @@ public class OLATAuthManager extends BasicManager implements AuthenticationSPI { @Autowired private LDAPLoginModule ldapLoginModule; @Autowired + private LDAPLoginManager ldapLoginManager; + @Autowired private RegistrationManager registrationManager; /** @@ -201,7 +202,6 @@ public class OLATAuthManager extends BasicManager implements AuthenticationSPI { if(ldapAuth != null) { if(ldapLoginModule.isPropagatePasswordChangedOnLdapServer()) { LDAPError ldapError = new LDAPError(); - LDAPLoginManager ldapLoginManager = (LDAPLoginManager) CoreSpringFactory.getBean("org.olat.ldap.LDAPLoginManager"); ldapLoginManager.changePassword(identity, newPwd, ldapError); log.audit(doer.getName() + " change the password on the LDAP server for identity: " + identity.getName()); allOk = ldapError.isEmpty(); @@ -229,7 +229,7 @@ public class OLATAuthManager extends BasicManager implements AuthenticationSPI { String[] args = new String[] { identity.getName(),//0: changed users username identity.getUser().getProperty(UserConstants.EMAIL, locale),// 1: changed users email address - UserManager.getInstance().getUserDisplayName(doer.getUser()),// 2: Name (first and last name) of user who changed the password + userManager.getUserDisplayName(doer.getUser()),// 2: Name (first and last name) of user who changed the password WebappHelper.getMailConfig("mailSupport"), //3: configured support email address changePwUrl //4: direct link to change password workflow (e.g. https://xx.xx.xx/olat/url/changepw/0) }; diff --git a/src/main/java/org/olat/registration/ConfirmTokenController.java b/src/main/java/org/olat/registration/ConfirmTokenController.java new file mode 100644 index 00000000000..8951e48e678 --- /dev/null +++ b/src/main/java/org/olat/registration/ConfirmTokenController.java @@ -0,0 +1,91 @@ +/** + * <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.TextElement; +import org.olat.core.gui.components.form.flexible.impl.FormBasicController; +import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer; +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.id.Identity; +import org.olat.core.util.StringHelper; + +/** + * + * Initial date: 6 févr. 2017<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class ConfirmTokenController extends FormBasicController { + + private TextElement tokenEl; + + private final String token; + private final Identity recipient; + + public ConfirmTokenController(UserRequest ureq, WindowControl wControl, Identity recipient, String token) { + super(ureq, wControl); + this.recipient = recipient; + this.token = token; + initForm(ureq); + } + + public Identity getRecipient() { + return recipient; + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + tokenEl = uifactory.addTextElement("token", "pw.change.confirm.token", 32, "", formLayout); + + FormLayoutContainer buttonsCont = FormLayoutContainer.createButtonLayout("buttons", getTranslator()); + formLayout.add(buttonsCont); + uifactory.addFormSubmitButton("pw.change.confirm", buttonsCont); + } + + @Override + protected void doDispose() { + // + } + + @Override + protected boolean validateFormLogic(UserRequest ureq) { + boolean allOk = true; + + if(StringHelper.containsNonWhitespace(tokenEl.getValue())) { + if(!tokenEl.getValue().equals(token)) { + tokenEl.setErrorKey("error.pw.change.confirm.token", null); + allOk &= false; + } + } else { + tokenEl.setErrorKey("form.legende.mandatory", null); + allOk &= false; + } + return allOk & super.validateFormLogic(ureq); + } + + @Override + protected void formOK(UserRequest ureq) { + fireEvent(ureq, Event.DONE_EVENT); + } +} diff --git a/src/main/java/org/olat/registration/PwChangeController.java b/src/main/java/org/olat/registration/PwChangeController.java index d15a9a5e0a5..bc821f63779 100644 --- a/src/main/java/org/olat/registration/PwChangeController.java +++ b/src/main/java/org/olat/registration/PwChangeController.java @@ -32,10 +32,10 @@ import java.util.List; import java.util.Locale; import org.olat.basesecurity.Authentication; -import org.olat.basesecurity.BaseSecurityManager; +import org.olat.basesecurity.BaseSecurity; import org.olat.basesecurity.BaseSecurityModule; -import org.olat.core.CoreSpringFactory; import org.olat.core.commons.fullWebApp.LayoutMain3ColsController; +import org.olat.core.commons.services.sms.SimpleMessageModule; import org.olat.core.dispatcher.DispatcherModule; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.Component; @@ -53,6 +53,7 @@ import org.olat.core.helpers.Settings; import org.olat.core.id.Identity; import org.olat.core.id.Preferences; import org.olat.core.id.UserConstants; +import org.olat.core.util.StringHelper; import org.olat.core.util.Util; import org.olat.core.util.i18n.I18nManager; import org.olat.core.util.mail.MailBundle; @@ -72,23 +73,32 @@ import org.springframework.beans.factory.annotation.Autowired; public class PwChangeController extends BasicController { private static String SEPARATOR = "____________________________________________________________________\n"; - private VelocityContainer myContent; + + private Panel passwordPanel; + private Link pwchangeHomelink; + private final VelocityContainer myContent; - private Panel pwarea; - private WizardInfoController wic; - private final MailManager mailManager; - private String pwKey; private PwChangeForm pwf; - private TemporaryKeyImpl tempKey; + private WizardInfoController wic; + private SendMessageController sendSmsCtr; + private ConfirmTokenController confirmTokenCtr; private EmailOrUsernameFormController emailOrUsernameCtr; - private Link pwchangeHomelink; + + private String pwKey; + private TemporaryKey tempKey; @Autowired private UserModule userModule; @Autowired private RegistrationManager rm; @Autowired + private MailManager mailManager; + @Autowired private UserManager userManager; + @Autowired + private BaseSecurity securityManager; + @Autowired + private SimpleMessageModule smsModule; /** * Controller to change a user's password. @@ -106,38 +116,34 @@ public class PwChangeController extends BasicController { */ public PwChangeController(UserRequest ureq, WindowControl wControl, String initialEmail, boolean modal) { super(ureq, wControl); - mailManager = CoreSpringFactory.getImpl(MailManager.class); myContent = createVelocityContainer("pwchange"); wic = new WizardInfoController(ureq, 4); myContent.put("pwwizard", wic.getInitialComponent()); - pwarea = new Panel("pwarea"); - myContent.put("pwarea", pwarea); + passwordPanel = new Panel("pwarea"); + myContent.put("pwarea", passwordPanel); pwKey = ureq.getHttpReq().getParameter("key"); - if (pwKey == null || pwKey.equals("")) { - // no temporarykey is given, we assume step 1 - createEmailForm(ureq, wControl, initialEmail); - } else { + + if (StringHelper.containsNonWhitespace(pwKey)) { // we check if given key is a valid temporary key tempKey = rm.loadTemporaryKeyByRegistrationKey(pwKey); // if key is not valid we redirect to first page if (tempKey == null) { // error, there should be an entry - getWindowControl().setError(translate("pwkey.missingentry")); + showError("pwkey.missingentry"); createEmailForm(ureq, wControl, initialEmail); } else { - wic.setCurStep(3); - pwf = new PwChangeForm(ureq, wControl); - listenTo(pwf); - myContent.contextPut("pwdhelp", translate("pwdhelp")); - myContent.contextPut("text", translate("step3.pw.text")); - pwarea.setContent(pwf.getInitialComponent()); + showChangePasswordForm(ureq, tempKey); } + } else { + // no temporarykey is given, we assume step 1 + createEmailForm(ureq, wControl, initialEmail); } if(modal) { putInitialPanel(myContent); } else { LayoutMain3ColsController layoutCtr = new LayoutMain3ColsController(ureq, getWindowControl(), null, myContent, null); + listenTo(layoutCtr); putInitialPanel(layoutCtr.getInitialComponent()); } } @@ -147,144 +153,204 @@ public class PwChangeController extends BasicController { } /** - * just needed for creating EmailForm + * Create the email / username form, the first step of the workflow. */ - //fxdiff FXOLAT-113: business path in DMZ private void createEmailForm(UserRequest ureq, WindowControl wControl, String initialEmail) { myContent.contextPut("title", translate("step1.pw.title")); myContent.contextPut("text", translate("step1.pw.text")); removeAsListenerAndDispose(emailOrUsernameCtr); emailOrUsernameCtr = new EmailOrUsernameFormController(ureq, wControl, initialEmail); listenTo(emailOrUsernameCtr); - pwarea.setContent(emailOrUsernameCtr.getInitialComponent()); + passwordPanel.setContent(emailOrUsernameCtr.getInitialComponent()); } - /** - * @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 public void event(UserRequest ureq, Component source, Event event) { if (source == pwchangeHomelink) { DispatcherModule.redirectToDefaultDispatcher(ureq.getHttpResp()); } } - /** - * @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 == pwf) { // pwchange Form was clicked if (event == Event.DONE_EVENT) { // form - // validation was ok - wic.setCurStep(4); - myContent.contextPut("pwdhelp", ""); - myContent.contextPut("text", translate("step4.pw.text")); - pwchangeHomelink = LinkFactory.createLink("pwchange.homelink", myContent, this); - pwchangeHomelink.setCustomEnabledLinkCSS("btn btn-primary"); - //pwf.setVisible(false); - pwarea.setVisible(false); - List<Identity> identToChanges = userManager.findIdentitiesByEmail(Collections.singletonList(tempKey.getEmailAddress())); - if(identToChanges == null || identToChanges.size() == 0 || identToChanges.size() > 1) { - getWindowControl().setError(translate("pwchange.failed")); - } else { - Identity identToChange = identToChanges.get(0); - if(!pwf.saveFormData(identToChange)) { - getWindowControl().setError(translate("pwchange.failed")); - } - } - rm.deleteTemporaryKeyWithId(tempKey.getRegistrationKey()); + showChangePasswordEnd(); } else if (event == Event.CANCELLED_EVENT) { - getWindowControl().setInfo(translate("pwform.cancelled")); + showInfo("pwform.cancelled"); fireEvent(ureq, Event.CANCELLED_EVENT); } } else if (source == emailOrUsernameCtr) { // eMail Form was clicked if (event == Event.DONE_EVENT) { // form - // Email requested for tempkey save the fields somewhere - String emailOrUsername = emailOrUsernameCtr.getEmailOrUsername(); - emailOrUsername = emailOrUsername.trim(); - - // get remote address - String ip = ureq.getHttpReq().getRemoteAddr(); - String today = DateFormat.getDateInstance(DateFormat.LONG, ureq.getLocale()).format(new Date()); - // mailer configuration - String serverpath = Settings.getServerContextPathURI(); - String servername = ureq.getHttpReq().getServerName(); - if(isLogDebugEnabled()) { - logDebug("this servername is " + servername + " and serverpath is " + serverpath, null); - } + doProcessEmailOrUsername(ureq); + } else if (event == Event.CANCELLED_EVENT) { + fireEvent(ureq, Event.CANCELLED_EVENT); + } + } else if (source == sendSmsCtr) { + if (event == Event.DONE_EVENT) { // form + doConfirmSendToken(ureq, sendSmsCtr.getRecipient(), sendSmsCtr.getSentToken()); + } else if (event == Event.CANCELLED_EVENT) { + fireEvent(ureq, Event.CANCELLED_EVENT); + } + } else if(source == confirmTokenCtr) { + if (event == Event.DONE_EVENT) { // form + showChangePasswordForm(ureq, confirmTokenCtr.getRecipient()); + } else if (event == Event.CANCELLED_EVENT) { + fireEvent(ureq, Event.CANCELLED_EVENT); + } + } + } + + private void doProcessEmailOrUsername(UserRequest ureq) { + // Email requested for tempkey save the fields somewhere + String emailOrUsername = emailOrUsernameCtr.getEmailOrUsername(); + emailOrUsername = emailOrUsername.trim(); - // Look for user in "Person" and "user" tables - Identity identity = null; - // See if the entered value is a username - identity = BaseSecurityManager.getInstance().findIdentityByName(emailOrUsername); - if (identity == null) { - // Try fallback with email, maybe user used his email address instead - // only do this, if its really an email, may lead to multiple results else. - if (MailHelper.isValidEmailAddress(emailOrUsername)) { - List<Identity> identities = userManager.findIdentitiesByEmail(Collections.singletonList(emailOrUsername)); - if(identities.size() == 1) { - identity = identities.get(0); - } - } - } - if (identity != null) { - // check if user has an OLAT provider token, otherwhise a pwd change makes no sense - Authentication auth = BaseSecurityManager.getInstance().findAuthentication(identity, BaseSecurityModule.getDefaultAuthProviderIdentifier()); - if (auth == null || !userModule.isPwdChangeAllowed(identity)) { - getWindowControl().setWarning(translate("password.cantchange")); - return; - } - Preferences prefs = identity.getUser().getPreferences(); - Locale locale = I18nManager.getInstance().getLocaleOrDefault(prefs.getLanguage()); - ureq.getUserSession().setLocale(locale); - myContent.contextPut("locale", locale); - Translator userTrans = Util.createPackageTranslator(PwChangeController.class, locale) ; - String emailAdress = identity.getUser().getProperty(UserConstants.EMAIL, locale); - TemporaryKey tk = rm.loadTemporaryKeyByEmail(emailAdress); - if (tk == null) tk = rm.createTemporaryKeyByEmail(emailAdress, ip, RegistrationManager.PW_CHANGE); - myContent.contextPut("pwKey", tk.getRegistrationKey()); - StringBuilder body = new StringBuilder(); - body.append(userTrans.translate("pwchange.intro", new String[] { identity.getName() })) - .append(userTrans.translate("pwchange.body", new String[] { serverpath, tk.getRegistrationKey(), I18nManager.getInstance().getLocaleKey(ureq.getLocale()) })) - .append(SEPARATOR) - .append(userTrans.translate("reg.wherefrom", new String[] { serverpath, today, ip })); + Identity identity = findIdentityByUsernameOrEmail(emailOrUsername); + if (identity != null) { + if(smsModule.isEnabled() && smsModule.isResetPasswordEnabled() + && StringHelper.containsNonWhitespace(identity.getUser().getProperty(UserConstants.SMSTELMOBILE, getLocale()))) { + tempKey = sendEmail(ureq, identity); + sendSms(ureq, identity); + } else { + sendEmail(ureq, identity); + } + } else { + // no user exists, this is an error in the pwchange page + // REVIEW:pb:2009-11-23:gw, setter should not be necessary. -> check the error already in th emailOrUsernameCtr + emailOrUsernameCtr.setUserNotIdentifiedError(); + } + } + + private void sendSms(UserRequest ureq, Identity recipient) { + removeAsListenerAndDispose(sendSmsCtr); + + sendSmsCtr = new SendMessageController(ureq, getWindowControl(), recipient); + listenTo(sendSmsCtr); + passwordPanel.setContent(sendSmsCtr.getInitialComponent()); + + wic.setCurStep(2); + myContent.contextPut("text", translate("step2.pw.text")); + } + + private void doConfirmSendToken(UserRequest ureq, Identity recipient, String sentToken) { + confirmTokenCtr = new ConfirmTokenController(ureq, getWindowControl(), recipient, sentToken); + listenTo(confirmTokenCtr); + passwordPanel.setContent(confirmTokenCtr.getInitialComponent()); + + wic.setCurStep(3); + myContent.contextPut("text", translate("pw.change.confirm.descr")); + } + + private TemporaryKey sendEmail(UserRequest ureq, Identity identity) { + // check if user has an OLAT provider token, otherwhise a pwd change makes no sense + Authentication auth = securityManager.findAuthentication(identity, BaseSecurityModule.getDefaultAuthProviderIdentifier()); + if (auth == null || !userModule.isPwdChangeAllowed(identity)) { + getWindowControl().setWarning(translate("password.cantchange")); + return null; + } + Preferences prefs = identity.getUser().getPreferences(); + Locale locale = I18nManager.getInstance().getLocaleOrDefault(prefs.getLanguage()); + ureq.getUserSession().setLocale(locale); + myContent.contextPut("locale", locale); + + Translator userTrans = Util.createPackageTranslator(PwChangeController.class, locale) ; + String emailAdress = identity.getUser().getProperty(UserConstants.EMAIL, locale); + + // get remote address + String ip = ureq.getHttpReq().getRemoteAddr(); + String today = DateFormat.getDateInstance(DateFormat.LONG, ureq.getLocale()).format(new Date()); + // mailer configuration + String serverpath = Settings.getServerContextPathURI(); - MailBundle bundle = new MailBundle(); - bundle.setToId(identity); - bundle.setContent(userTrans.translate("pwchange.subject"), body.toString()); - MailerResult result = mailManager.sendExternMessage(bundle, null, false); - if(result.getReturnCode() == 0) { - getWindowControl().setInfo(translate("email.sent")); - // prepare next step - wic.setCurStep(2); - myContent.contextPut("text", translate("step2.pw.text")); - emailOrUsernameCtr.getInitialComponent().setVisible(false); - } else { - getWindowControl().setError(translate("email.notsent")); - } - } else { - // no user exists, this is an error in the pwchange page - // REVIEW:pb:2009-11-23:gw, setter should not be necessary. -> check the error already in th emailOrUsernameCtr - emailOrUsernameCtr.setUserNotIdentifiedError(); + TemporaryKey tk = rm.loadTemporaryKeyByEmail(emailAdress); + if (tk == null) { + tk = rm.createTemporaryKeyByEmail(emailAdress, ip, RegistrationManager.PW_CHANGE); + } + myContent.contextPut("pwKey", tk.getRegistrationKey()); + StringBuilder body = new StringBuilder(); + body.append(userTrans.translate("pwchange.intro", new String[] { identity.getName() })) + .append(userTrans.translate("pwchange.body", new String[] { serverpath, tk.getRegistrationKey(), I18nManager.getInstance().getLocaleKey(ureq.getLocale()) })) + .append(SEPARATOR) + .append(userTrans.translate("reg.wherefrom", new String[] { serverpath, today, ip })); + + MailBundle bundle = new MailBundle(); + bundle.setToId(identity); + bundle.setContent(userTrans.translate("pwchange.subject"), body.toString()); + MailerResult result = mailManager.sendExternMessage(bundle, null, false); + if(result.getReturnCode() == MailerResult.OK) { + getWindowControl().setInfo(translate("email.sent")); + // prepare next step + wic.setCurStep(2); + myContent.contextPut("text", translate("step2.pw.text")); + emailOrUsernameCtr.getInitialComponent().setVisible(false); + } else { + showError("email.notsent"); + } + return tk; + } + + /** + * Look for user in "Person" and "user" tables. Fist search by user name + * and if the user cannot be found, search by email address. + * @return Identity or null if not found. + */ + private Identity findIdentityByUsernameOrEmail(String emailOrUsername) { + // See if the entered value is a username + Identity identity = securityManager.findIdentityByName(emailOrUsername); + if (identity == null) { + // Try fallback with email, maybe user used his email address instead + // only do this, if its really an email, may lead to multiple results else. + if (MailHelper.isValidEmailAddress(emailOrUsername)) { + List<Identity> identities = userManager.findIdentitiesByEmail(Collections.singletonList(emailOrUsername)); + if(identities.size() == 1) { + identity = identities.get(0); } - } else if (event == Event.CANCELLED_EVENT) { - fireEvent(ureq, Event.CANCELLED_EVENT); } - } + } + return identity; + } + + private void showChangePasswordForm(UserRequest ureq, TemporaryKey temporaryKey) { + wic.setCurStep(3); + pwf = new PwChangeForm(ureq, getWindowControl(), temporaryKey); + listenTo(pwf); + myContent.contextPut("pwdhelp", translate("pwdhelp")); + myContent.contextPut("text", translate("step3.pw.text")); + passwordPanel.setContent(pwf.getInitialComponent()); + } + + private void showChangePasswordForm(UserRequest ureq, Identity identityToChange) { + wic.setCurStep(3); + pwf = new PwChangeForm(ureq, getWindowControl(), identityToChange, tempKey); + listenTo(pwf); + myContent.contextPut("pwdhelp", translate("pwdhelp")); + myContent.contextPut("text", translate("step3.pw.text")); + passwordPanel.setContent(pwf.getInitialComponent()); } /** - * @see org.olat.core.gui.control.DefaultController#doDispose(boolean) + * Change the password of a confirmed identity (per SMS). + * + * @param identToChange The identity to change the password */ + private void showChangePasswordEnd() { + // validation was ok + wic.setCurStep(4); + myContent.contextPut("pwdhelp", ""); + myContent.contextPut("text", translate("step4.pw.text")); + pwchangeHomelink = LinkFactory.createLink("pwchange.homelink", myContent, this); + pwchangeHomelink.setCustomEnabledLinkCSS("btn btn-primary"); + passwordPanel.setVisible(false); + } + + @Override protected void doDispose() { if (wic != null) { wic.dispose(); wic = null; } } - } \ No newline at end of file diff --git a/src/main/java/org/olat/registration/PwChangeForm.java b/src/main/java/org/olat/registration/PwChangeForm.java index 9efcc534637..a798dd381da 100644 --- a/src/main/java/org/olat/registration/PwChangeForm.java +++ b/src/main/java/org/olat/registration/PwChangeForm.java @@ -25,7 +25,9 @@ package org.olat.registration; -import org.olat.core.CoreSpringFactory; +import java.util.Collections; +import java.util.List; + import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.FormItemContainer; import org.olat.core.gui.components.form.flexible.elements.TextElement; @@ -38,6 +40,7 @@ import org.olat.core.util.Util; import org.olat.login.auth.OLATAuthManager; import org.olat.user.ChangePasswordForm; import org.olat.user.UserManager; +import org.springframework.beans.factory.annotation.Autowired; /** * Description: @@ -49,24 +52,41 @@ public class PwChangeForm extends FormBasicController { private TextElement newpass1; private TextElement newpass2; // confirm - private final OLATAuthManager olatAuthenticationSpi; + private TemporaryKey tempKey; + private Identity identityToChange; + + @Autowired + private RegistrationManager rm; + @Autowired + private UserManager userManager; + @Autowired + private OLATAuthManager olatAuthenticationSpi; /** * Password change form. * @param name */ - public PwChangeForm(UserRequest ureq, WindowControl wControl) { + public PwChangeForm(UserRequest ureq, WindowControl wControl, Identity identityToChange, TemporaryKey tempKey) { super(ureq, wControl, null, Util.createPackageTranslator(ChangePasswordForm.class, ureq.getLocale())); - - olatAuthenticationSpi = CoreSpringFactory.getImpl(OLATAuthManager.class); - + this.identityToChange = identityToChange; + this.tempKey = tempKey; + initForm(ureq); + } + + /** + * Password change form. + * @param name + */ + public PwChangeForm(UserRequest ureq, WindowControl wControl, TemporaryKey tempKey) { + super(ureq, wControl, null, Util.createPackageTranslator(ChangePasswordForm.class, ureq.getLocale())); + this.tempKey = tempKey; initForm(ureq); } @Override public boolean validateFormLogic(UserRequest ureq) { - boolean newIsValid = UserManager.getInstance().syntaxCheckOlatPassword(newpass1.getValue()); + boolean newIsValid = userManager.syntaxCheckOlatPassword(newpass1.getValue()); if (!newIsValid) { newpass1.setErrorKey("form.checkPassword", null); } @@ -90,6 +110,24 @@ public class PwChangeForm extends FormBasicController { @Override protected void formOK(UserRequest ureq) { + if(tempKey != null) { + List<Identity> identToChanges = userManager.findIdentitiesByEmail(Collections.singletonList(tempKey.getEmailAddress())); + if(identToChanges == null || identToChanges.size() == 0 || identToChanges.size() > 1) { + showError("pwchange.failed"); + } else { + Identity identToChange = identToChanges.get(0); + if(!saveFormData(identToChange)) { + showError("pwchange.failed"); + } + } + } else if(identityToChange != null) { + if(!saveFormData(identityToChange)) { + showError("pwchange.failed"); + } + } + if(tempKey != null) { + rm.deleteTemporaryKeyWithId(tempKey.getRegistrationKey()); + } fireEvent (ureq, Event.DONE_EVENT); } diff --git a/src/main/java/org/olat/registration/RegistrationController.java b/src/main/java/org/olat/registration/RegistrationController.java index db4cc5c3b4d..b37da45a021 100644 --- a/src/main/java/org/olat/registration/RegistrationController.java +++ b/src/main/java/org/olat/registration/RegistrationController.java @@ -95,7 +95,7 @@ public class RegistrationController extends BasicController implements Activatea private RegistrationForm2 registrationForm; private LanguageChooserController langChooserController; private String uniqueRegistrationKey; - private TemporaryKeyImpl tempKey; + private TemporaryKey tempKey; @Autowired private I18nManager i18nManager; diff --git a/src/main/java/org/olat/registration/RegistrationManager.java b/src/main/java/org/olat/registration/RegistrationManager.java index 8ad83280364..b8115355c1b 100644 --- a/src/main/java/org/olat/registration/RegistrationManager.java +++ b/src/main/java/org/olat/registration/RegistrationManager.java @@ -43,7 +43,8 @@ import org.olat.core.helpers.Settings; import org.olat.core.id.Identity; import org.olat.core.id.User; import org.olat.core.id.UserConstants; -import org.olat.core.manager.BasicManager; +import org.olat.core.logging.OLog; +import org.olat.core.logging.Tracing; import org.olat.core.util.Encoder; import org.olat.core.util.StringHelper; import org.olat.core.util.Util; @@ -62,13 +63,14 @@ import org.springframework.stereotype.Service; * @author Sabina Jeger */ @Service("selfRegistrationManager") -public class RegistrationManager extends BasicManager { +public class RegistrationManager { + + private static final OLog log = Tracing.createLoggerFor(RegistrationManager.class); public static final String PW_CHANGE = "PW_CHANGE"; - public static final String REGISTRATION = "REGISTRATION";//fxdiff FXOLAT-113: business path in DMZ + public static final String REGISTRATION = "REGISTRATION"; public static final String EMAIL_CHANGE = "EMAIL_CHANGE"; protected static final int REG_WORKFLOW_STEPS = 5; - protected static final int PWCHANGE_WORKFLOW_STEPS = 4; @Autowired private DB dbInstance; @@ -106,7 +108,7 @@ public class RegistrationManager extends BasicManager { break; } } catch (Exception e) { - logError("Error matching an email adress", e); + log.error("Error matching an email adress", e); } } return valid; @@ -130,7 +132,7 @@ public class RegistrationManager extends BasicManager { emailDomain.matches(pattern); } catch (Exception e) { errors.add(domain); - logError("Error matching an email adress", e); + log.error("Error matching an email adress", e); } } return errors; @@ -153,7 +155,7 @@ public class RegistrationManager extends BasicManager { * @param tk Temporary key * @return the newly created subject or null */ - public Identity createNewUserAndIdentityFromTemporaryKey(String login, String pwd, User myUser, TemporaryKeyImpl tk) { + public Identity createNewUserAndIdentityFromTemporaryKey(String login, String pwd, User myUser, TemporaryKey tk) { Identity identity = securityManager.createAndPersistIdentityAndUserWithDefaultProviderAndUserGroup(login, null, pwd, myUser); if (identity == null) return null; deleteTemporaryKey(tk); @@ -174,7 +176,7 @@ public class RegistrationManager extends BasicManager { from = new InternetAddress(WebappHelper.getMailConfig("mailReplyTo")); to = new Address[] { new InternetAddress(notificationMailAddress)}; } catch (AddressException e) { - logError("Could not send registration notification message, bad mail address", e); + log.error("Could not send registration notification message, bad mail address", e); return; } MailerResult result = new MailerResult(); @@ -189,7 +191,7 @@ public class RegistrationManager extends BasicManager { MimeMessage msg = mailManager.createMimeMessage(from, to, null, null, body, subject, null, result); mailManager.sendMessage(msg, result); if (result.getReturnCode() != MailerResult.OK ) { - logError("Could not send registration notification message, MailerResult was ::" + result.getReturnCode(), null); + log.error("Could not send registration notification message, MailerResult was ::" + result.getReturnCode(), null); } } @@ -202,16 +204,14 @@ public class RegistrationManager extends BasicManager { * * @return TemporaryKey */ - public TemporaryKeyImpl createTemporaryKeyByEmail(String email, String ip, String action) { + public TemporaryKey createTemporaryKeyByEmail(String email, String ip, String action) { // check if the user is already registered // we also try to find it in the temporarykey list - String q = "select r from org.olat.registration.TemporaryKeyImpl as r where r.emailAddress = :email"; - List<TemporaryKeyImpl> tks = dbInstance.getCurrentEntityManager() - .createQuery(q, TemporaryKeyImpl.class) + List<TemporaryKey> tks = dbInstance.getCurrentEntityManager() + .createNamedQuery("loadTemporaryKeyByEmailAddress", TemporaryKey.class) .setParameter("email", email) .getResultList(); - - TemporaryKeyImpl tk = null; + TemporaryKey tk; if ((tks == null) || (tks.size() != 1)) { // no user found, create a new one tk = register(email, ip, action); } else { @@ -227,7 +227,7 @@ public class RegistrationManager extends BasicManager { * * @return true if successfully deleted */ - public void deleteTemporaryKey(TemporaryKeyImpl key) { + public void deleteTemporaryKey(TemporaryKey key) { TemporaryKeyImpl reloadedKey = dbInstance.getCurrentEntityManager() .getReference(TemporaryKeyImpl.class, key.getKey()); dbInstance.getCurrentEntityManager().remove(reloadedKey); @@ -241,13 +241,11 @@ public class RegistrationManager extends BasicManager { * * @return the found temporary key or null if none is found */ - public TemporaryKeyImpl loadTemporaryKeyByEmail(String email) { - String q = "select r from r in class org.olat.registration.TemporaryKeyImpl where r.emailAddress =:email"; - List<TemporaryKeyImpl> tks = dbInstance.getCurrentEntityManager() - .createQuery(q, TemporaryKeyImpl.class) + public TemporaryKey loadTemporaryKeyByEmail(String email) { + List<TemporaryKey> tks = dbInstance.getCurrentEntityManager() + .createNamedQuery("loadTemporaryKeyByEmailAddress", TemporaryKey.class) .setParameter("email", email) .getResultList(); - if (tks.size() == 1) { return tks.get(0); } @@ -263,12 +261,10 @@ public class RegistrationManager extends BasicManager { * @return the found temporary key or null if none is found */ public List<TemporaryKey> loadTemporaryKeyByAction(String action) { - String q = "select r from r in class org.olat.registration.TemporaryKeyImpl where r.regAction = :action"; List<TemporaryKey> tks = dbInstance.getCurrentEntityManager() - .createQuery(q, TemporaryKey.class) + .createNamedQuery("loadTemporaryKeyByRegAction", TemporaryKey.class) .setParameter("action", action) .getResultList(); - if (tks.size() > 0) { return tks; } else { @@ -283,10 +279,9 @@ public class RegistrationManager extends BasicManager { * * @return the found TemporaryKey or null if none is found */ - public TemporaryKeyImpl loadTemporaryKeyByRegistrationKey(String regkey) { - String q = "select r from r in class org.olat.registration.TemporaryKeyImpl where r.registrationKey = :regkey"; - List<TemporaryKeyImpl> tks = dbInstance.getCurrentEntityManager() - .createQuery(q, TemporaryKeyImpl.class) + public TemporaryKey loadTemporaryKeyByRegistrationKey(String regkey) { + List<TemporaryKey> tks = dbInstance.getCurrentEntityManager() + .createNamedQuery("loadTemporaryKeyByRegKey", TemporaryKey.class) .setParameter("regkey", regkey) .getResultList(); @@ -305,10 +300,15 @@ public class RegistrationManager extends BasicManager { * * @return newly created temporary key */ - public TemporaryKeyImpl register(String emailaddress, String ipaddress, String action) { + public TemporaryKey register(String emailaddress, String ipaddress, String action) { String today = new Date().toString(); String encryptMe = Encoder.md5hash(emailaddress + ipaddress + today); - TemporaryKeyImpl tk = new TemporaryKeyImpl(emailaddress, ipaddress, encryptMe, action); + TemporaryKeyImpl tk = new TemporaryKeyImpl(); + tk.setCreationDate(new Date()); + tk.setEmailAddress(emailaddress); + tk.setIpAddress(ipaddress); + tk.setRegistrationKey(encryptMe); + tk.setRegAction(action); dbInstance.getCurrentEntityManager().persist(tk); return tk; } @@ -318,7 +318,7 @@ public class RegistrationManager extends BasicManager { * @param keyValue */ public void deleteTemporaryKeyWithId(String keyValue) { - TemporaryKeyImpl tKey = loadTemporaryKeyByRegistrationKey(keyValue); + TemporaryKey tKey = loadTemporaryKeyByRegistrationKey(keyValue); if(tKey != null) { deleteTemporaryKey(tKey); } @@ -372,17 +372,4 @@ public class RegistrationManager extends BasicManager { public void revokeConfirmedDisclaimer(Identity identity) { propertyManager.deleteProperties(identity, null, null, "user", "dislaimer_accepted"); } - - /** - * Get a list of all users that did already confirm the disclaimer - * @return - */ - public List<Identity> getIdentitiesWithConfirmedDisclaimer() { - StringBuilder sb = new StringBuilder(); - sb.append("select distinct ident from org.olat.core.id.Identity as ident, org.olat.properties.Property as prop ") - .append(" where prop.identity=ident and prop.category='user' and prop.name='dislaimer_accepted'"); - return dbInstance.getCurrentEntityManager() - .createQuery(sb.toString(), Identity.class) - .getResultList(); - } } \ No newline at end of file diff --git a/src/main/java/org/olat/registration/SendMessageController.java b/src/main/java/org/olat/registration/SendMessageController.java new file mode 100644 index 00000000000..5a01b96c79d --- /dev/null +++ b/src/main/java/org/olat/registration/SendMessageController.java @@ -0,0 +1,89 @@ +/** + * <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.commons.services.sms.SimpleMessageException; +import org.olat.core.commons.services.sms.SimpleMessageService; +import org.olat.core.commons.services.sms.ui.SMSPhoneController; +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.form.flexible.FormItemContainer; +import org.olat.core.gui.components.form.flexible.impl.FormBasicController; +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.id.Identity; +import org.olat.core.util.Util; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * Initial date: 6 févr. 2017<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class SendMessageController extends FormBasicController { + + private final String sentToken; + private final Identity recipient; + + @Autowired + private SimpleMessageService messageService; + + public SendMessageController(UserRequest ureq, WindowControl wControl, Identity recipient) { + super(ureq, wControl, "send_message", Util.createPackageTranslator(SMSPhoneController.class, ureq.getLocale())); + this.recipient = recipient; + sentToken = messageService.generateToken(); + initForm(ureq); + } + + public Identity getRecipient() { + return recipient; + } + + public String getSentToken() { + return sentToken; + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + uifactory.addFormSubmitButton("send.sms", "pw.change.sms", formLayout); + } + + @Override + protected void doDispose() { + // + } + + @Override + protected void formOK(UserRequest ureq) { + try { + String msg = translate("sms.token", new String[]{ sentToken }); + messageService.sendMessage(msg, recipient); + fireEvent(ureq, Event.DONE_EVENT); + } catch (SimpleMessageException e) { + showWarning("warning.message.not.send"); + } + } + + @Override + protected void formCancelled(UserRequest ureq) { + fireEvent(ureq, Event.CANCELLED_EVENT); + } +} diff --git a/src/main/java/org/olat/registration/TemporaryKey.java b/src/main/java/org/olat/registration/TemporaryKey.java index b3486534ad3..71e54bfda50 100644 --- a/src/main/java/org/olat/registration/TemporaryKey.java +++ b/src/main/java/org/olat/registration/TemporaryKey.java @@ -34,10 +34,11 @@ import java.util.Date; * @author Sabina Jeger */ public interface TemporaryKey { + /** + * @return Object key. + */ + public Long getKey(); - - public int getVersion(); - public void setVersion(int version); /** * @return email address */ @@ -46,6 +47,7 @@ public interface TemporaryKey { * @param string */ public void setEmailAddress(String string); + /** * @return The ip address the registration request came from */ @@ -68,6 +70,7 @@ public interface TemporaryKey { * @param string */ public void setRegistrationKey(String string); + /** * @return Wether email has been sent. */ @@ -76,18 +79,8 @@ public interface TemporaryKey { * @param b */ public void setMailSent(boolean b); - /** - * @return Object key. - */ - public Long getKey(); - /** - * @param long1 - */ - public void setKey(Long long1); - /** - * @param date - */ - public void setCreationDate(Date date); + + /** * @return Registration action. */ diff --git a/src/main/java/org/olat/registration/TemporaryKeyImpl.hbm.xml b/src/main/java/org/olat/registration/TemporaryKeyImpl.hbm.xml deleted file mode 100644 index 7286a998983..00000000000 --- a/src/main/java/org/olat/registration/TemporaryKeyImpl.hbm.xml +++ /dev/null @@ -1,45 +0,0 @@ -<?xml version="1.0"?> -<!DOCTYPE hibernate-mapping PUBLIC - "-//Hibernate/Hibernate Mapping DTD//EN" - "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> - -<hibernate-mapping default-lazy="false"> - <class name="org.olat.registration.TemporaryKeyImpl" table="o_temporarykey"> - <id name="key" type="long" column="reglist_id" unsaved-value="null"> - <generator class="enhanced-sequence"> - <param name="sequence_name">hibernate_unique_key</param> - <param name="force_table_use">true</param> - <param name="optimizer">legacy-hilo</param> - <param name="value_column">next_hi</param> - <param name="increment_size">32767</param> - <param name="initial_value">32767</param> - </generator> - </id> - - <version name="version" access="field" column="version" type="int"/> - <property name="creationDate" column="creationdate" type="timestamp" /> - - <property name="emailAddress" > - <column name ="email" not-null="true" /> - </property> - - <property name="registrationKey" > - <column name ="regkey" not-null="true" /> - </property> - - <property name="ipAddress" > - <column name ="ip" not-null="true" /> - </property> - - <property name="mailSent" > - <column name ="mailsent" not-null="true" /> - </property> - - <property name="regAction" > - <column name ="action" not-null="true" /> - </property> - - </class> - -</hibernate-mapping> - diff --git a/src/main/java/org/olat/registration/TemporaryKeyImpl.java b/src/main/java/org/olat/registration/TemporaryKeyImpl.java index 10b32dd1828..20d933fa1d8 100644 --- a/src/main/java/org/olat/registration/TemporaryKeyImpl.java +++ b/src/main/java/org/olat/registration/TemporaryKeyImpl.java @@ -27,7 +27,21 @@ package org.olat.registration; import java.util.Date; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; +import javax.persistence.Version; + +import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.Parameter; import org.olat.core.id.CreateInfo; +import org.olat.core.id.Persistable; /** * Description: @@ -35,37 +49,65 @@ import org.olat.core.id.CreateInfo; * * @author Sabina Jeger */ -public class TemporaryKeyImpl implements CreateInfo, TemporaryKey { +@Entity(name="otemporarykey") +@Table(name="o_temporarykey") +@NamedQueries({ + @NamedQuery(name="loadTemporaryKeyByRegAction", query="select r from otemporarykey r where r.regAction=:action"), + @NamedQuery(name="loadTemporaryKeyByRegKey", query="select r from otemporarykey r where r.registrationKey=:regkey"), + @NamedQuery(name="loadTemporaryKeyByEmailAddress", query="select r from otemporarykey r where r.emailAddress=:email") +}) +public class TemporaryKeyImpl implements Persistable, CreateInfo, TemporaryKey { + + private static final long serialVersionUID = 2617181963956081372L; - private Long key = null; - private String emailAddress = null; - private String ipAddress = null; - private Date creationDate = new Date(); - private Date lastModified = null; - private String registrationKey = null; - private String regAction = null; - private boolean mailSent = false; + @Id + @GeneratedValue(generator = "system-uuid") + @GenericGenerator(name = "system-uuid", strategy = "enhanced-sequence", parameters={ + @Parameter(name="sequence_name", value="hibernate_unique_key"), + @Parameter(name="force_table_use", value="true"), + @Parameter(name="optimizer", value="legacy-hilo"), + @Parameter(name="value_column", value="next_hi"), + @Parameter(name="increment_size", value="32767"), + @Parameter(name="initial_value", value="32767") + }) + @Column(name="reglist_id", nullable=false, unique=true, insertable=true, updatable=false) + private Long key; + @Version private int version; - /** - * - */ - protected TemporaryKeyImpl() { - super(); + @Temporal(TemporalType.TIMESTAMP) + @Column(name="creationdate", nullable=false, insertable=true, updatable=false) + private Date creationDate; + + @Column(name="email", nullable=false, unique=true, insertable=true, updatable=true) + private String emailAddress; + @Column(name="ip", nullable=false, unique=true, insertable=true, updatable=true) + private String ipAddress; + @Column(name="regkey", nullable=false, unique=true, insertable=true, updatable=true) + private String registrationKey; + @Column(name="action", nullable=false, unique=true, insertable=true, updatable=true) + private String regAction; + @Column(name="mailsent", nullable=false, unique=true, insertable=true, updatable=true) + private boolean mailSent = false; + + public TemporaryKeyImpl() { + // + } + + @Override + public Long getKey() { + return key; + } + + public void setKey(Long key) { + this.key = key; } /** - * Temporary key database object. - * @param emailaddress - * @param ipaddress - * @param registrationKey - * @param action + * @see org.olat.registration.TemporaryKey#setCreationDate(java.util.Date) */ - public TemporaryKeyImpl(String emailaddress, String ipaddress, String registrationKey, String action) { - this.emailAddress = emailaddress; - this.ipAddress = ipaddress; - this.registrationKey = registrationKey; - this.regAction = action; + public void setCreationDate(Date date) { + creationDate = date; } /** @@ -103,13 +145,6 @@ public class TemporaryKeyImpl implements CreateInfo, TemporaryKey { return creationDate; } - /** - * @see org.olat.registration.TemporaryKey#getLastModified() - */ - public Date getLastModified() { - return lastModified; - } - /** * @see org.olat.registration.TemporaryKey#getRegistrationKey() */ @@ -138,53 +173,36 @@ public class TemporaryKeyImpl implements CreateInfo, TemporaryKey { mailSent = b; } - /** - * @see org.olat.registration.TemporaryKey#getKey() - */ - public Long getKey() { - return key; - } - - /** - * @see org.olat.registration.TemporaryKey#setKey(java.lang.Long) - */ - public void setKey(Long long1) { - key = long1; - } - - /** - * @see org.olat.registration.TemporaryKey#setCreationDate(java.util.Date) - */ - public void setCreationDate(Date date) { - creationDate = date; - } - - /** - * @see org.olat.registration.TemporaryKey#setLastModified(java.util.Date) - */ - public void setLastModified(Date date) { - lastModified = date; - } - /** - * @see org.olat.registration.TemporaryKey#getRegAction() - */ + @Override public String getRegAction() { return regAction; } - /** - * @see org.olat.registration.TemporaryKey#setRegAction(java.lang.String) - */ + @Override public void setRegAction(String string) { regAction = string; } - public int getVersion() { - return this.version; + @Override + public int hashCode() { + return getKey() == null ? 8742558 : getKey().hashCode(); + } + + @Override + public boolean equals(Object obj) { + if(this == obj) { + return true; + } + if(obj instanceof TemporaryKeyImpl) { + TemporaryKeyImpl tmpKey = (TemporaryKeyImpl)obj; + return getKey() != null && getKey().equals(tmpKey.getKey()); + } + return false; } - public void setVersion(int version) { - this.version = version; + @Override + public boolean equalsByPersistableKey(Persistable persistable) { + return equals(persistable); } } diff --git a/src/main/java/org/olat/registration/_content/pwchange.html b/src/main/java/org/olat/registration/_content/pwchange.html index 31c17b18540..c8ca1f0b25e 100644 --- a/src/main/java/org/olat/registration/_content/pwchange.html +++ b/src/main/java/org/olat/registration/_content/pwchange.html @@ -1,9 +1,9 @@ $r.render("pwwizard") <p class="o_info">$text</p> -#if ($pwdhelp) +#if ($r.isNotNull($pwdhelp)) <p>$pwdhelp</p> #end -<p>$r.render("pwarea")</p> +$r.render("pwarea") #if ($r.available("pwchange.homelink")) <div class="o_button_group o_button_group_left"> $r.render("pwchange.homelink") diff --git a/src/main/java/org/olat/registration/_content/send_message.html b/src/main/java/org/olat/registration/_content/send_message.html new file mode 100644 index 00000000000..87f6e24eb82 --- /dev/null +++ b/src/main/java/org/olat/registration/_content/send_message.html @@ -0,0 +1,5 @@ +<h3>$r.translate("pw.change.sms.title")</h3> +<p>$r.translate("pw.change.sms.descr")</p> +<div class="o_button_group"> + $r.render("send.sms") +</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 493f513fa51..f0e1ae9713e 100644 --- a/src/main/java/org/olat/registration/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/registration/_i18n/LocalStrings_de.properties @@ -1,22 +1,22 @@ -#Mon Mar 02 09:54:04 CET 2009 +#Tue Feb 07 14:00:34 CET 2017 admin.enableRegistration=Selbstregistration aktivieren +admin.enableRegistration.on=ein admin.enableRegistrationLink=Selbstregistration \u00FCber externe Webseiten aktivieren -admin.registrationLinkExample=Beispielcode admin.enableRegistrationLogin=Selbstregistrationslink auf Loginseite aktivieren -admin.enableRegistration.on=ein +admin.enableStaticProp=Standardwert aktivieren admin.menu.title=Selbstregistration admin.menu.title.alt=$\:admin.menu.title -admin.registration.title=Selbstregistrierung -admin.registration.domains.title=Einschr\u00E4nkung auf Dom\u00E4ne -admin.registration.domains.desc=Die Selbtregistration kann optional auf eine oder mehrere Dom\u00E4nen eingeschr\u00E4nkt werden. Um diese Funktion zu aktivieren f\u00FCgen Sie eine Liste von Dom\u00E4nen an z.B: openolat.com, *openolat.org, hotmail.com admin.registration.domains=Dom\u00E4nenliste -admin.registration.domains.error=Diese Dom\u00E4nen sind nicht g\u00FCltig: {0} -admin.registration.staticprop.title=Benutzerattribut zuweisen -admin.registration.staticprop.desc=Nach der Selbstregistrierung kann einem Benutzerattribut optional ein Standardwert zugewiesen werden. Dies kann genutzt werden um selbstregistrierte Benutzer einfach zu erkennen und dadurch z.B. von LDAP-Benutzern zu unterscheiden. -admin.enableStaticProp=Standardwert aktivieren +admin.registration.domains.desc=Die Selbtregistration kann optional auf eine oder mehrere Dom\u00E4nen eingeschr\u00E4nkt werden. Um diese Funktion zu aktivieren f\u00FCgen Sie eine Liste von Dom\u00E4nen an z.B\: openolat.com, *openolat.org, hotmail.com +admin.registration.domains.error=Diese Dom\u00E4nen sind nicht g\u00FCltig\: {0} +admin.registration.domains.title=Einschr\u00E4nkung auf Dom\u00E4ne admin.registration.property=Benutzerattribut admin.registration.propertyValue=Standardwert admin.registration.propertyValue.error=Ung\u00FCltiger Wert +admin.registration.staticprop.desc=Nach der Selbstregistrierung kann einem Benutzerattribut optional ein Standardwert zugewiesen werden. Dies kann genutzt werden um selbstregistrierte Benutzer einfach zu erkennen und dadurch z.B. von LDAP-Benutzern zu unterscheiden. +admin.registration.staticprop.title=Benutzerattribut zuweisen +admin.registration.title=Selbstregistrierung +admin.registrationLinkExample=Beispielcode disclaimer.acknowledged=<b>Ich habe die Nutzungsbedingungen gelesen, verstanden und stimme ihnen zu.</b> disclaimer.additionalcheckbox=<b>Ich bin mit der Datenspeicherung einverstanden.</b> disclaimer.additionallinktext=Nutzungsbedingungen (PDF Dokument) @@ -29,14 +29,15 @@ disclaimer.paragraph1=Der/die OpenOLAT-Benutzer/in nimmt zur Kenntnis, dass er/s disclaimer.paragraph2=Der Betreiber dieser Plattform behält sich das Recht vor, bei Missbrauch des OpenOLAT-Servers oder Verstössen gegen diese Nutzungsregelung, den Zugang zu OpenOLAT zu sperren und alle Daten des betreffenden Benutzers oder der betreffenden Benutzerin zu löschen. Ferner behält sie sich das Recht vor, strafrechtliche oder \tzivilrechtliche Untersuchungen einzuleiten. disclaimer.terms.of.usage=<b>Nutzungsbedingungen</b> email.address=E-Mail-Adresse -email.or.username=E-Mail-Adresse oder Benutzername -email.or.username.maynotbeempty=Bitte geben Sie Ihre E-Mail-Addresse oder Ihren Benutzernamen an -email.or.username.not.identified=Benutzer konnte nicht eindeutig identifiziert werden email.address.maynotbeempty=E-Mail-Adresse darf nicht leer sein email.address.notregular=E-Mail-Adresse muss g\u00FCltig sein email.address2=E-Mail-Adresse (bitte nochmals eingeben) email.notsent=E-Mail konnte nicht verschickt werden. Geben Sie bitte nochmals Ihre E-Mail-Adresse ein. +email.or.username=E-Mail-Adresse oder Benutzername +email.or.username.maynotbeempty=Bitte geben Sie Ihre E-Mail-Addresse oder Ihren Benutzernamen an +email.or.username.not.identified=Benutzer konnte nicht eindeutig identifiziert werden email.sent=E-Mail wurde verschickt. +error.pw.change.confirm.token=Der Code stimmt nicht mit dem per SMS geschickt. form.check1=Bitte geben Sie Ihren Vornamen an.\t form.check2=Bitte geben Sie Ihren Namen an. form.check3=$org.olat.user\:form.checkUsername @@ -45,12 +46,12 @@ form.check5=Bitte tragen Sie zweimal das gleiche Passwort ein. form.check6=Dieser Benutzername ist bereits besetzt. Bitte w\u00E4hlen Sie einen anderen. form.general.error=Bitte korrigieren Sie nachstehende Felder\: form.legende.mandatory=Diese Felder m\u00FCssen ausgef\u00FCllt werden. +form.login=Login +form.mail.whitelist.error=Die Dom\u00E4ne Ihrer E-Mail Adresse ist nicht f\u00FCr die Selbstregistration freigeschaltet. Bitte verwenden Sie die E-Mail Adresse Ihrer Institution. form.password.enter.new=Passwort neu setzen form.password.error.nomatch=Beide Passw\u00F6rter m\u00FCssen gleich sein form.password.new1=Neues Passwort form.password.new2=Passwort best\u00E4tigen -form.mail.whitelist.error=Die Dom\u00E4ne Ihrer E-Mail Adresse ist nicht f\u00FCr die Selbstregistration freigeschaltet. Bitte verwenden Sie die E-Mail Adresse Ihrer Institution. -form.login=Login login.body=Sie sind bereits in OpenOLAT registriert unter dem Benutzernamen\: {0} \n\nFalls Sie diese E-Mail unaufgefordert erhalten haben, l\u00F6schen Sie ganz einfach diese E-Mail.\n\nIhr OpenOLAT-Team \n login.subject=Bereits vorhandene Registrierung in OpenOLAT loginhelp=Der Benutzername<ul><li>muss mindestens 4 Zeichen lang sein</li><li>darf nur Ziffern und / oder Kleinbuchstaben enthalten (keine Umlaute, keine Sonderzeichen ausser .-_)</li><li>kann sp\u00E4ter nicht mehr ge\u00E4ndert werden</li></ul> @@ -58,8 +59,15 @@ menu.login.alt=Melden Sie sich f\u00FCr das Learning Management System OpenOLAT password.cantchange=Um Ihr Passwort zu \u00E4ndern, kontaktieren Sie bitte die entsprechende Stelle an Ihrer Hochschule. password.notchanged=OpenOLAT-Passwort wurde nicht neu gesetzt. password.successful=Ihr OpenOLAT-Passwort wurde neu gesetzt. -pwchange.intro=Sie oder eine andere Person haben f\u00FCr den OpenOLAT-Benutzeraccount {0} ein neues Passwort angefordert.\n\n +pw.change.confirm=SMS Code \u00FCberpr\u00FCfen +pw.change.confirm.descr=Geben Sie den Authentifizierungscode ein, den Sie per SMS erhalten haben\: +pw.change.confirm.token=SMS Authentifizierungscode +pw.change.sms=SMS Authentifizierung starten +pw.change.sms.descr=Sie haben eine Mobile Telefonnummer in OpenOLAT hinterlegt. Sie k\u00F6nnen sich daher \u00FCber SMS authentifizieren. W\u00E4hlen Sie den untenstehenden Button um die SMS-Authentifizierung zu starten\: +pw.change.sms.title=SMS Authentifizierung pwchange.body=\u00DCber den Link {0}/dmz/pwchange/index.html?key\={1}&language\={2} \nk\u00F6nnen Sie Ihr OpenOLAT-Passwort neu setzen und sich anschlie\u00DFend unter {0}/dmz/1%3A1%3Aomain_loging%3A1%3A0%3Acid%3Alogin/?lp\=OLAT einloggen. \n\nIhr OpenOLAT-Team \n +pwchange.homelink=Klicken Sie hier um sich anzumelden +pwchange.intro=Sie oder eine andere Person haben f\u00FCr den OpenOLAT-Benutzeraccount {0} ein neues Passwort angefordert.\n\n pwchange.subject=Schl\u00FCssel f\u00FCr neues OpenOLAT-Passwort pwdchangekey.missing=Bitte Schl\u00FCssel angeben, um ein neues OpenOLAT-Passwort zu setzen. pwdhelp=Das Passwort<ul><li>muss mindestens 4 Zeichen haben</li><li>muss Buchstaben und mindestens eine Ziffer enthalten</li><li>darf keine Umlaute und andere speziellen Buchstaben enthalten z.B. \u00FC, \u00E4, \u00E9</li><li>darf keine Leerschl\u00E4ge oder Escape-Sequenzen enthalten</li><li>kann folgende Sonderzeichen enthalten\: \! \# $ % & ( ) * + , - . / \: ; <\=> ? @ [ ] ^ _ ` { | } ~</li></ul> @@ -67,20 +75,20 @@ pwform.cancelled=Die Eingabe eines neuen OpenOLAT-Passwortes wurde abgebrochen. pwform.failed=Ein unerwarteter Fehler ist aufgetreten. Das Passwort bleibt unver\u00E4ndert. pwkey.missingentry=Es wurde kein Schl\u00FCssel gefunden, um Ihr OpenOLAT-Passwort neu zu setzen. reg.body=<p>Vielen Dank f\u00FCr Ihr Interesse an OpenOLAT.</p><p>\u00DCber den Link {3}<br>k\u00F6nnen Sie die Registrierung vervollst\u00E4ndigen.</p><p>Falls Sie sich doch nicht registrieren wollen, l\u00F6schen Sie diese E-Mail.</p><p>Ihr OpenOLAT-Team</p> +reg.error.disabled.body=Die Selbstregistrierung wurde f\u00FCr dieses System deaktiviert. Bitte kontaktieren Sie den zust\u00E4ndigen Systemadministrator unter {0} um einen Zugang zu erhalten. +reg.error.no_username=Kein Benutzername konnte erstellt werden +reg.error.title=Registrierung abgebrochen +reg.error.user_in_use=Benutzername ist schon besetzt reg.notiEmail.body=Soeben hat sich ein neuer Benutzer in OpenOLAT registriert\: \n\nName\: \t{2}\nVorname\: \t\t{1}\nLogin\: \t\t{0}\nE-Mail\: \t{3}\nSprache\: \t\t{4}\nServer\: \t\t{5} reg.notiEmail.subject=Neuer OpenOLAT-Benutzer\: {1} {2} ({0}) reg.subject=Registrierungsschl\u00FCssel f\u00FCr OpenOLAT reg.wherefrom=Diese Anfrage an den Server {0} wurde am {1} \nvon der IP-Adresse {2} abgeschickt. -reg.error.disabled.body=Die Selbstregistrierung wurde f\u00fcr dieses System deaktiviert. Bitte kontaktieren Sie den zust\u00e4ndigen Systemadministrator unter {0} um einen Zugang zu erhalten. -reg.error.title=Registrierung abgebrochen -reg.error.no_username=Kein Benutzername konnte erstellt werden -reg.error.user_in_use=Benutzername ist schon besetzt registration.form.cancelled=Sie haben die Registrierung abgebrochen. 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 -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. 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. sr.error.disclaimer.checkboxes=Sie m\u00FCssen durch Anklicken <i>beider</i> K\u00E4stchen best\u00E4tigen, dass Sie die Nutzungsbedingungen gelesen und verstanden haben und diese akzeptieren. step1.pw.text=Hier k\u00F6nnen Sie ein neues OpenOLAT-Passwort eingeben. Geben Sie bitte diejenige E-Mail-Adresse an, die in OpenOLAT bekannt ist, oder den Benutzernamen. @@ -93,9 +101,8 @@ step3.pw.text=Bitte beachten Sie bei der Eingabe des neuen OpenOLAT-Passwortes f step3.reg.text=Um die Registrierung abzuschliessen, f\u00FCllen Sie bitte das Formular mit Ihren Angaben aus. step4.pw.text=Sie haben Ihr OpenOLAT-Passwort neu gesetzt. step4.reg.text=<b>Bitte akzeptieren Sie die Nutzungsbedingungen, bevor Sie fortfahren.</b> -step5.reg.text=Sie k\u00F6nnen sich nun mit Ihrem Benutzernamen <b>{0}</b> und Passwort anmelden: +step5.reg.text=Sie k\u00F6nnen sich nun mit Ihrem Benutzernamen <b>{0}</b> und Passwort anmelden\: step5.reg.yourdata=Zusammenfassung Ihrer Angaben\: -pwchange.homelink=Klicken Sie hier um sich anzumelden submit.accept=Akzeptieren submit.cancel=Abbrechen submit.speichernUndpwchange=OpenOLAT-Passwort \u00E4ndern @@ -116,4 +123,5 @@ user.password=OpenOLAT-Passwort user.password2=OpenOLAT-Passwort wiederholen user.pwlength=min. 4 Zeichen, kann Buchstaben und Ziffern enthalten user.regkey=Registrierungsschl\u00FCssel +warning.message.not.send=SMS cannot be send. workflow.browsedback=Bitte benutzen Sie nicht die Browsernavigation. 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 818b42369fc..d521227803f 100644 --- a/src/main/java/org/olat/registration/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/registration/_i18n/LocalStrings_en.properties @@ -1,22 +1,22 @@ -#Wed Jan 26 18:46:42 CET 2011 +#Tue Feb 07 13:54:14 CET 2017 admin.enableRegistration=Activate self-registration +admin.enableRegistration.on=Enabled admin.enableRegistrationLink=Activate self-registration from external web sites -admin.registrationLinkExample=Example code admin.enableRegistrationLogin=Activate self-registration link on login page -admin.enableRegistration.on=Enabled +admin.enableStaticProp=Activate user property mapping admin.menu.title=Self-registration admin.menu.title.alt=$\:admin.menu.title -admin.registration.title=Self-registration -admin.registration.domains.title=Domain limitation -admin.registration.domains.desc=Optionally the self registration can be limited to one or multiple domains. To activate this feature add a list of domains into the form below, e.g. : openolat.com, *openolat.org, hotmail.com admin.registration.domains=List of domains -admin.registration.domains.error=The following domains are not valid: {0} -admin.registration.staticprop.title=User property mapping -admin.registration.staticprop.desc=Optionally a user property can be set to a default value after self registration. This can be used to easily identify users who self-registred and separate them e.g. from LDAP users. -admin.enableStaticProp=Activate user property mapping +admin.registration.domains.desc=Optionally the self registration can be limited to one or multiple domains. To activate this feature add a list of domains into the form below, e.g. \: openolat.com, *openolat.org, hotmail.com +admin.registration.domains.error=The following domains are not valid\: {0} +admin.registration.domains.title=Domain limitation admin.registration.property=User property name admin.registration.propertyValue=User property value admin.registration.propertyValue.error=Invalid user property value +admin.registration.staticprop.desc=Optionally a user property can be set to a default value after self registration. This can be used to easily identify users who self-registred and separate them e.g. from LDAP users. +admin.registration.staticprop.title=User property mapping +admin.registration.title=Self-registration +admin.registrationLinkExample=Example code disclaimer.acknowledged=<b>I have read your terms of use, do understand and agree.</b> disclaimer.additionalcheckbox=<b>I agree on the terms of data storage</b> disclaimer.additionallinktext=Terms of use (PDF document) @@ -37,6 +37,7 @@ email.or.username=E-mail address or user name email.or.username.maynotbeempty=Please indicate your e-mail address or user name email.or.username.not.identified=User could not be identified clearly. email.sent=E-mail sent. +error.pw.change.confirm.token=The code doesn't match the one which was sent to you by SMS. form.check1=Please enter your first name. form.check2=Please enter your last name. form.check3=$org.olat.user\:form.checkUsername @@ -45,12 +46,12 @@ form.check5=Please enter two identical passwords. form.check6=This user name already exists. Please select another. form.general.error=Please correct the following fields\: form.legende.mandatory=These fields are mandatory. +form.login=Login +form.mail.whitelist.error=Your e-mail address doesn't match our list. Please use your institutional e-mail address. form.password.enter.new=Set new password form.password.error.nomatch=Passwords do not match. form.password.new1=New password form.password.new2=Confirm password -form.login=Login -form.mail.whitelist.error=Your e-mail address doesn't match our list. Please use your institutional e-mail address. login.body=You are already registered in OpenOLAT. Your user name is\: {0}.\n\nIn case you got this e-mail unwanted, please delete it.\n\nYour OpenOLAT team.\n login.subject=You are already registered in OpenOLAT. loginhelp=A user name<ul><li>must contain at least 4 characters</li><li>may only contain digits and/or lower case letters (no special digits or umlauts except for . - _)</li><li>cannot be changed later on</li></ul> @@ -58,6 +59,12 @@ menu.login.alt=Please log in to profit from the Learning Management System OpenO password.cantchange=To change your password, please contact the support team at your university. password.notchanged=Your OpenOLAT password could not be changed. password.successful=Your OpenOLAT password was changed successfully. +pw.change.confirm=Check the SMS code +pw.change.confirm.descr=Please enter the authentication code you receive by SMS. +pw.change.confirm.token=SMS authentication code +pw.change.sms=Start authentication by SMS +pw.change.sms.descr=You have enter a mobile telecom number in OpenOLAT. You can authenticate you by SMS. Choose the button below to start the authentication by SMS\: +pw.change.sms.title=Authentication by SMS pwchange.body=Please use the link {0}/dmz/pwchange/index.html?key\={1}&language\={2} \r\nto change your OpenOLAT password. \r\n\r\nYour OpenOLAT team pwchange.homelink=Please click here to log on pwchange.intro=You have (or somebody else has) asked for a new password regarding the OpenOLAT user account {0}. @@ -68,7 +75,7 @@ pwform.cancelled=OpenOLAT password change was cancelled. Password remains unchan pwform.failed=An unexpected server error occurred. Your password was not altered. pwkey.missingentry=Key for OpenOLAT password change not found. reg.body=<p>Thank you for your interest in OpenOLAT.</p><p>Please use the link {3}<br>to complete your registration.</p><p>In case you do not want to register, just ignore this e-mail.</p><p>Your OpenOLAT team</p> -reg.error.disabled.body=The self registration for this system has been disabled. Please contact the system administrator ({0}) in order to gain access.\u00a0 +reg.error.disabled.body=The self registration for this system has been disabled. Please contact the system administrator ({0}) in order to gain access.\u00A0 reg.error.no_username=User name could not be created reg.error.title=Registration cancelled reg.error.user_in_use=This user name already exists @@ -94,7 +101,7 @@ step3.pw.text=Please consider the following instructions for setting an OpenOLAT step3.reg.text=In order to finish your registration, please fill in the form. step4.pw.text=You have changed your OpenOLAT password successfully. step4.reg.text=<b>Please read the terms of use before proceeding.</b> -step5.reg.text=You can now log in with your OpenOLAT user name <b>{0}</b> and password: +step5.reg.text=You can now log in with your OpenOLAT user name <b>{0}</b> and password\: step5.reg.yourdata=Summary of your data\: submit.accept=Accept submit.cancel=Cancel diff --git a/src/main/java/org/olat/user/ProfileFormController.java b/src/main/java/org/olat/user/ProfileFormController.java index 0dae8bb84a9..1f8195ae24e 100644 --- a/src/main/java/org/olat/user/ProfileFormController.java +++ b/src/main/java/org/olat/user/ProfileFormController.java @@ -65,7 +65,6 @@ import org.olat.core.util.resource.OresHelper; import org.olat.core.util.xml.XStreamHelper; import org.olat.registration.RegistrationManager; import org.olat.registration.TemporaryKey; -import org.olat.registration.TemporaryKeyImpl; import org.olat.user.propertyhandlers.UserPropertyHandler; import org.springframework.beans.factory.annotation.Autowired; @@ -215,7 +214,7 @@ public class ProfileFormController extends FormBasicController { // special case for email field if (userPropertyHandler.getName().equals("email")) { String key = user.getProperty("emchangeKey", null); - TemporaryKeyImpl tempKey = rm.loadTemporaryKeyByRegistrationKey(key); + TemporaryKey tempKey = rm.loadTemporaryKeyByRegistrationKey(key); if (tempKey != null) { XStream xml = XStreamHelper.createXStreamInstance(); @SuppressWarnings("unchecked") @@ -488,7 +487,7 @@ public class ProfileFormController extends FormBasicController { identityToModify.getUser().setProperty("email", currentEmail); } else { String key = identityToModify.getUser().getProperty("emchangeKey", null); - TemporaryKeyImpl tempKey = rm.loadTemporaryKeyByRegistrationKey(key); + TemporaryKey tempKey = rm.loadTemporaryKeyByRegistrationKey(key); if (tempKey != null) { rm.deleteTemporaryKey(tempKey); } diff --git a/src/main/java/org/olat/user/UserImpl.java b/src/main/java/org/olat/user/UserImpl.java index 2b3094c724a..97bd673daf3 100644 --- a/src/main/java/org/olat/user/UserImpl.java +++ b/src/main/java/org/olat/user/UserImpl.java @@ -130,6 +130,8 @@ public class UserImpl implements Persistable, User { private String telPrivate; @Column(name="u_telmobile", nullable=true, insertable=true, updatable=true) private String telMobile; + @Column(name="u_smstelmobile", nullable=true, insertable=true, updatable=true) + private String smsTelMobile; @Column(name="u_skype", nullable=true, insertable=true, updatable=true) private String skype; @Column(name="u_msn", nullable=true, insertable=true, updatable=true) @@ -369,6 +371,7 @@ public class UserImpl implements Persistable, User { case "gender": return gender; case "telPrivate": return telPrivate; case "telMobile": return telMobile; + case "smsTelMobile": return smsTelMobile; case "telOffice": return telOffice; case "skype": return skype; case "msn": return msn; @@ -444,6 +447,7 @@ public class UserImpl implements Persistable, User { case "gender": gender = value; break; case "telPrivate": telPrivate = value; break; case "telMobile": telMobile = value; break; + case "smsTelMobile": smsTelMobile = value; break; case "telOffice": telOffice = value; break; case "skype": skype = value; break; case "msn": msn = value; break; diff --git a/src/main/java/org/olat/user/propertyhandlers/SmsPhonePropertyHandler.java b/src/main/java/org/olat/user/propertyhandlers/SmsPhonePropertyHandler.java new file mode 100644 index 00000000000..87978483cbf --- /dev/null +++ b/src/main/java/org/olat/user/propertyhandlers/SmsPhonePropertyHandler.java @@ -0,0 +1,64 @@ +/** + * <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.propertyhandlers; + +import java.util.Locale; +import java.util.Map; + +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.id.User; +import org.olat.user.propertyhandlers.ui.SmsPhoneElement; + +/** + * + * Initial date: 3 févr. 2017<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class SmsPhonePropertyHandler extends PhonePropertyHandler { + + @Override + public FormItem addFormItem(Locale locale, User user, String usageIdentifyer, boolean isAdministrativeUser, + FormItemContainer formItemContainer) { + String name = getName(); + SmsPhoneElement phoneEl = new SmsPhoneElement(name, this, user, locale); + phoneEl.setLabel("form.name." + name, null); + formItemContainer.add(phoneEl); + return phoneEl; + } + + @Override + public boolean isValid(User user, FormItem formItem, Map<String,String> formContext) { + return true; + } + + @Override + public boolean isValidValue(User user, String value, ValidationError validationError, Locale locale) { + return true; + } + + @Override + public String getStringValue(FormItem formItem) { + return ((SmsPhoneElement) formItem).getPhone(); + } + +} diff --git a/src/main/java/org/olat/user/propertyhandlers/UserInterestsElement.java b/src/main/java/org/olat/user/propertyhandlers/UserInterestsElement.java index 983d77c6d37..b01c67e60bf 100644 --- a/src/main/java/org/olat/user/propertyhandlers/UserInterestsElement.java +++ b/src/main/java/org/olat/user/propertyhandlers/UserInterestsElement.java @@ -44,7 +44,6 @@ 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.util.Util; -import org.olat.core.util.ValidationStatus; /** * <h3>Description:</h3> @@ -200,11 +199,6 @@ public class UserInterestsElement extends FormItemImpl implements FormItemCollec } } - @Override - public void validate(List<ValidationStatus> validationResults) { - // Do nothing. - } - /** * Returns the IDs of the selected user interests. * diff --git a/src/main/java/org/olat/user/propertyhandlers/UserPropertyUsageContext.java b/src/main/java/org/olat/user/propertyhandlers/UserPropertyUsageContext.java index 2103f648ebf..b7622b1d903 100644 --- a/src/main/java/org/olat/user/propertyhandlers/UserPropertyUsageContext.java +++ b/src/main/java/org/olat/user/propertyhandlers/UserPropertyUsageContext.java @@ -119,6 +119,16 @@ public class UserPropertyUsageContext { if (propertyHandlers.contains(propertyHandler)) return; // do not add twice propertyHandlers.add(propertyHandler); } + + public void addPropertyHandler(int index, UserPropertyHandler propertyHandler) { + if (propertyHandlers.contains(propertyHandler)) return; // do not add twice + + if(index < 0 && index >= propertyHandlers.size()) { + propertyHandlers.add(propertyHandler); + } else { + propertyHandlers.add(index, propertyHandler); + } + } /** * removes the given propertyHandler from this context diff --git a/src/main/java/org/olat/user/propertyhandlers/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/user/propertyhandlers/_i18n/LocalStrings_de.properties index adf41bb86f0..44a2c02ad50 100644 --- a/src/main/java/org/olat/user/propertyhandlers/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/user/propertyhandlers/_i18n/LocalStrings_de.properties @@ -1,4 +1,4 @@ -#Mon Mar 02 14:11:51 CET 2015 +#Tue Feb 07 13:58:39 CET 2017 country.code.AD=Andorra country.code.AE=Vereinigte Arabische Emirate country.code.AG=Antigua und Barbuda @@ -9,7 +9,7 @@ country.code.AO=Angola country.code.AQ=Antarctica country.code.AR=Argentinien country.code.AS=Samoa (amerikanischer Teil) -country.code.AT=\u00d6sterreich +country.code.AT=\u00D6sterreich country.code.AU=Australien country.code.AW=Aruba country.code.AZ=Aserbaidschan @@ -22,7 +22,7 @@ country.code.BG=Bulgarien country.code.BH=Bahrain country.code.BI=Burundi country.code.BJ=Benin -country.code.BL=St. Barth\u00e9lemy +country.code.BL=St. Barth\u00E9lemy country.code.BM=Bermuda country.code.BN=Brunei country.code.BO=Bolivien @@ -40,7 +40,7 @@ country.code.CD=Kongo, demokratische Republik country.code.CF=Zentralafrika country.code.CG=Kongo, Republik country.code.CH=Schweiz -country.code.CI=Elfenbeink\u00fcste +country.code.CI=Elfenbeink\u00FCste country.code.CK=Cook-Inseln country.code.CL=Chile country.code.CM=Kamerun @@ -49,44 +49,44 @@ country.code.CO=Kolumbien country.code.CR=Costa Rica country.code.CU=Kuba country.code.CV=Kapverdische Inseln -country.code.CW=Cura\u00e7ao +country.code.CW=Cura\u00E7ao country.code.CX=Weihnachtsinsel (Indischer Ozean) country.code.CY=Zypern country.code.CZ=Tschechische Republik country.code.DE=Deutschland country.code.DJ=Djibouti -country.code.DK=D\u00e4nemark +country.code.DK=D\u00E4nemark country.code.DM=Dominica country.code.DO=Dominikanische Republik country.code.DZ=Algerien country.code.EC=Ekuador country.code.EE=Estland -country.code.EG=\u00c4gypten +country.code.EG=\u00C4gypten country.code.EH=Western Sahara country.code.ER=Eritrea country.code.ES=Spanien -country.code.ET=\u00c4thiopien +country.code.ET=\u00C4thiopien country.code.FI=Finnland country.code.FJ=Fidschi country.code.FK=Falkland country.code.FM=Micronesia, Federated States of -country.code.FO=F\u00e4r\u00f6er +country.code.FO=F\u00E4r\u00F6er country.code.FR=Frankreich country.code.GA=Gabun country.code.GB=Grossbritannien und Nordirland country.code.GD=Grenada country.code.GE=Georgien, Republik -country.code.GF=Franz\u00f6sisch-Guayana +country.code.GF=Franz\u00F6sisch-Guayana country.code.GG=Guernsey country.code.GH=Ghana country.code.GI=Gibraltar -country.code.GL=Gr\u00f6nland +country.code.GL=Gr\u00F6nland country.code.GM=Gambia country.code.GN=Guinea, Republik country.code.GP=Guadeloupe -country.code.GQ=\u00c4quatorial-Guinea +country.code.GQ=\u00C4quatorial-Guinea country.code.GR=Griechenland -country.code.GS=S\u00fcdgeorgien und die s\u00fcdlichen Sandwichinseln +country.code.GS=S\u00FCdgeorgien und die s\u00FCdlichen Sandwichinseln country.code.GT=Guatemala country.code.GU=Guam country.code.GW=Guinea-Bissau @@ -118,7 +118,7 @@ country.code.KI=Kiribati country.code.KM=Komoren country.code.KN=St. Christoph (St. Kitts) und Nevis country.code.KP=Korea, Demo. Volksrepublik (Nordkorea) -country.code.KR=Korea, Republik (S\u00fcdkorea) +country.code.KR=Korea, Republik (S\u00FCdkorea) country.code.KW=Kuwait country.code.KY=Cayman country.code.KZ=Kasachstan @@ -145,7 +145,7 @@ country.code.ML=Mali country.code.MM=Myanmar (Union) country.code.MN=Mongolei country.code.MO=Macao -country.code.MP=Marianen, n\u00f6rdliche +country.code.MP=Marianen, n\u00F6rdliche country.code.MQ=Martinique country.code.MR=Mauretanien country.code.MS=Montserrat @@ -171,7 +171,7 @@ country.code.NZ=Neuseeland country.code.OM=Oman country.code.PA=Panama country.code.PE=Peru -country.code.PF=Franz\u00f6sisch-Polynesien +country.code.PF=Franz\u00F6sisch-Polynesien country.code.PG=Papua-Neuguinea country.code.PH=Philippinen country.code.PK=Pakistan @@ -179,15 +179,15 @@ country.code.PL=Polen country.code.PM=St. Pierre und Miquelon country.code.PN=Pitcairn country.code.PR=Puerto Rico -country.code.PS=Pal\u00e4stina +country.code.PS=Pal\u00E4stina country.code.PT=Portugal country.code.PW=Palau country.code.PY=Paraguay country.code.QA=Qatar -country.code.RE=R\u00e9union -country.code.RO=Rum\u00e4nien +country.code.RE=R\u00E9union +country.code.RO=Rum\u00E4nien country.code.RS=Serbien, Republik -country.code.RU=Russische F\u00f6deration +country.code.RU=Russische F\u00F6deration country.code.RW=Rwanda country.code.SA=Saudi-Arabien country.code.SB=Salomon-Inseln @@ -220,14 +220,14 @@ country.code.TL=Timor-Leste country.code.TM=Turkmenistan country.code.TN=Tunesien country.code.TO=Tonga -country.code.TR=T\u00fcrkei +country.code.TR=T\u00FCrkei country.code.TT=Trinidad und Tobago country.code.TV=Tuvalu country.code.TW=China, Taiwan country.code.TZ=Tansania country.code.UA=Ukraine country.code.UG=Uganda -country.code.UM=Amerikanische \u00dcberseeinseln, kleinere +country.code.UM=Amerikanische \u00DCberseeinseln, kleinere country.code.US=Vereinigte Staaten von Amerika country.code.UY=Uruguay country.code.UZ=Usbekistan @@ -242,7 +242,7 @@ country.code.WF=Wallis und Futuna country.code.WS=Samoa, West country.code.YE=Jemen country.code.YT=Mayotte -country.code.ZA=S\u00fcdafrika +country.code.ZA=S\u00FCdafrika country.code.ZM=Sambia country.code.ZW=Zimbabwe form.example.free={0} @@ -254,23 +254,23 @@ form.example.phone=(+41 12 345 67 89) form.example.skypename=(meinskypename) form.example.url=(http\://www.openolat.org) form.example.xingname=(XING Profilname) +form.group.about=\u00DCber mich form.group.account=Personalien form.group.address=Adresse form.group.contact=Kontaktdaten form.group.institute=Institution -form.group.person=Person -form.group.about=\u00DCber mich form.group.officeaddress=Gesch\u00E4ftsadresse +form.group.person=Person form.name.birthDay=Geburtsdatum form.name.birthDay.error=Bitte geben Sie ein g\u00FCltiges Datum an. form.name.birthDay.error.empty=Das Feld "Geburtsdatum" darf nicht leer sein. -form.name.date.future.error=Das gew\u00E4hlte Datum muss in der Zukunft liegen -form.name.date.past.error=Das gew\u00E4hlte Datum muss in der Vergangenheit liegen form.name.city=Stadt form.name.city.error.empty=Das Feld "Stadt" darf nicht leer sein. form.name.country=Land -form.name.countryCode=$\:form.name.country form.name.country.error.empty=Das Feld "Land" darf nicht leer sein. +form.name.countryCode=$\:form.name.country +form.name.date.future.error=Das gew\u00E4hlte Datum muss in der Zukunft liegen +form.name.date.past.error=Das gew\u00E4hlte Datum muss in der Vergangenheit liegen form.name.degree=Akademischer Grad form.name.department=Dienststelle / Firma form.name.email=E-Mail @@ -326,6 +326,7 @@ form.name.region=Region / Kanton form.name.region.error.empty=Das Feld "Region / Kanton" darf nicht leer sein. form.name.skype=Skype ID form.name.skype.error.empty=Das Feld "Skype ID" darf nicht leer sein. +form.name.smsTelMobile=SMS Telephon Mobil form.name.socialSecurityNumber=Sozialversicherungsnummer form.name.street=Strasse form.name.street.error.empty=Das Feld "Strasse" darf nicht leer sein. @@ -352,12 +353,12 @@ gender.error=Ung\u00FCltiger Wert f\u00FCr Geschlecht general.error.max.127=Wert enth\u00E4lt mehr wie 127 Zeichen general.error.max.32=Wert enth\u00E4lt mehr wie 32 Zeichen general.error.unique=Dieser Wert wird bereits von Benutzer {0} verwendet. Bitte geben Sie einen eindeutigen Wert ein. -gsph.selectionerror=Bitte treffen Sie eine Auswahl gsph.doselect=Ausw\u00E4hlen -gsphc.issingle=Einzelauswahl +gsph.selectionerror=Bitte treffen Sie eine Auswahl +gsphc.addoption=+ gsphc.ismulti=Mehrfachauswahl +gsphc.issingle=Einzelauswahl gsphc.moderadio=Modus -gsphc.addoption=+ gsphc.remove=- gsphc.translate=\u00FCbersetzen import.example.birthDay=10.10.1970 @@ -374,8 +375,8 @@ import.example.institutionalEmail=peter.muster@uzh.ch import.example.institutionalName=Universit\u00E4t Z\u00FCrich import.example.institutionalUserIdentifier=08-123-987 import.example.lastName=Muster +import.example.msn=$\:import.example.msnname import.example.msnname=msnbenutzer@hotmail.com -import.example.msn=$:import.example.msnname import.example.orgUnit=Rechtswissenschaftliche Fakult\u00E4t import.example.poBox=Postfach import.example.region=ZH @@ -432,12 +433,12 @@ table.name.xing=Xing ID table.name.zipCode=Postleitzahl table.user.lastlogin=Letzter login text.element.error.notlongerthan=Wert enth\u00E4lt mehr wie {0} Zeichen +userinterests.configinfo=Die Konfiguration der verf\u00FCgbaren Benutzer-Interessen wird in der Datei "olatdata/{0}" vorgenommen... +userinterests.description=W\u00E4hlen Sie aus den untenstehenden Gebieten diese aus, auf die Sie spezialisiert sind (maximal 5). userinterests.editlink=Bearbeiten... -userinterests.configinfo=Die Konfiguration der verf\u00fcgbaren Benutzer-Interessen wird in der Datei "olatdata/{0}" vorgenommen... userinterests.title=Expertise -userinterests.description=W\u00e4hlen Sie aus den untenstehenden Gebieten diese aus, auf die Sie spezialisiert sind (maximal 5). username=Benutzername -yph.from=Von -yph.to=Bis yph.err=Bitte geben Sie einen g\u00FCltigen Wert ein +yph.from=Von yph.infomsg=Bitte geben Sie 'von' und 'bis' Jahreszahlen (JJJJ) ein. <br />Sie k\u00F6nnen auch '+N' oder '-N' verwenden... +yph.to=Bis diff --git a/src/main/java/org/olat/user/propertyhandlers/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/user/propertyhandlers/_i18n/LocalStrings_en.properties index 64f5f759836..5c9ff0b2785 100644 --- a/src/main/java/org/olat/user/propertyhandlers/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/user/propertyhandlers/_i18n/LocalStrings_en.properties @@ -1,4 +1,4 @@ -#Mon Mar 02 14:03:06 CET 2015 +#Tue Feb 07 13:47:41 CET 2017 country.code.AD=Andorra country.code.AE=United Arab Emirates country.code.AG=Antigua and Barbuda @@ -22,7 +22,7 @@ country.code.BG=Bulgaria country.code.BH=Bahrain country.code.BI=Burundi country.code.BJ=Benin -country.code.BL=Saint Barth\u00e9lemy +country.code.BL=Saint Barth\u00E9lemy country.code.BM=Bermuda country.code.BN=Brunei Darussalam country.code.BO=Bolivia, Plurinational State of @@ -40,7 +40,7 @@ country.code.CD=Congo, the Democratic Republic of the country.code.CF=Central African Republic country.code.CG=Congo country.code.CH=Switzerland -country.code.CI=C\u00f4te d'Ivoire +country.code.CI=C\u00F4te d'Ivoire country.code.CK=Cook Islands country.code.CL=Chile country.code.CM=Cameroon @@ -49,7 +49,7 @@ country.code.CO=Colombia country.code.CR=Costa Rica country.code.CU=Cuba country.code.CV=Cape Verde -country.code.CW=Cura\u00e7ao +country.code.CW=Cura\u00E7ao country.code.CX=Christmas Island country.code.CY=Cyprus country.code.CZ=Czech Republic @@ -184,7 +184,7 @@ country.code.PT=Portugal country.code.PW=Palau country.code.PY=Paraguay country.code.QA=Qatar -country.code.RE=R\u00e9union +country.code.RE=R\u00E9union country.code.RO=Romania country.code.RS=Serbia country.code.RU=Russian Federation @@ -254,21 +254,21 @@ form.example.phone=(+41 12 345 67 89) form.example.skypename=(myskypename) form.example.url=(http\://www.openolat.org) form.example.xingname=(XING profile name) +form.group.about=About me form.group.account=Personal data form.group.address=Address form.group.contact=Contact data form.group.institute=Institution -form.group.person=Person -form.group.about=About me form.group.officeaddress=Business address +form.group.person=Person form.name.birthDay=Date of birth form.name.birthDay.error=Please provide a valid date. form.name.birthDay.error.empty=The field "Date of birth" is mandatory. form.name.city=City form.name.city.error.empty=The field "City" is mandatory. form.name.country=Country -form.name.countryCode=$\:form.name.country form.name.country.error.empty=The field "Country" is mandatory. +form.name.countryCode=$\:form.name.country form.name.date.future.error=The chosen Date must lie in the future form.name.date.past.error=The chosen Date must lie in the past form.name.degree=Academic degree @@ -326,6 +326,7 @@ form.name.region=Region/canton form.name.region.error.empty=The field "Region/canton" is mandatory. form.name.skype=Skype ID form.name.skype.error.empty=The field "Skype ID" is mandatory. +form.name.smsTelMobile=SMS mobile phone form.name.socialSecurityNumber=Social security number form.name.street=Street form.name.street.error.empty=The field "Street" is mandatory. diff --git a/src/main/java/org/olat/user/propertyhandlers/_spring/userPropertiesContext.xml b/src/main/java/org/olat/user/propertyhandlers/_spring/userPropertiesContext.xml index cc777dfb0b3..f5766bda103 100644 --- a/src/main/java/org/olat/user/propertyhandlers/_spring/userPropertiesContext.xml +++ b/src/main/java/org/olat/user/propertyhandlers/_spring/userPropertiesContext.xml @@ -25,6 +25,7 @@ <ref bean="userPropertyGender" /> <ref bean="userPropertyTelPrivate" /> <ref bean="userPropertyTelMobile" /> + <ref bean="userPropertySmsTelMobile" /> <ref bean="userPropertyTelOffice" /> <ref bean="userPropertySkype" /> <ref bean="userPropertyMSN" /> diff --git a/src/main/java/org/olat/user/propertyhandlers/_spring/userPropertriesHandlersContext.xml b/src/main/java/org/olat/user/propertyhandlers/_spring/userPropertriesHandlersContext.xml index 5989cc828fc..2d4cf567d1f 100644 --- a/src/main/java/org/olat/user/propertyhandlers/_spring/userPropertriesHandlersContext.xml +++ b/src/main/java/org/olat/user/propertyhandlers/_spring/userPropertriesHandlersContext.xml @@ -66,6 +66,12 @@ <property name="deletable" value="true" /> </bean> + <bean id="userPropertySmsTelMobile" class="org.olat.user.propertyhandlers.SmsPhonePropertyHandler"> + <property name="name" value="smsTelMobile" /> + <property name="group" value="contact" /> + <property name="deletable" value="true" /> + </bean> + <bean id="userPropertyTelOffice" class="org.olat.user.propertyhandlers.PhonePropertyHandler"> <property name="name" value="telOffice" /> <property name="group" value="contact" /> diff --git a/src/main/java/org/olat/user/propertyhandlers/ui/SmsPhoneComponent.java b/src/main/java/org/olat/user/propertyhandlers/ui/SmsPhoneComponent.java new file mode 100644 index 00000000000..74df297c218 --- /dev/null +++ b/src/main/java/org/olat/user/propertyhandlers/ui/SmsPhoneComponent.java @@ -0,0 +1,50 @@ +/** + * <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.propertyhandlers.ui; + +import org.olat.core.gui.components.ComponentRenderer; +import org.olat.core.gui.components.form.flexible.impl.FormBaseComponentImpl; + +/** + * + * Initial date: 7 févr. 2017<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class SmsPhoneComponent extends FormBaseComponentImpl { + + private static final ComponentRenderer RENDERER = new SmsPhoneComponentRenderer(); + + private final SmsPhoneElement element; + + public SmsPhoneComponent(SmsPhoneElement element) { + super(element.getName()); + this.element = element; + } + + public SmsPhoneElement getSmsPhoneElement() { + return element; + } + + @Override + public ComponentRenderer getHTMLRendererSingleton() { + return RENDERER; + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/user/propertyhandlers/ui/SmsPhoneComponentRenderer.java b/src/main/java/org/olat/user/propertyhandlers/ui/SmsPhoneComponentRenderer.java new file mode 100644 index 00000000000..d0e4f9cf19f --- /dev/null +++ b/src/main/java/org/olat/user/propertyhandlers/ui/SmsPhoneComponentRenderer.java @@ -0,0 +1,64 @@ +/** + * <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.propertyhandlers.ui; + +import org.olat.core.gui.components.Component; +import org.olat.core.gui.components.DefaultComponentRenderer; +import org.olat.core.gui.components.form.flexible.elements.FormLink; +import org.olat.core.gui.render.RenderResult; +import org.olat.core.gui.render.Renderer; +import org.olat.core.gui.render.StringOutput; +import org.olat.core.gui.render.URLBuilder; +import org.olat.core.gui.translator.Translator; +import org.olat.core.util.StringHelper; + +/** + * + * Initial date: 7 févr. 2017<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class SmsPhoneComponentRenderer extends DefaultComponentRenderer { + + @Override + public void render(Renderer renderer, StringOutput sb, Component source, URLBuilder ubu, Translator translator, + RenderResult renderResult, String[] args) { + SmsPhoneComponent smsCmp = (SmsPhoneComponent)source; + SmsPhoneElement smsFte = smsCmp.getSmsPhoneElement(); + String id = smsCmp.getFormDispatchId(); + String phoneNumber = smsFte.getPhone(); + if(!StringHelper.containsNonWhitespace(phoneNumber)) { + phoneNumber = smsFte.getTranslator().translate("sms.phone.not.available"); + } + + sb.append("<p id=\"").append(id).append("\" ") + .append(" class='form-control-static "); + if(StringHelper.containsNonWhitespace(smsCmp.getElementCssClass())) { + sb.append(smsCmp.getElementCssClass()); + } + sb.append("'>").append(phoneNumber).append("</p>"); + + FormLink editLink = smsFte.getEditLink(); + if(editLink != null && editLink.isVisible()) { + Component cmp = editLink.getComponent(); + cmp.getHTMLRendererSingleton().render(renderer, sb, cmp, ubu, translator, renderResult, args); + } + } +} diff --git a/src/main/java/org/olat/user/propertyhandlers/ui/SmsPhoneConfirmController.java b/src/main/java/org/olat/user/propertyhandlers/ui/SmsPhoneConfirmController.java new file mode 100644 index 00000000000..3f13595b4e9 --- /dev/null +++ b/src/main/java/org/olat/user/propertyhandlers/ui/SmsPhoneConfirmController.java @@ -0,0 +1,85 @@ +/** + * <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.propertyhandlers.ui; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.form.flexible.FormItemContainer; +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.FormLayoutContainer; +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.util.StringHelper; + +/** + * + * Initial date: 6 févr. 2017<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class SmsPhoneConfirmController extends FormBasicController { + + private TextElement tokenEl; + + private final String token; + + public SmsPhoneConfirmController(UserRequest ureq, WindowControl wControl, String token) { + super(ureq, wControl); + this.token = token; + initForm(ureq); + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + setFormDescription("sms.change.confirm.descr"); + tokenEl = uifactory.addTextElement("token", "sms.change.confirm.token", 32, "", formLayout); + + FormLayoutContainer buttonsCont = FormLayoutContainer.createButtonLayout("buttons", getTranslator()); + formLayout.add(buttonsCont); + uifactory.addFormSubmitButton("sms.change.confirm", buttonsCont); + } + + @Override + protected void doDispose() { + // + } + + @Override + protected boolean validateFormLogic(UserRequest ureq) { + boolean allOk = true; + + if(StringHelper.containsNonWhitespace(tokenEl.getValue())) { + if(!tokenEl.getValue().equals(token)) { + tokenEl.setErrorKey("error.sms.change.confirm.token", null); + allOk &= false; + } + } else { + tokenEl.setErrorKey("form.legende.mandatory", null); + allOk &= false; + } + return allOk & super.validateFormLogic(ureq); + } + + @Override + protected void formOK(UserRequest ureq) { + fireEvent(ureq, Event.DONE_EVENT); + } +} diff --git a/src/main/java/org/olat/user/propertyhandlers/ui/SmsPhoneController.java b/src/main/java/org/olat/user/propertyhandlers/ui/SmsPhoneController.java new file mode 100644 index 00000000000..191c889d10e --- /dev/null +++ b/src/main/java/org/olat/user/propertyhandlers/ui/SmsPhoneController.java @@ -0,0 +1,90 @@ +/** + * <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.propertyhandlers.ui; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.Component; +import org.olat.core.gui.components.velocity.VelocityContainer; +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.id.User; +import org.olat.user.propertyhandlers.UserPropertyHandler; + +/** + * + * Initial date: 7 févr. 2017<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class SmsPhoneController extends BasicController { + + private final VelocityContainer mainVC; + + private SmsPhoneConfirmController confirmCtrl; + private final SmsPhoneSendController sendTokenCtrl; + + public SmsPhoneController(UserRequest ureq, WindowControl wControl, UserPropertyHandler handler, User userToChange) { + super(ureq, wControl); + + sendTokenCtrl = new SmsPhoneSendController(ureq, getWindowControl(), handler, userToChange); + listenTo(sendTokenCtrl); + + mainVC = createVelocityContainer("edit_sms"); + mainVC.put("cmp", sendTokenCtrl.getInitialComponent()); + putInitialPanel(mainVC); + } + + public String getPhone() { + return sendTokenCtrl.getPhone(); + } + + @Override + protected void doDispose() { + // + } + + @Override + protected void event(UserRequest ureq, Controller source, Event event) { + if(source == sendTokenCtrl) { + if(event == Event.DONE_EVENT) { + doConfirm(ureq); + } else { + fireEvent(ureq, Event.CANCELLED_EVENT); + } + } else if(source == confirmCtrl) { + fireEvent(ureq, event); + } + } + + @Override + protected void event(UserRequest ureq, Component source, Event event) { + // + } + + private void doConfirm(UserRequest ureq) { + if(confirmCtrl == null) { + confirmCtrl = new SmsPhoneConfirmController(ureq, getWindowControl(), sendTokenCtrl.getSentToken()); + listenTo(confirmCtrl); + } + mainVC.put("cmp", confirmCtrl.getInitialComponent()); + } +} diff --git a/src/main/java/org/olat/user/propertyhandlers/ui/SmsPhoneElement.java b/src/main/java/org/olat/user/propertyhandlers/ui/SmsPhoneElement.java new file mode 100644 index 00000000000..f9e1f0c30e4 --- /dev/null +++ b/src/main/java/org/olat/user/propertyhandlers/ui/SmsPhoneElement.java @@ -0,0 +1,167 @@ +/** + * <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.propertyhandlers.ui; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +import org.olat.core.CoreSpringFactory; +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.Windows; +import org.olat.core.gui.components.Component; +import org.olat.core.gui.components.form.flexible.FormItem; +import org.olat.core.gui.components.form.flexible.FormItemCollection; +import org.olat.core.gui.components.form.flexible.elements.FormLink; +import org.olat.core.gui.components.form.flexible.impl.Form; +import org.olat.core.gui.components.form.flexible.impl.FormItemImpl; +import org.olat.core.gui.components.form.flexible.impl.elements.FormLinkImpl; +import org.olat.core.gui.components.link.Link; +import org.olat.core.gui.control.ChiefController; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.ControllerEventListener; +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.User; +import org.olat.core.util.Util; +import org.olat.user.UserManager; +import org.olat.user.propertyhandlers.UserPropertyHandler; + +/** + * + * Initial date: 7 févr. 2017<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class SmsPhoneElement extends FormItemImpl implements FormItemCollection, ControllerEventListener { + + private final SmsPhoneComponent component; + + private String phone; + private final User editedUser; + private final UserPropertyHandler handler; + + private FormLink editLink; + private SmsPhoneController smsPhoneCtrl; + private CloseableModalController cmc; + + public SmsPhoneElement(String name, UserPropertyHandler handler, User editedUser, Locale locale) { + super(name); + setTranslator(Util.createPackageTranslator(SmsPhoneElement.class, locale)); + this.handler = handler; + this.editedUser = editedUser; + setPhone(editedUser.getProperty(handler.getName(), locale)); + component = new SmsPhoneComponent(this); + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public FormLink getEditLink() { + return editLink; + } + + @Override + public void dispatchEvent(UserRequest ureq, Controller source, Event event) { + if(cmc == source) { + smsPhoneCtrl = null; + cmc = null; + } else if(smsPhoneCtrl == source) { + if(event == Event.DONE_EVENT || event == Event.CHANGED_EVENT) { + setPhone(smsPhoneCtrl.getPhone()); + getComponent().setDirty(true); + } + cmc.deactivate(); + smsPhoneCtrl = null; + cmc = null; + } + } + + @Override + public Iterable<FormItem> getFormItems() { + List<FormItem> items = new ArrayList<>(1); + if(editLink != null) { + items.add(editLink); + } + return items; + } + + @Override + public FormItem getFormComponent(String name) { + return null; + } + + @Override + public void setRootForm(Form rootForm) { + String dispatchId = component.getDispatchID(); + editLink = new FormLinkImpl(dispatchId + "_editSmsButton", "editSms", "edit", Link.BUTTON); + editLink.setTranslator(getTranslator()); + editLink.setIconLeftCSS("o_icon o_icon_edit"); + super.setRootForm(rootForm); + } + + @Override + protected Component getFormItemComponent() { + return component; + } + + @Override + protected void rootFormAvailable() { + if(editLink != null && editLink.getRootForm() != getRootForm()) { + editLink.setRootForm(getRootForm()); + } + } + + @Override + public void evalFormRequest(UserRequest ureq) { + Form form = getRootForm(); + String dispatchuri = form.getRequestParameter("dispatchuri"); + if(editLink != null && editLink.getFormDispatchId().equals(dispatchuri)) { + doEdit(ureq); + } + } + + @Override + public void reset() { + // + } + + private void doEdit(UserRequest ureq) { + ChiefController chief = Windows.getWindows(ureq).getChiefController(); + WindowControl wControl = chief.getWindowControl(); + if (wControl != null) { + smsPhoneCtrl = new SmsPhoneController(ureq, wControl, handler, editedUser); + smsPhoneCtrl.addControllerListener(this); + + String propLabel = CoreSpringFactory.getImpl(UserManager.class) + .getPropertyHandlerTranslator(getTranslator()).translate(handler.i18nFormElementLabelKey()); + String title = getTranslator().translate("sms.title", new String[] { propLabel }); + cmc = new CloseableModalController(wControl, "close", smsPhoneCtrl.getInitialComponent(), true, title); + cmc.suppressDirtyFormWarningOnClose(); + cmc.activate(); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/user/propertyhandlers/ui/SmsPhoneSendController.java b/src/main/java/org/olat/user/propertyhandlers/ui/SmsPhoneSendController.java new file mode 100644 index 00000000000..bee123d145b --- /dev/null +++ b/src/main/java/org/olat/user/propertyhandlers/ui/SmsPhoneSendController.java @@ -0,0 +1,131 @@ +/** + * <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.propertyhandlers.ui; + +import org.olat.basesecurity.BaseSecurity; +import org.olat.core.commons.services.sms.SimpleMessageException; +import org.olat.core.commons.services.sms.SimpleMessageService; +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.form.flexible.FormItemContainer; +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.FormLayoutContainer; +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.id.Identity; +import org.olat.core.id.User; +import org.olat.core.util.StringHelper; +import org.olat.core.util.Util; +import org.olat.user.UserManager; +import org.olat.user.propertyhandlers.UserPropertyHandler; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * Initial date: 6 févr. 2017<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class SmsPhoneSendController extends FormBasicController { + + private TextElement newPhoneEl; + + private final String sentToken; + private final User userToChange; + private final UserPropertyHandler handler; + + @Autowired + private UserManager userManager; + @Autowired + private BaseSecurity securityManager; + @Autowired + private SimpleMessageService messageService; + + public SmsPhoneSendController(UserRequest ureq, WindowControl wControl, UserPropertyHandler handler, User userToChange) { + super(ureq, wControl); + setTranslator(userManager.getPropertyHandlerTranslator(Util.createPackageTranslator(SmsPhoneSendController.class, getLocale()))); + this.userToChange = userToChange; + this.handler = handler; + sentToken = messageService.generateToken(); + initForm(ureq); + } + + public String getSentToken() { + return sentToken; + } + + public String getPhone() { + return newPhoneEl.getValue(); + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + setFormDescription("sms.change.number.descr"); + + String i18nLabel = handler.i18nFormElementLabelKey(); + newPhoneEl = uifactory.addTextElement("sms.new.phone", i18nLabel, 32, "", formLayout); + newPhoneEl.setPlaceholderKey("sms.change.number.hint", null); + + FormLayoutContainer buttonsCont = FormLayoutContainer.createButtonLayout("buttons", getTranslator()); + formLayout.add(buttonsCont); + uifactory.addFormSubmitButton("sms.send", "sms.send", buttonsCont); + } + + @Override + protected void doDispose() { + // + } + + @Override + protected boolean validateFormLogic(UserRequest ureq) { + boolean allOk = true; + + newPhoneEl.clearError(); + if(!StringHelper.containsNonWhitespace(newPhoneEl.getValue())) { + newPhoneEl.setErrorKey("form.legende.mandatory", null); + allOk &= false; + } else if(!messageService.validate(newPhoneEl.getValue())) { + newPhoneEl.setErrorKey("error.phone.invalid", null); + allOk &= false; + } + + return allOk & super.validateFormLogic(ureq); + } + + @Override + protected void formOK(UserRequest ureq) { + try { + String msg = translate("sms.token", new String[]{ sentToken }); + String phone = newPhoneEl.getValue(); + + Identity recipient = securityManager.findIdentityByUser(userToChange); + messageService.sendMessage(msg, phone, recipient); + fireEvent(ureq, Event.DONE_EVENT); + } catch (SimpleMessageException e) { + showWarning("warning.message.not.send"); + } + } + + @Override + protected void formCancelled(UserRequest ureq) { + fireEvent(ureq, Event.CANCELLED_EVENT); + } +} diff --git a/src/main/java/org/olat/user/propertyhandlers/ui/_content/edit_sms.html b/src/main/java/org/olat/user/propertyhandlers/ui/_content/edit_sms.html new file mode 100644 index 00000000000..e9c001c718b --- /dev/null +++ b/src/main/java/org/olat/user/propertyhandlers/ui/_content/edit_sms.html @@ -0,0 +1 @@ +$r.render("cmp") \ No newline at end of file diff --git a/src/main/java/org/olat/user/propertyhandlers/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/user/propertyhandlers/ui/_i18n/LocalStrings_de.properties index a50a5a24f9b..29a651f4daa 100644 --- a/src/main/java/org/olat/user/propertyhandlers/ui/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/user/propertyhandlers/ui/_i18n/LocalStrings_de.properties @@ -31,4 +31,16 @@ upc.reset.config.minimal=Minimal upc.reset.config.school=School upc.reset.config.business=Business upc.reset.config.baks=BAKS -upc.defaulttranslation=Standard\u00FCbersetzung \ No newline at end of file +upc.defaulttranslation=Standard\u00FCbersetzung +sms.title={0} ändern +sms.send=SMS Authentifizierung starten +sms.change.number.title=Nummer ändern +sms.change.number.hint=+41 12 345 67 89 +sms.change.number.descr=Die Nummer muss bestätigt werden. Wählen Sie den untenstehenden Button um die SMS Bestätigungscode zu schicken: +sms.phone.not.available=Kein Nummer vorhanden +sms.change.confirm.descr=Geben Sie den Bestätigungscode ein, den Sie per SMS erhalten haben: +sms.change.confirm.token=SMS Bestätigungscode +sms.change.confirm=SMS Code überprüfen +sms.token=Ihr Bestätigungscode ist {0} +error.sms.change.confirm.token=Invalid +error.phone.invalid=Nummer ist nicht gültig \ No newline at end of file diff --git a/src/main/java/org/olat/user/propertyhandlers/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/user/propertyhandlers/ui/_i18n/LocalStrings_en.properties index 6951fdbed23..4e834e1356c 100644 --- a/src/main/java/org/olat/user/propertyhandlers/ui/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/user/propertyhandlers/ui/_i18n/LocalStrings_en.properties @@ -1,4 +1,16 @@ -#Fri Feb 24 11:41:56 CET 2012 +#Tue Feb 07 13:50:53 CET 2017 +error.phone.invalid=The number is not valid. +error.sms.change.confirm.token=The code is not valid. +sms.change.confirm=Enter the SMS code +sms.change.confirm.descr=Enter the 6 digit number you received per SMS\: +sms.change.confirm.token=SMS confirmation code +sms.change.number.descr=The number need a confirmation. Please, choose the button below to send a confirmation code by SMS\: +sms.change.number.hint=+41 12 345 67 89 +sms.change.number.title=Change the number +sms.phone.not.available=Number not available +sms.send=Start authentication by SMS +sms.title=Edit {} +sms.token=Your confirmation code is {0} upc.active=Activ upc.adminonly=Admin only upc.context.edit=edit Context @@ -24,12 +36,13 @@ upc.properties=Properties upc.reset=Reset upc.reset.config.baks=BAKS upc.reset.config.business=Business +upc.reset.config.done=Predefined config loaded... upc.reset.config.minimal=Minimal upc.reset.config.olatdefault=OLAT Default upc.reset.config.school=School upc.reset.configs=Load Preset\: upc.reset.configs.note=Note\: While loading a preset, unknown UserProperties stay activated... -upc.reset.config.done=Predefined config loaded... upc.translate=Translate upc.up=Up upc.userreadonly=User readonly +warning.message.not.send=The SMS cannot be send. diff --git a/src/main/resources/META-INF/persistence.xml b/src/main/resources/META-INF/persistence.xml index f6056eab24c..95f2aa950f6 100644 --- a/src/main/resources/META-INF/persistence.xml +++ b/src/main/resources/META-INF/persistence.xml @@ -33,7 +33,6 @@ <mapping-file>org/olat/course/assessment/model/UserEfficiencyStatementImpl.hbm.xml</mapping-file> <mapping-file>org/olat/modules/openmeetings/model/OpenMeetingsReference.hbm.xml</mapping-file> <mapping-file>org/olat/properties/Property.hbm.xml</mapping-file> - <mapping-file>org/olat/registration/TemporaryKeyImpl.hbm.xml</mapping-file> <mapping-file>org/olat/course/statistic/daily/DailyStat.hbm.xml</mapping-file> <mapping-file>org/olat/course/statistic/dayofweek/DayOfWeekStat.hbm.xml</mapping-file> <mapping-file>org/olat/course/statistic/hourofday/HourOfDayStat.hbm.xml</mapping-file> @@ -92,6 +91,7 @@ <class>org.olat.core.commons.services.taskexecutor.model.PersistentTaskModifier</class> <class>org.olat.core.commons.services.commentAndRating.model.UserRatingImpl</class> <class>org.olat.core.commons.services.commentAndRating.model.UserCommentImpl</class> + <class>org.olat.core.commons.services.sms.model.MessageLogImpl</class> <class>org.olat.course.assessment.model.AssessmentModeImpl</class> <class>org.olat.course.assessment.model.AssessmentModeToAreaImpl</class> <class>org.olat.course.assessment.model.AssessmentModeToGroupImpl</class> @@ -115,6 +115,7 @@ <class>org.olat.group.model.GroupToBusinessGroup</class> <class>org.olat.group.model.BusinessGroupToSearch</class> <class>org.olat.group.BusinessGroupImpl</class> + <class>org.olat.registration.TemporaryKeyImpl</class> <class>org.olat.repository.RepositoryEntry</class> <class>org.olat.repository.model.RepositoryEntryToGroupRelation</class> <class>org.olat.repository.model.RepositoryEntryLifecycle</class> diff --git a/src/main/resources/database/mysql/alter_11_2_x_to_11_3_0.sql b/src/main/resources/database/mysql/alter_11_2_x_to_11_3_0.sql index c021aae0b4f..523a972ebe8 100644 --- a/src/main/resources/database/mysql/alter_11_2_x_to_11_3_0.sql +++ b/src/main/resources/database/mysql/alter_11_2_x_to_11_3_0.sql @@ -1,7 +1,7 @@ create table o_vid_metadata ( id bigint not null auto_increment, - creationdate timestamp not null, - lastmodified timestamp not null, + creationdate datetime not null, + lastmodified datetime not null, vid_width bigint default null, vid_height bigint default null, vid_size bigint default null, @@ -14,3 +14,21 @@ create table o_vid_metadata ( alter table o_vid_metadata ENGINE = InnoDB; alter table o_vid_metadata add constraint vid_meta_rsrc_idx foreign key (fk_resource_id) references o_olatresource (resource_id); + + + +alter table o_user add column u_smstelmobile varchar(255); + +create table o_sms_message_log ( + id bigint not null auto_increment, + creationdate datetime not null, + lastmodified datetime not null, + s_message_uuid varchar(256) not null, + s_server_response varchar(256), + s_service_id varchar(32) not null, + fk_identity bigint not null, + primary key (id) +); +alter table o_sms_message_log ENGINE = InnoDB; + +alter table o_sms_message_log add constraint sms_log_to_identity_idx foreign key (fk_identity) references o_bs_identity (id); diff --git a/src/main/resources/database/mysql/setupDatabase.sql b/src/main/resources/database/mysql/setupDatabase.sql index 1d9106e9683..8c919488a31 100644 --- a/src/main/resources/database/mysql/setupDatabase.sql +++ b/src/main/resources/database/mysql/setupDatabase.sql @@ -230,6 +230,7 @@ create table if not exists o_user ( u_telprivate varchar(255), u_telmobile varchar(255), u_teloffice varchar(255), + u_smstelmobile varchar(255), u_skype varchar(255), u_msn varchar(255), u_xing varchar(255), @@ -1905,6 +1906,18 @@ create table o_ex_task_modifier ( primary key (id) ); +-- sms +create table o_sms_message_log ( + id bigint not null auto_increment, + creationdate datetime not null, + lastmodified datetime not null, + s_message_uuid varchar(256) not null, + s_server_response varchar(256), + s_service_id varchar(32) not null, + fk_identity bigint not null, + primary key (id) +); + -- user view create view o_bs_identity_short_v as ( select @@ -2235,7 +2248,7 @@ alter table o_pf_assignment ENGINE = InnoDB; alter table o_pf_binder_user_infos ENGINE = InnoDB; alter table o_eva_form_session ENGINE = InnoDB; alter table o_eva_form_response ENGINE = InnoDB; - +alter table o_sms_message_log ENGINE = InnoDB; -- rating alter table o_userrating add constraint FKF26C8375236F20X foreign key (creator_id) references o_bs_identity (id); @@ -2692,6 +2705,9 @@ alter table o_cer_certificate add constraint cer_to_resource_idx foreign key (fk create index cer_archived_resource_idx on o_cer_certificate (c_archived_resource_id); create index cer_uuid_idx on o_cer_certificate (c_uuid); +-- sms +alter table o_sms_message_log add constraint sms_log_to_identity_idx foreign key (fk_identity) references o_bs_identity (id); + -- o_logging_table create index log_target_resid_idx on o_loggingtable(targetresid); create index log_ptarget_resid_idx on o_loggingtable(parentresid); diff --git a/src/main/resources/database/oracle/alter_11_2_x_to_11_3_0.sql b/src/main/resources/database/oracle/alter_11_2_x_to_11_3_0.sql index 9bbd58a54bd..d713c012bfd 100644 --- a/src/main/resources/database/oracle/alter_11_2_x_to_11_3_0.sql +++ b/src/main/resources/database/oracle/alter_11_2_x_to_11_3_0.sql @@ -12,4 +12,21 @@ create table o_vid_metadata ( ); alter table o_vid_metadata add constraint vid_meta_rsrc_idx foreign key (fk_resource_id) references o_olatresource (resource_id); -create index idx_vid_meta_rsrc_idx on o_vid_metadata(fk_resource_id); \ No newline at end of file +create index idx_vid_meta_rsrc_idx on o_vid_metadata(fk_resource_id); + + +alter table o_user add u_smstelmobile varchar2(255 char); + +create table o_sms_message_log ( + id number(20) GENERATED ALWAYS AS IDENTITY, + creationdate date not null, + lastmodified date not null, + s_message_uuid varchar2(256 char) not null, + s_server_response varchar2(256 char), + s_service_id varchar2(32 char) not null, + fk_identity number(20) not null, + primary key (id) +); + +alter table o_sms_message_log add constraint sms_log_to_identity_idx foreign key (fk_identity) references o_bs_identity (id); +create index idx_sms_log_to_identity_idx on o_sms_message_log(fk_identity); diff --git a/src/main/resources/database/oracle/setupDatabase.sql b/src/main/resources/database/oracle/setupDatabase.sql index 9aaa09011fb..2f51847d080 100644 --- a/src/main/resources/database/oracle/setupDatabase.sql +++ b/src/main/resources/database/oracle/setupDatabase.sql @@ -259,6 +259,7 @@ CREATE TABLE o_user ( u_telprivate varchar2(255 char), u_telmobile varchar2(255 char), u_teloffice varchar2(255 char), + u_smstelmobile varchar2(255 char), u_skype varchar2(255 char), u_msn varchar2(255 char), u_xing varchar2(255 char), @@ -1949,6 +1950,18 @@ create table o_co_db_entry ( primary key (id) ); +-- sms +create table o_sms_message_log ( + id number(20) GENERATED ALWAYS AS IDENTITY, + creationdate date not null, + lastmodified date not null, + s_message_uuid varchar2(256 char) not null, + s_server_response varchar2(256 char), + s_service_id varchar2(32 char) not null, + fk_identity number(20) not null, + primary key (id) +); + -- user view create view o_bs_identity_short_v as ( select @@ -2885,6 +2898,10 @@ create index cer_resource_idx on o_cer_certificate (fk_olatresource); create index cer_archived_resource_idx on o_cer_certificate (c_archived_resource_id); create index cer_uuid_idx on o_cer_certificate (c_uuid); +-- sms +alter table o_sms_message_log add constraint sms_log_to_identity_idx foreign key (fk_identity) references o_bs_identity (id); +create index idx_sms_log_to_identity_idx on o_sms_message_log(fk_identity); + -- o_logging_table create index log_target_resid_idx on o_loggingtable(targetresid); create index log_ptarget_resid_idx on o_loggingtable(parentresid); diff --git a/src/main/resources/database/postgresql/alter_11_2_x_to_11_3_0.sql b/src/main/resources/database/postgresql/alter_11_2_x_to_11_3_0.sql index 8d495aff18d..fa2ce5850a7 100644 --- a/src/main/resources/database/postgresql/alter_11_2_x_to_11_3_0.sql +++ b/src/main/resources/database/postgresql/alter_11_2_x_to_11_3_0.sql @@ -2,14 +2,32 @@ create table o_vid_metadata ( id bigserial not null, creationdate timestamp not null, lastmodified timestamp not null, - vid_width bigint default null, - vid_height bigint default null, - vid_size bigint default null, + vid_width int8 default null, + vid_height int8 default null, + vid_size int8 default null, vid_format varchar(32) default null, vid_length varchar(32) default null, - fk_resource_id bigint not null, + fk_resource_id int8 not null, primary key (id) ); alter table o_vid_metadata add constraint vid_meta_rsrc_idx foreign key (fk_resource_id) references o_olatresource (resource_id); -create index idx_vid_meta_rsrc_idx on o_vid_metadata(fk_resource_id); \ No newline at end of file +create index idx_vid_meta_rsrc_idx on o_vid_metadata(fk_resource_id); + + + + +alter table o_user add column u_smstelmobile varchar(255); + +create table o_sms_message_log ( + id bigserial not null, + creationdate timestamp not null, + lastmodified timestamp not null, + s_message_uuid varchar(256) not null, s_server_response varchar(256), + s_service_id varchar(32) not null, + fk_identity int8 not null, + primary key (id) +); + +alter table o_sms_message_log add constraint sms_log_to_identity_idx foreign key (fk_identity) references o_bs_identity (id); +create index idx_sms_log_to_identity_idx on o_sms_message_log(fk_identity); diff --git a/src/main/resources/database/postgresql/setupDatabase.sql b/src/main/resources/database/postgresql/setupDatabase.sql index 3488c69638a..e44a49bd49f 100644 --- a/src/main/resources/database/postgresql/setupDatabase.sql +++ b/src/main/resources/database/postgresql/setupDatabase.sql @@ -228,6 +228,7 @@ create table o_user ( u_telprivate varchar(255), u_telmobile varchar(255), u_teloffice varchar(255), + u_smstelmobile varchar(255), u_skype varchar(255), u_msn varchar(255), u_xing varchar(255), @@ -1315,12 +1316,12 @@ create table o_vid_metadata ( id bigserial not null, creationdate timestamp not null, lastmodified timestamp not null, - vid_width bigint default null, - vid_height bigint default null, - vid_size bigint default null, + vid_width int8 default null, + vid_height int8 default null, + vid_size int8 default null, vid_format varchar(32) default null, vid_length varchar(32) default null, - fk_resource_id bigint not null, + fk_resource_id int8 not null, primary key (id) ); @@ -1903,6 +1904,17 @@ create table o_ex_task_modifier ( primary key (id) ); +-- sms +create table o_sms_message_log ( + id bigserial not null, + creationdate timestamp not null, + lastmodified timestamp not null, + s_message_uuid varchar(256) not null, s_server_response varchar(256), + s_service_id varchar(32) not null, + fk_identity int8 not null, + primary key (id) +); + -- user view create view o_bs_identity_short_v as ( select @@ -2736,6 +2748,10 @@ create index cer_resource_idx on o_cer_certificate (fk_olatresource); create index cer_archived_resource_idx on o_cer_certificate (c_archived_resource_id); create index cer_uuid_idx on o_cer_certificate (c_uuid); +-- sms +alter table o_sms_message_log add constraint sms_log_to_identity_idx foreign key (fk_identity) references o_bs_identity (id); +create index idx_sms_log_to_identity_idx on o_sms_message_log(fk_identity); + -- o_logging_table create index log_target_resid_idx on o_loggingtable(targetresid); create index log_ptarget_resid_idx on o_loggingtable(parentresid); diff --git a/src/main/resources/serviceconfig/olat.properties b/src/main/resources/serviceconfig/olat.properties index 045d530515d..0d2ffebcbec 100644 --- a/src/main/resources/serviceconfig/olat.properties +++ b/src/main/resources/serviceconfig/olat.properties @@ -1029,6 +1029,20 @@ build.repo.revision=local-devel ##### log.anonymous=false +######################################## +# Simple message service +######################################## +message.enabled=false +message.provider=Dummy +message.provider.values=Dummy,WebSMS + +#Features using the sms +message.reset.password.enabled=true + +#WebSMS configuration +websms.username= +websms.password= + ######################################## # Access control ######################################## diff --git a/src/test/java/org/olat/core/commons/services/sms/manager/MessageLogDAOTest.java b/src/test/java/org/olat/core/commons/services/sms/manager/MessageLogDAOTest.java new file mode 100644 index 00000000000..186e6ac5ed7 --- /dev/null +++ b/src/test/java/org/olat/core/commons/services/sms/manager/MessageLogDAOTest.java @@ -0,0 +1,87 @@ +/** + * <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.core.commons.services.sms.manager; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; +import org.olat.core.commons.persistence.DB; +import org.olat.core.commons.services.sms.MessageLog; +import org.olat.core.commons.services.sms.model.MessageStatistics; +import org.olat.core.id.Identity; +import org.olat.test.JunitTestHelper; +import org.olat.test.OlatTestCase; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * Initial date: 3 févr. 2017<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class MessageLogDAOTest extends OlatTestCase { + + @Autowired + private DB dbInstance; + @Autowired + private MessageLogDAO messageLogDao; + + @Test + public void createMessageLog() { + Identity recipient = JunitTestHelper.createAndPersistIdentityAsRndUser("sms-1"); + MessageLog mLog = messageLogDao.create(recipient, "devnull"); + Assert.assertNotNull(mLog); + Assert.assertNotNull(mLog.getCreationDate()); + Assert.assertNotNull(mLog.getMessageUuid()); + Assert.assertNotNull(mLog.getServiceId()); + } + + @Test + public void createAndPersistMessageLog() { + Identity recipient = JunitTestHelper.createAndPersistIdentityAsRndUser("sms-2"); + MessageLog mLog = messageLogDao.create(recipient, "devnull"); + Assert.assertNotNull(mLog); + mLog = messageLogDao.save(mLog); + dbInstance.commitAndCloseSession(); + + MessageLog reloadedLog = messageLogDao.loadMessageByKey(mLog.getKey()); + Assert.assertNotNull(mLog); + Assert.assertNotNull(reloadedLog.getCreationDate()); + Assert.assertEquals(mLog, reloadedLog); + Assert.assertEquals(mLog.getMessageUuid(), reloadedLog.getMessageUuid()); + Assert.assertEquals(recipient, reloadedLog.getRecipient()); + Assert.assertEquals("devnull", mLog.getServiceId()); + } + + @Test + public void getStatisticsPerMonth() { + Identity recipient = JunitTestHelper.createAndPersistIdentityAsRndUser("sms-2"); + MessageLog mLog = messageLogDao.create(recipient, "devnull"); + Assert.assertNotNull(mLog); + mLog = messageLogDao.save(mLog); + dbInstance.commitAndCloseSession(); + + List<MessageStatistics> stats = messageLogDao.getStatisticsPerMonth("devnull"); + Assert.assertNotNull(stats); + + } + +} diff --git a/src/test/java/org/olat/core/commons/services/sms/spi/WebSMSProviderTest.java b/src/test/java/org/olat/core/commons/services/sms/spi/WebSMSProviderTest.java new file mode 100644 index 00000000000..68cd351ee7f --- /dev/null +++ b/src/test/java/org/olat/core/commons/services/sms/spi/WebSMSProviderTest.java @@ -0,0 +1,48 @@ +/** + * <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.core.commons.services.sms.spi; + +import java.util.UUID; + +import org.junit.Assert; +import org.junit.Test; +import org.olat.test.OlatTestCase; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * Initial date: 3 févr. 2017<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class WebSMSProviderTest extends OlatTestCase { + + @Autowired + private WebSMSProvider webSmsProvider; + + @Test + public void send() { + //webSmsProvider.setCredentials("stephane.rosse@frentix.com", "secret"); + webSmsProvider.setTest(true); + boolean ok = webSmsProvider.send(UUID.randomUUID().toString(), "Hello from jenkins", "41797346615"); + Assert.assertTrue(ok); + } + +} diff --git a/src/test/java/org/olat/registration/RegistrationManagerTest.java b/src/test/java/org/olat/registration/RegistrationManagerTest.java index 8300c073422..4b1aa800213 100644 --- a/src/test/java/org/olat/registration/RegistrationManagerTest.java +++ b/src/test/java/org/olat/registration/RegistrationManagerTest.java @@ -31,8 +31,10 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import java.util.List; import java.util.UUID; +import org.junit.Assert; import org.junit.Test; import org.olat.core.commons.persistence.DB; import org.olat.test.OlatTestCase; @@ -64,12 +66,13 @@ public class RegistrationManagerTest extends OlatTestCase { */ @Test public void testRegister() { - String emailaddress = "sabina@jeger.net"; + String emailaddress = UUID.randomUUID() + "@openolat.com"; String ipaddress = "130.60.112.10"; - TemporaryKeyImpl result = registrationManager.register(emailaddress, ipaddress, "register"); - assertTrue(result != null); - assertEquals(emailaddress,result.getEmailAddress()); - assertEquals(ipaddress,result.getIpAddress()); + + TemporaryKey result = registrationManager.register(emailaddress, ipaddress, "register"); + Assert.assertTrue(result != null); + Assert.assertEquals(emailaddress, result.getEmailAddress()); + Assert.assertEquals(ipaddress, result.getIpAddress()); } @@ -78,27 +81,43 @@ public class RegistrationManagerTest extends OlatTestCase { */ @Test public void testLoadTemporaryKeyByRegistrationKey() { - String emailaddress = "christian.guretzki@id.uzh.ch"; + String emailaddress = UUID.randomUUID() + "@openolat.com"; String regkey = ""; - TemporaryKeyImpl result = null; String ipaddress = "130.60.112.12"; - // - result = registrationManager.loadTemporaryKeyByRegistrationKey(regkey); - assertTrue("not found, as registration key is empty", result == null); + TemporaryKey result1 = registrationManager.loadTemporaryKeyByRegistrationKey(regkey); + Assert.assertNull("not found, as registration key is empty", result1); //now create a temp key - result = registrationManager.createTemporaryKeyByEmail(emailaddress,ipaddress, RegistrationManager.REGISTRATION); - assertTrue("result not null because key generated", result != null); - //** - dbInstance.closeSession(); - regkey = result.getRegistrationKey(); - //** - + TemporaryKey result2 = registrationManager.createTemporaryKeyByEmail(emailaddress, ipaddress, RegistrationManager.REGISTRATION); + Assert.assertNotNull("result not null because key generated", result2); + dbInstance.commitAndCloseSession(); + + //check that loading the key by registration key works + TemporaryKey reloadedResult = registrationManager.loadTemporaryKeyByRegistrationKey(result2.getRegistrationKey()); + Assert.assertNotNull("we should find the key just created", reloadedResult); + Assert.assertEquals(result2, reloadedResult); + } + + /** + * Test load of temp key. + */ + @Test + public void testLoadTemporaryKeyByAction() { + String emailaddress = UUID.randomUUID() + "@openolat.com"; + String regAction = UUID.randomUUID().toString(); + String ipaddress = "130.60.112.12"; + + //now create a temporary key + TemporaryKey result = registrationManager.createTemporaryKeyByEmail(emailaddress, ipaddress, regAction); + Assert.assertNotNull("result not null because key generated", result); + dbInstance.commitAndCloseSession(); + //check that loading the key by registration key works - result = null; - result = registrationManager.loadTemporaryKeyByRegistrationKey(regkey); - assertTrue("we should find the key just created", result != null); + List<TemporaryKey> reloadedResults = registrationManager.loadTemporaryKeyByAction(regAction); + Assert.assertNotNull(reloadedResults); + Assert.assertEquals(1, reloadedResults.size()); + Assert.assertEquals(result, reloadedResults.get(0)); } /** @@ -106,48 +125,38 @@ public class RegistrationManagerTest extends OlatTestCase { */ @Test public void testLoadTemporaryKeyEntry() { - String emailaddress = UUID.randomUUID().toString().replace("-", "") + "@frentix.com"; - TemporaryKeyImpl result = null; + String emailaddress = UUID.randomUUID() + "@frentix.com"; String ipaddress = "130.60.112.11"; //try to load temp key which was not created before - result = registrationManager.loadTemporaryKeyByEmail(emailaddress); - assertTrue("result should be null, because not found", result == null); + TemporaryKey result = registrationManager.loadTemporaryKeyByEmail(emailaddress); + Assert.assertTrue("result should be null, because not found", result == null); //now create a temp key - result = registrationManager.createTemporaryKeyByEmail(emailaddress,ipaddress, RegistrationManager.REGISTRATION); - assertTrue("result not null because key generated", result != null); - //** - dbInstance.closeSession(); - //** + TemporaryKey realResult = registrationManager.createTemporaryKeyByEmail(emailaddress,ipaddress, RegistrationManager.REGISTRATION); + Assert.assertNotNull("result not null because key generated", realResult); + dbInstance.commitAndCloseSession(); //check that loading the key by e-mail works - result = null; - result = registrationManager.loadTemporaryKeyByEmail(emailaddress); - assertTrue("we shoult find the key just created", result != null); + TemporaryKey reloadResult = registrationManager.loadTemporaryKeyByEmail(emailaddress); + Assert.assertNotNull("we shoult find the key just created", reloadResult); + Assert.assertEquals(realResult, reloadResult); } - /** * Test load of temp key. */ @Test public void testCreateTemporaryKeyEntry() { - String emailaddress = "sabina@jeger.net"; - TemporaryKeyImpl result = null; + String emailaddress = UUID.randomUUID() + "@openolat.com"; String ipaddress = "130.60.112.10"; - result = registrationManager.createTemporaryKeyByEmail(emailaddress,ipaddress, RegistrationManager.REGISTRATION); - assertTrue(result != null); - - emailaddress = "sabina@jeger.ch"; - result = registrationManager.createTemporaryKeyByEmail(emailaddress,ipaddress, RegistrationManager.REGISTRATION); - - assertTrue(result != null); - - emailaddress = "info@jeger.net"; - result = registrationManager.createTemporaryKeyByEmail(emailaddress,ipaddress, RegistrationManager.REGISTRATION); - - assertNotNull(result); + TemporaryKey result = registrationManager.createTemporaryKeyByEmail(emailaddress, ipaddress, RegistrationManager.REGISTRATION); + dbInstance.commitAndCloseSession(); + Assert.assertNotNull(result); + Assert.assertNotNull(result.getKey()); + Assert.assertNotNull(result.getCreationDate()); + Assert.assertEquals(ipaddress, result.getIpAddress()); + Assert.assertEquals(emailaddress, result.getEmailAddress()); } @Test diff --git a/src/test/java/org/olat/test/AllTestsJunit4.java b/src/test/java/org/olat/test/AllTestsJunit4.java index 26bd9fd12a1..17cee890688 100644 --- a/src/test/java/org/olat/test/AllTestsJunit4.java +++ b/src/test/java/org/olat/test/AllTestsJunit4.java @@ -93,6 +93,7 @@ import org.junit.runners.Suite; org.olat.core.commons.services.webdav.manager.DigestAuthenticationTest.class, org.olat.core.commons.services.webdav.manager.WebDAVManagerTest.class, org.olat.core.commons.services.webdav.servlets.RequestUtilsTest.class, + org.olat.core.commons.services.sms.manager.MessageLogDAOTest.class, org.olat.core.commons.services.taskexecutor.PersistentTaskDAOTest.class, org.olat.core.commons.services.taskexecutor.TaskExecutorManagerTest.class, org.olat.admin.user.delete.service.UserDeletionManagerTest.class, -- GitLab