From f74e8647ef4e1252d1774ff809747c16d261517c Mon Sep 17 00:00:00 2001 From: Sarah Jamie Lewis Date: Wed, 22 Jul 2020 10:14:32 -0700 Subject: [PATCH] Fixup APIs, Error handling and formatting --- model/keyBundle.go | 25 +++++++++++--------- model/profile.go | 8 +++++++ peer/cwtch_peer.go | 57 +++++++++++++++++++++++++--------------------- server/server.go | 4 ++-- 4 files changed, 55 insertions(+), 39 deletions(-) diff --git a/model/keyBundle.go b/model/keyBundle.go index 7ff63e9..d5b7765 100644 --- a/model/keyBundle.go +++ b/model/keyBundle.go @@ -2,15 +2,18 @@ package model import "errors" +// KeyType provides a wrapper for a generic public key type identifier (could be an onion address, a zcash address etc.) +type KeyType string + const ( - // KeyTypeOnion - a cwtch address - KeyTypeOnion = "onion" // bulletin board + // KeyTypeServerOnion - a cwtch address + KeyTypeServerOnion = KeyType("bulletin_board_onion") // bulletin board // KeyTypeTokenOnion - a cwtch peer with a PoW based token protocol - KeyTypeTokenOnion = "token_onion" + KeyTypeTokenOnion = KeyType("token_service_onion") //KeyTypePrivacyPass - a privacy pass based token server - KeyTypePrivacyPass = "pp_key" + KeyTypePrivacyPass = KeyType("privacy_pass_public_key") ) // Key provides a wrapper for a generic public key identifier (could be an onion address, a zcash address etc.) @@ -18,18 +21,18 @@ type Key string // KeyBundle manages a collection of related keys for various different services. type KeyBundle struct { - Keys map[string]Key + Keys map[KeyType]Key } -// HasKey returns true if the bundle has a public key of a given type. -func (kb *KeyBundle) HasKey(name string) bool { - _, exists := kb.Keys[name] +// HasKeyType returns true if the bundle has a public key of a given type. +func (kb *KeyBundle) HasKeyType(keytype KeyType) bool { + _, exists := kb.Keys[keytype] return exists } // GetKey retrieves a key with a given type from the bundle -func (kb *KeyBundle) GetKey(name string) (Key, error) { - key, exists := kb.Keys[name] +func (kb *KeyBundle) GetKey(keytype KeyType) (Key, error) { + key, exists := kb.Keys[keytype] if exists { return key, nil } @@ -40,7 +43,7 @@ func (kb *KeyBundle) GetKey(name string) (Key, error) { func (kb *KeyBundle) AttributeBundle() map[string]string { ab := make(map[string]string) for k, v := range kb.Keys { - ab[k] = string(v) + ab[string(k)] = string(v) } return ab } diff --git a/model/profile.go b/model/profile.go index 00dbcb2..64f0577 100644 --- a/model/profile.go +++ b/model/profile.go @@ -78,6 +78,14 @@ func (p *PublicProfile) SetAttribute(name string, value string) { p.Attributes[name] = value } +// IsServer returns true if the onion address is associated with a server. +func (p *PublicProfile) IsServer(onion string) bool { + if _, isServer := p.GetAttribute(string(KeyTypeServerOnion)); isServer == true { + return true + } + return false +} + // GetAttribute returns the value of a value set with SetCustomAttribute. If no such value has been set exists is set to false. func (p *PublicProfile) GetAttribute(name string) (value string, exists bool) { p.lock.Lock() diff --git a/peer/cwtch_peer.go b/peer/cwtch_peer.go index 5a84107..68f84a8 100644 --- a/peer/cwtch_peer.go +++ b/peer/cwtch_peer.go @@ -48,7 +48,7 @@ type CwtchPeer interface { DeleteContact(string) DeleteGroup(string) - AddServer(string) + AddServer(string) error JoinServer(string) SendMessageToGroup(string, string) error SendMessageToGroupTracked(string, string) (string, error) @@ -205,36 +205,41 @@ func (cp *cwtchPeer) AddContact(nick, onion string, authorization model.Authoriz cp.eventBus.Publish(event.NewEventList(event.SetPeerAttribute, event.RemotePeer, onion, event.SaveHistoryKey, event.DeleteHistoryDefault)) } -func (cp *cwtchPeer) AddServer(serverSpecification string) { +func (cp *cwtchPeer) AddServer(serverSpecification string) error { keyBundle := new(model.KeyBundle) - json.Unmarshal([]byte(serverSpecification), &keyBundle) - + err := json.Unmarshal([]byte(serverSpecification), &keyBundle) log.Debugf("Got new key bundle %v", keyBundle) - - if keyBundle.HasKey(model.KeyTypeOnion) { - onionKey, _ := keyBundle.GetKey(model.KeyTypeOnion) + if keyBundle.HasKeyType(model.KeyTypeServerOnion) { + onionKey, _ := keyBundle.GetKey(model.KeyTypeServerOnion) onion := string(onionKey) - decodedPub, _ := base32.StdEncoding.DecodeString(strings.ToUpper(onion)) - ab := keyBundle.AttributeBundle() - ab["nick"] = onion - pp := &model.PublicProfile{Name: onion, Ed25519PublicKey: decodedPub, Authorization: model.AuthUnknown, Onion: onion, Attributes: ab} - cp.Profile.AddContact(onion, pp) - pd, _ := json.Marshal(pp) - cp.eventBus.Publish(event.NewEvent(event.PeerCreated, map[event.Field]string{ - event.Data: string(pd), - event.RemotePeer: onion, - })) + if cp.GetContact(onion) == nil { + decodedPub, _ := base32.StdEncoding.DecodeString(strings.ToUpper(onion)) + ab := keyBundle.AttributeBundle() + ab["nick"] = onion + pp := &model.PublicProfile{Name: onion, Ed25519PublicKey: decodedPub, Authorization: model.AuthUnknown, Onion: onion, Attributes: ab} - // Publish every key as an attribute - for k, v := range ab { - log.Debugf("Server (%v) has %v key %v", onion, k, v) - cp.eventBus.Publish(event.NewEventList(event.SetPeerAttribute, event.RemotePeer, onion, k, v)) + cp.Profile.AddContact(onion, pp) + pd, _ := json.Marshal(pp) + cp.eventBus.Publish(event.NewEvent(event.PeerCreated, map[event.Field]string{ + event.Data: string(pd), + event.RemotePeer: onion, + })) + + // Publish every key as an attribute + for k, v := range ab { + log.Debugf("Server (%v) has %v key %v", onion, k, v) + cp.eventBus.Publish(event.NewEventList(event.SetPeerAttribute, event.RemotePeer, onion, k, v)) + } + + // Default to Deleting Peer History + cp.eventBus.Publish(event.NewEventList(event.SetPeerAttribute, event.RemotePeer, onion, event.SaveHistoryKey, event.DeleteHistoryDefault)) + return nil } - - // Default to Deleting Peer History - cp.eventBus.Publish(event.NewEventList(event.SetPeerAttribute, event.RemotePeer, onion, event.SaveHistoryKey, event.DeleteHistoryDefault)) + // Server Already Exists + return errors.New("a contact already exists with the given onion address") } + return err } // GetContacts returns an unordered list of onions @@ -332,8 +337,8 @@ func (cp *cwtchPeer) InviteOnionToGroup(onion string, groupid string) error { // JoinServer manages a new server connection with the given onion address func (cp *cwtchPeer) JoinServer(onion string) { if cp.GetContact(onion) != nil { - tokenY, yExists := cp.GetContact(onion).GetAttribute(model.KeyTypePrivacyPass) - tokenOnion, onionExists := cp.GetContact(onion).GetAttribute(model.KeyTypeTokenOnion) + tokenY, yExists := cp.GetContact(onion).GetAttribute(string(model.KeyTypePrivacyPass)) + tokenOnion, onionExists := cp.GetContact(onion).GetAttribute(string(model.KeyTypeTokenOnion)) if yExists && onionExists { cp.eventBus.Publish(event.NewEvent(event.JoinServer, map[event.Field]string{event.GroupServer: onion, event.ServerTokenY: tokenY, event.ServerTokenOnion: tokenOnion})) } diff --git a/server/server.go b/server/server.go index ce6500b..2fa4792 100644 --- a/server/server.go +++ b/server/server.go @@ -84,9 +84,9 @@ func (s *Server) Run(acn connectivity.ACN) { // KeyBundle provides the keybundle of the server (mostly used for testing) func (s *Server) KeyBundle() model.KeyBundle { - kb := model.KeyBundle{Keys: make(map[string]model.Key)} + kb := model.KeyBundle{Keys: make(map[model.KeyType]model.Key)} identity := s.config.Identity() - kb.Keys[model.KeyTypeOnion] = model.Key(identity.Hostname()) + kb.Keys[model.KeyTypeServerOnion] = model.Key(identity.Hostname()) kb.Keys[model.KeyTypeTokenOnion] = model.Key(tor.GetTorV3Hostname(s.tokenService.PublicKey())) kb.Keys[model.KeyTypePrivacyPass] = model.Key(s.tokenServer.Y.String()) return kb