Skip to content

Commit fd1aae4

Browse files
authored
Add End-to-end encryption for TriggerBatch (#49)
- It adds missing End-to-end encryption support for TriggerBatch - It adds small refactors and moves hardcoded values into easy modifiable constants - It updates the max number of triggerable channels from 10 to 100 (as per official documentation of Pusher) ------------ commits details: * fix wrong comments on TriggerBatch * add comment to exported type EncryptedMessage * reorder external lib imports * move max event payload size into a const * updated maxTriggerableChans 10->100, move to const * move max channel name size into his own const * refactor payload encoding in its own func * remove encryptedChannelPresent for explicit logic * add missing end-to-end encryption in TriggerBatch * add in-depth TriggerBatch testing * refactor chan validation in fun, clean whitespaces * rename byteEncodePayload to encodePayload
1 parent 8890816 commit fd1aae4

File tree

9 files changed

+195
-111
lines changed

9 files changed

+195
-111
lines changed

channel_authentication_test.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
package pusher
22

33
import (
4-
"github.com/stretchr/testify/assert"
54
"testing"
5+
6+
"github.com/stretchr/testify/assert"
67
)
78

89
func setUpAuthClient() Client {
@@ -40,12 +41,8 @@ func TestPresenceChannelAuthentication(t *testing.T) {
4041

4142
func TestAuthSocketIdValidation(t *testing.T) {
4243
client := setUpAuthClient()
43-
4444
postParams := []byte("channel_name=private-foobar&socket_id=12341234")
45-
4645
result, err := client.AuthenticatePrivateChannel(postParams)
47-
4846
assert.Nil(t, result)
4947
assert.Error(t, err)
50-
5148
}

client.go

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
)
1515

1616
var pusherPathRegex = regexp.MustCompile("^/apps/([0-9]+)$")
17+
var maxTriggerableChannels = 100
1718

1819
/*
1920
Client to the HTTP API of Pusher.
@@ -138,7 +139,7 @@ func (c *Client) Trigger(channel string, eventName string, data interface{}) (*B
138139

139140
/*
140141
The same as `client.Trigger`, except one passes in a slice of `channels` as the first parameter.
141-
The maximum length of channels is 10.
142+
The maximum length of channels is 100.
142143
client.TriggerMulti([]string{"a_channel", "another_channel"}, "event", data)
143144
*/
144145
func (c *Client) TriggerMulti(channels []string, eventName string, data interface{}) (*BufferedEvents, error) {
@@ -167,30 +168,32 @@ func (c *Client) TriggerMultiExclusive(channels []string, eventName string, data
167168
}
168169

169170
func (c *Client) trigger(channels []string, eventName string, data interface{}, socketID *string) (*BufferedEvents, error) {
170-
if len(channels) > 10 {
171-
return nil, errors.New("You cannot trigger on more than 10 channels at once")
171+
hasEncryptedChannel := false
172+
for _, channel := range channels {
173+
if isEncryptedChannel(channel) {
174+
hasEncryptedChannel = true
175+
}
172176
}
173-
174-
if len(channels) > 1 && encryptedChannelPresent(channels) {
175-
return nil, errors.New("You cannot trigger batch events when using encrypted channels")
177+
if len(channels) > maxTriggerableChannels {
178+
return nil, fmt.Errorf("You cannot trigger on more than %d channels at once", maxTriggerableChannels)
179+
}
180+
if hasEncryptedChannel && len(channels) > 1 {
181+
// For rationale, see limitations of end-to-end encryption in the README
182+
return nil, errors.New("You cannot trigger to multiple channels when using encrypted channels")
176183
}
177-
178184
if !channelsAreValid(channels) {
179185
return nil, errors.New("At least one of your channels' names are invalid")
180186
}
181-
if !validEncryptionKey(c.EncryptionMasterKey) && encryptedChannelPresent(channels) {
182-
return nil, errors.New("Your Encryption key is not of the correct format")
187+
if hasEncryptedChannel && !validEncryptionKey(c.EncryptionMasterKey) {
188+
return nil, errors.New("Your encryptionMasterKey is not of the correct format")
183189
}
184-
185190
if err := validateSocketID(socketID); err != nil {
186191
return nil, err
187192
}
188-
189193
payload, err := createTriggerPayload(channels, eventName, data, socketID, c.EncryptionMasterKey)
190194
if err != nil {
191195
return nil, err
192196
}
193-
194197
path := fmt.Sprintf("/apps/%s/events", c.AppId)
195198
u, err := createRequestURL("POST", c.Host, path, c.Key, c.Secret, authTimestamp(), c.Secure, payload, nil, c.Cluster)
196199
if err != nil {
@@ -200,20 +203,43 @@ func (c *Client) trigger(channels []string, eventName string, data interface{},
200203
if err != nil {
201204
return nil, err
202205
}
203-
204206
return unmarshalledBufferedEvents(response)
205207
}
206208

207209
type batchRequest struct {
208210
Batch []Event `json:"batch"`
209211
}
210212

213+
/* TriggerBatch triggers multiple events on multiple types of channels in a single call:
214+
client.TriggerBatch([]pusher.Event{
215+
{ Channel: "donut-1", Name: "ev1", Data: "pippo1" },
216+
{ Channel: "private-encrypted-secretdonut", Name: "ev2", Data: "pippo2" },
217+
})
218+
*/
211219
func (c *Client) TriggerBatch(batch []Event) (*BufferedEvents, error) {
212-
payload, err := json.Marshal(&batchRequest{batch})
220+
hasEncryptedChannel := false
221+
// validate every channel name and every sockedID (if present) in batch
222+
for _, event := range batch {
223+
if !validChannel(event.Channel) {
224+
return nil, fmt.Errorf("The channel named %s has a non-valid name", event.Channel)
225+
}
226+
if err := validateSocketID(event.SocketId); err != nil {
227+
return nil, err
228+
}
229+
if isEncryptedChannel(event.Channel) {
230+
hasEncryptedChannel = true
231+
}
232+
}
233+
if hasEncryptedChannel {
234+
// validate EncryptionMasterKey
235+
if !validEncryptionKey(c.EncryptionMasterKey) {
236+
return nil, errors.New("Your encryptionMasterKey is not of the correct format")
237+
}
238+
}
239+
payload, err := createTriggerBatchPayload(batch, c.EncryptionMasterKey)
213240
if err != nil {
214241
return nil, err
215242
}
216-
217243
path := fmt.Sprintf("/apps/%s/batch_events", c.AppId)
218244
u, err := createRequestURL("POST", c.Host, path, c.Key, c.Secret, authTimestamp(), c.Secure, payload, nil, c.Cluster)
219245
if err != nil {
@@ -223,7 +249,6 @@ func (c *Client) TriggerBatch(batch []Event) (*BufferedEvents, error) {
223249
if err != nil {
224250
return nil, err
225251
}
226-
227252
return unmarshalledBufferedEvents(response)
228253
}
229254

0 commit comments

Comments
 (0)