Skip to content

Commit

Permalink
fix(core): p2p: getPushDestinationsForEvent
Browse files Browse the repository at this point in the history
  • Loading branch information
glouvigny committed Feb 5, 2019
1 parent 60a34d5 commit ffa470e
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 6 deletions.
3 changes: 2 additions & 1 deletion core/entity/device_push_config.go
@@ -1,10 +1,11 @@
package entity

import (
"encoding/base64"

"berty.tech/core/crypto/keypair"
"berty.tech/core/pkg/errorcodes"
"berty.tech/core/push"
"encoding/base64"
"github.com/google/uuid"
)

Expand Down
15 changes: 10 additions & 5 deletions core/node/p2papi.go
Expand Up @@ -200,6 +200,7 @@ func (n *Node) queuePushEvent(ctx context.Context, event *p2p.Event, envelope *p
func (n *Node) getPushDestinationsForEvent(ctx context.Context, event *p2p.Event) ([]*entity.DevicePushIdentifier, error) {
db := n.sql(ctx)
var subqueryContactIDs interface{}
deviceIDs := []string{}
pushIdentifiers := []*entity.DevicePushIdentifier{}

if event.ConversationID != "" {
Expand All @@ -212,14 +213,18 @@ func (n *Node) getPushDestinationsForEvent(ctx context.Context, event *p2p.Event
subqueryContactIDs = []string{event.ReceiverID}
}

if err := db.
Model(&entity.Device{}).
Where("contact_id IN (?)", subqueryContactIDs).
Pluck("id", &deviceIDs).Error; err != nil {
return nil, sql.GenericError(err)
}

if err := db.
Model(&entity.DevicePushIdentifier{}).
Where("device_id IN (?)", deviceIDs).
Find(&pushIdentifiers).
Where("device_id IN (?)", db.
Model(&entity.Device{}).
Select("device_id").
Where("contact_id IN (?)", subqueryContactIDs).
SubQuery()).Error; err != nil {
Error; err != nil {
return nil, sql.GenericError(err)
}

Expand Down
124 changes: 124 additions & 0 deletions core/node/p2papi_test.go
Expand Up @@ -2,8 +2,15 @@ package node

import (
"context"
"fmt"
"testing"

"github.com/pkg/errors"

"github.com/google/uuid"

"berty.tech/core/push"

"crypto/rand"
"crypto/rsa"

Expand Down Expand Up @@ -220,3 +227,120 @@ func TestOpenEnvelope(t *testing.T) {
}

}

func TestGetPushDestinationsForEvent(t *testing.T) {
var err error
identifiers := []*entity.DevicePushIdentifier{}

pushRelayPrivateKey, _ := rsa.GenerateKey(rand.Reader, 2048)
pushRelayPublicKeyBytes, _ := x509.MarshalPKIXPublicKey(pushRelayPrivateKey.Public())

ctx := context.Background()
alice, _ := testNode(t)

alice.sql(ctx).Create(&entity.DevicePushConfig{
ID: "AlicePushConfig",
DeviceID: alice.config.CurrentDeviceID,
PushType: push.DevicePushType_APNS,
PushID: []byte("AlicePushToken"),
RelayPubkey: b64(pushRelayPublicKeyBytes),
})

alice.sql(ctx).Create(&entity.Contact{ID: "Bob"})
alice.sql(ctx).Create(&entity.Device{ID: "BobDevice", ContactID: "Bob"})
pushIdBob := createPushId("BobDevice", push.DevicePushType_APNS, pushRelayPublicKeyBytes)
alice.sql(ctx).Create(pushIdBob)

alice.sql(ctx).Create(&entity.Contact{ID: "Charlie"})
alice.sql(ctx).Create(&entity.Device{ID: "CharlieDevice", ContactID: "Charlie"})
pushIdCharlie := createPushId("CharlieDevice", push.DevicePushType_FCM, pushRelayPublicKeyBytes)
alice.sql(ctx).Create(pushIdCharlie)

alice.sql(ctx).Create(&entity.Contact{ID: "Daryl"})
alice.sql(ctx).Create(&entity.Device{ID: "DarylDevice", ContactID: "Daryl"})
pushIdDaryl := createPushId("DarylDevice", push.DevicePushType_APNS, pushRelayPublicKeyBytes)
alice.sql(ctx).Create(pushIdDaryl)

alice.sql(ctx).Create(&entity.Conversation{ID: "ConversationBobCharlie"})

alice.sql(ctx).Create(&entity.ConversationMember{
ID: "ConversationMemberBob",
ConversationID: "ConversationBobCharlie",
ContactID: "Bob",
})
alice.sql(ctx).Create(&entity.ConversationMember{
ID: "ConversationMemberCharlie",
ConversationID: "ConversationBobCharlie",
ContactID: "Charlie",
})

//
// One to one checks
//

if identifiers, err = alice.getPushDestinationsForEvent(ctx, &p2p.Event{ReceiverID: "Bob"}); err != nil {
t.Error(err)
}

if len(identifiers) != 1 {
t.Error(errors.New(fmt.Sprintf("expected 1 push identifier for one-to-one event, got %d", len(identifiers))))
}

if identifiers[0].ID != "BobDevicePushIdentifier" {
t.Error(errors.New(fmt.Sprintf("invalid push identifier retrieved, expected BobDevicePushIdentifier, got %s", identifiers[0].ID)))
}

//
// Conversation checks
//

expectedIdentifiers := map[string]bool{
"BobDevicePushIdentifier": false,
"CharlieDevicePushIdentifier": false,
}

if identifiers, err = alice.getPushDestinationsForEvent(ctx, &p2p.Event{ConversationID: "ConversationBobCharlie"}); err != nil {
t.Error(err)
}

if len(identifiers) != 2 {
t.Error(errors.New(fmt.Sprintf("expected 2 push identifiers for conversation event, got %d", len(identifiers))))
}

for _, identifier := range identifiers {
_, ok := expectedIdentifiers[identifier.ID]
if !ok {
t.Error(errors.New(fmt.Sprintf("push identifier %s was not expected for conversation", identifier.ID)))
}

expectedIdentifiers[identifier.ID] = true
}

for identifier, found := range expectedIdentifiers {
if !found {
t.Error(errors.New(fmt.Sprintf("push identifier %s was expected for conversation", identifier)))
}
}
}

func createPushId(deviceId string, pushType push.DevicePushType, relayPubKeyBytes []byte) *entity.DevicePushIdentifier {
pushId := fmt.Sprintf("%sPushIdentifier", deviceId)
nonce, _ := uuid.New().MarshalBinary()

plainPushStruct := &push.PushDestination{
PushId: []byte(pushId),
Nonce: nonce,
PushType: pushType,
}

plainPushInfo, _ := plainPushStruct.Marshal()
pushInfo, _ := keypair.Encrypt(plainPushInfo, relayPubKeyBytes)

return &entity.DevicePushIdentifier{
ID: pushId,
PushInfo: pushInfo,
RelayPubkey: b64(relayPubKeyBytes),
DeviceID: deviceId,
}

}

0 comments on commit ffa470e

Please sign in to comment.