diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 4430dcec75f29df535fc2fe42d66f85a0425b754..1ac33fcef60efb5b1b33aac1d21127c3897cf524 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -83,25 +83,28 @@ build: - GOOS=windows GOARCH=386 CGO_ENABLED=0 go build -ldflags '-w -s' -o release/client.win32 main.go - GOOS=darwin GOARCH=amd64 CGO_ENABLED=0 go build -ldflags '-w -s' -o release/client.darwin64 main.go - release/client.linux64 --version + - git remote add origin_tags git@gitlab.com:elixxir/client.git || true + - git tag $(release/client.linux64 -V | grep "Elixxir Client v"| cut -d ' ' -f3) -f + - git push origin_tags -f --tags artifacts: paths: - release/ -bindings: - stage: build - tags: - - ios - script: - - GO111MODULE=off go get golang.org/x/mobile/cmd/gomobile - - GO111MODULE=off go get gitlab.com/elixxir/client - - GO111MODULE=off gomobile bind -target android -androidapi 21 gitlab.com/elixxir/client/bindings - - GO111MODULE=off gomobile bind -target ios gitlab.com/elixxir/client/bindings - - zip -r iOS.zip Bindings.framework - artifacts: - paths: - - iOS.zip - - bindings.aar - - bindings-sources.jar +#bindings: +# stage: build +# tags: +# - ios +# script: +# - GO111MODULE=off go get golang.org/x/mobile/cmd/gomobile +# - GO111MODULE=off go get gitlab.com/elixxir/client +# - GO111MODULE=off gomobile bind -target android -androidapi 21 gitlab.com/elixxir/client/bindings +# - GO111MODULE=off gomobile bind -target ios gitlab.com/elixxir/client/bindings +# - zip -r iOS.zip Bindings.framework +# artifacts: +# paths: +# - iOS.zip +# - bindings.aar +# - bindings-sources.jar trigger_integration: stage: trigger_integration diff --git a/api/client_test.go b/api/client_test.go index 59d5609b39b1c33b2c5370e8d533f4dc69ed5bab..4d78c2eae293c540d3a5cb21fed4a45e1d95bc1b 100644 --- a/api/client_test.go +++ b/api/client_test.go @@ -100,6 +100,29 @@ func TestParsedMessage_GetMessageType(t *testing.T) { } } +// Error path +func TestNewClient_Panic(t *testing.T) { + defer func() { + if e := recover(); e != nil { + + } + + }() + // Arbitrary invalid interface + var i rsa.PublicKey + // Passed into NewTestClient call to cause a panic + NewTestClient(&globals.RamStorage{}, "", "", def, i, send) + t.Errorf("Failed to detect a bad interface passed in") +} + +// Happy path +func TestNewClient(t *testing.T) { + _, err := NewTestClient(&globals.RamStorage{}, "", "", def, t, send) + if err != nil { + t.Errorf("Expected happy path, received error: %+v", err) + } +} + //Happy path func TestParse(t *testing.T) { ms := parse.Message{} diff --git a/api/register.go b/api/register.go index 6709ecc714b7ef8ad27f62e8c96c8465d8add8c3..afbefd0ad10d5f27783712877328913fb0314b5a 100644 --- a/api/register.go +++ b/api/register.go @@ -17,7 +17,9 @@ import ( "gitlab.com/elixxir/crypto/hash" "gitlab.com/elixxir/crypto/registration" "gitlab.com/elixxir/crypto/signature/rsa" + "gitlab.com/elixxir/crypto/tls" "gitlab.com/elixxir/primitives/id" + "gitlab.com/elixxir/primitives/ndf" "sync" "time" ) @@ -165,14 +167,24 @@ func (cl *Client) RegisterWithNodes() error { //Load the user ID UID := session.GetCurrentUser().User - + usr := session.GetCurrentUser() //Load the registration signature regSignature := session.GetRegistrationValidationSignature() - //Storage of the registration signature was broken in previous releases. - //get the signature again from permissioning if it is absent - //FIX-ME: check the signature is properly structured instead of the magic number - if len(regSignature) < 10 { + // Storage of the registration signature was broken in previous releases. + // get the signature again from permissioning if it is absent + var regPubKey *rsa.PublicKey + if cl.ndf.Registration.TlsCertificate != "" { + var err error + regPubKey, err = extractPublicKeyFromCert(cl.ndf) + if err != nil { + return err + } + } + + // Storage of the registration signature was broken in previous releases. + // get the signature again from permissioning if it is absent + if !usr.Precan && !rsa.IsValidSignature(regPubKey, regSignature) { // Or register with the permissioning server and generate user information regSignature, err := cl.registerWithPermissioning("", cl.session.GetRSAPublicKey()) if err != nil { @@ -318,8 +330,24 @@ func (cl *Client) registerWithPermissioning(registrationCode string, return nil, errors.Errorf("Register: Unable to send registration message: %+v", err) } - globals.Log.INFO.Println("Register: successfully registered") return regValidSig, nil } + +// extractPublicKeyFromCert is a utility function which pulls out the public key from a certificate +func extractPublicKeyFromCert(definition *ndf.NetworkDefinition) (*rsa.PublicKey, error) { + // Load certificate object + cert, err := tls.LoadCertificate(definition.Registration.TlsCertificate) + if err != nil { + return nil, errors.Errorf("Failed to parse certificate: %+v", err) + } + //Extract public key from cert + regPubKey, err := tls.ExtractPublicKey(cert) + if err != nil { + return nil, errors.Errorf("Failed to pull key from cert: %+v", err) + } + + return regPubKey, nil + +} diff --git a/bindings/client.go b/bindings/client.go index 4247f0e3d254054fec7e918bbee6f2eec8e88213..610b58b7fc13a65bceaebde645672bb3d29d7297 100644 --- a/bindings/client.go +++ b/bindings/client.go @@ -277,7 +277,7 @@ func (cl *Client) StorageIsEmpty() bool { // or not. If true, and there is no keying relationship with the user specified // in the message object, then it will return an error. If using precanned // users encryption must be set to false. -func (cl *Client) Send(m Message, encrypt bool) error { +func (cl *Client) Send(m Message, encrypt bool) (int64, error) { globals.Log.INFO.Printf("Binding call: Send()\n"+ "Sender: %v\n"+ "Payload: %v\n"+ @@ -295,7 +295,7 @@ func (cl *Client) Send(m Message, encrypt bool) error { cryptoType = parse.Unencrypted } - return cl.client.Send(&parse.Message{ + return time.Now().UnixNano(), cl.client.Send(&parse.Message{ TypedBody: parse.TypedBody{ MessageType: m.GetMessageType(), Body: m.GetPayload(), diff --git a/bindings/client_test.go b/bindings/client_test.go index 4fbf9ba072ca6d4537b1e3c331c758204feeadf8..3b134fa883b8e14499032d0753f1f90e6a478a7c 100644 --- a/bindings/client_test.go +++ b/bindings/client_test.go @@ -121,7 +121,7 @@ func TestRegister(t *testing.T) { t.Errorf("Could not connect: %+v", err) } - err = client.client.GenerateKeys(nil, "") + err = client.GenerateKeys("") if err != nil { t.Errorf("Could not generate Keys: %+v", err) } @@ -205,6 +205,36 @@ func TestClient_ChangeUsername(t *testing.T) { } +func TestClient_StorageIsEmpty(t *testing.T) { + ndfStr, pubKey := getNDFJSONStr(def, t) + + d := DummyStorage{LocationA: "Blah", StoreA: []byte{'a', 'b', 'c'}} + + testClient, err := NewClient(&d, "hello", "", ndfStr, pubKey) + if err != nil { + t.Errorf("Failed to marshal group JSON: %s", err) + } + + err = testClient.InitNetwork() + if err != nil { + t.Errorf("Could not connect: %+v", err) + } + + err = testClient.client.GenerateKeys(nil, "") + if err != nil { + t.Errorf("Could not generate Keys: %+v", err) + } + + regRes, err := testClient.RegisterWithPermissioning(false, ValidRegCode) + if len(regRes) == 0 { + t.Errorf("Invalid registration number received: %v", regRes) + } + + if testClient.StorageIsEmpty() { + t.Errorf("Unexpected empty storage!") + } +} + //Error path: Have added no contacts, so deleting a contact should fail func TestDeleteUsername_EmptyContactList(t *testing.T) { ndfStr, pubKey := getNDFJSONStr(def, t) @@ -324,7 +354,7 @@ func TestClient_Send(t *testing.T) { } // Test send with invalid sender ID - err = testClient.Send( + _, err = testClient.Send( mockMesssage{ Sender: id.NewUserFromUint(12, t), TypedBody: parse.TypedBody{Body: []byte("test")}, @@ -338,7 +368,7 @@ func TestClient_Send(t *testing.T) { } // Test send with valid inputs - err = testClient.Send( + _, err = testClient.Send( mockMesssage{ Sender: id.NewUserFromBytes(userID), TypedBody: parse.TypedBody{Body: []byte("test")}, diff --git a/bots/userDiscovery.go b/bots/userDiscovery.go index c819f66bbdcd618a74d0e89972732c5457c8d47f..35cd3970051e04839b5fb406536147f804d18b90 100644 --- a/bots/userDiscovery.go +++ b/bots/userDiscovery.go @@ -23,7 +23,6 @@ import ( ) var pushkeyExpected = "PUSHKEY COMPLETE" -var pushkeyErrorExpected = "Could not push key" // Register sends a registration message to the UDB. It does this by sending 2 // PUSHKEY messages to the UDB, then calling UDB's REGISTER command. @@ -65,8 +64,6 @@ func Register(valueType, value string, publicKey []byte, regStatus func(int), ti if strings.Contains(response, keyFP) { if strings.Contains(response, pushkeyExpected) { submitted = true - } else if strings.Contains(response, pushkeyErrorExpected) { - submitted = true } else { err := errors.New(response) return errors.Wrap(err, "PushKey failed") @@ -101,21 +98,10 @@ func Register(valueType, value string, publicKey []byte, regStatus func(int), ti case response = <-registerResponseListener: expected := "REGISTRATION COMPLETE" unavalibleReg := "Can not register with existing email" - alreadyExists := "Cannot write to a user that already exists" if strings.Contains(response, expected) { complete = true } else if strings.Contains(response, value) && strings.Contains(response, unavalibleReg) { return errors.New("Cannot register with existing username") - } else if strings.Contains(response, alreadyExists) { - id, b, err := Search("EMAIL", value, func(int) { return }, 1000*time.Millisecond) - if err != nil { - return errors.New("Cannot register with existing username") - } - if id != nil && bytes.Compare(b, publicKey) != 0 { - complete = true - } else { - return errors.New("Cannot register with existing username") - } } case <-registerTimeout.C: return errors.New("UDB register timeout exceeded on user submission") diff --git a/cmd/gen.go b/cmd/gen.go index be481df7b95cda1c7872379706123db41a1918b8..fae0ee14b5e302b964eee663bfaa217e3d76ce67 100644 --- a/cmd/gen.go +++ b/cmd/gen.go @@ -1,5 +1,5 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright © 2019 Privategrity Corporation / +// Copyright © 2020 Privategrity Corporation / // / // All rights reserved. / //////////////////////////////////////////////////////////////////////////////// @@ -72,5 +72,5 @@ var packageTemplate = template.Must(template.New("").Parse( "// {{ .Timestamp }}\n" + "package globals\n\n" + "const GITVERSION = `{{ .GITVER }}`\n" + - "const SEMVER = \"1.1.0\"\n" + + "const SEMVER = \"1.1.1\"\n" + "const GLIDEDEPS = `{{ .GLIDEDEPS }}`\n")) diff --git a/globals/version.go b/globals/version.go index 42c64ac0487ad58d416037f6e702eefabdd0c887..0d8e93c560ecf786637ddb63cd0cd4c140b87c75 100644 --- a/globals/version.go +++ b/globals/version.go @@ -1,183 +1,14 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2020 Privategrity Corporation / +// / +// All rights reserved. / +//////////////////////////////////////////////////////////////////////////////// + // Code generated by go generate; DO NOT EDIT. // This file was generated by robots at -// 2020-01-29 12:25:24.3078584 -0800 STD m=+0.117535101 +// 2020-02-06 14:09:54.442503 -0800 PST m=+0.007064579 package globals -const GITVERSION = `d3f8dd6 fixed a greatter then sign` -const SEMVER = "1.1.0" -const GLIDEDEPS = `hash: 1d2d2b561c9ab69ca26c5c10441883c15fc5491fbcd30bcc51e7f16d48d6e095 -updated: 2019-10-18T10:25:42.8425249-07:00 -imports: -- name: github.com/fsnotify/fsnotify - version: 4bf2d1fec78374803a39307bfb8d340688f4f28e -- name: github.com/golang-collections/collections - version: 604e922904d35e97f98a774db7881f049cd8d970 - repo: https://github.com/golang-collections/collections.git - vcs: git - subpackages: - - stack -- name: github.com/golang/protobuf - version: 1680a479a2cfb3fa22b972af7e36d0a0fde47bf8 - subpackages: - - proto - - protoc-gen-go/descriptor - - ptypes - - ptypes/any - - ptypes/duration - - ptypes/timestamp -- name: github.com/hashicorp/hcl - version: 914dc3f8dd7c463188c73fc47e9ced82a6e421ca - subpackages: - - hcl/ast - - hcl/parser - - hcl/printer - - hcl/scanner - - hcl/strconv - - hcl/token - - json/parser - - json/scanner - - json/token -- name: github.com/inconshreveable/mousetrap - version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 -- name: github.com/magiconair/properties - version: de8848e004dd33dc07a2947b3d76f618a7fc7ef1 -- name: github.com/mitchellh/go-homedir - version: af06845cf3004701891bf4fdb884bfe4920b3727 - repo: https://github.com/mitchellh/go-homedir.git - vcs: git -- name: github.com/mitchellh/mapstructure - version: 3536a929edddb9a5b34bd6861dc4a9647cb459fe -- name: github.com/pelletier/go-toml - version: e87c92d4f423f333363e6d45b03f65ff8becd029 -- name: github.com/pkg/errors - version: 27936f6d90f9c8e1145f11ed52ffffbfdb9e0af7 -- name: github.com/spf13/afero - version: 588a75ec4f32903aa5e39a2619ba6a4631e28424 - subpackages: - - mem -- name: github.com/spf13/cast - version: c01685bb8421cecb276fa517e91f757215f980b3 -- name: github.com/spf13/cobra - version: f2b07da1e2c38d5f12845a4f607e2e1018cbb1f5 - subpackages: - - cobra -- name: github.com/spf13/jwalterweatherman - version: 94f6ae3ed3bceceafa716478c5fbf8d29ca601a1 -- name: github.com/spf13/pflag - version: 2e9d26c8c37aae03e3f9d4e90b7116f5accb7cab -- name: github.com/spf13/viper - version: 40e41dd2240a2ae3f6b0a908ad9ddc6cefd5e456 -- name: github.com/subosito/gotenv - version: de67a6614a4de71ad5e380b6946e56ab957d58c5 -- name: github.com/xeipuuv/gojsonschema - version: 82fcdeb203eb6ab2a67d0a623d9c19e5e5a64927 - vcs: git -- name: gitlab.com/elixxir/comms - version: 52224bff4ee219b49c193179753e1eec951941be - repo: git@gitlab.com:elixxir/comms - vcs: git - subpackages: - - client - - connect - - gateway - - mixmessages - - registration -- name: gitlab.com/elixxir/crypto - version: d12eb719b4d870929c5f5b346b604a437304cbab - repo: git@gitlab.com:elixxir/crypto - vcs: git - subpackages: - - cmix - - csprng - - cyclic - - diffieHellman - - e2e - - hash - - large - - registration - - signature/rsa - - tls -- name: gitlab.com/elixxir/primitives - version: ab1ce1d42c85b39161a8d58a5d9c1c2f76ca9771 - repo: git@gitlab.com:elixxir/primitives - vcs: git - subpackages: - - circuit - - format - - id - - ndf - - switchboard - - utils -- name: golang.org/x/crypto - version: 87dc89f01550277dc22b74ffcf4cd89fa2f40f4c - subpackages: - - blake2b - - hkdf -- name: golang.org/x/net - version: da9a3fd4c5820e74b24a6cb7fb438dc9b0dd377c - subpackages: - - context - - http/httpguts - - http2 - - http2/hpack - - idna - - internal/timeseries - - trace -- name: golang.org/x/sys - version: 727590c5006e77ca5247972f47e877f4929fc985 - subpackages: - - cpu - - unix -- name: golang.org/x/text - version: 3d0f7978add91030e5e8976ff65ccdd828286cba - subpackages: - - secure/bidirule - - transform - - unicode/bidi - - unicode/norm -- name: google.golang.org/genproto - version: 548a555dbc03994223efbaba0090152849259498 - subpackages: - - googleapis/rpc/status -- name: google.golang.org/grpc - version: 7c3115d8bba8df106f26e55d52db456ed42893f8 - subpackages: - - backoff - - balancer - - balancer/base - - balancer/roundrobin - - binarylog/grpc_binarylog_v1 - - codes - - connectivity - - credentials - - credentials/internal - - encoding - - encoding/proto - - grpclog - - internal - - internal/backoff - - internal/balancerload - - internal/binarylog - - internal/channelz - - internal/envconfig - - internal/grpcrand - - internal/grpcsync - - internal/syscall - - internal/transport - - keepalive - - metadata - - naming - - peer - - reflection - - reflection/grpc_reflection_v1alpha - - resolver - - resolver/dns - - resolver/passthrough - - serviceconfig - - stats - - status - - tap -- name: gopkg.in/yaml.v2 - version: f221b8435cfb71e54062f6c6e99e9ade30b124d5 -testImports: [] -` +const GITVERSION = `368d13e Merge branch 'XX-1807/Version-Tagging' into 'release'` +const SEMVER = "1.1.1" +const GLIDEDEPS = `` diff --git a/go.mod b/go.mod index 542910b2896f91d5f0c7e99874cb23fdb9a5a5a0..c5b3ecf94b689cda3991e88517608066c29aa843 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.13 require ( github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 - github.com/golang/protobuf v1.3.2 + github.com/golang/protobuf v1.3.3 github.com/google/go-cmp v0.4.0 // indirect github.com/gopherjs/gopherjs v0.0.0-20191106031601-ce3c9ade29de // indirect github.com/pelletier/go-toml v1.6.0 // indirect @@ -16,14 +16,11 @@ require ( github.com/spf13/jwalterweatherman v1.1.0 github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.6.2 - gitlab.com/elixxir/comms v0.0.0-20200121191454-2e6135a303fe - gitlab.com/elixxir/crypto v0.0.0-20200108005412-8159c60663f9 - gitlab.com/elixxir/primitives v0.0.0-20200122202948-c556f3b5ab85 - golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d - golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa // indirect - golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9 // indirect - google.golang.org/genproto v0.0.0-20200128133413-58ce757ed39b // indirect - google.golang.org/grpc v1.27.0 // indirect - gopkg.in/ini.v1 v1.51.1 // indirect - gopkg.in/yaml.v2 v2.2.8 // indirect + gitlab.com/elixxir/comms v0.0.0-20200130173653-721e14282756 + gitlab.com/elixxir/crypto v0.0.0-20200205173613-ec404dbd2ad2 + gitlab.com/elixxir/primitives v0.0.0-20200131183153-e93c6b75019f + golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72 + golang.org/x/net v0.0.0-20200202094626-16171245cfb2 // indirect + google.golang.org/genproto v0.0.0-20200205142000-a86caf926a67 // indirect + gopkg.in/ini.v1 v1.52.0 // indirect ) diff --git a/go.sum b/go.sum index 7db2c546188d7b76cf3e416278a2f439ef36b787..ec8c0c8babd686ef9715737653b5a3d4d2c533d5 100644 --- a/go.sum +++ b/go.sum @@ -80,6 +80,8 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/gonum/blas v0.0.0-20181208220705-f22b278b28ac/go.mod h1:P32wAyui1PQ58Oce/KYkOqQv8cVw1zAapXOl+dRFGbc= github.com/gonum/floats v0.0.0-20181209220543-c233463c7e82/go.mod h1:PxC8OnwL11+aosOB5+iEPoV3picfs8tUpkVd0pDo+Kg= @@ -226,17 +228,17 @@ github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGr github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -gitlab.com/elixxir/comms v0.0.0-20200121191454-2e6135a303fe h1:oBEEc/9qXCkSyDv28yS4Bwjdkx1uRqkKWxAlaL1m95c= -gitlab.com/elixxir/comms v0.0.0-20200121191454-2e6135a303fe/go.mod h1:DblaR0msnWpNGzNK2fXvXbfGZQNPH4KPiBl4YkkGF4Y= +gitlab.com/elixxir/comms v0.0.0-20200130173653-721e14282756 h1:RYVhlBpxk2BmTPh/LBHHAdFkrfxOyD5TCsNfGphJL3w= +gitlab.com/elixxir/comms v0.0.0-20200130173653-721e14282756/go.mod h1:DblaR0msnWpNGzNK2fXvXbfGZQNPH4KPiBl4YkkGF4Y= gitlab.com/elixxir/crypto v0.0.0-20191121235352-86d305a9b253 h1:BqgqJ0mLANRjhAFLvGAcB5AWdgAnFZhsGx0qTk5G+3Y= gitlab.com/elixxir/crypto v0.0.0-20191121235352-86d305a9b253/go.mod h1:+46Zj/NE6JEkXExYnzdvvDokPpDbA+fJsRszvrezK9k= -gitlab.com/elixxir/crypto v0.0.0-20200108005412-8159c60663f9 h1:MJ87g3yMIvA9MTDMojuqaw1tCxU6LIKzxMaH3oEiP4M= -gitlab.com/elixxir/crypto v0.0.0-20200108005412-8159c60663f9/go.mod h1:+46Zj/NE6JEkXExYnzdvvDokPpDbA+fJsRszvrezK9k= +gitlab.com/elixxir/crypto v0.0.0-20200205173613-ec404dbd2ad2 h1:9i1dWxx/zMAFDM3aM1WaT/AmeJ5d2mIky18fwRSLs6U= +gitlab.com/elixxir/crypto v0.0.0-20200205173613-ec404dbd2ad2/go.mod h1:wWulHuSqxiGhvasduZrtyTTqy+7y5ebe440GdORhzig= gitlab.com/elixxir/primitives v0.0.0-20191028233752-882c08b8f095 h1:fnRh0PUwgy0qlWM7xMdk2w5MXh7gvQ0v/xyedn2gbcY= gitlab.com/elixxir/primitives v0.0.0-20191028233752-882c08b8f095/go.mod h1:+UiRRWzNpl/WoWUuQtJSoimfXImJAJ5lrrmg0pQKY3g= gitlab.com/elixxir/primitives v0.0.0-20200106183011-a68f1e6f188e/go.mod h1:g9v3S34ZUeqGRiOTV7esByK8a5TovJ3YgTv/328ny6w= -gitlab.com/elixxir/primitives v0.0.0-20200122202948-c556f3b5ab85 h1:ESFmep5i9xTJ7/dRPNXc4MJb8l4W34mfPmCZesrcOvU= -gitlab.com/elixxir/primitives v0.0.0-20200122202948-c556f3b5ab85/go.mod h1:REJMcwIcyxh74VSHqy4S9yYiaEsQYObOPglRExDpk14= +gitlab.com/elixxir/primitives v0.0.0-20200131183153-e93c6b75019f h1:F0YwFZz4umoXOJ+xX34WIRrucuLgHCSyKxWOKGaEt5g= +gitlab.com/elixxir/primitives v0.0.0-20200131183153-e93c6b75019f/go.mod h1:REJMcwIcyxh74VSHqy4S9yYiaEsQYObOPglRExDpk14= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -255,8 +257,8 @@ golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876 h1:sKJQZMuxjOAR/Uo2LBfU90onWEf1dF4C+0hPJCc9Mpc= golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200117160349-530e935923ad/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d h1:9FCpayM9Egr1baVnV1SX0H87m+XB0B8S0hAMi99X/3U= -golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72 h1:+ELyKg6m8UBf0nPFSqD0mi7zUfwPyXo23HNjMnXPz7w= +golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= @@ -286,8 +288,8 @@ golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa h1:F+8P+gmewFQYRk6JoLQLwjBCTu3mcIURZfNkVweuRKA= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -315,8 +317,8 @@ golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9 h1:1/DFK4b7JH8DmkqhUk48onnSfrPzImPoVxuomtbT2nk= -golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5 h1:LfCXLvNmTYH9kEmVgqbnsWfruoXZIrh4YBgqVHtDvw0= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -352,8 +354,8 @@ google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb h1:ADPHZzpzM4tk4V4S5cnCrr5SwzvlrPRmqqCuJDB8UTs= google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200128133413-58ce757ed39b h1:c8OBoXP3kTbDWWB/oVE3FkR851p4iZ3MPadz7zXEIPU= -google.golang.org/genproto v0.0.0-20200128133413-58ce757ed39b/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200205142000-a86caf926a67 h1:MBO9fkVSrTpJ8vgHLPi5gb+ZWXEy7/auJN8yqyu9EiE= +google.golang.org/genproto v0.0.0-20200205142000-a86caf926a67/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.0 h1:G+97AoqBnmZIT91cLG/EkCoK9NSelj64P8bOHHNmGn0= @@ -374,8 +376,8 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.51.1 h1:GyboHr4UqMiLUybYjd22ZjQIKEJEpgtLXtuGbR21Oho= -gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.52.0 h1:j+Lt/M1oPPejkniCg1TkWE2J3Eh1oZTsHSXzMTzUXn4= +gopkg.in/ini.v1 v1.52.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg= diff --git a/user/session.go b/user/session.go index f742b043e097e3737191bd326219f0bafc5c7b10..325db8c2db4c2eb13658903d8e69b67859f42a85 100644 --- a/user/session.go +++ b/user/session.go @@ -133,6 +133,18 @@ func LoadSession(store globals.Storage, password string) (Session, error) { return nil, err } + for wrappedSession.Version != SessionVersion { + switch wrappedSession.Version { + case 1: + globals.Log.INFO.Println("Converting session file from V1 to V2") + wrappedSession, err = ConvertSessionV1toV2(wrappedSession) + default: + } + if err != nil { + return nil, err + } + } + //extract teh session from the wrapper var sessionBytes bytes.Buffer @@ -160,27 +172,13 @@ func LoadSession(store globals.Storage, password string) (Session, error) { session.store = store session.password = password - // Update the session object to version 2 if it is currently version 1 - if wrappedSession.Version == 1 { - ConvertSessionV1toV2(&session) + if session.NodeKeys == nil { + session.NodeKeys = make(map[id.Node]NodeKeys) } return &session, nil } -// ConvertSessionV1toV2 converts the session object from version 1 to version 2. -// This conversion includes: -// 1. Changing the RegState values to the new integer values (1 to 2000, and 2 -// to 3000). -func ConvertSessionV1toV2(s *SessionObj) { - // Convert RegState to new values - if *s.RegState == 1 { - *s.RegState = 2000 - } else if *s.RegState == 2 { - *s.RegState = 3000 - } -} - //processSession: gets the loadLocation and decrypted wrappedSession func processSession(store globals.Storage, password string) (*SessionStorageWrapper, uint8, error) { var wrappedSession *SessionStorageWrapper @@ -242,6 +240,8 @@ func processSessionWrapper(sessionGob []byte, password string) (*SessionStorageW } // Struct holding relevant session data +// When adding to this structure, ALWAYS ALWAYS +// consider if you want the data to be in the session file type SessionObj struct { // Currently authenticated user CurrentUser *User @@ -471,6 +471,7 @@ func (s *SessionObj) GetCurrentUser() (currentUser *User) { currentUser = &User{ User: s.CurrentUser.User, Username: s.CurrentUser.Username, + Precan: s.CurrentUser.Precan, } } return currentUser diff --git a/user/session_test.go b/user/session_test.go index 7779e7f683e8e1db3316a2bb4c1057257c167cca..59068c9a7fa83d9668bb9502ce85eed2a30d42b3 100644 --- a/user/session_test.go +++ b/user/session_test.go @@ -9,6 +9,7 @@ package user import ( "bytes" "crypto/sha256" + "encoding/gob" "gitlab.com/elixxir/client/globals" "gitlab.com/elixxir/comms/connect" "gitlab.com/elixxir/crypto/cyclic" @@ -580,7 +581,7 @@ func TestSessionObj_PopGarbledMessages(t *testing.T) { } -// Tests ConvertSessionV1toV2() by creating an empty session object and setting +/*// Tests ConvertSessionV1toV2() by creating an empty session object and setting // the RegState to the version 1, running it through the function, and testing // that RegState has values that match version 2. func TestSessionObj_ConvertSessionV1toV2(t *testing.T) { @@ -617,7 +618,7 @@ func TestSessionObj_ConvertSessionV1toV2(t *testing.T) { "session object's RegState\n\texpected: %v\n\treceived: %v", 3000, *ses.RegState) } -} +}*/ func GenerateTestMessages(size int) []*format.Message { msgs := make([]*format.Message, size) @@ -632,3 +633,51 @@ func GenerateTestMessages(size int) []*format.Message { return msgs } + +// Happy path +func TestConvertSessionV1toV2(t *testing.T) { + u := new(User) + UID := id.NewUserFromUint(1, t) + + u.User = UID + u.Username = "Bernie" + + session := NewSession(nil, u, nil, nil, + nil, nil, nil, + nil, nil, nil, nil, "") + var sessionBuffer bytes.Buffer + + enc := gob.NewEncoder(&sessionBuffer) + + err := enc.Encode(session) + if err != nil { + t.Errorf("Failed to getSessionData: %+v", err) + } + + storageWrapper := &SessionStorageWrapper{Version: 1, Session: sessionBuffer.Bytes()} + newSession, err := ConvertSessionV1toV2(storageWrapper) + if err != nil { + t.Errorf("Failed conversion: %+v", err) + } + + if newSession.Version != SessionVersion { + t.Errorf("ConvertSessionV1toV2 should modify version number") + } + +} + +// Error path: Pass in an improper session +func TestConvertSessionV1toV2_Error(t *testing.T) { + // Pass in an improper session + var sessionBuffer bytes.Buffer + + _ = gob.NewEncoder(&sessionBuffer) + + storageWrapper := &SessionStorageWrapper{Version: 1, Session: sessionBuffer.Bytes()} + + _, err := ConvertSessionV1toV2(storageWrapper) + if err == nil { + t.Errorf("Failed conversion: %+v", err) + } + +} diff --git a/user/sessionv1.go b/user/sessionv1.go new file mode 100644 index 0000000000000000000000000000000000000000..0496913de013df8972cc45d0c5fb7dc88e785bb5 --- /dev/null +++ b/user/sessionv1.go @@ -0,0 +1,155 @@ +package user + +import ( + "bytes" + "encoding/gob" + "fmt" + "github.com/pkg/errors" + "gitlab.com/elixxir/client/globals" + "gitlab.com/elixxir/client/keyStore" + "gitlab.com/elixxir/crypto/cyclic" + "gitlab.com/elixxir/crypto/signature/rsa" + "gitlab.com/elixxir/primitives/format" + "gitlab.com/elixxir/primitives/id" + "gitlab.com/elixxir/primitives/switchboard" + "sync" +) + +// Struct holding relevant session data +type SessionObjV1 struct { + // Currently authenticated user + CurrentUser *UserV1 + + Keys map[id.Node]NodeKeys + RSAPrivateKey *rsa.PrivateKey + RSAPublicKey *rsa.PublicKey + CMIXDHPrivateKey *cyclic.Int + CMIXDHPublicKey *cyclic.Int + E2EDHPrivateKey *cyclic.Int + E2EDHPublicKey *cyclic.Int + CmixGrp *cyclic.Group + E2EGrp *cyclic.Group + Salt []byte + + // Last received message ID. Check messages after this on the gateway. + LastMessageID string + + //Interface map for random data storage + InterfaceMap map[string]interface{} + + // E2E KeyStore + KeyMaps *keyStore.KeyStore + + // Rekey Manager + RekeyManager *keyStore.RekeyManager + + // Non exported fields (not GOB encoded/decoded) + // Local pointer to storage of this session + store globals.Storage + + // Switchboard + listeners *switchboard.Switchboard + + // Quit channel for message reception runner + quitReceptionRunner chan struct{} + + lock sync.Mutex + + // The password used to encrypt this session when saved + password string + + //The validation signature provided by permissioning + regValidationSignature []byte + + // Buffer of messages that cannot be decrypted + garbledMessages []*format.Message + + RegState *uint32 + + storageLocation uint8 + + ContactsByValue map[string]SearchedUserRecord +} + +// Struct representing a User in the system +type UserV1 struct { + User *id.User + Nick string + Email string +} + +// ConvertSessionV1toV2 converts the session object from version 1 to version 2. +// This conversion includes: +// 1. Changing the RegState values to the new integer values (1 to 2000, and 2 +// to 3000). +func ConvertSessionV1toV2(inputWrappedSession *SessionStorageWrapper) (*SessionStorageWrapper, error) { + //extract teh session from the wrapper + var sessionBytes bytes.Buffer + + //get the old session object + sessionBytes.Write(inputWrappedSession.Session) + dec := gob.NewDecoder(&sessionBytes) + + sessionV1 := SessionObjV1{} + + err := dec.Decode(&sessionV1) + if err != nil { + return nil, errors.Wrap(err, "Unable to decode session") + } + + sessionV2 := SessionObj{} + + // Convert RegState to new values + if *sessionV1.RegState == 1 { + *sessionV1.RegState = 2000 + } else if *sessionV1.RegState == 2 { + *sessionV1.RegState = 3000 + } + + //convert the user object + sessionV2.CurrentUser = &User{ + User: sessionV1.CurrentUser.User, + Username: sessionV1.CurrentUser.Email, + } + + //port identical values over + sessionV2.NodeKeys = sessionV1.Keys + sessionV2.RSAPrivateKey = sessionV1.RSAPrivateKey + sessionV2.RSAPublicKey = sessionV1.RSAPublicKey + sessionV2.CMIXDHPrivateKey = sessionV1.CMIXDHPrivateKey + sessionV2.CMIXDHPublicKey = sessionV1.CMIXDHPublicKey + sessionV2.E2EDHPrivateKey = sessionV1.E2EDHPrivateKey + sessionV2.E2EDHPublicKey = sessionV1.E2EDHPublicKey + sessionV2.CmixGrp = sessionV1.CmixGrp + sessionV2.E2EGrp = sessionV1.E2EGrp + sessionV2.Salt = sessionV1.Salt + sessionV2.LastMessageID = sessionV1.LastMessageID + sessionV2.InterfaceMap = sessionV1.InterfaceMap + sessionV2.KeyMaps = sessionV1.KeyMaps + sessionV2.RekeyManager = sessionV1.RekeyManager + sessionV2.RegValidationSignature = sessionV1.regValidationSignature + sessionV2.RegState = sessionV1.RegState + sessionV2.ContactsByValue = sessionV1.ContactsByValue + + //re encode the session + var sessionBuffer bytes.Buffer + + enc := gob.NewEncoder(&sessionBuffer) + + err = enc.Encode(sessionV2) + + if err != nil { + err = errors.New(fmt.Sprintf("ConvertSessionV1toV2: Could not "+ + " store session v2: %s", err.Error())) + return nil, err + } + + //build the session wrapper + ssw := SessionStorageWrapper{ + Version: 2, + Timestamp: inputWrappedSession.Timestamp, + Session: sessionBuffer.Bytes(), + } + + return &ssw, nil +} diff --git a/user/user.go b/user/user.go index deff4cb45ed89793089083e5b819430421cd4104..6f0e56b7619a3d15457b80e37a70bd7d1d9392a2 100644 --- a/user/user.go +++ b/user/user.go @@ -57,55 +57,56 @@ func newRegistry(grp *cyclic.Group) Registry { if len(DemoChannelNames) > 10 || len(DemoUserNicks) > 30 { globals.Log.ERROR.Print("Not enough demo users have been hardcoded.") } - uc := make(map[id.User]*User) - ul := make(map[string]*id.User) + userUserIdMap := make(map[id.User]*User) + userRegCodeMap := make(map[string]*id.User) nk := make(map[id.User]*NodeKeys) // Deterministically create NumDemoUsers users // TODO Replace this with real user registration/discovery for i := uint64(1); i <= NumDemoUsers; i++ { currentID := id.NewUserFromUints(&[4]uint64{0, 0, 0, i}) - t := new(User) - k := new(NodeKeys) + newUsr := new(User) + nodeKey := new(NodeKeys) // Generate user parameters - t.User = currentID + newUsr.User = currentID + newUsr.Precan = true currentID.RegistrationCode() // TODO We need a better way to generate base/recursive keys h := sha256.New() h.Write([]byte(string(40000 + i))) - k.TransmissionKey = grp.NewIntFromBytes(h.Sum(nil)) + nodeKey.TransmissionKey = grp.NewIntFromBytes(h.Sum(nil)) h = sha256.New() h.Write([]byte(string(60000 + i))) - k.ReceptionKey = grp.NewIntFromBytes(h.Sum(nil)) + nodeKey.ReceptionKey = grp.NewIntFromBytes(h.Sum(nil)) // Add user to collection and lookup table - uc[*t.User] = t + userUserIdMap[*newUsr.User] = newUsr // Detect collisions in the registration code - if _, ok := ul[t.User.RegistrationCode()]; ok { + if _, ok := userRegCodeMap[newUsr.User.RegistrationCode()]; ok { globals.Log.ERROR.Printf( "Collision in demo user list creation at %v. "+ "Please fix ASAP (include more bits to the reg code.", i) } - ul[t.User.RegistrationCode()] = t.User - nk[*t.User] = k + userRegCodeMap[newUsr.User.RegistrationCode()] = newUsr.User + nk[*newUsr.User] = nodeKey } // Channels have been hardcoded to users starting with 31 for i := 0; i < len(DemoUserNicks); i++ { currentID := id.NewUserFromUints(&[4]uint64{0, 0, 0, uint64(i) + 1}) - uc[*currentID].Username = DemoUserNicks[i] + userUserIdMap[*currentID].Username = DemoUserNicks[i] } for i := 0; i < len(DemoChannelNames); i++ { currentID := id.NewUserFromUints(&[4]uint64{0, 0, 0, uint64(i) + 31}) - uc[*currentID].Username = DemoChannelNames[i] + userUserIdMap[*currentID].Username = DemoChannelNames[i] } // With an underlying UserMap data structure - return Registry(&UserMap{userCollection: uc, + return Registry(&UserMap{userCollection: userUserIdMap, idCounter: uint64(NumDemoUsers), - userLookup: ul, + userLookup: userRegCodeMap, keysLookup: nk}) } @@ -113,6 +114,7 @@ func newRegistry(grp *cyclic.Group) Registry { type User struct { User *id.User Username string + Precan bool } // DeepCopy performs a deep copy of a user and returns a pointer to the new copy @@ -123,6 +125,7 @@ func (u *User) DeepCopy() *User { nu := new(User) nu.User = u.User nu.Username = u.Username + nu.Precan = u.Precan return nu }