diff --git a/ud/addFact.go b/ud/addFact.go index 2dc11dfb46cbac1f09e66cb0d526f059b6da6b51..6412e94b308871e9aa7266b2176e39cb8f169376 100644 --- a/ud/addFact.go +++ b/ud/addFact.go @@ -26,7 +26,9 @@ func (m *Manager) SendRegisterFact(f fact.Fact) (string, error) { return m.addFact(f, m.e2e.GetReceptionID(), m.comms) } -func (m *Manager) addFact(inFact fact.Fact, myId *id.ID, aFC addFactComms) (string, error) { +// addFact is the helper function for SendRegisterFact. +func (m *Manager) addFact(inFact fact.Fact, myId *id.ID, + aFC addFactComms) (string, error) { // get UD host udHost, err := m.getOrAddUdHost() diff --git a/ud/confirmFact.go b/ud/confirmFact.go index 77d1f9abe0913ea523ee1d0ff9b2139d778ef3c2..fb81b7a9ee78e373fb54aaa6504d22c4eb1fa35b 100644 --- a/ud/confirmFact.go +++ b/ud/confirmFact.go @@ -17,6 +17,7 @@ func (m *Manager) ConfirmFact(confirmationID, code string) error { return nil } +// confirmFact is a helper function for ConfirmFact. func (m *Manager) confirmFact(confirmationID, code string, comm confirmFactComm) error { // get UD host udHost, err := m.getOrAddUdHost() diff --git a/ud/manager.go b/ud/manager.go index 692e787a6cee3299a6381cb367f9f25bbf62f299..8fd419e1e008e7d57cdcd9810ce13003cbda8cda 100644 --- a/ud/manager.go +++ b/ud/manager.go @@ -14,7 +14,6 @@ import ( "gitlab.com/elixxir/primitives/fact" "gitlab.com/xx_network/comms/connect" "gitlab.com/xx_network/primitives/id" - "math" "sync" "time" ) @@ -56,9 +55,9 @@ type Manager struct { // signature operations. rng *fastRNG.StreamGenerator - // kv is a versioned key-value store - // fixme: this is used for isRegistered and setRegistered - // which should be moved to store if possible (prefixing might break this?) + // kv is a versioned key-value store used for isRegistered and + // setRegistered. This is separated from store operations as store's kv + // has a different prefix which breaks backwards compatibility. kv *versioned.KV // factMux is to be used for Add/Remove fact.Fact operations. @@ -86,30 +85,25 @@ func NewManager(services cmix.Client, e2e E2E, "cannot start UD Manager when network follower is not running.") } - udStore, err := store.NewOrLoadStore(kv) - if err != nil { - return nil, errors.Errorf("Failed to initialize store: %v", err) - } - + // Initialize manager m := &Manager{ network: services, e2e: e2e, events: events, comms: comms, rng: rng, - store: udStore, user: userStore, kv: kv, } - // check that user discovery is available in the NDF - def := m.network.GetInstance().GetPartialNdf().Get() - - if def.UDB.Cert == "" { - return nil, errors.New("NDF does not have User Discovery " + - "information, is there network access?: Cert not present.") + // Initialize store + var err error + m.store, err = store.NewOrLoadStore(kv) + if err != nil { + return nil, errors.Errorf("Failed to initialize store: %v", err) } + // Initialize/Get host udHost, err := m.getOrAddUdHost() if err != nil { return nil, errors.WithMessage(err, "User Discovery host object could "+ @@ -123,7 +117,6 @@ func NewManager(services cmix.Client, e2e E2E, } // Set storage to registered - // todo: maybe we don't need this? if err = m.setRegistered(); err != nil && m.events != nil { m.events.Report(1, "UserDiscovery", "Registration", fmt.Sprintf("User Registered with UD: %+v", @@ -148,6 +141,7 @@ func NewManagerFromBackup(services cmix.Client, "network follower is not running.") } + // Initialize manager m := &Manager{ network: services, e2e: e2e, @@ -158,38 +152,29 @@ func NewManagerFromBackup(services cmix.Client, kv: kv, } - udStore, err := store.NewOrLoadStore(kv) + // Initialize our store + var err error + m.store, err = store.NewOrLoadStore(kv) if err != nil { return nil, err } - m.store = udStore - + // Put any passed in missing facts into store err = m.store.BackUpMissingFacts(email, phone) if err != nil { return nil, errors.WithMessage(err, "Failed to restore UD store "+ "from backup") } - // check that user discovery is available in the NDF - def := m.network.GetInstance().GetPartialNdf().Get() - - if def.UDB.Cert == "" { - return nil, errors.New("NDF does not have User Discovery information, " + - "is there network access?: Cert not present.") - } - // Create the user discovery host object - hp := connect.GetDefaultHostParams() - // Client will not send KeepAlive packets - hp.KaClientOpts.Time = time.Duration(math.MaxInt64) - hp.MaxRetries = 3 - hp.SendTimeout = 3 * time.Second - hp.AuthEnabled = false + _, err = m.getOrAddUdHost() + if err != nil { + return nil, errors.WithMessage(err, "User Discovery host object could "+ + "not be constructed.") + } // Set as registered. Since it's from a backup, // the client is already registered - // todo: maybe we don't need this? if err = m.setRegistered(); err != nil { return nil, errors.WithMessage(err, "failed to set client as "+ "registered with user discovery.") @@ -198,6 +183,9 @@ func NewManagerFromBackup(services cmix.Client, return m, nil } +// LoadManager loads the state of the Manager +// from disk. This is meant to be called after any the first +// instantiation of the manager by NewUserDiscovery. func LoadManager(services cmix.Client, e2e E2E, events event.Reporter, comms Comms, userStore UserInfo, rng *fastRNG.StreamGenerator, kv *versioned.KV) (*Manager, error) { @@ -217,13 +205,12 @@ func LoadManager(services cmix.Client, e2e E2E, "the user has been registered. Has a manager been initiated before?") } - udStore, err := store.NewOrLoadStore(kv) + var err error + m.store, err = store.NewOrLoadStore(kv) if err != nil { return nil, errors.Errorf("Failed to initialize store: %v", err) } - m.store = udStore - return m, err } @@ -270,8 +257,6 @@ func (m *Manager) GetContact() (contact.Contact, error) { errors.Errorf("failed to unmarshal UD ID from NDF: %+v", err) } - fmt.Printf("netDef ud dhpub: %v\n", netDef.UDB.DhPubKey) - // Unmarshal UD DH public key dhPubKey := grp.NewInt(1) if err = dhPubKey.UnmarshalJSON(netDef.UDB.DhPubKey); err != nil { @@ -297,6 +282,11 @@ func (m *Manager) getOrAddUdHost() (*connect.Host, error) { } netDef := m.network.GetInstance().GetPartialNdf().Get() + if netDef.UDB.Cert == "" { + return nil, errors.New("NDF does not have User Discovery information, " + + "is there network access?: Cert not present.") + } + // Unmarshal UD ID from the NDF udID, err := id.Unmarshal(netDef.UDB.ID) if err != nil { diff --git a/ud/remove.go b/ud/remove.go index 497ef2c595469c63789ff670934eadce9ee6c11a..61d130ec240ad1bda693af3c39c9660f7858f597 100644 --- a/ud/remove.go +++ b/ud/remove.go @@ -14,8 +14,9 @@ import ( "gitlab.com/xx_network/primitives/id" ) -// RemoveFact removes a previously confirmed fact. Will fail if the fact is not -// associated with this client. +// RemoveFact removes a previously confirmed fact. This will fail +// if the fact passed in is not UD service does not associate this +// fact with this user. func (m *Manager) RemoveFact(f fact.Fact) error { jww.INFO.Printf("ud.RemoveFact(%s)", f.Stringify()) m.factMux.Lock() @@ -23,6 +24,8 @@ func (m *Manager) RemoveFact(f fact.Fact) error { return m.removeFact(f, m.comms) } +// removeFact is a helper function which contacts the UD service +// to remove the association of a fact with a user. func (m *Manager) removeFact(f fact.Fact, rFC removeFactComms) error { @@ -66,8 +69,9 @@ func (m *Manager) removeFact(f fact.Fact, return m.store.DeleteFact(f) } -// PermanentDeleteAccount removes a previously confirmed fact. -// This call will fail if the fact is not associated with this client. +// PermanentDeleteAccount removes the username associated with this user +// from the UD service. This will only take a username type fact, +// and the fact must be associated with this user. func (m *Manager) PermanentDeleteAccount(f fact.Fact) error { jww.INFO.Printf("ud.PermanentDeleteAccount(%s)", f.Stringify()) if f.T != fact.Username { @@ -84,6 +88,7 @@ func (m *Manager) PermanentDeleteAccount(f fact.Fact) error { return m.permanentDeleteAccount(f, m.e2e.GetReceptionID(), privKey, m.comms, udHost) } +// permanentDeleteAccount is a helper function for PermanentDeleteAccount. func (m *Manager) permanentDeleteAccount(f fact.Fact, myId *id.ID, privateKey *rsa.PrivateKey, rFC removeUserComms, udHost *connect.Host) error { diff --git a/ud/store/facts.go b/ud/store/facts.go index 127e09d2bcf6287800f53e8c6496ff7e59114f0a..f2929c3fa22a9a206d4d5b3a9a16dbc2bbd1ffc3 100644 --- a/ud/store/facts.go +++ b/ud/store/facts.go @@ -10,9 +10,7 @@ package ud import ( "fmt" "github.com/pkg/errors" - "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/primitives/fact" - "sync" ) const ( @@ -24,31 +22,6 @@ const ( statefulStoreErr = "cannot overwrite ud store with existing data" ) -// Store is the storage object for the higher level ud.Manager object. -// This storage implementation is written for client side. -type Store struct { - // confirmedFacts contains facts that have been confirmed - confirmedFacts map[fact.Fact]struct{} - // Stores facts that have been added by UDB but unconfirmed facts. - // Maps confirmID to fact - unconfirmedFacts map[string]fact.Fact - kv *versioned.KV - mux sync.RWMutex -} - -// NewStore creates a new, empty Store object. -func NewStore(kv *versioned.KV) (*Store, error) { - kv = kv.Prefix(prefix) - - s := &Store{ - confirmedFacts: make(map[fact.Fact]struct{}, 0), - unconfirmedFacts: make(map[string]fact.Fact, 0), - kv: kv, - } - - return s, s.save() -} - // RestoreFromBackUp initializes the confirmedFacts map // with the backed up fact data. This will error if // the store is already stateful. diff --git a/ud/store/store.go b/ud/store/store.go index 45b7ffdc4e1e516445e0761f7bad08b9ca666e0c..0cf274add91a8d08791e7b0c189b8d190d0f7962 100644 --- a/ud/store/store.go +++ b/ud/store/store.go @@ -10,6 +10,7 @@ import ( "gitlab.com/xx_network/primitives/netTime" "io/fs" "strings" + "sync" ) // Storage constants @@ -30,12 +31,29 @@ const ( saveConfirmedFactErr = "Failed to save confirmed facts" ) -// unconfirmedFactDisk is an object used to store the data of an unconfirmed fact. -// It combines the key (confirmationId) and fact data (stringifiedFact) into a -// single JSON-able object. -type unconfirmedFactDisk struct { - confirmationId string - stringifiedFact string +// Store is the storage object for the higher level ud.Manager object. +// This storage implementation is written for client side. +type Store struct { + // confirmedFacts contains facts that have been confirmed + confirmedFacts map[fact.Fact]struct{} + // Stores facts that have been added by UDB but unconfirmed facts. + // Maps confirmID to fact + unconfirmedFacts map[string]fact.Fact + kv *versioned.KV + mux sync.RWMutex +} + +// NewStore creates a new, empty Store object. +func NewStore(kv *versioned.KV) (*Store, error) { + kv = kv.Prefix(prefix) + + s := &Store{ + confirmedFacts: make(map[fact.Fact]struct{}, 0), + unconfirmedFacts: make(map[string]fact.Fact, 0), + kv: kv, + } + + return s, s.save() } ///////////////////////////////////////////////////////////////// @@ -180,6 +198,14 @@ func (s *Store) loadUnconfirmedFacts() error { // MARSHAL/UNMARSHAL FUNCTIONS ///////////////////////////////////////////////////////////////// +// unconfirmedFactDisk is an object used to store the data of an unconfirmed fact. +// It combines the key (confirmationId) and fact data (stringifiedFact) into a +// single JSON-able object. +type unconfirmedFactDisk struct { + confirmationId string + stringifiedFact string +} + // marshalConfirmedFacts is a marshaller which serializes the data //// in the confirmedFacts map into a JSON. func (s *Store) marshalConfirmedFacts() ([]byte, error) {