From cddf2e1c6cdbdea77307eadac9f25af874e3d723 Mon Sep 17 00:00:00 2001 From: Pedro Pombeiro Date: Tue, 20 Nov 2018 19:02:54 +0100 Subject: [PATCH] Change `NotifyUsers` to allow only data JSON element. Part of status-im/status-react#6772 --- Gopkg.lock | 6 +-- Gopkg.toml | 5 ++ api/backend.go | 10 ++-- lib/library.go | 14 ++---- notifications/push/fcm/client.go | 1 - notifications/push/fcm/client_mock.go | 25 +++------- notifications/push/fcm/notification.go | 33 ++++++------- notifications/push/fcm/notification_test.go | 53 ++++++++++++--------- vendor/github.com/NaySoftware/go-fcm/fcm.go | 16 +++++++ 9 files changed, 87 insertions(+), 76 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 4bd7ac72b..fe6f6d2f6 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -2,12 +2,12 @@ [[projects]] - branch = "master" - digest = "1:5805073c158189c2af2f776b590fc9b88bcc68f2b983842adb08333dbd3c9ae7" + digest = "1:ab480b4ff653dc950445e4ac6747c2a063f3dee7b533f68d4314267ce0fd9005" name = "github.com/NaySoftware/go-fcm" packages = ["."] pruneopts = "NUT" - revision = "2a6c4f48b49f0d5dbfe621589da4c5405157d7c9" + revision = "024ca6a2c5444c93980f558f91c35a2defebd362" + source = "github.com/status-im/go-fcm" [[projects]] branch = "master" diff --git a/Gopkg.toml b/Gopkg.toml index f9df4e035..e37bc6056 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -35,6 +35,11 @@ name = "github.com/golang/protobuf" version = "1.1.0" +[[constraint]] + name = "github.com/NaySoftware/go-fcm" + revision = "024ca6a2c5444c93980f558f91c35a2defebd362" + source = "github.com/status-im/go-fcm" + # * * * * * `go-ethereum` dependencies * * * * * # Pinned down SHAs from `go-ethereum/vendor/vendor.json` # When upgrading upstream, upgrade these values too. diff --git a/api/backend.go b/api/backend.go index a862ede79..942ce9ec7 100644 --- a/api/backend.go +++ b/api/backend.go @@ -13,8 +13,6 @@ import ( gethnode "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/p2p/enode" - fcmlib "github.com/NaySoftware/go-fcm" - "github.com/status-im/status-go/account" "github.com/status-im/status-go/node" "github.com/status-im/status-go/notifications/push/fcm" @@ -446,10 +444,12 @@ func (b *StatusBackend) SelectAccount(address, password string) error { } // NotifyUsers sends push notifications to users. -func (b *StatusBackend) NotifyUsers(message string, payload fcmlib.NotificationPayload, tokens ...string) error { - err := b.newNotification().Send(message, payload, tokens...) +func (b *StatusBackend) NotifyUsers(dataPayloadJSON string, tokens ...string) error { + log.Debug("sending push notification") + + err := b.newNotification().Send(dataPayloadJSON, tokens...) if err != nil { - b.log.Error("Notify failed", "error", err) + b.log.Error("NotifyUsers failed", "dataPayloadJSON", dataPayloadJSON, "error", err) } return err diff --git a/lib/library.go b/lib/library.go index 4a6dbb171..5ce8790a3 100644 --- a/lib/library.go +++ b/lib/library.go @@ -8,7 +8,6 @@ import ( "os" "unsafe" - "github.com/NaySoftware/go-fcm" "github.com/ethereum/go-ethereum/log" "github.com/status-im/status-go/api" "github.com/status-im/status-go/logutils" @@ -417,7 +416,7 @@ func makeJSONResponse(err error) *C.char { // NotifyUsers sends push notifications by given tokens. //export NotifyUsers -func NotifyUsers(message, payloadJSON, tokensArray *C.char) (outCBytes *C.char) { +func NotifyUsers(dataPayloadJSON, tokensArray *C.char) (outCBytes *C.char) { var ( err error outBytes []byte @@ -432,7 +431,7 @@ func NotifyUsers(message, payloadJSON, tokensArray *C.char) (outCBytes *C.char) outBytes, err = json.Marshal(out) if err != nil { - logger.Error("failed to marshal Notify output", "error", err) + logger.Error("failed to marshal NotifyUsers output", "error", err) outCBytes = makeJSONResponse(err) return } @@ -446,14 +445,7 @@ func NotifyUsers(message, payloadJSON, tokensArray *C.char) (outCBytes *C.char) return } - var payload fcm.NotificationPayload - err = json.Unmarshal([]byte(C.GoString(payloadJSON)), &payload) - if err != nil { - errString = err.Error() - return - } - - err = statusBackend.NotifyUsers(C.GoString(message), payload, tokens...) + err = statusBackend.NotifyUsers(C.GoString(dataPayloadJSON), tokens...) if err != nil { errString = err.Error() return diff --git a/notifications/push/fcm/client.go b/notifications/push/fcm/client.go index 2c9b81806..5d66b586b 100644 --- a/notifications/push/fcm/client.go +++ b/notifications/push/fcm/client.go @@ -8,5 +8,4 @@ import ( type FirebaseClient interface { NewFcmRegIdsMsg(tokens []string, body interface{}) *gofcm.FcmClient Send() (*gofcm.FcmResponseStatus, error) - SetNotificationPayload(payload *gofcm.NotificationPayload) *gofcm.FcmClient } diff --git a/notifications/push/fcm/client_mock.go b/notifications/push/fcm/client_mock.go index 71dc2c293..d69f81ee6 100644 --- a/notifications/push/fcm/client_mock.go +++ b/notifications/push/fcm/client_mock.go @@ -5,9 +5,10 @@ package fcm import ( - go_fcm "github.com/NaySoftware/go-fcm" - gomock "github.com/golang/mock/gomock" reflect "reflect" + + fcm "github.com/NaySoftware/go-fcm" + gomock "github.com/golang/mock/gomock" ) // MockFirebaseClient is a mock of FirebaseClient interface @@ -34,9 +35,9 @@ func (m *MockFirebaseClient) EXPECT() *MockFirebaseClientMockRecorder { } // NewFcmRegIdsMsg mocks base method -func (m *MockFirebaseClient) NewFcmRegIdsMsg(tokens []string, body interface{}) *go_fcm.FcmClient { +func (m *MockFirebaseClient) NewFcmRegIdsMsg(tokens []string, body interface{}) *fcm.FcmClient { ret := m.ctrl.Call(m, "NewFcmRegIdsMsg", tokens, body) - ret0, _ := ret[0].(*go_fcm.FcmClient) + ret0, _ := ret[0].(*fcm.FcmClient) return ret0 } @@ -46,9 +47,9 @@ func (mr *MockFirebaseClientMockRecorder) NewFcmRegIdsMsg(tokens, body interface } // Send mocks base method -func (m *MockFirebaseClient) Send() (*go_fcm.FcmResponseStatus, error) { +func (m *MockFirebaseClient) Send() (*fcm.FcmResponseStatus, error) { ret := m.ctrl.Call(m, "Send") - ret0, _ := ret[0].(*go_fcm.FcmResponseStatus) + ret0, _ := ret[0].(*fcm.FcmResponseStatus) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -57,15 +58,3 @@ func (m *MockFirebaseClient) Send() (*go_fcm.FcmResponseStatus, error) { func (mr *MockFirebaseClientMockRecorder) Send() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Send", reflect.TypeOf((*MockFirebaseClient)(nil).Send)) } - -// SetNotificationPayload mocks base method -func (m *MockFirebaseClient) SetNotificationPayload(payload *go_fcm.NotificationPayload) *go_fcm.FcmClient { - ret := m.ctrl.Call(m, "SetNotificationPayload", payload) - ret0, _ := ret[0].(*go_fcm.FcmClient) - return ret0 -} - -// SetNotificationPayload indicates an expected call of SetNotificationPayload -func (mr *MockFirebaseClientMockRecorder) SetNotificationPayload(payload interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetNotificationPayload", reflect.TypeOf((*MockFirebaseClient)(nil).SetNotificationPayload), payload) -} diff --git a/notifications/push/fcm/notification.go b/notifications/push/fcm/notification.go index 9ba86b081..f7f56c15e 100644 --- a/notifications/push/fcm/notification.go +++ b/notifications/push/fcm/notification.go @@ -1,6 +1,7 @@ package fcm import ( + "encoding/json" "fmt" "github.com/NaySoftware/go-fcm" @@ -8,7 +9,7 @@ import ( // Notifier manages Push Notifications. type Notifier interface { - Send(body string, payload fcm.NotificationPayload, tokens ...string) error + Send(dataPayloadJSON string, tokens ...string) error } // NotificationConstructor returns constructor of configured instance Notifier interface. @@ -25,30 +26,30 @@ func NewNotification(key string) NotificationConstructor { client := fcm.NewFcmClient(key). SetDelayWhileIdle(true). SetContentAvailable(true). + SetPriority(fcm.Priority_HIGH). // Message needs to be marked as high-priority so that background task in an Android's recipient device can be invoked (https://github.com/invertase/react-native-firebase/blob/d13f0af53f1c8f20db8bc8d4b6f8c6d210e108b9/android/src/main/java/io/invertase/firebase/messaging/RNFirebaseMessagingService.java#L56) SetTimeToLive(fcm.MAX_TTL) return &Notification{client} } } -// Send send to the tokens list. -func (n *Notification) Send(body string, payload fcm.NotificationPayload, tokens ...string) error { - data := map[string]string{ - "msg": body, +// Send sends a push notification to the tokens list. +func (n *Notification) Send(dataPayloadJSON string, tokens ...string) error { + var dataPayload map[string]string + err := json.Unmarshal([]byte(dataPayloadJSON), &dataPayload) + if err != nil { + return err } - if payload.Title == "" { - payload.Title = "Status" - } - if payload.Body == "" { - payload.Body = "You have a new message" + n.client.NewFcmRegIdsMsg(tokens, dataPayload) + resp, err := n.client.Send() + if err != nil { + return err } - fmt.Println(payload.Title, payload.Body) + if resp != nil && !resp.Ok { + return fmt.Errorf("FCM error sending message, code=%d err=%s", resp.StatusCode, resp.Err) + } - n.client.NewFcmRegIdsMsg(tokens, data) - n.client.SetNotificationPayload(&payload) - _, err := n.client.Send() - - return err + return nil } diff --git a/notifications/push/fcm/notification_test.go b/notifications/push/fcm/notification_test.go index 025b91cd0..0d6356606 100644 --- a/notifications/push/fcm/notification_test.go +++ b/notifications/push/fcm/notification_test.go @@ -1,10 +1,10 @@ package fcm import ( + "encoding/json" "errors" "testing" - "github.com/NaySoftware/go-fcm" "github.com/golang/mock/gomock" "github.com/stretchr/testify/suite" ) @@ -29,43 +29,52 @@ func (s *NotifierTestSuite) TearDownTest() { s.fcmClientMockCtrl.Finish() } -func (s *NotifierTestSuite) TestNotifySuccess() { - fcmPayload := getPayload() +func (s *NotifierTestSuite) TestSendSuccess() { ids := []string{"1"} - payload := fcmPayload - msg := make(map[string]string) - body := "body1" - msg["msg"] = body + dataPayload := make(map[string]string) + dataPayload["from"] = "a" + dataPayload["to"] = "b" + dataPayloadByteArray, err := json.Marshal(dataPayload) + s.Require().NoError(err) + dataPayloadJSON := string(dataPayloadByteArray) - s.fcmClientMock.EXPECT().SetNotificationPayload(&fcmPayload).Times(1) - s.fcmClientMock.EXPECT().NewFcmRegIdsMsg(ids, msg).Times(1) + s.fcmClientMock.EXPECT().NewFcmRegIdsMsg(ids, dataPayload).Times(1) s.fcmClientMock.EXPECT().Send().Return(nil, nil).Times(1) fcmClient := Notification{s.fcmClientMock} - err := fcmClient.Send(body, payload, ids...) + err = fcmClient.Send(dataPayloadJSON, ids...) s.NoError(err) } -func (s *NotifierTestSuite) TestNotifyError() { +func (s *NotifierTestSuite) TestSendError() { expectedError := errors.New("error") - fcmPayload := getPayload() - ids := []string{"1"} - payload := fcmPayload - msg := make(map[string]string) - body := "body2" - msg["msg"] = body + ids := []string{"2"} + dataPayload := make(map[string]string) + dataPayload["from"] = "c" + dataPayload["to"] = "d" + dataPayloadByteArray, err := json.Marshal(dataPayload) + s.Require().NoError(err) + dataPayloadJSON := string(dataPayloadByteArray) - s.fcmClientMock.EXPECT().SetNotificationPayload(&fcmPayload).Times(1) - s.fcmClientMock.EXPECT().NewFcmRegIdsMsg(ids, msg).Times(1) + s.fcmClientMock.EXPECT().NewFcmRegIdsMsg(ids, dataPayload).Times(1) s.fcmClientMock.EXPECT().Send().Return(nil, expectedError).Times(1) fcmClient := Notification{s.fcmClientMock} - err := fcmClient.Send(body, payload, ids...) + err = fcmClient.Send(dataPayloadJSON, ids...) s.Equal(expectedError, err) } -func getPayload() fcm.NotificationPayload { - return fcm.NotificationPayload{Title: "Status - new message", Body: "sum"} +func (s *NotifierTestSuite) TestSendWithInvalidJSON() { + ids := []string{"3"} + dataPayloadJSON := "{a=b}" + + fcmClient := Notification{s.fcmClientMock} + + err := fcmClient.Send(dataPayloadJSON, ids...) + s.Require().Error(err) + + _, ok := err.(*json.SyntaxError) + s.True(ok) } diff --git a/vendor/github.com/NaySoftware/go-fcm/fcm.go b/vendor/github.com/NaySoftware/go-fcm/fcm.go index 97140a0bf..627eb24b8 100644 --- a/vendor/github.com/NaySoftware/go-fcm/fcm.go +++ b/vendor/github.com/NaySoftware/go-fcm/fcm.go @@ -55,6 +55,7 @@ type FcmMsg struct { RestrictedPackageName string `json:"restricted_package_name,omitempty"` DryRun bool `json:"dry_run,omitempty"` Condition string `json:"condition,omitempty"` + MutableContent bool `json:"mutable_content,omitempty"` } // FcmMsg represents fcm response message - (tokens and topics) @@ -179,6 +180,8 @@ func (this *FcmClient) sendOnce() (*FcmResponseStatus, error) { return fcmRespStatus, err } + fcmRespStatus.Err = string(body) + fcmRespStatus.StatusCode = response.StatusCode fcmRespStatus.RetryAfter = response.Header.Get(retry_after_header) @@ -313,6 +316,19 @@ func (this *FcmClient) SetDryRun(drun bool) *FcmClient { return this } +// SetMutableContent Currently for iOS 10+ devices only. On iOS, +// use this field to represent mutable-content in the APNs payload. +// When a notification is sent and this is set to true, the content +// of the notification can be modified before it is displayed, +// using a Notification Service app extension. +// This parameter will be ignored for Android and web. +func (this *FcmClient) SetMutableContent(mc bool) *FcmClient { + + this.Message.MutableContent = mc + + return this +} + // PrintResults prints the FcmResponseStatus results for fast using and debugging func (this *FcmResponseStatus) PrintResults() { fmt.Println("Status Code :", this.StatusCode)