Skip to content

Commit

Permalink
fix(db): generate conversation id for 1-1 conversation
Browse files Browse the repository at this point in the history
fix #764

Signed-off-by: Godefroy Ponsinet <godefroy.ponsinet@outlook.com>
  • Loading branch information
90dy committed Dec 14, 2018
1 parent 46de480 commit 6379a65
Show file tree
Hide file tree
Showing 7 changed files with 300 additions and 298 deletions.
5 changes: 5 additions & 0 deletions client/react-native/common/components/Screens/Chats/Add.js
Expand Up @@ -20,6 +20,11 @@ const Item = fragments.Contact(
data: { id, status, displayName, overrideDisplayName, displayStatus },
} = this.props
const { selected } = this.state

if (status === 42) {
return null
}

return (
<Flex.Cols
align='start'
Expand Down
19 changes: 2 additions & 17 deletions core/node/nodeapi.go
Expand Up @@ -242,23 +242,8 @@ func (n *Node) ContactRequest(ctx context.Context, req *node.ContactRequestInput
return nil, errorcodes.ErrContactReqExisting.New()
}

// check if already have contact request from/to this contact
// if not, create a conversation
count := 0
sql.Model(&p2p.Event{}).
Where(&p2p.Event{
SenderID: contact.ID,
Kind: p2p.Kind_ContactRequest,
}).
Or(&p2p.Event{
ReceiverID: contact.ID,
Kind: p2p.Kind_ContactRequest,
}).
Count(&count).
First(&p2p.Event{})
if count == 0 {
n.ConversationCreate(ctx, &node.ConversationCreateInput{Contacts: []*entity.Contact{contact}})
}
// create conversation if doesn't exist
n.ConversationCreate(ctx, &node.ConversationCreateInput{Contacts: []*entity.Contact{contact}})

// send request to peer
event := n.NewContactEvent(ctx, contact, p2p.Kind_ContactRequest)
Expand Down
466 changes: 239 additions & 227 deletions core/pkg/errorcodes/errors.pb.go

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions core/pkg/errorcodes/errors.proto
Expand Up @@ -99,6 +99,9 @@ enum BertyErrorCodes {
ErrSenderAliasNoCandidates = 12002;
ErrSenderAliasUpdateFailed = 12003;

ErrConversation = 13000;
ErrConversationMembers = 13001;
ErrConversationNotEnoughMembers = 13002;
}


Expand Down
89 changes: 43 additions & 46 deletions core/sql/helpers.go
Expand Up @@ -2,9 +2,10 @@ package sql

import (
"errors"
"fmt"
"sort"
"strings"

"berty.tech/core/api/p2p"
"berty.tech/core/entity"
"berty.tech/core/pkg/errorcodes"
"github.com/jinzhu/gorm"
Expand Down Expand Up @@ -38,44 +39,56 @@ func MembersByConversationID(db *gorm.DB, conversationID string) ([]*entity.Conv
Error
}

func MergeConversations(db *gorm.DB, conversations []entity.Conversation) (*entity.Conversation, error) {
logger().Debug("MERGE_CONVERSATION")
// chosse the conversation to save
merge := conversations[0]
for i := range conversations {
if strings.Compare(merge.ID, conversations[i].ID) > 0 {
merge = conversations[i]
func CreateConversation(db *gorm.DB, conversation *entity.Conversation) (*entity.Conversation, error) {

// remove members duplicates and sort them by contact id
members := map[string]*entity.ConversationMember{}
for _, member := range conversation.Members {
if member.ContactID != "" && member != nil {
members[member.ContactID] = member
}
}

// move all messages to that conversation
for i := range conversations {
if err := db.Model(&p2p.Event{}).Where(&p2p.Event{
ConversationID: conversations[i].ID,
Kind: p2p.Kind_ConversationNewMessage,
}).Update(&p2p.Event{
ConversationID: merge.ID,
}).Error; err != nil {
return nil, err
conversation.Members = []*entity.ConversationMember{}
for _, member := range members {
conversation.Members = append(conversation.Members, member)
}
// sort members
sort.Slice(conversation.Members, func(i, j int) bool {
if strings.Compare(
conversation.Members[i].ContactID,
conversation.Members[j].ContactID,
) > 0 {
return false
}
return true
})

// don't create 0-0 or 1-0 conversation
if len(conversation.Members) <= 1 {
return nil, errorcodes.ErrConversationNotEnoughMembers.New()
}

// remove other conversations
for i := range conversations {
if conversations[i].ID != merge.ID {
db.Where(&entity.ConversationMember{
ConversationID: conversations[i].ID,
}).Delete(&entity.ConversationMember{})
db.Delete(conversations[i])
// generate id for conversation 1-1
if len(conversation.Members) == 2 {
conversation.ID = fmt.Sprintf("%s:%s",
conversation.Members[0].ContactID,
conversation.Members[1].ContactID,
)

// check if conversation already exists
tmp := &entity.Conversation{}
db.Where(&entity.Conversation{ID: conversation.ID}).First(&tmp)
if tmp.ID != "" {
return tmp, nil
}
}

return &merge, nil
}
// make the two members as owners
conversation.Members[0].Status = entity.ConversationMember_Owner
conversation.Members[1].Status = entity.ConversationMember_Owner
}

func CreateConversation(db *gorm.DB, conversation *entity.Conversation) (*entity.Conversation, error) {
// save conversation
if err := db.Set("gorm:association_autoupdate", true).Save(conversation).Error; err != nil {
if err := db.Set("gorm:association_autoupdate", true).Create(conversation).Error; err != nil {
return nil, errorcodes.ErrDbCreate.Wrap(err)
}

Expand All @@ -85,21 +98,5 @@ func CreateConversation(db *gorm.DB, conversation *entity.Conversation) (*entity
return nil, errorcodes.ErrDb.Wrap(err)
}

// check if that is 1-1 conversation
// if len(conversation.Members) <= 2 {
// logger().Debug("CREATE_CONVERSATION")
// // check if there already a 1-1 conversation
// conversations := []entity.Conversation{}

// logger().Debug(fmt.Sprintf("GET_MEMBERS %+v", conversation.Members))
// db.Model(&entity.Conversation{}).Find(conversations).Error; err != nil {
// logger().Error(err.Error())
// }
// logger().Debug(fmt.Sprintf("CONVERSATIONS %+v", conversations))
// if len(conversations) >= 1 {
// return MergeConversations(db, conversations)
// }
// }

return conversation, nil
}
12 changes: 6 additions & 6 deletions core/test/e2e_test.go
Expand Up @@ -705,11 +705,11 @@ func TestAliasesFlow(t *testing.T) {

conversations, err := bob.client.ConversationList(internalCtx, &node.ConversationListInput{})
So(err, ShouldBeNil)
So(len(conversations), ShouldEqual, 2)
So(len(conversations), ShouldEqual, 1)

conversations, err = alice.client.ConversationList(internalCtx, &node.ConversationListInput{})
So(err, ShouldBeNil)
So(len(conversations), ShouldEqual, 2)
So(len(conversations), ShouldEqual, 1)

everythingWentFine()
})
Expand Down Expand Up @@ -747,11 +747,11 @@ func TestAliasesFlow(t *testing.T) {

conversations, err := bob.client.ConversationList(internalCtx, &node.ConversationListInput{})
So(err, ShouldBeNil)
So(len(conversations), ShouldEqual, 3)
So(len(conversations), ShouldEqual, 1)

conversations, err = alice.client.ConversationList(internalCtx, &node.ConversationListInput{})
So(err, ShouldBeNil)
So(len(conversations), ShouldEqual, 3)
So(len(conversations), ShouldEqual, 1)

envelope = bob.networkDriver.(*mock.SimpleDriver).GetLastReceivedEnvelope()
So(envelope.Source, ShouldEqual, alias.AliasIdentifier)
Expand All @@ -778,11 +778,11 @@ func TestAliasesFlow(t *testing.T) {

conversations, err = bob.client.ConversationList(internalCtx, &node.ConversationListInput{})
So(err, ShouldBeNil)
So(len(conversations), ShouldEqual, 4)
So(len(conversations), ShouldEqual, 1)

conversations, err = alice.client.ConversationList(internalCtx, &node.ConversationListInput{})
So(err, ShouldBeNil)
So(len(conversations), ShouldEqual, 4)
So(len(conversations), ShouldEqual, 1)

envelope = bob.networkDriver.(*mock.SimpleDriver).GetLastReceivedEnvelope()
So(envelope.Source, ShouldNotEqual, alias.AliasIdentifier)
Expand Down
4 changes: 2 additions & 2 deletions core/test/scenario_test.go
Expand Up @@ -176,7 +176,7 @@ func scenario(t *testing.T, alice, bob, eve *AppMock) {
So(memberAlice.Contact.DisplayName, ShouldEqual, "Alice")
So(memberBob.ContactID, ShouldEqual, bob.node.UserID())
So(memberAlice.ContactID, ShouldEqual, alice.node.UserID())
So(memberBob.Status, ShouldEqual, entity.ConversationMember_Active)
So(memberBob.Status, ShouldEqual, entity.ConversationMember_Owner)
So(memberAlice.Status, ShouldEqual, entity.ConversationMember_Owner)

everythingWentFine()
Expand All @@ -196,7 +196,7 @@ func scenario(t *testing.T, alice, bob, eve *AppMock) {
case alice.node.UserID():
So(member.Status, ShouldEqual, entity.ConversationMember_Owner)
case bob.node.UserID():
So(member.Status, ShouldEqual, entity.ConversationMember_Active)
So(member.Status, ShouldEqual, entity.ConversationMember_Owner)
}
}

Expand Down

0 comments on commit 6379a65

Please sign in to comment.