Merge pull request 'Completely Remove SetAttribute and GetAttribute.' (#396) from deprecate_get_attribute into master
Reviewed-on: #396
This commit is contained in:
commit
a30f8c4fa5
|
@ -16,6 +16,10 @@ ebusgraph.txt
|
||||||
messages/
|
messages/
|
||||||
serverMonitorReport.txt
|
serverMonitorReport.txt
|
||||||
testing/cwtch.out.png
|
testing/cwtch.out.png
|
||||||
|
testing/filesharing/storage
|
||||||
|
testing/filesharing/tordir
|
||||||
|
testing/filesharing/cwtch.out.png
|
||||||
|
testing/filesharing/cwtch.out.png.manifest
|
||||||
testing/cwtch.out.png.manifest
|
testing/cwtch.out.png.manifest
|
||||||
testing/tordir/
|
testing/tordir/
|
||||||
tokens-bak.db
|
tokens-bak.db
|
||||||
|
|
|
@ -4,6 +4,8 @@ import (
|
||||||
"cwtch.im/cwtch/app/plugins"
|
"cwtch.im/cwtch/app/plugins"
|
||||||
"cwtch.im/cwtch/event"
|
"cwtch.im/cwtch/event"
|
||||||
"cwtch.im/cwtch/model"
|
"cwtch.im/cwtch/model"
|
||||||
|
"cwtch.im/cwtch/model/attr"
|
||||||
|
"cwtch.im/cwtch/model/constants"
|
||||||
"cwtch.im/cwtch/peer"
|
"cwtch.im/cwtch/peer"
|
||||||
"cwtch.im/cwtch/protocol/connections"
|
"cwtch.im/cwtch/protocol/connections"
|
||||||
"cwtch.im/cwtch/storage"
|
"cwtch.im/cwtch/storage"
|
||||||
|
@ -18,9 +20,6 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AttributeTag is a const name for a peer attribute that can be set at creation time, for example for versioning info
|
|
||||||
const AttributeTag = "tag"
|
|
||||||
|
|
||||||
type applicationCore struct {
|
type applicationCore struct {
|
||||||
eventBuses map[string]event.Manager
|
eventBuses map[string]event.Manager
|
||||||
|
|
||||||
|
@ -58,7 +57,7 @@ type Application interface {
|
||||||
Shutdown()
|
Shutdown()
|
||||||
|
|
||||||
GetPeer(onion string) peer.CwtchPeer
|
GetPeer(onion string) peer.CwtchPeer
|
||||||
ListPeers() map[string]string
|
ListProfiles() []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadProfileFn is the function signature for a function in an app that loads a profile
|
// LoadProfileFn is the function signature for a function in an app that loads a profile
|
||||||
|
@ -131,7 +130,7 @@ func (app *application) CreateTaggedPeer(name string, password string, tag strin
|
||||||
app.engines[profile.Onion] = engine
|
app.engines[profile.Onion] = engine
|
||||||
|
|
||||||
if tag != "" {
|
if tag != "" {
|
||||||
p.SetAttribute(AttributeTag, tag)
|
p.SetScopedZonedAttribute(attr.LocalScope, attr.ProfileZone, constants.Tag, tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
app.appBus.Publish(event.NewEvent(event.NewPeer, map[event.Field]string{event.Identity: profile.Onion, event.Created: event.True}))
|
app.appBus.Publish(event.NewEvent(event.NewPeer, map[event.Field]string{event.Identity: profile.Onion, event.Created: event.True}))
|
||||||
|
|
|
@ -106,10 +106,6 @@ func (as *applicationService) createPeer(name, password, tag string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if tag != "" {
|
|
||||||
profile.SetAttribute(AttributeTag, tag)
|
|
||||||
}
|
|
||||||
|
|
||||||
profileStore := storage.CreateProfileWriterStore(as.eventBuses[profile.Onion], path.Join(as.directory, "profiles", profile.LocalID), password, profile)
|
profileStore := storage.CreateProfileWriterStore(as.eventBuses[profile.Onion], path.Join(as.directory, "profiles", profile.LocalID), password, profile)
|
||||||
|
|
||||||
peerAuthorizations := profile.ContactsAuthorizations()
|
peerAuthorizations := profile.ContactsAuthorizations()
|
||||||
|
|
|
@ -62,14 +62,14 @@ func (ap *appletPeers) LaunchPeers() {
|
||||||
ap.launched = true
|
ap.launched = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListPeers returns a map of onions to their profile's Name
|
// ListProfiles returns a map of onions to their profile's Name
|
||||||
func (ap *appletPeers) ListPeers() map[string]string {
|
func (ap *appletPeers) ListProfiles() []string {
|
||||||
keys := map[string]string{}
|
var keys []string
|
||||||
|
|
||||||
ap.peerLock.Lock()
|
ap.peerLock.Lock()
|
||||||
defer ap.peerLock.Unlock()
|
defer ap.peerLock.Unlock()
|
||||||
for k, p := range ap.peers {
|
for handle := range ap.peers {
|
||||||
keys[k] = p.GetOnion()
|
keys = append(keys, handle)
|
||||||
}
|
}
|
||||||
return keys
|
return keys
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,86 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
app2 "cwtch.im/cwtch/app"
|
|
||||||
"cwtch.im/cwtch/app/utils"
|
|
||||||
"cwtch.im/cwtch/peer"
|
|
||||||
"cwtch.im/cwtch/protocol/connections"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"git.openprivacy.ca/openprivacy/connectivity/tor"
|
|
||||||
"os"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func waitForPeerGroupConnection(peer peer.CwtchPeer, groupID string) error {
|
|
||||||
for {
|
|
||||||
group := peer.GetGroup(groupID)
|
|
||||||
if group != nil {
|
|
||||||
state, _ := peer.GetGroupState(groupID)
|
|
||||||
if state == connections.FAILED {
|
|
||||||
return errors.New("Connection to group " + groupID + " failed!")
|
|
||||||
}
|
|
||||||
if state != connections.AUTHENTICATED {
|
|
||||||
fmt.Printf("peer %v waiting to authenticate with group %v 's server, current state: %v\n", peer.GetOnion(), groupID, connections.ConnectionStateName[state])
|
|
||||||
time.Sleep(time.Second * 10)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return errors.New("peer server connections should have entry for server but do not")
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if len(os.Args) != 2 {
|
|
||||||
fmt.Printf("Usage: ./servermon SERVER_ADDRESS\n")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
serverAddr := os.Args[1]
|
|
||||||
|
|
||||||
acn, err := tor.NewTorACN(".", "")
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Could not start tor: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
app := app2.NewApp(acn, ".")
|
|
||||||
|
|
||||||
app.CreatePeer("servermon", "be gay, do crimes")
|
|
||||||
|
|
||||||
botPeer := utils.WaitGetPeer(app, "servermon")
|
|
||||||
|
|
||||||
fmt.Printf("Connecting to %v...\n", serverAddr)
|
|
||||||
botPeer.JoinServer(serverAddr)
|
|
||||||
groupID, _, err := botPeer.StartGroup(serverAddr)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Error creating group on server %v: %v\n", serverAddr, err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = waitForPeerGroupConnection(botPeer, groupID)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Could not connect to server %v: %v\n", serverAddr, err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
timeout := 1 * time.Second
|
|
||||||
timeElapsed := 0 * time.Second
|
|
||||||
for {
|
|
||||||
_, err := botPeer.SendMessageToGroupTracked(groupID, timeout.String())
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Sent to group on server %v failed at interval %v of total %v with: %v\n", serverAddr, timeout, timeElapsed, err)
|
|
||||||
os.Exit(1)
|
|
||||||
} else {
|
|
||||||
fmt.Printf("Successfully sent message to %v at interval %v of total %v\n", serverAddr, timeout, timeElapsed)
|
|
||||||
}
|
|
||||||
time.Sleep(timeout)
|
|
||||||
timeElapsed += timeout
|
|
||||||
if timeout < 2*time.Minute {
|
|
||||||
timeout = timeout * 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,159 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"git.openprivacy.ca/openprivacy/log"
|
|
||||||
"os"
|
|
||||||
//"bufio"
|
|
||||||
//"cwtch.im/cwtch/storage"
|
|
||||||
)
|
|
||||||
|
|
||||||
func convertTorFile(filename string, password string) error {
|
|
||||||
return errors.New("this code doesn't work and can never work :( it's a math thing")
|
|
||||||
|
|
||||||
/*name, _ := diceware.Generate(2)
|
|
||||||
sk, err := ioutil.ReadFile("hs_ed25519_secret_key")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
sk = sk[32:]
|
|
||||||
|
|
||||||
pk, err := ioutil.ReadFile("hs_ed25519_public_key")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
pk = pk[32:]
|
|
||||||
|
|
||||||
onion, err := ioutil.ReadFile("hostname")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
onion = onion[:56]
|
|
||||||
|
|
||||||
peer := libpeer.NewCwtchPeer(strings.Join(name, "-"))
|
|
||||||
|
|
||||||
fmt.Printf("%d %d %s\n", len(peer.GetProfile().Ed25519PublicKey), len(peer.GetProfile().Ed25519PrivateKey), peer.GetProfile().Onion)
|
|
||||||
peer.GetProfile().Ed25519PrivateKey = sk
|
|
||||||
peer.GetProfile().Ed25519PublicKey = pk
|
|
||||||
peer.GetProfile().Onion = string(onion)
|
|
||||||
fileStore := storage2.NewFileStore(filename, password)
|
|
||||||
err = fileStore.save(peer)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Infof("success! loaded %d byte pk and %d byte sk for %s.onion\n", len(pk), len(sk), onion)
|
|
||||||
return nil*/
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
func vanity() error {
|
|
||||||
for {
|
|
||||||
pk, sk, err := ed25519.GenerateKey(rand.Reader)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
onion := utils.GetTorV3Hostname(pk)
|
|
||||||
for i := 4; i < len(os.Args); i++ {
|
|
||||||
if strings.HasPrefix(onion, os.Args[i]) {
|
|
||||||
peer := libpeer.NewCwtchPeer(os.Args[i])
|
|
||||||
peer.GetProfile().Ed25519PrivateKey = sk
|
|
||||||
peer.GetProfile().Ed25519PublicKey = pk
|
|
||||||
peer.GetProfile().Onion = onion
|
|
||||||
profileStore, _ := storage2.NewProfileStore(nil, os.Args[3], onion+".cwtch")
|
|
||||||
profileStore.Init("")
|
|
||||||
// need to signal new onion? impossible
|
|
||||||
log.Infof("found %s.onion\n", onion)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
func printHelp() {
|
|
||||||
log.Infoln("usage: cwtchutil {help, convert-cwtch-file, convert-tor-file, changepw, vanity}")
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
log.SetLevel(log.LevelInfo)
|
|
||||||
if len(os.Args) < 2 {
|
|
||||||
printHelp()
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch os.Args[1] {
|
|
||||||
default:
|
|
||||||
printHelp()
|
|
||||||
case "help":
|
|
||||||
printHelp()
|
|
||||||
case "convert-tor-file":
|
|
||||||
if len(os.Args) != 4 {
|
|
||||||
fmt.Println("example: cwtchutil convert-tor-file /var/lib/tor/hs1 passw0rd")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
err := convertTorFile(os.Args[2], os.Args[3])
|
|
||||||
if err != nil {
|
|
||||||
log.Errorln(err)
|
|
||||||
}
|
|
||||||
/*case "vanity":
|
|
||||||
if len(os.Args) < 5 {
|
|
||||||
fmt.Println("example: cwtchutil vanity 4 passw0rd erinn openpriv")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
goroutines, err := strconv.Atoi(os.Args[2])
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("first parameter after vanity should be a number\n")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
log.Infoln("searching. press ctrl+c to stop")
|
|
||||||
for i := 0; i < goroutines; i++ {
|
|
||||||
go vanity()
|
|
||||||
}
|
|
||||||
|
|
||||||
for { // run until ctrl+c
|
|
||||||
time.Sleep(time.Hour * 24)
|
|
||||||
}*/
|
|
||||||
/*case "changepw":
|
|
||||||
if len(os.Args) != 3 {
|
|
||||||
fmt.Println("example: cwtch changepw ~/.cwtch/profiles/XXX")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("old password: ")
|
|
||||||
reader := bufio.NewReader(os.Stdin)
|
|
||||||
pw, err := reader.ReadString('\n')
|
|
||||||
if err != nil {
|
|
||||||
log.Errorln(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
pw = pw[:len(pw)-1]
|
|
||||||
|
|
||||||
profileStore, _ := storage.NewProfileStore(nil, os.Args[2], pw)
|
|
||||||
|
|
||||||
err = profileStore.Read()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorln(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("new password: ")
|
|
||||||
newpw1, err := reader.ReadString('\n')
|
|
||||||
if err != nil {
|
|
||||||
log.Errorln(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
newpw1 = newpw1[:len(newpw1)-1] // fuck go with this linebreak shit ^ea
|
|
||||||
|
|
||||||
fileStore2, _ := storage.NewProfileStore(nil, os.Args[2], newpw1)
|
|
||||||
// No way to copy, populate this method
|
|
||||||
err = fileStore2.save(peer)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorln(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Infoln("success!")
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
app2 "cwtch.im/cwtch/app"
|
|
||||||
"cwtch.im/cwtch/app/utils"
|
|
||||||
"cwtch.im/cwtch/event"
|
|
||||||
"git.openprivacy.ca/openprivacy/connectivity/tor"
|
|
||||||
"git.openprivacy.ca/openprivacy/log"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
|
|
||||||
// System Setup, We need Tor and Logging up and Running
|
|
||||||
log.AddEverythingFromPattern("peer/alice")
|
|
||||||
log.SetLevel(log.LevelDebug)
|
|
||||||
|
|
||||||
acn, err := tor.NewTorACN(path.Join(".", ".cwtch"), "")
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("\nError connecting to Tor: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
app := app2.NewApp(acn, ".")
|
|
||||||
app.CreatePeer("alice", "be gay, do crimes")
|
|
||||||
alice := utils.WaitGetPeer(app, "alice")
|
|
||||||
app.LaunchPeers()
|
|
||||||
eventBus := app.GetEventBus(alice.GetOnion())
|
|
||||||
queue := event.NewQueue()
|
|
||||||
eventBus.Subscribe(event.NewMessageFromPeer, queue)
|
|
||||||
|
|
||||||
// For every new Data Packet Alice received she will Print it out.
|
|
||||||
for {
|
|
||||||
event := queue.Next()
|
|
||||||
log.Printf(log.LevelInfo, "Received %v from %v: %s", event.EventType, event.Data["Onion"], event.Data["Data"])
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
app2 "cwtch.im/cwtch/app"
|
|
||||||
"cwtch.im/cwtch/app/utils"
|
|
||||||
"git.openprivacy.ca/openprivacy/connectivity/tor"
|
|
||||||
"git.openprivacy.ca/openprivacy/log"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
|
|
||||||
// System Boilerplate, We need Tor Up and Running
|
|
||||||
log.AddEverythingFromPattern("peer/bob")
|
|
||||||
log.SetLevel(log.LevelDebug)
|
|
||||||
acn, err := tor.NewTorACN(path.Join(".", ".cwtch"), "")
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("\nError connecting to Tor: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
app := app2.NewApp(acn, ".")
|
|
||||||
app.CreatePeer("bob", "be gay, do crimes")
|
|
||||||
bob := utils.WaitGetPeer(app, "bob")
|
|
||||||
|
|
||||||
// Add Alice's Onion Here (It changes run to run)
|
|
||||||
bob.PeerWithOnion("upiztu7myymjf2dn4x4czhagp7axlnqjvf5zwfegbhtpkqb6v3vgu5yd")
|
|
||||||
|
|
||||||
// Send the Message...
|
|
||||||
log.Infof("Waiting for Bob to Connect to Alice...")
|
|
||||||
bob.SendMessageToPeer("upiztu7myymjf2dn4x4czhagp7axlnqjvf5zwfegbhtpkqb6v3vgu5yd", "Hello Alice!!!")
|
|
||||||
|
|
||||||
// Wait a while...
|
|
||||||
// Everything is run in a goroutine so the main thread has to stay active
|
|
||||||
time.Sleep(time.Second * 100)
|
|
||||||
|
|
||||||
}
|
|
|
@ -3,6 +3,7 @@ package utils
|
||||||
import (
|
import (
|
||||||
app2 "cwtch.im/cwtch/app"
|
app2 "cwtch.im/cwtch/app"
|
||||||
"cwtch.im/cwtch/model/attr"
|
"cwtch.im/cwtch/model/attr"
|
||||||
|
"cwtch.im/cwtch/model/constants"
|
||||||
"cwtch.im/cwtch/peer"
|
"cwtch.im/cwtch/peer"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -13,9 +14,9 @@ import (
|
||||||
// may fill that usecase better
|
// may fill that usecase better
|
||||||
func WaitGetPeer(app app2.Application, name string) peer.CwtchPeer {
|
func WaitGetPeer(app app2.Application, name string) peer.CwtchPeer {
|
||||||
for {
|
for {
|
||||||
for id := range app.ListPeers() {
|
for _, handle := range app.ListProfiles() {
|
||||||
peer := app.GetPeer(id)
|
peer := app.GetPeer(handle)
|
||||||
localName, _ := peer.GetAttribute(attr.GetLocalScope("name"))
|
localName, _ := peer.GetScopedZonedAttribute(attr.LocalScope, attr.ProfileZone, constants.Name)
|
||||||
if localName == name {
|
if localName == name {
|
||||||
return peer
|
return peer
|
||||||
}
|
}
|
||||||
|
|
|
@ -149,11 +149,6 @@ const (
|
||||||
// GroupID
|
// GroupID
|
||||||
DeleteGroup = Type("DeleteGroup")
|
DeleteGroup = Type("DeleteGroup")
|
||||||
|
|
||||||
// change the .Name attribute of a profile (careful - this is not a custom attribute. it is used in the underlying protocol during handshakes!)
|
|
||||||
// attributes:
|
|
||||||
// ProfileName [eg "erinn"]
|
|
||||||
SetProfileName = Type("SetProfileName")
|
|
||||||
|
|
||||||
// request to store a profile-wide attribute (good for e.g. per-profile settings like theme prefs)
|
// request to store a profile-wide attribute (good for e.g. per-profile settings like theme prefs)
|
||||||
// attributes:
|
// attributes:
|
||||||
// Key [eg "fontcolor"]
|
// Key [eg "fontcolor"]
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
package constants
|
||||||
|
|
||||||
|
// Name refers to a Profile Name
|
||||||
|
const Name = "name"
|
||||||
|
|
||||||
|
// Tag describes the type of a profile e.g. default password / encrypted etc.
|
||||||
|
const Tag = "tag"
|
||||||
|
|
||||||
|
// ProfileTypeV1DefaultPassword is a tag describing a profile protected with the default password.
|
||||||
|
const ProfileTypeV1DefaultPassword = "v1-defaultPassword"
|
||||||
|
|
||||||
|
// ProfileTypeV1Password is a tag describing a profile encrypted derived from a user-provided password.
|
||||||
|
const ProfileTypeV1Password = "v1-userPassword"
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/sha512"
|
"crypto/sha512"
|
||||||
"cwtch.im/cwtch/model/attr"
|
"cwtch.im/cwtch/model/attr"
|
||||||
|
"cwtch.im/cwtch/model/constants"
|
||||||
"cwtch.im/cwtch/protocol/groups"
|
"cwtch.im/cwtch/protocol/groups"
|
||||||
"encoding/base32"
|
"encoding/base32"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
@ -72,7 +73,7 @@ func NewGroup(server string) (*Group, error) {
|
||||||
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
|
// 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.
|
// codes around invite, we assume that this is always set.
|
||||||
group.Attributes[attr.GetLocalScope("name")] = group.GroupID
|
group.Attributes[attr.GetLocalScope(constants.Name)] = group.GroupID
|
||||||
return group, nil
|
return group, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +100,7 @@ func (g *Group) Invite() (string, error) {
|
||||||
|
|
||||||
gci := &groups.GroupInvite{
|
gci := &groups.GroupInvite{
|
||||||
GroupID: g.GroupID,
|
GroupID: g.GroupID,
|
||||||
GroupName: g.Attributes[attr.GetLocalScope("name")],
|
GroupName: g.Attributes[attr.GetLocalScope(constants.Name)],
|
||||||
SharedKey: g.GroupKey[:],
|
SharedKey: g.GroupKey[:],
|
||||||
ServerHost: g.GroupServer,
|
ServerHost: g.GroupServer,
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package model
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"cwtch.im/cwtch/model/attr"
|
"cwtch.im/cwtch/model/attr"
|
||||||
|
"cwtch.im/cwtch/model/constants"
|
||||||
"cwtch.im/cwtch/protocol/groups"
|
"cwtch.im/cwtch/protocol/groups"
|
||||||
"encoding/base32"
|
"encoding/base32"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
@ -403,7 +404,7 @@ func (p *Profile) ProcessInvite(invite string) (string, error) {
|
||||||
group.GroupServer = gci.ServerHost
|
group.GroupServer = gci.ServerHost
|
||||||
group.Accepted = false
|
group.Accepted = false
|
||||||
group.Attributes = make(map[string]string)
|
group.Attributes = make(map[string]string)
|
||||||
group.Attributes[attr.GetLocalScope("name")] = gci.GroupName
|
group.Attributes[attr.GetLocalScope(constants.Name)] = gci.GroupName
|
||||||
p.AddGroup(group)
|
p.AddGroup(group)
|
||||||
return gci.GroupID, nil
|
return gci.GroupID, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package peer
|
package peer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"cwtch.im/cwtch/model/constants"
|
||||||
"encoding/base32"
|
"encoding/base32"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
@ -70,10 +71,6 @@ func (cp *cwtchPeer) GetScopedZonedAttribute(scope attr.Scope, zone attr.Zone, k
|
||||||
return val, true
|
return val, true
|
||||||
}
|
}
|
||||||
|
|
||||||
if key == attr.GetLocalScope("name") {
|
|
||||||
return cp.Profile.Name, true
|
|
||||||
}
|
|
||||||
|
|
||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,12 +236,6 @@ type CwtchPeer interface {
|
||||||
// Relating to local attributes
|
// Relating to local attributes
|
||||||
GetOnion() string
|
GetOnion() string
|
||||||
|
|
||||||
// Deprecated: SetAttribute is Unsafe used SetScopedZonedAttribute Instead
|
|
||||||
SetAttribute(string, string)
|
|
||||||
|
|
||||||
// Deprecated: GetAttribute is Unsafe used GetScopedZonedAttribute Instead
|
|
||||||
GetAttribute(string) (string, bool)
|
|
||||||
|
|
||||||
// scope.zone.key = value
|
// scope.zone.key = value
|
||||||
SetScopedZonedAttribute(scope attr.Scope, zone attr.Zone, key string, value string)
|
SetScopedZonedAttribute(scope attr.Scope, zone attr.Zone, key string, value string)
|
||||||
// scope.zone.key = value
|
// scope.zone.key = value
|
||||||
|
@ -288,6 +279,32 @@ func FromProfile(profile *model.Profile) CwtchPeer {
|
||||||
// Init instantiates a cwtchPeer
|
// Init instantiates a cwtchPeer
|
||||||
func (cp *cwtchPeer) Init(eventBus event.Manager) {
|
func (cp *cwtchPeer) Init(eventBus event.Manager) {
|
||||||
cp.InitForEvents(eventBus, DefaultEventsToHandle)
|
cp.InitForEvents(eventBus, DefaultEventsToHandle)
|
||||||
|
|
||||||
|
// Upgrade the Cwtch Peer if necessary
|
||||||
|
// It would be nice to do these checks in the storage engine itself, but it is easier to do them here
|
||||||
|
// rather than duplicating the logic to construct/reconstruct attributes in storage engine...
|
||||||
|
// TODO: Remove these checks after Cwtch ~1.5
|
||||||
|
// If local.profile.name does not exist then set it from deprecated GetAttribute
|
||||||
|
if _, exists := cp.GetScopedZonedAttribute(attr.LocalScope, attr.ProfileZone, constants.Name); !exists {
|
||||||
|
if name, exists := cp.Profile.GetAttribute(attr.GetLocalScope(constants.Name)); exists {
|
||||||
|
cp.SetScopedZonedAttribute(attr.LocalScope, attr.ProfileZone, constants.Name, name)
|
||||||
|
} else if name, exists := cp.Profile.GetAttribute(constants.Name); exists {
|
||||||
|
cp.SetScopedZonedAttribute(attr.LocalScope, attr.ProfileZone, constants.Name, name)
|
||||||
|
} else {
|
||||||
|
// Profile.Name is very deprecated at this point...
|
||||||
|
cp.SetScopedZonedAttribute(attr.LocalScope, attr.ProfileZone, constants.Name, cp.Profile.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If local.profile.tag does not exist then set it from deprecated GetAttribute
|
||||||
|
if _, exists := cp.GetScopedZonedAttribute(attr.LocalScope, attr.ProfileZone, constants.Tag); !exists {
|
||||||
|
if tag, exists := cp.Profile.GetAttribute(constants.Tag); exists {
|
||||||
|
cp.SetScopedZonedAttribute(attr.LocalScope, attr.ProfileZone, constants.Tag, tag)
|
||||||
|
} else {
|
||||||
|
// Assume a default password, which will allow the older profile to have it's password reset by the UI
|
||||||
|
cp.SetScopedZonedAttribute(attr.LocalScope, attr.ProfileZone, constants.Tag, constants.ProfileTypeV1DefaultPassword)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cp *cwtchPeer) InitForEvents(eventBus event.Manager, toBeHandled []event.Type) {
|
func (cp *cwtchPeer) InitForEvents(eventBus event.Manager, toBeHandled []event.Type) {
|
||||||
|
@ -685,33 +702,6 @@ func (cp *cwtchPeer) StartServerConnections() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetAttribute sets an attribute for this profile and emits an event
|
|
||||||
func (cp *cwtchPeer) SetAttribute(key string, val string) {
|
|
||||||
cp.mutex.Lock()
|
|
||||||
cp.Profile.SetAttribute(key, val)
|
|
||||||
defer cp.mutex.Unlock()
|
|
||||||
cp.eventBus.Publish(event.NewEvent(event.SetAttribute, map[event.Field]string{
|
|
||||||
event.Key: key,
|
|
||||||
event.Data: val,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated
|
|
||||||
// GetAttribute gets an attribute for the profile
|
|
||||||
func (cp *cwtchPeer) GetAttribute(key string) (string, bool) {
|
|
||||||
cp.mutex.Lock()
|
|
||||||
defer cp.mutex.Unlock()
|
|
||||||
if val, exists := cp.Profile.GetAttribute(key); exists {
|
|
||||||
return val, true
|
|
||||||
}
|
|
||||||
|
|
||||||
if key == attr.GetLocalScope("name") {
|
|
||||||
return cp.Profile.Name, true
|
|
||||||
}
|
|
||||||
|
|
||||||
return "", false
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetContactAttribute sets an attribute for the indicated contact and emits an event
|
// SetContactAttribute sets an attribute for the indicated contact and emits an event
|
||||||
func (cp *cwtchPeer) SetContactAttribute(onion string, key string, val string) {
|
func (cp *cwtchPeer) SetContactAttribute(onion string, key string, val string) {
|
||||||
cp.mutex.Lock()
|
cp.mutex.Lock()
|
||||||
|
|
|
@ -85,7 +85,6 @@ func (ps *ProfileStoreV1) initProfileWriterStore() {
|
||||||
ps.eventManager.Subscribe(event.SetPeerAuthorization, ps.queue)
|
ps.eventManager.Subscribe(event.SetPeerAuthorization, ps.queue)
|
||||||
ps.eventManager.Subscribe(event.PeerCreated, ps.queue)
|
ps.eventManager.Subscribe(event.PeerCreated, ps.queue)
|
||||||
ps.eventManager.Subscribe(event.GroupCreated, ps.queue)
|
ps.eventManager.Subscribe(event.GroupCreated, ps.queue)
|
||||||
ps.eventManager.Subscribe(event.SetProfileName, ps.queue)
|
|
||||||
ps.eventManager.Subscribe(event.SetAttribute, ps.queue)
|
ps.eventManager.Subscribe(event.SetAttribute, ps.queue)
|
||||||
ps.eventManager.Subscribe(event.SetPeerAttribute, ps.queue)
|
ps.eventManager.Subscribe(event.SetPeerAttribute, ps.queue)
|
||||||
ps.eventManager.Subscribe(event.SetGroupAttribute, ps.queue)
|
ps.eventManager.Subscribe(event.SetGroupAttribute, ps.queue)
|
||||||
|
@ -361,10 +360,6 @@ func (ps *ProfileStoreV1) eventHandler() {
|
||||||
ps.profile.AddGroup(group)
|
ps.profile.AddGroup(group)
|
||||||
ps.streamStores[group.GroupID] = NewStreamStore(ps.directory, group.LocalID, ps.key)
|
ps.streamStores[group.GroupID] = NewStreamStore(ps.directory, group.LocalID, ps.key)
|
||||||
ps.save()
|
ps.save()
|
||||||
case event.SetProfileName:
|
|
||||||
ps.profile.Name = ev.Data[event.ProfileName]
|
|
||||||
ps.profile.SetAttribute("name", ev.Data[event.ProfileName])
|
|
||||||
ps.save()
|
|
||||||
case event.SetAttribute:
|
case event.SetAttribute:
|
||||||
ps.profile.SetAttribute(ev.Data[event.Key], ev.Data[event.Data])
|
ps.profile.SetAttribute(ev.Data[event.Key], ev.Data[event.Data])
|
||||||
ps.save()
|
ps.save()
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"cwtch.im/cwtch/event/bridge"
|
"cwtch.im/cwtch/event/bridge"
|
||||||
"cwtch.im/cwtch/model"
|
"cwtch.im/cwtch/model"
|
||||||
"cwtch.im/cwtch/model/attr"
|
"cwtch.im/cwtch/model/attr"
|
||||||
|
"cwtch.im/cwtch/model/constants"
|
||||||
"cwtch.im/cwtch/peer"
|
"cwtch.im/cwtch/peer"
|
||||||
"cwtch.im/cwtch/protocol/connections"
|
"cwtch.im/cwtch/protocol/connections"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
@ -41,7 +42,7 @@ func printAndCountVerifedTimeline(t *testing.T, timeline []model.Message) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
func waitForPeerGroupConnection(t *testing.T, peer peer.CwtchPeer, groupID string) {
|
func waitForPeerGroupConnection(t *testing.T, peer peer.CwtchPeer, groupID string) {
|
||||||
peerName, _ := peer.GetAttribute(attr.GetLocalScope("name"))
|
peerName, _ := peer.GetScopedZonedAttribute(attr.LocalScope, attr.ProfileZone, constants.Name)
|
||||||
for {
|
for {
|
||||||
fmt.Printf("%v checking group connection...\n", peerName)
|
fmt.Printf("%v checking group connection...\n", peerName)
|
||||||
state, ok := peer.GetGroupState(groupID)
|
state, ok := peer.GetGroupState(groupID)
|
||||||
|
@ -77,8 +78,8 @@ func waitForPeerPeerConnection(t *testing.T, peera peer.CwtchPeer, peerb peer.Cw
|
||||||
time.Sleep(time.Second * 5)
|
time.Sleep(time.Second * 5)
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
peerAName, _ := peera.GetAttribute(attr.GetLocalScope("name"))
|
peerAName, _ := peera.GetScopedZonedAttribute(attr.LocalScope, attr.ProfileZone, constants.Name)
|
||||||
peerBName, _ := peerb.GetAttribute(attr.GetLocalScope("name"))
|
peerBName, _ := peerb.GetScopedZonedAttribute(attr.LocalScope, attr.ProfileZone, constants.Name)
|
||||||
fmt.Printf("%v CONNECTED and AUTHED to %v\n", peerAName, peerBName)
|
fmt.Printf("%v CONNECTED and AUTHED to %v\n", peerAName, peerBName)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -154,17 +155,17 @@ func TestCwtchPeerIntegration(t *testing.T) {
|
||||||
|
|
||||||
alice := utils.WaitGetPeer(app, "alice")
|
alice := utils.WaitGetPeer(app, "alice")
|
||||||
fmt.Println("Alice created:", alice.GetOnion())
|
fmt.Println("Alice created:", alice.GetOnion())
|
||||||
alice.SetScopedZonedAttribute(attr.PublicScope, attr.ProfileZone, "name", "Alice")
|
alice.SetScopedZonedAttribute(attr.PublicScope, attr.ProfileZone, constants.Name, "Alice")
|
||||||
alice.AutoHandleEvents([]event.Type{event.PeerStateChange, event.ServerStateChange, event.NewGroupInvite, event.NewRetValMessageFromPeer})
|
alice.AutoHandleEvents([]event.Type{event.PeerStateChange, event.ServerStateChange, event.NewGroupInvite, event.NewRetValMessageFromPeer})
|
||||||
|
|
||||||
bob := utils.WaitGetPeer(app, "bob")
|
bob := utils.WaitGetPeer(app, "bob")
|
||||||
fmt.Println("Bob created:", bob.GetOnion())
|
fmt.Println("Bob created:", bob.GetOnion())
|
||||||
bob.SetScopedZonedAttribute(attr.PublicScope, attr.ProfileZone, "name", "Bob")
|
bob.SetScopedZonedAttribute(attr.PublicScope, attr.ProfileZone, constants.Name, "Bob")
|
||||||
bob.AutoHandleEvents([]event.Type{event.PeerStateChange, event.ServerStateChange, event.NewGroupInvite, event.NewRetValMessageFromPeer})
|
bob.AutoHandleEvents([]event.Type{event.PeerStateChange, event.ServerStateChange, event.NewGroupInvite, event.NewRetValMessageFromPeer})
|
||||||
|
|
||||||
carol := utils.WaitGetPeer(appClient, "carol")
|
carol := utils.WaitGetPeer(appClient, "carol")
|
||||||
fmt.Println("Carol created:", carol.GetOnion())
|
fmt.Println("Carol created:", carol.GetOnion())
|
||||||
carol.SetScopedZonedAttribute(attr.PublicScope, attr.ProfileZone, "name", "Carol")
|
carol.SetScopedZonedAttribute(attr.PublicScope, attr.ProfileZone, constants.Name, "Carol")
|
||||||
carol.AutoHandleEvents([]event.Type{event.PeerStateChange, event.ServerStateChange, event.NewGroupInvite, event.NewRetValMessageFromPeer})
|
carol.AutoHandleEvents([]event.Type{event.PeerStateChange, event.ServerStateChange, event.NewGroupInvite, event.NewRetValMessageFromPeer})
|
||||||
|
|
||||||
app.LaunchPeers()
|
app.LaunchPeers()
|
||||||
|
@ -217,32 +218,32 @@ func TestCwtchPeerIntegration(t *testing.T) {
|
||||||
|
|
||||||
fmt.Println("Alice and Bob getVal public.name...")
|
fmt.Println("Alice and Bob getVal public.name...")
|
||||||
|
|
||||||
alice.SendScopedZonedGetValToContact(bob.GetOnion(), attr.PublicScope, attr.ProfileZone, "name")
|
alice.SendScopedZonedGetValToContact(bob.GetOnion(), attr.PublicScope, attr.ProfileZone, constants.Name)
|
||||||
bob.SendScopedZonedGetValToContact(alice.GetOnion(), attr.PublicScope, attr.ProfileZone, "name")
|
bob.SendScopedZonedGetValToContact(alice.GetOnion(), attr.PublicScope, attr.ProfileZone, constants.Name)
|
||||||
|
|
||||||
alice.SendScopedZonedGetValToContact(carol.GetOnion(), attr.PublicScope, attr.ProfileZone, "name")
|
alice.SendScopedZonedGetValToContact(carol.GetOnion(), attr.PublicScope, attr.ProfileZone, constants.Name)
|
||||||
carol.SendScopedZonedGetValToContact(alice.GetOnion(), attr.PublicScope, attr.ProfileZone, "name")
|
carol.SendScopedZonedGetValToContact(alice.GetOnion(), attr.PublicScope, attr.ProfileZone, constants.Name)
|
||||||
|
|
||||||
time.Sleep(10 * time.Second)
|
time.Sleep(10 * time.Second)
|
||||||
|
|
||||||
aliceName, exists := bob.GetContactAttribute(alice.GetOnion(), attr.GetPeerScope("name"))
|
aliceName, exists := bob.GetContactAttribute(alice.GetOnion(), attr.GetPeerScope(constants.Name))
|
||||||
if !exists || aliceName != "Alice" {
|
if !exists || aliceName != "Alice" {
|
||||||
t.Fatalf("Bob: alice GetKeyVal error on alice peer.name %v\n", exists)
|
t.Fatalf("Bob: alice GetKeyVal error on alice peer.name %v\n", exists)
|
||||||
}
|
}
|
||||||
fmt.Printf("Bob has alice's name as '%v'\n", aliceName)
|
fmt.Printf("Bob has alice's name as '%v'\n", aliceName)
|
||||||
|
|
||||||
bobName, exists := alice.GetContactAttribute(bob.GetOnion(), attr.GetPeerScope("name"))
|
bobName, exists := alice.GetContactAttribute(bob.GetOnion(), attr.GetPeerScope(constants.Name))
|
||||||
if !exists || bobName != "Bob" {
|
if !exists || bobName != "Bob" {
|
||||||
t.Fatalf("Alice: bob GetKeyVal error on bob peer.name\n")
|
t.Fatalf("Alice: bob GetKeyVal error on bob peer.name\n")
|
||||||
}
|
}
|
||||||
fmt.Printf("Alice has bob's name as '%v'\n", bobName)
|
fmt.Printf("Alice has bob's name as '%v'\n", bobName)
|
||||||
|
|
||||||
aliceName, exists = carol.GetContactAttribute(alice.GetOnion(), attr.GetPeerScope("name"))
|
aliceName, exists = carol.GetContactAttribute(alice.GetOnion(), attr.GetPeerScope(constants.Name))
|
||||||
if !exists || aliceName != "Alice" {
|
if !exists || aliceName != "Alice" {
|
||||||
t.Fatalf("carol GetKeyVal error for alice peer.name %v\n", exists)
|
t.Fatalf("carol GetKeyVal error for alice peer.name %v\n", exists)
|
||||||
}
|
}
|
||||||
|
|
||||||
carolName, exists := alice.GetContactAttribute(carol.GetOnion(), attr.GetPeerScope("name"))
|
carolName, exists := alice.GetContactAttribute(carol.GetOnion(), attr.GetPeerScope(constants.Name))
|
||||||
if !exists || carolName != "Carol" {
|
if !exists || carolName != "Carol" {
|
||||||
t.Fatalf("alice GetKeyVal error, carol peer.name\n")
|
t.Fatalf("alice GetKeyVal error, carol peer.name\n")
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"cwtch.im/cwtch/functionality/filesharing"
|
"cwtch.im/cwtch/functionality/filesharing"
|
||||||
"cwtch.im/cwtch/model"
|
"cwtch.im/cwtch/model"
|
||||||
"cwtch.im/cwtch/model/attr"
|
"cwtch.im/cwtch/model/attr"
|
||||||
|
"cwtch.im/cwtch/model/constants"
|
||||||
"cwtch.im/cwtch/peer"
|
"cwtch.im/cwtch/peer"
|
||||||
"cwtch.im/cwtch/protocol/connections"
|
"cwtch.im/cwtch/protocol/connections"
|
||||||
"cwtch.im/cwtch/protocol/files"
|
"cwtch.im/cwtch/protocol/files"
|
||||||
|
@ -40,8 +41,8 @@ func waitForPeerPeerConnection(t *testing.T, peera peer.CwtchPeer, peerb peer.Cw
|
||||||
time.Sleep(time.Second * 5)
|
time.Sleep(time.Second * 5)
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
peerAName, _ := peera.GetScopedZonedAttribute(attr.LocalScope, attr.ProfileZone, "name")
|
peerAName, _ := peera.GetScopedZonedAttribute(attr.LocalScope, attr.ProfileZone, constants.Name)
|
||||||
peerBName, _ := peerb.GetScopedZonedAttribute(attr.LocalScope, attr.ProfileZone, "name")
|
peerBName, _ := peerb.GetScopedZonedAttribute(attr.LocalScope, attr.ProfileZone, constants.Name)
|
||||||
fmt.Printf("%v CONNECTED and AUTHED to %v\n", peerAName, peerBName)
|
fmt.Printf("%v CONNECTED and AUTHED to %v\n", peerAName, peerBName)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue