diff --git a/api/client.go b/api/client.go index a289fea1e030118346df4011ef5601e49438fe6d..b7d91086a6f2ef483c0033ba2dccddebe39533cc 100644 --- a/api/client.go +++ b/api/client.go @@ -684,6 +684,30 @@ func (c *Client) GetNodeRegistrationStatus() (int, int, error) { return numRegistered, len(nodes) - numStale, nil } +// DeleteSentRequest will delete a Sent request for the given partner ID. +// If no request exists for this partner ID, or the request is not +// a Sent request, an error will be returned. +func (c *Client) DeleteSentRequest(partnerId *id.ID) error { + jww.DEBUG.Printf("Deleting sent request for partner ID: %s", partnerId) + return c.GetStorage().Auth().DeleteSentRequest(partnerId) +} + +// DeleteReceiveRequest will delete a Receive request for the given partner ID. +// If no request exists for this partner ID, or the request is not +// a Receive request, an error will be returned. +func (c *Client) DeleteReceiveRequest(partnerId *id.ID) error { + jww.DEBUG.Printf("Deleting receive request for partner ID: %s", partnerId) + return c.GetStorage().Auth().DeleteReceiveRequest(partnerId) +} + +// DeleteRequest will delete a request, agnostic of request type +// for the given partner ID. If no request exists for this +// partner ID an error will be returned. +func (c *Client) DeleteRequest(partnerId *id.ID) error { + jww.DEBUG.Printf("Deleting request for partner ID: %s", partnerId) + return c.GetStorage().Auth().DeleteRequest(partnerId) +} + // DeleteAllRequests clears all requests from client's auth storage. func (c *Client) DeleteAllRequests() error { jww.DEBUG.Printf("Deleting all requests") diff --git a/bindings/client.go b/bindings/client.go index 1996507cbc0a005ae20006763f6596fe1ca25834..dbca6bdc28ed2e83dc74d849f8f5600029595044 100644 --- a/bindings/client.go +++ b/bindings/client.go @@ -450,6 +450,30 @@ func (c *Client) GetNodeRegistrationStatus() (*NodeRegistrationsStatus, error) { return &NodeRegistrationsStatus{registered, total}, err } +// DeleteSentRequest will delete a Sent request for the given partner ID. +// If no request exists for this partner ID, or the request is not +// a Sent request, an error will be returned. +func (c *Client) DeleteSentRequest(partnerId *id.ID) error { + jww.DEBUG.Printf("Deleting sent request for partner ID: %s", partnerId) + return c.api.DeleteSentRequest(partnerId) +} + +// DeleteReceiveRequest will delete a Receive request for the given partner ID. +// If no request exists for this partner ID, or the request is not +// a Receive request, an error will be returned. +func (c *Client) DeleteReceiveRequest(partnerId *id.ID) error { + jww.DEBUG.Printf("Deleting receive request for partner ID: %s", partnerId) + return c.api.DeleteReceiveRequest(partnerId) +} + +// DeleteRequest will delete a request, agnostic of request type +// for the given partner ID. If no request exists for this +// partner ID an error will be returned. +func (c *Client) DeleteRequest(partnerId *id.ID) error { + jww.DEBUG.Printf("Deleting request for partner ID: %s", partnerId) + return c.api.DeleteRequest(partnerId) +} + // DeleteAllRequests clears all requests from Client's auth storage. func (c *Client) DeleteAllRequests() error { return c.api.DeleteAllRequests() diff --git a/storage/auth/store.go b/storage/auth/store.go index fb9aa2b04be8875bae32de4c74752db3dd80ddee..9c2159f3928c15593cc18066809521d53c336315 100644 --- a/storage/auth/store.go +++ b/storage/auth/store.go @@ -458,6 +458,96 @@ func (s *Store) DeleteAllRequests() error { return nil } +// DeleteSentRequest deletes a Sent request from Store given a partner ID. +// If the partner ID exists as a request, and the request is of type Sent, +// then the request will be deleted and the state stored. If either of +// those conditions are not met, then an error will be returned. +func (s *Store) DeleteSentRequest(partnerId *id.ID) error { + s.mux.Lock() + defer s.mux.Unlock() + + req, ok := s.requests[*partnerId] + if !ok { + return errors.Errorf("Sent request for %s does not exist", partnerId) + } + + if req.rt != Sent { + return errors.Errorf("Request for partner %s is not a sent request, "+ + "cannot delete using DeleteSentRequest()", partnerId) + } + + s.deleteSentRequest(req) + + delete(s.requests, *partnerId) + + if err := s.save(); err != nil { + jww.FATAL.Panicf("Failed to store updated request map after "+ + "deleting sent request for partner %s: %+v", partnerId, err) + } + + return nil +} + +// DeleteReceiveRequest deletes a Receive request from Store given a partner ID. +// If the partner ID exists as a request, and the request is of type Receive, +// then the request will be deleted and the state stored. If either of +// those conditions are not met, then an error will be returned. +func (s *Store) DeleteReceiveRequest(partnerId *id.ID) error { + s.mux.Lock() + defer s.mux.Unlock() + + req, ok := s.requests[*partnerId] + if !ok { + return errors.Errorf("Receive request for %s does not exist", partnerId) + } + + if req.rt != Receive { + return errors.Errorf("Request for partner %s is not a receive request, "+ + "cannot delete using DeleteReceiveRequest()", partnerId) + } + + s.deleteReceiveRequest(req) + + delete(s.requests, *partnerId) + + if err := s.save(); err != nil { + jww.FATAL.Panicf("Failed to store updated request map after "+ + "deleting receive request for partner %s: %+v", partnerId, err) + } + + return nil +} + +// DeleteRequest deletes a request from Store given a partner ID. +// If the partner ID exists as a request, then the request will be deleted +// and the state stored. If the partner does not exist, then an error will +// be returned. +func (s *Store) DeleteRequest(partnerId *id.ID) error { + s.mux.Lock() + defer s.mux.Unlock() + + req, ok := s.requests[*partnerId] + if !ok { + return errors.Errorf("Request for %s does not exist", partnerId) + } + + switch req.rt { + case Sent: + s.deleteSentRequest(req) + case Receive: + s.deleteReceiveRequest(req) + } + + delete(s.requests, *partnerId) + + if err := s.save(); err != nil { + jww.FATAL.Panicf("Failed to store updated request map after "+ + "deleting receive request for partner %s: %+v", partnerId, err) + } + + return nil +} + // DeleteSentRequests deletes all Sent requests from Store. func (s *Store) DeleteSentRequests() error { s.mux.Lock() diff --git a/storage/auth/store_test.go b/storage/auth/store_test.go index f1f10414836eb6c37596593322d112dbcfcc9394..7123126cf7583dd45c7ba5924e1b1042469cc845 100644 --- a/storage/auth/store_test.go +++ b/storage/auth/store_test.go @@ -905,6 +905,169 @@ func TestStore_GetAllReceived_MixSentReceived(t *testing.T) { } +// Unit test. +func TestStore_DeleteReceiveRequest(t *testing.T) { + s, _, _ := makeTestStore(t) + c := contact.Contact{ID: id.NewIdFromUInt(rand.Uint64(), id.User, t)} + rng := csprng.NewSystemRNG() + _, sidhPubKey := genSidhAKeys(rng) + if err := s.AddReceived(c, sidhPubKey); err != nil { + t.Fatalf("AddReceived() returned an error: %+v", err) + } + if _, _, err := s.GetReceivedRequest(c.ID); err != nil { + t.Fatalf("GetReceivedRequest() returned an error: %+v", err) + } + + err := s.DeleteReceiveRequest(c.ID) + if err != nil { + t.Fatalf("DeleteSentRequest error: %v", err) + } +} + +// Error case: call a DeleteReceiveRequest on a partner that is a sent request. +func TestStore_DeleteReceiveRequest_SentInMap(t *testing.T) { + s, _, _ := makeTestStore(t) + partnerID := id.NewIdFromUInt(rand.Uint64(), id.User, t) + rng := csprng.NewSystemRNG() + sidhPrivKey, sidhPubKey := genSidhAKeys(rng) + sr := &SentRequest{ + kv: s.kv, + partner: partnerID, + partnerHistoricalPubKey: s.grp.NewInt(1), + myPrivKey: s.grp.NewInt(2), + myPubKey: s.grp.NewInt(3), + mySidHPrivKeyA: sidhPrivKey, + mySidHPubKeyA: sidhPubKey, + fingerprint: format.Fingerprint{5}, + } + if err := s.AddSent(sr.partner, sr.partnerHistoricalPubKey, + sr.myPrivKey, sr.myPubKey, sr.mySidHPrivKeyA, + sr.mySidHPubKeyA, sr.fingerprint); err != nil { + t.Fatalf("AddSent() returned an error: %+v", err) + } + + err := s.DeleteReceiveRequest(partnerID) + if err == nil { + t.Fatalf("DeleteReceiveRequest should error when trying to " + + "delete a Sent request") + } +} + +// Error case: Call DeleteReceiveRequest on a request that does +// not exist. +func TestStore_DeleteReceiveRequest_NonexistantRequest(t *testing.T) { + s, _, _ := makeTestStore(t) + + err := s.DeleteReceiveRequest(id.NewIdFromUInt(rand.Uint64(), id.User, t)) + if err == nil { + t.Errorf("DeleteReceiveRequest should return an error " + + "when trying to delete a request that does not exist") + } +} + +// Unit test. +func TestStore_DeleteSentRequest(t *testing.T) { + s, _, _ := makeTestStore(t) + partnerID := id.NewIdFromUInt(rand.Uint64(), id.User, t) + rng := csprng.NewSystemRNG() + sidhPrivKey, sidhPubKey := genSidhAKeys(rng) + sr := &SentRequest{ + kv: s.kv, + partner: partnerID, + partnerHistoricalPubKey: s.grp.NewInt(1), + myPrivKey: s.grp.NewInt(2), + myPubKey: s.grp.NewInt(3), + mySidHPrivKeyA: sidhPrivKey, + mySidHPubKeyA: sidhPubKey, + fingerprint: format.Fingerprint{5}, + } + if err := s.AddSent(sr.partner, sr.partnerHistoricalPubKey, + sr.myPrivKey, sr.myPubKey, sr.mySidHPrivKeyA, + sr.mySidHPubKeyA, sr.fingerprint); err != nil { + t.Fatalf("AddSent() returned an error: %+v", err) + } + + err := s.DeleteSentRequest(partnerID) + if err != nil { + t.Errorf("DeleteSentRequest error: %v", err) + } +} + +// Error case: call a DeleteSentRequest on a partner that is a receive request. +func TestStore_DeleteSentRequest_ReceiveInMap(t *testing.T) { + s, _, _ := makeTestStore(t) + c := contact.Contact{ID: id.NewIdFromUInt(rand.Uint64(), id.User, t)} + rng := csprng.NewSystemRNG() + _, sidhPubKey := genSidhAKeys(rng) + if err := s.AddReceived(c, sidhPubKey); err != nil { + t.Fatalf("AddReceived() returned an error: %+v", err) + } + if _, _, err := s.GetReceivedRequest(c.ID); err != nil { + t.Fatalf("GetReceivedRequest() returned an error: %+v", err) + } + + err := s.DeleteSentRequest(c.ID) + if err == nil { + t.Errorf("DeleteSentRequest should return an error " + + "when trying to delete a receive request") + } +} + +// Error case: Call DeleteSentRequest on a request that does +// not exist. +func TestStore_DeleteSentRequest_NonexistantRequest(t *testing.T) { + s, _, _ := makeTestStore(t) + + err := s.DeleteSentRequest(id.NewIdFromUInt(rand.Uint64(), id.User, t)) + if err == nil { + t.Errorf("DeleteSentRequest should return an error " + + "when trying to delete a request that does not exist") + } +} + +// Unit test. +func TestStore_DeleteRequest(t *testing.T) { + s, _, _ := makeTestStore(t) + c := contact.Contact{ID: id.NewIdFromUInt(rand.Uint64(), id.User, t)} + rng := csprng.NewSystemRNG() + _, sidhPubKey := genSidhAKeys(rng) + if err := s.AddReceived(c, sidhPubKey); err != nil { + t.Fatalf("AddReceived() returned an error: %+v", err) + } + if _, _, err := s.GetReceivedRequest(c.ID); err != nil { + t.Fatalf("GetReceivedRequest() returned an error: %+v", err) + } + + err := s.DeleteSentRequest(c.ID) + if err == nil { + t.Errorf("DeleteSentRequest should return an error " + + "when trying to delete a receive request") + } + +} + +// Error case: Call DeleteRequest on a request that does +// not exist. +func TestStore_DeleteRequest_NonexistantRequest(t *testing.T) { + s, _, _ := makeTestStore(t) + c := contact.Contact{ID: id.NewIdFromUInt(rand.Uint64(), id.User, t)} + rng := csprng.NewSystemRNG() + _, sidhPubKey := genSidhAKeys(rng) + if err := s.AddReceived(c, sidhPubKey); err != nil { + t.Fatalf("AddReceived() returned an error: %+v", err) + } + if _, _, err := s.GetReceivedRequest(c.ID); err != nil { + t.Fatalf("GetReceivedRequest() returned an error: %+v", err) + } + + err := s.DeleteRequest(c.ID) + if err != nil { + t.Errorf("DeleteRequest should return an error " + + "when trying to delete a receive request") + } + +} + // Unit test. func TestStore_DeleteReceiveRequests(t *testing.T) { s, _, _ := makeTestStore(t)