diff --git a/flows/actions/base.go b/flows/actions/base.go index bce62db41..08ca13224 100644 --- a/flows/actions/base.go +++ b/flows/actions/base.go @@ -86,8 +86,8 @@ func (a *baseAction) evaluateMessage(run flows.Run, languages []i18n.Language, a for _, a := range translatedAttachments { evaluatedAttachment, _ := run.EvaluateTemplate(a, logEvent) evaluatedAttachment = strings.TrimSpace(evaluatedAttachment) - if evaluatedAttachment == "" { - logEvent(events.NewErrorf("attachment text evaluated to empty string, skipping")) + if !utils.IsValidAttachment(evaluatedAttachment) { + logEvent(events.NewErrorf("attachment evaluated to invalid value, skipping")) continue } if len(evaluatedAttachment) > flows.MaxAttachmentLength { @@ -103,7 +103,7 @@ func (a *baseAction) evaluateMessage(run flows.Run, languages []i18n.Language, a for _, qr := range translatedQuickReplies { evaluatedQuickReply, _ := run.EvaluateTemplate(qr, logEvent) if evaluatedQuickReply == "" { - logEvent(events.NewErrorf("quick reply text evaluated to empty string, skipping")) + logEvent(events.NewErrorf("quick reply evaluated to empty string, skipping")) continue } evaluatedQuickReplies = append(evaluatedQuickReplies, stringsx.TruncateEllipsis(evaluatedQuickReply, flows.MaxQuickReplyLength)) @@ -261,9 +261,9 @@ func (a *otherContactsAction) resolveRecipients(run flows.Run, logEvent flows.Ev // utility struct for actions which create a message type createMsgAction struct { - Text string `json:"text" validate:"required" engine:"localized,evaluated"` - Attachments []string `json:"attachments,omitempty" engine:"localized,evaluated"` - QuickReplies []string `json:"quick_replies,omitempty" engine:"localized,evaluated"` + Text string `json:"text" validate:"required" engine:"localized,evaluated"` + Attachments []string `json:"attachments,omitempty" validate:"dive,attachment" engine:"localized,evaluated"` + QuickReplies []string `json:"quick_replies,omitempty" engine:"localized,evaluated"` } // helper function for actions that have a set of group references that must be resolved to actual groups diff --git a/flows/actions/testdata/send_broadcast.json b/flows/actions/testdata/send_broadcast.json index 0cedc2b65..68e4e3fdf 100644 --- a/flows/actions/testdata/send_broadcast.json +++ b/flows/actions/testdata/send_broadcast.json @@ -251,7 +251,7 @@ ], "text": "Hi there!", "attachments": [ - "http://example.com/red.jpg" + "image:http://example.com/red.jpg" ], "quick_replies": [ "Yes", @@ -265,7 +265,7 @@ "Hola!" ], "attachments": [ - "http://example.com/rojo.jpg" + "image:http://example.com/rojo.jpg" ], "quick_replies": [ "Si", @@ -283,7 +283,7 @@ "eng": { "text": "Hi there!", "attachments": [ - "http://example.com/red.jpg" + "image:http://example.com/red.jpg" ], "quick_replies": [ "Yes", @@ -293,7 +293,7 @@ "spa": { "text": "Hola!", "attachments": [ - "http://example.com/rojo.jpg" + "image:http://example.com/rojo.jpg" ], "quick_replies": [ "Si", @@ -310,8 +310,8 @@ "templates": [ "Hi there!", "Hola!", - "http://example.com/red.jpg", - "http://example.com/rojo.jpg", + "image:http://example.com/red.jpg", + "image:http://example.com/rojo.jpg", "Yes", "No", "Si", diff --git a/flows/actions/testdata/send_msg.json b/flows/actions/testdata/send_msg.json index e8e63f01a..883e92ffc 100644 --- a/flows/actions/testdata/send_msg.json +++ b/flows/actions/testdata/send_msg.json @@ -6,7 +6,7 @@ "uuid": "ad154980-7bf7-4ab8-8728-545fd6378912", "text": "", "attachments": [ - "http://example.com/red.jpg" + "image:http://example.com/red.jpg" ] }, "read_error": "field 'text' is required" @@ -28,8 +28,8 @@ "uuid": "ad154980-7bf7-4ab8-8728-545fd6378912", "text": "Hi there @(1 / 0)", "attachments": [ - "http://example.com/red.jpg@(1 / 0)", - "@(xxxxx)" + "image:http://example.com/red.jpg@(1 / 0)", + "image:@(xxxxx)" ], "quick_replies": [ "Red@(1 / 0)", @@ -60,7 +60,7 @@ "type": "error", "created_on": "2018-10-18T14:20:30.000123456Z", "step_uuid": "59d74b86-3e2f-4a93-aece-b05d2fdcde0c", - "text": "attachment text evaluated to empty string, skipping" + "text": "attachment evaluated to invalid value, skipping" }, { "type": "error", @@ -78,7 +78,7 @@ "type": "error", "created_on": "2018-10-18T14:20:30.000123456Z", "step_uuid": "59d74b86-3e2f-4a93-aece-b05d2fdcde0c", - "text": "quick reply text evaluated to empty string, skipping" + "text": "quick reply evaluated to empty string, skipping" }, { "type": "msg_created", @@ -93,7 +93,7 @@ }, "text": "Hi there ", "attachments": [ - "http://example.com/red.jpg" + "image:http://example.com/red.jpg" ], "quick_replies": [ "Red", @@ -111,7 +111,7 @@ "uuid": "ad154980-7bf7-4ab8-8728-545fd6378912", "text": "Hi there", "attachments": [ - "@(\" \")" + "image:@(\" \")" ], "quick_replies": [ "@(\"\")" @@ -122,13 +122,13 @@ "type": "error", "created_on": "2018-10-18T14:20:30.000123456Z", "step_uuid": "59d74b86-3e2f-4a93-aece-b05d2fdcde0c", - "text": "attachment text evaluated to empty string, skipping" + "text": "attachment evaluated to invalid value, skipping" }, { "type": "error", "created_on": "2018-10-18T14:20:30.000123456Z", "step_uuid": "59d74b86-3e2f-4a93-aece-b05d2fdcde0c", - "text": "quick reply text evaluated to empty string, skipping" + "text": "quick reply evaluated to empty string, skipping" }, { "type": "msg_created", @@ -154,7 +154,7 @@ "uuid": "ad154980-7bf7-4ab8-8728-545fd6378912", "text": "Hi there", "attachments": [ - "@(json(run) & json(run) & json(run))", + "image:@(json(run) & json(run) & json(run))", "image/jpeg:http://exacmple.com/test.jpg" ] }, @@ -710,7 +710,7 @@ "uuid": "ad154980-7bf7-4ab8-8728-545fd6378912", "text": "Hi there!", "attachments": [ - "http://example.com/red.jpg" + "image:http://example.com/red.jpg" ], "quick_replies": [ "Yes", @@ -724,7 +724,7 @@ "Hola!" ], "attachments": [ - "http://example.com/rojo.jpg" + "image:http://example.com/rojo.jpg" ], "quick_replies": [ "Si", @@ -747,7 +747,7 @@ }, "text": "Hola!", "attachments": [ - "http://example.com/rojo.jpg" + "image:http://example.com/rojo.jpg" ], "quick_replies": [ "Si", @@ -760,8 +760,8 @@ "templates": [ "Hi there!", "Hola!", - "http://example.com/red.jpg", - "http://example.com/rojo.jpg", + "image:http://example.com/red.jpg", + "image:http://example.com/rojo.jpg", "Yes", "No", "Si", @@ -769,7 +769,7 @@ ], "localizables": [ "Hi there!", - "http://example.com/red.jpg", + "image:http://example.com/red.jpg", "Yes", "No" ], diff --git a/flows/urn_test.go b/flows/urn_test.go index eaae0c8ee..cd15dcc18 100644 --- a/flows/urn_test.go +++ b/flows/urn_test.go @@ -17,14 +17,14 @@ import ( "github.com/stretchr/testify/require" ) -type testStruct struct { - ValidURN string `json:"valid_urn" validate:"urn"` - InvalidURN string `json:"invalid_urn" validate:"urn"` - ValidScheme string `json:"valid_scheme" validate:"urnscheme"` - InvalidScheme string `json:"invalid_scheme" validate:"urnscheme"` -} - func TestURNValidation(t *testing.T) { + type testStruct struct { + ValidURN string `json:"valid_urn" validate:"urn"` + InvalidURN string `json:"invalid_urn" validate:"urn"` + ValidScheme string `json:"valid_scheme" validate:"urnscheme"` + InvalidScheme string `json:"invalid_scheme" validate:"urnscheme"` + } + obj := testStruct{ ValidURN: "tel:+123456789", InvalidURN: "xyz", diff --git a/utils/attachment.go b/utils/attachment.go index 9c75fc496..67dce2fdf 100644 --- a/utils/attachment.go +++ b/utils/attachment.go @@ -3,8 +3,21 @@ package utils import ( "regexp" "strings" + + "github.com/go-playground/validator/v10" ) +func init() { + RegisterValidatorTag("attachment", + func(fl validator.FieldLevel) bool { + return IsValidAttachment(fl.Field().String()) + }, + func(validator.FieldError) string { + return "is not a valid attachment" + }, + ) +} + // Attachment is a media attachment on a message in the format :. Content type may be a full // media type or may omit the subtype when it is unknown. // diff --git a/utils/attachment_test.go b/utils/attachment_test.go index 7eca6996a..b366b67f1 100644 --- a/utils/attachment_test.go +++ b/utils/attachment_test.go @@ -40,3 +40,17 @@ func TestAttachment(t *testing.T) { assertParse("HTTPS://test.jpg", "", "HTTPS://test.jpg", false) assertParse(":http://test.jpg", "", ":http://test.jpg", false) } + +func TestAttachmentValidation(t *testing.T) { + type testStruct struct { + Valid string `json:"valid" validate:"attachment"` + Invalid string `json:"invalid" validate:"attachment"` + } + + obj := testStruct{ + Valid: "image:http://test.jpg", + Invalid: "xyz", + } + err := utils.Validate(obj) + assert.EqualError(t, err, "field 'invalid' is not a valid attachment") +}