Skip to content

Commit 8d70f22

Browse files
authored
Merge pull request #78 from Ilhasoft/update/v6.5.8
Update/v6.5.8
2 parents dc629b1 + 6c31eb7 commit 8d70f22

17 files changed

+673
-272
lines changed

Diff for: CHANGELOG.md

+27
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,30 @@
1+
v6.5.8
2+
----------
3+
* Fix Facebook document attachment
4+
* Update to latest gocommon and phonenumbers
5+
6+
v6.5.7
7+
----------
8+
* Fix to only set the quick replies keyboard for the last message
9+
* Update to latest gocommon
10+
11+
v6.5.6
12+
----------
13+
* Fix FB signing checks by trimming prefix instead of stripping
14+
* Improve layout of Telegram keyboards
15+
16+
v6.5.5
17+
----------
18+
* Send WhatsApp buttons and list buttons when supported (thanks Weni)
19+
20+
v6.5.4
21+
----------
22+
* trim prefix instead of strip when comparing FB sigs
23+
24+
v6.5.3
25+
----------
26+
* log body when calculating signatures, include expected and calculated
27+
128
v6.5.2
229
----------
330
* Add ticket_count column to contact and set to zero when creating new contacts

Diff for: backends/rapidpro/contact.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,8 @@ SELECT
8484
c.modified_on,
8585
c.created_on,
8686
c.name,
87-
u.id as "urn_id"
87+
u.id as "urn_id",
88+
c.status
8889
FROM
8990
contacts_contact AS c,
9091
contacts_contacturn AS u
@@ -232,7 +233,8 @@ type DBContact struct {
232233
CreatedBy_ int `db:"created_by_id"`
233234
ModifiedBy_ int `db:"modified_by_id"`
234235

235-
IsNew_ bool
236+
IsNew_ bool
237+
Status_ string `db:"status"`
236238
}
237239

238240
// UUID returns the UUID for this contact

Diff for: go.mod

+3-2
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,16 @@ require (
2222
github.com/lib/pq v1.0.0
2323
github.com/mattn/go-sqlite3 v1.10.0 // indirect
2424
github.com/nyaruka/ezconf v0.2.1
25-
github.com/nyaruka/gocommon v1.13.0
25+
github.com/nyaruka/gocommon v1.13.2
2626
github.com/nyaruka/librato v1.0.0
2727
github.com/nyaruka/null v1.1.1
2828
github.com/patrickmn/go-cache v2.1.0+incompatible
2929
github.com/pkg/errors v0.9.1
3030
github.com/sirupsen/logrus v1.4.2
3131
github.com/stretchr/testify v1.7.0
32+
golang.org/x/mod v0.4.2
3233
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
33-
gopkg.in/go-playground/assert.v1 v1.2.1
34+
gopkg.in/go-playground/assert.v1 v1.2.1 // indirect
3435
gopkg.in/go-playground/validator.v9 v9.11.0
3536
gopkg.in/h2non/filetype.v1 v1.0.5
3637
)

Diff for: go.sum

