Integrate Group Name into Invite #336
|
@ -46,6 +46,10 @@ const (
|
|||
// Imported
|
||||
NewGroupInvite = Type("NewGroupInvite")
|
||||
|
||||
// Inform the UI about a new group
|
||||
// GroupID: groupID (allows them to fetch from the peer)
|
||||
NewGroup = Type("NewGroup")
|
||||
|
||||
// GroupID
|
||||
AcceptGroupInvite = Type("AcceptGroupInvite")
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package model
|
|||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"cwtch.im/cwtch/model/attr"
|
||||
"cwtch.im/cwtch/protocol/groups"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
@ -64,6 +65,9 @@ func NewGroup(server string) (*Group, error) {
|
|||
copy(group.GroupKey[:], groupKey[:])
|
||||
group.Owner = "self"
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -95,7 +99,8 @@ func (g *Group) Invite(initialMessage []byte) ([]byte, error) {
|
|||
g.InitialMessage = initialMessage[:]
|
||||
|
||||
gci := &groups.GroupInvite{
|
||||
GroupName: g.GroupID,
|
||||
GroupID: g.GroupID,
|
||||
GroupName: g.Attributes[attr.GetLocalScope("name")],
|
||||
|
||||
SharedKey: g.GroupKey[:],
|
||||
ServerHost: g.GroupServer,
|
||||
SignedGroupID: g.SignedGroupID[:],
|
||||
|
|
|
@ -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
|
||||
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
|
||||
err := json.Unmarshal([]byte(invite), &gci)
|
||||
if err == nil {
|
||||
group := new(Group)
|
||||
group.Version = CurrentGroupVersion
|
||||
group.GroupID = gci.GroupName
|
||||
group.GroupID = gci.GroupID
|
||||
group.LocalID = GenerateRandomID()
|
||||
group.SignedGroupID = gci.SignedGroupID
|
||||
copy(group.GroupKey[:], gci.SharedKey[:])
|
||||
|
@ -377,9 +377,9 @@ func (p *Profile) ProcessInvite(invite string, peerHostname string) (string, err
|
|||
group.Owner = peerHostname
|
||||
group.Attributes = make(map[string]string)
|
||||
p.AddGroup(group)
|
||||
return group.GroupID, nil
|
||||
return group.GroupID, gci.GroupName, nil
|
||||
}
|
||||
return "", err
|
||||
return "", "", err
|
||||
dan
commented
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
sarah
commented
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.
|
||||
|
|
|
@ -55,7 +55,7 @@ type CwtchPeer interface {
|
|||
StoreMessage(onion string, messageTxt string, sent time.Time)
|
||||
|
||||
SetContactAuthorization(string, model.Authorization) error
|
||||
ProcessInvite(string, string) (string, error)
|
||||
ProcessInvite(string, string) (string, string, error)
|
||||
AcceptInvite(string) error
|
||||
RejectInvite(string)
|
||||
DeleteContact(string)
|
||||
|
@ -63,6 +63,7 @@ type CwtchPeer interface {
|
|||
|
||||
AddServer(string) error
|
||||
JoinServer(string) error
|
||||
GetServers() []string
|
||||
SendMessageToGroupTracked(string, string) (string, error)
|
||||
|
||||
GetName() string
|
||||
|
@ -294,6 +295,18 @@ func (cp *cwtchPeer) GetContacts() []string {
|
|||
return cp.Profile.GetContacts()
|
||||
}
|
||||
|
||||
// GetServers returns an unordered list of servers
|
||||
func (cp *cwtchPeer) GetServers() []string {
|
||||
dan
commented
cp.mutex.Lock() at the start cp.mutex.Lock()
defer cp.mutex.Unlock()
at the start
sarah
commented
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
|
||||
func (cp *cwtchPeer) GetContact(onion string) *model.PublicProfile {
|
||||
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
|
||||
func (cp *cwtchPeer) ProcessInvite(invite string, remotePeer string) (string, error) {
|
||||
func (cp *cwtchPeer) ProcessInvite(invite string, remotePeer string) (string, string, error) {
|
||||
cp.mutex.Lock()
|
||||
defer cp.mutex.Unlock()
|
||||
return cp.Profile.ProcessInvite(invite, remotePeer)
|
||||
|
@ -656,17 +669,19 @@ func (cp *cwtchPeer) eventHandler() {
|
|||
}
|
||||
case event.NewGroupInvite:
|
||||
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 ev.Data[event.Imported] == "true" {
|
||||
cp.Profile.GetGroup(group).Accepted = true
|
||||
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)
|
||||
cp.mutex.Lock()
|
||||
if err != nil {
|
||||
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()
|
||||
case event.PeerStateChange:
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
// Fuzz various group related functions
|
||||
func Fuzz(data []byte) int {
|
||||
profile := model.GenerateNewProfile("fuzz")
|
||||
inviteid, err := profile.ProcessInvite(string(data), profile.Onion)
|
||||
inviteid, _, err := profile.ProcessInvite(string(data), profile.Onion)
|
||||
|
||||
if err != nil {
|
||||
if inviteid != "" {
|
||||
|
|
|
@ -11,6 +11,7 @@ const CwtchServerSyncedCapability = tapir.Capability("CwtchServerSyncedCapabilit
|
|||
|
||||
// GroupInvite provides a structured type for communicating group information to peers
|
||||
type GroupInvite struct {
|
||||
GroupID string
|
||||
GroupName string
|
||||
SignedGroupID []byte
|
||||
Timestamp uint64
|
||||
|
|
|
@ -82,4 +82,7 @@ func main() {
|
|||
bundle := server.KeyBundle().Serialize()
|
||||
log.Infof("Server Config: server:%s", base64.StdEncoding.EncodeToString(bundle))
|
||||
server.Run(acn)
|
||||
for {
|
||||
time.Sleep(time.Second)
|
||||
dan
commented
hahahha oph... hahahha oph...
sarah
commented
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.
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ type Server struct {
|
|||
onionServiceStopped bool
|
||||
running bool
|
||||
existingMessageCount int
|
||||
lock sync.RWMutex
|
||||
lock sync.RWMutex
|
||||
}
|
||||
|
||||
// Setup initialized a server from a given configuration
|
||||
|
|
|
@ -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)
|
||||
dan
commented
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
sarah
commented
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) {
|
||||
gid, err := ps.profile.ProcessInvite(string(invite), peer)
|
||||
gid, _, err := ps.profile.ProcessInvite(string(invite), peer)
|
||||
if err == nil {
|
||||
ps.save()
|
||||
group := ps.profile.Groups[gid]
|
||||
|
|
|
@ -373,7 +373,7 @@ func (ps *ProfileStoreV1) eventHandler() {
|
|||
log.Errorf("error accepting group invite")
|
||||
}
|
||||
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 {
|
||||
ps.save()
|
||||
group := ps.profile.Groups[gid]
|
||||
|
|
for ease and safety of reuseability from clients, might want to replace "name" with a const in model/group.go ... Name
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.