Add notification for trustworthy/untrustworthy

This commit is contained in:
Andrea Maria Piana 2022-10-28 12:37:46 +01:00
parent 98f7324ae1
commit 2572321063
9 changed files with 304 additions and 51 deletions

View File

@ -1 +1 @@
0.115.0 0.115.1

View File

@ -738,7 +738,6 @@ func (db sqlitePersistence) UpdateActivityCenterNotificationFields(id types.HexB
return err return err
} }
_, err = db.db.Exec(`UPDATE activity_center_notifications SET message = ?, reply_message = ?, contact_verification_status = ? WHERE id = ?`, encodedMessage, encodedReplyMessage, status, id) _, err = db.db.Exec(`UPDATE activity_center_notifications SET message = ?, reply_message = ?, contact_verification_status = ? WHERE id = ?`, encodedMessage, encodedReplyMessage, status, id)
return err return err

View File

@ -65,6 +65,8 @@ const (
ContactVerificationStatePending ContactVerificationState = iota + 1 ContactVerificationStatePending ContactVerificationState = iota + 1
ContactVerificationStateAccepted ContactVerificationStateAccepted
ContactVerificationStateDeclined ContactVerificationStateDeclined
ContactVerificationStateTrusted
ContactVerificationStateUntrustworthy
) )
type CommandParameters struct { type CommandParameters struct {

View File

@ -16,6 +16,7 @@ import (
"github.com/status-im/status-go/protocol/common" "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/requests"
"github.com/status-im/status-go/protocol/verification" "github.com/status-im/status-go/protocol/verification"
) )
@ -298,27 +299,43 @@ func (m *Messenger) AcceptContactVerificationRequest(ctx context.Context, id str
return resp, nil return resp, nil
} }
func (m *Messenger) VerifiedTrusted(ctx context.Context, contactID string) error { func (m *Messenger) VerifiedTrusted(ctx context.Context, request *requests.VerifiedTrusted) (*MessengerResponse, error) {
contact, ok := m.allContacts.Load(contactID) err := request.Validate()
if !ok || !contact.Added || !contact.HasAddedUs { if err != nil {
return errors.New("must be a mutual contact") return nil, err
}
// Pull one from the db if there
notification, err := m.persistence.GetActivityCenterNotificationByID(request.ID)
if err != nil {
return nil, err
} }
err := m.verificationDatabase.SetTrustStatus(contactID, verification.TrustStatusTRUSTED, m.getTimesource().GetCurrentTime()) if notification == nil || notification.ReplyMessage == nil {
return nil, errors.New("could not find notification")
}
contactID := notification.ReplyMessage.From
contact, ok := m.allContacts.Load(contactID)
if !ok || !contact.Added || !contact.HasAddedUs {
return nil, errors.New("must be a mutual contact")
}
err = m.verificationDatabase.SetTrustStatus(contactID, verification.TrustStatusTRUSTED, m.getTimesource().GetCurrentTime())
if err != nil { if err != nil {
return err return nil, err
} }
err = m.SyncTrustedUser(context.Background(), contactID, verification.TrustStatusTRUSTED) err = m.SyncTrustedUser(context.Background(), contactID, verification.TrustStatusTRUSTED)
if err != nil { if err != nil {
return err return nil, err
} }
contact.VerificationStatus = VerificationStatusVERIFIED contact.VerificationStatus = VerificationStatusVERIFIED
contact.LastUpdatedLocally = m.getTimesource().GetCurrentTime() contact.LastUpdatedLocally = m.getTimesource().GetCurrentTime()
err = m.persistence.SaveContact(contact, nil) err = m.persistence.SaveContact(contact, nil)
if err != nil { if err != nil {
return err return nil, err
} }
chat, ok := m.allChats.Load(contactID) chat, ok := m.allChats.Load(contactID)
@ -326,20 +343,20 @@ func (m *Messenger) VerifiedTrusted(ctx context.Context, contactID string) error
if !ok { if !ok {
publicKey, err := contact.PublicKey() publicKey, err := contact.PublicKey()
if err != nil { if err != nil {
return err return nil, err
} }
chat = OneToOneFromPublicKey(publicKey, m.getTimesource()) chat = OneToOneFromPublicKey(publicKey, m.getTimesource())
// We don't want to show the chat to the user // We don't want to show the chat to the user
chat.Active = false chat.Active = false
} }
request := &protobuf.ContactVerificationTrusted{ r := &protobuf.ContactVerificationTrusted{
Clock: clock, Clock: clock,
} }
encodedMessage, err := proto.Marshal(request) encodedMessage, err := proto.Marshal(r)
if err != nil { if err != nil {
return err return nil, err
} }
_, err = m.dispatchMessage(ctx, common.RawMessage{ _, err = m.dispatchMessage(ctx, common.RawMessage{
@ -350,69 +367,133 @@ func (m *Messenger) VerifiedTrusted(ctx context.Context, contactID string) error
}) })
if err != nil { if err != nil {
return err return nil, err
} }
verifRequest, err := m.verificationDatabase.GetVerificationRequestSentTo(contactID) verifRequest, err := m.verificationDatabase.GetVerificationRequestSentTo(contactID)
if err != nil { if err != nil {
return err return nil, err
} }
if verifRequest == nil { if verifRequest == nil {
return errors.New("no contact verification found") return nil, errors.New("no contact verification found")
} }
verifRequest.RequestStatus = verification.RequestStatusTRUSTED verifRequest.RequestStatus = verification.RequestStatusTRUSTED
verifRequest.RepliedAt = clock verifRequest.RepliedAt = clock
err = m.verificationDatabase.SaveVerificationRequest(verifRequest) err = m.verificationDatabase.SaveVerificationRequest(verifRequest)
if err != nil { if err != nil {
return err return nil, err
} }
err = m.SyncVerificationRequest(context.Background(), verifRequest) err = m.SyncVerificationRequest(context.Background(), verifRequest)
if err != nil { if err != nil {
return err return nil, err
} }
// We sync the contact with the other devices // We sync the contact with the other devices
err = m.syncContact(context.Background(), contact) err = m.syncContact(context.Background(), contact)
if err != nil { if err != nil {
return err return nil, err
} }
return nil response := &MessengerResponse{}
notification.ContactVerificationStatus = verification.RequestStatusTRUSTED
notification.Message.ContactVerificationState = common.ContactVerificationStateTrusted
err = m.persistence.UpdateActivityCenterNotificationFields(notification.ID, notification.Message, notification.ReplyMessage, notification.ContactVerificationStatus)
if err != nil {
return nil, err
} }
func (m *Messenger) VerifiedUntrustworthy(ctx context.Context, contactID string) error { msg, err := m.persistence.MessageByID(notification.ReplyMessage.ID)
if err != nil {
return nil, err
}
msg.ContactVerificationState = common.ContactVerificationStateTrusted
err = m.persistence.SaveMessages([]*common.Message{msg})
if err != nil {
return nil, err
}
response.AddMessage(msg)
response.AddActivityCenterNotification(notification)
return response, nil
}
func (m *Messenger) VerifiedUntrustworthy(ctx context.Context, request *requests.VerifiedUntrustworthy) (*MessengerResponse, error) {
if err := request.Validate(); err != nil {
return nil, err
}
// Pull one from the db if there
notification, err := m.persistence.GetActivityCenterNotificationByID(request.ID)
if err != nil {
return nil, err
}
if notification == nil || notification.ReplyMessage == nil {
return nil, errors.New("could not find notification")
}
contactID := notification.ReplyMessage.From
contact, ok := m.allContacts.Load(contactID) contact, ok := m.allContacts.Load(contactID)
if !ok || !contact.Added || !contact.HasAddedUs { if !ok || !contact.Added || !contact.HasAddedUs {
return errors.New("must be a mutual contact") return nil, errors.New("must be a mutual contact")
} }
err := m.verificationDatabase.SetTrustStatus(contactID, verification.TrustStatusUNTRUSTWORTHY, m.getTimesource().GetCurrentTime()) err = m.verificationDatabase.SetTrustStatus(contactID, verification.TrustStatusUNTRUSTWORTHY, m.getTimesource().GetCurrentTime())
if err != nil { if err != nil {
return err return nil, err
} }
err = m.SyncTrustedUser(context.Background(), contactID, verification.TrustStatusUNTRUSTWORTHY) err = m.SyncTrustedUser(context.Background(), contactID, verification.TrustStatusUNTRUSTWORTHY)
if err != nil { if err != nil {
return err return nil, err
} }
contact.VerificationStatus = VerificationStatusVERIFIED contact.VerificationStatus = VerificationStatusVERIFIED
contact.LastUpdatedLocally = m.getTimesource().GetCurrentTime() contact.LastUpdatedLocally = m.getTimesource().GetCurrentTime()
err = m.persistence.SaveContact(contact, nil) err = m.persistence.SaveContact(contact, nil)
if err != nil { if err != nil {
return err return nil, err
} }
// We sync the contact with the other devices // We sync the contact with the other devices
err = m.syncContact(context.Background(), contact) err = m.syncContact(context.Background(), contact)
if err != nil { if err != nil {
return err return nil, err
} }
return nil response := &MessengerResponse{}
notification.ContactVerificationStatus = verification.RequestStatusUNTRUSTWORTHY
notification.Message.ContactVerificationState = common.ContactVerificationStateUntrustworthy
err = m.persistence.UpdateActivityCenterNotificationFields(notification.ID, notification.Message, notification.ReplyMessage, notification.ContactVerificationStatus)
if err != nil {
return nil, err
}
msg, err := m.persistence.MessageByID(notification.ReplyMessage.ID)
if err != nil {
return nil, err
}
msg.ContactVerificationState = common.ContactVerificationStateUntrustworthy
err = m.persistence.SaveMessages([]*common.Message{msg})
if err != nil {
return nil, err
}
response.AddMessage(msg)
response.AddActivityCenterNotification(notification)
return response, nil
} }
func (m *Messenger) DeclineContactVerificationRequest(ctx context.Context, id string) (*MessengerResponse, error) { func (m *Messenger) DeclineContactVerificationRequest(ctx context.Context, id string) (*MessengerResponse, error) {

View File

@ -263,6 +263,134 @@ func (s *MessengerVerificationRequests) TestAcceptVerificationRequests() {
s.Require().NotNil(resp.ActivityCenterNotifications()[0].ReplyMessage) s.Require().NotNil(resp.ActivityCenterNotifications()[0].ReplyMessage)
s.Require().Empty(resp.ActivityCenterNotifications()[0].ReplyMessage.OutgoingStatus) s.Require().Empty(resp.ActivityCenterNotifications()[0].ReplyMessage.OutgoingStatus)
s.Require().Equal("hello back", resp.ActivityCenterNotifications()[0].ReplyMessage.Text) s.Require().Equal("hello back", resp.ActivityCenterNotifications()[0].ReplyMessage.Text)
resp, err = s.m.VerifiedTrusted(context.Background(), &requests.VerifiedTrusted{ID: types.FromHex(verificationRequestID)})
s.Require().NoError(err)
s.Require().NotNil(resp)
s.Require().Len(resp.ActivityCenterNotifications(), 1)
s.Require().Equal(resp.ActivityCenterNotifications()[0].ID.String(), verificationRequestID)
s.Require().Equal(resp.ActivityCenterNotifications()[0].ContactVerificationStatus, verification.RequestStatusTRUSTED)
s.Require().Equal(common.ContactVerificationStateTrusted, resp.ActivityCenterNotifications()[0].Message.ContactVerificationState)
s.Require().Len(resp.Messages(), 1)
s.Require().Equal(common.ContactVerificationStateTrusted, resp.Messages()[0].ContactVerificationState)
}
func (s *MessengerVerificationRequests) TestUnthrustworthyVerificationRequests() {
theirMessenger := s.newMessenger(s.shh)
_, err := theirMessenger.Start()
s.Require().NoError(err)
s.mutualContact(theirMessenger)
theirPk := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey))
challenge := "challenge"
resp, err := s.m.SendContactVerificationRequest(context.Background(), theirPk, challenge)
s.Require().NoError(err)
s.Require().Len(resp.VerificationRequests, 1)
verificationRequestID := resp.VerificationRequests[0].ID
s.Require().Len(resp.Messages(), 1)
s.Require().NotEmpty(resp.Messages()[0].OutgoingStatus)
s.Require().Equal(challenge, resp.Messages()[0].Text)
s.Require().Equal(common.ContactVerificationStatePending, resp.Messages()[0].ContactVerificationState)
// Wait for the message to reach its destination
resp, err = WaitOnMessengerResponse(
theirMessenger,
func(r *MessengerResponse) bool {
return len(r.VerificationRequests) > 0 && len(r.ActivityCenterNotifications()) > 0
},
"no messages",
)
s.Require().NoError(err)
s.Require().Len(resp.VerificationRequests, 1)
s.Require().Equal(resp.VerificationRequests[0].ID, verificationRequestID)
s.Require().Equal(resp.ActivityCenterNotifications()[0].Type, ActivityCenterNotificationTypeContactVerification)
s.Require().Equal(resp.ActivityCenterNotifications()[0].ContactVerificationStatus, verification.RequestStatusPENDING)
s.Require().NotNil(resp.ActivityCenterNotifications()[0].Message)
s.Require().Equal(challenge, resp.ActivityCenterNotifications()[0].Message.Text)
s.Require().Equal(common.ContactVerificationStatePending, resp.ActivityCenterNotifications()[0].Message.ContactVerificationState)
s.Require().Len(resp.Messages(), 1)
s.Require().Empty(resp.Messages()[0].OutgoingStatus)
s.Require().Equal(challenge, resp.Messages()[0].Text)
s.Require().Equal(common.ContactVerificationStatePending, resp.Messages()[0].ContactVerificationState)
resp, err = theirMessenger.AcceptContactVerificationRequest(context.Background(), verificationRequestID, "hello back")
s.Require().NoError(err)
s.Require().NoError(err)
s.Require().Len(resp.VerificationRequests, 1)
s.Require().Equal(resp.VerificationRequests[0].ID, verificationRequestID)
s.Require().Equal(resp.VerificationRequests[0].RequestStatus, verification.RequestStatusACCEPTED)
s.Require().NotEmpty(resp.VerificationRequests[0].RepliedAt)
s.Require().Len(resp.ActivityCenterNotifications(), 1)
s.Require().Equal(resp.ActivityCenterNotifications()[0].ID.String(), verificationRequestID)
s.Require().Equal(resp.ActivityCenterNotifications()[0].ContactVerificationStatus, verification.RequestStatusACCEPTED)
s.Require().Equal(common.ContactVerificationStateAccepted, resp.ActivityCenterNotifications()[0].Message.ContactVerificationState)
s.Require().Len(resp.Messages(), 1)
s.Require().Equal(common.ContactVerificationStateAccepted, resp.Messages()[0].ContactVerificationState)
s.Require().NotNil(resp.ActivityCenterNotifications()[0].ReplyMessage)
s.Require().NotEmpty(resp.ActivityCenterNotifications()[0].ReplyMessage.OutgoingStatus)
s.Require().Equal("hello back", resp.ActivityCenterNotifications()[0].ReplyMessage.Text)
// Wait for the message to reach its destination
resp, err = WaitOnMessengerResponse(
s.m,
func(r *MessengerResponse) bool {
return len(r.VerificationRequests) > 0
},
"no messages",
)
s.Require().NoError(err)
s.Require().Len(resp.VerificationRequests, 1)
s.Require().Equal(resp.VerificationRequests[0].ID, verificationRequestID)
messages := resp.Messages()
s.Require().Len(messages, 2)
var originalMessage *common.Message
var replyMessage *common.Message
if messages[0].ID == resp.VerificationRequests[0].ID {
originalMessage = messages[0]
replyMessage = messages[1]
} else {
originalMessage = messages[1]
replyMessage = messages[0]
}
s.Require().Equal(common.ContactVerificationStateAccepted, originalMessage.ContactVerificationState)
// Not sure this is the right state for this, it should probably be pendingtrustedverification or something
s.Require().Equal(common.ContactVerificationStateAccepted, replyMessage.ContactVerificationState)
s.Require().Len(resp.ActivityCenterNotifications(), 1)
s.Require().Equal(resp.ActivityCenterNotifications()[0].ID.String(), verificationRequestID)
s.Require().Equal(resp.ActivityCenterNotifications()[0].ContactVerificationStatus, verification.RequestStatusACCEPTED)
s.Require().Equal(common.ContactVerificationStateAccepted, resp.ActivityCenterNotifications()[0].Message.ContactVerificationState)
s.Require().NotNil(resp.ActivityCenterNotifications()[0].ReplyMessage)
s.Require().Empty(resp.ActivityCenterNotifications()[0].ReplyMessage.OutgoingStatus)
s.Require().Equal("hello back", resp.ActivityCenterNotifications()[0].ReplyMessage.Text)
resp, err = s.m.VerifiedUntrustworthy(context.Background(), &requests.VerifiedUntrustworthy{ID: types.FromHex(verificationRequestID)})
s.Require().NoError(err)
s.Require().NotNil(resp)
s.Require().Len(resp.ActivityCenterNotifications(), 1)
s.Require().Equal(resp.ActivityCenterNotifications()[0].ID.String(), verificationRequestID)
s.Require().Equal(resp.ActivityCenterNotifications()[0].ContactVerificationStatus, verification.RequestStatusUNTRUSTWORTHY)
s.Require().Equal(common.ContactVerificationStateUntrustworthy, resp.ActivityCenterNotifications()[0].Message.ContactVerificationState)
s.Require().Len(resp.Messages(), 1)
s.Require().Equal(common.ContactVerificationStateUntrustworthy, resp.Messages()[0].ContactVerificationState)
} }
func (s *MessengerVerificationRequests) TestDeclineVerificationRequests() { func (s *MessengerVerificationRequests) TestDeclineVerificationRequests() {

View File

@ -0,0 +1,21 @@
package requests
import (
"errors"
"github.com/status-im/status-go/eth-node/types"
)
var ErrVerifiedTrustedInvalidID = errors.New("verified-trusted: invalid id")
type VerifiedTrusted struct {
ID types.HexBytes `json:"id"`
}
func (a *VerifiedTrusted) Validate() error {
if len(a.ID) == 0 {
return ErrVerifiedTrustedInvalidID
}
return nil
}

View File

@ -0,0 +1,21 @@
package requests
import (
"errors"
"github.com/status-im/status-go/eth-node/types"
)
var ErrVerifiedUntrustworthyInvalidID = errors.New("verified-untrustworthy: invalid id")
type VerifiedUntrustworthy struct {
ID types.HexBytes `json:"id"`
}
func (a *VerifiedUntrustworthy) Validate() error {
if len(a.ID) == 0 {
return ErrVerifiedUntrustworthyInvalidID
}
return nil
}

View File

@ -29,6 +29,7 @@ const (
RequestStatusDECLINED RequestStatusDECLINED
RequestStatusCANCELED RequestStatusCANCELED
RequestStatusTRUSTED RequestStatusTRUSTED
RequestStatusUNTRUSTWORTHY
) )
type TrustStatus int type TrustStatus int

View File

@ -820,12 +820,12 @@ func (api *PublicAPI) DeclineContactVerificationRequest(ctx context.Context, con
return api.service.messenger.DeclineContactVerificationRequest(ctx, contactID) return api.service.messenger.DeclineContactVerificationRequest(ctx, contactID)
} }
func (api *PublicAPI) VerifiedTrusted(ctx context.Context, contactID string) error { func (api *PublicAPI) VerifiedTrusted(ctx context.Context, request *requests.VerifiedTrusted) (*protocol.MessengerResponse, error) {
return api.service.messenger.VerifiedTrusted(ctx, contactID) return api.service.messenger.VerifiedTrusted(ctx, request)
} }
func (api *PublicAPI) VerifiedUntrustworthy(ctx context.Context, contactID string) error { func (api *PublicAPI) VerifiedUntrustworthy(ctx context.Context, request *requests.VerifiedUntrustworthy) (*protocol.MessengerResponse, error) {
return api.service.messenger.VerifiedUntrustworthy(ctx, contactID) return api.service.messenger.VerifiedUntrustworthy(ctx, request)
} }
func (api *PublicAPI) SendPairInstallation(ctx context.Context) (*protocol.MessengerResponse, error) { func (api *PublicAPI) SendPairInstallation(ctx context.Context) (*protocol.MessengerResponse, error) {