Author: mdisabatino
Date: Wed May 14 11:54:58 2014
New Revision: 1594549
URL: http://svn.apache.org/r1594549
Log:
[SYNCOPE-445] Provide a text field to specify whatever notification recipient
Modified:
syncope/trunk/common/src/main/java/org/apache/syncope/common/SyncopeConstants.java
syncope/trunk/common/src/main/java/org/apache/syncope/common/to/NotificationTO.java
syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/NotificationModalPage.java
syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/NotificationModalPage.html
syncope/trunk/console/src/test/java/org/apache/syncope/console/ConfigurationTestITCase.java
syncope/trunk/core/src/main/java/org/apache/syncope/core/notification/NotificationManager.java
syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/beans/Notification.java
syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/validation/attrvalue/EmailAddressValidator.java
syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/validation/entity/NotificationValidator.java
syncope/trunk/core/src/test/java/org/apache/syncope/core/notification/NotificationTest.java
syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/dao/NotificationTest.java
syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/NotificationTestITCase.java
Modified:
syncope/trunk/common/src/main/java/org/apache/syncope/common/SyncopeConstants.java
URL:
http://svn.apache.org/viewvc/syncope/trunk/common/src/main/java/org/apache/syncope/common/SyncopeConstants.java?rev=1594549&r1=1594548&r2=1594549&view=diff
==============================================================================
---
syncope/trunk/common/src/main/java/org/apache/syncope/common/SyncopeConstants.java
(original)
+++
syncope/trunk/common/src/main/java/org/apache/syncope/common/SyncopeConstants.java
Wed May 14 11:54:58 2014
@@ -18,6 +18,8 @@
*/
package org.apache.syncope.common;
+import java.util.regex.Pattern;
+
public class SyncopeConstants {
public static final String NAMESPACE = "http://syncope.apache.org/1.2";
@@ -42,4 +44,9 @@ public class SyncopeConstants {
public static final String ROOT_LOGGER = "ROOT";
+ public static final Pattern EMAIL_PATTERN = Pattern.compile(
+ "^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*"
+ +
"@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$",
+ Pattern.CASE_INSENSITIVE);
+
}
Modified:
syncope/trunk/common/src/main/java/org/apache/syncope/common/to/NotificationTO.java
URL:
http://svn.apache.org/viewvc/syncope/trunk/common/src/main/java/org/apache/syncope/common/to/NotificationTO.java?rev=1594549&r1=1594548&r2=1594549&view=diff
==============================================================================
---
syncope/trunk/common/src/main/java/org/apache/syncope/common/to/NotificationTO.java
(original)
+++
syncope/trunk/common/src/main/java/org/apache/syncope/common/to/NotificationTO.java
Wed May 14 11:54:58 2014
@@ -45,6 +45,8 @@ public class NotificationTO extends Abst
private String recipients;
+ private List<String> staticRecipients = new ArrayList<String>();
+
private IntMappingType recipientAttrType;
private String recipientAttrName;
@@ -74,6 +76,13 @@ public class NotificationTO extends Abst
return events;
}
+ @XmlElementWrapper(name = "staticRecipients")
+ @XmlElement(name = "staticRecipient")
+ @JsonProperty("staticRecipients")
+ public List<String> getStaticRecipients() {
+ return staticRecipients;
+ }
+
public Long getId() {
return id;
}
Modified:
syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/NotificationModalPage.java
URL:
http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/NotificationModalPage.java?rev=1594549&r1=1594548&r2=1594549&view=diff
==============================================================================
---
syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/NotificationModalPage.java
(original)
+++
syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/NotificationModalPage.java
Wed May 14 11:54:58 2014
@@ -36,6 +36,7 @@ import org.apache.syncope.console.rest.N
import org.apache.syncope.console.wicket.markup.html.form.AjaxCheckBoxPanel;
import
org.apache.syncope.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
import org.apache.syncope.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.console.wicket.markup.html.form.MultiFieldPanel;
import org.apache.wicket.PageReference;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
@@ -171,6 +172,19 @@ class NotificationModalPage extends Base
form.add(recipientsContainer);
+ final AjaxTextFieldPanel staticRecipientsFieldPanel
+ = new AjaxTextFieldPanel("panel", "staticRecipients", new
Model<String>(null));
+
staticRecipientsFieldPanel.addValidator(EmailAddressValidator.getInstance());
+
+ if (notificationTO.getStaticRecipients().isEmpty()) {
+ notificationTO.getStaticRecipients().add(null);
+ }
+
+ final MultiFieldPanel staticRecipients = new
MultiFieldPanel("staticRecipients",
+ new PropertyModel<List<String>>(notificationTO,
"staticRecipients"), staticRecipientsFieldPanel);
+
+ form.add(staticRecipients);
+
final AjaxCheckBoxPanel selfAsRecipient = new
AjaxCheckBoxPanel("selfAsRecipient",
getString("selfAsRecipient"), new
PropertyModel<Boolean>(notificationTO, "selfAsRecipient"));
form.add(selfAsRecipient);
@@ -229,7 +243,8 @@ class NotificationModalPage extends Base
protected void onSubmit(final AjaxRequestTarget target, final
Form<?> form) {
notificationTO.setAbout(checkAbout.getModelObject() ? null :
about.buildFIQL());
notificationTO.setRecipients(checkRecipients.getModelObject()
? recipients.buildFIQL() : null);
-
+
notificationTO.getStaticRecipients().removeAll(Collections.singleton(null));
+
try {
if (createFlag) {
restClient.createNotification(notificationTO);
Modified:
syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/NotificationModalPage.html
URL:
http://svn.apache.org/viewvc/syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/NotificationModalPage.html?rev=1594549&r1=1594548&r2=1594549&view=diff
==============================================================================
---
syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/NotificationModalPage.html
(original)
+++
syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/NotificationModalPage.html
Wed May 14 11:54:58 2014
@@ -145,6 +145,14 @@ under the License.
</div>
<div id="recipients">
+ <div class="tablerow alt">
+ <div class="tablecolumn_label medium_fixedsize">
+ <label for="recipients"><wicket:message
key="recipients"/></label>
+ </div>
+ <div class="tablecolumn_field medium_dynamicsize">
+ <span wicket:id="staticRecipients">[staticRecipients]</span>
+ </div>
+ </div>
<div class="tablerow" style="width: auto; display: block;">
<div class="tablecolumn_field" style="width: auto;
padding-right: 5px;">
<span wicket:id="selfAsRecipient">[selfAsRecipient]</span>
Modified:
syncope/trunk/console/src/test/java/org/apache/syncope/console/ConfigurationTestITCase.java
URL:
http://svn.apache.org/viewvc/syncope/trunk/console/src/test/java/org/apache/syncope/console/ConfigurationTestITCase.java?rev=1594549&r1=1594548&r2=1594549&view=diff
==============================================================================
---
syncope/trunk/console/src/test/java/org/apache/syncope/console/ConfigurationTestITCase.java
(original)
+++
syncope/trunk/console/src/test/java/org/apache/syncope/console/ConfigurationTestITCase.java
Wed May 14 11:54:58 2014
@@ -173,6 +173,9 @@ public class ConfigurationTestITCase ext
selenium.click("//div[2]/form/div[3]/ul/li[4]/a/span");
+ selenium.type(
+
"name=staticRecipients:multiValueContainer:view:0:panel:textField",
"[email protected]");
+
selenium.waitForCondition("selenium.isElementPresent("
+ "\"//div[2]/form/div[3]/div[4]/div/div[2]/label\");",
"30000");
Modified:
syncope/trunk/core/src/main/java/org/apache/syncope/core/notification/NotificationManager.java
URL:
http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/notification/NotificationManager.java?rev=1594549&r1=1594548&r2=1594549&view=diff
==============================================================================
---
syncope/trunk/core/src/main/java/org/apache/syncope/core/notification/NotificationManager.java
(original)
+++
syncope/trunk/core/src/main/java/org/apache/syncope/core/notification/NotificationManager.java
Wed May 14 11:54:58 2014
@@ -184,6 +184,10 @@ public class NotificationManager {
}
}
+ if (notification.getStaticRecipients() != null) {
+ recipientEmails.addAll(notification.getStaticRecipients());
+ }
+
model.put("recipients", recipientTOs);
model.put("syncopeConf", this.findAllSyncopeConfs());
model.put("events", notification.getEvents());
Modified:
syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/beans/Notification.java
URL:
http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/beans/Notification.java?rev=1594549&r1=1594548&r2=1594549&view=diff
==============================================================================
---
syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/beans/Notification.java
(original)
+++
syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/beans/Notification.java
Wed May 14 11:54:58 2014
@@ -54,6 +54,10 @@ public class Notification extends Abstra
private String recipients;
+ @ElementCollection(fetch = FetchType.EAGER)
+ @Column(name = "staticRecipients")
+ private List<String> staticRecipients;
+
@NotNull
@Enumerated(EnumType.STRING)
private IntMappingType recipientAttrType;
@@ -82,6 +86,7 @@ public class Notification extends Abstra
public Notification() {
events = new ArrayList<String>();
+ staticRecipients = new ArrayList<String>();
selfAsRecipient = getBooleanAsInteger(false);
traceLevel = TraceLevel.ALL;
}
@@ -141,6 +146,25 @@ public class Notification extends Abstra
}
}
+ public List<String> getStaticRecipients() {
+ return staticRecipients;
+ }
+
+ public boolean addStaticRecipient(String staticRecipient) {
+ return staticRecipient != null &&
!staticRecipients.contains(staticRecipient) &&
staticRecipients.add(staticRecipient);
+ }
+
+ public boolean removeStaticRecipient(String staticRecipient) {
+ return staticRecipient != null &&
staticRecipients.remove(staticRecipient);
+ }
+
+ public void setStaticRecipients(List<String> staticRecipients) {
+ this.staticRecipients.clear();
+ if (staticRecipients != null) {
+ this.staticRecipients.addAll(staticRecipients);
+ }
+ }
+
public boolean isSelfAsRecipient() {
return isBooleanAsInteger(selfAsRecipient);
}
Modified:
syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/validation/attrvalue/EmailAddressValidator.java
URL:
http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/validation/attrvalue/EmailAddressValidator.java?rev=1594549&r1=1594548&r2=1594549&view=diff
==============================================================================
---
syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/validation/attrvalue/EmailAddressValidator.java
(original)
+++
syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/validation/attrvalue/EmailAddressValidator.java
Wed May 14 11:54:58 2014
@@ -19,8 +19,7 @@
package org.apache.syncope.core.persistence.validation.attrvalue;
import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
+import org.apache.syncope.common.SyncopeConstants;
import org.apache.syncope.core.persistence.beans.AbstractAttrValue;
import org.apache.syncope.core.persistence.beans.AbstractNormalSchema;
@@ -28,18 +27,13 @@ public class EmailAddressValidator exten
private static final long serialVersionUID = 792457177290331518L;
- private static final Pattern EMAIL_PATTERN = Pattern.compile(
- "^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*"
- +
"@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$",
- Pattern.CASE_INSENSITIVE);
-
public EmailAddressValidator(final AbstractNormalSchema schema) {
super(schema);
}
@Override
protected void doValidate(final AbstractAttrValue attributeValue) throws
InvalidAttrValueException {
- Matcher matcher =
EMAIL_PATTERN.matcher(attributeValue.<CharSequence>getValue());
+ Matcher matcher =
SyncopeConstants.EMAIL_PATTERN.matcher(attributeValue.<CharSequence>getValue());
if (!matcher.matches()) {
throw new InvalidAttrValueException("\"" +
attributeValue.getValue() + "\" is not a valid email address");
}
Modified:
syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/validation/entity/NotificationValidator.java
URL:
http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/validation/entity/NotificationValidator.java?rev=1594549&r1=1594548&r2=1594549&view=diff
==============================================================================
---
syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/validation/entity/NotificationValidator.java
(original)
+++
syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/validation/entity/NotificationValidator.java
Wed May 14 11:54:58 2014
@@ -18,8 +18,9 @@
*/
package org.apache.syncope.core.persistence.validation.entity;
+import java.util.regex.Matcher;
import javax.validation.ConstraintValidatorContext;
-
+import org.apache.syncope.common.SyncopeConstants;
import org.apache.syncope.common.types.EntityViolationType;
import org.apache.syncope.core.persistence.beans.Notification;
@@ -39,6 +40,20 @@ public class NotificationValidator exten
addNode("events").addConstraintViolation();
}
+ if (!value.getStaticRecipients().isEmpty()) {
+ for (String mail : value.getStaticRecipients()) {
+ Matcher matcher = SyncopeConstants.EMAIL_PATTERN.matcher(mail);
+ if (!matcher.matches()) {
+ LOG.error("Invalid mail address: {}", mail);
+ isValid = false;
+
+ context.buildConstraintViolationWithTemplate(
+
getTemplate(EntityViolationType.InvalidNotification, "Invalid mail address: " +
mail)).
+
addNode("staticRecipients").addConstraintViolation();
+ }
+ }
+ }
+
return isValid;
}
}
Modified:
syncope/trunk/core/src/test/java/org/apache/syncope/core/notification/NotificationTest.java
URL:
http://svn.apache.org/viewvc/syncope/trunk/core/src/test/java/org/apache/syncope/core/notification/NotificationTest.java?rev=1594549&r1=1594548&r2=1594549&view=diff
==============================================================================
---
syncope/trunk/core/src/test/java/org/apache/syncope/core/notification/NotificationTest.java
(original)
+++
syncope/trunk/core/src/test/java/org/apache/syncope/core/notification/NotificationTest.java
Wed May 14 11:54:58 2014
@@ -28,6 +28,7 @@ import com.icegreen.greenmail.util.Serve
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
+import java.util.Set;
import javax.annotation.Resource;
import javax.mail.Flags.Flag;
@@ -35,7 +36,6 @@ import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Store;
-
import org.apache.commons.lang3.StringUtils;
import org.apache.syncope.client.SyncopeClient;
import org.apache.syncope.common.SyncopeConstants;
@@ -252,10 +252,10 @@ public class NotificationTest {
assertNotNull(taskId);
assertNotNull(textBody);
assertTrue("Notification mail text doesn't contain expected content.",
- textBody.contains("Your email address is
[email protected]."));
+ textBody.contains("Your email address is
[email protected]."));
assertTrue("Notification mail text doesn't contain expected content.",
- textBody.contains("Your email address inside a link: "
- +
"http://localhost/?email=notificationtest%40syncope.apache.org ."));
+ textBody.contains("Your email address inside a link: "
+ +
"http://localhost/?email=notificationtest%40syncope.apache.org ."));
// 5. execute Notification task and verify e-mail
taskController.execute(taskId, false);
@@ -429,4 +429,63 @@ public class NotificationTest {
confDAO.save(retryConf);
confDAO.flush();
}
+
+ @Test
+ public void issueSYNCOPE445() throws Exception {
+ // 1. create suitable notification for subsequent tests
+ Notification notification = new Notification();
+ notification.addEvent("[REST]:[UserController]:[]:[create]:[SUCCESS]");
+
notification.setAbout(SyncopeClient.getUserSearchConditionBuilder().hasRoles(7L).query());
+
notification.setRecipients(SyncopeClient.getUserSearchConditionBuilder().hasRoles(8L).query());
+ notification.setSelfAsRecipient(true);
+
+ notification.setRecipientAttrName("email");
+ notification.setRecipientAttrType(IntMappingType.UserSchema);
+
+
notification.getStaticRecipients().add("[email protected]");
+
+ Random random = new Random(System.currentTimeMillis());
+ String sender = "syncopetest-" + random.nextLong() +
"@syncope.apache.org";
+ notification.setSender(sender);
+ String subject = "Test notification " + random.nextLong();
+ notification.setSubject(subject);
+ notification.setTemplate("optin");
+
+ Notification actual = notificationDAO.save(notification);
+ assertNotNull(actual);
+
+ notificationDAO.flush();
+
+ // 2. create user
+ UserTO userTO = UserTestITCase.getSampleTO(mailAddress);
+ MembershipTO membershipTO = new MembershipTO();
+ membershipTO.setRoleId(7);
+ userTO.getMemberships().add(membershipTO);
+
+ userController.create(userTO);
+
+ // 3. force Quartz job execution and verify e-mail
+ notificationJob.execute(null);
+ assertTrue(verifyMail(sender, subject));
+
+ // 4. get NotificationTask id and text body
+ Long taskId = null;
+ String textBody = null;
+ Set<String> recipients = null;
+ for (NotificationTask task : taskDAO.findAll(NotificationTask.class)) {
+ if (sender.equals(task.getSender())) {
+ taskId = task.getId();
+ textBody = task.getTextBody();
+ recipients = task.getRecipients();
+ }
+ }
+
+ assertNotNull(taskId);
+ assertNotNull(textBody);
+ assertTrue(recipients.contains("[email protected]"));
+
+ // 5. execute Notification task and verify e-mail
+ taskController.execute(taskId, false);
+ assertTrue(verifyMail(sender, subject));
+ }
}
Modified:
syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/dao/NotificationTest.java
URL:
http://svn.apache.org/viewvc/syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/dao/NotificationTest.java?rev=1594549&r1=1594548&r2=1594549&view=diff
==============================================================================
---
syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/dao/NotificationTest.java
(original)
+++
syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/dao/NotificationTest.java
Wed May 14 11:54:58 2014
@@ -18,6 +18,7 @@
*/
package org.apache.syncope.core.persistence.dao;
+import java.util.ArrayList;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
@@ -45,6 +46,7 @@ public class NotificationTest extends Ab
assertFalse(notification.getEvents().isEmpty());
assertNotNull(notification.getAbout());
assertNotNull(notification.getRecipients());
+
}
@Test
@@ -81,4 +83,31 @@ public class NotificationTest extends Ab
notificationDAO.delete(1L);
assertNull(notificationDAO.find(1L));
}
+
+ @Test
+ public void issueSYNCOPE445() {
+ Notification notification = new Notification();
+ notification.addEvent("save");
+
+ notification.setAbout(SyncopeClient.getUserSearchConditionBuilder().
+
is("fullname").equalTo("*o*").and("fullname").equalTo("*i*").query());
+
+
notification.setRecipients(SyncopeClient.getUserSearchConditionBuilder().hasRoles(7L).query());
+
+ notification.setRecipientAttrName("email");
+ notification.setRecipientAttrType(IntMappingType.UserSchema);
+
+ notification.addStaticRecipient("[email protected]");
+
+ notification.setSender("[email protected]");
+ notification.setSubject("Test notification");
+ notification.setTemplate("test");
+
+ Notification actual = notificationDAO.save(notification);
+ assertNotNull(actual);
+ assertNotNull(actual.getId());
+ assertNotNull(actual.getStaticRecipients());
+ assertFalse(actual.getStaticRecipients().isEmpty());
+ }
+
}
Modified:
syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/NotificationTestITCase.java
URL:
http://svn.apache.org/viewvc/syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/NotificationTestITCase.java?rev=1594549&r1=1594548&r2=1594549&view=diff
==============================================================================
---
syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/NotificationTestITCase.java
(original)
+++
syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/NotificationTestITCase.java
Wed May 14 11:54:58 2014
@@ -50,7 +50,7 @@ public class NotificationTestITCase exte
notificationTO.setRecipientAttrName("email");
notificationTO.setRecipientAttrType(IntMappingType.UserSchema);
-
+
notificationTO.setSender("[email protected]");
notificationTO.setSubject("Test notification");
notificationTO.setTemplate("test");
@@ -134,4 +134,22 @@ public class NotificationTestITCase exte
assertEquals(actual, notificationTO);
}
+ @Test
+ public void issueSYNCOPE445() {
+ NotificationTO notificationTO = buildNotificationTO();
+
notificationTO.getStaticRecipients().add("[email protected]");
+
+ NotificationTO actual = null;
+ try {
+ Response response = notificationService.create(notificationTO);
+ actual = getObject(response.getLocation(),
NotificationService.class, NotificationTO.class);
+ } catch (SyncopeClientException e) {
+ assertNotNull(e);
+ }
+ assertNotNull(actual);
+ assertNotNull(actual.getId());
+ notificationTO.setId(actual.getId());
+ assertEquals(actual, notificationTO);
+ }
+
}