Integrate Group Name into Invite #336

Merged
dan merged 1 commits from group_create_ui into master 2020-12-17 05:54:03 +00:00
10 changed files with 41 additions and 13 deletions

View File

@ -46,6 +46,10 @@ const (
// Imported // Imported
NewGroupInvite = Type("NewGroupInvite") NewGroupInvite = Type("NewGroupInvite")
// Inform the UI about a new group
// GroupID: groupID (allows them to fetch from the peer)
NewGroup = Type("NewGroup")
// GroupID // GroupID
AcceptGroupInvite = Type("AcceptGroupInvite") AcceptGroupInvite = Type("AcceptGroupInvite")

View File

@ -2,6 +2,7 @@ package model
import ( import (
"crypto/rand" "crypto/rand"
"cwtch.im/cwtch/model/attr"
"cwtch.im/cwtch/protocol/groups" "cwtch.im/cwtch/protocol/groups"
"encoding/json" "encoding/json"
"errors" "errors"
@ -64,6 +65,9 @@ func NewGroup(server string) (*Group, error) {
copy(group.GroupKey[:], groupKey[:]) copy(group.GroupKey[:], groupKey[:])
group.Owner = "self" group.Owner = "self"
group.Attributes = make(map[string]string) group.Attributes = make(map[string]string)
// By default we set the "name" of the group to a random string, we can override this later, but to simplify the
// codes around invite, we assume that this is always set.
group.Attributes[attr.GetLocalScope("name")] = group.GroupID
return group, nil return group, nil
} }
@ -95,7 +99,8 @@ func (g *Group) Invite(initialMessage []byte) ([]byte, error) {
g.InitialMessage = initialMessage[:] g.InitialMessage = initialMessage[:]
gci := &groups.GroupInvite{ gci := &groups.GroupInvite{
GroupName: g.GroupID, GroupID: g.GroupID,
GroupName: g.Attributes[attr.GetLocalScope("name")],
Outdated
Review

for ease and safety of reuseability from clients, might want to replace "name" with a const in model/group.go ... Name

for ease and safety of reuseability from clients, might want to replace "name" with a const in model/group.go ... Name
Outdated
Review

This needs a wider rethink as we are technically crossing boundaries here already, and duplicating constants isn't the right approach - we either should extract this code out or move the UI code back.

This needs a wider rethink as we are technically crossing boundaries here already, and duplicating constants isn't the right approach - we either should extract this code out or move the UI code back.
SharedKey: g.GroupKey[:], SharedKey: g.GroupKey[:],
ServerHost: g.GroupServer, ServerHost: g.GroupServer,
SignedGroupID: g.SignedGroupID[:], SignedGroupID: g.SignedGroupID[:],

View File

@ -361,13 +361,13 @@ func (p *Profile) GetGroup(groupID string) (g *Group) {
} }
// ProcessInvite adds a new group invite to the profile. returns the new group ID // ProcessInvite adds a new group invite to the profile. returns the new group ID
func (p *Profile) ProcessInvite(invite string, peerHostname string) (string, error) { func (p *Profile) ProcessInvite(invite string, peerHostname string) (string, string, error) {
var gci groups.GroupInvite var gci groups.GroupInvite
err := json.Unmarshal([]byte(invite), &gci) err := json.Unmarshal([]byte(invite), &gci)
if err == nil { if err == nil {
group := new(Group) group := new(Group)
group.Version = CurrentGroupVersion group.Version = CurrentGroupVersion
group.GroupID = gci.GroupName group.GroupID = gci.GroupID
group.LocalID = GenerateRandomID() group.LocalID = GenerateRandomID()
group.SignedGroupID = gci.SignedGroupID group.SignedGroupID = gci.SignedGroupID
copy(group.GroupKey[:], gci.SharedKey[:]) copy(group.GroupKey[:], gci.SharedKey[:])
@ -377,9 +377,9 @@ func (p *Profile) ProcessInvite(invite string, peerHostname string) (string, err
group.Owner = peerHostname group.Owner = peerHostname
group.Attributes = make(map[string]string) group.Attributes = make(map[string]string)
p.AddGroup(group) p.AddGroup(group)
return group.GroupID, nil return group.GroupID, gci.GroupName, nil
} }
return "", err return "", "", err
Outdated
Review

should use SetAttribute() which uses p.lock.Lock() (ProcessInvite mostly just operates on args, doesnt touch the Profile, except fotthe call to AddGroup, which also uses the lock

should use SetAttribute() which uses p.lock.Lock() (ProcessInvite mostly just operates on args, doesnt touch the Profile, except fotthe call to AddGroup, which also uses the lock
Outdated
Review

Ah yeah I wrote this code before writing the other code that actually does what you suggest and is in this PR...will delete.

Ah yeah I wrote this code before writing the other code that actually does what you suggest and is in this PR...will delete.
} }
// AddGroup is a convenience method for adding a group to a profile. // AddGroup is a convenience method for adding a group to a profile.

View File

@ -55,7 +55,7 @@ type CwtchPeer interface {
StoreMessage(onion string, messageTxt string, sent time.Time) StoreMessage(onion string, messageTxt string, sent time.Time)
SetContactAuthorization(string, model.Authorization) error SetContactAuthorization(string, model.Authorization) error
ProcessInvite(string, string) (string, error) ProcessInvite(string, string) (string, string, error)
AcceptInvite(string) error AcceptInvite(string) error
RejectInvite(string) RejectInvite(string)
DeleteContact(string) DeleteContact(string)
@ -63,6 +63,7 @@ type CwtchPeer interface {
AddServer(string) error AddServer(string) error
JoinServer(string) error JoinServer(string) error
GetServers() []string
SendMessageToGroupTracked(string, string) (string, error) SendMessageToGroupTracked(string, string) (string, error)
GetName() string GetName() string
@ -294,6 +295,18 @@ func (cp *cwtchPeer) GetContacts() []string {
return cp.Profile.GetContacts() return cp.Profile.GetContacts()
} }
// GetServers returns an unordered list of servers
func (cp *cwtchPeer) GetServers() []string {
Outdated
Review

cp.mutex.Lock()
defer cp.mutex.Unlock()

at the start

cp.mutex.Lock() defer cp.mutex.Unlock() at the start
Outdated
Review

This would cause a deadlock because this only calls other peer functions.

This would cause a deadlock because this only calls other peer functions.
contacts := cp.Profile.GetContacts()
var servers []string
for _, contact := range contacts {
if cp.GetContact(contact).IsServer() {
servers = append(servers, contact)
}
}
return servers
}
// GetContact returns a given contact, nil is no such contact exists // GetContact returns a given contact, nil is no such contact exists
func (cp *cwtchPeer) GetContact(onion string) *model.PublicProfile { func (cp *cwtchPeer) GetContact(onion string) *model.PublicProfile {
cp.mutex.Lock() cp.mutex.Lock()
@ -440,7 +453,7 @@ func (cp *cwtchPeer) SetContactAuthorization(peer string, authorization model.Au
} }
// ProcessInvite adds a new group invite to the profile. returns the new group ID // ProcessInvite adds a new group invite to the profile. returns the new group ID
func (cp *cwtchPeer) ProcessInvite(invite string, remotePeer string) (string, error) { func (cp *cwtchPeer) ProcessInvite(invite string, remotePeer string) (string, string, error) {
cp.mutex.Lock() cp.mutex.Lock()
defer cp.mutex.Unlock() defer cp.mutex.Unlock()
return cp.Profile.ProcessInvite(invite, remotePeer) return cp.Profile.ProcessInvite(invite, remotePeer)
@ -656,17 +669,19 @@ func (cp *cwtchPeer) eventHandler() {
} }
case event.NewGroupInvite: case event.NewGroupInvite:
cp.mutex.Lock() cp.mutex.Lock()
group, err := cp.Profile.ProcessInvite(ev.Data[event.GroupInvite], ev.Data[event.RemotePeer]) group, groupName, err := cp.Profile.ProcessInvite(ev.Data[event.GroupInvite], ev.Data[event.RemotePeer])
if err == nil { if err == nil {
if ev.Data[event.Imported] == "true" { if ev.Data[event.Imported] == "true" {
cp.Profile.GetGroup(group).Accepted = true cp.Profile.GetGroup(group).Accepted = true
cp.mutex.Unlock() // TODO...seriously need a better way of handling these cases cp.mutex.Unlock() // TODO...seriously need a better way of handling these cases
cp.SetGroupAttribute(group, attr.GetLocalScope("name"), groupName)
err = cp.JoinServer(cp.Profile.GetGroup(group).GroupServer) err = cp.JoinServer(cp.Profile.GetGroup(group).GroupServer)
cp.mutex.Lock() cp.mutex.Lock()
if err != nil { if err != nil {
log.Errorf("Joining Server should have worked %v", err) log.Errorf("Joining Server should have worked %v", err)
} }
} }
cp.eventBus.Publish(event.NewEvent(event.NewGroup, map[event.Field]string{event.GroupID: group}))
} }
cp.mutex.Unlock() cp.mutex.Unlock()
case event.PeerStateChange: case event.PeerStateChange:

View File

@ -10,7 +10,7 @@ import (
// Fuzz various group related functions // Fuzz various group related functions
func Fuzz(data []byte) int { func Fuzz(data []byte) int {
profile := model.GenerateNewProfile("fuzz") profile := model.GenerateNewProfile("fuzz")
inviteid, err := profile.ProcessInvite(string(data), profile.Onion) inviteid, _, err := profile.ProcessInvite(string(data), profile.Onion)
if err != nil { if err != nil {
if inviteid != "" { if inviteid != "" {

View File

@ -11,6 +11,7 @@ const CwtchServerSyncedCapability = tapir.Capability("CwtchServerSyncedCapabilit
// GroupInvite provides a structured type for communicating group information to peers // GroupInvite provides a structured type for communicating group information to peers
type GroupInvite struct { type GroupInvite struct {
GroupID string
GroupName string GroupName string
SignedGroupID []byte SignedGroupID []byte
Timestamp uint64 Timestamp uint64

View File

@ -82,4 +82,7 @@ func main() {
bundle := server.KeyBundle().Serialize() bundle := server.KeyBundle().Serialize()
log.Infof("Server Config: server:%s", base64.StdEncoding.EncodeToString(bundle)) log.Infof("Server Config: server:%s", base64.StdEncoding.EncodeToString(bundle))
server.Run(acn) server.Run(acn)
for {
time.Sleep(time.Second)
Outdated
Review

hahahha oph...

hahahha oph...
Outdated
Review

Not technically part of this PR but it works better...needs a complete rework, but out of scope.

Not technically part of this PR but it works better...needs a complete rework, but out of scope.
}
} }

View File

@ -32,7 +32,7 @@ type Server struct {
onionServiceStopped bool onionServiceStopped bool
running bool running bool
existingMessageCount int existingMessageCount int
lock sync.RWMutex lock sync.RWMutex
} }
// Setup initialized a server from a given configuration // Setup initialized a server from a given configuration

View File

@ -52,9 +52,9 @@ func ReadProfile(directory, password string) (*model.Profile, error) {
/********************************************************************************************/ /********************************************************************************************/
// AddGroup For testing, adds a group to the profile (and startsa stream store) // AddGroup For testing, adds a group to the profile (and starts a stream store)
Outdated
Review

this is legacy v0 storage engine, just for loading old saves in order to upgrad them to v1

AddGroup here can just be (and should be deleted) rather than updated to post v0 model changes. As the models it imports change... unless we make a model/v0 ... it's window of usability dwindles anyways

this is legacy v0 storage engine, just for loading old saves in order to upgrad them to v1 AddGroup here can just be (and should be deleted) rather than updated to post v0 model changes. As the models it imports change... unless we make a model/v0 ... it's window of usability dwindles anyways
Outdated
Review

Moving this to an issue, since deprecation is a separate concern.

Moving this to an issue, since deprecation is a separate concern.
func (ps *ProfileStoreV0) AddGroup(invite []byte, peer string) { func (ps *ProfileStoreV0) AddGroup(invite []byte, peer string) {
gid, err := ps.profile.ProcessInvite(string(invite), peer) gid, _, err := ps.profile.ProcessInvite(string(invite), peer)
if err == nil { if err == nil {
ps.save() ps.save()
group := ps.profile.Groups[gid] group := ps.profile.Groups[gid]

View File

@ -373,7 +373,7 @@ func (ps *ProfileStoreV1) eventHandler() {
log.Errorf("error accepting group invite") log.Errorf("error accepting group invite")
} }
case event.NewGroupInvite: case event.NewGroupInvite:
gid, err := ps.profile.ProcessInvite(ev.Data[event.GroupInvite], ev.Data[event.RemotePeer]) gid, _, err := ps.profile.ProcessInvite(ev.Data[event.GroupInvite], ev.Data[event.RemotePeer])
if err == nil { if err == nil {
ps.save() ps.save()
group := ps.profile.Groups[gid] group := ps.profile.Groups[gid]