Changed `attach_data` in emails to be more flexible
Bye default, when `attach_data` is set to `true` we attache the watch execution data as a `yaml` file. Now it's possible to configure the format of the file by setting the `attach_data` to an object with a `format` field (can either be set to `yaml` or `json`). Example: ``` "attach_data" : { "format" : "json" } ``` Original commit: elastic/x-pack-elasticsearch@5cab59a676
This commit is contained in:
parent
97413eba38
commit
3289ee9029
|
@ -0,0 +1,123 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License;
|
||||||
|
* you may not use this file except in compliance with the Elastic License.
|
||||||
|
*/
|
||||||
|
package org.elasticsearch.watcher.actions.email;
|
||||||
|
|
||||||
|
import org.elasticsearch.common.ParseField;
|
||||||
|
import org.elasticsearch.common.xcontent.ToXContent;
|
||||||
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
|
import org.elasticsearch.common.xcontent.XContentParser;
|
||||||
|
import org.elasticsearch.common.xcontent.XContentType;
|
||||||
|
import org.elasticsearch.watcher.WatcherException;
|
||||||
|
import org.elasticsearch.watcher.actions.email.service.Attachment;
|
||||||
|
import org.elasticsearch.watcher.watch.Payload;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public enum DataAttachment implements ToXContent {
|
||||||
|
|
||||||
|
YAML() {
|
||||||
|
@Override
|
||||||
|
public String contentType() {
|
||||||
|
return XContentType.YAML.restContentType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Attachment create(Map<String, Object> data) {
|
||||||
|
return new Attachment.XContent.Yaml("data", "data.yml", new Payload.Simple(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||||
|
return builder.startObject().field(Field.FORMAT.getPreferredName(), "yaml").endObject();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
JSON() {
|
||||||
|
@Override
|
||||||
|
public String contentType() {
|
||||||
|
return XContentType.JSON.restContentType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Attachment create(Map<String, Object> data) {
|
||||||
|
return new Attachment.XContent.Json("data", "data.json", new Payload.Simple(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||||
|
return builder.startObject().field(Field.FORMAT.getPreferredName(), "json").endObject();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static DataAttachment DEFAULT = YAML;
|
||||||
|
|
||||||
|
public abstract String contentType();
|
||||||
|
|
||||||
|
public abstract Attachment create(Map<String, Object> data);
|
||||||
|
|
||||||
|
public static DataAttachment resolve(String format) {
|
||||||
|
switch (format.toLowerCase(Locale.ROOT)) {
|
||||||
|
case "yaml": return YAML;
|
||||||
|
case "json": return JSON;
|
||||||
|
default:
|
||||||
|
throw new Exception("unknown data attachment format [{}]", format);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DataAttachment parse(XContentParser parser) throws IOException {
|
||||||
|
XContentParser.Token token = parser.currentToken();
|
||||||
|
if (token == XContentParser.Token.VALUE_NULL) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (token == XContentParser.Token.VALUE_BOOLEAN) {
|
||||||
|
return parser.booleanValue() ? DEFAULT : null;
|
||||||
|
}
|
||||||
|
if (token != XContentParser.Token.START_OBJECT) {
|
||||||
|
throw new Exception("could not parse data attachment. expected either a boolean value or an object but found [{}] instead", token);
|
||||||
|
}
|
||||||
|
|
||||||
|
DataAttachment dataAttachment = DEFAULT;
|
||||||
|
|
||||||
|
String currentFieldName = null;
|
||||||
|
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||||
|
if (token == XContentParser.Token.FIELD_NAME) {
|
||||||
|
currentFieldName = parser.currentName();
|
||||||
|
} else if (currentFieldName == null) {
|
||||||
|
throw new Exception("could not parse data attachment. expected [{}] field but found [{}] instead", Field.FORMAT.getPreferredName(), token);
|
||||||
|
} else if (Field.FORMAT.match(currentFieldName)) {
|
||||||
|
if (token == XContentParser.Token.VALUE_STRING) {
|
||||||
|
dataAttachment = resolve(parser.text());
|
||||||
|
} else {
|
||||||
|
throw new Exception("could not parse data attachment. expected string value for [{}] field but found [{}] instead", currentFieldName, token);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Exception("could not parse data attachment. unexpected field [{}]", currentFieldName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dataAttachment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Exception extends WatcherException {
|
||||||
|
|
||||||
|
public Exception(String msg, Object... args) {
|
||||||
|
super(msg, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Exception(String msg, Throwable cause, Object... args) {
|
||||||
|
super(msg, cause, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Field {
|
||||||
|
ParseField FORMAT = new ParseField("format");
|
||||||
|
}
|
||||||
|
}
|
|
@ -32,14 +32,14 @@ public class EmailAction implements Action {
|
||||||
private final @Nullable String account;
|
private final @Nullable String account;
|
||||||
private final @Nullable Authentication auth;
|
private final @Nullable Authentication auth;
|
||||||
private final @Nullable Profile profile;
|
private final @Nullable Profile profile;
|
||||||
private final @Nullable Boolean attachData;
|
private final @Nullable DataAttachment dataAttachment;
|
||||||
|
|
||||||
public EmailAction(EmailTemplate email, @Nullable String account, @Nullable Authentication auth, @Nullable Profile profile, @Nullable Boolean attachData) {
|
public EmailAction(EmailTemplate email, @Nullable String account, @Nullable Authentication auth, @Nullable Profile profile, @Nullable DataAttachment dataAttachment) {
|
||||||
this.email = email;
|
this.email = email;
|
||||||
this.account = account;
|
this.account = account;
|
||||||
this.auth = auth;
|
this.auth = auth;
|
||||||
this.profile = profile;
|
this.profile = profile;
|
||||||
this.attachData = attachData;
|
this.dataAttachment = dataAttachment;
|
||||||
}
|
}
|
||||||
|
|
||||||
public EmailTemplate getEmail() {
|
public EmailTemplate getEmail() {
|
||||||
|
@ -58,8 +58,8 @@ public class EmailAction implements Action {
|
||||||
return profile;
|
return profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getAttachData() {
|
public DataAttachment getDataAttachment() {
|
||||||
return attachData != null && attachData;
|
return dataAttachment;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -78,7 +78,7 @@ public class EmailAction implements Action {
|
||||||
if (account != null ? !account.equals(action.account) : action.account != null) return false;
|
if (account != null ? !account.equals(action.account) : action.account != null) return false;
|
||||||
if (auth != null ? !auth.equals(action.auth) : action.auth != null) return false;
|
if (auth != null ? !auth.equals(action.auth) : action.auth != null) return false;
|
||||||
if (profile != action.profile) return false;
|
if (profile != action.profile) return false;
|
||||||
return !(attachData != null ? !attachData.equals(action.attachData) : action.attachData != null);
|
return !(dataAttachment != null ? !dataAttachment.equals(action.dataAttachment) : action.dataAttachment != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -87,7 +87,7 @@ public class EmailAction implements Action {
|
||||||
result = 31 * result + (account != null ? account.hashCode() : 0);
|
result = 31 * result + (account != null ? account.hashCode() : 0);
|
||||||
result = 31 * result + (auth != null ? auth.hashCode() : 0);
|
result = 31 * result + (auth != null ? auth.hashCode() : 0);
|
||||||
result = 31 * result + (profile != null ? profile.hashCode() : 0);
|
result = 31 * result + (profile != null ? profile.hashCode() : 0);
|
||||||
result = 31 * result + (attachData != null ? attachData.hashCode() : 0);
|
result = 31 * result + (dataAttachment != null ? dataAttachment.hashCode() : 0);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,8 +106,8 @@ public class EmailAction implements Action {
|
||||||
if (profile != null) {
|
if (profile != null) {
|
||||||
builder.field(Field.PROFILE.getPreferredName(), profile.name().toLowerCase(Locale.ROOT));
|
builder.field(Field.PROFILE.getPreferredName(), profile.name().toLowerCase(Locale.ROOT));
|
||||||
}
|
}
|
||||||
if (attachData != null) {
|
if (dataAttachment != null) {
|
||||||
builder.field(Field.ATTACH_DATA.getPreferredName(), attachData);
|
builder.field(Field.ATTACH_DATA.getPreferredName(), dataAttachment, params);
|
||||||
}
|
}
|
||||||
email.xContentBody(builder, params);
|
email.xContentBody(builder, params);
|
||||||
return builder.endObject();
|
return builder.endObject();
|
||||||
|
@ -119,13 +119,19 @@ public class EmailAction implements Action {
|
||||||
String user = null;
|
String user = null;
|
||||||
Secret password = null;
|
Secret password = null;
|
||||||
Profile profile = Profile.STANDARD;
|
Profile profile = Profile.STANDARD;
|
||||||
Boolean attachPayload = null;
|
DataAttachment dataAttachment = null;
|
||||||
|
|
||||||
String currentFieldName = null;
|
String currentFieldName = null;
|
||||||
XContentParser.Token token;
|
XContentParser.Token token;
|
||||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||||
if (token == XContentParser.Token.FIELD_NAME) {
|
if (token == XContentParser.Token.FIELD_NAME) {
|
||||||
currentFieldName = parser.currentName();
|
currentFieldName = parser.currentName();
|
||||||
|
} else if (Field.ATTACH_DATA.match(currentFieldName)) {
|
||||||
|
try {
|
||||||
|
dataAttachment = DataAttachment.parse(parser);
|
||||||
|
} catch (DataAttachment.Exception dae) {
|
||||||
|
throw new EmailActionException("could not parse [{}] action [{}/{}]. failed to parse data attachment field [{}]", dae, TYPE, watchId, actionId, currentFieldName);
|
||||||
|
}
|
||||||
}else if (!emailParser.handle(currentFieldName, parser)) {
|
}else if (!emailParser.handle(currentFieldName, parser)) {
|
||||||
if (token == XContentParser.Token.VALUE_STRING) {
|
if (token == XContentParser.Token.VALUE_STRING) {
|
||||||
if (Field.ACCOUNT.match(currentFieldName)) {
|
if (Field.ACCOUNT.match(currentFieldName)) {
|
||||||
|
@ -139,12 +145,6 @@ public class EmailAction implements Action {
|
||||||
} else {
|
} else {
|
||||||
throw new EmailActionException("could not parse [{}] action [{}/{}]. unexpected string field [{}]", TYPE, watchId, actionId, currentFieldName);
|
throw new EmailActionException("could not parse [{}] action [{}/{}]. unexpected string field [{}]", TYPE, watchId, actionId, currentFieldName);
|
||||||
}
|
}
|
||||||
} else if (token == XContentParser.Token.VALUE_BOOLEAN) {
|
|
||||||
if (Field.ATTACH_DATA.match(currentFieldName)) {
|
|
||||||
attachPayload = parser.booleanValue();
|
|
||||||
} else {
|
|
||||||
throw new EmailActionException("could not parse [{}] action [{}/{}]. unexpected boolean field [{}]", TYPE, watchId, actionId, currentFieldName);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
throw new EmailActionException("could not parse [{}] action [{}/{}]. unexpected token [{}]", TYPE, watchId, actionId, token);
|
throw new EmailActionException("could not parse [{}] action [{}/{}]. unexpected token [{}]", TYPE, watchId, actionId, token);
|
||||||
}
|
}
|
||||||
|
@ -156,7 +156,7 @@ public class EmailAction implements Action {
|
||||||
auth = new Authentication(user, password);
|
auth = new Authentication(user, password);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new EmailAction(emailParser.parsedTemplate(), account, auth, profile, attachPayload);
|
return new EmailAction(emailParser.parsedTemplate(), account, auth, profile, dataAttachment);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Builder builder(EmailTemplate email) {
|
public static Builder builder(EmailTemplate email) {
|
||||||
|
@ -306,7 +306,7 @@ public class EmailAction implements Action {
|
||||||
@Nullable String account;
|
@Nullable String account;
|
||||||
@Nullable Authentication auth;
|
@Nullable Authentication auth;
|
||||||
@Nullable Profile profile;
|
@Nullable Profile profile;
|
||||||
@Nullable Boolean attachPayload;
|
@Nullable DataAttachment dataAttachment;
|
||||||
|
|
||||||
private Builder(EmailTemplate email) {
|
private Builder(EmailTemplate email) {
|
||||||
this.email = email;
|
this.email = email;
|
||||||
|
@ -327,13 +327,13 @@ public class EmailAction implements Action {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setAttachPayload(boolean attachPayload) {
|
public Builder setAttachPayload(DataAttachment dataAttachment) {
|
||||||
this.attachPayload = attachPayload;
|
this.dataAttachment = dataAttachment;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public EmailAction build() {
|
public EmailAction build() {
|
||||||
return new EmailAction(email, account, auth, profile, attachPayload);
|
return new EmailAction(email, account, auth, profile, dataAttachment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,18 +34,15 @@ public class ExecutableEmailAction extends ExecutableAction<EmailAction, EmailAc
|
||||||
protected EmailAction.Result doExecute(String actionId, WatchExecutionContext ctx, Payload payload) throws Exception {
|
protected EmailAction.Result doExecute(String actionId, WatchExecutionContext ctx, Payload payload) throws Exception {
|
||||||
Map<String, Object> model = Variables.createCtxModel(ctx, payload);
|
Map<String, Object> model = Variables.createCtxModel(ctx, payload);
|
||||||
|
|
||||||
Map<String, Attachment> attachmentMap = new HashMap<>();
|
Map<String, Attachment> attachments = new HashMap<>();
|
||||||
Attachment.Bytes attachment = null;
|
DataAttachment dataAttachment = action.getDataAttachment();
|
||||||
if (action.getAttachData()) {
|
if (dataAttachment != null) {
|
||||||
attachment = new Attachment.XContent.Yaml("data", "data.yml", new Payload.Simple(model));
|
Attachment attachment = dataAttachment.create(model);
|
||||||
attachmentMap.put(attachment.id(), attachment);
|
attachments.put(attachment.id(), attachment);
|
||||||
}
|
}
|
||||||
|
|
||||||
Email.Builder email = action.getEmail().render(templateEngine, model, attachmentMap);
|
Email.Builder email = action.getEmail().render(templateEngine, model, attachments);
|
||||||
email.id(ctx.id().value());
|
email.id(ctx.id().value());
|
||||||
if (attachment != null) {
|
|
||||||
email.attach(attachment);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx.simulateAction(actionId)) {
|
if (ctx.simulateAction(actionId)) {
|
||||||
return new EmailAction.Result.Simulated(email.build());
|
return new EmailAction.Result.Simulated(email.build());
|
||||||
|
|
|
@ -153,7 +153,7 @@ public abstract class Attachment extends BodyPartSource {
|
||||||
|
|
||||||
static byte[] bytes(String name, ToXContent content, XContentType type) {
|
static byte[] bytes(String name, ToXContent content, XContentType type) {
|
||||||
try {
|
try {
|
||||||
XContentBuilder builder = XContentBuilder.builder(type.xContent());
|
XContentBuilder builder = XContentBuilder.builder(type.xContent()).prettyPrint();
|
||||||
content.toXContent(builder, ToXContent.EMPTY_PARAMS);
|
content.toXContent(builder, ToXContent.EMPTY_PARAMS);
|
||||||
return builder.bytes().toBytes();
|
return builder.bytes().toBytes();
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
|
|
|
@ -218,7 +218,6 @@ public class Email implements ToXContent {
|
||||||
private String htmlBody;
|
private String htmlBody;
|
||||||
private ImmutableMap.Builder<String, Attachment> attachments = ImmutableMap.builder();
|
private ImmutableMap.Builder<String, Attachment> attachments = ImmutableMap.builder();
|
||||||
private ImmutableMap.Builder<String, Inline> inlines = ImmutableMap.builder();
|
private ImmutableMap.Builder<String, Inline> inlines = ImmutableMap.builder();
|
||||||
private boolean sanitizeHtmlBody = true;
|
|
||||||
|
|
||||||
private Builder() {
|
private Builder() {
|
||||||
}
|
}
|
||||||
|
@ -237,8 +236,6 @@ public class Email implements ToXContent {
|
||||||
htmlBody = email.htmlBody;
|
htmlBody = email.htmlBody;
|
||||||
attachments.putAll(email.attachments);
|
attachments.putAll(email.attachments);
|
||||||
inlines.putAll(email.inlines);
|
inlines.putAll(email.inlines);
|
||||||
//The builder will already have sanitized the html when the email was built originally so don't double sanitize
|
|
||||||
sanitizeHtmlBody = false;
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -88,7 +88,7 @@ public class EmailTemplate implements ToXContent {
|
||||||
return sanitizeHtmlBody;
|
return sanitizeHtmlBody;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Email.Builder render(TemplateEngine engine, Map<String, Object> model, Map<String, Attachment> attachmentsMap) throws AddressException {
|
public Email.Builder render(TemplateEngine engine, Map<String, Object> model, Map<String, Attachment> attachments) throws AddressException {
|
||||||
Email.Builder builder = Email.builder();
|
Email.Builder builder = Email.builder();
|
||||||
if (from != null) {
|
if (from != null) {
|
||||||
builder.from(engine.render(from, model));
|
builder.from(engine.render(from, model));
|
||||||
|
@ -118,10 +118,15 @@ public class EmailTemplate implements ToXContent {
|
||||||
if (textBody != null) {
|
if (textBody != null) {
|
||||||
builder.textBody(engine.render(textBody, model));
|
builder.textBody(engine.render(textBody, model));
|
||||||
}
|
}
|
||||||
|
if (attachments != null) {
|
||||||
|
for (Attachment attachment : attachments.values()) {
|
||||||
|
builder.attach(attachment);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (htmlBody != null) {
|
if (htmlBody != null) {
|
||||||
String renderedHtml = engine.render(htmlBody, model);
|
String renderedHtml = engine.render(htmlBody, model);
|
||||||
if (sanitizeHtmlBody && htmlBody != null) {
|
if (sanitizeHtmlBody && htmlBody != null) {
|
||||||
renderedHtml = sanitizeHtml(attachmentsMap, renderedHtml);
|
renderedHtml = sanitizeHtml(renderedHtml, attachments);
|
||||||
}
|
}
|
||||||
builder.htmlBody(renderedHtml);
|
builder.htmlBody(renderedHtml);
|
||||||
}
|
}
|
||||||
|
@ -457,7 +462,7 @@ public class EmailTemplate implements ToXContent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static String sanitizeHtml(final Map<String, Attachment> attachments, String html){
|
static String sanitizeHtml(String html, final Map<String, Attachment> attachments){
|
||||||
ElementPolicy onlyCIDImgPolicy = new AttachementVerifyElementPolicy(attachments);
|
ElementPolicy onlyCIDImgPolicy = new AttachementVerifyElementPolicy(attachments);
|
||||||
PolicyFactory policy = Sanitizers.FORMATTING
|
PolicyFactory policy = Sanitizers.FORMATTING
|
||||||
.and(new HtmlPolicyBuilder()
|
.and(new HtmlPolicyBuilder()
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License;
|
||||||
|
* you may not use this file except in compliance with the Elastic License.
|
||||||
|
*/
|
||||||
|
package org.elasticsearch.watcher.actions.email;
|
||||||
|
|
||||||
|
import org.elasticsearch.common.base.Charsets;
|
||||||
|
import org.elasticsearch.common.collect.ImmutableMap;
|
||||||
|
import org.elasticsearch.common.io.Streams;
|
||||||
|
import org.elasticsearch.test.ElasticsearchTestCase;
|
||||||
|
import org.elasticsearch.watcher.actions.email.service.Attachment;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class DataAttachmentTests extends ElasticsearchTestCase {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreate_Json() throws Exception {
|
||||||
|
Map<String, Object> data = ImmutableMap.<String, Object>of("key", "value");
|
||||||
|
Attachment attachment = DataAttachment.JSON.create(data);
|
||||||
|
InputStream input = attachment.bodyPart().getDataHandler().getInputStream();
|
||||||
|
String content = Streams.copyToString(new InputStreamReader(input, Charsets.UTF_8));
|
||||||
|
assertThat(content, is("{\n \"key\" : \"value\"\n}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreate_Yaml() throws Exception {
|
||||||
|
Map<String, Object> data = ImmutableMap.<String, Object>of("key", "value");
|
||||||
|
Attachment attachment = DataAttachment.YAML.create(data);
|
||||||
|
InputStream input = attachment.bodyPart().getDataHandler().getInputStream();
|
||||||
|
String content = Streams.copyToString(new InputStreamReader(input, Charsets.UTF_8));
|
||||||
|
assertThat(content, is("---\nkey: \"value\"\n"));
|
||||||
|
}
|
||||||
|
}
|
|
@ -79,9 +79,9 @@ public class EmailActionTests extends ElasticsearchTestCase {
|
||||||
Authentication auth = new Authentication("user", new Secret("passwd".toCharArray()));
|
Authentication auth = new Authentication("user", new Secret("passwd".toCharArray()));
|
||||||
Profile profile = randomFrom(Profile.values());
|
Profile profile = randomFrom(Profile.values());
|
||||||
|
|
||||||
boolean attachPayload = randomBoolean();
|
DataAttachment dataAttachment = randomDataAttachment();
|
||||||
|
|
||||||
EmailAction action = new EmailAction(email, account, auth, profile, attachPayload);
|
EmailAction action = new EmailAction(email, account, auth, profile, dataAttachment);
|
||||||
ExecutableEmailAction executable = new ExecutableEmailAction(action, logger, service, engine);
|
ExecutableEmailAction executable = new ExecutableEmailAction(action, logger, service, engine);
|
||||||
|
|
||||||
Map<String, Object> data = new HashMap<>();
|
Map<String, Object> data = new HashMap<>();
|
||||||
|
@ -133,7 +133,7 @@ public class EmailActionTests extends ElasticsearchTestCase {
|
||||||
assertThat(actualEmail.subject(), is(subject == null ? null : subject.getTemplate()));
|
assertThat(actualEmail.subject(), is(subject == null ? null : subject.getTemplate()));
|
||||||
assertThat(actualEmail.textBody(), is(textBody == null ? null : textBody.getTemplate()));
|
assertThat(actualEmail.textBody(), is(textBody == null ? null : textBody.getTemplate()));
|
||||||
assertThat(actualEmail.htmlBody(), is(htmlBody == null ? null : htmlBody.getTemplate()));
|
assertThat(actualEmail.htmlBody(), is(htmlBody == null ? null : htmlBody.getTemplate()));
|
||||||
if (attachPayload) {
|
if (dataAttachment != null) {
|
||||||
assertThat(actualEmail.attachments(), hasKey("data"));
|
assertThat(actualEmail.attachments(), hasKey("data"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -151,15 +151,23 @@ public class EmailActionTests extends ElasticsearchTestCase {
|
||||||
Template subject = randomBoolean() ? Template.inline("_subject").build() : null;
|
Template subject = randomBoolean() ? Template.inline("_subject").build() : null;
|
||||||
Template textBody = randomBoolean() ? Template.inline("_text_body").build() : null;
|
Template textBody = randomBoolean() ? Template.inline("_text_body").build() : null;
|
||||||
Template htmlBody = randomBoolean() ? Template.inline("_text_html").build() : null;
|
Template htmlBody = randomBoolean() ? Template.inline("_text_html").build() : null;
|
||||||
boolean attachData = randomBoolean();
|
DataAttachment dataAttachment = randomDataAttachment();
|
||||||
XContentBuilder builder = jsonBuilder().startObject()
|
XContentBuilder builder = jsonBuilder().startObject()
|
||||||
.field("account", "_account")
|
.field("account", "_account")
|
||||||
.field("profile", profile.name())
|
.field("profile", profile.name())
|
||||||
.field("user", "_user")
|
.field("user", "_user")
|
||||||
.field("password", "_passwd")
|
.field("password", "_passwd")
|
||||||
.field("attach_data", attachData)
|
|
||||||
.field("from", "from@domain")
|
.field("from", "from@domain")
|
||||||
.field("priority", priority.name());
|
.field("priority", priority.name());
|
||||||
|
if (dataAttachment != null) {
|
||||||
|
builder.field("attach_data", dataAttachment);
|
||||||
|
} else if (randomBoolean()) {
|
||||||
|
dataAttachment = DataAttachment.DEFAULT;
|
||||||
|
builder.field("attach_data", true);
|
||||||
|
} else if (randomBoolean()) {
|
||||||
|
builder.field("attach_data", false);
|
||||||
|
}
|
||||||
|
|
||||||
if (to != null) {
|
if (to != null) {
|
||||||
if (to.length == 1) {
|
if (to.length == 1) {
|
||||||
builder.field("to", to[0]);
|
builder.field("to", to[0]);
|
||||||
|
@ -219,7 +227,11 @@ public class EmailActionTests extends ElasticsearchTestCase {
|
||||||
|
|
||||||
assertThat(executable, notNullValue());
|
assertThat(executable, notNullValue());
|
||||||
assertThat(executable.action().getAccount(), is("_account"));
|
assertThat(executable.action().getAccount(), is("_account"));
|
||||||
assertThat(executable.action().getAttachData(), is(attachData));
|
if (dataAttachment == null) {
|
||||||
|
assertThat(executable.action().getDataAttachment(), nullValue());
|
||||||
|
} else {
|
||||||
|
assertThat(executable.action().getDataAttachment(), is(dataAttachment));
|
||||||
|
}
|
||||||
assertThat(executable.action().getAuth(), notNullValue());
|
assertThat(executable.action().getAuth(), notNullValue());
|
||||||
assertThat(executable.action().getAuth().user(), is("_user"));
|
assertThat(executable.action().getAuth().user(), is("_user"));
|
||||||
assertThat(executable.action().getAuth().password(), is(new Secret("_passwd".toCharArray())));
|
assertThat(executable.action().getAuth().password(), is(new Secret("_passwd".toCharArray())));
|
||||||
|
@ -278,9 +290,9 @@ public class EmailActionTests extends ElasticsearchTestCase {
|
||||||
Authentication auth = randomBoolean() ? null : new Authentication("_user", new Secret("_passwd".toCharArray()));
|
Authentication auth = randomBoolean() ? null : new Authentication("_user", new Secret("_passwd".toCharArray()));
|
||||||
Profile profile = randomFrom(Profile.values());
|
Profile profile = randomFrom(Profile.values());
|
||||||
String account = randomAsciiOfLength(6);
|
String account = randomAsciiOfLength(6);
|
||||||
boolean attachPayload = randomBoolean();
|
DataAttachment dataAttachment = randomDataAttachment();
|
||||||
|
|
||||||
EmailAction action = new EmailAction(email, account, auth, profile, attachPayload);
|
EmailAction action = new EmailAction(email, account, auth, profile, dataAttachment);
|
||||||
ExecutableEmailAction executable = new ExecutableEmailAction(action, logger, service, engine);
|
ExecutableEmailAction executable = new ExecutableEmailAction(action, logger, service, engine);
|
||||||
|
|
||||||
boolean hideSecrets = randomBoolean();
|
boolean hideSecrets = randomBoolean();
|
||||||
|
@ -299,14 +311,17 @@ public class EmailActionTests extends ElasticsearchTestCase {
|
||||||
} else {
|
} else {
|
||||||
assertThat(parsed.action().getAccount(), is(executable.action().getAccount()));
|
assertThat(parsed.action().getAccount(), is(executable.action().getAccount()));
|
||||||
assertThat(parsed.action().getEmail(), is(executable.action().getEmail()));
|
assertThat(parsed.action().getEmail(), is(executable.action().getEmail()));
|
||||||
assertThat(parsed.action().getAttachData(), is(executable.action().getAttachData()));
|
if (executable.action().getDataAttachment() == null) {
|
||||||
|
assertThat(parsed.action().getDataAttachment(), nullValue());
|
||||||
|
} else {
|
||||||
|
assertThat(parsed.action().getDataAttachment(), is(executable.action().getDataAttachment()));
|
||||||
|
}
|
||||||
if (auth != null) {
|
if (auth != null) {
|
||||||
assertThat(parsed.action().getAuth().user(), is(executable.action().getAuth().user()));
|
assertThat(parsed.action().getAuth().user(), is(executable.action().getAuth().user()));
|
||||||
assertThat(parsed.action().getAuth().password(), nullValue());
|
assertThat(parsed.action().getAuth().password(), nullValue());
|
||||||
assertThat(executable.action().getAuth().password(), notNullValue());
|
assertThat(executable.action().getAuth().password(), notNullValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = EmailActionException.class) @Repeat(iterations = 100)
|
@Test(expected = EmailActionException.class) @Repeat(iterations = 100)
|
||||||
|
@ -413,4 +428,8 @@ public class EmailActionTests extends ElasticsearchTestCase {
|
||||||
new EmailActionFactory(ImmutableSettings.EMPTY, mock(EmailService.class), mock(TemplateEngine.class))
|
new EmailActionFactory(ImmutableSettings.EMPTY, mock(EmailService.class), mock(TemplateEngine.class))
|
||||||
.parseResult(wid, actionId, parser);
|
.parseResult(wid, actionId, parser);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DataAttachment randomDataAttachment() {
|
||||||
|
return randomFrom(DataAttachment.JSON, DataAttachment.YAML, null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ public class HtmlSanitizeTests extends ElasticsearchTestCase {
|
||||||
"onclick=\"document.getElementById('demo').innerHTML = Date()\">" +
|
"onclick=\"document.getElementById('demo').innerHTML = Date()\">" +
|
||||||
"Click me to display Date and Time.</button>";
|
"Click me to display Date and Time.</button>";
|
||||||
byte[] bytes = new byte[0];
|
byte[] bytes = new byte[0];
|
||||||
String sanitizedHtml = sanitizeHtml(ImmutableMap.of("foo", (Attachment) new Attachment.Bytes("foo", bytes, "")), badHtml);
|
String sanitizedHtml = sanitizeHtml(badHtml, ImmutableMap.of("foo", (Attachment) new Attachment.Bytes("foo", bytes, "")));
|
||||||
assertThat(sanitizedHtml, equalTo("Click me to display Date and Time."));
|
assertThat(sanitizedHtml, equalTo("Click me to display Date and Time."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ public class HtmlSanitizeTests extends ElasticsearchTestCase {
|
||||||
public void test_HtmlSanitizer_Nonattachment_img() {
|
public void test_HtmlSanitizer_Nonattachment_img() {
|
||||||
String badHtml = "<img src=\"http://test.com/nastyimage.jpg\"/>This is a bad image";
|
String badHtml = "<img src=\"http://test.com/nastyimage.jpg\"/>This is a bad image";
|
||||||
byte[] bytes = new byte[0];
|
byte[] bytes = new byte[0];
|
||||||
String sanitizedHtml = sanitizeHtml(ImmutableMap.of("foo", (Attachment) new Attachment.Bytes("foo", bytes, "")), badHtml);
|
String sanitizedHtml = sanitizeHtml(badHtml, ImmutableMap.of("foo", (Attachment) new Attachment.Bytes("foo", bytes, "")));
|
||||||
assertThat(sanitizedHtml, equalTo("This is a bad image"));
|
assertThat(sanitizedHtml, equalTo("This is a bad image"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ public class HtmlSanitizeTests extends ElasticsearchTestCase {
|
||||||
public void test_HtmlSanitizer_Goodattachment_img() {
|
public void test_HtmlSanitizer_Goodattachment_img() {
|
||||||
String goodHtml = "<img src=\"cid:foo\" />This is a good image";
|
String goodHtml = "<img src=\"cid:foo\" />This is a good image";
|
||||||
byte[] bytes = new byte[0];
|
byte[] bytes = new byte[0];
|
||||||
String sanitizedHtml = sanitizeHtml(ImmutableMap.of("foo", (Attachment) new Attachment.Bytes("foo", bytes, "")), goodHtml);
|
String sanitizedHtml = sanitizeHtml(goodHtml, ImmutableMap.of("foo", (Attachment) new Attachment.Bytes("foo", bytes, "")));
|
||||||
assertThat(sanitizedHtml, equalTo(goodHtml));
|
assertThat(sanitizedHtml, equalTo(goodHtml));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ public class HtmlSanitizeTests extends ElasticsearchTestCase {
|
||||||
public void test_HtmlSanitizer_table() {
|
public void test_HtmlSanitizer_table() {
|
||||||
String goodHtml = "<table><tr><td>cell1</td><td>cell2</td></tr></table>";
|
String goodHtml = "<table><tr><td>cell1</td><td>cell2</td></tr></table>";
|
||||||
byte[] bytes = new byte[0];
|
byte[] bytes = new byte[0];
|
||||||
String sanitizedHtml = sanitizeHtml(ImmutableMap.of("foo", (Attachment) new Attachment.Bytes("foo", bytes, "")), goodHtml);
|
String sanitizedHtml = sanitizeHtml(goodHtml, ImmutableMap.of("foo", (Attachment) new Attachment.Bytes("foo", bytes, "")));
|
||||||
assertThat(sanitizedHtml, equalTo(goodHtml));
|
assertThat(sanitizedHtml, equalTo(goodHtml));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ public class HtmlSanitizeTests extends ElasticsearchTestCase {
|
||||||
public void test_HtmlSanitizer_Badattachment_img() {
|
public void test_HtmlSanitizer_Badattachment_img() {
|
||||||
String goodHtml = "<img src=\"cid:bad\" />This is a bad image";
|
String goodHtml = "<img src=\"cid:bad\" />This is a bad image";
|
||||||
byte[] bytes = new byte[0];
|
byte[] bytes = new byte[0];
|
||||||
String sanitizedHtml = sanitizeHtml(ImmutableMap.of("foo", (Attachment) new Attachment.Bytes("foo", bytes, "")), goodHtml);
|
String sanitizedHtml = sanitizeHtml(goodHtml, ImmutableMap.of("foo", (Attachment) new Attachment.Bytes("foo", bytes, "")));
|
||||||
assertThat(sanitizedHtml, equalTo("This is a bad image"));
|
assertThat(sanitizedHtml, equalTo("This is a bad image"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ public class HtmlSanitizeTests extends ElasticsearchTestCase {
|
||||||
public void test_HtmlSanitizer_Script() {
|
public void test_HtmlSanitizer_Script() {
|
||||||
String badHtml = "<script>doSomethingNefarious()</script>This was a dangerous script";
|
String badHtml = "<script>doSomethingNefarious()</script>This was a dangerous script";
|
||||||
byte[] bytes = new byte[0];
|
byte[] bytes = new byte[0];
|
||||||
String sanitizedHtml = sanitizeHtml(ImmutableMap.of("foo", (Attachment) new Attachment.Bytes("foo", bytes, "")), badHtml);
|
String sanitizedHtml = sanitizeHtml(badHtml, ImmutableMap.of("foo", (Attachment) new Attachment.Bytes("foo", bytes, "")));
|
||||||
assertThat(sanitizedHtml, equalTo("This was a dangerous script"));
|
assertThat(sanitizedHtml, equalTo("This was a dangerous script"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ public class HtmlSanitizeTests extends ElasticsearchTestCase {
|
||||||
public void test_HtmlSanitizer_FullHtmlWithMetaString() {
|
public void test_HtmlSanitizer_FullHtmlWithMetaString() {
|
||||||
String needsSanitation = "<html><head></head><body><h1>Hello {{ctx.metadata.name}}</h1> meta <a href='https://www.google.com/search?q={{ctx.metadata.name}}'>Testlink</a>meta</body></html>";
|
String needsSanitation = "<html><head></head><body><h1>Hello {{ctx.metadata.name}}</h1> meta <a href='https://www.google.com/search?q={{ctx.metadata.name}}'>Testlink</a>meta</body></html>";
|
||||||
byte[] bytes = new byte[0];
|
byte[] bytes = new byte[0];
|
||||||
String sanitizedHtml = sanitizeHtml(ImmutableMap.of("foo", (Attachment) new Attachment.Bytes("foo", bytes, "")), needsSanitation);
|
String sanitizedHtml = sanitizeHtml(needsSanitation, ImmutableMap.of("foo", (Attachment) new Attachment.Bytes("foo", bytes, "")));
|
||||||
assertThat(sanitizedHtml, equalTo("<head></head><body><h1>Hello {{ctx.metadata.name}}</h1> meta <a href=\"https://www.google.com/search?q={{ctx.metadata.name}}\" rel=\"nofollow\">Testlink</a>meta</body>"));
|
assertThat(sanitizedHtml, equalTo("<head></head><body><h1>Hello {{ctx.metadata.name}}</h1> meta <a href=\"https://www.google.com/search?q={{ctx.metadata.name}}\" rel=\"nofollow\">Testlink</a>meta</body>"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -171,7 +171,7 @@ public final class WatcherTestUtils {
|
||||||
|
|
||||||
Authentication auth = new Authentication("testname", new Secret("testpassword".toCharArray()));
|
Authentication auth = new Authentication("testname", new Secret("testpassword".toCharArray()));
|
||||||
|
|
||||||
EmailAction action = new EmailAction(email, "testaccount", auth, Profile.STANDARD, false);
|
EmailAction action = new EmailAction(email, "testaccount", auth, Profile.STANDARD, null);
|
||||||
ExecutableEmailAction executale = new ExecutableEmailAction(action, logger, emailService, templateEngine);
|
ExecutableEmailAction executale = new ExecutableEmailAction(action, logger, emailService, templateEngine);
|
||||||
|
|
||||||
actions.add(new ActionWrapper("_email", executale));
|
actions.add(new ActionWrapper("_email", executale));
|
||||||
|
|
|
@ -7,6 +7,7 @@ package org.elasticsearch.watcher.watch;
|
||||||
|
|
||||||
import com.carrotsearch.ant.tasks.junit4.dependencies.com.google.common.collect.ImmutableSet;
|
import com.carrotsearch.ant.tasks.junit4.dependencies.com.google.common.collect.ImmutableSet;
|
||||||
import com.carrotsearch.randomizedtesting.annotations.Repeat;
|
import com.carrotsearch.randomizedtesting.annotations.Repeat;
|
||||||
|
import com.carrotsearch.randomizedtesting.annotations.Seed;
|
||||||
import org.elasticsearch.common.bytes.BytesReference;
|
import org.elasticsearch.common.bytes.BytesReference;
|
||||||
import org.elasticsearch.common.collect.ImmutableList;
|
import org.elasticsearch.common.collect.ImmutableList;
|
||||||
import org.elasticsearch.common.collect.ImmutableMap;
|
import org.elasticsearch.common.collect.ImmutableMap;
|
||||||
|
@ -23,6 +24,7 @@ import org.elasticsearch.watcher.actions.ActionFactory;
|
||||||
import org.elasticsearch.watcher.actions.ActionRegistry;
|
import org.elasticsearch.watcher.actions.ActionRegistry;
|
||||||
import org.elasticsearch.watcher.actions.ActionWrapper;
|
import org.elasticsearch.watcher.actions.ActionWrapper;
|
||||||
import org.elasticsearch.watcher.actions.ExecutableActions;
|
import org.elasticsearch.watcher.actions.ExecutableActions;
|
||||||
|
import org.elasticsearch.watcher.actions.email.DataAttachment;
|
||||||
import org.elasticsearch.watcher.actions.email.EmailAction;
|
import org.elasticsearch.watcher.actions.email.EmailAction;
|
||||||
import org.elasticsearch.watcher.actions.email.EmailActionFactory;
|
import org.elasticsearch.watcher.actions.email.EmailActionFactory;
|
||||||
import org.elasticsearch.watcher.actions.email.ExecutableEmailAction;
|
import org.elasticsearch.watcher.actions.email.ExecutableEmailAction;
|
||||||
|
@ -160,7 +162,6 @@ public class WatchTests extends ElasticsearchTestCase {
|
||||||
logger.info(bytes.toUtf8());
|
logger.info(bytes.toUtf8());
|
||||||
Watch.Parser watchParser = new Watch.Parser(settings, mock(LicenseService.class), conditionRegistry, triggerService, transformRegistry, actionRegistry, inputRegistry, SystemClock.INSTANCE, secretService);
|
Watch.Parser watchParser = new Watch.Parser(settings, mock(LicenseService.class), conditionRegistry, triggerService, transformRegistry, actionRegistry, inputRegistry, SystemClock.INSTANCE, secretService);
|
||||||
|
|
||||||
|
|
||||||
Watch parsedWatch = watchParser.parse("_name", includeStatus, bytes);
|
Watch parsedWatch = watchParser.parse("_name", includeStatus, bytes);
|
||||||
|
|
||||||
if (includeStatus) {
|
if (includeStatus) {
|
||||||
|
@ -335,7 +336,7 @@ public class WatchTests extends ElasticsearchTestCase {
|
||||||
ImmutableList.Builder<ActionWrapper> list = ImmutableList.builder();
|
ImmutableList.Builder<ActionWrapper> list = ImmutableList.builder();
|
||||||
if (randomBoolean()) {
|
if (randomBoolean()) {
|
||||||
ExecutableTransform transform = randomTransform();
|
ExecutableTransform transform = randomTransform();
|
||||||
EmailAction action = new EmailAction(EmailTemplate.builder().build(), null, null, Profile.STANDARD, randomBoolean());
|
EmailAction action = new EmailAction(EmailTemplate.builder().build(), null, null, Profile.STANDARD, randomFrom(DataAttachment.JSON, DataAttachment.YAML, null));
|
||||||
list.add(new ActionWrapper("_email_" + randomAsciiOfLength(8), transform, new ExecutableEmailAction(action, logger, emailService, templateEngine)));
|
list.add(new ActionWrapper("_email_" + randomAsciiOfLength(8), transform, new ExecutableEmailAction(action, logger, emailService, templateEngine)));
|
||||||
}
|
}
|
||||||
if (randomBoolean()) {
|
if (randomBoolean()) {
|
||||||
|
|
Loading…
Reference in New Issue