Skip to content
Snippets Groups Projects
Commit 27327e0c authored by srosse's avatar srosse
Browse files

OO-3919: BulkSMS as SMS provider and UI to configure the SPIes

parent 5019e023
No related branches found
No related tags found
No related merge requests found
Showing
with 615 additions and 45 deletions
...@@ -19,6 +19,11 @@ ...@@ -19,6 +19,11 @@
*/ */
package org.olat.core.commons.services.sms; package org.olat.core.commons.services.sms;
import org.olat.core.commons.services.sms.ui.AbstractSMSConfigurationController;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.form.flexible.impl.Form;
import org.olat.core.gui.control.WindowControl;
/** /**
* *
* Initial date: 3 févr. 2017<br> * Initial date: 3 févr. 2017<br>
...@@ -32,6 +37,8 @@ public interface MessagesSPI { ...@@ -32,6 +37,8 @@ public interface MessagesSPI {
public String getName(); public String getName();
public boolean isValid(); public boolean isValid();
public AbstractSMSConfigurationController getConfigurationController(UserRequest ureq, WindowControl wControl, Form form);
public boolean send(String messageId, String text, String recipient) throws SimpleMessageException; public boolean send(String messageId, String text, String recipient) throws SimpleMessageException;
......
...@@ -42,13 +42,16 @@ import org.springframework.stereotype.Service; ...@@ -42,13 +42,16 @@ import org.springframework.stereotype.Service;
@Service @Service
public class SimpleMessageModule extends AbstractSpringModule implements ConfigOnOff { public class SimpleMessageModule extends AbstractSpringModule implements ConfigOnOff {
public static final String SMS_ENABLED = "message.enabled"; private static final String SMS_ENABLED = "message.enabled";
public static final String RESET_PASSWORD_ENABLED = "message.reset.password.enabled"; private static final String PROVIDER_ID = "message.provider.id";
private static final String RESET_PASSWORD_ENABLED = "message.reset.password.enabled";
@Value("${message.enabled:false}") @Value("${message.enabled:false}")
private boolean enabled; private boolean enabled;
@Value("${message.reset.password.enabled:true}") @Value("${message.reset.password.enabled:true}")
private boolean resetPassword; private boolean resetPassword;
@Value("${message.provider:WebSMS}")
private String providerId;
@Autowired @Autowired
...@@ -66,11 +69,13 @@ public class SimpleMessageModule extends AbstractSpringModule implements ConfigO ...@@ -66,11 +69,13 @@ public class SimpleMessageModule extends AbstractSpringModule implements ConfigO
enabled = "true".equals(enabledObj); enabled = "true".equals(enabledObj);
} }
String resetPasswordEnabledObj = getStringPropertyValue(RESET_PASSWORD_ENABLED, true); String resetEnabledObj = getStringPropertyValue(RESET_PASSWORD_ENABLED, true);
if(StringHelper.containsNonWhitespace(resetPasswordEnabledObj)) { if(StringHelper.containsNonWhitespace(resetEnabledObj)) {
resetPassword = "true".equals(resetPasswordEnabledObj); resetPassword = "true".equals(resetEnabledObj);
} }
providerId = getStringPropertyValue(PROVIDER_ID, providerId);
if(enabled) {//check if(enabled) {//check
enableSmsUserProperty(); enableSmsUserProperty();
} }
...@@ -127,6 +132,12 @@ public class SimpleMessageModule extends AbstractSpringModule implements ConfigO ...@@ -127,6 +132,12 @@ public class SimpleMessageModule extends AbstractSpringModule implements ConfigO
setStringProperty(RESET_PASSWORD_ENABLED, Boolean.toString(resetPassword), true); setStringProperty(RESET_PASSWORD_ENABLED, Boolean.toString(resetPassword), true);
} }
public String getProviderId() {
return providerId == null ? null : providerId.toLowerCase();
}
public void setProviderId(String providerId) {
this.providerId = providerId;
setStringProperty(PROVIDER_ID, providerId, true);
}
} }
...@@ -29,6 +29,10 @@ import org.olat.core.commons.services.sms.SimpleMessageException; ...@@ -29,6 +29,10 @@ import org.olat.core.commons.services.sms.SimpleMessageException;
import org.olat.core.commons.services.sms.SimpleMessageModule; import org.olat.core.commons.services.sms.SimpleMessageModule;
import org.olat.core.commons.services.sms.SimpleMessageService; import org.olat.core.commons.services.sms.SimpleMessageService;
import org.olat.core.commons.services.sms.model.MessageStatistics; import org.olat.core.commons.services.sms.model.MessageStatistics;
import org.olat.core.commons.services.sms.ui.AbstractSMSConfigurationController;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.form.flexible.impl.Form;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.helpers.Settings; import org.olat.core.helpers.Settings;
import org.olat.core.id.Identity; import org.olat.core.id.Identity;
import org.olat.core.id.UserConstants; import org.olat.core.id.UserConstants;
...@@ -84,7 +88,7 @@ public class SimpleMessageServiceImpl implements SimpleMessageService { ...@@ -84,7 +88,7 @@ public class SimpleMessageServiceImpl implements SimpleMessageService {
number = number.replace("+", "").replace(" ", ""); number = number.replace("+", "").replace(" ", "");
if(StringHelper.isLong(number)) { if(StringHelper.isLong(number)) {
try { try {
Long phone = new Long(number); Long phone = Long.valueOf(number);
return phone > 0; return phone > 0;
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
// //
...@@ -134,8 +138,15 @@ public class SimpleMessageServiceImpl implements SimpleMessageService { ...@@ -134,8 +138,15 @@ public class SimpleMessageServiceImpl implements SimpleMessageService {
public MessagesSPI getMessagesSpi() { public MessagesSPI getMessagesSpi() {
if(Settings.isDebuging()) return new DevNullProvider(); if(Settings.isDebuging()) return new DevNullProvider();
if(messageModule.isEnabled() && messagesSpiList.size() > 0) { if(messageModule.isEnabled() && !messagesSpiList.isEmpty()) {
return messagesSpiList.get(0); String providerId = messageModule.getProviderId();
if(StringHelper.containsNonWhitespace(providerId) && !"devnull".equals(providerId)) {
for(MessagesSPI spi:messagesSpiList) {
if(providerId.equalsIgnoreCase(spi.getId())) {
return spi;
}
}
}
} }
return new DevNullProvider(); return new DevNullProvider();
} }
...@@ -157,6 +168,11 @@ public class SimpleMessageServiceImpl implements SimpleMessageService { ...@@ -157,6 +168,11 @@ public class SimpleMessageServiceImpl implements SimpleMessageService {
return true; return true;
} }
@Override
public AbstractSMSConfigurationController getConfigurationController(UserRequest ureq, WindowControl wControl, Form form) {
return null;
}
@Override @Override
public boolean send(String messageId, String text, String recipient) { public boolean send(String messageId, String text, String recipient) {
log.info("Send: " + text); log.info("Send: " + text);
......
/**
* <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.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.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicHeader;
import org.apache.http.util.EntityUtils;
import org.json.JSONObject;
import org.olat.core.commons.services.sms.MessagesSPI;
import org.olat.core.commons.services.sms.SimpleMessageException;
import org.olat.core.commons.services.sms.ui.BulksSMSConfigurationController;
import org.olat.core.configuration.AbstractSpringModule;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.form.flexible.impl.Form;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing;
import org.olat.core.util.StringHelper;
import org.olat.core.util.coordinate.CoordinatorManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
/**
*
* Initial date: 4 mars 2019<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
@Service("messagesSpiBulkSMS")
public class BulkSMSProvider extends AbstractSpringModule implements MessagesSPI {
private static final OLog log = Tracing.createLoggerFor(BulkSMSProvider.class);
private static final String TOKEN_ID = "bulksms.token.id";
private static final String TOKEN_SECRET = "bulksms.token.secret";
@Value("${websms.url:https://api.bulksms.com/v1/messages}")
private String url;
@Value("${bulksms.token.id:}")
private String tokenId;
@Value("${bulksms.token.secret:}")
private String tokenSecret;
@Autowired
public BulkSMSProvider(CoordinatorManager coordinatorManager) {
super(coordinatorManager);
}
@Override
public void init() {
updateProperties();
}
@Override
protected void initFromChangedProperties() {
updateProperties();
}
private void updateProperties() {
tokenId = getStringPropertyValue(TOKEN_ID, tokenId);
tokenSecret = getStringPropertyValue(TOKEN_SECRET, tokenSecret);
}
@Override
public String getId() {
return "bulksms";
}
@Override
public String getName() {
return "BulkSMS";
}
@Override
public boolean isValid() {
return StringHelper.containsNonWhitespace(tokenId) && StringHelper.containsNonWhitespace(tokenSecret);
}
@Override
public BulksSMSConfigurationController getConfigurationController(UserRequest ureq, WindowControl wControl, Form form) {
return new BulksSMSConfigurationController(ureq, wControl, form);
}
public String getTokenId() {
return tokenId;
}
public void setTokenId(String tokenId) {
this.tokenId = tokenId;
setSecretStringProperty(TOKEN_ID, tokenId, true);
}
public String getTokenSecret() {
return tokenSecret;
}
public void setTokenSecret(String tokenSecret) {
this.tokenSecret = tokenSecret;
setSecretStringProperty(TOKEN_SECRET, tokenSecret, true);
}
@Override
public boolean send(String messageId, String text, String recipient)
throws SimpleMessageException {
HttpPost send = new HttpPost(url + "?deduplication-id=" + messageId);
String token = StringHelper.encodeBase64(tokenId + ":" + tokenSecret);
send.setHeader(new BasicHeader("Authorization", "Basic " + token));
send.setHeader(new BasicHeader("Content-Type", "application/json"));
try(CloseableHttpClient httpclient = HttpClientBuilder.create().build()) {
String phone = recipient.replace("+", "").replace(" ", "");
String objectStr = jsonPayload(text, 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 == 201) {
return true;
}
log.error("WebSMS return an error code " + returnCode + ": " + responseString);
return false;
} catch(Exception e) {
log.error("", e);
return false;
}
}
private String jsonPayload(String text, String recipient) {
try {
JSONObject message = new JSONObject();
message.put("body", text);
message.put("to", recipient);
message.put("encoding", "UNICODE");
return message.toString();
} catch (Exception e) {
log.error("", e);
return null;
}
}
}
...@@ -33,10 +33,16 @@ import org.apache.http.util.EntityUtils; ...@@ -33,10 +33,16 @@ import org.apache.http.util.EntityUtils;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONObject; import org.json.JSONObject;
import org.olat.core.commons.services.sms.MessagesSPI; import org.olat.core.commons.services.sms.MessagesSPI;
import org.olat.core.commons.services.sms.ui.WebSMSConfigurationController;
import org.olat.core.configuration.AbstractSpringModule;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.form.flexible.impl.Form;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.logging.OLog; import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing; import org.olat.core.logging.Tracing;
import org.olat.core.util.StringHelper; import org.olat.core.util.StringHelper;
import org.springframework.beans.factory.InitializingBean; import org.olat.core.util.coordinate.CoordinatorManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
...@@ -48,11 +54,14 @@ import org.springframework.stereotype.Service; ...@@ -48,11 +54,14 @@ import org.springframework.stereotype.Service;
* *
*/ */
@Service("messagesSpiWebSMS") @Service("messagesSpiWebSMS")
public class WebSMSProvider implements MessagesSPI, InitializingBean { public class WebSMSProvider extends AbstractSpringModule implements MessagesSPI {
private static final OLog log = Tracing.createLoggerFor(WebSMSProvider.class); private static final OLog log = Tracing.createLoggerFor(WebSMSProvider.class);
private final BasicCredentialsProvider provider = new BasicCredentialsProvider(); private final BasicCredentialsProvider provider = new BasicCredentialsProvider();
private static final String NAME = "websms.username";
private static final String CREDENTIALS = "websms.password";
@Value("${websms.url:https://api.websms.com/rest/smsmessaging/text}") @Value("${websms.url:https://api.websms.com/rest/smsmessaging/text}")
private String url; private String url;
...@@ -63,6 +72,11 @@ public class WebSMSProvider implements MessagesSPI, InitializingBean { ...@@ -63,6 +72,11 @@ public class WebSMSProvider implements MessagesSPI, InitializingBean {
private boolean test = false; private boolean test = false;
@Autowired
public WebSMSProvider(CoordinatorManager coordinatorManager) {
super(coordinatorManager);
}
/** /**
* Method means for unit tests. The changes are not persisted. * Method means for unit tests. The changes are not persisted.
* *
...@@ -76,6 +90,24 @@ public class WebSMSProvider implements MessagesSPI, InitializingBean { ...@@ -76,6 +90,24 @@ public class WebSMSProvider implements MessagesSPI, InitializingBean {
new UsernamePasswordCredentials(username, password)); new UsernamePasswordCredentials(username, password));
} }
@Override
public void init() {
updateProperties();
}
@Override
protected void initFromChangedProperties() {
updateProperties();
}
private void updateProperties() {
username = getStringPropertyValue(NAME, username);
password = getStringPropertyValue(CREDENTIALS, password);
provider.setCredentials(new AuthScope("api.websms.com", 443),
new UsernamePasswordCredentials(username, password));
}
protected void setTest(boolean test) { protected void setTest(boolean test) {
this.test = test; this.test = test;
} }
...@@ -94,11 +126,28 @@ public class WebSMSProvider implements MessagesSPI, InitializingBean { ...@@ -94,11 +126,28 @@ public class WebSMSProvider implements MessagesSPI, InitializingBean {
public boolean isValid() { public boolean isValid() {
return StringHelper.containsNonWhitespace(username) && StringHelper.containsNonWhitespace(password); return StringHelper.containsNonWhitespace(username) && StringHelper.containsNonWhitespace(password);
} }
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
setSecretStringProperty(NAME, username, true);
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
setSecretStringProperty(CREDENTIALS, password, true);
}
@Override @Override
public void afterPropertiesSet() throws Exception { public WebSMSConfigurationController getConfigurationController(UserRequest ureq, WindowControl wControl, Form form) {
provider.setCredentials(new AuthScope("api.websms.com", 443), return new WebSMSConfigurationController(ureq, wControl, form);
new UsernamePasswordCredentials(username, password));
} }
@Override @Override
...@@ -109,7 +158,7 @@ public class WebSMSProvider implements MessagesSPI, InitializingBean { ...@@ -109,7 +158,7 @@ public class WebSMSProvider implements MessagesSPI, InitializingBean {
.build()) { .build()) {
String phone = recipient.replace("+", "").replace(" ", ""); String phone = recipient.replace("+", "").replace(" ", "");
String objectStr = jsonPayload(messageId, text, new Long(phone)); String objectStr = jsonPayload(messageId, text, Long.valueOf(phone));
HttpEntity smsEntity = new StringEntity(objectStr, ContentType.APPLICATION_JSON); HttpEntity smsEntity = new StringEntity(objectStr, ContentType.APPLICATION_JSON);
send.setEntity(smsEntity); send.setEntity(smsEntity);
CloseableHttpResponse response = httpclient.execute(send); CloseableHttpResponse response = httpclient.execute(send);
......
/**
* <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.form.flexible.impl.Form;
import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
import org.olat.core.gui.control.WindowControl;
/**
*
* Initial date: 6 mars 2019<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
public abstract class AbstractSMSConfigurationController extends FormBasicController {
public AbstractSMSConfigurationController(UserRequest ureq, WindowControl wControl, Form form) {
super(ureq, wControl, LAYOUT_DEFAULT, null, form);
}
@Override
protected boolean validateFormLogic(UserRequest ureq) {
return super.validateFormLogic(ureq);
}
@Override
protected void formOK(UserRequest ureq) {
//
}
}
/**
* <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.spi.BulkSMSProvider;
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.Form;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.util.StringHelper;
import org.springframework.beans.factory.annotation.Autowired;
/**
*
* Initial date: 6 mars 2019<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
public class BulksSMSConfigurationController extends AbstractSMSConfigurationController {
private TextElement tokenIdEl;
private TextElement tokenSecretEl;
@Autowired
private BulkSMSProvider bulkSmsProvider;
public BulksSMSConfigurationController(UserRequest ureq, WindowControl wControl, Form form) {
super(ureq, wControl, form);
initForm(ureq);
}
@Override
protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
String tokenId = bulkSmsProvider.getTokenId();
tokenIdEl = uifactory.addTextElement("bulksms.token.id", 128, tokenId, formLayout);
tokenIdEl.setMandatory(true);
String tokenSecret = bulkSmsProvider.getTokenSecret();
tokenSecretEl = uifactory.addTextElement("bulksms.token.secret", 128, tokenSecret, formLayout);
tokenSecretEl.setMandatory(true);
}
@Override
protected void doDispose() {
//
}
@Override
protected boolean validateFormLogic(UserRequest ureq) {
boolean allOk = super.validateFormLogic(ureq);
tokenIdEl.clearError();
if(!StringHelper.containsNonWhitespace(tokenIdEl.getValue())) {
tokenIdEl.setErrorKey("form.legende.mandatory", null);
allOk &= false;
}
tokenSecretEl.clearError();
if(!StringHelper.containsNonWhitespace(tokenSecretEl.getValue())) {
tokenSecretEl.setErrorKey("form.legende.mandatory", null);
allOk &= false;
}
return allOk;
}
@Override
protected void formOK(UserRequest ureq) {
bulkSmsProvider.setTokenId(tokenIdEl.getValue());
bulkSmsProvider.setTokenSecret(tokenSecretEl.getValue());
}
}
...@@ -31,6 +31,7 @@ import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElem ...@@ -31,6 +31,7 @@ import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElem
import org.olat.core.gui.components.form.flexible.elements.SingleSelection; 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.FormBasicController;
import org.olat.core.gui.components.form.flexible.impl.FormEvent; import org.olat.core.gui.components.form.flexible.impl.FormEvent;
import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer;
import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.WindowControl;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
...@@ -49,39 +50,49 @@ public class SimpleMessageServiceAdminConfigurationController extends FormBasicC ...@@ -49,39 +50,49 @@ public class SimpleMessageServiceAdminConfigurationController extends FormBasicC
private MultipleSelectionElement enableEl; private MultipleSelectionElement enableEl;
private MultipleSelectionElement resetPasswordEl; private MultipleSelectionElement resetPasswordEl;
private AbstractSMSConfigurationController providerConfigCtrl;
@Autowired @Autowired
private SimpleMessageModule messageModule; private SimpleMessageModule messageModule;
@Autowired @Autowired
private SimpleMessageService messagesService; private SimpleMessageService messagesService;
public SimpleMessageServiceAdminConfigurationController(UserRequest ureq, WindowControl wControl) { public SimpleMessageServiceAdminConfigurationController(UserRequest ureq, WindowControl wControl) {
super(ureq, wControl); super(ureq, wControl, "admin_configuration");
initForm(ureq); initForm(ureq);
updateEnableDisable();
updateProviderConfiguration(ureq);
} }
@Override @Override
protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
FormLayoutContainer serviceCont = FormLayoutContainer.createDefaultFormLayout("service", getTranslator());
formLayout.add(serviceCont);
setFormTitle("admin.configuration.title"); setFormTitle("admin.configuration.title");
setFormDescription("admin.configuration.description"); setFormDescription("admin.configuration.description");
String[] onValues = new String[]{ translate("on") }; String[] onValues = new String[]{ translate("on") };
enableEl = uifactory.addCheckboxesHorizontal("enable", "admin.enable", formLayout, onKeys, onValues); enableEl = uifactory.addCheckboxesHorizontal("enable", "admin.enable", serviceCont, onKeys, onValues);
enableEl.addActionListener(FormEvent.ONCHANGE); enableEl.addActionListener(FormEvent.ONCHANGE);
if(messageModule.isEnabled()) { if(messageModule.isEnabled()) {
enableEl.select(onKeys[0], true); enableEl.select(onKeys[0], true);
} }
List<MessagesSPI> spies = messagesService.getMessagesSpiList(); List<MessagesSPI> spies = messagesService.getMessagesSpiList();
String[] serviceKeys = new String[spies.size()]; String[] serviceKeys = new String[spies.size() + 1];
String[] serviceValues = new String[spies.size()]; String[] serviceValues = new String[spies.size() + 1];
serviceKeys[0] = "devnull";
serviceValues[0] = translate("no.service.provider");
for(int i=spies.size(); i-->0; ) { for(int i=spies.size(); i-->0; ) {
serviceKeys[i] = spies.get(i).getId(); serviceKeys[i + 1] = spies.get(i).getId();
serviceValues[i] = spies.get(i).getName(); serviceValues[i + 1] = spies.get(i).getName();
} }
serviceEl = uifactory.addDropdownSingleselect("service", "service", formLayout, serviceKeys, serviceValues, null); serviceEl = uifactory.addDropdownSingleselect("service.providers", "service", serviceCont, serviceKeys, serviceValues, null);
serviceEl.addActionListener(FormEvent.ONCHANGE);
if(messagesService.getMessagesSpi() != null) { if(messagesService.getMessagesSpi() != null) {
String activeServiceId = messagesService.getMessagesSpi().getId(); String activeServiceId = messageModule.getProviderId();
for(int i=serviceKeys.length; i-->0; ) { for(int i=serviceKeys.length; i-->0; ) {
if(serviceKeys[i].equals(activeServiceId)) { if(serviceKeys[i].equals(activeServiceId)) {
serviceEl.select(serviceKeys[i], true); serviceEl.select(serviceKeys[i], true);
...@@ -90,12 +101,34 @@ public class SimpleMessageServiceAdminConfigurationController extends FormBasicC ...@@ -90,12 +101,34 @@ public class SimpleMessageServiceAdminConfigurationController extends FormBasicC
} }
String[] resetPasswordValues = new String[]{ translate("on.sms") }; String[] resetPasswordValues = new String[]{ translate("on.sms") };
resetPasswordEl = uifactory.addCheckboxesHorizontal("reset.password", "reset.password", formLayout, onKeys, resetPasswordValues); resetPasswordEl = uifactory.addCheckboxesHorizontal("reset.password", "reset.password", serviceCont, onKeys, resetPasswordValues);
resetPasswordEl.addActionListener(FormEvent.ONCHANGE);
if(messageModule.isResetPasswordEnabled()) { if(messageModule.isResetPasswordEnabled()) {
resetPasswordEl.select(onKeys[0], true); resetPasswordEl.select(onKeys[0], true);
} }
updateEnableDisable();
FormLayoutContainer buttonCont = FormLayoutContainer.createButtonLayout("buttons", getTranslator());
formLayout.add(buttonCont);
uifactory.addFormSubmitButton("save", buttonCont);
}
private void updateProviderConfiguration(UserRequest ureq) {
removeControllerListener(providerConfigCtrl);
if(serviceEl.isOneSelected()) {
flc.remove("configuration");
String selectedProviderId = serviceEl.getSelectedKey();
List<MessagesSPI> spies = messagesService.getMessagesSpiList();
for(MessagesSPI spi:spies) {
if(spi.getId().equals(selectedProviderId)) {
providerConfigCtrl = spi.getConfigurationController(ureq, getWindowControl(), mainForm);
if(providerConfigCtrl != null) {
flc.add("configuration", providerConfigCtrl.getInitialFormItem());
}
}
}
} else {
flc.remove("configuration");
}
} }
private void updateEnableDisable() { private void updateEnableDisable() {
...@@ -118,23 +151,32 @@ public class SimpleMessageServiceAdminConfigurationController extends FormBasicC ...@@ -118,23 +151,32 @@ public class SimpleMessageServiceAdminConfigurationController extends FormBasicC
// //
} }
@Override
protected boolean validateFormLogic(UserRequest ureq) {
boolean allOk = super.validateFormLogic(ureq);
if(providerConfigCtrl != null) {
allOk &= providerConfigCtrl.validateFormLogic(ureq);
}
return allOk;
}
@Override @Override
protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
if(enableEl == source) { if(enableEl == source) {
updateEnableDisable(); updateEnableDisable();
messageModule.setEnabled(enableEl.isAtLeastSelected(1)); } else if(serviceEl == source) {
} else if(resetPasswordEl == source) { updateProviderConfiguration(ureq);
messageModule.setResetPasswordEnabled(resetPasswordEl.isAtLeastSelected(1));
} }
super.formInnerEvent(ureq, source, event); super.formInnerEvent(ureq, source, event);
} }
@Override @Override
protected void formOK(UserRequest ureq) { protected void formOK(UserRequest ureq) {
// messageModule.setEnabled(enableEl.isAtLeastSelected(1));
messageModule.setResetPasswordEnabled(resetPasswordEl.isAtLeastSelected(1));
messageModule.setProviderId(serviceEl.getSelectedKey());
if(providerConfigCtrl != null) {
providerConfigCtrl.formOK(ureq);
}
} }
} }
/**
* <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.spi.WebSMSProvider;
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.Form;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.util.StringHelper;
import org.springframework.beans.factory.annotation.Autowired;
/**
*
* Initial date: 6 mars 2019<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
public class WebSMSConfigurationController extends AbstractSMSConfigurationController {
private static final String PLACEHOLDER = "xxx-placeholder-xxx";
private TextElement usernameEl;
private TextElement passwordEl;
private String replacedValue;
@Autowired
private WebSMSProvider webSmsProvider;
public WebSMSConfigurationController(UserRequest ureq, WindowControl wControl, Form form) {
super(ureq, wControl, form);
initForm(ureq);
}
@Override
protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
String uname = webSmsProvider.getUsername();
usernameEl = uifactory.addTextElement("websms.username", 128, uname, formLayout);
usernameEl.setMandatory(true);
String creds = webSmsProvider.getPassword();
if(StringHelper.containsNonWhitespace(creds)) {
replacedValue = creds;
creds = PLACEHOLDER;
}
passwordEl = uifactory.addPasswordElement("websms.password", "websms.password", 128, creds, formLayout);
passwordEl.setMandatory(true);
}
@Override
protected void doDispose() {
//
}
@Override
protected boolean validateFormLogic(UserRequest ureq) {
boolean allOk = super.validateFormLogic(ureq);
usernameEl.clearError();
if(!StringHelper.containsNonWhitespace(usernameEl.getValue())) {
usernameEl.setErrorKey("form.legende.mandatory", null);
allOk &= false;
}
passwordEl.clearError();
if(!StringHelper.containsNonWhitespace(passwordEl.getValue())) {
passwordEl.setErrorKey("form.legende.mandatory", null);
allOk &= false;
} else if(!PLACEHOLDER.equals(passwordEl.getValue())) {
replacedValue = passwordEl.getValue();
passwordEl.setValue(PLACEHOLDER);
}
return allOk;
}
@Override
protected void formOK(UserRequest ureq) {
webSmsProvider.setUsername(usernameEl.getValue());
String credential = passwordEl.getValue();
if(!PLACEHOLDER.equals(credential)) {
webSmsProvider.setPassword(credential);
passwordEl.setValue(PLACEHOLDER);
} else if(StringHelper.containsNonWhitespace(replacedValue)) {
webSmsProvider.setPassword(replacedValue);
}
}
}
$r.render("service")
#if($r.available("configuration"))
$r.render("configuration")
#end
<div class="o_form form-horizontal"><div class="form-group clearfix">
<div class="col-sm-offset-3 col-sm-9">
$r.render("buttons")
</div>
</div></div>
\ No newline at end of file
#Tue Feb 07 13:58:37 CET 2017 #Wed Mar 06 14:56:25 CET 2019
admin.configuration.description=<p>Die Benachrichtigung per SMS ist eine optionale Komponente.</p><p>Achtung\: durch das Versenden von SMS entstehen Kosten pro SMS\!</p> admin.configuration.description=<p>Die Benachrichtigung 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.configuration.title=SMS Konfiguration
admin.enable=SMS Versand admin.enable=SMS Versand
...@@ -6,23 +6,28 @@ admin.menu.title=SMS ...@@ -6,23 +6,28 @@ admin.menu.title=SMS
admin.menu.title.alt=SMS Konfiguration udn Statistik admin.menu.title.alt=SMS Konfiguration udn Statistik
admin.settings=SMS Dienst Konfiguration admin.settings=SMS Dienst Konfiguration
admin.statistics=SMS Versand admin.statistics=SMS Versand
bulksms.token.id=Token ID
bulksms.token.secret=Token secret
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> 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 dont.activate=Nicht aktivieren
error.invalid.token=Token stimmt nicht\! error.invalid.token=Token stimmt nicht\!
error.phone.invalid=Das Nummer ist nicht valid (z.B. +41 12 345 67 89) error.phone.invalid=Das Nummer ist nicht valid (z.B. +41 12 345 67 89)
no.service.provider=Kein Provider angew\u00E4hlt
on=ein on=ein
on.sms=mit SMS Code on.sms=mit SMS Code
start.sms.authentication=SMS Authentifizierung starten
reset.password=Password zur\u00FCcksetzen reset.password=Password zur\u00FCcksetzen
service=Dienst service=Dienst
sms.phone.number=Telephon Mobil sms.phone.number=Telephon Mobil
sms.phone.number.hint=+41 12 345 67 89
sms.phone.number.example=Sie m\u00FCssen Ihre Telefonnummer im internationalen Format angeben (+41 12 345 67 89). sms.phone.number.example=Sie m\u00FCssen Ihre Telefonnummer im internationalen Format angeben (+41 12 345 67 89).
sms.phone.number.hint=+41 12 345 67 89
sms.send=SMS Authentifizierung starten sms.send=SMS Authentifizierung starten
sms.token=Ihr Token ist {0} sms.token=Ihr Token ist {0}
sms.token.number=Token sms.token.number=Token
sms.token.number.explain=Geben Sie den Best\u00E4tigungscode ein, den Sie per SMS erhalten haben. Falls Sie nach 1 Minute noch keine SMS erhalten haben, überprüfen Sie bitte, ob Sie das korrekte internationale Nummernformat verwendet haben. sms.token.number.explain=Geben Sie den Best\u00E4tigungscode ein, den Sie per SMS erhalten haben. Falls Sie nach 1 Minute noch keine SMS erhalten haben, \u00FCberpr\u00FCfen Sie bitte, ob Sie das korrekte internationale Nummernformat verwendet haben.
start.sms.authentication=SMS Authentifizierung starten
table.header.month=Monat table.header.month=Monat
table.header.numOfMessages=SMS table.header.numOfMessages=SMS
table.header.year=Jahr table.header.year=Jahr
warning.spi.not.configured=Dienst ist nicht konfiguriert warning.spi.not.configured=Dienst ist nicht konfiguriert
websms.password=Passwort
websms.username=Benutzername
#Tue Feb 07 13:47:28 CET 2017 #Wed Mar 06 14:56:12 CET 2019
admin.configuration.description=<p>Notification with SMS is an optional component.</p><p>Warning\: SMS costs occurred per SMS\!</p> admin.configuration.description=<p>Notification with SMS is an optional component.</p><p>Warning\: SMS costs occurred per SMS\!</p>
admin.configuration.title=SMS configuration admin.configuration.title=SMS configuration
admin.enable=SMS distribution admin.enable=SMS distribution
...@@ -6,23 +6,28 @@ admin.menu.title=SMS ...@@ -6,23 +6,28 @@ admin.menu.title=SMS
admin.menu.title.alt=SMS configuration and statistics admin.menu.title.alt=SMS configuration and statistics
admin.settings=SMS service configuration admin.settings=SMS service configuration
admin.statistics=SMS distribution admin.statistics=SMS distribution
bulksms.token.id=Token ID
bulksms.token.secret=Token secret
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> 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 dont.activate=Don't activate
error.invalid.token=The code is not valid. 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) error.phone.invalid=The number is not a valid phone number (e.g. +41 12 345 67 89)
no.service.provider=No provider selected
on=on on=on
on.sms=with SMS code on.sms=with SMS code
start.sms.authentication=Start SMS Authentication
reset.password=Reset password reset.password=Reset password
service=Service service=Service
sms.phone.number=Mobile telefon sms.phone.number=Mobile telefon
sms.phone.number.hint=+41 12 345 67 89
sms.phone.number.example=You need to enter your phone number in the international format (e.g. +41 12 345 67 89). sms.phone.number.example=You need to enter your phone number in the international format (e.g. +41 12 345 67 89).
sms.phone.number.hint=+41 12 345 67 89
sms.send=Start authentication by SMS sms.send=Start authentication by SMS
sms.token=Your token is {0} sms.token=Your token is {0}
sms.token.number=Code sms.token.number=Code
sms.token.number.explain=Please enter the 6 digit number that you received by SMS. If you don't receive a SMS after 1 minute, please make sure you used the correct international number format. sms.token.number.explain=Please enter the 6 digit number that you received by SMS. If you don't receive a SMS after 1 minute, please make sure you used the correct international number format.
start.sms.authentication=Start SMS Authentication
table.header.month=Month table.header.month=Month
table.header.numOfMessages=SMS table.header.numOfMessages=SMS
table.header.year=Year table.header.year=Year
warning.spi.not.configured=The service is not configured. warning.spi.not.configured=The service is not configured.
websms.password=Password
websms.username=User name
#Wed Mar 08 12:06:24 CET 2017 #Wed Mar 06 14:57:26 CET 2019
admin.configuration.description=<p>La notifications par SMS est un composant optionnel.</p><p>Attention\: l'envoi de SMS occasione des co\u00FBts\!</p> admin.configuration.description=<p>La notifications par SMS est un composant optionnel.</p><p>Attention\: l'envoi de SMS occasione des co\u00FBts\!</p>
admin.configuration.title=Configuration SMS admin.configuration.title=Configuration SMS
admin.enable=Distribution SMS admin.enable=Distribution SMS
...@@ -6,10 +6,13 @@ admin.menu.title=SMS ...@@ -6,10 +6,13 @@ admin.menu.title=SMS
admin.menu.title.alt=Configuration SMS et statistiques admin.menu.title.alt=Configuration SMS et statistiques
admin.settings=Configuration du service SMS admin.settings=Configuration du service SMS
admin.statistics=Distribution de SMS admin.statistics=Distribution de SMS
bulksms.token.id=Token ID
bulksms.token.secret=Token secret
confirm.sms.phone=<h3>Authentication par SMS</h3><p>Le syst\u00E8me permet de s'authentifier par SMS en cas d''oubli du mot de passe. Pour activer cette fonction, veuillez entrer votre num\u00E9ro de t\u00E9l\u00E9phone portable.</p> confirm.sms.phone=<h3>Authentication par SMS</h3><p>Le syst\u00E8me permet de s'authentifier par SMS en cas d''oubli du mot de passe. Pour activer cette fonction, veuillez entrer votre num\u00E9ro de t\u00E9l\u00E9phone portable.</p>
dont.activate=Ne pas activer dont.activate=Ne pas activer
error.invalid.token=Le code n'est pas valide. error.invalid.token=Le code n'est pas valide.
error.phone.invalid=Le num\u00E9ro n'est pas un num\u00E9ro de t\u00E9l\u00E9phone valide (par exemple +41 12 345 67 89) error.phone.invalid=Le num\u00E9ro n'est pas un num\u00E9ro de t\u00E9l\u00E9phone valide (par exemple +41 12 345 67 89)
no.service.provider=Aucun
on=Activ\u00E9 on=Activ\u00E9
on.sms=par code SMS on.sms=par code SMS
reset.password=R\u00E9initialiser le mot de passe reset.password=R\u00E9initialiser le mot de passe
...@@ -26,3 +29,5 @@ table.header.month=Mois ...@@ -26,3 +29,5 @@ table.header.month=Mois
table.header.numOfMessages=SMS table.header.numOfMessages=SMS
table.header.year=Ann\u00E9e table.header.year=Ann\u00E9e
warning.spi.not.configured=Le service n'est pas configur\u00E9. warning.spi.not.configured=Le service n'est pas configur\u00E9.
websms.password=Mot de passe
websms.username=Nom d'utilisateur
...@@ -297,9 +297,12 @@ public class FormLayoutContainer extends FormItemImpl implements FormItemContain ...@@ -297,9 +297,12 @@ public class FormLayoutContainer extends FormItemImpl implements FormItemContain
* remove the component with the give name from this container * remove the component with the give name from this container
* @param binderName * @param binderName
*/ */
@Override
public void remove(String formCompName) { public void remove(String formCompName) {
FormItem toBeRemoved = getFormComponent(formCompName); FormItem toBeRemoved = getFormComponent(formCompName);
remove(formCompName, toBeRemoved); if(toBeRemoved != null) {
remove(formCompName, toBeRemoved);
}
} }
private void remove(String formCompName, FormItem toBeRemoved) { private void remove(String formCompName, FormItem toBeRemoved) {
......
#Thu Feb 28 14:56:33 CET 2019 #Wed Mar 06 14:57:30 CET 2019
analysis.details=D\u00E9tails des tendances analysis.details=D\u00E9tails des tendances
analysis.details.print.title={0}\: {1}
analysis.export=Exporter Excel analysis.export=Exporter Excel
analysis.pdf=Exporter au format PDF analysis.pdf=Exporter au format PDF
analysis.print=Imprimer analysis.print=Imprimer
......
#Thu Feb 28 14:58:47 CET 2019 #Wed Mar 06 14:57:45 CET 2019
add.role=Ajouter un nouveau r\u00F4le add.role=Ajouter un nouveau r\u00F4le
admin.menu.title=R\u00F4le utilisateur \u00E0 utilisateur admin.menu.title=R\u00F4le utilisateur \u00E0 utilisateur
admin.menu.title.alt=R\u00F4le utilisateur \u00E0 utilisateur admin.menu.title.alt=R\u00F4le utilisateur \u00E0 utilisateur
...@@ -16,6 +16,7 @@ role.identifier=Identifiant ...@@ -16,6 +16,7 @@ role.identifier=Identifiant
role.name=R\u00F4le role.name=R\u00F4le
role.rights=Permissions role.rights=Permissions
table.header.id=ID table.header.id=ID
table.header.identifier=Identifiant
table.header.managed=<i class\='o_icon o_icon_managed'> </i> table.header.managed=<i class\='o_icon o_icon_managed'> </i>
table.header.role=R\u00F4le table.header.role=R\u00F4le
table.header.role.contra=R\u00F4le inverse table.header.role.contra=R\u00F4le inverse
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment