Handle identity verifications

This commit is contained in:
Andrea Maria Piana 2022-10-24 12:33:47 +01:00
parent a89f4b2d71
commit de61ed1213
10 changed files with 278 additions and 178 deletions

View File

@ -41,21 +41,21 @@ const (
var ErrInvalidActivityCenterNotification = errors.New("invalid activity center notification")
type ActivityCenterNotification struct {
ID types.HexBytes `json:"id"`
ChatID string `json:"chatId"`
CommunityID string `json:"communityId"`
MembershipStatus ActivityCenterMembershipStatus `json:"membershipStatus"`
Name string `json:"name"`
Author string `json:"author"`
Type ActivityCenterType `json:"type"`
LastMessage *common.Message `json:"lastMessage"`
Message *common.Message `json:"message"`
ReplyMessage *common.Message `json:"replyMessage"`
Timestamp uint64 `json:"timestamp"`
Read bool `json:"read"`
Dismissed bool `json:"dismissed"`
Accepted bool `json:"accepted"`
ContactVerificationStatus verification.RequestStatus `json:"contactVerificationStatus"`
ID types.HexBytes `json:"id"`
ChatID string `json:"chatId"`
CommunityID string `json:"communityId"`
MembershipStatus ActivityCenterMembershipStatus `json:"membershipStatus"`
Name string `json:"name"`
Author string `json:"author"`
Type ActivityCenterType `json:"type"`
LastMessage *common.Message `json:"lastMessage"`
Message *common.Message `json:"message"`
ReplyMessage *common.Message `json:"replyMessage"`
Timestamp uint64 `json:"timestamp"`
Read bool `json:"read"`
Dismissed bool `json:"dismissed"`
Accepted bool `json:"accepted"`
ContactVerificationStatus verification.RequestStatus `json:"contactVerificationStatus"`
}
type ActivityCenterPaginationResponse struct {

View File

@ -122,7 +122,7 @@ func (db sqlitePersistence) SaveActivityCenterNotification(notification *Activit
}
}
_, err = tx.Exec(`INSERT OR REPLACE INTO activity_center_notifications (id, timestamp, notification_type, chat_id, community_id, membership_status, message, reply_message, author) VALUES (?,?,?,?,?,?,?,?,?)`, notification.ID, notification.Timestamp, notification.Type, notification.ChatID, notification.CommunityID, notification.MembershipStatus, encodedMessage, encodedReplyMessage, notification.Author)
_, err = tx.Exec(`INSERT OR REPLACE INTO activity_center_notifications (id, timestamp, notification_type, chat_id, community_id, membership_status, message, reply_message, author, contact_verification_status) VALUES (?,?,?,?,?,?,?,?,?,?)`, notification.ID, notification.Timestamp, notification.Type, notification.ChatID, notification.CommunityID, notification.MembershipStatus, encodedMessage, encodedReplyMessage, notification.Author, notification.ContactVerificationStatus)
return err
}
@ -148,7 +148,7 @@ func (db sqlitePersistence) unmarshalActivityCenterNotificationRow(row *sql.Row)
&messageBytes,
&lastMessageBytes,
&replyMessageBytes,
&notification.ContactVerificationStatus,
&notification.ContactVerificationStatus,
&name,
&author)
@ -710,12 +710,11 @@ func (db sqlitePersistence) UpdateActivityCenterNotificationMessage(id types.Hex
}
func (db sqlitePersistence) UpdateActivityCenterNotificationContactVerificationStatus(id types.HexBytes, status verification.RequestStatus) error {
_, err := db.db.Exec(`UPDATE activity_center_notifications SET contact_verification_status = ? WHERE id = ?`, status, id)
return err
_, err := db.db.Exec(`UPDATE activity_center_notifications SET contact_verification_status = ? WHERE id = ?`, status, id)
return err
}
func (db sqlitePersistence) AcceptActivityCenterNotificationsForInvitesFromUser(userPublicKey string) ([]*ActivityCenterNotification, error) {
var tx *sql.Tx
var err error

View File

@ -64,7 +64,7 @@ type ContactVerificationState int
const (
ContactVerificationStatePending ContactVerificationState = iota + 1
ContactVerificationStateAccepted
ContactVerificationStateDismissed
ContactVerificationStateDeclined
)
type CommandParameters struct {
@ -205,81 +205,81 @@ func (m *Message) MarshalJSON() ([]byte, error) {
URL string `json:"url"`
}
item := struct {
ID string `json:"id"`
WhisperTimestamp uint64 `json:"whisperTimestamp"`
From string `json:"from"`
Alias string `json:"alias"`
Identicon string `json:"identicon"`
Seen bool `json:"seen"`
OutgoingStatus string `json:"outgoingStatus,omitempty"`
QuotedMessage *QuotedMessage `json:"quotedMessage"`
RTL bool `json:"rtl"`
ParsedText json.RawMessage `json:"parsedText,omitempty"`
LineCount int `json:"lineCount"`
Text string `json:"text"`
ChatID string `json:"chatId"`
LocalChatID string `json:"localChatId"`
Clock uint64 `json:"clock"`
Replace string `json:"replace"`
ResponseTo string `json:"responseTo"`
New bool `json:"new,omitempty"`
EnsName string `json:"ensName"`
DisplayName string `json:"displayName"`
Image string `json:"image,omitempty"`
Audio string `json:"audio,omitempty"`
AudioDurationMs uint64 `json:"audioDurationMs,omitempty"`
CommunityID string `json:"communityId,omitempty"`
Sticker *StickerAlias `json:"sticker,omitempty"`
CommandParameters *CommandParameters `json:"commandParameters,omitempty"`
GapParameters *GapParameters `json:"gapParameters,omitempty"`
Timestamp uint64 `json:"timestamp"`
ContentType protobuf.ChatMessage_ContentType `json:"contentType"`
MessageType protobuf.MessageType `json:"messageType"`
Mentions []string `json:"mentions,omitempty"`
Mentioned bool `json:"mentioned,omitempty"`
Links []string `json:"links,omitempty"`
EditedAt uint64 `json:"editedAt,omitempty"`
Deleted bool `json:"deleted,omitempty"`
DeletedForMe bool `json:"deletedForMe,omitempty"`
ContactRequestState ContactRequestState `json:"contactRequestState,omitempty"`
ContactVerificationState ContactVerificationState `json:"contactVerificationState,omitempty"`
DiscordMessage *protobuf.DiscordMessage `json:"discordMessage,omitempty"`
ID string `json:"id"`
WhisperTimestamp uint64 `json:"whisperTimestamp"`
From string `json:"from"`
Alias string `json:"alias"`
Identicon string `json:"identicon"`
Seen bool `json:"seen"`
OutgoingStatus string `json:"outgoingStatus,omitempty"`
QuotedMessage *QuotedMessage `json:"quotedMessage"`
RTL bool `json:"rtl"`
ParsedText json.RawMessage `json:"parsedText,omitempty"`
LineCount int `json:"lineCount"`
Text string `json:"text"`
ChatID string `json:"chatId"`
LocalChatID string `json:"localChatId"`
Clock uint64 `json:"clock"`
Replace string `json:"replace"`
ResponseTo string `json:"responseTo"`
New bool `json:"new,omitempty"`
EnsName string `json:"ensName"`
DisplayName string `json:"displayName"`
Image string `json:"image,omitempty"`
Audio string `json:"audio,omitempty"`
AudioDurationMs uint64 `json:"audioDurationMs,omitempty"`
CommunityID string `json:"communityId,omitempty"`
Sticker *StickerAlias `json:"sticker,omitempty"`
CommandParameters *CommandParameters `json:"commandParameters,omitempty"`
GapParameters *GapParameters `json:"gapParameters,omitempty"`
Timestamp uint64 `json:"timestamp"`
ContentType protobuf.ChatMessage_ContentType `json:"contentType"`
MessageType protobuf.MessageType `json:"messageType"`
Mentions []string `json:"mentions,omitempty"`
Mentioned bool `json:"mentioned,omitempty"`
Links []string `json:"links,omitempty"`
EditedAt uint64 `json:"editedAt,omitempty"`
Deleted bool `json:"deleted,omitempty"`
DeletedForMe bool `json:"deletedForMe,omitempty"`
ContactRequestState ContactRequestState `json:"contactRequestState,omitempty"`
ContactVerificationState ContactVerificationState `json:"contactVerificationState,omitempty"`
DiscordMessage *protobuf.DiscordMessage `json:"discordMessage,omitempty"`
}{
ID: m.ID,
WhisperTimestamp: m.WhisperTimestamp,
From: m.From,
Alias: m.Alias,
Identicon: m.Identicon,
Seen: m.Seen,
OutgoingStatus: m.OutgoingStatus,
QuotedMessage: m.QuotedMessage,
RTL: m.RTL,
ParsedText: m.ParsedText,
LineCount: m.LineCount,
Text: m.Text,
Replace: m.Replace,
ChatID: m.ChatId,
LocalChatID: m.LocalChatID,
Clock: m.Clock,
ResponseTo: m.ResponseTo,
New: m.New,
EnsName: m.EnsName,
DisplayName: m.DisplayName,
Image: m.ImageLocalURL,
Audio: m.AudioLocalURL,
CommunityID: m.CommunityID,
Timestamp: m.Timestamp,
ContentType: m.ContentType,
Mentions: m.Mentions,
Mentioned: m.Mentioned,
Links: m.Links,
MessageType: m.MessageType,
CommandParameters: m.CommandParameters,
GapParameters: m.GapParameters,
EditedAt: m.EditedAt,
Deleted: m.Deleted,
DeletedForMe: m.DeletedForMe,
ContactRequestState: m.ContactRequestState,
ID: m.ID,
WhisperTimestamp: m.WhisperTimestamp,
From: m.From,
Alias: m.Alias,
Identicon: m.Identicon,
Seen: m.Seen,
OutgoingStatus: m.OutgoingStatus,
QuotedMessage: m.QuotedMessage,
RTL: m.RTL,
ParsedText: m.ParsedText,
LineCount: m.LineCount,
Text: m.Text,
Replace: m.Replace,
ChatID: m.ChatId,
LocalChatID: m.LocalChatID,
Clock: m.Clock,
ResponseTo: m.ResponseTo,
New: m.New,
EnsName: m.EnsName,
DisplayName: m.DisplayName,
Image: m.ImageLocalURL,
Audio: m.AudioLocalURL,
CommunityID: m.CommunityID,
Timestamp: m.Timestamp,
ContentType: m.ContentType,
Mentions: m.Mentions,
Mentioned: m.Mentioned,
Links: m.Links,
MessageType: m.MessageType,
CommandParameters: m.CommandParameters,
GapParameters: m.GapParameters,
EditedAt: m.EditedAt,
Deleted: m.Deleted,
DeletedForMe: m.DeletedForMe,
ContactRequestState: m.ContactRequestState,
ContactVerificationState: m.ContactVerificationState,
}
if sticker := m.GetSticker(); sticker != nil {

View File

@ -279,13 +279,13 @@ func (m *Messenger) AcceptContactVerificationRequest(ctx context.Context, id str
resp.AddMessage(chatMessage)
if notification != nil {
// TODO: Should we update only the message or only the notification or both?
err := m.persistence.UpdateActivityCenterNotificationContactVerificationStatus(notification.ID, verification.RequestStatusACCEPTED)
if err != nil {
return nil, err
}
// TODO: Should we update only the message or only the notification or both?
err := m.persistence.UpdateActivityCenterNotificationContactVerificationStatus(notification.ID, verification.RequestStatusACCEPTED)
if err != nil {
return nil, err
}
notification.ContactVerificationStatus = verification.RequestStatusACCEPTED
notification.ContactVerificationStatus = verification.RequestStatusACCEPTED
message := notification.Message
message.ContactVerificationState = common.ContactVerificationStateAccepted
err = m.persistence.UpdateActivityCenterNotificationMessage(notification.ID, message)
@ -416,31 +416,31 @@ func (m *Messenger) VerifiedUntrustworthy(ctx context.Context, contactID string)
return nil
}
func (m *Messenger) DeclineContactVerificationRequest(ctx context.Context, id string) error {
func (m *Messenger) DeclineContactVerificationRequest(ctx context.Context, id string) (*MessengerResponse, error) {
verifRequest, err := m.verificationDatabase.GetVerificationRequest(id)
if err != nil {
return err
return nil, err
}
if verifRequest == nil {
m.logger.Error("could not find verification request with id", zap.String("id", id))
return verification.ErrVerificationRequestNotFound
return nil, verification.ErrVerificationRequestNotFound
}
contact, ok := m.allContacts.Load(verifRequest.From)
if !ok || !contact.Added || !contact.HasAddedUs {
return errors.New("must be a mutual contact")
return nil, errors.New("must be a mutual contact")
}
if verifRequest == nil {
return errors.New("no contact verification found")
return nil, errors.New("no contact verification found")
}
chat, ok := m.allChats.Load(verifRequest.From)
if !ok {
publicKey, err := contact.PublicKey()
if err != nil {
return err
return nil, err
}
chat = OneToOneFromPublicKey(publicKey, m.getTimesource())
// We don't want to show the chat to the user
@ -454,12 +454,16 @@ func (m *Messenger) DeclineContactVerificationRequest(ctx context.Context, id st
verifRequest.RepliedAt = clock
err = m.verificationDatabase.SaveVerificationRequest(verifRequest)
if err != nil {
return err
return nil, err
}
response := &MessengerResponse{}
response.AddVerificationRequest(verifRequest)
err = m.SyncVerificationRequest(context.Background(), verifRequest)
if err != nil {
return err
return nil, err
}
request := &protobuf.DeclineContactVerification{
@ -469,7 +473,7 @@ func (m *Messenger) DeclineContactVerificationRequest(ctx context.Context, id st
encodedMessage, err := proto.Marshal(request)
if err != nil {
return err
return nil, err
}
_, err = m.dispatchMessage(ctx, common.RawMessage{
@ -480,10 +484,38 @@ func (m *Messenger) DeclineContactVerificationRequest(ctx context.Context, id st
})
if err != nil {
return err
return nil, err
}
return m.verificationDatabase.DeclineContactVerificationRequest(verifRequest.From)
err = m.verificationDatabase.DeclineContactVerificationRequest(id)
if err != nil {
return nil, err
}
notification, err := m.persistence.GetActivityCenterNotificationByID(types.FromHex(id))
if err != nil {
return nil, err
}
if notification != nil {
// TODO: Should we update only the message or only the notification or both?
err := m.persistence.UpdateActivityCenterNotificationContactVerificationStatus(notification.ID, verification.RequestStatusDECLINED)
if err != nil {
return nil, err
}
notification.ContactVerificationStatus = verification.RequestStatusDECLINED
message := notification.Message
message.ContactVerificationState = common.ContactVerificationStateDeclined
err = m.persistence.UpdateActivityCenterNotificationMessage(notification.ID, message)
if err != nil {
return nil, err
}
response.AddActivityCenterNotification(notification)
response.AddMessage(message)
}
return response, nil
}
func (m *Messenger) MarkAsTrusted(ctx context.Context, contactID string) error {
@ -728,7 +760,7 @@ func (m *Messenger) HandleDeclineContactVerification(state *ReceivedMessageState
return errors.New("must be a mutual contact")
}
persistedVR, err := m.verificationDatabase.GetVerificationRequestSentTo(contactID)
persistedVR, err := m.verificationDatabase.GetVerificationRequest(request.Id)
if err != nil {
m.logger.Debug("Error obtaining verification request", zap.Error(err))
return err
@ -765,9 +797,17 @@ func (m *Messenger) HandleDeclineContactVerification(state *ReceivedMessageState
state.AllVerificationRequests = append(state.AllVerificationRequests, persistedVR)
// TODO: create or update activity center notification
msg, err := m.persistence.MessageByID(request.Id)
if err != nil {
return err
}
return nil
if msg != nil {
msg.ContactVerificationState = common.ContactVerificationStateDeclined
state.Response.AddMessage(msg)
}
return m.createContactVerificationNotification(contact, state, persistedVR, msg)
}
func (m *Messenger) HandleContactVerificationTrusted(state *ReceivedMessageState, request protobuf.ContactVerificationTrusted) error {

View File

@ -162,7 +162,7 @@ func (s *MessengerVerificationRequests) mutualContact(theirMessenger *Messenger)
}
func (s *MessengerVerificationRequests) TestVerificationRequests() {
func (s *MessengerVerificationRequests) TestAcceptVerificationRequests() {
theirMessenger := s.newMessenger(s.shh)
_, err := theirMessenger.Start()
s.Require().NoError(err)
@ -241,6 +241,100 @@ func (s *MessengerVerificationRequests) TestVerificationRequests() {
s.Require().Equal(common.ContactVerificationStateAccepted, resp.ActivityCenterNotifications()[0].Message.ContactVerificationState)
}
func (s *MessengerVerificationRequests) TestDeclineVerificationRequests() {
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().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().Equal(challenge, resp.Messages()[0].Text)
s.Require().Equal(common.ContactVerificationStatePending, resp.Messages()[0].ContactVerificationState)
// Make sure it's stored and retrieved correctly
notifications, err := theirMessenger.UnreadActivityCenterNotifications("", 4, ActivityCenterNotificationTypeContactVerification)
s.Require().NoError(err)
s.Require().Len(notifications.Notifications, 1)
s.Require().Equal(notifications.Notifications[0].ContactVerificationStatus, verification.RequestStatusPENDING)
s.Require().Equal(common.ContactVerificationStatePending, notifications.Notifications[0].Message.ContactVerificationState)
resp, err = theirMessenger.DeclineContactVerificationRequest(context.Background(), verificationRequestID)
s.Require().NoError(err)
s.Require().NotNil(resp)
s.Require().Len(resp.VerificationRequests, 1)
s.Require().Equal(resp.VerificationRequests[0].ID, verificationRequestID)
s.Require().Equal(resp.VerificationRequests[0].RequestStatus, verification.RequestStatusDECLINED)
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.RequestStatusDECLINED)
s.Require().Equal(common.ContactVerificationStateDeclined, resp.ActivityCenterNotifications()[0].Message.ContactVerificationState)
s.Require().Len(resp.Messages(), 1)
s.Require().Equal(common.ContactVerificationStateDeclined, resp.Messages()[0].ContactVerificationState)
// Make sure it's stored and retrieved correctly
notifications, err = theirMessenger.UnreadActivityCenterNotifications("", 4, ActivityCenterNotificationTypeContactVerification)
s.Require().NoError(err)
s.Require().Len(notifications.Notifications, 1)
s.Require().Equal(notifications.Notifications[0].ContactVerificationStatus, verification.RequestStatusDECLINED)
s.Require().Equal(common.ContactVerificationStateDeclined, notifications.Notifications[0].Message.ContactVerificationState)
// 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)
s.Require().Len(resp.Messages(), 1)
s.Require().Equal(common.ContactVerificationStateDeclined, resp.Messages()[0].ContactVerificationState)
s.Require().Len(resp.ActivityCenterNotifications(), 1)
s.Require().Equal(resp.ActivityCenterNotifications()[0].ID.String(), verificationRequestID)
s.Require().Equal(resp.ActivityCenterNotifications()[0].ContactVerificationStatus, verification.RequestStatusDECLINED)
s.Require().Equal(common.ContactVerificationStateDeclined, resp.ActivityCenterNotifications()[0].Message.ContactVerificationState)
}
func (s *MessengerVerificationRequests) TearDownTest() {
s.Require().NoError(s.m.Shutdown())
}

View File

@ -66,7 +66,7 @@
// 1665079662_add_spectated_column_in_communities.up.sql (86B)
// 1665479047_add_community_id_in_notifications.up.sql (169B)
// 1665484435_add_encrypted_messages.up.sql (402B)
// 1665560200_add_contact_verification_individual.up.sql (474B)
// 1665560200_add_contact_verification_individual.up.sql (509B)
// README.md (554B)
// doc.go (850B)
@ -1457,7 +1457,7 @@ func _1665484435_add_encrypted_messagesUpSql() (*asset, error) {
return a, nil
}
var __1665560200_add_contact_verification_individualUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\x8f\xc1\x6a\xf3\x30\x10\x84\xef\x7a\x8a\x3d\xfe\x3f\xf4\xd0\xbb\x4f\xaa\x2d\x83\xa9\x22\x07\x47\x86\xe4\x24\x84\xbc\x49\x05\x8e\x94\x4a\x6b\x43\xdf\xbe\xc4\x49\xd3\x06\x5a\x4a\x8f\xd2\xce\x7c\x33\xc3\xa5\x16\x1d\x68\xfe\x24\x05\x4c\x19\x93\x39\x62\xce\xf6\x80\x19\x78\x55\x41\xd9\xca\x7e\xa5\xc0\xc5\x40\xd6\x91\x99\x31\xf9\xbd\x77\x96\x7c\x0c\x26\x93\xa5\x29\x43\xa3\x74\xc1\xbe\x52\xac\x23\x3f\x7b\x7a\x33\x0e\x03\x61\x32\x21\xd2\xcd\xf4\x17\x2a\x54\xa2\xe6\xbd\xd4\xf0\x58\x30\x56\x76\x82\x6b\x71\x4d\x68\x6a\x50\xad\x06\xb1\x6d\x36\x7a\x03\x77\xf6\x84\xaf\x13\x66\xca\xc6\x87\xc1\xcf\x7e\x98\xec\x08\xff\x18\xc0\x3e\xc5\xa3\x39\xef\x03\x2d\xb6\xfa\x81\x01\x50\xbc\x7f\xbb\x17\x3b\x8e\x18\x0e\xb8\xfc\x2c\x01\xaa\x97\xf2\x7c\xba\x42\x71\x30\x96\x96\x66\x1f\xc7\xcf\x8a\x17\x59\x3e\xc5\x90\xf1\x86\x4c\x78\x1a\xfd\x6f\xae\x9f\xd6\x7f\xaf\xf6\xc3\xa5\xde\xba\x6b\x56\xbc\xdb\xc1\xb3\xd8\x41\xab\xa0\x6c\x55\x2d\x9b\x52\x43\x27\xd6\x92\x97\x82\xfd\x2f\xd8\x7b\x00\x00\x00\xff\xff\xe0\x53\x96\x59\xda\x01\x00\x00")
var __1665560200_add_contact_verification_individualUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\x90\xc1\x6a\x03\x21\x10\x86\xef\x3e\xc5\x1c\x5b\xe8\xa1\xf7\x3d\xd9\x5d\x03\x4b\x8d\x1b\x8c\x81\xe4\x24\xe2\x4e\x52\x61\xa3\xa9\xce\x06\xfa\xf6\x25\xc9\x36\x6d\x20\xa5\xf4\xa8\xf3\xfd\x9f\xe3\xcf\xa5\x11\x1a\x0c\x7f\x91\x02\xc6\x82\xd9\xee\xb1\x14\xb7\xc3\x02\xbc\x69\xa0\xee\xe4\x6a\xae\xc0\xa7\x48\xce\x93\x3d\x62\x0e\xdb\xe0\x1d\x85\x14\x6d\x21\x47\x63\x81\x56\x99\x8a\xfd\xb4\x38\x4f\xe1\x18\xe8\xc3\x7a\x8c\x84\xd9\xc6\x44\xd7\xd0\x7f\xac\xd0\x88\x19\x5f\x49\x03\xcf\x15\x63\x8d\xee\x16\x93\xff\x06\xcf\xf8\x3e\x62\xa1\x52\x31\x56\x6b\xc1\x8d\x98\xa0\x76\x06\xaa\x33\x20\xd6\xed\xd2\x2c\xef\x47\x6c\x88\x7d\x38\x86\x7e\x74\x03\x3c\x30\x80\x6d\x4e\x7b\x7b\xaa\x00\x8c\x58\x9b\x27\x06\x40\xe9\xf6\xec\xdf\xdc\x30\x60\xdc\xe1\xf9\xe6\xfc\x80\x5a\x49\x79\x1a\x4d\x52\xec\xad\xa3\xf3\xf2\x5f\xc3\xef\x5f\x5c\xb0\x72\x48\xb1\xe0\x55\x99\xf1\x30\x84\xbf\x52\xbf\x15\x74\x9f\x0e\xfd\x65\xbd\x85\x6e\xe7\x5c\x6f\xe0\x55\x6c\xa0\x53\x50\x77\x6a\x26\xdb\xda\x80\x16\x0b\xc9\x6b\xc1\x1e\x2b\xf6\x19\x00\x00\xff\xff\xfa\x97\x1b\xc5\xfd\x01\x00\x00")
func _1665560200_add_contact_verification_individualUpSqlBytes() ([]byte, error) {
return bindataRead(
@ -1472,8 +1472,8 @@ func _1665560200_add_contact_verification_individualUpSql() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "1665560200_add_contact_verification_individual.up.sql", size: 474, mode: os.FileMode(0644), modTime: time.Unix(1666784614, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x1a, 0x9e, 0x80, 0x24, 0xd3, 0xd5, 0x19, 0x52, 0x28, 0x9f, 0xe6, 0x60, 0x3a, 0xd9, 0x8e, 0x32, 0x86, 0x7b, 0x43, 0x35, 0x9e, 0x21, 0x6e, 0x2b, 0xe5, 0x86, 0xf3, 0xcf, 0xe4, 0x6b, 0x91, 0x2f}}
info := bindataFileInfo{name: "1665560200_add_contact_verification_individual.up.sql", size: 509, mode: os.FileMode(0644), modTime: time.Unix(1666788871, 0)}
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc5, 0xbb, 0x61, 0xfd, 0xbf, 0x33, 0x1d, 0x4e, 0x5f, 0xbd, 0x86, 0x42, 0xb0, 0x6c, 0xf7, 0x39, 0x19, 0x6e, 0x72, 0x35, 0xfd, 0x1b, 0xd6, 0xbd, 0xf6, 0x81, 0x21, 0xc4, 0xaa, 0x6, 0x62, 0x40}}
return a, nil
}

View File

@ -1,6 +1,8 @@
ALTER TABLE user_messages ADD COLUMN contact_verification_status INT;
ALTER TABLE activity_center_notifications ADD COLUMN contact_verification_status INT DEFAULT 0;
DROP TABLE verification_requests;
CREATE TABLE IF NOT EXISTS verification_requests_individual (
from_user TEXT,
to_user TEXT,

View File

@ -40,7 +40,7 @@ const (
)
type Request struct {
ID string `json:"id"`
ID string `json:"id"`
From string `json:"from"`
To string `json:"to"`
Challenge string `json:"challenge"`
@ -72,7 +72,7 @@ func (p *Persistence) GetVerificationRequests() ([]Request, error) {
func (p *Persistence) GetVerificationRequest(id string) (*Request, error) {
var vr Request
err := p.db.QueryRow(`SELECT id, from_user, to_user, challenge, response, requested_at, verification_status, replied_at FROM verification_requests_individual WHERE id = ?`, id).Scan(
&vr.ID,
&vr.ID,
&vr.From,
&vr.To,
&vr.Challenge,
@ -107,7 +107,7 @@ func (p *Persistence) GetReceivedVerificationRequests(myPublicKey string) ([]*Re
var vr Request
err := rows.Scan(
&vr.ID,
&vr.ID,
&vr.From,
&vr.To,
&vr.Challenge,
@ -129,7 +129,7 @@ func (p *Persistence) GetReceivedVerificationRequests(myPublicKey string) ([]*Re
func (p *Persistence) GetVerificationRequestSentTo(contactID string) (*Request, error) {
var vr Request
err := p.db.QueryRow(`SELECT id, from_user, to_user, challenge, response, requested_at, verification_status, replied_at FROM verification_requests_individual WHERE to_user = ?`, contactID).Scan(
&vr.ID,
&vr.ID,
&vr.From,
&vr.To,
&vr.Challenge,

View File

@ -34,7 +34,7 @@ func (s *PersistenceSuite) SetupTest() {
func (s *PersistenceSuite) TestVerificationRequests() {
request := &Request{
ID: "0xabc",
ID: "0xabc",
From: "0x01",
To: "0x02",
Challenge: "ABC",
@ -46,30 +46,32 @@ func (s *PersistenceSuite) TestVerificationRequests() {
// Test Insert
err := s.db.SaveVerificationRequest(request)
s.NoError(err)
s.Require().NoError(err)
// Test Found
dbRequest, err := s.db.GetVerificationRequest("0xabc")
s.NoError(err)
s.Equal(request, dbRequest)
s.Require().NoError(err)
s.Require().Equal(request, dbRequest)
// Test Not Found
dbRequest2, err := s.db.GetVerificationRequestFrom("0xdef")
s.NoError(err)
s.Nil(dbRequest2)
dbRequest2, err := s.db.GetVerificationRequest("0xdef")
s.Require().NoError(err)
s.Require().Nil(dbRequest2)
// Test Accept
err = s.db.AcceptContactVerificationRequest("0x01", "XYZ")
s.NoError(err)
err = s.db.AcceptContactVerificationRequest("0xabc", "XYZ")
s.Require().NoError(err)
dbRequest, err = s.db.GetVerificationRequestFrom("0x01")
s.NoError(err)
s.Equal(RequestStatusACCEPTED, dbRequest.RequestStatus)
s.Equal("XYZ", dbRequest.Response)
s.NotEqual(time.Unix(0, 0), dbRequest.RepliedAt)
dbRequest, err = s.db.GetVerificationRequest("0xabc")
s.Require().NoError(err)
s.Require().NotNil(dbRequest)
s.Require().Equal(RequestStatusACCEPTED, dbRequest.RequestStatus)
s.Require().Equal("XYZ", dbRequest.Response)
s.Require().NotEqual(time.Unix(0, 0), dbRequest.RepliedAt)
// Test Decline
request = &Request{
ID: "0x01",
From: "0x03",
To: "0x02",
Challenge: "ABC",
@ -82,51 +84,14 @@ func (s *PersistenceSuite) TestVerificationRequests() {
err = s.db.SaveVerificationRequest(request)
s.NoError(err)
err = s.db.DeclineContactVerificationRequest("0x03")
err = s.db.DeclineContactVerificationRequest("0x01")
s.NoError(err)
dbRequest, err = s.db.GetVerificationRequestFrom("0x03")
dbRequest, err = s.db.GetVerificationRequest("0x01")
s.NoError(err)
s.Equal(RequestStatusDECLINED, dbRequest.RequestStatus)
s.NotEqual(time.Unix(0, 0), dbRequest.RepliedAt)
// Test Upsert fails because of older record
ogDbRequestStatus := dbRequest.RequestStatus
dbRequest.RequestStatus = RequestStatusPENDING
shouldSync, err := s.db.UpsertVerificationRequest(dbRequest)
s.NoError(err)
s.False(shouldSync)
dbRequest.RequestStatus = ogDbRequestStatus
dbRequest2, err = s.db.GetVerificationRequestFrom("0x03")
s.NoError(err)
s.Equal(dbRequest, dbRequest2)
// Test upsert success (update)
dbRequest2.RequestStatus = RequestStatusPENDING
dbRequest2.RepliedAt = dbRequest2.RepliedAt + 100
shouldSync, err = s.db.UpsertVerificationRequest(dbRequest2)
s.NoError(err)
s.True(shouldSync)
// Test upsert success (insert)
verifReq := &Request{
From: "0x0A",
To: "0x0B",
Challenge: "123",
Response: "456",
RequestedAt: uint64(time.Now().Unix()),
RepliedAt: uint64(time.Now().Unix()),
RequestStatus: RequestStatusPENDING,
}
shouldSync, err = s.db.UpsertVerificationRequest(verifReq)
s.NoError(err)
s.True(shouldSync)
dbRequest, err = s.db.GetVerificationRequestFrom("0x0A")
s.NoError(err)
s.Equal(verifReq.To, dbRequest.To)
}
func (s *PersistenceSuite) TestTrustStatus() {

View File

@ -797,7 +797,7 @@ func (api *PublicAPI) AcceptContactVerificationRequest(ctx context.Context, cont
return api.service.messenger.AcceptContactVerificationRequest(ctx, contactID, response)
}
func (api *PublicAPI) DeclineContactVerificationRequest(ctx context.Context, contactID string) error {
func (api *PublicAPI) DeclineContactVerificationRequest(ctx context.Context, contactID string) (*protocol.MessengerResponse, error) {
return api.service.messenger.DeclineContactVerificationRequest(ctx, contactID)
}