From 30f433a85d3351ff1b378089f15970294edfc988 Mon Sep 17 00:00:00 2001 From: joshemb <josh@elixxir.io> Date: Mon, 22 Aug 2022 09:23:04 -0700 Subject: [PATCH] Have UD store username --- bindings/ud.go | 21 +++++++++++++++++---- ud/manager.go | 14 +++++++++++--- ud/store/facts.go | 36 ++++++++++++++++++++++++++++++++++-- ud/store/facts_test.go | 37 ++++++++++++++++++++++++++++--------- 4 files changed, 90 insertions(+), 18 deletions(-) diff --git a/bindings/ud.go b/bindings/ud.go index c9f75557f..217fb964b 100644 --- a/bindings/ud.go +++ b/bindings/ud.go @@ -208,6 +208,9 @@ func NewOrLoadUd(e2eID int, follower UdNetworkStatus, username string, // Parameters: // - e2eID - e2e object ID in the tracker // - follower - network follower func wrapped in UdNetworkStatus +// - username - The username this user registered with initially. This should +// not be nullable, and be JSON marshalled as retrieved from +// UserDiscovery.GetFacts(). // - emailFactJson - nullable JSON marshalled email [fact.Fact] // - phoneFactJson - nullable JSON marshalled phone [fact.Fact] // - cert - the TLS certificate for the UD server this call will connect with. @@ -220,8 +223,9 @@ func NewOrLoadUd(e2eID int, follower UdNetworkStatus, username string, // - address - the IP address of the UD server this call will connect with. You // may use the UD server run by the xx network team by using // E2e.GetUdAddressFromNdf. -func NewUdManagerFromBackup(e2eID int, follower UdNetworkStatus, emailFactJson, - phoneFactJson, cert, contactFile []byte, address string) (*UserDiscovery, error) { +func NewUdManagerFromBackup(e2eID int, follower UdNetworkStatus, + usernameJson, emailFactJson, phoneFactJson, + cert, contactFile []byte, address string) (*UserDiscovery, error) { // Get user from singleton user, err := e2eTrackerSingleton.get(e2eID) @@ -229,7 +233,9 @@ func NewUdManagerFromBackup(e2eID int, follower UdNetworkStatus, emailFactJson, return nil, err } - var email, phone fact.Fact + var email, phone, username fact.Fact + + // Parse email if non-nil if emailFactJson != nil { err = json.Unmarshal(emailFactJson, &email) if err != nil { @@ -237,6 +243,7 @@ func NewUdManagerFromBackup(e2eID int, follower UdNetworkStatus, emailFactJson, } } + // Parse phone if non-nil if phoneFactJson != nil { err = json.Unmarshal(phoneFactJson, &phone) if err != nil { @@ -244,13 +251,19 @@ func NewUdManagerFromBackup(e2eID int, follower UdNetworkStatus, emailFactJson, } } + // Parse username + err = json.Unmarshal(usernameJson, &username) + if err != nil { + return nil, err + } + UdNetworkStatusFn := func() xxdk.Status { return xxdk.Status(follower.UdNetworkStatus()) } u, err := ud.NewManagerFromBackup( user.api, user.api.GetComms(), UdNetworkStatusFn, - email, phone, + username, email, phone, cert, contactFile, address) if err != nil { return nil, err diff --git a/ud/manager.go b/ud/manager.go index 1f2301050..d431da78c 100644 --- a/ud/manager.go +++ b/ud/manager.go @@ -102,6 +102,13 @@ func NewOrLoad(user udE2e, comms Comms, follower udNetworkStatus, return nil, err } + usernameFact, err := fact.NewFact(fact.Username, username) + if err != nil { + return nil, err + } + + err = m.store.StoreUsername(usernameFact) + return m, nil } @@ -127,7 +134,8 @@ func NewOrLoad(user udE2e, comms Comms, follower udNetworkStatus, // Returns // - A Manager object which is registered to the specified UD service. func NewManagerFromBackup(user udE2e, comms Comms, follower udNetworkStatus, - email, phone fact.Fact, cert, contactFile []byte, address string) (*Manager, error) { + username, email, phone fact.Fact, + cert, contactFile []byte, address string) (*Manager, error) { jww.INFO.Println("ud.NewManagerFromBackup()") if follower() != xxdk.Running { return nil, errors.New( @@ -149,7 +157,7 @@ func NewManagerFromBackup(user udE2e, comms Comms, follower udNetworkStatus, } // Put any passed in missing facts into store - err = m.store.BackUpMissingFacts(email, phone) + err = m.store.BackUpMissingFacts(username, email, phone) if err != nil { return nil, errors.WithMessage(err, "Failed to restore UD store "+ "from backup") @@ -180,7 +188,7 @@ func InitStoreFromBackup(kv *versioned.KV, } // Put any passed in missing facts into store - err = udStore.BackUpMissingFacts(email, phone) + err = udStore.BackUpMissingFacts(username, email, phone) if err != nil { return errors.WithMessage(err, "Failed to restore UD store "+ "from backup") diff --git a/ud/store/facts.go b/ud/store/facts.go index 202d8814b..8ca6c8c37 100644 --- a/ud/store/facts.go +++ b/ud/store/facts.go @@ -42,6 +42,22 @@ func (s *Store) RestoreFromBackUp(backupData fact.FactList) error { return s.save() } +// StoreUsername forces the storage of a username fact.Fact into the +// Store's confirmedFacts map. The passed in fact.Fact must be of +// type fact.Username or this will not store the username. +func (s *Store) StoreUsername(f fact.Fact) error { + s.mux.Lock() + defer s.mux.Unlock() + + if f.T != fact.Username { + return errors.Errorf("Fact (%s) is not of type username", f.Stringify()) + } + + s.confirmedFacts[f] = struct{}{} + + return s.saveUnconfirmedFacts() +} + // StoreUnconfirmedFact stores a fact that has been added to UD but has not been // confirmed by the user. It is keyed on the confirmation ID given by UD. func (s *Store) StoreUnconfirmedFact(confirmationId string, f fact.Fact) error { @@ -84,11 +100,11 @@ func (s *Store) ConfirmFact(confirmationId string) error { // If you attempt to back up a fact type that has already been backed up, // an error will be returned and nothing will be backed up. // Otherwise, it adds the fact and returns whether the Store saved successfully. -func (s *Store) BackUpMissingFacts(email, phone fact.Fact) error { +func (s *Store) BackUpMissingFacts(username, email, phone fact.Fact) error { s.mux.Lock() defer s.mux.Unlock() - modifiedEmail, modifiedPhone := false, false + modifiedUsername, modifiedEmail, modifiedPhone := false, false, false // Handle email if it is not zero (empty string) if !isFactZero(email) { @@ -106,6 +122,7 @@ func (s *Store) BackUpMissingFacts(email, phone fact.Fact) error { } } + // Handle phone if it is not an empty string if !isFactZero(phone) { // check if fact is expected type if phone.T != fact.Phone { @@ -121,6 +138,17 @@ func (s *Store) BackUpMissingFacts(email, phone fact.Fact) error { } } + if !isFactZero(username) { + // Check if fact type is already in map. You should not be able to + // overwrite your username. + if isFactTypeInMap(fact.Username, s.confirmedFacts) { + // If a username exists in memory, return an error + return errors.Errorf(factTypeExistsErr, username, fact.Username) + } else { + modifiedUsername = true + } + } + if modifiedPhone || modifiedEmail { if modifiedEmail { s.confirmedFacts[email] = struct{}{} @@ -130,6 +158,10 @@ func (s *Store) BackUpMissingFacts(email, phone fact.Fact) error { s.confirmedFacts[phone] = struct{}{} } + if modifiedUsername { + s.confirmedFacts[username] = struct{}{} + } + return s.saveConfirmedFacts() } diff --git a/ud/store/facts_test.go b/ud/store/facts_test.go index 332b5289d..edb141e97 100644 --- a/ud/store/facts_test.go +++ b/ud/store/facts_test.go @@ -203,7 +203,12 @@ func TestStore_BackUpMissingFacts(t *testing.T) { T: fact.Phone, } - err = expectedStore.BackUpMissingFacts(email, phone) + username := fact.Fact{ + Fact: "admin", + T: fact.Username, + } + + err = expectedStore.BackUpMissingFacts(username, email, phone) if err != nil { t.Fatalf("BackUpMissingFacts() produced an error: %v", err) } @@ -238,18 +243,23 @@ func TestStore_BackUpMissingFacts_DuplicateFactType(t *testing.T) { T: fact.Phone, } - err = expectedStore.BackUpMissingFacts(email, phone) + username := fact.Fact{ + Fact: "admin", + T: fact.Username, + } + + err = expectedStore.BackUpMissingFacts(username, email, phone) if err != nil { t.Fatalf("BackUpMissingFacts() produced an error: %v", err) } - err = expectedStore.BackUpMissingFacts(email, fact.Fact{}) + err = expectedStore.BackUpMissingFacts(username, email, fact.Fact{}) if err == nil { t.Fatalf("BackUpMissingFacts() should not allow backing up an "+ "email when an email has already been backed up: %v", err) } - err = expectedStore.BackUpMissingFacts(fact.Fact{}, phone) + err = expectedStore.BackUpMissingFacts(username, fact.Fact{}, phone) if err == nil { t.Fatalf("BackUpMissingFacts() should not allow backing up a "+ "phone number when a phone number has already been backed up: %v", err) @@ -272,7 +282,12 @@ func TestStore_GetFacts(t *testing.T) { emptyFact := fact.Fact{} - err = testStore.BackUpMissingFacts(emailFact, emptyFact) + username := fact.Fact{ + Fact: "admin", + T: fact.Username, + } + + err = testStore.BackUpMissingFacts(username, emailFact, emptyFact) if err != nil { t.Fatalf("Faild to add fact %v: %v", emailFact, err) } @@ -282,7 +297,7 @@ func TestStore_GetFacts(t *testing.T) { T: fact.Phone, } - err = testStore.BackUpMissingFacts(emptyFact, phoneFact) + err = testStore.BackUpMissingFacts(username, emptyFact, phoneFact) if err != nil { t.Fatalf("Faild to add fact %v: %v", phoneFact, err) } @@ -318,10 +333,14 @@ func TestStore_GetFactStrings(t *testing.T) { Fact: "josh@elixxir.io", T: fact.Email, } + username := fact.Fact{ + Fact: "admin", + T: fact.Username, + } emptyFact := fact.Fact{} - err = testStore.BackUpMissingFacts(emailFact, emptyFact) + err = testStore.BackUpMissingFacts(username, emailFact, emptyFact) if err != nil { t.Fatalf("Faild to add fact %v: %v", emailFact, err) } @@ -331,12 +350,12 @@ func TestStore_GetFactStrings(t *testing.T) { T: fact.Phone, } - err = testStore.BackUpMissingFacts(emptyFact, phoneFact) + err = testStore.BackUpMissingFacts(emptyFact, emptyFact, phoneFact) if err != nil { t.Fatalf("Faild to add fact %v: %v", phoneFact, err) } - expectedFacts := []string{emailFact.Stringify(), phoneFact.Stringify()} + expectedFacts := []string{username.Stringify(), emailFact.Stringify(), phoneFact.Stringify()} receivedFacts := testStore.GetStringifiedFacts() sort.SliceStable(receivedFacts, func(i, j int) bool { -- GitLab