Implement server persistence for client & basic tests
This commit is contained in:
parent
3afde67022
commit
d985af4a7e
|
@ -1,19 +1,24 @@
|
|||
package push_notification_server
|
||||
package common
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/ecdsa"
|
||||
"errors"
|
||||
"github.com/status-im/status-go/eth-node/crypto"
|
||||
"golang.org/x/crypto/sha3"
|
||||
"io"
|
||||
)
|
||||
|
||||
func hashPublicKey(pk *ecdsa.PublicKey) []byte {
|
||||
return shake256(crypto.CompressPubkey(pk))
|
||||
const nonceLength = 12
|
||||
|
||||
var ErrInvalidCiphertextLength = errors.New("invalid cyphertext length")
|
||||
|
||||
func HashPublicKey(pk *ecdsa.PublicKey) []byte {
|
||||
return Shake256(crypto.CompressPubkey(pk))
|
||||
}
|
||||
|
||||
func decrypt(cyphertext []byte, key []byte) ([]byte, error) {
|
||||
func Decrypt(cyphertext []byte, key []byte) ([]byte, error) {
|
||||
if len(cyphertext) < nonceLength {
|
||||
return nil, ErrInvalidCiphertextLength
|
||||
}
|
||||
|
@ -32,7 +37,7 @@ func decrypt(cyphertext []byte, key []byte) ([]byte, error) {
|
|||
return gcm.Open(nil, nonce, cyphertext[nonceLength:], nil)
|
||||
}
|
||||
|
||||
func encrypt(plaintext []byte, key []byte, reader io.Reader) ([]byte, error) {
|
||||
func Encrypt(plaintext []byte, key []byte, reader io.Reader) ([]byte, error) {
|
||||
c, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -51,8 +56,14 @@ func encrypt(plaintext []byte, key []byte, reader io.Reader) ([]byte, error) {
|
|||
return gcm.Seal(nonce, nonce, plaintext, nil), nil
|
||||
}
|
||||
|
||||
func shake256(buf []byte) []byte {
|
||||
func Shake256(buf []byte) []byte {
|
||||
h := make([]byte, 64)
|
||||
sha3.ShakeSum256(h, buf)
|
||||
return h
|
||||
}
|
||||
|
||||
// IsPubKeyEqual checks that two public keys are equal
|
||||
func IsPubKeyEqual(a, b *ecdsa.PublicKey) bool {
|
||||
// the curve is always the same, just compare the points
|
||||
return a.X.Cmp(b.X) == 0 && a.Y.Cmp(b.Y) == 0
|
||||
}
|
|
@ -482,9 +482,3 @@ func calculatePoW(payload []byte) float64 {
|
|||
}
|
||||
return whisperDefaultPoW
|
||||
}
|
||||
|
||||
// IsPubKeyEqual checks that two public keys are equal
|
||||
func IsPubKeyEqual(a, b *ecdsa.PublicKey) bool {
|
||||
// the curve is always the same, just compare the points
|
||||
return a.X.Cmp(b.X) == 0 && a.Y.Cmp(b.Y) == 0
|
||||
}
|
||||
|
|
|
@ -72,6 +72,7 @@ type Messenger struct {
|
|||
allInstallations map[string]*multidevice.Installation
|
||||
modifiedInstallations map[string]bool
|
||||
installationID string
|
||||
mailserver []byte
|
||||
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
@ -2036,13 +2037,19 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte
|
|||
return messageState.Response, nil
|
||||
}
|
||||
|
||||
func (m *Messenger) SetMailserver(peer []byte) {
|
||||
m.mailserver = peer
|
||||
}
|
||||
|
||||
func (m *Messenger) RequestHistoricMessages(
|
||||
ctx context.Context,
|
||||
peer []byte, // should be removed after mailserver logic is ported
|
||||
from, to uint32,
|
||||
cursor []byte,
|
||||
) ([]byte, error) {
|
||||
return m.transport.SendMessagesRequest(ctx, peer, from, to, cursor)
|
||||
if m.mailserver == nil {
|
||||
return nil, errors.New("no mailserver selected")
|
||||
}
|
||||
return m.transport.SendMessagesRequest(ctx, m.mailserver, from, to, cursor)
|
||||
}
|
||||
|
||||
func (m *Messenger) LoadFilters(filters []*transport.Filter) ([]*transport.Filter, error) {
|
||||
|
@ -2965,6 +2972,46 @@ func (m *Messenger) Timesource() TimeSource {
|
|||
return m.getTimesource()
|
||||
}
|
||||
|
||||
// AddPushNotificationServer adds a push notification server
|
||||
func (m *Messenger) AddPushNotificationServer(ctx context.Context, publicKey *ecdsa.PublicKey) error {
|
||||
if m.pushNotificationClient == nil {
|
||||
return errors.New("push notification client not enabled")
|
||||
}
|
||||
return m.pushNotificationClient.AddPushNotificationServer(publicKey)
|
||||
}
|
||||
|
||||
// RegisterForPushNotification register deviceToken with any push notification server enabled
|
||||
func (m *Messenger) RegisterForPushNotifications(ctx context.Context, deviceToken string) error {
|
||||
if m.pushNotificationClient == nil {
|
||||
return errors.New("push notification client not enabled")
|
||||
}
|
||||
|
||||
var contactIDs []*ecdsa.PublicKey
|
||||
var mutedChatIDs []string
|
||||
|
||||
m.mutex.Lock()
|
||||
for _, contact := range m.allContacts {
|
||||
if contact.IsAdded() {
|
||||
pk, err := contact.PublicKey()
|
||||
if err != nil {
|
||||
m.logger.Warn("could not parse contact public key")
|
||||
continue
|
||||
}
|
||||
contactIDs = append(contactIDs, pk)
|
||||
} else if contact.IsBlocked() {
|
||||
mutedChatIDs = append(mutedChatIDs, contact.ID)
|
||||
}
|
||||
}
|
||||
for _, chat := range m.allChats {
|
||||
if chat.Muted {
|
||||
mutedChatIDs = append(mutedChatIDs, chat.ID)
|
||||
}
|
||||
|
||||
}
|
||||
m.mutex.Unlock()
|
||||
return m.pushNotificationClient.Register(deviceToken, contactIDs, mutedChatIDs)
|
||||
}
|
||||
|
||||
func generateAliasAndIdenticon(pk string) (string, string, error) {
|
||||
identicon, err := identicon.GenerateBase64(pk)
|
||||
if err != nil {
|
||||
|
|
|
@ -2106,7 +2106,8 @@ func (s *MessengerSuite) TestRequestHistoricMessagesRequest() {
|
|||
m := s.newMessenger(shh)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond)
|
||||
defer cancel()
|
||||
cursor, err := m.RequestHistoricMessages(ctx, nil, 10, 20, []byte{0x01})
|
||||
m.mailserver = []byte("mailserver-id")
|
||||
cursor, err := m.RequestHistoricMessages(ctx, 10, 20, []byte{0x01})
|
||||
s.EqualError(err, ctx.Err().Error())
|
||||
s.Empty(cursor)
|
||||
// verify request is correct
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
DROP TABLE push_notification_client_servers;
|
||||
DROP TABLE push_notification_client_info;
|
||||
DROP INDEX idx_push_notification_client_info_public_key;
|
|
@ -0,0 +1,15 @@
|
|||
CREATE TABLE IF NOT EXISTS push_notification_client_servers (
|
||||
public_key BLOB NOT NULL,
|
||||
registered BOOLEAN DEFAULT FALSE,
|
||||
registered_at INT NOT NULL DEFAULT 0,
|
||||
UNIQUE(public_key) ON CONFLICT REPLACE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS push_notification_client_info (
|
||||
public_key BLOB NOT NULL,
|
||||
installation_id TEXT NOT NULL,
|
||||
access_token TEXT NOT NULL,
|
||||
UNIQUE(public_key, installation_id) ON CONFLICT REPLACE
|
||||
);
|
||||
|
||||
CREATE INDEX idx_push_notification_client_info_public_key ON push_notification_client_info(public_key, installation_id);
|
|
@ -0,0 +1,9 @@
|
|||
// This file is necessary because "github.com/status-im/migrate/v4"
|
||||
// can't handle files starting with a prefix. At least that's the case
|
||||
// for go-bindata.
|
||||
// If go-bindata is called from the same directory, asset names
|
||||
// have no prefix and "github.com/status-im/migrate/v4" works as expected.
|
||||
|
||||
package migrations
|
||||
|
||||
//go:generate go-bindata -pkg migrations -o ./migrations.go .
|
|
@ -0,0 +1,57 @@
|
|||
package push_notification_client
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"database/sql"
|
||||
|
||||
"github.com/status-im/status-go/eth-node/crypto"
|
||||
)
|
||||
|
||||
type Persistence struct {
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
func NewPersistence(db *sql.DB) *Persistence {
|
||||
return &Persistence{db: db}
|
||||
}
|
||||
|
||||
func (p *Persistence) TrackPushNotification(messageID []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Persistence) ShouldSentNotificationFor(publicKey *ecdsa.PublicKey, messageID []byte) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (p *Persistence) SentFor(publicKey *ecdsa.PublicKey, messageID []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Persistence) UpsertServer(server *PushNotificationServer) error {
|
||||
_, err := p.db.Exec(`INSERT INTO push_notification_client_servers (public_key, registered, registered_at) VALUES (?,?,?)`, crypto.CompressPubkey(server.publicKey), server.registered, server.registeredAt)
|
||||
return err
|
||||
|
||||
}
|
||||
|
||||
func (p *Persistence) GetServers() ([]*PushNotificationServer, error) {
|
||||
rows, err := p.db.Query(`SELECT public_key, registered, registered_at FROM push_notification_client_servers`)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var servers []*PushNotificationServer
|
||||
for rows.Next() {
|
||||
server := &PushNotificationServer{}
|
||||
var key []byte
|
||||
err := rows.Scan(&key, &server.registered, &server.registeredAt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
parsedKey, err := crypto.DecompressPubkey(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
server.publicKey = parsedKey
|
||||
servers = append(servers, server)
|
||||
}
|
||||
return servers, nil
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
package push_notification_client
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"github.com/status-im/status-go/eth-node/crypto"
|
||||
"github.com/status-im/status-go/protocol/common"
|
||||
"github.com/status-im/status-go/protocol/sqlite"
|
||||
)
|
||||
|
||||
func TestSQLitePersistenceSuite(t *testing.T) {
|
||||
suite.Run(t, new(SQLitePersistenceSuite))
|
||||
}
|
||||
|
||||
type SQLitePersistenceSuite struct {
|
||||
suite.Suite
|
||||
tmpFile *os.File
|
||||
persistence *Persistence
|
||||
}
|
||||
|
||||
func (s *SQLitePersistenceSuite) SetupTest() {
|
||||
tmpFile, err := ioutil.TempFile("", "")
|
||||
s.Require().NoError(err)
|
||||
s.tmpFile = tmpFile
|
||||
|
||||
database, err := sqlite.Open(s.tmpFile.Name(), "")
|
||||
s.Require().NoError(err)
|
||||
s.persistence = NewPersistence(database)
|
||||
}
|
||||
|
||||
func (s *SQLitePersistenceSuite) TearDownTest() {
|
||||
_ = os.Remove(s.tmpFile.Name())
|
||||
}
|
||||
|
||||
func (s *SQLitePersistenceSuite) TestSaveAndRetrieveServer() {
|
||||
key, err := crypto.GenerateKey()
|
||||
s.Require().NoError(err)
|
||||
|
||||
server := &PushNotificationServer{
|
||||
publicKey: &key.PublicKey,
|
||||
registered: true,
|
||||
registeredAt: 1,
|
||||
}
|
||||
|
||||
s.Require().NoError(s.persistence.UpsertServer(server))
|
||||
|
||||
retrievedServers, err := s.persistence.GetServers()
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().Len(retrievedServers, 1)
|
||||
s.Require().True(retrievedServers[0].registered)
|
||||
s.Require().Equal(int64(1), retrievedServers[0].registeredAt)
|
||||
s.Require().True(common.IsPubKeyEqual(retrievedServers[0].publicKey, &key.PublicKey))
|
||||
|
||||
server.registered = false
|
||||
server.registeredAt = 2
|
||||
|
||||
s.Require().NoError(s.persistence.UpsertServer(server))
|
||||
|
||||
retrievedServers, err = s.persistence.GetServers()
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().Len(retrievedServers, 1)
|
||||
s.Require().False(retrievedServers[0].registered)
|
||||
s.Require().Equal(int64(2), retrievedServers[0].registeredAt)
|
||||
s.Require().True(common.IsPubKeyEqual(retrievedServers[0].publicKey, &key.PublicKey))
|
||||
}
|
|
@ -20,8 +20,15 @@ import (
|
|||
const accessTokenKeyLength = 16
|
||||
|
||||
type PushNotificationServer struct {
|
||||
key *ecdsa.PublicKey
|
||||
registered bool
|
||||
publicKey *ecdsa.PublicKey
|
||||
registered bool
|
||||
registeredAt int64
|
||||
}
|
||||
|
||||
type PushNotificationInfo struct {
|
||||
AccessToken string
|
||||
InstallationID string
|
||||
PublicKey *ecdsa.PublicKey
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
|
@ -35,10 +42,6 @@ type Config struct {
|
|||
// AllowOnlyFromContacts indicates whether we should be receiving push notifications
|
||||
// only from contacts
|
||||
AllowOnlyFromContacts bool
|
||||
// ContactIDs is the public keys for each contact that we allow notifications from
|
||||
ContactIDs []*ecdsa.PublicKey
|
||||
// MutedChatIDs is the IDs of the chats we don't want to receive notifications from
|
||||
MutedChatIDs []string
|
||||
// PushNotificationServers is an array of push notification servers we want to register with
|
||||
PushNotificationServers []*PushNotificationServer
|
||||
// InstallationID is the installation-id for this device
|
||||
|
@ -122,10 +125,10 @@ func (p *Client) NotifyOnMessageID(messageID []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *Client) mutedChatIDsHashes() [][]byte {
|
||||
func (p *Client) mutedChatIDsHashes(chatIDs []string) [][]byte {
|
||||
var mutedChatListHashes [][]byte
|
||||
|
||||
for _, chatID := range p.config.MutedChatIDs {
|
||||
for _, chatID := range chatIDs {
|
||||
mutedChatListHashes = append(mutedChatListHashes, shake256(chatID))
|
||||
}
|
||||
|
||||
|
@ -148,9 +151,9 @@ func (p *Client) encryptToken(publicKey *ecdsa.PublicKey, token []byte) ([]byte,
|
|||
return encryptedToken, nil
|
||||
}
|
||||
|
||||
func (p *Client) allowedUserList(token []byte) ([][]byte, error) {
|
||||
func (p *Client) allowedUserList(token []byte, contactIDs []*ecdsa.PublicKey) ([][]byte, error) {
|
||||
var encryptedTokens [][]byte
|
||||
for _, publicKey := range p.config.ContactIDs {
|
||||
for _, publicKey := range contactIDs {
|
||||
encryptedToken, err := p.encryptToken(publicKey, token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -162,9 +165,9 @@ func (p *Client) allowedUserList(token []byte) ([][]byte, error) {
|
|||
return encryptedTokens, nil
|
||||
}
|
||||
|
||||
func (p *Client) buildPushNotificationRegistrationMessage() (*protobuf.PushNotificationRegistration, error) {
|
||||
func (p *Client) buildPushNotificationRegistrationMessage(contactIDs []*ecdsa.PublicKey, mutedChatIDs []string) (*protobuf.PushNotificationRegistration, error) {
|
||||
token := uuid.New().String()
|
||||
allowedUserList, err := p.allowedUserList([]byte(token))
|
||||
allowedUserList, err := p.allowedUserList([]byte(token), contactIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -175,13 +178,20 @@ func (p *Client) buildPushNotificationRegistrationMessage() (*protobuf.PushNotif
|
|||
InstallationId: p.config.InstallationID,
|
||||
Token: p.DeviceToken,
|
||||
Enabled: p.config.RemoteNotificationsEnabled,
|
||||
BlockedChatList: p.mutedChatIDsHashes(),
|
||||
BlockedChatList: p.mutedChatIDsHashes(mutedChatIDs),
|
||||
AllowedUserList: allowedUserList,
|
||||
}
|
||||
return options, nil
|
||||
}
|
||||
|
||||
func (p *Client) Register(deviceToken string) error {
|
||||
func (p *Client) Register(deviceToken string, contactIDs []*ecdsa.PublicKey, mutedChatIDs []string) error {
|
||||
servers, err := p.persistence.GetServers()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(servers) == 0 {
|
||||
return errors.New("no servers to register with")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -205,16 +215,40 @@ func (p *Client) HandlePushNotificationResponse(ack *protobuf.PushNotificationRe
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *Client) SetContactIDs(contactIDs []*ecdsa.PublicKey) error {
|
||||
p.config.ContactIDs = contactIDs
|
||||
// Update or schedule update
|
||||
return nil
|
||||
func (c *Client) AddPushNotificationServer(publicKey *ecdsa.PublicKey) error {
|
||||
currentServers, err := c.persistence.GetServers()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, server := range currentServers {
|
||||
if common.IsPubKeyEqual(server.publicKey, publicKey) {
|
||||
return errors.New("push notification server already added")
|
||||
}
|
||||
}
|
||||
|
||||
return c.persistence.UpsertServer(&PushNotificationServer{
|
||||
publicKey: publicKey,
|
||||
})
|
||||
}
|
||||
|
||||
func (p *Client) SetMutedChatIDs(chatIDs []string) error {
|
||||
p.config.MutedChatIDs = chatIDs
|
||||
// Update or schedule update
|
||||
return nil
|
||||
func (c *Client) RetrievePushNotificationInfo(publicKey *ecdsa.PublicKey) ([]*PushNotificationInfo, error) {
|
||||
return nil, nil
|
||||
/*
|
||||
currentServers, err := c.persistence.GetServers()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, server := range currentServers {
|
||||
if common.IsPubKeyEqual(server.publicKey, publicKey) {
|
||||
return errors.New("push notification server already added")
|
||||
}
|
||||
}
|
||||
|
||||
return c.persistence.UpsertServer(&PushNotificationServer{
|
||||
publicKey: publicKey,
|
||||
})*/
|
||||
}
|
||||
|
||||
func encryptAccessToken(plaintext []byte, key []byte, reader io.Reader) ([]byte, error) {
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
package push_notification_client
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"database/sql"
|
||||
)
|
||||
|
||||
type Persistence struct {
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
func NewPersistence(db *sql.DB) *Persistence {
|
||||
return &Persistence{db: db}
|
||||
}
|
||||
|
||||
func (p *Persistence) TrackPushNotification(messageID []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Persistence) ShouldSentNotificationFor(publicKey *ecdsa.PublicKey, messageID []byte) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
func (p *Persistence) SentFor(publicKey *ecdsa.PublicKey, messageID []byte) error {
|
||||
|
||||
return nil
|
||||
}
|
|
@ -56,8 +56,6 @@ func TestBuildPushNotificationRegisterMessage(t *testing.T) {
|
|||
config := &Config{
|
||||
Identity: identity,
|
||||
RemoteNotificationsEnabled: true,
|
||||
MutedChatIDs: mutedChatList,
|
||||
ContactIDs: contactIDs,
|
||||
InstallationID: myInstallationID,
|
||||
}
|
||||
|
||||
|
@ -77,7 +75,7 @@ func TestBuildPushNotificationRegisterMessage(t *testing.T) {
|
|||
AllowedUserList: [][]byte{encryptedToken},
|
||||
}
|
||||
|
||||
actualMessage, err := client.buildPushNotificationRegistrationMessage()
|
||||
actualMessage, err := client.buildPushNotificationRegistrationMessage(contactIDs, mutedChatList)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, options, actualMessage)
|
||||
|
|
|
@ -7,7 +7,6 @@ var ErrEmptyPushNotificationRegistrationPayload = errors.New("empty payload")
|
|||
var ErrMalformedPushNotificationRegistrationInstallationID = errors.New("invalid installationID")
|
||||
var ErrEmptyPushNotificationRegistrationPublicKey = errors.New("no public key")
|
||||
var ErrCouldNotUnmarshalPushNotificationRegistration = errors.New("could not unmarshal preferences")
|
||||
var ErrInvalidCiphertextLength = errors.New("invalid cyphertext length")
|
||||
var ErrMalformedPushNotificationRegistrationDeviceToken = errors.New("invalid device token")
|
||||
var ErrMalformedPushNotificationRegistrationAccessToken = errors.New("invalid access token")
|
||||
var ErrUnknownPushNotificationRegistrationTokenType = errors.New("invalid token type")
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package push_notification_server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
"errors"
|
||||
|
||||
|
@ -14,7 +15,6 @@ import (
|
|||
)
|
||||
|
||||
const encryptedPayloadKeyLength = 16
|
||||
const nonceLength = 12
|
||||
|
||||
type Config struct {
|
||||
// Identity is our identity key
|
||||
|
@ -57,7 +57,7 @@ func (p *Server) decryptRegistration(publicKey *ecdsa.PublicKey, payload []byte)
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return decrypt(payload, sharedKey)
|
||||
return common.Decrypt(payload, sharedKey)
|
||||
}
|
||||
|
||||
// ValidateRegistration validates a new message against the last one received for a given installationID and and public key
|
||||
|
@ -90,7 +90,7 @@ func (p *Server) ValidateRegistration(publicKey *ecdsa.PublicKey, payload []byte
|
|||
return nil, ErrMalformedPushNotificationRegistrationInstallationID
|
||||
}
|
||||
|
||||
previousRegistration, err := p.persistence.GetPushNotificationRegistrationByPublicKeyAndInstallationID(hashPublicKey(publicKey), registration.InstallationId)
|
||||
previousRegistration, err := p.persistence.GetPushNotificationRegistrationByPublicKeyAndInstallationID(common.HashPublicKey(publicKey), registration.InstallationId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -205,7 +205,7 @@ func (p *Server) HandlePushNotificationRequest(request *protobuf.PushNotificatio
|
|||
|
||||
func (p *Server) HandlePushNotificationRegistration(publicKey *ecdsa.PublicKey, payload []byte) *protobuf.PushNotificationRegistrationResponse {
|
||||
response := &protobuf.PushNotificationRegistrationResponse{
|
||||
RequestId: shake256(payload),
|
||||
RequestId: common.Shake256(payload),
|
||||
}
|
||||
|
||||
registration, err := p.ValidateRegistration(publicKey, payload)
|
||||
|
@ -227,12 +227,12 @@ func (p *Server) HandlePushNotificationRegistration(publicKey *ecdsa.PublicKey,
|
|||
Version: registration.Version,
|
||||
InstallationId: registration.InstallationId,
|
||||
}
|
||||
if err := p.persistence.SavePushNotificationRegistration(hashPublicKey(publicKey), emptyRegistration); err != nil {
|
||||
if err := p.persistence.SavePushNotificationRegistration(common.HashPublicKey(publicKey), emptyRegistration); err != nil {
|
||||
response.Error = protobuf.PushNotificationRegistrationResponse_INTERNAL_ERROR
|
||||
return response
|
||||
}
|
||||
|
||||
} else if err := p.persistence.SavePushNotificationRegistration(hashPublicKey(publicKey), registration); err != nil {
|
||||
} else if err := p.persistence.SavePushNotificationRegistration(common.HashPublicKey(publicKey), registration); err != nil {
|
||||
response.Error = protobuf.PushNotificationRegistrationResponse_INTERNAL_ERROR
|
||||
return response
|
||||
}
|
||||
|
@ -243,17 +243,60 @@ func (p *Server) HandlePushNotificationRegistration(publicKey *ecdsa.PublicKey,
|
|||
}
|
||||
|
||||
func (p *Server) HandlePushNotificationRegistration2(publicKey *ecdsa.PublicKey, payload []byte) error {
|
||||
return nil
|
||||
response := p.HandlePushNotificationRegistration(publicKey, payload)
|
||||
if response == nil {
|
||||
return nil
|
||||
}
|
||||
encodedMessage, err := proto.Marshal(response)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rawMessage := &common.RawMessage{
|
||||
Payload: encodedMessage,
|
||||
MessageType: protobuf.ApplicationMetadataMessage_PUSH_NOTIFICATION_REGISTRATION_RESPONSE,
|
||||
}
|
||||
|
||||
_, err = p.messageProcessor.SendPrivate(context.Background(), publicKey, rawMessage)
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *Server) HandlePushNotificationQuery2(publicKey *ecdsa.PublicKey, query protobuf.PushNotificationQuery) error {
|
||||
return nil
|
||||
response := p.HandlePushNotificationQuery(&query)
|
||||
if response == nil {
|
||||
return nil
|
||||
}
|
||||
encodedMessage, err := proto.Marshal(response)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rawMessage := &common.RawMessage{
|
||||
Payload: encodedMessage,
|
||||
MessageType: protobuf.ApplicationMetadataMessage_PUSH_NOTIFICATION_QUERY_RESPONSE,
|
||||
}
|
||||
|
||||
_, err = p.messageProcessor.SendPrivate(context.Background(), publicKey, rawMessage)
|
||||
return err
|
||||
|
||||
}
|
||||
|
||||
func (p *Server) HandlePushNotificationRequest2(publicKey *ecdsa.PublicKey,
|
||||
request protobuf.PushNotificationRequest) error {
|
||||
return nil
|
||||
response := p.HandlePushNotificationRequest(&request)
|
||||
if response == nil {
|
||||
return nil
|
||||
}
|
||||
encodedMessage, err := proto.Marshal(response)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rawMessage := &common.RawMessage{
|
||||
Payload: encodedMessage,
|
||||
MessageType: protobuf.ApplicationMetadataMessage_PUSH_NOTIFICATION_RESPONSE,
|
||||
}
|
||||
|
||||
_, err = p.messageProcessor.SendPrivate(context.Background(), publicKey, rawMessage)
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"github.com/status-im/status-go/eth-node/crypto"
|
||||
"github.com/status-im/status-go/protocol/common"
|
||||
"github.com/status-im/status-go/protocol/protobuf"
|
||||
"github.com/status-im/status-go/protocol/sqlite"
|
||||
)
|
||||
|
@ -49,9 +50,9 @@ func (s *SQLitePersistenceSuite) TestSaveAndRetrieve() {
|
|||
Version: 5,
|
||||
}
|
||||
|
||||
s.Require().NoError(s.persistence.SavePushNotificationRegistration(hashPublicKey(&key.PublicKey), registration))
|
||||
s.Require().NoError(s.persistence.SavePushNotificationRegistration(common.HashPublicKey(&key.PublicKey), registration))
|
||||
|
||||
retrievedRegistration, err := s.persistence.GetPushNotificationRegistrationByPublicKeyAndInstallationID(hashPublicKey(&key.PublicKey), installationID)
|
||||
retrievedRegistration, err := s.persistence.GetPushNotificationRegistrationByPublicKeyAndInstallationID(common.HashPublicKey(&key.PublicKey), installationID)
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().True(proto.Equal(registration, retrievedRegistration))
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/golang/protobuf/proto"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"github.com/status-im/status-go/protocol/common"
|
||||
"github.com/status-im/status-go/protocol/protobuf"
|
||||
"github.com/status-im/status-go/protocol/sqlite"
|
||||
)
|
||||
|
@ -76,24 +77,24 @@ func (s *ServerSuite) TestPushNotificationServerValidateRegistration() {
|
|||
|
||||
// Invalid cyphertext length
|
||||
_, err = s.server.ValidateRegistration(&s.key.PublicKey, []byte("too short"))
|
||||
s.Require().Equal(ErrInvalidCiphertextLength, err)
|
||||
s.Require().Equal(common.ErrInvalidCiphertextLength, err)
|
||||
|
||||
// Invalid cyphertext length
|
||||
_, err = s.server.ValidateRegistration(&s.key.PublicKey, []byte("too short"))
|
||||
s.Require().Equal(ErrInvalidCiphertextLength, err)
|
||||
s.Require().Equal(common.ErrInvalidCiphertextLength, err)
|
||||
|
||||
// Invalid ciphertext
|
||||
_, err = s.server.ValidateRegistration(&s.key.PublicKey, []byte("not too short but invalid"))
|
||||
s.Require().Error(ErrInvalidCiphertextLength, err)
|
||||
s.Require().Error(common.ErrInvalidCiphertextLength, err)
|
||||
|
||||
// Different key ciphertext
|
||||
cyphertext, err := encrypt([]byte("plaintext"), make([]byte, 32), rand.Reader)
|
||||
cyphertext, err := common.Encrypt([]byte("plaintext"), make([]byte, 32), rand.Reader)
|
||||
s.Require().NoError(err)
|
||||
_, err = s.server.ValidateRegistration(&s.key.PublicKey, cyphertext)
|
||||
s.Require().Error(err)
|
||||
|
||||
// Right cyphertext but non unmarshable payload
|
||||
cyphertext, err = encrypt([]byte("plaintext"), s.sharedKey, rand.Reader)
|
||||
cyphertext, err = common.Encrypt([]byte("plaintext"), s.sharedKey, rand.Reader)
|
||||
s.Require().NoError(err)
|
||||
_, err = s.server.ValidateRegistration(&s.key.PublicKey, cyphertext)
|
||||
s.Require().Equal(ErrCouldNotUnmarshalPushNotificationRegistration, err)
|
||||
|
@ -106,7 +107,7 @@ func (s *ServerSuite) TestPushNotificationServerValidateRegistration() {
|
|||
})
|
||||
s.Require().NoError(err)
|
||||
|
||||
cyphertext, err = encrypt(payload, s.sharedKey, rand.Reader)
|
||||
cyphertext, err = common.Encrypt(payload, s.sharedKey, rand.Reader)
|
||||
s.Require().NoError(err)
|
||||
_, err = s.server.ValidateRegistration(&s.key.PublicKey, cyphertext)
|
||||
s.Require().Equal(ErrMalformedPushNotificationRegistrationInstallationID, err)
|
||||
|
@ -118,7 +119,7 @@ func (s *ServerSuite) TestPushNotificationServerValidateRegistration() {
|
|||
InstallationId: "abc",
|
||||
Version: 1,
|
||||
})
|
||||
cyphertext, err = encrypt(payload, s.sharedKey, rand.Reader)
|
||||
cyphertext, err = common.Encrypt(payload, s.sharedKey, rand.Reader)
|
||||
s.Require().NoError(err)
|
||||
_, err = s.server.ValidateRegistration(&s.key.PublicKey, cyphertext)
|
||||
s.Require().Equal(ErrMalformedPushNotificationRegistrationInstallationID, err)
|
||||
|
@ -131,7 +132,7 @@ func (s *ServerSuite) TestPushNotificationServerValidateRegistration() {
|
|||
})
|
||||
s.Require().NoError(err)
|
||||
|
||||
cyphertext, err = encrypt(payload, s.sharedKey, rand.Reader)
|
||||
cyphertext, err = common.Encrypt(payload, s.sharedKey, rand.Reader)
|
||||
s.Require().NoError(err)
|
||||
_, err = s.server.ValidateRegistration(&s.key.PublicKey, cyphertext)
|
||||
s.Require().Equal(ErrInvalidPushNotificationRegistrationVersion, err)
|
||||
|
@ -145,11 +146,11 @@ func (s *ServerSuite) TestPushNotificationServerValidateRegistration() {
|
|||
})
|
||||
s.Require().NoError(err)
|
||||
|
||||
cyphertext, err = encrypt(payload, s.sharedKey, rand.Reader)
|
||||
cyphertext, err = common.Encrypt(payload, s.sharedKey, rand.Reader)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Setup persistence
|
||||
s.Require().NoError(s.persistence.SavePushNotificationRegistration(hashPublicKey(&s.key.PublicKey), &protobuf.PushNotificationRegistration{
|
||||
s.Require().NoError(s.persistence.SavePushNotificationRegistration(common.HashPublicKey(&s.key.PublicKey), &protobuf.PushNotificationRegistration{
|
||||
AccessToken: s.accessToken,
|
||||
TokenType: protobuf.PushNotificationRegistration_APN_TOKEN,
|
||||
InstallationId: s.installationID,
|
||||
|
@ -159,7 +160,7 @@ func (s *ServerSuite) TestPushNotificationServerValidateRegistration() {
|
|||
s.Require().Equal(ErrInvalidPushNotificationRegistrationVersion, err)
|
||||
|
||||
// Cleanup persistence
|
||||
s.Require().NoError(s.persistence.DeletePushNotificationRegistration(hashPublicKey(&s.key.PublicKey), s.installationID))
|
||||
s.Require().NoError(s.persistence.DeletePushNotificationRegistration(common.HashPublicKey(&s.key.PublicKey), s.installationID))
|
||||
|
||||
// Unregistering message
|
||||
payload, err = proto.Marshal(&protobuf.PushNotificationRegistration{
|
||||
|
@ -170,7 +171,7 @@ func (s *ServerSuite) TestPushNotificationServerValidateRegistration() {
|
|||
})
|
||||
s.Require().NoError(err)
|
||||
|
||||
cyphertext, err = encrypt(payload, s.sharedKey, rand.Reader)
|
||||
cyphertext, err = common.Encrypt(payload, s.sharedKey, rand.Reader)
|
||||
s.Require().NoError(err)
|
||||
_, err = s.server.ValidateRegistration(&s.key.PublicKey, cyphertext)
|
||||
s.Require().Nil(err)
|
||||
|
@ -183,7 +184,7 @@ func (s *ServerSuite) TestPushNotificationServerValidateRegistration() {
|
|||
})
|
||||
s.Require().NoError(err)
|
||||
|
||||
cyphertext, err = encrypt(payload, s.sharedKey, rand.Reader)
|
||||
cyphertext, err = common.Encrypt(payload, s.sharedKey, rand.Reader)
|
||||
s.Require().NoError(err)
|
||||
_, err = s.server.ValidateRegistration(&s.key.PublicKey, cyphertext)
|
||||
s.Require().Equal(ErrMalformedPushNotificationRegistrationAccessToken, err)
|
||||
|
@ -197,7 +198,7 @@ func (s *ServerSuite) TestPushNotificationServerValidateRegistration() {
|
|||
})
|
||||
s.Require().NoError(err)
|
||||
|
||||
cyphertext, err = encrypt(payload, s.sharedKey, rand.Reader)
|
||||
cyphertext, err = common.Encrypt(payload, s.sharedKey, rand.Reader)
|
||||
s.Require().NoError(err)
|
||||
_, err = s.server.ValidateRegistration(&s.key.PublicKey, cyphertext)
|
||||
s.Require().Equal(ErrMalformedPushNotificationRegistrationAccessToken, err)
|
||||
|
@ -211,7 +212,7 @@ func (s *ServerSuite) TestPushNotificationServerValidateRegistration() {
|
|||
})
|
||||
s.Require().NoError(err)
|
||||
|
||||
cyphertext, err = encrypt(payload, s.sharedKey, rand.Reader)
|
||||
cyphertext, err = common.Encrypt(payload, s.sharedKey, rand.Reader)
|
||||
s.Require().NoError(err)
|
||||
_, err = s.server.ValidateRegistration(&s.key.PublicKey, cyphertext)
|
||||
s.Require().Equal(ErrMalformedPushNotificationRegistrationDeviceToken, err)
|
||||
|
@ -225,7 +226,7 @@ func (s *ServerSuite) TestPushNotificationServerValidateRegistration() {
|
|||
})
|
||||
s.Require().NoError(err)
|
||||
|
||||
cyphertext, err = encrypt(payload, s.sharedKey, rand.Reader)
|
||||
cyphertext, err = common.Encrypt(payload, s.sharedKey, rand.Reader)
|
||||
s.Require().NoError(err)
|
||||
_, err = s.server.ValidateRegistration(&s.key.PublicKey, cyphertext)
|
||||
s.Require().Equal(ErrUnknownPushNotificationRegistrationTokenType, err)
|
||||
|
@ -240,7 +241,7 @@ func (s *ServerSuite) TestPushNotificationServerValidateRegistration() {
|
|||
})
|
||||
s.Require().NoError(err)
|
||||
|
||||
cyphertext, err = encrypt(payload, s.sharedKey, rand.Reader)
|
||||
cyphertext, err = common.Encrypt(payload, s.sharedKey, rand.Reader)
|
||||
s.Require().NoError(err)
|
||||
_, err = s.server.ValidateRegistration(&s.key.PublicKey, cyphertext)
|
||||
s.Require().NoError(err)
|
||||
|
@ -278,7 +279,7 @@ func (s *ServerSuite) TestPushNotificationHandleRegistration() {
|
|||
s.Require().Equal(response.Error, protobuf.PushNotificationRegistrationResponse_MALFORMED_MESSAGE)
|
||||
|
||||
// Different key ciphertext
|
||||
cyphertext, err := encrypt([]byte("plaintext"), make([]byte, 32), rand.Reader)
|
||||
cyphertext, err := common.Encrypt([]byte("plaintext"), make([]byte, 32), rand.Reader)
|
||||
s.Require().NoError(err)
|
||||
response = s.server.HandlePushNotificationRegistration(&s.key.PublicKey, cyphertext)
|
||||
s.Require().NotNil(response)
|
||||
|
@ -286,7 +287,7 @@ func (s *ServerSuite) TestPushNotificationHandleRegistration() {
|
|||
s.Require().Equal(response.Error, protobuf.PushNotificationRegistrationResponse_MALFORMED_MESSAGE)
|
||||
|
||||
// Right cyphertext but non unmarshable payload
|
||||
cyphertext, err = encrypt([]byte("plaintext"), s.sharedKey, rand.Reader)
|
||||
cyphertext, err = common.Encrypt([]byte("plaintext"), s.sharedKey, rand.Reader)
|
||||
s.Require().NoError(err)
|
||||
response = s.server.HandlePushNotificationRegistration(&s.key.PublicKey, cyphertext)
|
||||
s.Require().NotNil(response)
|
||||
|
@ -300,7 +301,7 @@ func (s *ServerSuite) TestPushNotificationHandleRegistration() {
|
|||
})
|
||||
s.Require().NoError(err)
|
||||
|
||||
cyphertext, err = encrypt(payload, s.sharedKey, rand.Reader)
|
||||
cyphertext, err = common.Encrypt(payload, s.sharedKey, rand.Reader)
|
||||
s.Require().NoError(err)
|
||||
response = s.server.HandlePushNotificationRegistration(&s.key.PublicKey, cyphertext)
|
||||
s.Require().NotNil(response)
|
||||
|
@ -313,7 +314,7 @@ func (s *ServerSuite) TestPushNotificationHandleRegistration() {
|
|||
InstallationId: "abc",
|
||||
Version: 1,
|
||||
})
|
||||
cyphertext, err = encrypt(payload, s.sharedKey, rand.Reader)
|
||||
cyphertext, err = common.Encrypt(payload, s.sharedKey, rand.Reader)
|
||||
s.Require().NoError(err)
|
||||
response = s.server.HandlePushNotificationRegistration(&s.key.PublicKey, cyphertext)
|
||||
s.Require().NotNil(response)
|
||||
|
@ -327,7 +328,7 @@ func (s *ServerSuite) TestPushNotificationHandleRegistration() {
|
|||
})
|
||||
s.Require().NoError(err)
|
||||
|
||||
cyphertext, err = encrypt(payload, s.sharedKey, rand.Reader)
|
||||
cyphertext, err = common.Encrypt(payload, s.sharedKey, rand.Reader)
|
||||
s.Require().NoError(err)
|
||||
response = s.server.HandlePushNotificationRegistration(&s.key.PublicKey, cyphertext)
|
||||
s.Require().NotNil(response)
|
||||
|
@ -342,11 +343,11 @@ func (s *ServerSuite) TestPushNotificationHandleRegistration() {
|
|||
})
|
||||
s.Require().NoError(err)
|
||||
|
||||
cyphertext, err = encrypt(payload, s.sharedKey, rand.Reader)
|
||||
cyphertext, err = common.Encrypt(payload, s.sharedKey, rand.Reader)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Setup persistence
|
||||
s.Require().NoError(s.persistence.SavePushNotificationRegistration(hashPublicKey(&s.key.PublicKey), &protobuf.PushNotificationRegistration{
|
||||
s.Require().NoError(s.persistence.SavePushNotificationRegistration(common.HashPublicKey(&s.key.PublicKey), &protobuf.PushNotificationRegistration{
|
||||
AccessToken: s.accessToken,
|
||||
InstallationId: s.installationID,
|
||||
Version: 2}))
|
||||
|
@ -357,7 +358,7 @@ func (s *ServerSuite) TestPushNotificationHandleRegistration() {
|
|||
s.Require().Equal(response.Error, protobuf.PushNotificationRegistrationResponse_VERSION_MISMATCH)
|
||||
|
||||
// Cleanup persistence
|
||||
s.Require().NoError(s.persistence.DeletePushNotificationRegistration(hashPublicKey(&s.key.PublicKey), s.installationID))
|
||||
s.Require().NoError(s.persistence.DeletePushNotificationRegistration(common.HashPublicKey(&s.key.PublicKey), s.installationID))
|
||||
|
||||
// Missing access token
|
||||
payload, err = proto.Marshal(&protobuf.PushNotificationRegistration{
|
||||
|
@ -366,7 +367,7 @@ func (s *ServerSuite) TestPushNotificationHandleRegistration() {
|
|||
})
|
||||
s.Require().NoError(err)
|
||||
|
||||
cyphertext, err = encrypt(payload, s.sharedKey, rand.Reader)
|
||||
cyphertext, err = common.Encrypt(payload, s.sharedKey, rand.Reader)
|
||||
s.Require().NoError(err)
|
||||
response = s.server.HandlePushNotificationRegistration(&s.key.PublicKey, cyphertext)
|
||||
s.Require().NotNil(response)
|
||||
|
@ -381,7 +382,7 @@ func (s *ServerSuite) TestPushNotificationHandleRegistration() {
|
|||
})
|
||||
s.Require().NoError(err)
|
||||
|
||||
cyphertext, err = encrypt(payload, s.sharedKey, rand.Reader)
|
||||
cyphertext, err = common.Encrypt(payload, s.sharedKey, rand.Reader)
|
||||
s.Require().NoError(err)
|
||||
response = s.server.HandlePushNotificationRegistration(&s.key.PublicKey, cyphertext)
|
||||
s.Require().NotNil(response)
|
||||
|
@ -396,7 +397,7 @@ func (s *ServerSuite) TestPushNotificationHandleRegistration() {
|
|||
})
|
||||
s.Require().NoError(err)
|
||||
|
||||
cyphertext, err = encrypt(payload, s.sharedKey, rand.Reader)
|
||||
cyphertext, err = common.Encrypt(payload, s.sharedKey, rand.Reader)
|
||||
s.Require().NoError(err)
|
||||
response = s.server.HandlePushNotificationRegistration(&s.key.PublicKey, cyphertext)
|
||||
s.Require().NotNil(response)
|
||||
|
@ -414,14 +415,14 @@ func (s *ServerSuite) TestPushNotificationHandleRegistration() {
|
|||
payload, err = proto.Marshal(registration)
|
||||
s.Require().NoError(err)
|
||||
|
||||
cyphertext, err = encrypt(payload, s.sharedKey, rand.Reader)
|
||||
cyphertext, err = common.Encrypt(payload, s.sharedKey, rand.Reader)
|
||||
s.Require().NoError(err)
|
||||
response = s.server.HandlePushNotificationRegistration(&s.key.PublicKey, cyphertext)
|
||||
s.Require().NotNil(response)
|
||||
s.Require().True(response.Success)
|
||||
|
||||
// Pull from the db
|
||||
retrievedRegistration, err := s.persistence.GetPushNotificationRegistrationByPublicKeyAndInstallationID(hashPublicKey(&s.key.PublicKey), s.installationID)
|
||||
retrievedRegistration, err := s.persistence.GetPushNotificationRegistrationByPublicKeyAndInstallationID(common.HashPublicKey(&s.key.PublicKey), s.installationID)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(retrievedRegistration)
|
||||
s.Require().True(proto.Equal(retrievedRegistration, registration))
|
||||
|
@ -435,25 +436,25 @@ func (s *ServerSuite) TestPushNotificationHandleRegistration() {
|
|||
})
|
||||
s.Require().NoError(err)
|
||||
|
||||
cyphertext, err = encrypt(payload, s.sharedKey, rand.Reader)
|
||||
cyphertext, err = common.Encrypt(payload, s.sharedKey, rand.Reader)
|
||||
s.Require().NoError(err)
|
||||
response = s.server.HandlePushNotificationRegistration(&s.key.PublicKey, cyphertext)
|
||||
s.Require().NotNil(response)
|
||||
s.Require().True(response.Success)
|
||||
|
||||
// Check is gone from the db
|
||||
retrievedRegistration, err = s.persistence.GetPushNotificationRegistrationByPublicKeyAndInstallationID(hashPublicKey(&s.key.PublicKey), s.installationID)
|
||||
retrievedRegistration, err = s.persistence.GetPushNotificationRegistrationByPublicKeyAndInstallationID(common.HashPublicKey(&s.key.PublicKey), s.installationID)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(retrievedRegistration)
|
||||
s.Require().Empty(retrievedRegistration.AccessToken)
|
||||
s.Require().Empty(retrievedRegistration.Token)
|
||||
s.Require().Equal(uint64(2), retrievedRegistration.Version)
|
||||
s.Require().Equal(s.installationID, retrievedRegistration.InstallationId)
|
||||
s.Require().Equal(shake256(cyphertext), response.RequestId)
|
||||
s.Require().Equal(common.Shake256(cyphertext), response.RequestId)
|
||||
}
|
||||
|
||||
func (s *ServerSuite) TestHandlePushNotificationQueryNoFiltering() {
|
||||
hashedPublicKey := hashPublicKey(&s.key.PublicKey)
|
||||
hashedPublicKey := common.HashPublicKey(&s.key.PublicKey)
|
||||
// Successful
|
||||
registration := &protobuf.PushNotificationRegistration{
|
||||
Token: "abc",
|
||||
|
@ -465,7 +466,7 @@ func (s *ServerSuite) TestHandlePushNotificationQueryNoFiltering() {
|
|||
payload, err := proto.Marshal(registration)
|
||||
s.Require().NoError(err)
|
||||
|
||||
cyphertext, err := encrypt(payload, s.sharedKey, rand.Reader)
|
||||
cyphertext, err := common.Encrypt(payload, s.sharedKey, rand.Reader)
|
||||
s.Require().NoError(err)
|
||||
response := s.server.HandlePushNotificationRegistration(&s.key.PublicKey, cyphertext)
|
||||
s.Require().NotNil(response)
|
||||
|
@ -486,7 +487,7 @@ func (s *ServerSuite) TestHandlePushNotificationQueryNoFiltering() {
|
|||
}
|
||||
|
||||
func (s *ServerSuite) TestHandlePushNotificationQueryWithFiltering() {
|
||||
hashedPublicKey := hashPublicKey(&s.key.PublicKey)
|
||||
hashedPublicKey := common.HashPublicKey(&s.key.PublicKey)
|
||||
allowedUserList := [][]byte{[]byte("a")}
|
||||
// Successful
|
||||
|
||||
|
@ -501,7 +502,7 @@ func (s *ServerSuite) TestHandlePushNotificationQueryWithFiltering() {
|
|||
payload, err := proto.Marshal(registration)
|
||||
s.Require().NoError(err)
|
||||
|
||||
cyphertext, err := encrypt(payload, s.sharedKey, rand.Reader)
|
||||
cyphertext, err := common.Encrypt(payload, s.sharedKey, rand.Reader)
|
||||
s.Require().NoError(err)
|
||||
response := s.server.HandlePushNotificationRegistration(&s.key.PublicKey, cyphertext)
|
||||
s.Require().NotNil(response)
|
||||
|
|
|
@ -0,0 +1,145 @@
|
|||
package protocol
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"go.uber.org/zap"
|
||||
|
||||
gethbridge "github.com/status-im/status-go/eth-node/bridge/geth"
|
||||
"github.com/status-im/status-go/eth-node/crypto"
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
"github.com/status-im/status-go/protocol/tt"
|
||||
"github.com/status-im/status-go/whisper/v6"
|
||||
)
|
||||
|
||||
func TestMessengerPushNotificationSuite(t *testing.T) {
|
||||
suite.Run(t, new(MessengerPushNotificationSuite))
|
||||
}
|
||||
|
||||
type MessengerPushNotificationSuite struct {
|
||||
suite.Suite
|
||||
m *Messenger // main instance of Messenger
|
||||
privateKey *ecdsa.PrivateKey // private key for the main instance of Messenger
|
||||
// If one wants to send messages between different instances of Messenger,
|
||||
// a single Whisper service should be shared.
|
||||
shh types.Whisper
|
||||
tmpFiles []*os.File // files to clean up
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
func (s *MessengerPushNotificationSuite) SetupTest() {
|
||||
s.logger = tt.MustCreateTestLogger()
|
||||
|
||||
config := whisper.DefaultConfig
|
||||
config.MinimumAcceptedPOW = 0
|
||||
shh := whisper.New(&config)
|
||||
s.shh = gethbridge.NewGethWhisperWrapper(shh)
|
||||
s.Require().NoError(shh.Start(nil))
|
||||
|
||||
s.m = s.newMessenger(s.shh)
|
||||
s.privateKey = s.m.identity
|
||||
}
|
||||
|
||||
func (s *MessengerPushNotificationSuite) newMessengerWithKey(shh types.Whisper, privateKey *ecdsa.PrivateKey) *Messenger {
|
||||
tmpFile, err := ioutil.TempFile("", "")
|
||||
s.Require().NoError(err)
|
||||
|
||||
options := []Option{
|
||||
WithCustomLogger(s.logger),
|
||||
WithMessagesPersistenceEnabled(),
|
||||
WithDatabaseConfig(tmpFile.Name(), "some-key"),
|
||||
WithDatasync(),
|
||||
}
|
||||
m, err := NewMessenger(
|
||||
privateKey,
|
||||
&testNode{shh: shh},
|
||||
uuid.New().String(),
|
||||
options...,
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
err = m.Init()
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.tmpFiles = append(s.tmpFiles, tmpFile)
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
func (s *MessengerPushNotificationSuite) newMessenger(shh types.Whisper) *Messenger {
|
||||
privateKey, err := crypto.GenerateKey()
|
||||
s.Require().NoError(err)
|
||||
|
||||
return s.newMessengerWithKey(s.shh, privateKey)
|
||||
}
|
||||
|
||||
func (s *MessengerPushNotificationSuite) TestReceivePushNotification() {
|
||||
deviceToken := "token"
|
||||
|
||||
server := s.newMessenger(s.shh)
|
||||
client2 := s.newMessenger(s.shh)
|
||||
|
||||
err := s.m.AddPushNotificationServer(context.Background(), &server.identity.PublicKey)
|
||||
s.Require().NoError(err)
|
||||
|
||||
err = s.m.RegisterForPushNotifications(context.Background(), deviceToken)
|
||||
s.Require().NoError(err)
|
||||
|
||||
info, err := client2.pushNotificationClient.RetrievePushNotificationInfo(&s.m.identity.PublicKey)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(info)
|
||||
|
||||
/*
|
||||
s.Require().Len(response.Contacts, 1)
|
||||
contact := response.Contacts[0]
|
||||
s.Require().True(contact.IsAdded())
|
||||
|
||||
s.Require().Len(response.Chats, 1)
|
||||
chat := response.Chats[0]
|
||||
s.Require().False(chat.Active, "It does not create an active chat")
|
||||
|
||||
// Wait for the message to reach its destination
|
||||
response, err = WaitOnMessengerResponse(
|
||||
s.m,
|
||||
func(r *MessengerResponse) bool { return len(r.Contacts) > 0 },
|
||||
"contact request not received",
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
receivedContact := response.Contacts[0]
|
||||
s.Require().Equal(theirName, receivedContact.Name)
|
||||
s.Require().Equal(theirPicture, receivedContact.Photo)
|
||||
s.Require().False(receivedContact.ENSVerified)
|
||||
s.Require().True(receivedContact.HasBeenAdded())
|
||||
s.Require().NotEmpty(receivedContact.LastUpdated)
|
||||
|
||||
newPicture := "new-picture"
|
||||
err = theirMessenger.SendPushNotifications(context.Background(), newName, newPicture)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Wait for the message to reach its destination
|
||||
response, err = WaitOnMessengerResponse(
|
||||
s.m,
|
||||
func(r *MessengerResponse) bool {
|
||||
return len(r.Contacts) > 0 && response.Contacts[0].ID == theirContactID
|
||||
},
|
||||
"contact request not received",
|
||||
)
|
||||
|
||||
s.Require().NoError(err)
|
||||
|
||||
receivedContact = response.Contacts[0]
|
||||
s.Require().Equal(theirContactID, receivedContact.ID)
|
||||
s.Require().Equal(newName, receivedContact.Name)
|
||||
s.Require().Equal(newPicture, receivedContact.Photo)
|
||||
s.Require().False(receivedContact.ENSVerified)
|
||||
s.Require().True(receivedContact.HasBeenAdded())
|
||||
s.Require().NotEmpty(receivedContact.LastUpdated)
|
||||
*/
|
||||
}
|
|
@ -7,6 +7,7 @@ import (
|
|||
|
||||
encryptmigrations "github.com/status-im/status-go/protocol/encryption/migrations"
|
||||
appmigrations "github.com/status-im/status-go/protocol/migrations"
|
||||
push_notification_client_migrations "github.com/status-im/status-go/protocol/push_notification_client/migrations"
|
||||
push_notification_server_migrations "github.com/status-im/status-go/protocol/push_notification_server/migrations"
|
||||
wakumigrations "github.com/status-im/status-go/protocol/transport/waku/migrations"
|
||||
whispermigrations "github.com/status-im/status-go/protocol/transport/whisper/migrations"
|
||||
|
@ -40,6 +41,10 @@ var defaultMigrations = []migrationsWithGetter{
|
|||
Names: push_notification_server_migrations.AssetNames(),
|
||||
Getter: push_notification_server_migrations.Asset,
|
||||
},
|
||||
{
|
||||
Names: push_notification_client_migrations.AssetNames(),
|
||||
Getter: push_notification_client_migrations.Asset,
|
||||
},
|
||||
}
|
||||
|
||||
func prepareMigrations(migrations []migrationsWithGetter) ([]string, getter, error) {
|
||||
|
|
|
@ -339,6 +339,9 @@ func (s *Service) DisableInstallation(installationID string) error {
|
|||
|
||||
// UpdateMailservers updates information about selected mail servers.
|
||||
func (s *Service) UpdateMailservers(nodes []*enode.Node) error {
|
||||
if len(nodes) > 0 && s.messenger != nil {
|
||||
s.messenger.SetMailserver(nodes[0].ID().Bytes())
|
||||
}
|
||||
if err := s.peerStore.Update(nodes); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue