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 (
|
import (
|
||||||
"crypto/aes"
|
"crypto/aes"
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
|
"errors"
|
||||||
"github.com/status-im/status-go/eth-node/crypto"
|
"github.com/status-im/status-go/eth-node/crypto"
|
||||||
"golang.org/x/crypto/sha3"
|
"golang.org/x/crypto/sha3"
|
||||||
"io"
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
func hashPublicKey(pk *ecdsa.PublicKey) []byte {
|
const nonceLength = 12
|
||||||
return shake256(crypto.CompressPubkey(pk))
|
|
||||||
|
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 {
|
if len(cyphertext) < nonceLength {
|
||||||
return nil, ErrInvalidCiphertextLength
|
return nil, ErrInvalidCiphertextLength
|
||||||
}
|
}
|
||||||
|
@ -32,7 +37,7 @@ func decrypt(cyphertext []byte, key []byte) ([]byte, error) {
|
||||||
return gcm.Open(nil, nonce, cyphertext[nonceLength:], nil)
|
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)
|
c, err := aes.NewCipher(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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
|
return gcm.Seal(nonce, nonce, plaintext, nil), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func shake256(buf []byte) []byte {
|
func Shake256(buf []byte) []byte {
|
||||||
h := make([]byte, 64)
|
h := make([]byte, 64)
|
||||||
sha3.ShakeSum256(h, buf)
|
sha3.ShakeSum256(h, buf)
|
||||||
return h
|
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
|
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
|
allInstallations map[string]*multidevice.Installation
|
||||||
modifiedInstallations map[string]bool
|
modifiedInstallations map[string]bool
|
||||||
installationID string
|
installationID string
|
||||||
|
mailserver []byte
|
||||||
|
|
||||||
mutex sync.Mutex
|
mutex sync.Mutex
|
||||||
}
|
}
|
||||||
|
@ -2036,13 +2037,19 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte
|
||||||
return messageState.Response, nil
|
return messageState.Response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Messenger) SetMailserver(peer []byte) {
|
||||||
|
m.mailserver = peer
|
||||||
|
}
|
||||||
|
|
||||||
func (m *Messenger) RequestHistoricMessages(
|
func (m *Messenger) RequestHistoricMessages(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
peer []byte, // should be removed after mailserver logic is ported
|
|
||||||
from, to uint32,
|
from, to uint32,
|
||||||
cursor []byte,
|
cursor []byte,
|
||||||
) ([]byte, error) {
|
) ([]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) {
|
func (m *Messenger) LoadFilters(filters []*transport.Filter) ([]*transport.Filter, error) {
|
||||||
|
@ -2965,6 +2972,46 @@ func (m *Messenger) Timesource() TimeSource {
|
||||||
return m.getTimesource()
|
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) {
|
func generateAliasAndIdenticon(pk string) (string, string, error) {
|
||||||
identicon, err := identicon.GenerateBase64(pk)
|
identicon, err := identicon.GenerateBase64(pk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -2106,7 +2106,8 @@ func (s *MessengerSuite) TestRequestHistoricMessagesRequest() {
|
||||||
m := s.newMessenger(shh)
|
m := s.newMessenger(shh)
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond)
|
||||||
defer cancel()
|
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.EqualError(err, ctx.Err().Error())
|
||||||
s.Empty(cursor)
|
s.Empty(cursor)
|
||||||
// verify request is correct
|
// 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
|
const accessTokenKeyLength = 16
|
||||||
|
|
||||||
type PushNotificationServer struct {
|
type PushNotificationServer struct {
|
||||||
key *ecdsa.PublicKey
|
publicKey *ecdsa.PublicKey
|
||||||
registered bool
|
registered bool
|
||||||
|
registeredAt int64
|
||||||
|
}
|
||||||
|
|
||||||
|
type PushNotificationInfo struct {
|
||||||
|
AccessToken string
|
||||||
|
InstallationID string
|
||||||
|
PublicKey *ecdsa.PublicKey
|
||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
|
@ -35,10 +42,6 @@ type Config struct {
|
||||||
// AllowOnlyFromContacts indicates whether we should be receiving push notifications
|
// AllowOnlyFromContacts indicates whether we should be receiving push notifications
|
||||||
// only from contacts
|
// only from contacts
|
||||||
AllowOnlyFromContacts bool
|
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 is an array of push notification servers we want to register with
|
||||||
PushNotificationServers []*PushNotificationServer
|
PushNotificationServers []*PushNotificationServer
|
||||||
// InstallationID is the installation-id for this device
|
// InstallationID is the installation-id for this device
|
||||||
|
@ -122,10 +125,10 @@ func (p *Client) NotifyOnMessageID(messageID []byte) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Client) mutedChatIDsHashes() [][]byte {
|
func (p *Client) mutedChatIDsHashes(chatIDs []string) [][]byte {
|
||||||
var mutedChatListHashes [][]byte
|
var mutedChatListHashes [][]byte
|
||||||
|
|
||||||
for _, chatID := range p.config.MutedChatIDs {
|
for _, chatID := range chatIDs {
|
||||||
mutedChatListHashes = append(mutedChatListHashes, shake256(chatID))
|
mutedChatListHashes = append(mutedChatListHashes, shake256(chatID))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,9 +151,9 @@ func (p *Client) encryptToken(publicKey *ecdsa.PublicKey, token []byte) ([]byte,
|
||||||
return encryptedToken, nil
|
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
|
var encryptedTokens [][]byte
|
||||||
for _, publicKey := range p.config.ContactIDs {
|
for _, publicKey := range contactIDs {
|
||||||
encryptedToken, err := p.encryptToken(publicKey, token)
|
encryptedToken, err := p.encryptToken(publicKey, token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -162,9 +165,9 @@ func (p *Client) allowedUserList(token []byte) ([][]byte, error) {
|
||||||
return encryptedTokens, nil
|
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()
|
token := uuid.New().String()
|
||||||
allowedUserList, err := p.allowedUserList([]byte(token))
|
allowedUserList, err := p.allowedUserList([]byte(token), contactIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -175,13 +178,20 @@ func (p *Client) buildPushNotificationRegistrationMessage() (*protobuf.PushNotif
|
||||||
InstallationId: p.config.InstallationID,
|
InstallationId: p.config.InstallationID,
|
||||||
Token: p.DeviceToken,
|
Token: p.DeviceToken,
|
||||||
Enabled: p.config.RemoteNotificationsEnabled,
|
Enabled: p.config.RemoteNotificationsEnabled,
|
||||||
BlockedChatList: p.mutedChatIDsHashes(),
|
BlockedChatList: p.mutedChatIDsHashes(mutedChatIDs),
|
||||||
AllowedUserList: allowedUserList,
|
AllowedUserList: allowedUserList,
|
||||||
}
|
}
|
||||||
return options, nil
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,16 +215,40 @@ func (p *Client) HandlePushNotificationResponse(ack *protobuf.PushNotificationRe
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Client) SetContactIDs(contactIDs []*ecdsa.PublicKey) error {
|
func (c *Client) AddPushNotificationServer(publicKey *ecdsa.PublicKey) error {
|
||||||
p.config.ContactIDs = contactIDs
|
currentServers, err := c.persistence.GetServers()
|
||||||
// Update or schedule update
|
if err != nil {
|
||||||
return 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 {
|
func (c *Client) RetrievePushNotificationInfo(publicKey *ecdsa.PublicKey) ([]*PushNotificationInfo, error) {
|
||||||
p.config.MutedChatIDs = chatIDs
|
return nil, nil
|
||||||
// Update or schedule update
|
/*
|
||||||
return 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) {
|
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{
|
config := &Config{
|
||||||
Identity: identity,
|
Identity: identity,
|
||||||
RemoteNotificationsEnabled: true,
|
RemoteNotificationsEnabled: true,
|
||||||
MutedChatIDs: mutedChatList,
|
|
||||||
ContactIDs: contactIDs,
|
|
||||||
InstallationID: myInstallationID,
|
InstallationID: myInstallationID,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,7 +75,7 @@ func TestBuildPushNotificationRegisterMessage(t *testing.T) {
|
||||||
AllowedUserList: [][]byte{encryptedToken},
|
AllowedUserList: [][]byte{encryptedToken},
|
||||||
}
|
}
|
||||||
|
|
||||||
actualMessage, err := client.buildPushNotificationRegistrationMessage()
|
actualMessage, err := client.buildPushNotificationRegistrationMessage(contactIDs, mutedChatList)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.Equal(t, options, actualMessage)
|
require.Equal(t, options, actualMessage)
|
||||||
|
|
|
@ -7,7 +7,6 @@ var ErrEmptyPushNotificationRegistrationPayload = errors.New("empty payload")
|
||||||
var ErrMalformedPushNotificationRegistrationInstallationID = errors.New("invalid installationID")
|
var ErrMalformedPushNotificationRegistrationInstallationID = errors.New("invalid installationID")
|
||||||
var ErrEmptyPushNotificationRegistrationPublicKey = errors.New("no public key")
|
var ErrEmptyPushNotificationRegistrationPublicKey = errors.New("no public key")
|
||||||
var ErrCouldNotUnmarshalPushNotificationRegistration = errors.New("could not unmarshal preferences")
|
var ErrCouldNotUnmarshalPushNotificationRegistration = errors.New("could not unmarshal preferences")
|
||||||
var ErrInvalidCiphertextLength = errors.New("invalid cyphertext length")
|
|
||||||
var ErrMalformedPushNotificationRegistrationDeviceToken = errors.New("invalid device token")
|
var ErrMalformedPushNotificationRegistrationDeviceToken = errors.New("invalid device token")
|
||||||
var ErrMalformedPushNotificationRegistrationAccessToken = errors.New("invalid access token")
|
var ErrMalformedPushNotificationRegistrationAccessToken = errors.New("invalid access token")
|
||||||
var ErrUnknownPushNotificationRegistrationTokenType = errors.New("invalid token type")
|
var ErrUnknownPushNotificationRegistrationTokenType = errors.New("invalid token type")
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package push_notification_server
|
package push_notification_server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
|
@ -14,7 +15,6 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const encryptedPayloadKeyLength = 16
|
const encryptedPayloadKeyLength = 16
|
||||||
const nonceLength = 12
|
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
// Identity is our identity key
|
// Identity is our identity key
|
||||||
|
@ -57,7 +57,7 @@ func (p *Server) decryptRegistration(publicKey *ecdsa.PublicKey, payload []byte)
|
||||||
return nil, err
|
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
|
// 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
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
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 {
|
func (p *Server) HandlePushNotificationRegistration(publicKey *ecdsa.PublicKey, payload []byte) *protobuf.PushNotificationRegistrationResponse {
|
||||||
response := &protobuf.PushNotificationRegistrationResponse{
|
response := &protobuf.PushNotificationRegistrationResponse{
|
||||||
RequestId: shake256(payload),
|
RequestId: common.Shake256(payload),
|
||||||
}
|
}
|
||||||
|
|
||||||
registration, err := p.ValidateRegistration(publicKey, payload)
|
registration, err := p.ValidateRegistration(publicKey, payload)
|
||||||
|
@ -227,12 +227,12 @@ func (p *Server) HandlePushNotificationRegistration(publicKey *ecdsa.PublicKey,
|
||||||
Version: registration.Version,
|
Version: registration.Version,
|
||||||
InstallationId: registration.InstallationId,
|
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
|
response.Error = protobuf.PushNotificationRegistrationResponse_INTERNAL_ERROR
|
||||||
return response
|
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
|
response.Error = protobuf.PushNotificationRegistrationResponse_INTERNAL_ERROR
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
@ -243,17 +243,60 @@ func (p *Server) HandlePushNotificationRegistration(publicKey *ecdsa.PublicKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Server) HandlePushNotificationRegistration2(publicKey *ecdsa.PublicKey, payload []byte) error {
|
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 {
|
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,
|
func (p *Server) HandlePushNotificationRequest2(publicKey *ecdsa.PublicKey,
|
||||||
request protobuf.PushNotificationRequest) error {
|
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/stretchr/testify/suite"
|
||||||
|
|
||||||
"github.com/status-im/status-go/eth-node/crypto"
|
"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/protobuf"
|
||||||
"github.com/status-im/status-go/protocol/sqlite"
|
"github.com/status-im/status-go/protocol/sqlite"
|
||||||
)
|
)
|
||||||
|
@ -49,9 +50,9 @@ func (s *SQLitePersistenceSuite) TestSaveAndRetrieve() {
|
||||||
Version: 5,
|
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().NoError(err)
|
||||||
|
|
||||||
s.Require().True(proto.Equal(registration, retrievedRegistration))
|
s.Require().True(proto.Equal(registration, retrievedRegistration))
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
"github.com/stretchr/testify/suite"
|
"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/protobuf"
|
||||||
"github.com/status-im/status-go/protocol/sqlite"
|
"github.com/status-im/status-go/protocol/sqlite"
|
||||||
)
|
)
|
||||||
|
@ -76,24 +77,24 @@ func (s *ServerSuite) TestPushNotificationServerValidateRegistration() {
|
||||||
|
|
||||||
// Invalid cyphertext length
|
// Invalid cyphertext length
|
||||||
_, err = s.server.ValidateRegistration(&s.key.PublicKey, []byte("too short"))
|
_, err = s.server.ValidateRegistration(&s.key.PublicKey, []byte("too short"))
|
||||||
s.Require().Equal(ErrInvalidCiphertextLength, err)
|
s.Require().Equal(common.ErrInvalidCiphertextLength, err)
|
||||||
|
|
||||||
// Invalid cyphertext length
|
// Invalid cyphertext length
|
||||||
_, err = s.server.ValidateRegistration(&s.key.PublicKey, []byte("too short"))
|
_, err = s.server.ValidateRegistration(&s.key.PublicKey, []byte("too short"))
|
||||||
s.Require().Equal(ErrInvalidCiphertextLength, err)
|
s.Require().Equal(common.ErrInvalidCiphertextLength, err)
|
||||||
|
|
||||||
// Invalid ciphertext
|
// Invalid ciphertext
|
||||||
_, err = s.server.ValidateRegistration(&s.key.PublicKey, []byte("not too short but invalid"))
|
_, 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
|
// 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)
|
s.Require().NoError(err)
|
||||||
_, err = s.server.ValidateRegistration(&s.key.PublicKey, cyphertext)
|
_, err = s.server.ValidateRegistration(&s.key.PublicKey, cyphertext)
|
||||||
s.Require().Error(err)
|
s.Require().Error(err)
|
||||||
|
|
||||||
// Right cyphertext but non unmarshable payload
|
// 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)
|
s.Require().NoError(err)
|
||||||
_, err = s.server.ValidateRegistration(&s.key.PublicKey, cyphertext)
|
_, err = s.server.ValidateRegistration(&s.key.PublicKey, cyphertext)
|
||||||
s.Require().Equal(ErrCouldNotUnmarshalPushNotificationRegistration, err)
|
s.Require().Equal(ErrCouldNotUnmarshalPushNotificationRegistration, err)
|
||||||
|
@ -106,7 +107,7 @@ func (s *ServerSuite) TestPushNotificationServerValidateRegistration() {
|
||||||
})
|
})
|
||||||
s.Require().NoError(err)
|
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)
|
s.Require().NoError(err)
|
||||||
_, err = s.server.ValidateRegistration(&s.key.PublicKey, cyphertext)
|
_, err = s.server.ValidateRegistration(&s.key.PublicKey, cyphertext)
|
||||||
s.Require().Equal(ErrMalformedPushNotificationRegistrationInstallationID, err)
|
s.Require().Equal(ErrMalformedPushNotificationRegistrationInstallationID, err)
|
||||||
|
@ -118,7 +119,7 @@ func (s *ServerSuite) TestPushNotificationServerValidateRegistration() {
|
||||||
InstallationId: "abc",
|
InstallationId: "abc",
|
||||||
Version: 1,
|
Version: 1,
|
||||||
})
|
})
|
||||||
cyphertext, err = encrypt(payload, s.sharedKey, rand.Reader)
|
cyphertext, err = common.Encrypt(payload, s.sharedKey, rand.Reader)
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
_, err = s.server.ValidateRegistration(&s.key.PublicKey, cyphertext)
|
_, err = s.server.ValidateRegistration(&s.key.PublicKey, cyphertext)
|
||||||
s.Require().Equal(ErrMalformedPushNotificationRegistrationInstallationID, err)
|
s.Require().Equal(ErrMalformedPushNotificationRegistrationInstallationID, err)
|
||||||
|
@ -131,7 +132,7 @@ func (s *ServerSuite) TestPushNotificationServerValidateRegistration() {
|
||||||
})
|
})
|
||||||
s.Require().NoError(err)
|
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)
|
s.Require().NoError(err)
|
||||||
_, err = s.server.ValidateRegistration(&s.key.PublicKey, cyphertext)
|
_, err = s.server.ValidateRegistration(&s.key.PublicKey, cyphertext)
|
||||||
s.Require().Equal(ErrInvalidPushNotificationRegistrationVersion, err)
|
s.Require().Equal(ErrInvalidPushNotificationRegistrationVersion, err)
|
||||||
|
@ -145,11 +146,11 @@ func (s *ServerSuite) TestPushNotificationServerValidateRegistration() {
|
||||||
})
|
})
|
||||||
s.Require().NoError(err)
|
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)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
// Setup persistence
|
// 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,
|
AccessToken: s.accessToken,
|
||||||
TokenType: protobuf.PushNotificationRegistration_APN_TOKEN,
|
TokenType: protobuf.PushNotificationRegistration_APN_TOKEN,
|
||||||
InstallationId: s.installationID,
|
InstallationId: s.installationID,
|
||||||
|
@ -159,7 +160,7 @@ func (s *ServerSuite) TestPushNotificationServerValidateRegistration() {
|
||||||
s.Require().Equal(ErrInvalidPushNotificationRegistrationVersion, err)
|
s.Require().Equal(ErrInvalidPushNotificationRegistrationVersion, err)
|
||||||
|
|
||||||
// Cleanup persistence
|
// 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
|
// Unregistering message
|
||||||
payload, err = proto.Marshal(&protobuf.PushNotificationRegistration{
|
payload, err = proto.Marshal(&protobuf.PushNotificationRegistration{
|
||||||
|
@ -170,7 +171,7 @@ func (s *ServerSuite) TestPushNotificationServerValidateRegistration() {
|
||||||
})
|
})
|
||||||
s.Require().NoError(err)
|
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)
|
s.Require().NoError(err)
|
||||||
_, err = s.server.ValidateRegistration(&s.key.PublicKey, cyphertext)
|
_, err = s.server.ValidateRegistration(&s.key.PublicKey, cyphertext)
|
||||||
s.Require().Nil(err)
|
s.Require().Nil(err)
|
||||||
|
@ -183,7 +184,7 @@ func (s *ServerSuite) TestPushNotificationServerValidateRegistration() {
|
||||||
})
|
})
|
||||||
s.Require().NoError(err)
|
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)
|
s.Require().NoError(err)
|
||||||
_, err = s.server.ValidateRegistration(&s.key.PublicKey, cyphertext)
|
_, err = s.server.ValidateRegistration(&s.key.PublicKey, cyphertext)
|
||||||
s.Require().Equal(ErrMalformedPushNotificationRegistrationAccessToken, err)
|
s.Require().Equal(ErrMalformedPushNotificationRegistrationAccessToken, err)
|
||||||
|
@ -197,7 +198,7 @@ func (s *ServerSuite) TestPushNotificationServerValidateRegistration() {
|
||||||
})
|
})
|
||||||
s.Require().NoError(err)
|
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)
|
s.Require().NoError(err)
|
||||||
_, err = s.server.ValidateRegistration(&s.key.PublicKey, cyphertext)
|
_, err = s.server.ValidateRegistration(&s.key.PublicKey, cyphertext)
|
||||||
s.Require().Equal(ErrMalformedPushNotificationRegistrationAccessToken, err)
|
s.Require().Equal(ErrMalformedPushNotificationRegistrationAccessToken, err)
|
||||||
|
@ -211,7 +212,7 @@ func (s *ServerSuite) TestPushNotificationServerValidateRegistration() {
|
||||||
})
|
})
|
||||||
s.Require().NoError(err)
|
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)
|
s.Require().NoError(err)
|
||||||
_, err = s.server.ValidateRegistration(&s.key.PublicKey, cyphertext)
|
_, err = s.server.ValidateRegistration(&s.key.PublicKey, cyphertext)
|
||||||
s.Require().Equal(ErrMalformedPushNotificationRegistrationDeviceToken, err)
|
s.Require().Equal(ErrMalformedPushNotificationRegistrationDeviceToken, err)
|
||||||
|
@ -225,7 +226,7 @@ func (s *ServerSuite) TestPushNotificationServerValidateRegistration() {
|
||||||
})
|
})
|
||||||
s.Require().NoError(err)
|
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)
|
s.Require().NoError(err)
|
||||||
_, err = s.server.ValidateRegistration(&s.key.PublicKey, cyphertext)
|
_, err = s.server.ValidateRegistration(&s.key.PublicKey, cyphertext)
|
||||||
s.Require().Equal(ErrUnknownPushNotificationRegistrationTokenType, err)
|
s.Require().Equal(ErrUnknownPushNotificationRegistrationTokenType, err)
|
||||||
|
@ -240,7 +241,7 @@ func (s *ServerSuite) TestPushNotificationServerValidateRegistration() {
|
||||||
})
|
})
|
||||||
s.Require().NoError(err)
|
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)
|
s.Require().NoError(err)
|
||||||
_, err = s.server.ValidateRegistration(&s.key.PublicKey, cyphertext)
|
_, err = s.server.ValidateRegistration(&s.key.PublicKey, cyphertext)
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
@ -278,7 +279,7 @@ func (s *ServerSuite) TestPushNotificationHandleRegistration() {
|
||||||
s.Require().Equal(response.Error, protobuf.PushNotificationRegistrationResponse_MALFORMED_MESSAGE)
|
s.Require().Equal(response.Error, protobuf.PushNotificationRegistrationResponse_MALFORMED_MESSAGE)
|
||||||
|
|
||||||
// Different key ciphertext
|
// 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)
|
s.Require().NoError(err)
|
||||||
response = s.server.HandlePushNotificationRegistration(&s.key.PublicKey, cyphertext)
|
response = s.server.HandlePushNotificationRegistration(&s.key.PublicKey, cyphertext)
|
||||||
s.Require().NotNil(response)
|
s.Require().NotNil(response)
|
||||||
|
@ -286,7 +287,7 @@ func (s *ServerSuite) TestPushNotificationHandleRegistration() {
|
||||||
s.Require().Equal(response.Error, protobuf.PushNotificationRegistrationResponse_MALFORMED_MESSAGE)
|
s.Require().Equal(response.Error, protobuf.PushNotificationRegistrationResponse_MALFORMED_MESSAGE)
|
||||||
|
|
||||||
// Right cyphertext but non unmarshable payload
|
// 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)
|
s.Require().NoError(err)
|
||||||
response = s.server.HandlePushNotificationRegistration(&s.key.PublicKey, cyphertext)
|
response = s.server.HandlePushNotificationRegistration(&s.key.PublicKey, cyphertext)
|
||||||
s.Require().NotNil(response)
|
s.Require().NotNil(response)
|
||||||
|
@ -300,7 +301,7 @@ func (s *ServerSuite) TestPushNotificationHandleRegistration() {
|
||||||
})
|
})
|
||||||
s.Require().NoError(err)
|
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)
|
s.Require().NoError(err)
|
||||||
response = s.server.HandlePushNotificationRegistration(&s.key.PublicKey, cyphertext)
|
response = s.server.HandlePushNotificationRegistration(&s.key.PublicKey, cyphertext)
|
||||||
s.Require().NotNil(response)
|
s.Require().NotNil(response)
|
||||||
|
@ -313,7 +314,7 @@ func (s *ServerSuite) TestPushNotificationHandleRegistration() {
|
||||||
InstallationId: "abc",
|
InstallationId: "abc",
|
||||||
Version: 1,
|
Version: 1,
|
||||||
})
|
})
|
||||||
cyphertext, err = encrypt(payload, s.sharedKey, rand.Reader)
|
cyphertext, err = common.Encrypt(payload, s.sharedKey, rand.Reader)
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
response = s.server.HandlePushNotificationRegistration(&s.key.PublicKey, cyphertext)
|
response = s.server.HandlePushNotificationRegistration(&s.key.PublicKey, cyphertext)
|
||||||
s.Require().NotNil(response)
|
s.Require().NotNil(response)
|
||||||
|
@ -327,7 +328,7 @@ func (s *ServerSuite) TestPushNotificationHandleRegistration() {
|
||||||
})
|
})
|
||||||
s.Require().NoError(err)
|
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)
|
s.Require().NoError(err)
|
||||||
response = s.server.HandlePushNotificationRegistration(&s.key.PublicKey, cyphertext)
|
response = s.server.HandlePushNotificationRegistration(&s.key.PublicKey, cyphertext)
|
||||||
s.Require().NotNil(response)
|
s.Require().NotNil(response)
|
||||||
|
@ -342,11 +343,11 @@ func (s *ServerSuite) TestPushNotificationHandleRegistration() {
|
||||||
})
|
})
|
||||||
s.Require().NoError(err)
|
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)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
// Setup persistence
|
// 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,
|
AccessToken: s.accessToken,
|
||||||
InstallationId: s.installationID,
|
InstallationId: s.installationID,
|
||||||
Version: 2}))
|
Version: 2}))
|
||||||
|
@ -357,7 +358,7 @@ func (s *ServerSuite) TestPushNotificationHandleRegistration() {
|
||||||
s.Require().Equal(response.Error, protobuf.PushNotificationRegistrationResponse_VERSION_MISMATCH)
|
s.Require().Equal(response.Error, protobuf.PushNotificationRegistrationResponse_VERSION_MISMATCH)
|
||||||
|
|
||||||
// Cleanup persistence
|
// 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
|
// Missing access token
|
||||||
payload, err = proto.Marshal(&protobuf.PushNotificationRegistration{
|
payload, err = proto.Marshal(&protobuf.PushNotificationRegistration{
|
||||||
|
@ -366,7 +367,7 @@ func (s *ServerSuite) TestPushNotificationHandleRegistration() {
|
||||||
})
|
})
|
||||||
s.Require().NoError(err)
|
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)
|
s.Require().NoError(err)
|
||||||
response = s.server.HandlePushNotificationRegistration(&s.key.PublicKey, cyphertext)
|
response = s.server.HandlePushNotificationRegistration(&s.key.PublicKey, cyphertext)
|
||||||
s.Require().NotNil(response)
|
s.Require().NotNil(response)
|
||||||
|
@ -381,7 +382,7 @@ func (s *ServerSuite) TestPushNotificationHandleRegistration() {
|
||||||
})
|
})
|
||||||
s.Require().NoError(err)
|
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)
|
s.Require().NoError(err)
|
||||||
response = s.server.HandlePushNotificationRegistration(&s.key.PublicKey, cyphertext)
|
response = s.server.HandlePushNotificationRegistration(&s.key.PublicKey, cyphertext)
|
||||||
s.Require().NotNil(response)
|
s.Require().NotNil(response)
|
||||||
|
@ -396,7 +397,7 @@ func (s *ServerSuite) TestPushNotificationHandleRegistration() {
|
||||||
})
|
})
|
||||||
s.Require().NoError(err)
|
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)
|
s.Require().NoError(err)
|
||||||
response = s.server.HandlePushNotificationRegistration(&s.key.PublicKey, cyphertext)
|
response = s.server.HandlePushNotificationRegistration(&s.key.PublicKey, cyphertext)
|
||||||
s.Require().NotNil(response)
|
s.Require().NotNil(response)
|
||||||
|
@ -414,14 +415,14 @@ func (s *ServerSuite) TestPushNotificationHandleRegistration() {
|
||||||
payload, err = proto.Marshal(registration)
|
payload, err = proto.Marshal(registration)
|
||||||
s.Require().NoError(err)
|
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)
|
s.Require().NoError(err)
|
||||||
response = s.server.HandlePushNotificationRegistration(&s.key.PublicKey, cyphertext)
|
response = s.server.HandlePushNotificationRegistration(&s.key.PublicKey, cyphertext)
|
||||||
s.Require().NotNil(response)
|
s.Require().NotNil(response)
|
||||||
s.Require().True(response.Success)
|
s.Require().True(response.Success)
|
||||||
|
|
||||||
// Pull from the db
|
// 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().NoError(err)
|
||||||
s.Require().NotNil(retrievedRegistration)
|
s.Require().NotNil(retrievedRegistration)
|
||||||
s.Require().True(proto.Equal(retrievedRegistration, registration))
|
s.Require().True(proto.Equal(retrievedRegistration, registration))
|
||||||
|
@ -435,25 +436,25 @@ func (s *ServerSuite) TestPushNotificationHandleRegistration() {
|
||||||
})
|
})
|
||||||
s.Require().NoError(err)
|
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)
|
s.Require().NoError(err)
|
||||||
response = s.server.HandlePushNotificationRegistration(&s.key.PublicKey, cyphertext)
|
response = s.server.HandlePushNotificationRegistration(&s.key.PublicKey, cyphertext)
|
||||||
s.Require().NotNil(response)
|
s.Require().NotNil(response)
|
||||||
s.Require().True(response.Success)
|
s.Require().True(response.Success)
|
||||||
|
|
||||||
// Check is gone from the db
|
// 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().NoError(err)
|
||||||
s.Require().NotNil(retrievedRegistration)
|
s.Require().NotNil(retrievedRegistration)
|
||||||
s.Require().Empty(retrievedRegistration.AccessToken)
|
s.Require().Empty(retrievedRegistration.AccessToken)
|
||||||
s.Require().Empty(retrievedRegistration.Token)
|
s.Require().Empty(retrievedRegistration.Token)
|
||||||
s.Require().Equal(uint64(2), retrievedRegistration.Version)
|
s.Require().Equal(uint64(2), retrievedRegistration.Version)
|
||||||
s.Require().Equal(s.installationID, retrievedRegistration.InstallationId)
|
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() {
|
func (s *ServerSuite) TestHandlePushNotificationQueryNoFiltering() {
|
||||||
hashedPublicKey := hashPublicKey(&s.key.PublicKey)
|
hashedPublicKey := common.HashPublicKey(&s.key.PublicKey)
|
||||||
// Successful
|
// Successful
|
||||||
registration := &protobuf.PushNotificationRegistration{
|
registration := &protobuf.PushNotificationRegistration{
|
||||||
Token: "abc",
|
Token: "abc",
|
||||||
|
@ -465,7 +466,7 @@ func (s *ServerSuite) TestHandlePushNotificationQueryNoFiltering() {
|
||||||
payload, err := proto.Marshal(registration)
|
payload, err := proto.Marshal(registration)
|
||||||
s.Require().NoError(err)
|
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)
|
s.Require().NoError(err)
|
||||||
response := s.server.HandlePushNotificationRegistration(&s.key.PublicKey, cyphertext)
|
response := s.server.HandlePushNotificationRegistration(&s.key.PublicKey, cyphertext)
|
||||||
s.Require().NotNil(response)
|
s.Require().NotNil(response)
|
||||||
|
@ -486,7 +487,7 @@ func (s *ServerSuite) TestHandlePushNotificationQueryNoFiltering() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ServerSuite) TestHandlePushNotificationQueryWithFiltering() {
|
func (s *ServerSuite) TestHandlePushNotificationQueryWithFiltering() {
|
||||||
hashedPublicKey := hashPublicKey(&s.key.PublicKey)
|
hashedPublicKey := common.HashPublicKey(&s.key.PublicKey)
|
||||||
allowedUserList := [][]byte{[]byte("a")}
|
allowedUserList := [][]byte{[]byte("a")}
|
||||||
// Successful
|
// Successful
|
||||||
|
|
||||||
|
@ -501,7 +502,7 @@ func (s *ServerSuite) TestHandlePushNotificationQueryWithFiltering() {
|
||||||
payload, err := proto.Marshal(registration)
|
payload, err := proto.Marshal(registration)
|
||||||
s.Require().NoError(err)
|
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)
|
s.Require().NoError(err)
|
||||||
response := s.server.HandlePushNotificationRegistration(&s.key.PublicKey, cyphertext)
|
response := s.server.HandlePushNotificationRegistration(&s.key.PublicKey, cyphertext)
|
||||||
s.Require().NotNil(response)
|
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"
|
encryptmigrations "github.com/status-im/status-go/protocol/encryption/migrations"
|
||||||
appmigrations "github.com/status-im/status-go/protocol/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"
|
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"
|
wakumigrations "github.com/status-im/status-go/protocol/transport/waku/migrations"
|
||||||
whispermigrations "github.com/status-im/status-go/protocol/transport/whisper/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(),
|
Names: push_notification_server_migrations.AssetNames(),
|
||||||
Getter: push_notification_server_migrations.Asset,
|
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) {
|
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.
|
// UpdateMailservers updates information about selected mail servers.
|
||||||
func (s *Service) UpdateMailservers(nodes []*enode.Node) error {
|
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 {
|
if err := s.peerStore.Update(nodes); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue