Add tests for send notification & review feedback
This commit is contained in:
parent
28e06daf6d
commit
3c6b741f71
|
@ -117,9 +117,9 @@ func (c *Chat) MembersAsPublicKeys() ([]*ecdsa.PublicKey, error) {
|
||||||
|
|
||||||
func (c *Chat) JoinedMembersAsPublicKeys() ([]*ecdsa.PublicKey, error) {
|
func (c *Chat) JoinedMembersAsPublicKeys() ([]*ecdsa.PublicKey, error) {
|
||||||
var publicKeys []string
|
var publicKeys []string
|
||||||
for _, item := range c.Members {
|
for _, member := range c.Members {
|
||||||
if item.Joined {
|
if member.Joined {
|
||||||
publicKeys = append(publicKeys, item.ID)
|
publicKeys = append(publicKeys, member.ID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return stringSliceToPublicKeys(publicKeys, true)
|
return stringSliceToPublicKeys(publicKeys, true)
|
||||||
|
|
|
@ -302,6 +302,7 @@ func (m *Message) parseAudio() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// implement interface of https://github.com/status-im/markdown/blob/b9fe921681227b1dace4b56364e15edb3b698308/ast/node.go#L701
|
||||||
type MentionNodeVisitor struct {
|
type MentionNodeVisitor struct {
|
||||||
mentions []string
|
mentions []string
|
||||||
}
|
}
|
||||||
|
|
|
@ -248,11 +248,11 @@ func (m *MessageHandler) HandleSyncInstallationContact(state *ReceivedMessageSta
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MessageHandler) HandleSyncInstallationPublicChat(state *ReceivedMessageState, message protobuf.SyncInstallationPublicChat) (bool, error) {
|
func (m *MessageHandler) HandleSyncInstallationPublicChat(state *ReceivedMessageState, message protobuf.SyncInstallationPublicChat) bool {
|
||||||
chatID := message.Id
|
chatID := message.Id
|
||||||
_, ok := state.AllChats[chatID]
|
_, ok := state.AllChats[chatID]
|
||||||
if ok {
|
if ok {
|
||||||
return false, nil
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
chat := CreatePublicChat(chatID, state.Timesource)
|
chat := CreatePublicChat(chatID, state.Timesource)
|
||||||
|
@ -260,7 +260,7 @@ func (m *MessageHandler) HandleSyncInstallationPublicChat(state *ReceivedMessage
|
||||||
state.AllChats[chat.ID] = &chat
|
state.AllChats[chat.ID] = &chat
|
||||||
state.ModifiedChats[chat.ID] = true
|
state.ModifiedChats[chat.ID] = true
|
||||||
|
|
||||||
return true, nil
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MessageHandler) HandleContactUpdate(state *ReceivedMessageState, message protobuf.ContactUpdate) error {
|
func (m *MessageHandler) HandleContactUpdate(state *ReceivedMessageState, message protobuf.ContactUpdate) error {
|
||||||
|
|
|
@ -2274,11 +2274,7 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte
|
||||||
|
|
||||||
p := msg.ParsedMessage.Interface().(protobuf.SyncInstallationPublicChat)
|
p := msg.ParsedMessage.Interface().(protobuf.SyncInstallationPublicChat)
|
||||||
logger.Debug("Handling SyncInstallationPublicChat", zap.Any("message", p))
|
logger.Debug("Handling SyncInstallationPublicChat", zap.Any("message", p))
|
||||||
added, err := m.handler.HandleSyncInstallationPublicChat(messageState, p)
|
added := m.handler.HandleSyncInstallationPublicChat(messageState, p)
|
||||||
if err != nil {
|
|
||||||
logger.Warn("failed to handle SyncInstallationPublicChat", zap.Error(err))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// We re-register as we want to receive mentions from the newly joined public chat
|
// We re-register as we want to receive mentions from the newly joined public chat
|
||||||
if added {
|
if added {
|
||||||
|
|
|
@ -174,9 +174,7 @@ func init() {
|
||||||
proto.RegisterType((*ApplicationMetadataMessage)(nil), "protobuf.ApplicationMetadataMessage")
|
proto.RegisterType((*ApplicationMetadataMessage)(nil), "protobuf.ApplicationMetadataMessage")
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() { proto.RegisterFile("application_metadata_message.proto", fileDescriptor_ad09a6406fcf24c7) }
|
||||||
proto.RegisterFile("application_metadata_message.proto", fileDescriptor_ad09a6406fcf24c7)
|
|
||||||
}
|
|
||||||
|
|
||||||
var fileDescriptor_ad09a6406fcf24c7 = []byte{
|
var fileDescriptor_ad09a6406fcf24c7 = []byte{
|
||||||
// 493 bytes of a gzipped FileDescriptorProto
|
// 493 bytes of a gzipped FileDescriptorProto
|
||||||
|
|
|
@ -123,9 +123,7 @@ func init() {
|
||||||
proto.RegisterType((*GroupChatInvitation)(nil), "protobuf.GroupChatInvitation")
|
proto.RegisterType((*GroupChatInvitation)(nil), "protobuf.GroupChatInvitation")
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() { proto.RegisterFile("group_chat_invitation.proto", fileDescriptor_a6a73333de6a8ebe) }
|
||||||
proto.RegisterFile("group_chat_invitation.proto", fileDescriptor_a6a73333de6a8ebe)
|
|
||||||
}
|
|
||||||
|
|
||||||
var fileDescriptor_a6a73333de6a8ebe = []byte{
|
var fileDescriptor_a6a73333de6a8ebe = []byte{
|
||||||
// 234 bytes of a gzipped FileDescriptorProto
|
// 234 bytes of a gzipped FileDescriptorProto
|
||||||
|
|
|
@ -335,9 +335,7 @@ func init() {
|
||||||
proto.RegisterType((*SyncInstallation)(nil), "protobuf.SyncInstallation")
|
proto.RegisterType((*SyncInstallation)(nil), "protobuf.SyncInstallation")
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() { proto.RegisterFile("pairing.proto", fileDescriptor_d61ab7221f0b5518) }
|
||||||
proto.RegisterFile("pairing.proto", fileDescriptor_d61ab7221f0b5518)
|
|
||||||
}
|
|
||||||
|
|
||||||
var fileDescriptor_d61ab7221f0b5518 = []byte{
|
var fileDescriptor_d61ab7221f0b5518 = []byte{
|
||||||
// 397 bytes of a gzipped FileDescriptorProto
|
// 397 bytes of a gzipped FileDescriptorProto
|
||||||
|
|
|
@ -566,6 +566,7 @@ type PushNotification struct {
|
||||||
InstallationId string `protobuf:"bytes,4,opt,name=installation_id,json=installationId,proto3" json:"installation_id,omitempty"`
|
InstallationId string `protobuf:"bytes,4,opt,name=installation_id,json=installationId,proto3" json:"installation_id,omitempty"`
|
||||||
Message []byte `protobuf:"bytes,5,opt,name=message,proto3" json:"message,omitempty"`
|
Message []byte `protobuf:"bytes,5,opt,name=message,proto3" json:"message,omitempty"`
|
||||||
Type PushNotification_PushNotificationType `protobuf:"varint,6,opt,name=type,proto3,enum=protobuf.PushNotification_PushNotificationType" json:"type,omitempty"`
|
Type PushNotification_PushNotificationType `protobuf:"varint,6,opt,name=type,proto3,enum=protobuf.PushNotification_PushNotificationType" json:"type,omitempty"`
|
||||||
|
Author []byte `protobuf:"bytes,7,opt,name=author,proto3" json:"author,omitempty"`
|
||||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||||
XXX_unrecognized []byte `json:"-"`
|
XXX_unrecognized []byte `json:"-"`
|
||||||
XXX_sizecache int32 `json:"-"`
|
XXX_sizecache int32 `json:"-"`
|
||||||
|
@ -638,6 +639,13 @@ func (m *PushNotification) GetType() PushNotification_PushNotificationType {
|
||||||
return PushNotification_UNKNOWN_PUSH_NOTIFICATION_TYPE
|
return PushNotification_UNKNOWN_PUSH_NOTIFICATION_TYPE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *PushNotification) GetAuthor() []byte {
|
||||||
|
if m != nil {
|
||||||
|
return m.Author
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type PushNotificationRequest struct {
|
type PushNotificationRequest struct {
|
||||||
Requests []*PushNotification `protobuf:"bytes,1,rep,name=requests,proto3" json:"requests,omitempty"`
|
Requests []*PushNotification `protobuf:"bytes,1,rep,name=requests,proto3" json:"requests,omitempty"`
|
||||||
MessageId []byte `protobuf:"bytes,2,opt,name=message_id,json=messageId,proto3" json:"message_id,omitempty"`
|
MessageId []byte `protobuf:"bytes,2,opt,name=message_id,json=messageId,proto3" json:"message_id,omitempty"`
|
||||||
|
@ -815,67 +823,68 @@ func init() {
|
||||||
func init() { proto.RegisterFile("push_notifications.proto", fileDescriptor_200acd86044eaa5d) }
|
func init() { proto.RegisterFile("push_notifications.proto", fileDescriptor_200acd86044eaa5d) }
|
||||||
|
|
||||||
var fileDescriptor_200acd86044eaa5d = []byte{
|
var fileDescriptor_200acd86044eaa5d = []byte{
|
||||||
// 990 bytes of a gzipped FileDescriptorProto
|
// 1002 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x55, 0x4d, 0x6f, 0xe3, 0x44,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x55, 0xdd, 0x6e, 0xe3, 0x44,
|
||||||
0x18, 0xc6, 0x4e, 0xda, 0x24, 0x6f, 0xd2, 0xd4, 0x1d, 0xf5, 0xc3, 0x14, 0xba, 0x04, 0x03, 0x22,
|
0x14, 0xc6, 0x4e, 0xda, 0x24, 0x27, 0x69, 0x9a, 0x8e, 0xfa, 0x63, 0x0a, 0x5d, 0x82, 0x01, 0x11,
|
||||||
0xea, 0x21, 0xa0, 0x22, 0xb1, 0x2b, 0xb8, 0x10, 0x52, 0xa7, 0x6b, 0xb5, 0xb1, 0xc3, 0xc4, 0x65,
|
0xf5, 0xa2, 0xa0, 0x22, 0xb1, 0x2b, 0xb8, 0x21, 0xa4, 0x6e, 0xd7, 0x6a, 0x63, 0x87, 0x89, 0xcb,
|
||||||
0xb5, 0x12, 0xd2, 0xc8, 0xb1, 0x27, 0xad, 0x55, 0xd7, 0x36, 0x1e, 0xa7, 0x28, 0x37, 0x7e, 0x00,
|
0x6a, 0x25, 0xa4, 0x91, 0x9b, 0x4c, 0x5b, 0xab, 0xae, 0xc7, 0x78, 0xc6, 0x45, 0xb9, 0xe3, 0x01,
|
||||||
0x17, 0xae, 0x9c, 0xf8, 0x0d, 0xfc, 0x0d, 0xfe, 0x14, 0xf2, 0xd8, 0xce, 0xba, 0x8d, 0x9b, 0x16,
|
0xb8, 0xe1, 0x96, 0x2b, 0x9e, 0x81, 0x57, 0xe2, 0x45, 0x90, 0xc7, 0x76, 0xd6, 0x6d, 0xdc, 0xb4,
|
||||||
0x69, 0x4f, 0xc9, 0x3c, 0xef, 0xc7, 0xcc, 0xfb, 0xf1, 0x3c, 0x06, 0x39, 0x9c, 0xb3, 0x6b, 0xe2,
|
0x48, 0x7b, 0x95, 0x9c, 0x6f, 0xce, 0x39, 0x33, 0xe7, 0xe7, 0xfb, 0x0c, 0x5a, 0x18, 0xf3, 0x6b,
|
||||||
0x07, 0xb1, 0x3b, 0x73, 0x6d, 0x2b, 0x76, 0x03, 0x9f, 0xf5, 0xc2, 0x28, 0x88, 0x03, 0x54, 0xe7,
|
0x12, 0x30, 0xe1, 0x5d, 0x7a, 0x13, 0x57, 0x78, 0x2c, 0xe0, 0x07, 0x61, 0xc4, 0x04, 0x43, 0x75,
|
||||||
0x3f, 0xd3, 0xf9, 0x4c, 0xf9, 0x7b, 0x03, 0x3e, 0x1e, 0xcf, 0xd9, 0xb5, 0x5e, 0xf0, 0xc2, 0xf4,
|
0xf9, 0x73, 0x11, 0x5f, 0xea, 0x7f, 0xaf, 0xc0, 0xc7, 0xa3, 0x98, 0x5f, 0x5b, 0x05, 0x2f, 0x4c,
|
||||||
0xca, 0x65, 0x71, 0xc4, 0xff, 0x23, 0x03, 0x20, 0x0e, 0x6e, 0xa8, 0x4f, 0xe2, 0x45, 0x48, 0x65,
|
0xaf, 0x3c, 0x2e, 0x22, 0xf9, 0x1f, 0xd9, 0x00, 0x82, 0xdd, 0xd0, 0x80, 0x88, 0x59, 0x48, 0x35,
|
||||||
0xa1, 0x23, 0x74, 0xdb, 0x27, 0x5f, 0xf7, 0xf2, 0xf8, 0xde, 0xba, 0xd8, 0x9e, 0x99, 0x04, 0x9a,
|
0xa5, 0xab, 0xf4, 0xda, 0x87, 0x5f, 0x1f, 0xe4, 0xf1, 0x07, 0xcb, 0x62, 0x0f, 0x9c, 0x24, 0xd0,
|
||||||
0x8b, 0x90, 0xe2, 0x46, 0x9c, 0xff, 0x45, 0x9f, 0x42, 0xcb, 0xa1, 0x77, 0xae, 0x4d, 0x09, 0xc7,
|
0x99, 0x85, 0x14, 0x37, 0x44, 0xfe, 0x17, 0x7d, 0x0a, 0xad, 0x29, 0xbd, 0xf3, 0x26, 0x94, 0x48,
|
||||||
0x64, 0xb1, 0x23, 0x74, 0x1b, 0xb8, 0x99, 0x62, 0x3c, 0x02, 0x7d, 0x09, 0xdb, 0xae, 0xcf, 0x62,
|
0x4c, 0x53, 0xbb, 0x4a, 0xaf, 0x81, 0x9b, 0x29, 0x26, 0x23, 0xd0, 0x97, 0xb0, 0xee, 0x05, 0x5c,
|
||||||
0xcb, 0xf3, 0x78, 0x1e, 0xe2, 0x3a, 0x72, 0x85, 0x7b, 0xb5, 0x8b, 0xb0, 0xe6, 0x24, 0xb9, 0x2c,
|
0xb8, 0xbe, 0x2f, 0xf3, 0x10, 0x6f, 0xaa, 0x55, 0xa4, 0x57, 0xbb, 0x08, 0x9b, 0xd3, 0x24, 0x97,
|
||||||
0xdb, 0xa6, 0x8c, 0x65, 0xb9, 0xaa, 0x69, 0xae, 0x14, 0x4b, 0x73, 0xc9, 0x50, 0xa3, 0xbe, 0x35,
|
0x3b, 0x99, 0x50, 0xce, 0xb3, 0x5c, 0xd5, 0x34, 0x57, 0x8a, 0xa5, 0xb9, 0x34, 0xa8, 0xd1, 0xc0,
|
||||||
0xf5, 0xa8, 0x23, 0x6f, 0x74, 0x84, 0x6e, 0x1d, 0xe7, 0xc7, 0xc4, 0x72, 0x47, 0x23, 0xe6, 0x06,
|
0xbd, 0xf0, 0xe9, 0x54, 0x5b, 0xe9, 0x2a, 0xbd, 0x3a, 0xce, 0xcd, 0xe4, 0xe4, 0x8e, 0x46, 0xdc,
|
||||||
0xbe, 0xbc, 0xd9, 0x11, 0xba, 0x55, 0x9c, 0x1f, 0x51, 0x17, 0x24, 0xcb, 0xf3, 0x82, 0xdf, 0xa8,
|
0x63, 0x81, 0xb6, 0xda, 0x55, 0x7a, 0x55, 0x9c, 0x9b, 0xa8, 0x07, 0x1d, 0xd7, 0xf7, 0xd9, 0x6f,
|
||||||
0x43, 0x6e, 0xe8, 0x82, 0x78, 0x2e, 0x8b, 0xe5, 0x5a, 0xa7, 0xd2, 0x6d, 0xe1, 0x76, 0x86, 0x9f,
|
0x74, 0x4a, 0x6e, 0xe8, 0x8c, 0xf8, 0x1e, 0x17, 0x5a, 0xad, 0x5b, 0xe9, 0xb5, 0x70, 0x3b, 0xc3,
|
||||||
0xd3, 0xc5, 0x85, 0xcb, 0x62, 0x74, 0x0c, 0x3b, 0x53, 0x2f, 0xb0, 0x6f, 0xa8, 0x43, 0xec, 0x6b,
|
0x4f, 0xe9, 0xec, 0xcc, 0xe3, 0x02, 0xed, 0xc3, 0xc6, 0x85, 0xcf, 0x26, 0x37, 0x74, 0x4a, 0x26,
|
||||||
0x2b, 0x4e, 0x5d, 0xeb, 0xdc, 0x75, 0x3b, 0x33, 0x0c, 0xae, 0xad, 0x98, 0xfb, 0xbe, 0x00, 0x98,
|
0xd7, 0xae, 0x48, 0x5d, 0xeb, 0xd2, 0x75, 0x3d, 0x3b, 0x18, 0x5c, 0xbb, 0x42, 0xfa, 0xbe, 0x00,
|
||||||
0xfb, 0x11, 0xef, 0x0f, 0x8d, 0xe4, 0x06, 0x7f, 0x4c, 0x01, 0x41, 0xbb, 0xb0, 0x71, 0x15, 0x59,
|
0x88, 0x83, 0x48, 0xf6, 0x87, 0x46, 0x5a, 0x43, 0x3e, 0xa6, 0x80, 0xa0, 0x4d, 0x58, 0xb9, 0x8a,
|
||||||
0x7e, 0x2c, 0x43, 0x47, 0xe8, 0xb6, 0x70, 0x7a, 0x40, 0x2f, 0x41, 0xe6, 0x77, 0x92, 0x59, 0x14,
|
0xdc, 0x40, 0x68, 0xd0, 0x55, 0x7a, 0x2d, 0x9c, 0x1a, 0xe8, 0x25, 0x68, 0xf2, 0x4e, 0x72, 0x19,
|
||||||
0xdc, 0x12, 0x3b, 0xf0, 0x63, 0xcb, 0x8e, 0x19, 0x09, 0x7c, 0x6f, 0x21, 0x37, 0x79, 0x8e, 0x3d,
|
0xb1, 0x5b, 0x32, 0x61, 0x81, 0x70, 0x27, 0x82, 0x13, 0x16, 0xf8, 0x33, 0xad, 0x29, 0x73, 0x6c,
|
||||||
0x6e, 0x1f, 0x46, 0xc1, 0xed, 0x20, 0xb3, 0x1a, 0xbe, 0xb7, 0x40, 0x1f, 0x41, 0xc3, 0x0a, 0x7d,
|
0xc9, 0xf3, 0xe3, 0x88, 0xdd, 0x0e, 0xb2, 0x53, 0x3b, 0xf0, 0x67, 0xe8, 0x23, 0x68, 0xb8, 0x61,
|
||||||
0x12, 0x07, 0xa1, 0x6b, 0xcb, 0x2d, 0xde, 0x98, 0xba, 0x15, 0xfa, 0x66, 0x72, 0x46, 0x5f, 0x40,
|
0x40, 0x04, 0x0b, 0xbd, 0x89, 0xd6, 0x92, 0x8d, 0xa9, 0xbb, 0x61, 0xe0, 0x24, 0x36, 0xfa, 0x02,
|
||||||
0x9b, 0x3f, 0x8f, 0xdc, 0x52, 0x9f, 0x2f, 0x86, 0xbc, 0xc5, 0x73, 0x6d, 0x71, 0x74, 0x94, 0x81,
|
0xda, 0xf2, 0x79, 0xe4, 0x96, 0x06, 0x72, 0x31, 0xb4, 0x35, 0x99, 0x6b, 0x4d, 0xa2, 0xc3, 0x0c,
|
||||||
0xe8, 0x7b, 0x38, 0xcc, 0x1b, 0x91, 0x3b, 0x16, 0xea, 0x6c, 0xf3, 0x3a, 0x0f, 0x32, 0x8f, 0x3c,
|
0x44, 0xdf, 0xc3, 0x6e, 0xde, 0x88, 0xdc, 0xb1, 0x50, 0x67, 0x5b, 0xd6, 0xb9, 0x93, 0x79, 0xe4,
|
||||||
0x28, 0xaf, 0x57, 0x19, 0x42, 0x63, 0xb9, 0x00, 0x68, 0x1f, 0xd0, 0xa5, 0x7e, 0xae, 0x1b, 0x6f,
|
0x41, 0x79, 0xbd, 0xfa, 0x31, 0x34, 0xe6, 0x0b, 0x80, 0xb6, 0x01, 0x9d, 0x5b, 0xa7, 0x96, 0xfd,
|
||||||
0x74, 0x62, 0x1a, 0xe7, 0xaa, 0x4e, 0xcc, 0xb7, 0x63, 0x55, 0xfa, 0x00, 0x6d, 0x41, 0xa3, 0x3f,
|
0xc6, 0x22, 0x8e, 0x7d, 0x6a, 0x58, 0xc4, 0x79, 0x3b, 0x32, 0x3a, 0x1f, 0xa0, 0x35, 0x68, 0xf4,
|
||||||
0xce, 0x30, 0x49, 0x40, 0x08, 0xda, 0x43, 0x0d, 0xab, 0x3f, 0xf6, 0x27, 0x6a, 0x86, 0x89, 0xca,
|
0x47, 0x19, 0xd6, 0x51, 0x10, 0x82, 0xf6, 0xb1, 0x89, 0x8d, 0x1f, 0xfb, 0x63, 0x23, 0xc3, 0x54,
|
||||||
0x3f, 0x22, 0x7c, 0xbe, 0x6e, 0xcd, 0x30, 0x65, 0x61, 0xe0, 0x33, 0x9a, 0x0c, 0x94, 0xcd, 0xf9,
|
0xfd, 0x1f, 0x15, 0x3e, 0x5f, 0xb6, 0x66, 0x98, 0xf2, 0x90, 0x05, 0x9c, 0x26, 0x03, 0xe5, 0xb1,
|
||||||
0xe8, 0xf9, 0x9e, 0xd6, 0x71, 0x7e, 0x44, 0x3a, 0x6c, 0xd0, 0x28, 0x0a, 0x22, 0xbe, 0x6c, 0xed,
|
0x1c, 0xbd, 0xdc, 0xd3, 0x3a, 0xce, 0x4d, 0x64, 0xc1, 0x0a, 0x8d, 0x22, 0x16, 0xc9, 0x65, 0x6b,
|
||||||
0x93, 0x57, 0xcf, 0xdb, 0xdf, 0x3c, 0x71, 0x4f, 0x4d, 0x62, 0xf9, 0x1e, 0xa7, 0x69, 0xd0, 0x11,
|
0x1f, 0xbe, 0x7a, 0xde, 0xfe, 0xe6, 0x89, 0x0f, 0x8c, 0x24, 0x56, 0xee, 0x71, 0x9a, 0x06, 0xed,
|
||||||
0x40, 0x44, 0x7f, 0x9d, 0x53, 0x16, 0xe7, 0xbb, 0xd9, 0xc2, 0x8d, 0x0c, 0xd1, 0x1c, 0xe5, 0x77,
|
0x01, 0x44, 0xf4, 0xd7, 0x98, 0x72, 0x91, 0xef, 0x66, 0x0b, 0x37, 0x32, 0xc4, 0x9c, 0xea, 0xbf,
|
||||||
0x01, 0x1a, 0xcb, 0x98, 0x62, 0xe9, 0x2a, 0xc6, 0x06, 0xce, 0x4b, 0xdf, 0x83, 0x9d, 0x51, 0xff,
|
0x2b, 0xd0, 0x98, 0xc7, 0x14, 0x4b, 0x37, 0x30, 0xb6, 0x71, 0x5e, 0xfa, 0x16, 0x6c, 0x0c, 0xfb,
|
||||||
0x62, 0x68, 0xe0, 0x91, 0x7a, 0x4a, 0x46, 0xea, 0x64, 0xd2, 0x3f, 0x53, 0x25, 0x01, 0xed, 0x82,
|
0x67, 0xc7, 0x36, 0x1e, 0x1a, 0x47, 0x64, 0x68, 0x8c, 0xc7, 0xfd, 0x13, 0xa3, 0xa3, 0xa0, 0x4d,
|
||||||
0xf4, 0xb3, 0x8a, 0x27, 0x9a, 0xa1, 0x93, 0x91, 0x36, 0x19, 0xf5, 0xcd, 0xc1, 0x6b, 0x49, 0x44,
|
0xe8, 0xfc, 0x6c, 0xe0, 0xb1, 0x69, 0x5b, 0x64, 0x68, 0x8e, 0x87, 0x7d, 0x67, 0xf0, 0xba, 0xa3,
|
||||||
0x87, 0xb0, 0x7f, 0xa9, 0x4f, 0x2e, 0xc7, 0x63, 0x03, 0x9b, 0xea, 0x69, 0xb1, 0x87, 0x95, 0xa4,
|
0xa2, 0x5d, 0xd8, 0x3e, 0xb7, 0xc6, 0xe7, 0xa3, 0x91, 0x8d, 0x1d, 0xe3, 0xa8, 0xd8, 0xc3, 0x4a,
|
||||||
0x69, 0x9a, 0x6e, 0xaa, 0x58, 0xef, 0x5f, 0xa4, 0x37, 0x48, 0x55, 0x65, 0x0e, 0x72, 0xb6, 0x0d,
|
0xd2, 0x34, 0xd3, 0x72, 0x0c, 0x6c, 0xf5, 0xcf, 0xd2, 0x1b, 0x3a, 0x55, 0x3d, 0x06, 0x2d, 0xdb,
|
||||||
0x83, 0xc0, 0xa1, 0x7d, 0xe7, 0x8e, 0x46, 0xb1, 0xcb, 0x68, 0x32, 0x45, 0xf4, 0x16, 0xf6, 0x57,
|
0x86, 0x01, 0x9b, 0xd2, 0xfe, 0xf4, 0x8e, 0x46, 0xc2, 0xe3, 0x34, 0x99, 0x22, 0x7a, 0x0b, 0xdb,
|
||||||
0x94, 0x81, 0xb8, 0xfe, 0x2c, 0x90, 0x85, 0x4e, 0xa5, 0xdb, 0x3c, 0xf9, 0xec, 0xf1, 0xf6, 0xfc,
|
0x0b, 0xca, 0x40, 0xbc, 0xe0, 0x92, 0x69, 0x4a, 0xb7, 0xd2, 0x6b, 0x1e, 0x7e, 0xf6, 0x78, 0x7b,
|
||||||
0x34, 0xa7, 0xd1, 0x42, 0xf3, 0x67, 0x01, 0xde, 0x0d, 0x1f, 0x98, 0x12, 0x54, 0x79, 0x05, 0x7b,
|
0x7e, 0x8a, 0x69, 0x34, 0x33, 0x83, 0x4b, 0x86, 0x37, 0xc3, 0x07, 0x47, 0x09, 0xaa, 0xbf, 0x82,
|
||||||
0xa5, 0x21, 0xe8, 0x13, 0x68, 0x86, 0xf3, 0xa9, 0xe7, 0xda, 0x09, 0xa3, 0x18, 0xbf, 0xa8, 0x85,
|
0xad, 0xd2, 0x10, 0xf4, 0x09, 0x34, 0xc3, 0xf8, 0xc2, 0xf7, 0x26, 0x09, 0xa3, 0xb8, 0xbc, 0xa8,
|
||||||
0x21, 0x85, 0xce, 0xe9, 0x82, 0x29, 0x7f, 0x88, 0xf0, 0xe1, 0xa3, 0xb7, 0xad, 0x10, 0x5d, 0x58,
|
0x85, 0x21, 0x85, 0x4e, 0xe9, 0x8c, 0xeb, 0x7f, 0xa8, 0xf0, 0xe1, 0xa3, 0xb7, 0x2d, 0x10, 0x5d,
|
||||||
0x25, 0x7a, 0x89, 0x68, 0x88, 0xa5, 0xa2, 0x71, 0x04, 0xf0, 0xee, 0x29, 0xf9, 0xf0, 0x96, 0x2f,
|
0x59, 0x24, 0x7a, 0x89, 0x68, 0xa8, 0xa5, 0xa2, 0xb1, 0x07, 0xf0, 0xee, 0x29, 0xf9, 0xf0, 0xe6,
|
||||||
0x29, 0x25, 0x7f, 0xb5, 0x94, 0xfc, 0x4b, 0xc2, 0x6e, 0x14, 0x09, 0xfb, 0xb8, 0xac, 0x1c, 0xc3,
|
0x2f, 0x29, 0x25, 0x7f, 0xb5, 0x94, 0xfc, 0x73, 0xc2, 0xae, 0x14, 0x09, 0xfb, 0xb8, 0xac, 0xec,
|
||||||
0x0e, 0xa3, 0xd1, 0x1d, 0x8d, 0x48, 0xe1, 0xfe, 0x1a, 0x8f, 0xdd, 0x4e, 0x0d, 0xe3, 0xfc, 0x15,
|
0xc3, 0x06, 0xa7, 0xd1, 0x1d, 0x8d, 0x48, 0xe1, 0xfe, 0x9a, 0x8c, 0x5d, 0x4f, 0x0f, 0x46, 0xf9,
|
||||||
0xca, 0x9f, 0x02, 0x1c, 0x95, 0xb6, 0x63, 0xb9, 0xed, 0x2f, 0xa1, 0xfa, 0x7f, 0x67, 0xc6, 0x03,
|
0x2b, 0xf4, 0x3f, 0x15, 0xd8, 0x2b, 0x6d, 0xc7, 0x7c, 0xdb, 0x5f, 0x42, 0xf5, 0xff, 0xce, 0x4c,
|
||||||
0x92, 0xfa, 0x6f, 0x29, 0x63, 0xd6, 0x15, 0xcd, 0x7b, 0xd4, 0xc2, 0x8d, 0x0c, 0xd1, 0x9c, 0x22,
|
0x06, 0x24, 0xf5, 0xdf, 0x52, 0xce, 0xdd, 0x2b, 0x9a, 0xf7, 0xa8, 0x85, 0x1b, 0x19, 0x62, 0x4e,
|
||||||
0x8b, 0x2a, 0xf7, 0x58, 0xa4, 0xfc, 0x2b, 0x82, 0xf4, 0x30, 0xf9, 0x73, 0x26, 0x73, 0x00, 0x35,
|
0x8b, 0x2c, 0xaa, 0xdc, 0x63, 0x91, 0xfe, 0xaf, 0x0a, 0x9d, 0x87, 0xc9, 0x9f, 0x33, 0x99, 0x1d,
|
||||||
0x2e, 0x1a, 0xcb, 0xdb, 0x36, 0x93, 0xe3, 0xd3, 0x93, 0x28, 0x99, 0x68, 0xb5, 0x74, 0xa2, 0x32,
|
0xa8, 0x49, 0xd1, 0x98, 0xdf, 0xb6, 0x9a, 0x98, 0x4f, 0x4f, 0xa2, 0x64, 0xa2, 0xd5, 0xd2, 0x89,
|
||||||
0xd4, 0xb2, 0xf7, 0x67, 0xa3, 0xc8, 0x8f, 0x68, 0x00, 0x55, 0xfe, 0xdd, 0xda, 0xe4, 0xbc, 0xff,
|
0x6a, 0x50, 0xcb, 0xde, 0x9f, 0x8d, 0x22, 0x37, 0xd1, 0x00, 0xaa, 0xf2, 0xbb, 0xb5, 0x2a, 0x79,
|
||||||
0xea, 0xf1, 0x26, 0xad, 0x00, 0x9c, 0xee, 0x3c, 0x58, 0x31, 0x61, 0xb7, 0xcc, 0x8a, 0x14, 0x78,
|
0xff, 0xd5, 0xe3, 0x4d, 0x5a, 0x00, 0x24, 0xdd, 0x65, 0x30, 0xda, 0x86, 0x55, 0x37, 0x16, 0xd7,
|
||||||
0x91, 0x13, 0x7b, 0x7c, 0x39, 0x79, 0x4d, 0x74, 0xc3, 0xd4, 0x86, 0xda, 0xa0, 0x6f, 0x26, 0xdc,
|
0x2c, 0xca, 0x86, 0x95, 0x59, 0xba, 0x03, 0x9b, 0x65, 0x51, 0x48, 0x87, 0x17, 0x39, 0xe1, 0x47,
|
||||||
0xcd, 0x48, 0xde, 0x84, 0xda, 0x3b, 0x6a, 0xf3, 0x83, 0x9e, 0x98, 0x25, 0x51, 0x09, 0xe1, 0x60,
|
0xe7, 0xe3, 0xd7, 0xc4, 0xb2, 0x1d, 0xf3, 0xd8, 0x1c, 0xf4, 0x9d, 0x84, 0xd3, 0x19, 0xf9, 0x9b,
|
||||||
0x55, 0x7c, 0xb8, 0x82, 0xa0, 0x6f, 0xa1, 0x9e, 0x89, 0x09, 0xcb, 0xc6, 0x7b, 0xb8, 0x46, 0xb1,
|
0x50, 0x7b, 0x47, 0x79, 0x69, 0x58, 0xc9, 0x71, 0x47, 0xd5, 0x43, 0xd8, 0x59, 0x14, 0x25, 0xa9,
|
||||||
0x96, 0xbe, 0x4f, 0x4c, 0x56, 0xf9, 0x4b, 0x84, 0xfd, 0xd5, 0x2b, 0xc3, 0x20, 0x8a, 0xd7, 0x48,
|
0x2c, 0xe8, 0x5b, 0xa8, 0x67, 0x22, 0xc3, 0xb3, 0xb1, 0xef, 0x2e, 0x51, 0xb2, 0xb9, 0xef, 0x13,
|
||||||
0xe7, 0x0f, 0xf7, 0xa5, 0xf3, 0x78, 0x9d, 0x74, 0x26, 0xa9, 0x4a, 0xc5, 0xf2, 0x7d, 0x4c, 0x59,
|
0x13, 0xd7, 0xff, 0x52, 0x61, 0x7b, 0xf1, 0xca, 0x90, 0x45, 0x62, 0x89, 0xa4, 0xfe, 0x70, 0x5f,
|
||||||
0xf9, 0xe5, 0x39, 0xa2, 0xba, 0x0d, 0xcd, 0x37, 0xd8, 0xd0, 0xcf, 0x8a, 0x5f, 0x94, 0x07, 0xe2,
|
0x52, 0xf7, 0x97, 0x49, 0x6a, 0x92, 0xaa, 0x54, 0x44, 0xdf, 0xc7, 0xf4, 0xf5, 0x5f, 0x9e, 0x23,
|
||||||
0x28, 0x26, 0x98, 0x6e, 0x98, 0x04, 0xab, 0x67, 0xda, 0xc4, 0x54, 0xb1, 0x7a, 0x2a, 0x55, 0x12,
|
0xb6, 0xeb, 0xd0, 0x7c, 0x83, 0x6d, 0xeb, 0xa4, 0xf8, 0xa5, 0x79, 0x20, 0x9a, 0x6a, 0x82, 0x59,
|
||||||
0xc1, 0x5c, 0x2d, 0x28, 0xa3, 0xda, 0xfd, 0xbe, 0x0a, 0x0f, 0x19, 0xf3, 0x1d, 0xd4, 0x22, 0x5e,
|
0xb6, 0x43, 0xb0, 0x71, 0x62, 0x8e, 0x1d, 0x03, 0x1b, 0x47, 0x9d, 0x4a, 0x22, 0xa4, 0x8b, 0x05,
|
||||||
0x3b, 0x93, 0x45, 0x3e, 0xad, 0xce, 0x53, 0x4d, 0xc2, 0x79, 0xc0, 0x74, 0x93, 0x7b, 0x7e, 0xf3,
|
0x65, 0x14, 0xbc, 0xdf, 0x57, 0xe5, 0x21, 0x93, 0xbe, 0x83, 0x5a, 0x24, 0x6b, 0xe7, 0x9a, 0x2a,
|
||||||
0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x65, 0x07, 0x55, 0xdb, 0xac, 0x09, 0x00, 0x00,
|
0xa7, 0xd5, 0x7d, 0xaa, 0x49, 0x38, 0x0f, 0xb8, 0x58, 0x95, 0x9e, 0xdf, 0xfc, 0x17, 0x00, 0x00,
|
||||||
|
0xff, 0xff, 0xd4, 0x90, 0x1f, 0x72, 0xc4, 0x09, 0x00, 0x00,
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,6 +74,7 @@ message PushNotification {
|
||||||
MESSAGE = 1;
|
MESSAGE = 1;
|
||||||
MENTION = 2;
|
MENTION = 2;
|
||||||
}
|
}
|
||||||
|
bytes author = 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
message PushNotificationRequest {
|
message PushNotificationRequest {
|
||||||
|
|
|
@ -49,7 +49,7 @@ const encryptedPayloadKeyLength = 16
|
||||||
const accessTokenKeyLength = 16
|
const accessTokenKeyLength = 16
|
||||||
const staleQueryTimeInSeconds = 86400
|
const staleQueryTimeInSeconds = 86400
|
||||||
const mentionInstallationID = "mention"
|
const mentionInstallationID = "mention"
|
||||||
const oneToOneChatIDLength = 65
|
const oneToOneChatIDLength = 132
|
||||||
|
|
||||||
// maxRegistrationRetries is the maximum number of attempts we do before giving up registering with a server
|
// maxRegistrationRetries is the maximum number of attempts we do before giving up registering with a server
|
||||||
const maxRegistrationRetries int64 = 12
|
const maxRegistrationRetries int64 = 12
|
||||||
|
@ -211,8 +211,6 @@ func (c *Client) Start() error {
|
||||||
return errors.New("can't start, missing message processor")
|
return errors.New("can't start, missing message processor")
|
||||||
}
|
}
|
||||||
|
|
||||||
c.config.Logger.Debug("starting push notification client", zap.Any("config", c.config))
|
|
||||||
|
|
||||||
err := c.loadLastPushNotificationRegistration()
|
err := c.loadLastPushNotificationRegistration()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -996,7 +994,7 @@ func (c *Client) handleDirectMessageSent(sentMessage *common.SentMessage) error
|
||||||
// If it's a public key, we use our own public key as chatID, which correspond to the chatID used by the other peer
|
// If it's a public key, we use our own public key as chatID, which correspond to the chatID used by the other peer
|
||||||
// otherwise we use the group chat ID
|
// otherwise we use the group chat ID
|
||||||
var chatID string
|
var chatID string
|
||||||
if len(chatID) == oneToOneChatIDLength {
|
if len(message.ChatId) == oneToOneChatIDLength {
|
||||||
chatID = types.EncodeHex(crypto.FromECDSAPub(&c.config.Identity.PublicKey))
|
chatID = types.EncodeHex(crypto.FromECDSAPub(&c.config.Identity.PublicKey))
|
||||||
} else {
|
} else {
|
||||||
// this is a group chat
|
// this is a group chat
|
||||||
|
@ -1350,6 +1348,7 @@ func (c *Client) sendNotification(publicKey *ecdsa.PublicKey, installationIDs []
|
||||||
// For now we set the ChatID to our own identity key, this will work fine for blocked users
|
// For now we set the ChatID to our own identity key, this will work fine for blocked users
|
||||||
// and muted 1-to-1 chats, but not for group chats.
|
// and muted 1-to-1 chats, but not for group chats.
|
||||||
ChatId: common.Shake256([]byte(chatID)),
|
ChatId: common.Shake256([]byte(chatID)),
|
||||||
|
Author: common.Shake256([]byte(types.EncodeHex(crypto.FromECDSAPub(&c.config.Identity.PublicKey)))),
|
||||||
AccessToken: i.AccessToken,
|
AccessToken: i.AccessToken,
|
||||||
PublicKey: common.HashPublicKey(publicKey),
|
PublicKey: common.HashPublicKey(publicKey),
|
||||||
InstallationId: i.InstallationID,
|
InstallationId: i.InstallationID,
|
||||||
|
|
|
@ -21,6 +21,8 @@ import (
|
||||||
const encryptedPayloadKeyLength = 16
|
const encryptedPayloadKeyLength = 16
|
||||||
const defaultGorushURL = "https://gorush.status.im"
|
const defaultGorushURL = "https://gorush.status.im"
|
||||||
|
|
||||||
|
var errUnhandledPushNotificationType = errors.New("unhandled push notification type")
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Enabled bool
|
Enabled bool
|
||||||
// Identity is our identity key
|
// Identity is our identity key
|
||||||
|
@ -56,7 +58,7 @@ func (s *Server) Start() error {
|
||||||
|
|
||||||
s.config.Logger.Info("starting push notification server")
|
s.config.Logger.Info("starting push notification server")
|
||||||
if s.config.Identity == nil {
|
if s.config.Identity == nil {
|
||||||
s.config.Logger.Info("Identity nil")
|
s.config.Logger.Debug("Identity nil")
|
||||||
// Pull identity from database
|
// Pull identity from database
|
||||||
identity, err := s.persistence.GetIdentity()
|
identity, err := s.persistence.GetIdentity()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -139,7 +141,7 @@ func (s *Server) HandlePushNotificationQuery(publicKey *ecdsa.PublicKey, message
|
||||||
func (s *Server) HandlePushNotificationRequest(publicKey *ecdsa.PublicKey,
|
func (s *Server) HandlePushNotificationRequest(publicKey *ecdsa.PublicKey,
|
||||||
messageID []byte,
|
messageID []byte,
|
||||||
request protobuf.PushNotificationRequest) error {
|
request protobuf.PushNotificationRequest) error {
|
||||||
s.config.Logger.Info("handling pn request", zap.Binary("message-id", messageID))
|
s.config.Logger.Debug("handling pn request", zap.Binary("message-id", messageID))
|
||||||
|
|
||||||
// This is at-most-once semantic for now
|
// This is at-most-once semantic for now
|
||||||
exists, err := s.persistence.PushNotificationExists(messageID)
|
exists, err := s.persistence.PushNotificationExists(messageID)
|
||||||
|
@ -148,7 +150,7 @@ func (s *Server) HandlePushNotificationRequest(publicKey *ecdsa.PublicKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
if exists {
|
if exists {
|
||||||
s.config.Logger.Info("already handled")
|
s.config.Logger.Debug("already handled")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,7 +306,7 @@ func (s *Server) validateRegistration(publicKey *ecdsa.PublicKey, payload []byte
|
||||||
// buildPushNotificationQueryResponse check if we have the client information and send them back
|
// buildPushNotificationQueryResponse check if we have the client information and send them back
|
||||||
func (s *Server) buildPushNotificationQueryResponse(query *protobuf.PushNotificationQuery) *protobuf.PushNotificationQueryResponse {
|
func (s *Server) buildPushNotificationQueryResponse(query *protobuf.PushNotificationQuery) *protobuf.PushNotificationQueryResponse {
|
||||||
|
|
||||||
s.config.Logger.Info("handling push notification query")
|
s.config.Logger.Debug("handling push notification query")
|
||||||
response := &protobuf.PushNotificationQueryResponse{}
|
response := &protobuf.PushNotificationQueryResponse{}
|
||||||
if query == nil || len(query.PublicKeys) == 0 {
|
if query == nil || len(query.PublicKeys) == 0 {
|
||||||
return response
|
return response
|
||||||
|
@ -349,6 +351,49 @@ func (s *Server) contains(list [][]byte, chatID []byte) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type reportResult struct {
|
||||||
|
sendNotification bool
|
||||||
|
report *protobuf.PushNotificationReport
|
||||||
|
}
|
||||||
|
|
||||||
|
// buildPushNotificationReport checks the request against the registration and
|
||||||
|
// returns whether we should send the notification and what the response should be
|
||||||
|
func (s *Server) buildPushNotificationReport(pn *protobuf.PushNotification, registration *protobuf.PushNotificationRegistration) (*reportResult, error) {
|
||||||
|
response := &reportResult{}
|
||||||
|
report := &protobuf.PushNotificationReport{
|
||||||
|
PublicKey: pn.PublicKey,
|
||||||
|
InstallationId: pn.InstallationId,
|
||||||
|
}
|
||||||
|
|
||||||
|
if pn.Type == protobuf.PushNotification_UNKNOWN_PUSH_NOTIFICATION_TYPE {
|
||||||
|
s.config.Logger.Warn("unhandled type")
|
||||||
|
return nil, errUnhandledPushNotificationType
|
||||||
|
}
|
||||||
|
|
||||||
|
if registration == nil {
|
||||||
|
s.config.Logger.Warn("empty registration")
|
||||||
|
report.Error = protobuf.PushNotificationReport_NOT_REGISTERED
|
||||||
|
} else if registration.AccessToken != pn.AccessToken {
|
||||||
|
s.config.Logger.Debug("invalid token")
|
||||||
|
report.Error = protobuf.PushNotificationReport_WRONG_TOKEN
|
||||||
|
} else if (s.isMessageNotification(pn) && !s.isValidMessageNotification(pn, registration)) || (s.isMentionNotification(pn) && !s.isValidMentionNotification(pn, registration)) {
|
||||||
|
s.config.Logger.Debug("filtered notification")
|
||||||
|
// We report as successful but don't send the notification
|
||||||
|
// for privacy reasons, as otherwise we would disclose that
|
||||||
|
// the sending client has been blocked or that the registering
|
||||||
|
// client has not joined a given public chat
|
||||||
|
report.Success = true
|
||||||
|
} else {
|
||||||
|
response.sendNotification = true
|
||||||
|
s.config.Logger.Debug("sending push notification")
|
||||||
|
report.Success = true
|
||||||
|
}
|
||||||
|
|
||||||
|
response.report = report
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
}
|
||||||
|
|
||||||
// buildPushNotificationRequestResponse will build a response
|
// buildPushNotificationRequestResponse will build a response
|
||||||
func (s *Server) buildPushNotificationRequestResponse(request *protobuf.PushNotificationRequest) (*protobuf.PushNotificationResponse, []*RequestAndRegistration) {
|
func (s *Server) buildPushNotificationRequestResponse(request *protobuf.PushNotificationRequest) (*protobuf.PushNotificationResponse, []*RequestAndRegistration) {
|
||||||
response := &protobuf.PushNotificationResponse{}
|
response := &protobuf.PushNotificationResponse{}
|
||||||
|
@ -363,49 +408,36 @@ func (s *Server) buildPushNotificationRequestResponse(request *protobuf.PushNoti
|
||||||
// collect successful requests & registrations
|
// collect successful requests & registrations
|
||||||
var requestAndRegistrations []*RequestAndRegistration
|
var requestAndRegistrations []*RequestAndRegistration
|
||||||
|
|
||||||
// TODO: this logic needs to be extracted and tested
|
|
||||||
for _, pn := range request.Requests {
|
for _, pn := range request.Requests {
|
||||||
registration, err := s.persistence.GetPushNotificationRegistrationByPublicKeyAndInstallationID(pn.PublicKey, pn.InstallationId)
|
registration, err := s.persistence.GetPushNotificationRegistrationByPublicKeyAndInstallationID(pn.PublicKey, pn.InstallationId)
|
||||||
report := &protobuf.PushNotificationReport{
|
var report *protobuf.PushNotificationReport
|
||||||
PublicKey: pn.PublicKey,
|
|
||||||
InstallationId: pn.InstallationId,
|
|
||||||
}
|
|
||||||
s.config.Logger.Info("registration and request", zap.Any("registration", registration), zap.Any("request", pn))
|
|
||||||
|
|
||||||
if pn.Type == protobuf.PushNotification_UNKNOWN_PUSH_NOTIFICATION_TYPE {
|
|
||||||
s.config.Logger.Warn("unhandled type")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.config.Logger.Error("failed to retrieve registration", zap.Error(err))
|
report = &protobuf.PushNotificationReport{
|
||||||
report.Error = protobuf.PushNotificationReport_UNKNOWN_ERROR_TYPE
|
PublicKey: pn.PublicKey,
|
||||||
} else if registration == nil {
|
Error: protobuf.PushNotificationReport_UNKNOWN_ERROR_TYPE,
|
||||||
s.config.Logger.Warn("empty registration")
|
InstallationId: pn.InstallationId,
|
||||||
report.Error = protobuf.PushNotificationReport_NOT_REGISTERED
|
}
|
||||||
} else if registration.AccessToken != pn.AccessToken {
|
|
||||||
s.config.Logger.Debug("invalid token")
|
|
||||||
report.Error = protobuf.PushNotificationReport_WRONG_TOKEN
|
|
||||||
} else if s.contains(registration.BlockedChatList, pn.ChatId) || (s.isMentionNotification(pn) && !s.isValidMentionNotification(pn, registration)) {
|
|
||||||
// We report as successful but don't send the notification
|
|
||||||
// for privacy reasons, as otherwise we would disclose that
|
|
||||||
// the sending client has been blocked or that the registering
|
|
||||||
// client has not joined a given public chat
|
|
||||||
report.Success = true
|
|
||||||
s.config.Logger.Debug("invalid token", zap.Bool("blocked", s.contains(registration.BlockedChatList, pn.ChatId)), zap.Bool("mention", (s.isMentionNotification(pn) && !s.isValidMentionNotification(pn, registration))))
|
|
||||||
} else {
|
} else {
|
||||||
s.config.Logger.Debug("sending push notification")
|
response, err := s.buildPushNotificationReport(pn, registration)
|
||||||
// For now we just assume that the notification will be successful
|
if err != nil {
|
||||||
requestAndRegistrations = append(requestAndRegistrations, &RequestAndRegistration{
|
s.config.Logger.Warn("unhandled type")
|
||||||
Request: pn,
|
continue
|
||||||
Registration: registration,
|
}
|
||||||
})
|
|
||||||
report.Success = true
|
if response.sendNotification {
|
||||||
|
requestAndRegistrations = append(requestAndRegistrations, &RequestAndRegistration{
|
||||||
|
Request: pn,
|
||||||
|
Registration: registration,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
report = response.report
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
response.Reports = append(response.Reports, report)
|
response.Reports = append(response.Reports, report)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.config.Logger.Info("built pn request")
|
s.config.Logger.Debug("built pn request")
|
||||||
if len(requestAndRegistrations) == 0 {
|
if len(requestAndRegistrations) == 0 {
|
||||||
s.config.Logger.Warn("no request and registration")
|
s.config.Logger.Warn("no request and registration")
|
||||||
return response, nil
|
return response, nil
|
||||||
|
@ -434,7 +466,7 @@ func (s *Server) listenToPublicKeyQueryTopic(hashedPublicKey []byte) error {
|
||||||
// buildPushNotificationRegistrationResponse will check the registration is valid, save it, and listen to the topic for the queries
|
// buildPushNotificationRegistrationResponse will check the registration is valid, save it, and listen to the topic for the queries
|
||||||
func (s *Server) buildPushNotificationRegistrationResponse(publicKey *ecdsa.PublicKey, payload []byte) *protobuf.PushNotificationRegistrationResponse {
|
func (s *Server) buildPushNotificationRegistrationResponse(publicKey *ecdsa.PublicKey, payload []byte) *protobuf.PushNotificationRegistrationResponse {
|
||||||
|
|
||||||
s.config.Logger.Info("handling push notification registration")
|
s.config.Logger.Debug("handling push notification registration")
|
||||||
response := &protobuf.PushNotificationRegistrationResponse{
|
response := &protobuf.PushNotificationRegistrationResponse{
|
||||||
RequestId: common.Shake256(payload),
|
RequestId: common.Shake256(payload),
|
||||||
}
|
}
|
||||||
|
@ -452,7 +484,7 @@ func (s *Server) buildPushNotificationRegistrationResponse(publicKey *ecdsa.Publ
|
||||||
}
|
}
|
||||||
|
|
||||||
if registration.Unregister {
|
if registration.Unregister {
|
||||||
s.config.Logger.Info("unregistering client")
|
s.config.Logger.Debug("unregistering client")
|
||||||
// We save an empty registration, only keeping version and installation-id
|
// We save an empty registration, only keeping version and installation-id
|
||||||
if err := s.persistence.UnregisterPushNotificationRegistration(common.HashPublicKey(publicKey), registration.InstallationId, registration.Version); err != nil {
|
if err := s.persistence.UnregisterPushNotificationRegistration(common.HashPublicKey(publicKey), registration.InstallationId, registration.Version); err != nil {
|
||||||
response.Error = protobuf.PushNotificationRegistrationResponse_INTERNAL_ERROR
|
response.Error = protobuf.PushNotificationRegistrationResponse_INTERNAL_ERROR
|
||||||
|
@ -474,7 +506,7 @@ func (s *Server) buildPushNotificationRegistrationResponse(publicKey *ecdsa.Publ
|
||||||
}
|
}
|
||||||
response.Success = true
|
response.Success = true
|
||||||
|
|
||||||
s.config.Logger.Info("handled push notification registration successfully")
|
s.config.Logger.Debug("handled push notification registration successfully")
|
||||||
|
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
@ -483,6 +515,23 @@ func (s *Server) isMentionNotification(pn *protobuf.PushNotification) bool {
|
||||||
return pn.Type == protobuf.PushNotification_MENTION
|
return pn.Type == protobuf.PushNotification_MENTION
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isValidMentionNotification checks:
|
||||||
|
// this is a mention
|
||||||
|
// mentions are enabled
|
||||||
|
// the user joined the public chat
|
||||||
|
// the author is not blocked
|
||||||
func (s *Server) isValidMentionNotification(pn *protobuf.PushNotification, registration *protobuf.PushNotificationRegistration) bool {
|
func (s *Server) isValidMentionNotification(pn *protobuf.PushNotification, registration *protobuf.PushNotificationRegistration) bool {
|
||||||
return s.isMentionNotification(pn) && !registration.BlockMentions && s.contains(registration.AllowedMentionsChatList, pn.ChatId)
|
return s.isMentionNotification(pn) && !registration.BlockMentions && s.contains(registration.AllowedMentionsChatList, pn.ChatId) && !s.contains(registration.BlockedChatList, pn.Author)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) isMessageNotification(pn *protobuf.PushNotification) bool {
|
||||||
|
return pn.Type == protobuf.PushNotification_MESSAGE
|
||||||
|
}
|
||||||
|
|
||||||
|
// isValidMentionNotification checks:
|
||||||
|
// this is a message
|
||||||
|
// the chat is not muted
|
||||||
|
// the author is not blocked
|
||||||
|
func (s *Server) isValidMessageNotification(pn *protobuf.PushNotification, registration *protobuf.PushNotificationRegistration) bool {
|
||||||
|
return s.isMessageNotification(pn) && !s.contains(registration.BlockedChatList, pn.ChatId) && !s.contains(registration.BlockedChatList, pn.Author)
|
||||||
}
|
}
|
||||||
|
|
|
@ -670,3 +670,210 @@ func (s *ServerSuite) TestPushNotificationDisabledMentions() {
|
||||||
s.Require().NotNil(pushNotificationResponse)
|
s.Require().NotNil(pushNotificationResponse)
|
||||||
s.Require().Nil(requestAndRegistrations)
|
s.Require().Nil(requestAndRegistrations)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *ServerSuite) TestBuildPushNotificationReport() {
|
||||||
|
accessToken := "a"
|
||||||
|
chatID := []byte("chat-id")
|
||||||
|
author := []byte("author")
|
||||||
|
blockedAuthor := []byte("blocked-author")
|
||||||
|
blockedChatID := []byte("blocked-chat-id")
|
||||||
|
blockedChatList := [][]byte{blockedChatID, blockedAuthor}
|
||||||
|
nonJoinedChatID := []byte("non-joined-chat-id")
|
||||||
|
allowedMentionsChatList := [][]byte{chatID}
|
||||||
|
validMessagePN := &protobuf.PushNotification{
|
||||||
|
Type: protobuf.PushNotification_MESSAGE,
|
||||||
|
ChatId: chatID,
|
||||||
|
Author: author,
|
||||||
|
AccessToken: accessToken,
|
||||||
|
}
|
||||||
|
validMentionPN := &protobuf.PushNotification{
|
||||||
|
Type: protobuf.PushNotification_MENTION,
|
||||||
|
ChatId: chatID,
|
||||||
|
AccessToken: accessToken,
|
||||||
|
}
|
||||||
|
validRegistration := &protobuf.PushNotificationRegistration{
|
||||||
|
AccessToken: accessToken,
|
||||||
|
BlockedChatList: blockedChatList,
|
||||||
|
AllowedMentionsChatList: allowedMentionsChatList,
|
||||||
|
}
|
||||||
|
blockedMentionsRegistration := &protobuf.PushNotificationRegistration{
|
||||||
|
AccessToken: accessToken,
|
||||||
|
BlockMentions: true,
|
||||||
|
BlockedChatList: blockedChatList,
|
||||||
|
AllowedMentionsChatList: allowedMentionsChatList,
|
||||||
|
}
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
pn *protobuf.PushNotification
|
||||||
|
registration *protobuf.PushNotificationRegistration
|
||||||
|
expectedError error
|
||||||
|
expectedResponse *reportResult
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "valid message",
|
||||||
|
pn: validMessagePN,
|
||||||
|
registration: validRegistration,
|
||||||
|
expectedResponse: &reportResult{
|
||||||
|
sendNotification: true,
|
||||||
|
report: &protobuf.PushNotificationReport{
|
||||||
|
Success: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "valid mention",
|
||||||
|
pn: validMentionPN,
|
||||||
|
registration: validRegistration,
|
||||||
|
expectedResponse: &reportResult{
|
||||||
|
sendNotification: true,
|
||||||
|
report: &protobuf.PushNotificationReport{
|
||||||
|
Success: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "unknow push notification",
|
||||||
|
pn: &protobuf.PushNotification{
|
||||||
|
ChatId: chatID,
|
||||||
|
AccessToken: accessToken,
|
||||||
|
},
|
||||||
|
registration: validRegistration,
|
||||||
|
expectedError: errUnhandledPushNotificationType,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "empty registration",
|
||||||
|
pn: validMessagePN,
|
||||||
|
registration: nil,
|
||||||
|
expectedResponse: &reportResult{
|
||||||
|
sendNotification: false,
|
||||||
|
report: &protobuf.PushNotificationReport{
|
||||||
|
Success: false,
|
||||||
|
Error: protobuf.PushNotificationReport_NOT_REGISTERED,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid access token message",
|
||||||
|
pn: &protobuf.PushNotification{
|
||||||
|
Type: protobuf.PushNotification_MESSAGE,
|
||||||
|
Author: author,
|
||||||
|
ChatId: chatID,
|
||||||
|
AccessToken: "invalid",
|
||||||
|
},
|
||||||
|
registration: validRegistration,
|
||||||
|
expectedResponse: &reportResult{
|
||||||
|
sendNotification: false,
|
||||||
|
report: &protobuf.PushNotificationReport{
|
||||||
|
Success: false,
|
||||||
|
Error: protobuf.PushNotificationReport_WRONG_TOKEN,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid access token mention",
|
||||||
|
pn: &protobuf.PushNotification{
|
||||||
|
Type: protobuf.PushNotification_MENTION,
|
||||||
|
Author: author,
|
||||||
|
ChatId: chatID,
|
||||||
|
AccessToken: "invalid",
|
||||||
|
},
|
||||||
|
registration: validRegistration,
|
||||||
|
expectedResponse: &reportResult{
|
||||||
|
sendNotification: false,
|
||||||
|
report: &protobuf.PushNotificationReport{
|
||||||
|
Success: false,
|
||||||
|
Error: protobuf.PushNotificationReport_WRONG_TOKEN,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "blocked chat list message",
|
||||||
|
pn: &protobuf.PushNotification{
|
||||||
|
Type: protobuf.PushNotification_MESSAGE,
|
||||||
|
ChatId: blockedChatID,
|
||||||
|
Author: author,
|
||||||
|
AccessToken: accessToken,
|
||||||
|
},
|
||||||
|
registration: validRegistration,
|
||||||
|
expectedResponse: &reportResult{
|
||||||
|
sendNotification: false,
|
||||||
|
report: &protobuf.PushNotificationReport{
|
||||||
|
Success: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "blocked group chat message",
|
||||||
|
pn: &protobuf.PushNotification{
|
||||||
|
Type: protobuf.PushNotification_MESSAGE,
|
||||||
|
Author: blockedAuthor,
|
||||||
|
ChatId: chatID,
|
||||||
|
AccessToken: accessToken,
|
||||||
|
},
|
||||||
|
registration: validRegistration,
|
||||||
|
expectedResponse: &reportResult{
|
||||||
|
sendNotification: false,
|
||||||
|
report: &protobuf.PushNotificationReport{
|
||||||
|
Success: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "blocked chat list mention",
|
||||||
|
pn: &protobuf.PushNotification{
|
||||||
|
Type: protobuf.PushNotification_MENTION,
|
||||||
|
Author: blockedAuthor,
|
||||||
|
ChatId: chatID,
|
||||||
|
AccessToken: accessToken,
|
||||||
|
},
|
||||||
|
registration: validRegistration,
|
||||||
|
expectedResponse: &reportResult{
|
||||||
|
sendNotification: false,
|
||||||
|
report: &protobuf.PushNotificationReport{
|
||||||
|
Success: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "blocked mentions",
|
||||||
|
pn: &protobuf.PushNotification{
|
||||||
|
Type: protobuf.PushNotification_MENTION,
|
||||||
|
Author: author,
|
||||||
|
ChatId: chatID,
|
||||||
|
AccessToken: accessToken,
|
||||||
|
},
|
||||||
|
registration: blockedMentionsRegistration,
|
||||||
|
expectedResponse: &reportResult{
|
||||||
|
sendNotification: false,
|
||||||
|
report: &protobuf.PushNotificationReport{
|
||||||
|
Success: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "not in allowed mention chat list",
|
||||||
|
pn: &protobuf.PushNotification{
|
||||||
|
Type: protobuf.PushNotification_MENTION,
|
||||||
|
Author: author,
|
||||||
|
ChatId: nonJoinedChatID,
|
||||||
|
AccessToken: accessToken,
|
||||||
|
},
|
||||||
|
registration: validRegistration,
|
||||||
|
expectedResponse: &reportResult{
|
||||||
|
sendNotification: false,
|
||||||
|
report: &protobuf.PushNotificationReport{
|
||||||
|
Success: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
s.Run(tc.name, func() {
|
||||||
|
response, err := s.server.buildPushNotificationReport(tc.pn, tc.registration)
|
||||||
|
s.Require().Equal(tc.expectedError, err)
|
||||||
|
s.Require().Equal(tc.expectedResponse, response)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue