From 4ded7bf74c52c5c044806144d82f4763631f1805 Mon Sep 17 00:00:00 2001 From: Andrea Maria Piana Date: Tue, 30 Jun 2020 10:30:58 +0200 Subject: [PATCH] Add skeleton for server and separate namespace for client --- protocol/messenger.go | 15 +++--- .../push_notification.go | 46 +++++++++---------- .../push_notification_persistence.go | 26 +++++++++++ .../push_notification_test.go | 28 +++++------ protocol/push_notification_persistence.go | 26 ----------- .../push_notification_server.go | 32 +++++++++++++ .../push_notification_server_persistence.go | 13 ++++++ .../push_notification_server_test.go | 13 ++++++ 8 files changed, 129 insertions(+), 70 deletions(-) rename protocol/{ => push_notification_client}/push_notification.go (74%) create mode 100644 protocol/push_notification_client/push_notification_persistence.go rename protocol/{ => push_notification_client}/push_notification_test.go (90%) delete mode 100644 protocol/push_notification_persistence.go create mode 100644 protocol/push_notification_server/push_notification_server.go create mode 100644 protocol/push_notification_server/push_notification_server_persistence.go create mode 100644 protocol/push_notification_server/push_notification_server_test.go diff --git a/protocol/messenger.go b/protocol/messenger.go index 176dabbf8..a1ebe3824 100644 --- a/protocol/messenger.go +++ b/protocol/messenger.go @@ -25,6 +25,7 @@ import ( "github.com/status-im/status-go/protocol/identity/identicon" "github.com/status-im/status-go/protocol/images" "github.com/status-im/status-go/protocol/protobuf" + "github.com/status-im/status-go/protocol/push_notification_client" "github.com/status-im/status-go/protocol/sqlite" "github.com/status-im/status-go/protocol/transport" wakutransp "github.com/status-im/status-go/protocol/transport/waku" @@ -57,7 +58,7 @@ type Messenger struct { encryptor *encryption.Protocol processor *messageProcessor handler *MessageHandler - pushNotificationService *PushNotificationService + pushNotificationClient *push_notification_client.Client logger *zap.Logger verifyTransactionClient EthClient featureFlags featureFlags @@ -329,8 +330,8 @@ func NewMessenger( logger, ) - pushNotificationPersistence := NewPushNotificationPersistence(database) - pushNotificationService := NewPushNotificationService(pushNotificationPersistence) + pushNotificationClientPersistence := push_notification_client.NewPersistence(database) + pushNotificationClient := push_notification_client.New(pushNotificationClientPersistence) processor, err := newMessageProcessor( identity, @@ -339,7 +340,7 @@ func NewMessenger( transp, logger, c.featureFlags, - pushNotificationService.HandleMessageSent, + pushNotificationClient.HandleMessageSent, ) if err != nil { return nil, errors.Wrap(err, "failed to create messageProcessor") @@ -355,7 +356,7 @@ func NewMessenger( encryptor: encryptionProtocol, processor: processor, handler: handler, - pushNotificationService: pushNotificationService, + pushNotificationClient: pushNotificationClient, featureFlags: c.featureFlags, systemMessagesTranslations: c.systemMessagesTranslations, allChats: make(map[string]*Chat), @@ -1473,8 +1474,8 @@ func (m *Messenger) SendChatMessage(ctx context.Context, message *Message) (*Mes } // If the chat is not public, we instruct the pushNotificationService to send a notification - if !chat.Public() && m.pushNotificationService != nil { - if err := m.pushNotificationService.NotifyOnMessageID(id); err != nil { + if !chat.Public() && m.pushNotificationClient != nil { + if err := m.pushNotificationClient.NotifyOnMessageID(id); err != nil { return nil, err } diff --git a/protocol/push_notification.go b/protocol/push_notification_client/push_notification.go similarity index 74% rename from protocol/push_notification.go rename to protocol/push_notification_client/push_notification.go index 5d57233cf..6416eb298 100644 --- a/protocol/push_notification.go +++ b/protocol/push_notification_client/push_notification.go @@ -1,4 +1,4 @@ -package protocol +package push_notification_client import ( "crypto/aes" @@ -26,7 +26,7 @@ type PushNotificationServer struct { registered bool } -type PushNotificationConfig struct { +type Config struct { // Identity is our identity key Identity *ecdsa.PrivateKey // SendEnabled indicates whether we should be sending push notifications @@ -47,9 +47,9 @@ type PushNotificationConfig struct { InstallationID string } -type PushNotificationService struct { - persistence *PushNotificationPersistence - config *PushNotificationConfig +type Client struct { + persistence *Persistence + config *Config // lastPushNotificationRegister is the latest known push notification register message lastPushNotificationRegister *protobuf.PushNotificationRegister @@ -63,8 +63,8 @@ type PushNotificationService struct { reader io.Reader } -func NewPushNotificationService(persistence *PushNotificationPersistence) *PushNotificationService { - return &PushNotificationService{persistence: persistence, reader: rand.Reader} +func New(persistence *Persistence) *Client { + return &Client{persistence: persistence, reader: rand.Reader} } // This likely will return a channel as it's an asynchrous operation @@ -81,15 +81,15 @@ func sendPushNotificationTo(publicKey *ecdsa.PublicKey, chatID string) error { // 1) Check we have reasonably fresh push notifications info // 2) Otherwise it should fetch them // 3) Send a push notification to the devices in question -func (p *PushNotificationService) HandleMessageSent(publicKey *ecdsa.PublicKey, spec *encryption.ProtocolMessageSpec, messageIDs [][]byte) error { +func (p *Client) HandleMessageSent(publicKey *ecdsa.PublicKey, spec *encryption.ProtocolMessageSpec, messageIDs [][]byte) error { return nil } -func (p *PushNotificationService) NotifyOnMessageID(messageID []byte) error { +func (p *Client) NotifyOnMessageID(messageID []byte) error { return nil } -func (p *PushNotificationService) mutedChatIDsHashes() [][]byte { +func (p *Client) mutedChatIDsHashes() [][]byte { var mutedChatListHashes [][]byte for _, chatID := range p.config.MutedChatIDs { @@ -99,7 +99,7 @@ func (p *PushNotificationService) mutedChatIDsHashes() [][]byte { return mutedChatListHashes } -func (p *PushNotificationService) reEncryptTokenPair(token []byte, pair *protobuf.PushNotificationTokenPair) (*protobuf.PushNotificationTokenPair, error) { +func (p *Client) reEncryptTokenPair(token []byte, pair *protobuf.PushNotificationTokenPair) (*protobuf.PushNotificationTokenPair, error) { publicKey, err := crypto.DecompressPubkey(pair.PublicKey) if err != nil { return nil, err @@ -107,7 +107,7 @@ func (p *PushNotificationService) reEncryptTokenPair(token []byte, pair *protobu return p.encryptTokenPair(publicKey, token) } -func (p *PushNotificationService) encryptTokenPair(publicKey *ecdsa.PublicKey, token []byte) (*protobuf.PushNotificationTokenPair, error) { +func (p *Client) encryptTokenPair(publicKey *ecdsa.PublicKey, token []byte) (*protobuf.PushNotificationTokenPair, error) { sharedKey, err := ecies.ImportECDSA(p.config.Identity).GenerateShared( ecies.ImportECDSAPublic(publicKey), accessTokenKeyLength, @@ -127,7 +127,7 @@ func (p *PushNotificationService) encryptTokenPair(publicKey *ecdsa.PublicKey, t }, nil } -func (p *PushNotificationService) allowedUserList(token []byte) ([]*protobuf.PushNotificationTokenPair, error) { +func (p *Client) allowedUserList(token []byte) ([]*protobuf.PushNotificationTokenPair, error) { var tokenPairs []*protobuf.PushNotificationTokenPair for _, publicKey := range p.config.ContactIDs { tokenPair, err := p.encryptTokenPair(publicKey, token) @@ -141,7 +141,7 @@ func (p *PushNotificationService) allowedUserList(token []byte) ([]*protobuf.Pus return tokenPairs, nil } -func (p *PushNotificationService) reEncryptAllowedUserList(token []byte, oldTokenPairs []*protobuf.PushNotificationTokenPair) ([]*protobuf.PushNotificationTokenPair, error) { +func (p *Client) reEncryptAllowedUserList(token []byte, oldTokenPairs []*protobuf.PushNotificationTokenPair) ([]*protobuf.PushNotificationTokenPair, error) { var tokenPairs []*protobuf.PushNotificationTokenPair for _, tokenPair := range oldTokenPairs { tokenPair, err := p.reEncryptTokenPair(token, tokenPair) @@ -155,7 +155,7 @@ func (p *PushNotificationService) reEncryptAllowedUserList(token []byte, oldToke return tokenPairs, nil } -func (p *PushNotificationService) buildPushNotificationOptionsMessage(token string) (*protobuf.PushNotificationOptions, error) { +func (p *Client) buildPushNotificationOptionsMessage(token string) (*protobuf.PushNotificationOptions, error) { allowedUserList, err := p.allowedUserList([]byte(token)) if err != nil { return nil, err @@ -171,7 +171,7 @@ func (p *PushNotificationService) buildPushNotificationOptionsMessage(token stri return options, nil } -func (p *PushNotificationService) buildPushNotificationRegisterMessage() (*protobuf.PushNotificationRegister, error) { +func (p *Client) buildPushNotificationRegisterMessage() (*protobuf.PushNotificationRegister, error) { pushNotificationPreferences := &protobuf.PushNotificationPreferences{} if p.lastPushNotificationRegister != nil { @@ -219,37 +219,37 @@ func (p *PushNotificationService) buildPushNotificationRegisterMessage() (*proto return message, nil } -func (p *PushNotificationService) Register(deviceToken string) error { +func (p *Client) Register(deviceToken string) error { return nil } // HandlePushNotificationRegistrationResponse should check whether the response was successful or not, retry if necessary otherwise store the result in the database -func (p *PushNotificationService) HandlePushNotificationRegistrationResponse(response *protobuf.PushNotificationRegistrationResponse) error { +func (p *Client) HandlePushNotificationRegistrationResponse(response *protobuf.PushNotificationRegistrationResponse) error { return nil } // HandlePushNotificationAdvertisement should store any info related to push notifications -func (p *PushNotificationService) HandlePushNotificationAdvertisement(info *protobuf.PushNotificationAdvertisementInfo) error { +func (p *Client) HandlePushNotificationAdvertisement(info *protobuf.PushNotificationAdvertisementInfo) error { return nil } // HandlePushNotificationQueryResponse should update the data in the database for a given user -func (p *PushNotificationService) HandlePushNotificationQueryResponse(response *protobuf.PushNotificationQueryResponse) error { +func (p *Client) HandlePushNotificationQueryResponse(response *protobuf.PushNotificationQueryResponse) error { return nil } // HandlePushNotificationAcknowledgement should set the request as processed -func (p *PushNotificationService) HandlePushNotificationAcknowledgement(ack *protobuf.PushNotificationAcknowledgement) error { +func (p *Client) HandlePushNotificationAcknowledgement(ack *protobuf.PushNotificationAcknowledgement) error { return nil } -func (p *PushNotificationService) SetContactIDs(contactIDs []*ecdsa.PublicKey) error { +func (p *Client) SetContactIDs(contactIDs []*ecdsa.PublicKey) error { p.config.ContactIDs = contactIDs // Update or schedule update return nil } -func (p *PushNotificationService) SetMutedChatIDs(chatIDs []string) error { +func (p *Client) SetMutedChatIDs(chatIDs []string) error { p.config.MutedChatIDs = chatIDs // Update or schedule update return nil diff --git a/protocol/push_notification_client/push_notification_persistence.go b/protocol/push_notification_client/push_notification_persistence.go new file mode 100644 index 000000000..7305ced91 --- /dev/null +++ b/protocol/push_notification_client/push_notification_persistence.go @@ -0,0 +1,26 @@ +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 +} diff --git a/protocol/push_notification_test.go b/protocol/push_notification_client/push_notification_test.go similarity index 90% rename from protocol/push_notification_test.go rename to protocol/push_notification_client/push_notification_test.go index 955af1968..a07ded2d4 100644 --- a/protocol/push_notification_test.go +++ b/protocol/push_notification_client/push_notification_test.go @@ -1,4 +1,4 @@ -package protocol +package push_notification_client import ( "bytes" @@ -59,7 +59,7 @@ func TestBuildPushNotificationRegisterMessage(t *testing.T) { // Reset random generator uuid.SetRand(rand.New(rand.NewSource(seed))) - config := &PushNotificationConfig{ + config := &Config{ Identity: identity, RemoteNotificationsEnabled: true, MutedChatIDs: mutedChatList, @@ -67,11 +67,11 @@ func TestBuildPushNotificationRegisterMessage(t *testing.T) { InstallationID: myInstallationID, } - service := &PushNotificationService{} - service.config = config - service.DeviceToken = myDeviceToken + client := &Client{} + client.config = config + client.DeviceToken = myDeviceToken // Set reader - service.reader = bytes.NewReader([]byte(expectedUUID)) + client.reader = bytes.NewReader([]byte(expectedUUID)) options := &protobuf.PushNotificationOptions{ Token: myDeviceToken, @@ -92,7 +92,7 @@ func TestBuildPushNotificationRegisterMessage(t *testing.T) { require.NoError(t, err) expectedMessage := &protobuf.PushNotificationRegister{Payload: marshaledPreferences} - actualMessage, err := service.buildPushNotificationRegisterMessage() + actualMessage, err := client.buildPushNotificationRegisterMessage() require.NoError(t, err) require.Equal(t, expectedMessage, actualMessage) @@ -177,7 +177,7 @@ func TestBuildPushNotificationRegisterMessageWithPrevious(t *testing.T) { // Reset random generator uuid.SetRand(rand.New(rand.NewSource(seed))) - config := &PushNotificationConfig{ + config := &Config{ Identity: identity, RemoteNotificationsEnabled: true, MutedChatIDs: mutedChatList, @@ -185,12 +185,12 @@ func TestBuildPushNotificationRegisterMessageWithPrevious(t *testing.T) { InstallationID: installationID1, } - service := &PushNotificationService{} - service.config = config - service.DeviceToken = deviceToken1 - service.lastPushNotificationRegister = lastPushNotificationRegister + client := &Client{} + client.config = config + client.DeviceToken = deviceToken1 + client.lastPushNotificationRegister = lastPushNotificationRegister // Set reader - service.reader = bytes.NewReader([]byte(expectedUUID)) + client.reader = bytes.NewReader([]byte(expectedUUID)) options1 := &protobuf.PushNotificationOptions{ Token: deviceToken1, @@ -212,7 +212,7 @@ func TestBuildPushNotificationRegisterMessageWithPrevious(t *testing.T) { require.NoError(t, err) expectedMessage := &protobuf.PushNotificationRegister{Payload: marshaledPreferences} - actualMessage, err := service.buildPushNotificationRegisterMessage() + actualMessage, err := client.buildPushNotificationRegisterMessage() require.NoError(t, err) require.Equal(t, expectedMessage, actualMessage) diff --git a/protocol/push_notification_persistence.go b/protocol/push_notification_persistence.go deleted file mode 100644 index b41057917..000000000 --- a/protocol/push_notification_persistence.go +++ /dev/null @@ -1,26 +0,0 @@ -package protocol - -import ( - "crypto/ecdsa" - "database/sql" -) - -type PushNotificationPersistence struct { - db *sql.DB -} - -func NewPushNotificationPersistence(db *sql.DB) *PushNotificationPersistence { - return &PushNotificationPersistence{db: db} -} - -func (p *PushNotificationPersistence) TrackPushNotification(messageID []byte) error { - return nil -} - -func (p *PushNotificationPersistence) ShouldSentNotificationFor(publicKey *ecdsa.PublicKey, messageID []byte) (bool, error) { - return false, nil -} -func (p *PushNotificationPersistence) PushNotificationSentFor(publicKey *ecdsa.PublicKey, messageID []byte) error { - - return nil -} diff --git a/protocol/push_notification_server/push_notification_server.go b/protocol/push_notification_server/push_notification_server.go new file mode 100644 index 000000000..9dc92d333 --- /dev/null +++ b/protocol/push_notification_server/push_notification_server.go @@ -0,0 +1,32 @@ +package protocol + +import ( + "crypto/ecdsa" + "errors" + "github.com/status-im/status-go/protocol/protobuf" +) + +var ErrEmptyPushNotificationRegisterMessage = errors.New("empty PushNotificationRegisterMessage") + +type Config struct { + // Identity is our identity key + Identity *ecdsa.PrivateKey + // GorushUrl is the url for the gorush service + GorushURL string +} + +type Server struct { + persistence *Persistence + config *Config +} + +func New(persistence *Persistence) *Server { + return &Server{persistence: persistence} +} + +func (p *Server) ValidateRegistration(previousRegistration *protobuf.PushNotificationRegister, newRegistration *protobuf.PushNotificationRegister) error { + if newRegistration == nil { + return ErrEmptyPushNotificationRegisterMessage + } + return nil +} diff --git a/protocol/push_notification_server/push_notification_server_persistence.go b/protocol/push_notification_server/push_notification_server_persistence.go new file mode 100644 index 000000000..25de3818b --- /dev/null +++ b/protocol/push_notification_server/push_notification_server_persistence.go @@ -0,0 +1,13 @@ +package protocol + +import ( + "database/sql" +) + +type Persistence struct { + db *sql.DB +} + +func NewPersistence(db *sql.DB) *Persistence { + return &Persistence{db: db} +} diff --git a/protocol/push_notification_server/push_notification_server_test.go b/protocol/push_notification_server/push_notification_server_test.go new file mode 100644 index 000000000..2f947e569 --- /dev/null +++ b/protocol/push_notification_server/push_notification_server_test.go @@ -0,0 +1,13 @@ +package protocol + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestPushNotificationServerValidateRegistration(t *testing.T) { + server := Server{} + require.Equal(t, ErrEmptyPushNotificationRegisterMessage, server.ValidateRegistration(nil, nil)) + +}