+12-4
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,14 @@ github.com/naoina/toml v0.1.1 h1:PT/lllxVVN0gzzSqSlHEmP8MJB4MY2U7STGxiouV4X8=
6262
github.com/naoina/toml v0.1.1/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E=
6363
github.com/nyaruka/ezconf v0.2.1 h1:TDXWoqjqYya1uhou1mAJZg7rgFYL98EB0Tb3+BWtUh0=
6464
github.com/nyaruka/ezconf v0.2.1/go.mod h1:ey182kYkw2MIi4XiWe1FR/mzI33WCmTWuceDYYxgnQw=
65-
github.com/nyaruka/gocommon v1.13.0 h1:WPL//ekajA30KinYRr6IrdP1igNZpcUAfABleHCuxPQ=
66-
github.com/nyaruka/gocommon v1.13.0/go.mod h1:Jn7UIE8zwIr4JaviDf4PZrrQlN8r6QGVhOuaF/JoKus=
65+
github.com/nyaruka/gocommon v1.13.2 h1:dNe8nGDSeECC7zL6H/0vmx9yp6UG8HJFxjKcIQmiccY=
66+
github.com/nyaruka/gocommon v1.13.2/go.mod h1:2DWgWcjsfdU/+29xEP75G9xnorxvrxxe1pSISzUcSgw=
6767
github.com/nyaruka/librato v1.0.0 h1:Vznj9WCeC1yZXbBYyYp40KnbmXLbEkjKmHesV/v2SR0=
6868
github.com/nyaruka/librato v1.0.0/go.mod h1:pkRNLFhFurOz0QqBz6/DuTFhHHxAubWxs4Jx+J7yUgg=
6969
github.com/nyaruka/null v1.1.1 h1:kRy1Luj7jUHWEFqc2J6VXrKYi/beLEZdS1C7rA6vqTE=
7070
github.com/nyaruka/null v1.1.1/go.mod h1:HSAFbLNOaEhHnoU0VCveCPz0GDtJ3GEtFWhvnBNkhPE=
71-
github.com/nyaruka/phonenumbers v1.0.58 h1:IAlGDA4wuGQXe2lwOQvkZfBvA1DlAik+MX5k9k5C2IU=
72-
github.com/nyaruka/phonenumbers v1.0.58/go.mod h1:sDaTZ/KPX5f8qyV9qN+hIm+4ZBARJrupC6LuhshJq1U=
71+
github.com/nyaruka/phonenumbers v1.0.71 h1:itkCGhxkQkHrJ6OyZSApdjQVlPmrWs88MF283pPvbFU=
72+
github.com/nyaruka/phonenumbers v1.0.71/go.mod h1:sDaTZ/KPX5f8qyV9qN+hIm+4ZBARJrupC6LuhshJq1U=
7373
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
7474
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
7575
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -88,11 +88,16 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
8888
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
8989
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
9090
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
91+
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
9192
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
93+
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
94+
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
9295
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
96+
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
9397
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
9498
golang.org/x/net v0.0.0-20200925080053-05aa5d4ee321 h1:lleNcKRbcaC8MqgLwghIkzZ2JBQAb7QQ9MiwRt1BisA=
9599
golang.org/x/net v0.0.0-20200925080053-05aa5d4ee321/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
100+
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
96101
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
97102
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
98103
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -102,6 +107,9 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
102107
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
103108
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
104109
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
110+
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
111+
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
112+
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
105113
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
106114
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
107115
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

Diff for: handlers/facebook/facebook.go

+3
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,9 @@ func (h *handler) SendMsg(ctx context.Context, msg courier.Msg) (courier.MsgStat
517517
payload.Message.Attachment = &mtAttachment{}
518518
attType, attURL := handlers.SplitAttachment(msg.Attachments()[i])
519519
attType = strings.Split(attType, "/")[0]
520+
if attType == "application" {
521+
attType = "file"
522+
}
520523
payload.Message.Attachment.Type = attType
521524
payload.Message.Attachment.Payload.URL = attURL
522525
payload.Message.Attachment.Payload.IsReusable = true

Diff for: handlers/facebook/facebook_test.go

+6
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,12 @@ var defaultSendTestCases = []ChannelSendTestCase{
607607
ResponseBody: `{"message_id": "mid.133"}`, ResponseStatus: 200,
608608
RequestBody: `{"messaging_type":"MESSAGE_TAG","tag":"CONFIRMED_EVENT_UPDATE","recipient":{"id":"12345"},"message":{"text":"This is some text.","quick_replies":[{"title":"Yes","payload":"Yes","content_type":"text"},{"title":"No","payload":"No","content_type":"text"}]}}`,
609609
SendPrep: setSendURL},
610+
{Label: "Send Document",
611+
URN: "facebook:12345", Attachments: []string{"application/pdf:https://foo.bar/document.pdf"},
612+
Status: "W", ExternalID: "mid.133",
613+
ResponseBody: `{"message_id": "mid.133"}`, ResponseStatus: 200,
614+
RequestBody: `{"messaging_type":"NON_PROMOTIONAL_SUBSCRIPTION","recipient":{"id":"12345"},"message":{"attachment":{"type":"file","payload":{"url":"https://foo.bar/document.pdf","is_reusable":true}}}}`,
615+
SendPrep: setSendURL},
610616
{Label: "ID Error",
611617
Text: "ID Error", URN: "facebook:12345",
612618
Status: "E",

Diff for: handlers/facebookapp/facebookapp.go

+13-10
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,9 @@ func (h *handler) SendMsg(ctx context.Context, msg courier.Msg) (courier.MsgStat
524524
payload.Message.Attachment = &mtAttachment{}
525525
attType, attURL := handlers.SplitAttachment(msg.Attachments()[i])
526526
attType = strings.Split(attType, "/")[0]
527+
if attType == "application" {
528+
attType = "file"
529+
}
527530
payload.Message.Attachment.Type = attType
528531
payload.Message.Attachment.Payload.URL = attURL
529532
payload.Message.Attachment.Payload.IsReusable = true
@@ -662,32 +665,32 @@ func (h *handler) validateSignature(r *http.Request) error {
662665
}
663666
appSecret := h.Server().Config().FacebookApplicationSecret
664667

665-
expectedSignature, err := fbCalculateSignature(appSecret, r)
668+
body, err := handlers.ReadBody(r, 100000)
669+
if err != nil {
670+
return fmt.Errorf("unable to read request body: %s", err)
671+
}
672+
673+
expectedSignature, err := fbCalculateSignature(appSecret, body)
666674
if err != nil {
667675
return err
668676
}
669677

670678
signature := ""
671679
if len(headerSignature) == 45 && strings.HasPrefix(headerSignature, "sha1=") {
672-
signature = strings.TrimLeft(headerSignature, "sha1=")
680+
signature = strings.TrimPrefix(headerSignature, "sha1=")
673681
}
674682

675683
// compare signatures in way that isn't sensitive to a timing attack
676684
if !hmac.Equal([]byte(expectedSignature), []byte(signature)) {
677-
return fmt.Errorf("invalid request signature")
685+
return fmt.Errorf("invalid request signature, expected: %s got: %s for body: '%s'", expectedSignature, signature, string(body))
678686
}
679687

680688
return nil
681689
}
682690

683-
func fbCalculateSignature(appSecret string, r *http.Request) (string, error) {
684-
rawPostData, err := handlers.ReadBody(r, 100000)
685-
if err != nil {
686-
return "", fmt.Errorf("unable to read request body: %s", err)
687-
}
688-
691+
func fbCalculateSignature(appSecret string, body []byte) (string, error) {
689692
var buffer bytes.Buffer
690-
buffer.Write(rawPostData)
693+
buffer.Write(body)
691694

692695
// hash with SHA1
693696
mac := hmac.New(sha1.New, []byte(appSecret))

Diff for: handlers/facebookapp/facebookapp_test.go

+32-2
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ import (
1010
"time"
1111

1212
"github.com/nyaruka/courier"
13+
"github.com/nyaruka/courier/handlers"
1314
. "github.com/nyaruka/courier/handlers"
1415
"github.com/nyaruka/gocommon/urns"
15-
"gopkg.in/go-playground/assert.v1"
16+
"github.com/stretchr/testify/assert"
1617
)
1718

1819
var testChannels = []courier.Channel{
@@ -479,7 +480,8 @@ var testCases = []ChannelHandleTestCase{
479480
}
480481

481482
func addValidSignature(r *http.Request) {
482-
sig, _ := fbCalculateSignature("fb_app_secret", r)
483+
body, _ := handlers.ReadBody(r, 100000)
484+
sig, _ := fbCalculateSignature("fb_app_secret", body)
483485
r.Header.Set(signatureHeader, fmt.Sprintf("sha1=%s", string(sig)))
484486
}
485487

@@ -606,6 +608,12 @@ var defaultSendTestCases = []ChannelSendTestCase{
606608
ResponseBody: `{"message_id": "mid.133"}`, ResponseStatus: 200,
607609
RequestBody: `{"messaging_type":"MESSAGE_TAG","tag":"CONFIRMED_EVENT_UPDATE","recipient":{"id":"12345"},"message":{"text":"This is some text.","quick_replies":[{"title":"Yes","payload":"Yes","content_type":"text"},{"title":"No","payload":"No","content_type":"text"}]}}`,
608610
SendPrep: setSendURL},
611+
{Label: "Send Document",
612+
URN: "facebook:12345", Attachments: []string{"application/pdf:https://foo.bar/document.pdf"},
613+
Status: "W", ExternalID: "mid.133",
614+
ResponseBody: `{"message_id": "mid.133"}`, ResponseStatus: 200,
615+
RequestBody: `{"messaging_type":"NON_PROMOTIONAL_SUBSCRIPTION","recipient":{"id":"12345"},"message":{"attachment":{"type":"file","payload":{"url":"https://foo.bar/document.pdf","is_reusable":true}}}}`,
616+
SendPrep: setSendURL},
609617
{Label: "ID Error",
610618
Text: "ID Error", URN: "facebook:12345",
611619
Status: "E",
@@ -624,3 +632,25 @@ func TestSending(t *testing.T) {
624632
var defaultChannel = courier.NewMockChannel("8eb23e93-5ecb-45ba-b726-3b064e0c56ab", "FBA", "2020", "US", map[string]interface{}{courier.ConfigAuthToken: "access_token"})
625633
RunChannelSendTestCases(t, defaultChannel, newHandler(), defaultSendTestCases, nil)
626634
}
635+
636+
func TestSigning(t *testing.T) {
637+
tcs := []struct {
638+
Body string
639+
Signature string
640+
}{
641+
{
642+
"hello world",
643+
"308de7627fe19e92294c4572a7f831bc1002809d",
644+
},
645+
{
646+
"hello world2",
647+
"ab6f902b58b9944032d4a960f470d7a8ebfd12b7",
648+
},
649+
}
650+
651+
for i, tc := range tcs {
652+
sig, err := fbCalculateSignature("sesame", []byte(tc.Body))
653+
assert.NoError(t, err)
654+
assert.Equal(t, tc.Signature, sig, "%d: mismatched signature", i)
655+
}
656+
}

Diff for: handlers/telegram/keyboard.go

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package telegram
2+
3+
import "github.com/nyaruka/courier/utils"
4+
5+
// KeyboardButton is button on a keyboard, see https://core.telegram.org/bots/api/#keyboardbutton
6+
type KeyboardButton struct {
7+
Text string `json:"text"`
8+
RequestContact bool `json:"request_contact,omitempty"`
9+
RequestLocation bool `json:"request_location,omitempty"`
10+
}
11+
12+
// ReplyKeyboardMarkup models a keyboard, see https://core.telegram.org/bots/api/#replykeyboardmarkup
13+
type ReplyKeyboardMarkup struct {
14+
Keyboard [][]KeyboardButton `json:"keyboard"`
15+
ResizeKeyboard bool `json:"resize_keyboard"`
16+
OneTimeKeyboard bool `json:"one_time_keyboard"`
17+
}
18+
19+
// NewKeyboardFromReplies creates a keyboard from the given quick replies
20+
func NewKeyboardFromReplies(replies []string) *ReplyKeyboardMarkup {
21+
rows := utils.StringsToRows(replies, 5, 30, 2)
22+
keyboard := make([][]KeyboardButton, len(rows))
23+
24+
for i := range rows {
25+
keyboard[i] = make([]KeyboardButton, len(rows[i]))
26+
for j := range rows[i] {
27+
keyboard[i][j].Text = rows[i][j]
28+
}
29+
}
30+
31+
return &ReplyKeyboardMarkup{Keyboard: keyboard, ResizeKeyboard: true, OneTimeKeyboard: true}
32+
}

Diff for: handlers/telegram/keyboard_test.go

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package telegram_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/nyaruka/courier/handlers/telegram"
7+
"github.com/stretchr/testify/assert"
8+
)
9+
10+
func TestKeyboardFromReplies(t *testing.T) {
11+
tcs := []struct {
12+
replies []string
13+
expected *telegram.ReplyKeyboardMarkup
14+
}{
15+
{
16+
17+
[]string{"OK"},
18+
&telegram.ReplyKeyboardMarkup{
19+
[][]telegram.KeyboardButton{
20+
{{Text: "OK"}},
21+
},
22+
true, true,
23+
},
24+
},
25+
{
26+
[]string{"Yes", "No", "Maybe"},
27+
&telegram.ReplyKeyboardMarkup{
28+
[][]telegram.KeyboardButton{
29+
{{Text: "Yes"}, {Text: "No"}, {Text: "Maybe"}},
30+
},
31+
true, true,
32+
},
33+
},
34+
{
35+
[]string{"Vanilla", "Chocolate", "Mint", "Lemon Sorbet", "Papaya", "Strawberry"},
36+
&telegram.ReplyKeyboardMarkup{
37+
[][]telegram.KeyboardButton{
38+
{{Text: "Vanilla"}, {Text: "Chocolate"}},
39+
{{Text: "Mint"}, {Text: "Lemon Sorbet"}},
40+
{{Text: "Papaya"}, {Text: "Strawberry"}},
41+
},
42+
true, true,
43+
},
44+
},
45+
{
46+
[]string{"A", "B", "C", "D", "Chicken", "Fish", "Peanut Butter Pickle"},
47+
&telegram.ReplyKeyboardMarkup{
48+
[][]telegram.KeyboardButton{
49+
{{Text: "A"}, {Text: "B"}, {Text: "C"}, {Text: "D"}},
50+
{{Text: "Chicken"}, {Text: "Fish"}},
51+
{{Text: "Peanut Butter Pickle"}},
52+
},
53+
true, true,
54+
},
55+
},
56+
}
57+
58+
for _, tc := range tcs {
59+
kb := telegram.NewKeyboardFromReplies(tc.replies)
60+
assert.Equal(t, tc.expected, kb, "keyboard mismatch for replies %v", tc.replies)
61+
}
62+
}

0 commit comments

Comments
 (0)