From b42baef6c59647508be092dd5e09bdb5bcb0caf6 Mon Sep 17 00:00:00 2001 From: Dan Ballard Date: Thu, 31 Oct 2019 14:39:31 -0700 Subject: [PATCH] add get/set attribute for profile/contact/group to cwtch_peer that does the action and emits an event; rename profile.GetGroupByGroupID to GetGroup for consitency --- model/message.go | 4 +-- model/message_test.go | 4 +-- model/profile.go | 8 ++--- model/profile_test.go | 10 +++--- peer/cwtch_peer.go | 69 +++++++++++++++++++++++++++++++++++++--- storage/profile_store.go | 2 +- 6 files changed, 79 insertions(+), 18 deletions(-) diff --git a/model/message.go b/model/message.go index 4bcd378..69d5c96 100644 --- a/model/message.go +++ b/model/message.go @@ -23,8 +23,8 @@ type Message struct { Message string Signature []byte PreviousMessageSig []byte - ReceivedByServer bool // messages sent to a server - Acknowledged bool // peer to peer + ReceivedByServer bool // messages sent to a server + Acknowledged bool // peer to peer Error string `json:",omitempty"` } diff --git a/model/message_test.go b/model/message_test.go index 007af59..49516d5 100644 --- a/model/message_test.go +++ b/model/message_test.go @@ -18,7 +18,7 @@ func TestMessagePadding(t *testing.T) { sarah.ProcessInvite(string(invite), alice.Onion) - group := alice.GetGroupByGroupID(gid) + group := alice.GetGroup(gid) c1, s1, err := sarah.EncryptMessageToGroup("Hello World 1", group.GroupID) t.Logf("Length of Encrypted Message: %v %v", len(c1), err) @@ -51,7 +51,7 @@ func TestTranscriptConsistency(t *testing.T) { sarah.ProcessInvite(string(invite), alice.Onion) - group := alice.GetGroupByGroupID(gid) + group := alice.GetGroup(gid) t.Logf("group: %v, sarah %v", group, sarah) diff --git a/model/profile.go b/model/profile.go index f434d8d..fef480d 100644 --- a/model/profile.go +++ b/model/profile.go @@ -308,7 +308,7 @@ func (p *Profile) GetContact(onion string) (*PublicProfile, bool) { // VerifyGroupMessage confirms the authenticity of a message given an onion, message and signature. func (p *Profile) VerifyGroupMessage(onion string, groupID string, message string, timestamp int32, ciphertext []byte, signature []byte) bool { - group := p.GetGroupByGroupID(groupID) + group := p.GetGroup(groupID) if group == nil { return false } @@ -356,8 +356,8 @@ func (p *Profile) StartGroupWithMessage(server string, initialMessage []byte) (g return } -// GetGroupByGroupID a pointer to a Group by the group Id, returns nil if no group found. -func (p *Profile) GetGroupByGroupID(groupID string) (g *Group) { +// GetGroup a pointer to a Group by the group Id, returns nil if no group found. +func (p *Profile) GetGroup(groupID string) (g *Group) { p.lock.Lock() defer p.lock.Unlock() g = p.Groups[groupID] @@ -433,7 +433,7 @@ func (p *Profile) EncryptMessageToGroup(message string, groupID string) ([]byte, return nil, nil, errors.New("group message is too long") } - group := p.GetGroupByGroupID(groupID) + group := p.GetGroup(groupID) if group != nil { timestamp := time.Now().Unix() diff --git a/model/profile_test.go b/model/profile_test.go index 238e228..8484d95 100644 --- a/model/profile_test.go +++ b/model/profile_test.go @@ -69,9 +69,9 @@ func TestRejectGroupInvite(t *testing.T) { gid, invite, _ := alice.StartGroup("2c3kmoobnyghj2zw6pwv7d57yzld753auo3ugauezzpvfak3ahc4bdyd") sarah.ProcessInvite(string(invite), alice.Onion) - group := alice.GetGroupByGroupID(gid) + group := alice.GetGroup(gid) if len(sarah.Groups) == 1 { - if sarah.GetGroupByGroupID(group.GroupID).Accepted { + if sarah.GetGroup(group.GroupID).Accepted { t.Errorf("Group should not be accepted") } sarah.RejectInvite(group.GroupID) @@ -95,18 +95,18 @@ func TestProfileGroup(t *testing.T) { t.Errorf("sarah should only be in 1 group instead: %v", sarah.GetGroups()) } - group := alice.GetGroupByGroupID(gid) + group := alice.GetGroup(gid) sarah.AcceptInvite(group.GroupID) c, s1, _ := sarah.EncryptMessageToGroup("Hello World", group.GroupID) alice.AttemptDecryption(c, s1) gid2, invite2, _ := alice.StartGroup("2c3kmoobnyghj2zw6pwv7d57yzld753auo3ugauezzpvfak3ahc4bdyd") sarah.ProcessInvite(string(invite2), alice.Onion) - group2 := alice.GetGroupByGroupID(gid2) + group2 := alice.GetGroup(gid2) c2, s2, _ := sarah.EncryptMessageToGroup("Hello World", group2.GroupID) alice.AttemptDecryption(c2, s2) - sarahGroup := sarah.GetGroupByGroupID(group.GroupID) + sarahGroup := sarah.GetGroup(group.GroupID) im := sarahGroup.GetInitialMessage() if string(im) != "Hello World" { t.Errorf("Initial Message was not stored properly: %v", im) diff --git a/peer/cwtch_peer.go b/peer/cwtch_peer.go index 44cd4b6..7a70eeb 100644 --- a/peer/cwtch_peer.go +++ b/peer/cwtch_peer.go @@ -64,6 +64,13 @@ type CwtchPeer interface { GetContacts() []string GetContact(string) *model.PublicProfile + SetAttribute(string, string) + GetAttribute(string) (string, bool) + SetContactAttribute(string, string, string) + GetContactAttribute(string, string) (string, bool) + SetGroupAttribute(string, string, string) + GetGroupAttribute(string, string) (string, bool) + Listen() StartPeersConnections() StartGroupConnections() @@ -124,7 +131,7 @@ func (cp *cwtchPeer) ImportGroup(exportedInvite string) (err error) { // ExportGroup serializes a group invite so it can be given offline func (cp *cwtchPeer) ExportGroup(groupID string) (string, error) { - group := cp.Profile.GetGroupByGroupID(groupID) + group := cp.Profile.GetGroup(groupID) if group != nil { invite, err := group.Invite(group.GetInitialMessage()) if err == nil { @@ -164,7 +171,7 @@ func (cp *cwtchPeer) GetGroups() []string { // GetGroup returns a pointer to a specific group, nil if no group exists. func (cp *cwtchPeer) GetGroup(groupID string) *model.Group { - return cp.Profile.GetGroupByGroupID(groupID) + return cp.Profile.GetGroup(groupID) } func (cp *cwtchPeer) AddContact(nick, onion string, trusted bool) { @@ -221,7 +228,7 @@ func (cp *cwtchPeer) DeleteGroup(groupID string) { // InviteOnionToGroup kicks off the invite process func (cp *cwtchPeer) InviteOnionToGroup(onion string, groupid string) error { - group := cp.Profile.GetGroupByGroupID(groupid) + group := cp.Profile.GetGroup(groupid) if group == nil { return errors.New("invalid group id") } @@ -248,7 +255,7 @@ func (cp *cwtchPeer) SendMessageToGroup(groupid string, message string) error { // SendMessageToGroup attempts to sent the given message to the given group id. // It returns the signature of the message which can be used to identify it in any UX layer. func (cp *cwtchPeer) SendMessageToGroupTracked(groupid string, message string) (string, error) { - group := cp.Profile.GetGroupByGroupID(groupid) + group := cp.Profile.GetGroup(groupid) if group == nil { return "", errors.New("invalid group id") } @@ -337,6 +344,60 @@ func (cp *cwtchPeer) StartGroupConnections() { } } +// SetAttribute sets an attribute for this profile and emits an event +func (cp *cwtchPeer) SetAttribute(key string, val string) { + cp.Profile.SetAttribute(key, val) + cp.eventBus.Publish(event.NewEvent(event.SetAttribute, map[event.Field]string{ + event.Key: key, + event.Data: val, + })) +} + +// GetAttribute gets an attribute for the profile +func (cp *cwtchPeer) GetAttribute(key string) (string, bool) { + return cp.Profile.GetAttribute(key) +} + +// SetContactAttribute sets an attribute for the indicated contact and emits an event +func (cp *cwtchPeer) SetContactAttribute(onion string, key string, val string) { + if contact, ok := cp.Profile.GetContact(onion); ok { + contact.SetAttribute(key, val) + cp.eventBus.Publish(event.NewEvent(event.SetPeerAttribute, map[event.Field]string{ + event.RemotePeer: onion, + event.Key: key, + event.Data: val, + })) + } +} + +// GetContactAttribute gets an attribute for the indicated contact +func (cp *cwtchPeer) GetContactAttribute(onion string, key string) (string, bool) { + if contact, ok := cp.Profile.GetContact(onion); ok { + return contact.GetAttribute(key) + } + return "", false +} + +// SetGroupAttribute sets an attribute for the indicated group and emits an event +func (cp *cwtchPeer) SetGroupAttribute(gid string, key string, val string) { + if group := cp.Profile.GetGroup(gid); group != nil { + group.SetAttribute(key, val) + cp.eventBus.Publish(event.NewEvent(event.SetGroupAttribute, map[event.Field]string{ + event.GroupID: gid, + event.Key: key, + event.Data: val, + })) + } +} + +// GetGroupAttribute gets an attribute for the indicated group +func (cp *cwtchPeer) GetGroupAttribute(gid string, key string) (string, bool) { + if group := cp.Profile.GetGroup(gid); group != nil { + return group.GetAttribute(key) + } + return "", false +} + // Shutdown kills all connections and cleans up all goroutines for the peer func (cp *cwtchPeer) Shutdown() { cp.shutdown = true diff --git a/storage/profile_store.go b/storage/profile_store.go index 529756c..a7954f8 100644 --- a/storage/profile_store.go +++ b/storage/profile_store.go @@ -195,7 +195,7 @@ func (ps *profileStore) eventHandler() { log.Errorf("error setting attribute on peer %v peer does not exist", ev) } case event.SetGroupAttribute: - group := ps.profile.GetGroupByGroupID(ev.Data[event.GroupID]) + group := ps.profile.GetGroup(ev.Data[event.GroupID]) if group != nil { group.SetAttribute(ev.Data[event.Key], ev.Data[event.Data]) ps.save()