From 8a0dd19e13061b682b41bb42f4bcd5820b1bf6c3 Mon Sep 17 00:00:00 2001 From: CarlHembrough Date: Thu, 6 Aug 2020 13:17:43 +0100 Subject: [PATCH 01/13] Correctly set the configured EnableDetachDataset value --- api/api.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/api.go b/api/api.go index 189e0c43..58d75685 100644 --- a/api/api.go +++ b/api/api.go @@ -190,7 +190,7 @@ func NewDatasetAPI(ctx context.Context, cfg config.Configuration, router *mux.Ro Host: api.host, Storer: api.dataStore.Backend, Auditor: api.auditor, - EnableDetachDataset: api.enablePrivateEndpoints, + EnableDetachDataset: api.enableDetachDataset, } dimensionAPI := &dimension.Store{ From d990829633c39cf9a14fcb8ccc5446d92798395c Mon Sep 17 00:00:00 2001 From: CarlHembrough Date: Thu, 6 Aug 2020 13:18:31 +0100 Subject: [PATCH 02/13] Do not fail if the current doc is nil It is nil when a new dataset is added - we do not want this case to fail. --- instance/editions.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instance/editions.go b/instance/editions.go index 8ab9a51e..0ec7d255 100644 --- a/instance/editions.go +++ b/instance/editions.go @@ -47,7 +47,7 @@ func (s *Store) confirmEdition(ctx context.Context, datasetID, edition, instance // TODO - feature flag. Will need removing eventually. if s.EnableDetachDataset { // Abort if a new/next version is already in flight - if editionDoc.Current == nil || editionDoc.Current.Links.LatestVersion.ID != editionDoc.Next.Links.LatestVersion.ID { + if editionDoc.Current.Links.LatestVersion.ID != editionDoc.Next.Links.LatestVersion.ID { log.Event(ctx, "confirm edition: there was an attempted skip of versioning sequence. Aborting edition update", log.INFO, logData) return nil, action, errs.ErrVersionAlreadyExists } From c371bfa40b314e34b22ceafbc0dd4a94d4ca8010 Mon Sep 17 00:00:00 2001 From: CarlHembrough Date: Fri, 7 Aug 2020 11:17:44 +0100 Subject: [PATCH 03/13] Prevent nil pointer panic when validating version number Check the edition's current and next doc are not nil before validating the version. --- instance/editions.go | 2 +- instance/editions_internal_test.go | 74 ++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/instance/editions.go b/instance/editions.go index 0ec7d255..039ddd61 100644 --- a/instance/editions.go +++ b/instance/editions.go @@ -47,7 +47,7 @@ func (s *Store) confirmEdition(ctx context.Context, datasetID, edition, instance // TODO - feature flag. Will need removing eventually. if s.EnableDetachDataset { // Abort if a new/next version is already in flight - if editionDoc.Current.Links.LatestVersion.ID != editionDoc.Next.Links.LatestVersion.ID { + if editionDoc.Current != nil && editionDoc.Next != nil && editionDoc.Current.Links.LatestVersion.ID != editionDoc.Next.Links.LatestVersion.ID { log.Event(ctx, "confirm edition: there was an attempted skip of versioning sequence. Aborting edition update", log.INFO, logData) return nil, action, errs.ErrVersionAlreadyExists } diff --git a/instance/editions_internal_test.go b/instance/editions_internal_test.go index 168bae44..574318e2 100644 --- a/instance/editions_internal_test.go +++ b/instance/editions_internal_test.go @@ -264,6 +264,80 @@ func Test_ConfirmEditionReturnsError(t *testing.T) { }) }) + Convey("given an edition exists with nil current doc", t, func() { + mockedDataStore := &storetest.StorerMock{ + GetEditionFunc: func(dataset, edition, state string) (*models.EditionUpdate, error) { + return &models.EditionUpdate{ + ID: "test", + Next: &models.Edition{ + Links: &models.EditionUpdateLinks{ + LatestVersion: &models.LinkObject{ + ID: ""}, + }, + }, + }, nil + }, + } + + host := "example.com" + s := Store{ + Storer: mockedDataStore, + Host: host, + Auditor: auditortest.New(), + EnableDetachDataset: true, + } + + Convey("when confirmEdition is called", func() { + datasetID := "1234" + editionName := "failure" + instanceID := "new-instance-1234" + + _, err := s.confirmEdition(ctx, datasetID, editionName, instanceID) + + Convey("then updating links fails and an error is returned", func() { + So(err, ShouldNotBeNil) + So(err, ShouldResemble, models.ErrEditionLinksInvalid) + }) + }) + }) + + Convey("given an edition exists with nil next doc", t, func() { + mockedDataStore := &storetest.StorerMock{ + GetEditionFunc: func(dataset, edition, state string) (*models.EditionUpdate, error) { + return &models.EditionUpdate{ + ID: "test", + Current: &models.Edition{ + Links: &models.EditionUpdateLinks{ + LatestVersion: &models.LinkObject{ + ID: ""}, + }, + }, + }, nil + }, + } + + host := "example.com" + s := Store{ + Storer: mockedDataStore, + Host: host, + Auditor: auditortest.New(), + EnableDetachDataset: true, + } + + Convey("when confirmEdition is called", func() { + datasetID := "1234" + editionName := "failure" + instanceID := "new-instance-1234" + + _, err := s.confirmEdition(ctx, datasetID, editionName, instanceID) + + Convey("then updating links fails and an error is returned", func() { + So(err, ShouldNotBeNil) + So(err, ShouldResemble, models.ErrEditionLinksInvalid) + }) + }) + }) + Convey("given intermittent datastore failures", t, func() { mockedDataStore := &storetest.StorerMock{ GetEditionFunc: func(dataset, edition, state string) (*models.EditionUpdate, error) { From 542082a3f7f6a8c151086c242e62c68a7ddbcea7 Mon Sep 17 00:00:00 2001 From: David Subiros Date: Thu, 27 Aug 2020 16:00:55 +0200 Subject: [PATCH 04/13] removed audit producer and all its usages in the code. Migrated from go-ns to dp-net --- api/api.go | 39 +- api/dataset.go | 45 +- api/dataset_test.go | 1140 +--------------- api/dimensions.go | 32 +- api/dimensions_test.go | 421 +----- api/editions.go | 34 +- api/editions_test.go | 337 +---- api/metadata.go | 18 +- api/metadata_test.go | 332 +---- api/observation.go | 19 +- api/observation_test.go | 432 +----- api/publish_state_checker.go | 39 +- api/versions.go | 117 +- api/versions_test.go | 1316 +------------------ api/webendpoints_test.go | 23 +- config/config.go | 2 - config/config_test.go | 2 - dimension/dimension.go | 57 +- dimension/dimension_test.go | 813 +----------- dimension/helpers.go | 21 +- go.mod | 20 +- go.sum | 44 +- initialise/initialise.go | 31 +- instance/dimensions.go | 16 +- instance/dimensions_external_test.go | 184 +-- instance/editions.go | 17 +- instance/editions_internal_test.go | 32 +- instance/event.go | 11 - instance/import.go | 26 +- instance/import_external_test.go | 609 +-------- instance/instance.go | 72 +- instance/instance_editions_external_test.go | 307 +---- instance/instance_external_test.go | 691 +--------- main.go | 50 +- 34 files changed, 390 insertions(+), 6959 deletions(-) diff --git a/api/api.go b/api/api.go index 58d75685..b06cd851 100644 --- a/api/api.go +++ b/api/api.go @@ -15,17 +15,15 @@ import ( "github.com/ONSdigital/dp-dataset-api/store" "github.com/ONSdigital/dp-dataset-api/url" "github.com/ONSdigital/dp-healthcheck/healthcheck" - "github.com/ONSdigital/go-ns/audit" - "github.com/ONSdigital/go-ns/common" - "github.com/ONSdigital/go-ns/handlers/collectionID" - "github.com/ONSdigital/go-ns/identity" - "github.com/ONSdigital/go-ns/server" + dphandlers "github.com/ONSdigital/dp-net/handlers" + dphttp "github.com/ONSdigital/dp-net/http" + dprequest "github.com/ONSdigital/dp-net/request" "github.com/ONSdigital/log.go/log" "github.com/gorilla/mux" "github.com/justinas/alice" ) -var httpServer *server.Server +var httpServer *dphttp.Server const ( downloadServiceToken = "X-Download-Service-Token" @@ -73,9 +71,6 @@ type DownloadsGenerator interface { Generate(ctx context.Context, datasetID, instanceID, edition, version string) error } -// Auditor is an alias for the auditor service -type Auditor audit.AuditorService - // AuthHandler provides authorisation checks on requests type AuthHandler interface { Require(required auth.Permissions, handler http.HandlerFunc) http.HandlerFunc @@ -93,7 +88,6 @@ type DatasetAPI struct { urlBuilder *url.Builder downloadGenerator DownloadsGenerator serviceAuthToken string - auditor Auditor enablePrivateEndpoints bool enableDetachDataset bool enableObservationEndpoint bool @@ -104,9 +98,9 @@ type DatasetAPI struct { } // CreateAndInitialiseDatasetAPI create a new DatasetAPI instance based on the configuration provided, apply middleware and starts the HTTP server. -func CreateAndInitialiseDatasetAPI(ctx context.Context, cfg config.Configuration, hc *healthcheck.HealthCheck, dataStore store.DataStore, urlBuilder *url.Builder, errorChan chan error, downloadGenerator DownloadsGenerator, auditor Auditor, datasetPermissions AuthHandler, permissions AuthHandler) { +func CreateAndInitialiseDatasetAPI(ctx context.Context, cfg config.Configuration, hc *healthcheck.HealthCheck, dataStore store.DataStore, urlBuilder *url.Builder, errorChan chan error, downloadGenerator DownloadsGenerator, datasetPermissions AuthHandler, permissions AuthHandler) { router := mux.NewRouter() - api := NewDatasetAPI(ctx, cfg, router, dataStore, urlBuilder, downloadGenerator, auditor, datasetPermissions, permissions) + api := NewDatasetAPI(ctx, cfg, router, dataStore, urlBuilder, downloadGenerator, datasetPermissions, permissions) healthcheckHandler := newMiddleware(hc.Handler, "/health") middleware := alice.New(healthcheckHandler) @@ -117,12 +111,12 @@ func CreateAndInitialiseDatasetAPI(ctx context.Context, cfg config.Configuration // Only add the identity middleware when running in publishing. if cfg.EnablePrivateEndpoints { - middleware = middleware.Append(identity.Handler(cfg.ZebedeeURL)) + middleware = middleware.Append(dphandlers.Identity(cfg.ZebedeeURL)) } - middleware = middleware.Append(collectionID.CheckHeader) + middleware = middleware.Append(dphandlers.CheckHeader(dphandlers.CollectionID)) - httpServer = server.New(cfg.BindAddr, middleware.Then(api.Router)) + httpServer = dphttp.NewServer(cfg.BindAddr, middleware.Then(api.Router)) // Disable this here to allow main to manage graceful shutdown of the entire app. httpServer.HandleOSSignals = false @@ -152,7 +146,7 @@ func newMiddleware(healthcheckHandler func(http.ResponseWriter, *http.Request), } // NewDatasetAPI create a new Dataset API instance and register the API routes based on the application configuration. -func NewDatasetAPI(ctx context.Context, cfg config.Configuration, router *mux.Router, dataStore store.DataStore, urlBuilder *url.Builder, downloadGenerator DownloadsGenerator, auditor Auditor, datasetPermissions AuthHandler, permissions AuthHandler) *DatasetAPI { +func NewDatasetAPI(ctx context.Context, cfg config.Configuration, router *mux.Router, dataStore store.DataStore, urlBuilder *url.Builder, downloadGenerator DownloadsGenerator, datasetPermissions AuthHandler, permissions AuthHandler) *DatasetAPI { api := &DatasetAPI{ dataStore: dataStore, host: cfg.DatasetAPIURL, @@ -163,7 +157,6 @@ func NewDatasetAPI(ctx context.Context, cfg config.Configuration, router *mux.Ro Router: router, urlBuilder: urlBuilder, downloadGenerator: downloadGenerator, - auditor: auditor, enablePrivateEndpoints: cfg.EnablePrivateEndpoints, enableDetachDataset: cfg.EnableDetachDataset, enableObservationEndpoint: cfg.EnableObservationEndpoint, @@ -177,25 +170,21 @@ func NewDatasetAPI(ctx context.Context, cfg config.Configuration, router *mux.Ro log.Event(ctx, "enabling private endpoints for dataset api", log.INFO) api.versionPublishedChecker = &PublishCheck{ - Auditor: auditor, Datastore: api.dataStore.Backend, } api.instancePublishedChecker = &instance.PublishCheck{ - Auditor: api.auditor, Datastore: api.dataStore.Backend, } instanceAPI := &instance.Store{ Host: api.host, Storer: api.dataStore.Backend, - Auditor: api.auditor, EnableDetachDataset: api.enableDetachDataset, } dimensionAPI := &dimension.Store{ - Auditor: api.auditor, - Storer: api.dataStore.Backend, + Storer: api.dataStore.Backend, } api.enablePrivateDatasetEndpoints(ctx) @@ -431,7 +420,7 @@ func (api *DatasetAPI) enablePrivateDimensionsEndpoints(dimensionAPI *dimension. // perform the requested action action. action is the audit event name, handler is the http.HandlerFunc to wrap in an // authentication check. The wrapped handler is only called is the caller is authenticated func (api *DatasetAPI) isAuthenticated(action string, handler http.HandlerFunc) http.HandlerFunc { - return identity.Check(api.auditor, action, handler) + return dphandlers.CheckIdentity(handler) } // isAuthorised wraps a http.HandlerFunc another http.HandlerFunc that checks the caller is authorised to perform the @@ -487,13 +476,13 @@ func (api *DatasetAPI) authenticate(r *http.Request, logData log.Data) bool { if api.EnablePrePublishView { var hasCallerIdentity, hasUserIdentity bool - callerIdentity := common.Caller(r.Context()) + callerIdentity := dprequest.Caller(r.Context()) if callerIdentity != "" { logData["caller_identity"] = callerIdentity hasCallerIdentity = true } - userIdentity := common.User(r.Context()) + userIdentity := dprequest.User(r.Context()) if userIdentity != "" { logData["user_identity"] = userIdentity hasUserIdentity = true diff --git a/api/dataset.go b/api/dataset.go index 8f4bd49e..f10f4e89 100644 --- a/api/dataset.go +++ b/api/dataset.go @@ -9,9 +9,7 @@ import ( errs "github.com/ONSdigital/dp-dataset-api/apierrors" "github.com/ONSdigital/dp-dataset-api/models" - "github.com/ONSdigital/go-ns/audit" - "github.com/ONSdigital/go-ns/common" - "github.com/ONSdigital/go-ns/request" + dphttp "github.com/ONSdigital/dp-net/http" "github.com/ONSdigital/log.go/log" "github.com/gorilla/mux" ) @@ -42,10 +40,6 @@ var ( func (api *DatasetAPI) getDatasets(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - if err := api.auditor.Record(ctx, getDatasetsAction, audit.Attempted, nil); err != nil { - http.Error(w, errs.ErrInternalServer.Error(), http.StatusInternalServerError) - return - } b, err := func() ([]byte, error) { datasets, err := api.dataStore.Backend.GetDatasets(ctx) @@ -78,18 +72,10 @@ func (api *DatasetAPI) getDatasets(w http.ResponseWriter, r *http.Request) { }() if err != nil { - if auditErr := api.auditor.Record(ctx, getDatasetsAction, audit.Unsuccessful, nil); auditErr != nil { - err = auditErr - } handleDatasetAPIErr(ctx, err, w, nil) return } - if auditErr := api.auditor.Record(ctx, getDatasetsAction, audit.Successful, nil); auditErr != nil { - handleDatasetAPIErr(ctx, auditErr, w, nil) - return - } - setJSONContentType(w) if _, err = w.Write(b); err != nil { log.Event(ctx, "api endpoint getDatasets error writing response body", log.ERROR, log.Error(err)) @@ -104,12 +90,6 @@ func (api *DatasetAPI) getDataset(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) datasetID := vars["dataset_id"] logData := log.Data{"dataset_id": datasetID} - auditParams := common.Params{"dataset_id": datasetID} - - if auditErr := api.auditor.Record(ctx, getDatasetAction, audit.Attempted, auditParams); auditErr != nil { - handleDatasetAPIErr(ctx, errs.ErrInternalServer, w, logData) - return - } b, err := func() ([]byte, error) { dataset, err := api.dataStore.Backend.GetDataset(datasetID) @@ -154,18 +134,10 @@ func (api *DatasetAPI) getDataset(w http.ResponseWriter, r *http.Request) { }() if err != nil { - if auditErr := api.auditor.Record(ctx, getDatasetAction, audit.Unsuccessful, auditParams); auditErr != nil { - err = auditErr - } handleDatasetAPIErr(ctx, err, w, logData) return } - if auditErr := api.auditor.Record(ctx, getDatasetAction, audit.Successful, auditParams); auditErr != nil { - handleDatasetAPIErr(ctx, auditErr, w, logData) - return - } - setJSONContentType(w) if _, err = w.Write(b); err != nil { log.Event(ctx, "getDataset endpoint: error writing bytes to response", log.ERROR, log.Error(err), logData) @@ -176,14 +148,13 @@ func (api *DatasetAPI) getDataset(w http.ResponseWriter, r *http.Request) { func (api *DatasetAPI) addDataset(w http.ResponseWriter, r *http.Request) { - defer request.DrainBody(r) + defer dphttp.DrainBody(r) ctx := r.Context() vars := mux.Vars(r) datasetID := vars["dataset_id"] logData := log.Data{"dataset_id": datasetID} - auditParams := common.Params{"dataset_id": datasetID} // TODO Could just do an insert, if dataset already existed we would get a duplicate key error instead of reading then writing doc b, err := func() ([]byte, error) { @@ -244,13 +215,10 @@ func (api *DatasetAPI) addDataset(w http.ResponseWriter, r *http.Request) { }() if err != nil { - api.auditor.Record(ctx, addDatasetAction, audit.Unsuccessful, auditParams) handleDatasetAPIErr(ctx, err, w, logData) return } - api.auditor.Record(ctx, addDatasetAction, audit.Successful, auditParams) - setJSONContentType(w) w.WriteHeader(http.StatusCreated) if _, err = w.Write(b); err != nil { @@ -262,13 +230,12 @@ func (api *DatasetAPI) addDataset(w http.ResponseWriter, r *http.Request) { func (api *DatasetAPI) putDataset(w http.ResponseWriter, r *http.Request) { - defer request.DrainBody(r) + defer dphttp.DrainBody(r) ctx := r.Context() vars := mux.Vars(r) datasetID := vars["dataset_id"] data := log.Data{"dataset_id": datasetID} - auditParams := common.Params{"dataset_id": datasetID} err := func() error { @@ -299,13 +266,10 @@ func (api *DatasetAPI) putDataset(w http.ResponseWriter, r *http.Request) { }() if err != nil { - api.auditor.Record(ctx, updateDatasetAction, audit.Unsuccessful, auditParams) handleDatasetAPIErr(ctx, err, w, data) return } - api.auditor.Record(ctx, updateDatasetAction, audit.Successful, auditParams) - setJSONContentType(w) w.WriteHeader(http.StatusOK) log.Event(ctx, "putDataset endpoint: request successful", log.INFO, data) @@ -347,7 +311,6 @@ func (api *DatasetAPI) deleteDataset(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) datasetID := vars["dataset_id"] logData := log.Data{"dataset_id": datasetID, "func": "deleteDataset"} - auditParams := common.Params{"dataset_id": datasetID, "func": "deleteDataset"} // attempt to delete the dataset. err := func() error { @@ -392,12 +355,10 @@ func (api *DatasetAPI) deleteDataset(w http.ResponseWriter, r *http.Request) { }() if err != nil { - api.auditor.Record(ctx, deleteDatasetAction, audit.Unsuccessful, auditParams) handleDatasetAPIErr(ctx, err, w, logData) return } - api.auditor.Record(ctx, deleteDatasetAction, audit.Successful, auditParams) w.WriteHeader(http.StatusNoContent) log.Event(ctx, "delete dataset", log.INFO, logData) } diff --git a/api/dataset_test.go b/api/dataset_test.go index 21288aa6..bae35a2e 100644 --- a/api/dataset_test.go +++ b/api/dataset_test.go @@ -3,7 +3,6 @@ package api import ( "bytes" "context" - "encoding/json" "errors" "io" "net/http" @@ -18,9 +17,7 @@ import ( "github.com/ONSdigital/dp-dataset-api/store" storetest "github.com/ONSdigital/dp-dataset-api/store/datastoretest" "github.com/ONSdigital/dp-dataset-api/url" - "github.com/ONSdigital/go-ns/audit" - "github.com/ONSdigital/go-ns/audit/auditortest" - "github.com/ONSdigital/go-ns/common" + dprequest "github.com/ONSdigital/dp-net/request" "github.com/gorilla/mux" "github.com/ONSdigital/dp-dataset-api/config" @@ -38,9 +35,8 @@ const ( var ( datasetPayload = `{"contacts":[{"email":"testing@hotmail.com","name":"John Cox","telephone":"01623 456789"}],"description":"census","links":{"access_rights":{"href":"http://ons.gov.uk/accessrights"}},"title":"CensusEthnicity","theme":"population","periodicity":"yearly","state":"completed","next_release":"2016-04-04","publisher":{"name":"The office of national statistics","type":"government department","url":"https://www.ons.gov.uk/"}}` - urlBuilder = url.NewBuilder("localhost:20000") - genericAuditParams = common.Params{"caller_identity": callerIdentity, "dataset_id": "123-456"} - mu sync.Mutex + urlBuilder = url.NewBuilder("localhost:20000") + mu sync.Mutex ) func getAuthorisationHandlerMock() *mocks.AuthHandlerMock { @@ -50,7 +46,7 @@ func getAuthorisationHandlerMock() *mocks.AuthHandlerMock { } // GetAPIWithMocks also used in other tests, so exported -func GetAPIWithMocks(mockedDataStore store.Storer, mockedGeneratedDownloads DownloadsGenerator, auditMock Auditor, datasetPermissions AuthHandler, permissions AuthHandler) *DatasetAPI { +func GetAPIWithMocks(mockedDataStore store.Storer, mockedGeneratedDownloads DownloadsGenerator, datasetPermissions AuthHandler, permissions AuthHandler) *DatasetAPI { mu.Lock() defer mu.Unlock() cfg, err := config.Get() @@ -59,13 +55,13 @@ func GetAPIWithMocks(mockedDataStore store.Storer, mockedGeneratedDownloads Down cfg.DatasetAPIURL = host cfg.EnablePrivateEndpoints = true - return NewDatasetAPI(testContext, *cfg, mux.NewRouter(), store.DataStore{Backend: mockedDataStore}, urlBuilder, mockedGeneratedDownloads, auditMock, datasetPermissions, permissions) + return NewDatasetAPI(testContext, *cfg, mux.NewRouter(), store.DataStore{Backend: mockedDataStore}, urlBuilder, mockedGeneratedDownloads, datasetPermissions, permissions) } func createRequestWithAuth(method, URL string, body io.Reader) (*http.Request, error) { r, err := http.NewRequest(method, URL, body) ctx := r.Context() - ctx = common.SetCaller(ctx, "someone@ons.gov.uk") + ctx = dprequest.SetCaller(ctx, "someone@ons.gov.uk") r = r.WithContext(ctx) return r, err } @@ -83,89 +79,14 @@ func TestGetDatasetsReturnsOK(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditMock := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) So(len(mockedDataStore.GetDatasetsCalls()), ShouldEqual, 1) So(datasetPermissions.Required.Calls, ShouldEqual, 0) So(permissions.Required.Calls, ShouldEqual, 1) - - auditMock.AssertRecordCalls( - auditortest.Expected{Action: getDatasetsAction, Result: audit.Attempted, Params: nil}, - auditortest.Expected{Action: getDatasetsAction, Result: audit.Successful, Params: nil}, - ) - }) -} - -func TestGetDatasetsReturnsErrorIfAuditAttemptFails(t *testing.T) { - t.Parallel() - Convey("When auditing get datasets attempt returns an error an internal server error is returned", t, func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets", nil) - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - GetDatasetsFunc: func(context.Context) ([]models.DatasetUpdate, error) { - return nil, errs.ErrInternalServer - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - auditMock := auditortest.New() - auditMock.RecordFunc = func(ctx context.Context, action string, result string, params common.Params) error { - return errors.New("boom!") - } - - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 1) - So(len(mockedDataStore.GetDatasetsCalls()), ShouldEqual, 0) - - auditMock.AssertRecordCalls( - auditortest.Expected{ - Action: getDatasetsAction, - Result: audit.Attempted, - Params: nil, - }, - ) - }) - - Convey("When auditing get datasets errors an internal server error is returned", t, func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets", nil) - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - GetDatasetsFunc: func(context.Context) ([]models.DatasetUpdate, error) { - return nil, errs.ErrInternalServer - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - auditMock := auditortest.New() - auditMock.RecordFunc = func(ctx context.Context, action string, result string, params common.Params) error { - if action == getDatasetsAction && result == audit.Unsuccessful { - return errors.New("boom!") - } - return nil - } - - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 1) - So(len(mockedDataStore.GetDatasetsCalls()), ShouldEqual, 1) - - auditMock.AssertRecordCalls( - auditortest.Expected{Action: getDatasetsAction, Result: audit.Attempted, Params: nil}, - auditortest.Expected{Action: getDatasetsAction, Result: audit.Unsuccessful, Params: nil}, - ) }) } @@ -182,54 +103,17 @@ func TestGetDatasetsReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditMock := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) assertInternalServerErr(w) So(len(mockedDataStore.GetDatasetsCalls()), ShouldEqual, 1) So(datasetPermissions.Required.Calls, ShouldEqual, 0) So(permissions.Required.Calls, ShouldEqual, 1) - - auditMock.AssertRecordCalls( - auditortest.Expected{Action: getDatasetsAction, Result: audit.Attempted, Params: nil}, - auditortest.Expected{Action: getDatasetsAction, Result: audit.Unsuccessful, Params: nil}, - ) - }) -} - -func TestGetDatasetsAuditSuccessfulError(t *testing.T) { - t.Parallel() - Convey("when a successful request to get dataset fails to audit action successful then a 500 response is returned", t, func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets", nil) - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - GetDatasetsFunc: func(context.Context) ([]models.DatasetUpdate, error) { - return []models.DatasetUpdate{}, nil - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - auditMock := auditortest.NewErroring(getDatasetsAction, audit.Successful) - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - assertInternalServerErr(w) - So(len(mockedDataStore.GetDatasetsCalls()), ShouldEqual, 1) - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 1) - - auditMock.AssertRecordCalls( - auditortest.Expected{Action: getDatasetsAction, Result: audit.Attempted, Params: nil}, - auditortest.Expected{Action: getDatasetsAction, Result: audit.Successful, Params: nil}, - ) }) } func TestGetDatasetReturnsOK(t *testing.T) { - auditParams := common.Params{"dataset_id": "123-456"} - t.Parallel() Convey("When dataset document has a current sub document return status 200", t, func() { r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123-456", nil) @@ -242,19 +126,13 @@ func TestGetDatasetReturnsOK(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditMock := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) So(datasetPermissions.Required.Calls, ShouldEqual, 1) So(permissions.Required.Calls, ShouldEqual, 0) So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) - - auditMock.AssertRecordCalls( - auditortest.Expected{Action: getDatasetAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getDatasetAction, Result: audit.Successful, Params: auditParams}, - ) }) Convey("When dataset document has only a next sub document and request is authorised return status 200", t, func() { @@ -270,25 +148,17 @@ func TestGetDatasetReturnsOK(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditMock := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) So(datasetPermissions.Required.Calls, ShouldEqual, 1) So(permissions.Required.Calls, ShouldEqual, 0) - - auditMock.AssertRecordCalls( - auditortest.Expected{Action: getDatasetAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getDatasetAction, Result: audit.Successful, Params: auditParams}, - ) }) } func TestGetDatasetReturnsError(t *testing.T) { - auditParams := common.Params{"dataset_id": "123-456"} - t.Parallel() Convey("When the api cannot connect to datastore return an internal server error", t, func() { r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123-456", nil) @@ -301,19 +171,13 @@ func TestGetDatasetReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditMock := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) assertInternalServerErr(w) So(datasetPermissions.Required.Calls, ShouldEqual, 1) So(permissions.Required.Calls, ShouldEqual, 0) So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) - - auditMock.AssertRecordCalls( - auditortest.Expected{Action: getDatasetAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getDatasetAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When dataset document has only a next sub document return status 404", t, func() { @@ -327,19 +191,13 @@ func TestGetDatasetReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditMock := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) So(datasetPermissions.Required.Calls, ShouldEqual, 1) So(permissions.Required.Calls, ShouldEqual, 0) So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) - - auditMock.AssertRecordCalls( - auditortest.Expected{Action: getDatasetAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getDatasetAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When there is no dataset document return status 404", t, func() { @@ -355,134 +213,13 @@ func TestGetDatasetReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditMock := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) So(datasetPermissions.Required.Calls, ShouldEqual, 1) So(permissions.Required.Calls, ShouldEqual, 0) So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) - - auditMock.AssertRecordCalls( - auditortest.Expected{Action: getDatasetAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getDatasetAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) -} - -func TestGetDatasetAuditingErrors(t *testing.T) { - auditParams := common.Params{"dataset_id": "123-456"} - - Convey("given auditing attempted action returns an error", t, func() { - auditMock := auditortest.New() - auditMock.RecordFunc = func(ctx context.Context, action string, result string, params common.Params) error { - return errors.New("auditing error") - } - - Convey("when get dataset is called", func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123-456", nil) - w := httptest.NewRecorder() - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - mockDatastore := &storetest.StorerMock{} - api := GetAPIWithMocks(mockDatastore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) - - api.Router.ServeHTTP(w, r) - - Convey("then a 500 status is returned", func() { - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockDatastore.GetDatasetCalls()), ShouldEqual, 0) - - auditMock.AssertRecordCalls( - auditortest.Expected{ - Action: getDatasetAction, - Result: audit.Attempted, - Params: auditParams, - }, - ) - }) - }) - }) - - Convey("given audit action successful returns an error", t, func() { - auditMock := auditortest.New() - auditMock.RecordFunc = func(ctx context.Context, action string, result string, params common.Params) error { - if action == getDatasetAction && result == audit.Successful { - return errors.New("auditing error") - } - return nil - } - - Convey("when get dataset is called", func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123-456", nil) - w := httptest.NewRecorder() - - mockDatastore := &storetest.StorerMock{ - GetDatasetFunc: func(id string) (*models.DatasetUpdate, error) { - return &models.DatasetUpdate{ID: "123", Current: &models.Dataset{ID: "123"}}, nil - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - - api := GetAPIWithMocks(mockDatastore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - Convey("then a 500 status is returned", func() { - So(len(mockDatastore.GetDatasetCalls()), ShouldEqual, 1) - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - - auditMock.AssertRecordCalls( - auditortest.Expected{Action: getDatasetAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getDatasetAction, Result: audit.Successful, Params: auditParams}, - ) - }) - }) - }) - - Convey("given auditing action unsuccessful returns an error", t, func() { - auditMock := auditortest.New() - auditMock.RecordFunc = func(ctx context.Context, action string, result string, params common.Params) error { - if action == getDatasetAction && result == audit.Unsuccessful { - return errors.New("auditing error") - } - return nil - } - - Convey("when get dataset is called", func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123-456", nil) - w := httptest.NewRecorder() - - mockDatastore := &storetest.StorerMock{ - GetDatasetFunc: func(id string) (*models.DatasetUpdate, error) { - return nil, errors.New("get dataset error") - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockDatastore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - Convey("then a 500 status is returned", func() { - assertInternalServerErr(w) - So(len(mockDatastore.GetDatasetCalls()), ShouldEqual, 1) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - - auditMock.AssertRecordCalls( - auditortest.Expected{Action: getDatasetAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getDatasetAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) - }) }) } @@ -507,8 +244,7 @@ func TestPostDatasetsReturnsCreated(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() mockedDataStore.UpsertDataset("123", &models.DatasetUpdate{Next: &models.Dataset{}}) - auditMock := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusCreated) @@ -517,11 +253,6 @@ func TestPostDatasetsReturnsCreated(t *testing.T) { So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) So(len(mockedDataStore.UpsertDatasetCalls()), ShouldEqual, 2) - auditMock.AssertRecordCalls( - auditortest.Expected{Action: addDatasetAction, Result: audit.Attempted, Params: common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123"}}, - auditortest.Expected{Action: addDatasetAction, Result: audit.Successful, Params: common.Params{"dataset_id": "123"}}, - ) - Convey("then the request body has been drained", func() { _, err = r.Body.Read(make([]byte, 1)) So(err, ShouldEqual, io.EOF) @@ -549,8 +280,7 @@ func TestPostDatasetReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditMock := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusBadRequest) @@ -560,11 +290,6 @@ func TestPostDatasetReturnsError(t *testing.T) { So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) So(len(mockedDataStore.UpsertDatasetCalls()), ShouldEqual, 0) - auditMock.AssertRecordCalls( - auditortest.Expected{Action: addDatasetAction, Result: audit.Attempted, Params: common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123"}}, - auditortest.Expected{Action: addDatasetAction, Result: audit.Unsuccessful, Params: common.Params{"dataset_id": "123"}}, - ) - Convey("then the request body has been drained", func() { _, err = r.Body.Read(make([]byte, 1)) So(err, ShouldEqual, io.EOF) @@ -589,8 +314,7 @@ func TestPostDatasetReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditMock := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) assertInternalServerErr(w) @@ -599,11 +323,6 @@ func TestPostDatasetReturnsError(t *testing.T) { So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) So(len(mockedDataStore.UpsertDatasetCalls()), ShouldEqual, 0) - auditMock.AssertRecordCalls( - auditortest.Expected{Action: addDatasetAction, Result: audit.Attempted, Params: common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123"}}, - auditortest.Expected{Action: addDatasetAction, Result: audit.Unsuccessful, Params: common.Params{"dataset_id": "123"}}, - ) - Convey("then the request body has been drained", func() { _, err = r.Body.Read(make([]byte, 1)) So(err, ShouldEqual, io.EOF) @@ -625,8 +344,7 @@ func TestPostDatasetReturnsError(t *testing.T) { } datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditMock := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusUnauthorized) @@ -636,12 +354,6 @@ func TestPostDatasetReturnsError(t *testing.T) { So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpsertDatasetCalls()), ShouldEqual, 0) - auditParams := common.Params{"dataset_id": "123"} - auditMock.AssertRecordCalls( - auditortest.Expected{Action: addDatasetAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: addDatasetAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - Convey("then the request body has been drained", func() { _, err := r.Body.Read(make([]byte, 1)) So(err, ShouldEqual, io.EOF) @@ -670,8 +382,7 @@ func TestPostDatasetReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditMock := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusForbidden) @@ -681,11 +392,6 @@ func TestPostDatasetReturnsError(t *testing.T) { So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) So(len(mockedDataStore.UpsertDatasetCalls()), ShouldEqual, 0) - auditMock.AssertRecordCalls( - auditortest.Expected{Action: addDatasetAction, Result: audit.Attempted, Params: common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123"}}, - auditortest.Expected{Action: addDatasetAction, Result: audit.Unsuccessful, Params: common.Params{"dataset_id": "123"}}, - ) - Convey("then the request body has been drained", func() { _, err = r.Body.Read(make([]byte, 1)) So(err, ShouldEqual, io.EOF) @@ -693,200 +399,6 @@ func TestPostDatasetReturnsError(t *testing.T) { }) } -func TestPostDatasetAuditErrors(t *testing.T) { - Convey("given audit action attempted returns an error", t, func() { - auditMock := auditortest.NewErroring(addDatasetAction, audit.Attempted) - - Convey("when add dataset is called", func() { - r, err := createRequestWithAuth("POST", "http://localhost:22000/datasets/123", bytes.NewBufferString("{")) - So(err, ShouldBeNil) - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{} - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - Convey("then a 500 status is returned", func() { - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 0) - So(len(mockedDataStore.UpsertDatasetCalls()), ShouldEqual, 0) - - auditMock.AssertRecordCalls( - auditortest.Expected{ - Action: addDatasetAction, - Result: audit.Attempted, - Params: common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123"}, - }, - ) - }) - - Convey("then the request body has been drained", func() { - _, err = r.Body.Read(make([]byte, 1)) - So(err, ShouldEqual, io.EOF) - }) - }) - }) - - Convey("given audit action unsuccessful returns an error", t, func() { - auditMock := auditortest.NewErroring(addDatasetAction, audit.Unsuccessful) - - Convey("when datastore getdataset returns an error", func() { - r, err := createRequestWithAuth("POST", "http://localhost:22000/datasets/123", bytes.NewBufferString("{")) - So(err, ShouldBeNil) - w := httptest.NewRecorder() - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - mockedDataStore := &storetest.StorerMock{ - GetDatasetFunc: func(string) (*models.DatasetUpdate, error) { - return nil, errors.New("get dataset error") - }, - } - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - Convey("then a 500 status is returned", func() { - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) - So(len(mockedDataStore.UpsertDatasetCalls()), ShouldEqual, 0) - - auditMock.AssertRecordCalls( - auditortest.Expected{Action: addDatasetAction, Result: audit.Attempted, Params: common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123"}}, - auditortest.Expected{Action: addDatasetAction, Result: audit.Unsuccessful, Params: common.Params{"dataset_id": "123"}}, - ) - }) - - Convey("then the request body has been drained", func() { - _, err = r.Body.Read(make([]byte, 1)) - So(err, ShouldEqual, io.EOF) - }) - }) - - Convey("when datastore getdataset returns an existing dataset", func() { - r, err := createRequestWithAuth("POST", "http://localhost:22000/datasets/123", bytes.NewBufferString("{")) - So(err, ShouldBeNil) - w := httptest.NewRecorder() - - mockedDataStore := &storetest.StorerMock{ - GetDatasetFunc: func(string) (*models.DatasetUpdate, error) { - return &models.DatasetUpdate{}, nil - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - Convey("then a 403 status is returned", func() { - So(w.Code, ShouldEqual, http.StatusForbidden) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(w.Body.String(), ShouldContainSubstring, errs.ErrAddDatasetAlreadyExists.Error()) - So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) - So(len(mockedDataStore.UpsertDatasetCalls()), ShouldEqual, 0) - - auditMock.AssertRecordCalls( - auditortest.Expected{Action: addDatasetAction, Result: audit.Attempted, Params: common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123"}}, - auditortest.Expected{Action: addDatasetAction, Result: audit.Unsuccessful, Params: common.Params{"dataset_id": "123"}}, - ) - }) - - Convey("then the request body has been drained", func() { - _, err = r.Body.Read(make([]byte, 1)) - So(err, ShouldEqual, io.EOF) - }) - }) - - Convey("when datastore upsertDataset returns error", func() { - r, err := createRequestWithAuth("POST", "http://localhost:22000/datasets/123", bytes.NewBufferString(datasetPayload)) - So(err, ShouldBeNil) - w := httptest.NewRecorder() - - mockedDataStore := &storetest.StorerMock{ - GetDatasetFunc: func(string) (*models.DatasetUpdate, error) { - return nil, errs.ErrDatasetNotFound - }, - UpsertDatasetFunc: func(ID string, datasetDoc *models.DatasetUpdate) error { - return errors.New("upsert datset error") - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - Convey("then a 500 status is returned", func() { - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) - So(len(mockedDataStore.UpsertDatasetCalls()), ShouldEqual, 1) - - auditMock.AssertRecordCalls( - auditortest.Expected{Action: addDatasetAction, Result: audit.Attempted, Params: common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123"}}, - auditortest.Expected{Action: addDatasetAction, Result: audit.Unsuccessful, Params: common.Params{"dataset_id": "123"}}, - ) - }) - - Convey("then the request body has been drained", func() { - _, err = r.Body.Read(make([]byte, 1)) - So(err, ShouldEqual, io.EOF) - }) - }) - }) - - Convey("given audit action successful returns an error", t, func() { - auditMock := auditortest.NewErroring(addDatasetAction, audit.Successful) - - Convey("when add dataset is successful", func() { - r, err := createRequestWithAuth("POST", "http://localhost:22000/datasets/123", bytes.NewBufferString(datasetPayload)) - So(err, ShouldBeNil) - w := httptest.NewRecorder() - - mockedDataStore := &storetest.StorerMock{ - GetDatasetFunc: func(string) (*models.DatasetUpdate, error) { - return nil, errs.ErrDatasetNotFound - }, - UpsertDatasetFunc: func(ID string, datasetDoc *models.DatasetUpdate) error { - return nil - }, - } - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - Convey("then a 201 status is returned", func() { - So(w.Code, ShouldEqual, http.StatusCreated) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) - So(len(mockedDataStore.UpsertDatasetCalls()), ShouldEqual, 1) - - auditMock.AssertRecordCalls( - auditortest.Expected{Action: addDatasetAction, Result: audit.Attempted, Params: common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123"}}, - auditortest.Expected{Action: addDatasetAction, Result: audit.Successful, Params: common.Params{"dataset_id": "123"}}, - ) - }) - - Convey("then the request body has been drained", func() { - _, err = r.Body.Read(make([]byte, 1)) - So(err, ShouldEqual, io.EOF) - }) - }) - }) -} - func TestPutDatasetReturnsSuccessfully(t *testing.T) { t.Parallel() Convey("A successful request to put dataset returns 200 OK response", t, func() { @@ -913,8 +425,7 @@ func TestPutDatasetReturnsSuccessfully(t *testing.T) { } mockedDataStore.UpdateDataset(testContext, "123", dataset, models.CreatedState) - auditMock := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) @@ -923,11 +434,6 @@ func TestPutDatasetReturnsSuccessfully(t *testing.T) { So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) So(len(mockedDataStore.UpdateDatasetCalls()), ShouldEqual, 2) - auditMock.AssertRecordCalls( - auditortest.Expected{Action: updateDatasetAction, Result: audit.Attempted, Params: common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123"}}, - auditortest.Expected{Action: updateDatasetAction, Result: audit.Successful, Params: common.Params{"dataset_id": "123"}}, - ) - Convey("then the request body has been drained", func() { _, err = r.Body.Read(make([]byte, 1)) So(err, ShouldEqual, io.EOF) @@ -958,8 +464,7 @@ func TestPutDatasetReturnsError(t *testing.T) { }, } - auditMock := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusBadRequest) @@ -969,11 +474,6 @@ func TestPutDatasetReturnsError(t *testing.T) { So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateVersionCalls()), ShouldEqual, 0) - auditMock.AssertRecordCalls( - auditortest.Expected{Action: updateDatasetAction, Result: audit.Attempted, Params: common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123"}}, - auditortest.Expected{Action: updateDatasetAction, Result: audit.Unsuccessful, Params: common.Params{"dataset_id": "123"}}, - ) - Convey("then the request body has been drained", func() { _, err = r.Body.Read(make([]byte, 1)) So(err, ShouldEqual, io.EOF) @@ -1004,8 +504,7 @@ func TestPutDatasetReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() mockedDataStore.UpdateDataset(testContext, "123", dataset, models.CreatedState) - auditMock := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusInternalServerError) @@ -1015,11 +514,6 @@ func TestPutDatasetReturnsError(t *testing.T) { So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) So(len(mockedDataStore.UpdateDatasetCalls()), ShouldEqual, 2) - auditMock.AssertRecordCalls( - auditortest.Expected{Action: updateDatasetAction, Result: audit.Attempted, Params: common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123"}}, - auditortest.Expected{Action: updateDatasetAction, Result: audit.Unsuccessful, Params: common.Params{"dataset_id": "123"}}, - ) - Convey("then the request body has been drained", func() { _, err = r.Body.Read(make([]byte, 1)) So(err, ShouldEqual, io.EOF) @@ -1045,8 +539,7 @@ func TestPutDatasetReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditMock := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -1057,11 +550,6 @@ func TestPutDatasetReturnsError(t *testing.T) { So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) So(len(mockedDataStore.UpdateDatasetCalls()), ShouldEqual, 0) - auditMock.AssertRecordCalls( - auditortest.Expected{Action: updateDatasetAction, Result: audit.Attempted, Params: common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123"}}, - auditortest.Expected{Action: updateDatasetAction, Result: audit.Unsuccessful, Params: common.Params{"dataset_id": "123"}}, - ) - Convey("then the request body has been drained", func() { _, err = r.Body.Read(make([]byte, 1)) So(err, ShouldEqual, io.EOF) @@ -1086,8 +574,7 @@ func TestPutDatasetReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditMock := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusUnauthorized) @@ -1098,11 +585,6 @@ func TestPutDatasetReturnsError(t *testing.T) { So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateDatasetCalls()), ShouldEqual, 0) - auditMock.AssertRecordCalls( - auditortest.Expected{Action: updateDatasetAction, Result: audit.Attempted, Params: common.Params{"dataset_id": "123"}}, - auditortest.Expected{Action: updateDatasetAction, Result: audit.Unsuccessful, Params: common.Params{"dataset_id": "123"}}, - ) - Convey("then the request body has been drained", func() { _, err = r.Body.Read(make([]byte, 1)) So(err, ShouldEqual, io.EOF) @@ -1110,261 +592,6 @@ func TestPutDatasetReturnsError(t *testing.T) { }) } -func TestPutDatasetAuditErrors(t *testing.T) { - - t.Parallel() - Convey("given audit action attempted returns an error", t, func() { - auditMock := auditortest.NewErroring(updateDatasetAction, audit.Attempted) - - Convey("when put dataset is called", func() { - r, err := createRequestWithAuth("PUT", "http://localhost:22000/datasets/123", bytes.NewBufferString(datasetPayload)) - So(err, ShouldBeNil) - - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - GetDatasetFunc: func(string) (*models.DatasetUpdate, error) { - return &models.DatasetUpdate{Next: &models.Dataset{}}, nil - }, - UpdateDatasetFunc: func(context.Context, string, *models.Dataset, string) error { - return nil - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - Convey("then a 500 status is returned", func() { - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 0) - So(len(mockedDataStore.UpdateDatasetCalls()), ShouldEqual, 0) - - auditMock.AssertRecordCalls( - auditortest.Expected{ - Action: updateDatasetAction, - Result: audit.Attempted, - Params: common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123"}, - }, - ) - }) - - Convey("then the request body has been drained", func() { - _, err = r.Body.Read(make([]byte, 1)) - So(err, ShouldEqual, io.EOF) - }) - }) - }) - - Convey("given audit action successful returns an error", t, func() { - auditMock := auditortest.NewErroring(updateDatasetAction, audit.Successful) - - Convey("when a put dataset request is successful", func() { - r, err := createRequestWithAuth("PUT", "http://localhost:22000/datasets/123", bytes.NewBufferString(datasetPayload)) - So(err, ShouldBeNil) - - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - GetDatasetFunc: func(string) (*models.DatasetUpdate, error) { - return &models.DatasetUpdate{Next: &models.Dataset{}}, nil - }, - UpdateDatasetFunc: func(context.Context, string, *models.Dataset, string) error { - return nil - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - Convey("then a 200 status is returned", func() { - So(w.Code, ShouldEqual, http.StatusOK) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) - So(len(mockedDataStore.UpdateDatasetCalls()), ShouldEqual, 1) - - auditMock.AssertRecordCalls( - auditortest.Expected{Action: updateDatasetAction, Result: audit.Attempted, Params: common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123"}}, - auditortest.Expected{Action: updateDatasetAction, Result: audit.Successful, Params: common.Params{"dataset_id": "123"}}, - ) - }) - - Convey("then the request body has been drained", func() { - _, err = r.Body.Read(make([]byte, 1)) - So(err, ShouldEqual, io.EOF) - }) - }) - }) - - Convey("given audit action unsuccessful returns an error", t, func() { - auditMock := auditortest.NewErroring(updateDatasetAction, audit.Unsuccessful) - - Convey("when a put dataset request contains an invalid dataset body", func() { - r, err := createRequestWithAuth("PUT", "http://localhost:22000/datasets/123", bytes.NewBufferString("`zxcvbnm,./")) - So(err, ShouldBeNil) - - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - GetDatasetFunc: func(string) (*models.DatasetUpdate, error) { - return &models.DatasetUpdate{Next: &models.Dataset{}}, nil - }, - UpdateDatasetFunc: func(context.Context, string, *models.Dataset, string) error { - return nil - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - Convey("then a 400 status is returned", func() { - So(w.Code, ShouldEqual, http.StatusBadRequest) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 0) - So(len(mockedDataStore.UpdateDatasetCalls()), ShouldEqual, 0) - - auditMock.AssertRecordCalls( - auditortest.Expected{Action: updateDatasetAction, Result: audit.Attempted, Params: common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123"}}, - auditortest.Expected{Action: updateDatasetAction, Result: audit.Unsuccessful, Params: common.Params{"dataset_id": "123"}}, - ) - }) - - Convey("then the request body has been drained", func() { - _, err = r.Body.Read(make([]byte, 1)) - So(err, ShouldEqual, io.EOF) - }) - }) - - Convey("when datastore.getDataset returns an error", func() { - r, err := createRequestWithAuth("PUT", "http://localhost:22000/datasets/123", bytes.NewBufferString(datasetPayload)) - So(err, ShouldBeNil) - - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - GetDatasetFunc: func(string) (*models.DatasetUpdate, error) { - return nil, errs.ErrDatasetNotFound - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - Convey("then a 400 status is returned", func() { - So(w.Code, ShouldEqual, http.StatusNotFound) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) - So(len(mockedDataStore.UpdateDatasetCalls()), ShouldEqual, 0) - - auditMock.AssertRecordCalls( - auditortest.Expected{Action: updateDatasetAction, Result: audit.Attempted, Params: common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123"}}, - auditortest.Expected{Action: updateDatasetAction, Result: audit.Unsuccessful, Params: common.Params{"dataset_id": "123"}}, - ) - }) - - Convey("then the request body has been drained", func() { - _, err = r.Body.Read(make([]byte, 1)) - So(err, ShouldEqual, io.EOF) - }) - }) - - Convey("when the requested dataset has a published state", func() { - - var publishedDataset models.Dataset - json.Unmarshal([]byte(datasetPayload), &publishedDataset) - publishedDataset.State = models.PublishedState - b, _ := json.Marshal(publishedDataset) - - r, err := createRequestWithAuth("PUT", "http://localhost:22000/datasets/123", bytes.NewBuffer(b)) - So(err, ShouldBeNil) - - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - GetDatasetFunc: func(string) (*models.DatasetUpdate, error) { - return &models.DatasetUpdate{Next: &models.Dataset{}}, nil - }, - UpsertDatasetFunc: func(ID string, datasetDoc *models.DatasetUpdate) error { - return errors.New("upsertDataset error") - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - Convey("then a 400 status is returned", func() { - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) - So(len(mockedDataStore.UpsertDatasetCalls()), ShouldEqual, 1) - - auditMock.AssertRecordCalls( - auditortest.Expected{Action: updateDatasetAction, Result: audit.Attempted, Params: common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123"}}, - auditortest.Expected{Action: updateDatasetAction, Result: audit.Unsuccessful, Params: common.Params{"dataset_id": "123"}}, - ) - }) - - Convey("then the request body has been drained", func() { - _, err = r.Body.Read(make([]byte, 1)) - So(err, ShouldEqual, io.EOF) - }) - }) - - Convey("when datastore.UpdateDataset returns an error", func() { - r, err := createRequestWithAuth("PUT", "http://localhost:22000/datasets/123", bytes.NewBufferString(datasetPayload)) - So(err, ShouldBeNil) - - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - GetDatasetFunc: func(string) (*models.DatasetUpdate, error) { - return &models.DatasetUpdate{Next: &models.Dataset{}}, nil - }, - UpdateDatasetFunc: func(ctx context.Context, ID string, dataset *models.Dataset, currentState string) error { - return errors.New("update dataset error") - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - Convey("then a 400 status is returned", func() { - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) - So(len(mockedDataStore.UpdateDatasetCalls()), ShouldEqual, 1) - - auditMock.AssertRecordCalls( - auditortest.Expected{Action: updateDatasetAction, Result: audit.Attempted, Params: common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123"}}, - auditortest.Expected{Action: updateDatasetAction, Result: audit.Unsuccessful, Params: common.Params{"dataset_id": "123"}}, - ) - }) - - Convey("then the request body has been drained", func() { - _, err = r.Body.Read(make([]byte, 1)) - So(err, ShouldEqual, io.EOF) - }) - }) - }) -} - func TestDeleteDatasetReturnsSuccessfully(t *testing.T) { t.Parallel() Convey("A successful request to delete dataset returns 200 OK response", t, func() { @@ -1386,8 +613,7 @@ func TestDeleteDatasetReturnsSuccessfully(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditMock := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNoContent) @@ -1396,11 +622,6 @@ func TestDeleteDatasetReturnsSuccessfully(t *testing.T) { So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetEditionsCalls()), ShouldEqual, 1) So(len(mockedDataStore.DeleteDatasetCalls()), ShouldEqual, 1) - - auditMock.AssertRecordCalls( - auditortest.Expected{Action: deleteDatasetAction, Result: audit.Attempted, Params: common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123"}}, - auditortest.Expected{Action: deleteDatasetAction, Result: audit.Successful, Params: common.Params{"dataset_id": "123", "func": "deleteDataset"}}, - ) }) Convey("A successful request to delete dataset with editions returns 200 OK response", t, func() { @@ -1427,8 +648,7 @@ func TestDeleteDatasetReturnsSuccessfully(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditMock := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNoContent) @@ -1438,11 +658,6 @@ func TestDeleteDatasetReturnsSuccessfully(t *testing.T) { So(len(mockedDataStore.GetEditionsCalls()), ShouldEqual, 1) So(len(mockedDataStore.DeleteEditionCalls()), ShouldEqual, 1) So(len(mockedDataStore.DeleteDatasetCalls()), ShouldEqual, 1) - - auditMock.AssertRecordCalls( - auditortest.Expected{Action: deleteDatasetAction, Result: audit.Attempted, Params: common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123"}}, - auditortest.Expected{Action: deleteDatasetAction, Result: audit.Successful, Params: common.Params{"dataset_id": "123", "func": "deleteDataset"}}, - ) }) } @@ -1467,8 +682,7 @@ func TestDeleteDatasetReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditMock := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusForbidden) @@ -1478,11 +692,6 @@ func TestDeleteDatasetReturnsError(t *testing.T) { So(len(mockedDataStore.GetEditionsCalls()), ShouldEqual, 0) So(len(mockedDataStore.DeleteEditionCalls()), ShouldEqual, 0) So(len(mockedDataStore.DeleteDatasetCalls()), ShouldEqual, 0) - - auditMock.AssertRecordCalls( - auditortest.Expected{Action: deleteDatasetAction, Result: audit.Attempted, Params: common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123"}}, - auditortest.Expected{Action: deleteDatasetAction, Result: audit.Unsuccessful, Params: common.Params{"dataset_id": "123", "func": "deleteDataset"}}, - ) }) Convey("When the api cannot connect to datastore return an internal server error", t, func() { @@ -1505,8 +714,7 @@ func TestDeleteDatasetReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditMock := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) assertInternalServerErr(w) @@ -1515,11 +723,6 @@ func TestDeleteDatasetReturnsError(t *testing.T) { So(len(mockedDataStore.GetEditionsCalls()), ShouldEqual, 1) So(len(mockedDataStore.DeleteEditionCalls()), ShouldEqual, 0) So(len(mockedDataStore.DeleteDatasetCalls()), ShouldEqual, 1) - - auditMock.AssertRecordCalls( - auditortest.Expected{Action: deleteDatasetAction, Result: audit.Attempted, Params: common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123"}}, - auditortest.Expected{Action: deleteDatasetAction, Result: audit.Unsuccessful, Params: common.Params{"dataset_id": "123", "func": "deleteDataset"}}, - ) }) Convey("When the dataset document cannot be found return status not found ", t, func() { @@ -1542,8 +745,7 @@ func TestDeleteDatasetReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditMock := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNoContent) @@ -1553,11 +755,6 @@ func TestDeleteDatasetReturnsError(t *testing.T) { So(len(mockedDataStore.GetEditionsCalls()), ShouldEqual, 0) So(len(mockedDataStore.DeleteEditionCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateDatasetCalls()), ShouldEqual, 0) - - auditMock.AssertRecordCalls( - auditortest.Expected{Action: deleteDatasetAction, Result: audit.Attempted, Params: common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123"}}, - auditortest.Expected{Action: deleteDatasetAction, Result: audit.Unsuccessful, Params: common.Params{"dataset_id": "123", "func": "deleteDataset"}}, - ) }) Convey("When the dataset document cannot be queried return status 500 ", t, func() { @@ -1580,8 +777,7 @@ func TestDeleteDatasetReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditMock := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) assertInternalServerErr(w) @@ -1590,11 +786,6 @@ func TestDeleteDatasetReturnsError(t *testing.T) { So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetEditionsCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateDatasetCalls()), ShouldEqual, 0) - - auditMock.AssertRecordCalls( - auditortest.Expected{Action: deleteDatasetAction, Result: audit.Attempted, Params: common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123"}}, - auditortest.Expected{Action: deleteDatasetAction, Result: audit.Unsuccessful, Params: common.Params{"dataset_id": "123", "func": "deleteDataset"}}, - ) }) Convey("When the request is not authorised to delete the dataset return status not found", t, func() { @@ -1607,8 +798,7 @@ func TestDeleteDatasetReturnsError(t *testing.T) { mockedDataStore := &storetest.StorerMock{} datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditMock := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusUnauthorized) @@ -1619,275 +809,5 @@ func TestDeleteDatasetReturnsError(t *testing.T) { So(len(mockedDataStore.GetEditionsCalls()), ShouldEqual, 0) So(len(mockedDataStore.DeleteEditionCalls()), ShouldEqual, 0) So(len(mockedDataStore.DeleteDatasetCalls()), ShouldEqual, 0) - - auditMock.AssertRecordCalls( - auditortest.Expected{Action: deleteDatasetAction, Result: audit.Attempted, Params: common.Params{"dataset_id": "123"}}, - auditortest.Expected{Action: deleteDatasetAction, Result: audit.Unsuccessful, Params: common.Params{"dataset_id": "123"}}, - ) - }) - -} - -func TestDeleteDatasetAuditActionAttemptedError(t *testing.T) { - t.Parallel() - Convey("given audit action attempted returns an error", t, func() { - auditMock := auditortest.NewErroring(deleteDatasetAction, audit.Attempted) - - Convey("when delete dataset is called", func() { - r, err := createRequestWithAuth("DELETE", "http://localhost:22000/datasets/123", nil) - So(err, ShouldBeNil) - - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{} - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - Convey("then a 500 status is returned", func() { - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 0) - So(len(mockedDataStore.GetEditionsCalls()), ShouldEqual, 0) - So(len(mockedDataStore.DeleteEditionCalls()), ShouldEqual, 0) - So(len(mockedDataStore.DeleteDatasetCalls()), ShouldEqual, 0) - - auditMock.AssertRecordCalls( - auditortest.Expected{ - Action: deleteDatasetAction, - Result: audit.Attempted, - Params: common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123"}, - }, - ) - }) - }) - }) -} - -func TestDeleteDatasetAuditauditUnsuccessfulError(t *testing.T) { - Convey("given auditing action unsuccessful returns an errors", t, func() { - auditMock := auditortest.NewErroring(deleteDatasetAction, audit.Unsuccessful) - - Convey("when attempting to delete a dataset that does not exist", func() { - - r, err := createRequestWithAuth("DELETE", "http://localhost:22000/datasets/123", nil) - So(err, ShouldBeNil) - - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - GetDatasetFunc: func(string) (*models.DatasetUpdate, error) { - return nil, errs.ErrDatasetNotFound - }, - } - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - Convey("then a 204 status is returned", func() { - So(w.Code, ShouldEqual, http.StatusNoContent) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetEditionsCalls()), ShouldEqual, 0) - So(len(mockedDataStore.DeleteEditionCalls()), ShouldEqual, 0) - So(len(mockedDataStore.DeleteDatasetCalls()), ShouldEqual, 0) - - auditMock.AssertRecordCalls( - auditortest.Expected{Action: deleteDatasetAction, Result: audit.Attempted, Params: common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123"}}, - auditortest.Expected{Action: deleteDatasetAction, Result: audit.Unsuccessful, Params: common.Params{"dataset_id": "123", "func": "deleteDataset"}}, - ) - }) - }) - - Convey("when dataStore.Backend.GetDataset returns an error", func() { - r, err := createRequestWithAuth("DELETE", "http://localhost:22000/datasets/123", nil) - So(err, ShouldBeNil) - - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - GetDatasetFunc: func(string) (*models.DatasetUpdate, error) { - return nil, errors.New("dataStore.Backend.GetDataset error") - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - auditMock = auditortest.NewErroring(deleteDatasetAction, audit.Unsuccessful) - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - Convey("then a 500 status is returned", func() { - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetEditionsCalls()), ShouldEqual, 0) - So(len(mockedDataStore.DeleteEditionCalls()), ShouldEqual, 0) - So(len(mockedDataStore.DeleteDatasetCalls()), ShouldEqual, 0) - - auditMock.AssertRecordCalls( - auditortest.Expected{Action: deleteDatasetAction, Result: audit.Attempted, Params: common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123"}}, - auditortest.Expected{Action: deleteDatasetAction, Result: audit.Unsuccessful, Params: common.Params{"dataset_id": "123", "func": "deleteDataset"}}, - ) - }) - }) - - Convey("when attempting to delete a published dataset", func() { - r, err := createRequestWithAuth("DELETE", "http://localhost:22000/datasets/123", nil) - So(err, ShouldBeNil) - - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - GetDatasetFunc: func(string) (*models.DatasetUpdate, error) { - return &models.DatasetUpdate{Current: &models.Dataset{State: models.PublishedState}}, nil - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - auditMock = auditortest.NewErroring(deleteDatasetAction, audit.Unsuccessful) - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - Convey("then a 403 status is returned", func() { - So(w.Code, ShouldEqual, http.StatusForbidden) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetEditionsCalls()), ShouldEqual, 0) - So(len(mockedDataStore.DeleteEditionCalls()), ShouldEqual, 0) - So(len(mockedDataStore.DeleteDatasetCalls()), ShouldEqual, 0) - - auditMock.AssertRecordCalls( - auditortest.Expected{Action: deleteDatasetAction, Result: audit.Attempted, Params: common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123"}}, - auditortest.Expected{Action: deleteDatasetAction, Result: audit.Unsuccessful, Params: common.Params{"dataset_id": "123", "func": "deleteDataset"}}, - ) - }) - }) - - Convey("when dataStore.Backend.DeleteEdition returns an error", func() { - r, err := createRequestWithAuth("DELETE", "http://localhost:22000/datasets/123", nil) - So(err, ShouldBeNil) - - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - GetDatasetFunc: func(string) (*models.DatasetUpdate, error) { - return &models.DatasetUpdate{Next: &models.Dataset{State: models.CompletedState}}, nil - }, - GetEditionsFunc: func(ctx context.Context, ID string, state string) (*models.EditionUpdateResults, error) { - var items []*models.EditionUpdate - items = append(items, &models.EditionUpdate{}) - return &models.EditionUpdateResults{Items: items}, nil - }, - DeleteEditionFunc: func(ID string) error { - return errors.New("DeleteEditionFunc error") - }, - } - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - - auditMock = auditortest.NewErroring(deleteDatasetAction, audit.Unsuccessful) - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - Convey("then a 500 status is returned", func() { - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetEditionsCalls()), ShouldEqual, 1) - So(len(mockedDataStore.DeleteEditionCalls()), ShouldEqual, 1) - So(len(mockedDataStore.DeleteDatasetCalls()), ShouldEqual, 0) - - auditMock.AssertRecordCalls( - auditortest.Expected{Action: deleteDatasetAction, Result: audit.Attempted, Params: common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123"}}, - auditortest.Expected{Action: deleteDatasetAction, Result: audit.Unsuccessful, Params: common.Params{"dataset_id": "123", "func": "deleteDataset"}}, - ) - }) - }) - - Convey("when dataStore.Backend.DeleteDataset returns an error", func() { - r, err := createRequestWithAuth("DELETE", "http://localhost:22000/datasets/123", nil) - So(err, ShouldBeNil) - - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - GetDatasetFunc: func(string) (*models.DatasetUpdate, error) { - return &models.DatasetUpdate{Next: &models.Dataset{State: models.CompletedState}}, nil - }, - GetEditionsFunc: func(ctx context.Context, ID string, state string) (*models.EditionUpdateResults, error) { - return &models.EditionUpdateResults{}, nil - }, - DeleteDatasetFunc: func(ID string) error { - return errors.New("DeleteDatasetFunc error") - }, - } - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - auditMock = auditortest.NewErroring(deleteDatasetAction, audit.Unsuccessful) - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - Convey("then a 500 status is returned", func() { - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetEditionsCalls()), ShouldEqual, 1) - So(len(mockedDataStore.DeleteEditionCalls()), ShouldEqual, 0) - So(len(mockedDataStore.DeleteDatasetCalls()), ShouldEqual, 1) - - auditMock.AssertRecordCalls( - auditortest.Expected{Action: deleteDatasetAction, Result: audit.Attempted, Params: common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123"}}, - auditortest.Expected{Action: deleteDatasetAction, Result: audit.Unsuccessful, Params: common.Params{"dataset_id": "123", "func": "deleteDataset"}}, - ) - }) - }) - }) -} - -func TestDeleteDatasetAuditActionSuccessfulError(t *testing.T) { - Convey("given audit action successful returns an error", t, func() { - r, err := createRequestWithAuth("DELETE", "http://localhost:22000/datasets/123", nil) - So(err, ShouldBeNil) - - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - GetDatasetFunc: func(string) (*models.DatasetUpdate, error) { - return &models.DatasetUpdate{Next: &models.Dataset{State: models.CreatedState}}, nil - }, - GetEditionsFunc: func(ctx context.Context, ID string, state string) (*models.EditionUpdateResults, error) { - return &models.EditionUpdateResults{}, nil - }, - DeleteDatasetFunc: func(string) error { - return nil - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - auditMock := auditortest.NewErroring(deleteDatasetAction, audit.Successful) - - Convey("when delete dataset is called", func() { - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditMock, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - Convey("then a 204 status is returned", func() { - So(w.Code, ShouldEqual, http.StatusNoContent) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetEditionsCalls()), ShouldEqual, 1) - So(len(mockedDataStore.DeleteEditionCalls()), ShouldEqual, 0) - So(len(mockedDataStore.DeleteDatasetCalls()), ShouldEqual, 1) - - auditMock.AssertRecordCalls( - auditortest.Expected{Action: deleteDatasetAction, Result: audit.Attempted, Params: common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123"}}, - auditortest.Expected{Action: deleteDatasetAction, Result: audit.Successful, Params: common.Params{"dataset_id": "123", "func": "deleteDataset"}}, - ) - }) - }) }) } diff --git a/api/dimensions.go b/api/dimensions.go index b726acb8..3ee7791c 100644 --- a/api/dimensions.go +++ b/api/dimensions.go @@ -9,8 +9,7 @@ import ( errs "github.com/ONSdigital/dp-dataset-api/apierrors" "github.com/ONSdigital/dp-dataset-api/models" - "github.com/ONSdigital/go-ns/audit" - "github.com/ONSdigital/go-ns/common" + dprequest "github.com/ONSdigital/dp-net/request" "github.com/ONSdigital/log.go/log" "github.com/globalsign/mgo/bson" "github.com/gorilla/mux" @@ -23,12 +22,6 @@ func (api *DatasetAPI) getDimensions(w http.ResponseWriter, r *http.Request) { edition := vars["edition"] version := vars["version"] logData := log.Data{"dataset_id": datasetID, "edition": edition, "version": version, "func": "getDimensions"} - auditParams := common.Params{"dataset_id": datasetID, "edition": edition, "version": version} - - if err := api.auditor.Record(ctx, getDimensionsAction, audit.Attempted, auditParams); err != nil { - handleDimensionsErr(ctx, w, err, logData) - return - } b, err := func() ([]byte, error) { authorised := api.authenticate(r, logData) @@ -72,18 +65,10 @@ func (api *DatasetAPI) getDimensions(w http.ResponseWriter, r *http.Request) { return b, nil }() if err != nil { - if auditErr := api.auditor.Record(ctx, getDimensionsAction, audit.Unsuccessful, auditParams); auditErr != nil { - err = auditErr - } handleDimensionsErr(ctx, w, err, logData) return } - if auditErr := api.auditor.Record(ctx, getDimensionsAction, audit.Successful, auditParams); auditErr != nil { - handleDimensionsErr(ctx, w, auditErr, logData) - return - } - setJSONContentType(w) _, err = w.Write(b) if err != nil { @@ -149,12 +134,7 @@ func (api *DatasetAPI) getDimensionOptions(w http.ResponseWriter, r *http.Reques dimension := vars["dimension"] logData := log.Data{"dataset_id": datasetID, "edition": edition, "version": versionID, "dimension": dimension, "func": "getDimensionOptions"} - auditParams := common.Params{"dataset_id": datasetID, "edition": edition, "version": versionID, "dimension": dimension} - - if err := api.auditor.Record(ctx, getDimensionOptionsAction, audit.Attempted, auditParams); err != nil { - handleDimensionsErr(ctx, w, err, logData) - return - } + auditParams := dprequest.Params{"dataset_id": datasetID, "edition": edition, "version": versionID, "dimension": dimension} authorised := api.authenticate(r, logData) auditParams["authorised"] = strconv.FormatBool(authorised) @@ -198,18 +178,10 @@ func (api *DatasetAPI) getDimensionOptions(w http.ResponseWriter, r *http.Reques return b, nil }() if err != nil { - if auditErr := api.auditor.Record(ctx, getDimensionOptionsAction, audit.Unsuccessful, auditParams); auditErr != nil { - err = auditErr - } handleDimensionsErr(ctx, w, err, logData) return } - if auditErr := api.auditor.Record(ctx, getDimensionOptionsAction, audit.Successful, auditParams); auditErr != nil { - handleDimensionsErr(ctx, w, auditErr, logData) - return - } - setJSONContentType(w) _, err = w.Write(b) if err != nil { diff --git a/api/dimensions_test.go b/api/dimensions_test.go index 5338532a..f9f02d65 100644 --- a/api/dimensions_test.go +++ b/api/dimensions_test.go @@ -9,9 +9,6 @@ import ( "github.com/ONSdigital/dp-dataset-api/mocks" "github.com/ONSdigital/dp-dataset-api/models" storetest "github.com/ONSdigital/dp-dataset-api/store/datastoretest" - "github.com/ONSdigital/go-ns/audit" - "github.com/ONSdigital/go-ns/audit/auditortest" - "github.com/ONSdigital/go-ns/common" "github.com/globalsign/mgo/bson" . "github.com/smartystreets/goconvey/convey" ) @@ -32,8 +29,7 @@ func TestGetDimensionsReturnsOk(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) @@ -41,26 +37,10 @@ func TestGetDimensionsReturnsOk(t *testing.T) { So(permissions.Required.Calls, ShouldEqual, 0) So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetDimensionsCalls()), ShouldEqual, 1) - - auditParams := common.Params{ - "dataset_id": "123", - "edition": "2017", - "version": "1", - } - auditor.AssertRecordCalls( - auditortest.Expected{Action: getDimensionsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getDimensionsAction, Result: audit.Successful, Params: auditParams}, - ) }) } func TestGetDimensionsReturnsErrors(t *testing.T) { - auditParams := common.Params{ - "dataset_id": "123", - "edition": "2017", - "version": "1", - } - t.Parallel() Convey("When the api cannot connect to datastore to get dimension resource return an internal server error", t, func() { r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123/editions/2017/versions/1/dimensions", nil) @@ -73,8 +53,7 @@ func TestGetDimensionsReturnsErrors(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusInternalServerError) @@ -83,11 +62,6 @@ func TestGetDimensionsReturnsErrors(t *testing.T) { So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetDimensionsCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getDimensionsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getDimensionsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When the request contain an invalid version return not found", t, func() { @@ -101,8 +75,7 @@ func TestGetDimensionsReturnsErrors(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -111,11 +84,6 @@ func TestGetDimensionsReturnsErrors(t *testing.T) { So(w.Body.String(), ShouldContainSubstring, errs.ErrVersionNotFound.Error()) So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetDimensionsCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getDimensionsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getDimensionsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When there are no dimensions then return not found error", t, func() { @@ -132,8 +100,7 @@ func TestGetDimensionsReturnsErrors(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -142,11 +109,6 @@ func TestGetDimensionsReturnsErrors(t *testing.T) { So(w.Body.String(), ShouldContainSubstring, errs.ErrDimensionsNotFound.Error()) So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetDimensionsCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getDimensionsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getDimensionsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When the version has an invalid state return internal server error", t, func() { @@ -160,8 +122,7 @@ func TestGetDimensionsReturnsErrors(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusInternalServerError) @@ -170,172 +131,6 @@ func TestGetDimensionsReturnsErrors(t *testing.T) { So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetDimensionsCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getDimensionsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getDimensionsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) -} - -func TestGetDimensionsAuditingErrors(t *testing.T) { - t.Parallel() - auditParams := common.Params{"dataset_id": "123", "edition": "2017", "version": "1"} - - Convey("given audit action attempted returns an error", t, func() { - auditor := auditortest.NewErroring(getDimensionsAction, audit.Attempted) - - Convey("when get dimensions is called", func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123/editions/2017/versions/1/dimensions", nil) - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{} - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - Convey("then a 500 status is returned", func() { - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 0) - So(len(mockedDataStore.GetDimensionsCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{ - Action: getDimensionsAction, - Result: audit.Attempted, - Params: auditParams, - }, - ) - }) - }) - }) - - Convey("given audit action successful returns an error", t, func() { - auditor := auditortest.NewErroring(getDimensionsAction, audit.Successful) - - Convey("when get dimensions is called", func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123/editions/2017/versions/1/dimensions", nil) - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - GetVersionFunc: func(datasetID, edition, version, state string) (*models.Version, error) { - return &models.Version{State: models.AssociatedState}, nil - }, - GetDimensionsFunc: func(datasetID, versionID string) ([]bson.M, error) { - return []bson.M{}, nil - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - Convey("then a 500 status is returned", func() { - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetDimensionsCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getDimensionsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getDimensionsAction, Result: audit.Successful, Params: auditParams}, - ) - }) - }) - }) - - Convey("given audit action unsuccessful returns an error", t, func() { - auditor := auditortest.NewErroring(getDimensionsAction, audit.Unsuccessful) - - Convey("when datastore.getVersion returns an error", func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123/editions/2017/versions/1/dimensions", nil) - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - GetVersionFunc: func(datasetID, edition, version, state string) (*models.Version, error) { - return nil, errs.ErrVersionNotFound - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - Convey("then a 500 status is returned", func() { - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetDimensionsCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getDimensionsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getDimensionsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) - }) - - Convey("when the version in not in a valid state", func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123/editions/2017/versions/1/dimensions", nil) - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - GetVersionFunc: func(datasetID, edition, version, state string) (*models.Version, error) { - return &models.Version{State: "BROKEN"}, nil - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - Convey("then a 500 status is returned", func() { - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetDimensionsCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getDimensionsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getDimensionsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) - }) - - Convey("when datastore.getDataset returns an error", func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123/editions/2017/versions/1/dimensions", nil) - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - GetVersionFunc: func(datasetID, edition, version, state string) (*models.Version, error) { - return &models.Version{State: models.AssociatedState}, nil - }, - GetDimensionsFunc: func(datasetID string, versionID string) ([]bson.M, error) { - return nil, errs.ErrDimensionsNotFound - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - Convey("then a 500 status is returned", func() { - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetDimensionsCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getDimensionsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getDimensionsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) - }) }) } @@ -355,8 +150,7 @@ func TestGetDimensionOptionsReturnsOk(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) @@ -364,12 +158,6 @@ func TestGetDimensionOptionsReturnsOk(t *testing.T) { So(permissions.Required.Calls, ShouldEqual, 0) So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetDimensionOptionsCalls()), ShouldEqual, 1) - - auditParams := common.Params{"authorised": "false", "dataset_id": "123", "edition": "2017", "version": "1", "dimension": "age"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getDimensionOptionsAction, Result: audit.Attempted, Params: common.Params{"dataset_id": "123", "edition": "2017", "version": "1", "dimension": "age"}}, - auditortest.Expected{Action: getDimensionOptionsAction, Result: audit.Successful, Params: auditParams}, - ) }) } @@ -386,8 +174,7 @@ func TestGetDimensionOptionsReturnsErrors(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -396,12 +183,6 @@ func TestGetDimensionOptionsReturnsErrors(t *testing.T) { So(permissions.Required.Calls, ShouldEqual, 0) So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetDimensionOptionsCalls()), ShouldEqual, 0) - - auditParams := common.Params{"authorised": "false", "dataset_id": "123", "edition": "2017", "version": "1", "dimension": "age"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getDimensionOptionsAction, Result: audit.Attempted, Params: common.Params{"dataset_id": "123", "edition": "2017", "version": "1", "dimension": "age"}}, - auditortest.Expected{Action: getDimensionOptionsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When an internal error causes failure to retrieve dimension options, then return internal server error", t, func() { @@ -418,8 +199,7 @@ func TestGetDimensionOptionsReturnsErrors(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusInternalServerError) @@ -428,12 +208,6 @@ func TestGetDimensionOptionsReturnsErrors(t *testing.T) { So(permissions.Required.Calls, ShouldEqual, 0) So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetDimensionOptionsCalls()), ShouldEqual, 1) - - auditParams := common.Params{"authorised": "false", "dataset_id": "123", "edition": "2017", "version": "1", "dimension": "age"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getDimensionOptionsAction, Result: audit.Attempted, Params: common.Params{"dataset_id": "123", "edition": "2017", "version": "1", "dimension": "age"}}, - auditortest.Expected{Action: getDimensionOptionsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When the version has an invalid state return internal server error", t, func() { @@ -447,8 +221,7 @@ func TestGetDimensionOptionsReturnsErrors(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusInternalServerError) @@ -457,181 +230,5 @@ func TestGetDimensionOptionsReturnsErrors(t *testing.T) { So(permissions.Required.Calls, ShouldEqual, 0) So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetDimensionOptionsCalls()), ShouldEqual, 0) - - auditParams := common.Params{"authorised": "false", "dataset_id": "123", "edition": "2017", "version": "1", "dimension": "age"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getDimensionOptionsAction, Result: audit.Attempted, Params: common.Params{"dataset_id": "123", "edition": "2017", "version": "1", "dimension": "age"}}, - auditortest.Expected{Action: getDimensionOptionsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) -} - -func TestGetDimensionOptionsAuditingErrors(t *testing.T) { - t.Parallel() - - Convey("given audit action attempted returns an error", t, func() { - auditor := auditortest.NewErroring(getDimensionOptionsAction, audit.Attempted) - - Convey("when get dimensions options is called", func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123/editions/2017/versions/1/dimensions/age/options", nil) - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{} - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - Convey("then a 500 status is returned", func() { - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) - So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 0) - So(len(mockedDataStore.GetDimensionOptionsCalls()), ShouldEqual, 0) - - auditParams := common.Params{"dataset_id": "123", "edition": "2017", "version": "1", "dimension": "age"} - auditor.AssertRecordCalls( - auditortest.Expected{ - Action: getDimensionOptionsAction, - Result: audit.Attempted, - Params: auditParams, - }, - ) - }) - }) - }) - - Convey("given audit action successful returns an error", t, func() { - auditor := auditortest.NewErroring(getDimensionOptionsAction, audit.Successful) - - Convey("when get dimension options is called", func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123/editions/2017/versions/1/dimensions/age/options", nil) - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - GetVersionFunc: func(datasetID, edition, version, state string) (*models.Version, error) { - return &models.Version{State: models.AssociatedState}, nil - }, - GetDimensionOptionsFunc: func(version *models.Version, dimensions string) (*models.DimensionOptionResults, error) { - return &models.DimensionOptionResults{}, nil - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - Convey("then a 500 status is returned", func() { - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) - So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetDimensionOptionsCalls()), ShouldEqual, 1) - - auditParams := common.Params{"authorised": "false", "dataset_id": "123", "edition": "2017", "version": "1", "dimension": "age"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getDimensionOptionsAction, Result: audit.Attempted, Params: common.Params{"dataset_id": "123", "edition": "2017", "version": "1", "dimension": "age"}}, - auditortest.Expected{Action: getDimensionOptionsAction, Result: audit.Successful, Params: auditParams}, - ) - }) - }) - }) - - Convey("given audit action unsuccessful returns an error", t, func() { - auditor := auditortest.NewErroring(getDimensionOptionsAction, audit.Unsuccessful) - - Convey("when datastore.getVersion returns an error", func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123/editions/2017/versions/1/dimensions/age/options", nil) - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - GetVersionFunc: func(datasetID, edition, version, state string) (*models.Version, error) { - return nil, errs.ErrVersionNotFound - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - Convey("then a 500 status is returned", func() { - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) - So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetDimensionsCalls()), ShouldEqual, 0) - - auditParams := common.Params{"authorised": "false", "dataset_id": "123", "edition": "2017", "version": "1", "dimension": "age"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getDimensionOptionsAction, Result: audit.Attempted, Params: common.Params{"dataset_id": "123", "edition": "2017", "version": "1", "dimension": "age"}}, - auditortest.Expected{Action: getDimensionOptionsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) - }) - - Convey("when the version in not in a valid state", func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123/editions/2017/versions/1/dimensions/age/options", nil) - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - GetVersionFunc: func(datasetID, edition, version, state string) (*models.Version, error) { - return &models.Version{State: "BROKEN"}, nil - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - Convey("then a 500 status is returned", func() { - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) - So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetDimensionsCalls()), ShouldEqual, 0) - - auditParams := common.Params{"authorised": "false", "dataset_id": "123", "edition": "2017", "version": "1", "dimension": "age"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getDimensionOptionsAction, Result: audit.Attempted, Params: common.Params{"dataset_id": "123", "edition": "2017", "version": "1", "dimension": "age"}}, - auditortest.Expected{Action: getDimensionOptionsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) - }) - - Convey("when datastore.getDataset returns an error", func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123/editions/2017/versions/1/dimensions/age/options", nil) - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - GetVersionFunc: func(datasetID, edition, version, state string) (*models.Version, error) { - return &models.Version{State: models.AssociatedState}, nil - }, - GetDimensionOptionsFunc: func(version *models.Version, dimensions string) (*models.DimensionOptionResults, error) { - return nil, errs.ErrDimensionNotFound - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - Convey("then a 500 status is returned", func() { - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) - So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetDimensionOptionsCalls()), ShouldEqual, 1) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - - auditParams := common.Params{"authorised": "false", "dataset_id": "123", "edition": "2017", "version": "1", "dimension": "age"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getDimensionOptionsAction, Result: audit.Attempted, Params: common.Params{"dataset_id": "123", "edition": "2017", "version": "1", "dimension": "age"}}, - auditortest.Expected{Action: getDimensionOptionsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) - }) }) } diff --git a/api/editions.go b/api/editions.go index a15db448..f39e20b3 100644 --- a/api/editions.go +++ b/api/editions.go @@ -6,8 +6,6 @@ import ( errs "github.com/ONSdigital/dp-dataset-api/apierrors" "github.com/ONSdigital/dp-dataset-api/models" - "github.com/ONSdigital/go-ns/audit" - "github.com/ONSdigital/go-ns/common" "github.com/ONSdigital/log.go/log" "github.com/gorilla/mux" ) @@ -17,12 +15,6 @@ func (api *DatasetAPI) getEditions(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) datasetID := vars["dataset_id"] logData := log.Data{"dataset_id": datasetID} - auditParams := common.Params{"dataset_id": datasetID} - - if auditErr := api.auditor.Record(r.Context(), getEditionsAction, audit.Attempted, auditParams); auditErr != nil { - http.Error(w, errs.ErrInternalServer.Error(), http.StatusInternalServerError) - return - } b, err := func() ([]byte, error) { authorised := api.authenticate(r, logData) @@ -75,10 +67,6 @@ func (api *DatasetAPI) getEditions(w http.ResponseWriter, r *http.Request) { }() if err != nil { - if auditErr := api.auditor.Record(ctx, getEditionsAction, audit.Unsuccessful, auditParams); auditErr != nil { - err = auditErr - } - if err == errs.ErrDatasetNotFound || err == errs.ErrEditionNotFound { http.Error(w, err.Error(), http.StatusNotFound) } else { @@ -87,11 +75,6 @@ func (api *DatasetAPI) getEditions(w http.ResponseWriter, r *http.Request) { return } - if auditErr := api.auditor.Record(r.Context(), getEditionsAction, audit.Successful, auditParams); auditErr != nil { - http.Error(w, errs.ErrInternalServer.Error(), http.StatusInternalServerError) - return - } - setJSONContentType(w) _, err = w.Write(b) if err != nil { @@ -106,13 +89,7 @@ func (api *DatasetAPI) getEdition(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) datasetID := vars["dataset_id"] edition := vars["edition"] - auditParams := common.Params{"dataset_id": datasetID, "edition": edition} - logData := audit.ToLogData(auditParams) - - if auditErr := api.auditor.Record(r.Context(), getEditionAction, audit.Attempted, auditParams); auditErr != nil { - http.Error(w, errs.ErrInternalServer.Error(), http.StatusInternalServerError) - return - } + logData := log.Data{"dataset_id": datasetID, "edition": edition} b, err := func() ([]byte, error) { authorised := api.authenticate(r, logData) @@ -157,10 +134,6 @@ func (api *DatasetAPI) getEdition(w http.ResponseWriter, r *http.Request) { }() if err != nil { - if auditErr := api.auditor.Record(ctx, getEditionAction, audit.Unsuccessful, auditParams); auditErr != nil { - err = auditErr - } - if err == errs.ErrDatasetNotFound || err == errs.ErrEditionNotFound { http.Error(w, err.Error(), http.StatusNotFound) } else { @@ -169,11 +142,6 @@ func (api *DatasetAPI) getEdition(w http.ResponseWriter, r *http.Request) { return } - if auditErr := api.auditor.Record(ctx, getEditionAction, audit.Successful, auditParams); auditErr != nil { - http.Error(w, errs.ErrInternalServer.Error(), http.StatusInternalServerError) - return - } - setJSONContentType(w) _, err = w.Write(b) if err != nil { diff --git a/api/editions_test.go b/api/editions_test.go index 5078cb7b..5edf5f9e 100644 --- a/api/editions_test.go +++ b/api/editions_test.go @@ -2,7 +2,6 @@ package api import ( "context" - "errors" "net/http" "net/http/httptest" "testing" @@ -11,9 +10,6 @@ import ( "github.com/ONSdigital/dp-dataset-api/mocks" "github.com/ONSdigital/dp-dataset-api/models" storetest "github.com/ONSdigital/dp-dataset-api/store/datastoretest" - "github.com/ONSdigital/go-ns/audit" - "github.com/ONSdigital/go-ns/audit/auditortest" - "github.com/ONSdigital/go-ns/common" . "github.com/smartystreets/goconvey/convey" ) @@ -36,10 +32,9 @@ func TestGetEditionsReturnsOK(t *testing.T) { }, } - auditor := auditortest.New() datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) @@ -47,146 +42,10 @@ func TestGetEditionsReturnsOK(t *testing.T) { So(permissions.Required.Calls, ShouldEqual, 0) So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetEditionsCalls()), ShouldEqual, 1) - - auditParams := common.Params{"dataset_id": "123-456"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getEditionsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getEditionsAction, Result: audit.Successful, Params: auditParams}, - ) - }) -} - -func TestGetEditionsAuditingError(t *testing.T) { - auditParams := common.Params{"dataset_id": "123-456"} - - t.Parallel() - Convey("given auditing get editions attempted action returns an error then a 500 response is returned", t, func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123-456/editions", nil) - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - CheckDatasetExistsFunc: func(datasetID, state string) error { - return nil - }, - GetEditionsFunc: func(ctx context.Context, id string, state string) (*models.EditionUpdateResults, error) { - return &models.EditionUpdateResults{}, nil - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - auditor.RecordFunc = func(ctx context.Context, action string, result string, params common.Params) error { - return errors.New("get editions action attempted audit event error") - } - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 0) - So(len(mockedDataStore.GetEditionsCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{ - Action: getEditionsAction, - Result: audit.Attempted, - Params: auditParams, - }, - ) - }) - - Convey("given auditing get editions action successful returns an error then a 500 response is returned", t, func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123-456/editions", nil) - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - CheckDatasetExistsFunc: func(datasetID, state string) error { - return nil - }, - GetEditionsFunc: func(ctx context.Context, id string, state string) (*models.EditionUpdateResults, error) { - return &models.EditionUpdateResults{}, nil - }, - } - - auditor := auditortest.NewErroring(getEditionsAction, audit.Successful) - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetEditionsCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getEditionsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getEditionsAction, Result: audit.Successful, Params: auditParams}, - ) - }) - - Convey("When the dataset does not exist and auditing the action result fails then return status 500", t, func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123-456/editions", nil) - r.Header.Add("internal-token", "coffee") - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - CheckDatasetExistsFunc: func(datasetID, state string) error { - return errs.ErrDatasetNotFound - }, - } - - auditor := auditortest.NewErroring(getEditionsAction, audit.Unsuccessful) - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetEditionsCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getEditionsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getEditionsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) - - Convey("When no published editions exist against a published dataset and auditing unsuccessful errors return status 500", t, func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123-456/editions", nil) - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - CheckDatasetExistsFunc: func(datasetID, state string) error { - return nil - }, - GetEditionsFunc: func(ctx context.Context, id string, state string) (*models.EditionUpdateResults, error) { - return nil, errs.ErrEditionNotFound - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - auditor := auditortest.NewErroring(getEditionsAction, audit.Unsuccessful) - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetEditionsCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getEditionsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getEditionsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) } func TestGetEditionsReturnsError(t *testing.T) { - auditParams := common.Params{"dataset_id": "123-456"} t.Parallel() Convey("When the api cannot connect to datastore return an internal server error", t, func() { r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123-456/editions", nil) @@ -197,10 +56,9 @@ func TestGetEditionsReturnsError(t *testing.T) { }, } - auditor := auditortest.New() datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusInternalServerError) @@ -209,11 +67,6 @@ func TestGetEditionsReturnsError(t *testing.T) { So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetEditionsCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getEditionsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getEditionsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When the dataset does not exist return status not found", t, func() { @@ -228,8 +81,7 @@ func TestGetEditionsReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -238,11 +90,6 @@ func TestGetEditionsReturnsError(t *testing.T) { So(w.Body.String(), ShouldContainSubstring, errs.ErrDatasetNotFound.Error()) So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetEditionsCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getEditionsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getEditionsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When no editions exist against an existing dataset return status not found", t, func() { @@ -260,8 +107,7 @@ func TestGetEditionsReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -270,11 +116,6 @@ func TestGetEditionsReturnsError(t *testing.T) { So(w.Body.String(), ShouldContainSubstring, errs.ErrEditionNotFound.Error()) So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetEditionsCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getEditionsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getEditionsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When no published editions exist against a published dataset return status not found", t, func() { @@ -291,8 +132,7 @@ func TestGetEditionsReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -301,11 +141,6 @@ func TestGetEditionsReturnsError(t *testing.T) { So(w.Body.String(), ShouldContainSubstring, errs.ErrEditionNotFound.Error()) So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetEditionsCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getEditionsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getEditionsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) } @@ -325,8 +160,7 @@ func TestGetEditionReturnsOK(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) @@ -334,18 +168,10 @@ func TestGetEditionReturnsOK(t *testing.T) { So(permissions.Required.Calls, ShouldEqual, 0) So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetEditionCalls()), ShouldEqual, 1) - - auditParams := common.Params{"dataset_id": "123-456", "edition": "678"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getEditionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getEditionAction, Result: audit.Successful, Params: auditParams}, - ) }) } func TestGetEditionReturnsError(t *testing.T) { - auditParams := common.Params{"dataset_id": "123-456", "edition": "678"} - t.Parallel() Convey("When the api cannot connect to datastore return an internal server error", t, func() { r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123-456/editions/678", nil) @@ -358,8 +184,7 @@ func TestGetEditionReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusInternalServerError) @@ -368,11 +193,6 @@ func TestGetEditionReturnsError(t *testing.T) { So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetEditionCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getEditionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getEditionAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When the dataset does not exist return status not found", t, func() { @@ -387,8 +207,7 @@ func TestGetEditionReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -397,11 +216,6 @@ func TestGetEditionReturnsError(t *testing.T) { So(w.Body.String(), ShouldContainSubstring, errs.ErrDatasetNotFound.Error()) So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetEditionCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getEditionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getEditionAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When edition does not exist for a dataset return status not found", t, func() { @@ -419,8 +233,7 @@ func TestGetEditionReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -429,11 +242,6 @@ func TestGetEditionReturnsError(t *testing.T) { So(w.Body.String(), ShouldContainSubstring, errs.ErrEditionNotFound.Error()) So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetEditionCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getEditionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getEditionAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When edition is not published for a dataset return status not found", t, func() { @@ -450,8 +258,7 @@ func TestGetEditionReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -460,129 +267,5 @@ func TestGetEditionReturnsError(t *testing.T) { So(w.Body.String(), ShouldContainSubstring, errs.ErrEditionNotFound.Error()) So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetEditionCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getEditionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getEditionAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) -} - -func TestGetEditionAuditErrors(t *testing.T) { - auditParams := common.Params{"dataset_id": "123-456", "edition": "678"} - - t.Parallel() - Convey("when auditing get edition attempted action errors then a 500 status is returned", t, func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123-456/editions/678", nil) - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{} - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - auditor := auditortest.NewErroring(getEditionAction, audit.Attempted) - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 0) - So(len(mockedDataStore.GetEditionCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{ - Action: getEditionAction, - Result: audit.Attempted, - Params: auditParams, - }, - ) - }) - - Convey("when check dataset exists errors and auditing action unsuccessful errors then a 500 status is returned", t, func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123-456/editions/678", nil) - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - CheckDatasetExistsFunc: func(ID string, state string) error { - return errors.New("check dataset error") - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - auditor := auditortest.NewErroring(getEditionAction, audit.Unsuccessful) - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetEditionCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getEditionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getEditionAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) - - Convey("when check edition exists errors and auditing action unsuccessful errors then a 500 status is returned", t, func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123-456/editions/678", nil) - w := httptest.NewRecorder() - - mockedDataStore := &storetest.StorerMock{ - CheckDatasetExistsFunc: func(ID string, state string) error { - return nil - }, - GetEditionFunc: func(ID, editionID, state string) (*models.EditionUpdate, error) { - return nil, errors.New("get edition error") - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - auditor := auditortest.NewErroring(getEditionAction, audit.Unsuccessful) - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetEditionCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getEditionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getEditionAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) - - Convey("when get edition audit even successful errors then a 500 status is returned", t, func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123-456/editions/678", nil) - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - CheckDatasetExistsFunc: func(datasetID, state string) error { - return nil - }, - GetEditionFunc: func(id string, editionID string, state string) (*models.EditionUpdate, error) { - return &models.EditionUpdate{}, nil - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - auditor := auditortest.NewErroring(getEditionAction, audit.Successful) - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetEditionCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getEditionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getEditionAction, Result: audit.Successful, Params: auditParams}, - ) }) } diff --git a/api/metadata.go b/api/metadata.go index 239e2bb6..b075693f 100644 --- a/api/metadata.go +++ b/api/metadata.go @@ -6,8 +6,6 @@ import ( errs "github.com/ONSdigital/dp-dataset-api/apierrors" "github.com/ONSdigital/dp-dataset-api/models" - "github.com/ONSdigital/go-ns/audit" - "github.com/ONSdigital/go-ns/common" "github.com/ONSdigital/log.go/log" "github.com/gorilla/mux" "github.com/pkg/errors" @@ -19,13 +17,7 @@ func (api *DatasetAPI) getMetadata(w http.ResponseWriter, r *http.Request) { datasetID := vars["dataset_id"] edition := vars["edition"] version := vars["version"] - auditParams := common.Params{"dataset_id": datasetID, "edition": edition, "version": version} - logData := audit.ToLogData(auditParams) - - if auditErr := api.auditor.Record(ctx, getMetadataAction, audit.Attempted, auditParams); auditErr != nil { - handleMetadataErr(w, auditErr) - return - } + logData := log.Data{"dataset_id": datasetID, "edition": edition, "version": version} b, err := func() ([]byte, error) { @@ -95,18 +87,10 @@ func (api *DatasetAPI) getMetadata(w http.ResponseWriter, r *http.Request) { if err != nil { log.Event(ctx, "received error", log.ERROR, log.Error(err), logData) - if auditErr := api.auditor.Record(ctx, getMetadataAction, audit.Unsuccessful, auditParams); auditErr != nil { - err = auditErr - } handleMetadataErr(w, err) return } - if auditErr := api.auditor.Record(ctx, getMetadataAction, audit.Successful, auditParams); auditErr != nil { - handleMetadataErr(w, auditErr) - return - } - setJSONContentType(w) if _, err = w.Write(b); err != nil { log.Event(ctx, "getMetadata endpoint: failed to write bytes to response", log.ERROR, log.Error(err), logData) diff --git a/api/metadata_test.go b/api/metadata_test.go index 366f3b20..79107cd9 100644 --- a/api/metadata_test.go +++ b/api/metadata_test.go @@ -11,10 +11,7 @@ import ( errs "github.com/ONSdigital/dp-dataset-api/apierrors" "github.com/ONSdigital/dp-dataset-api/mocks" "github.com/ONSdigital/dp-dataset-api/models" - "github.com/ONSdigital/dp-dataset-api/store/datastoretest" - "github.com/ONSdigital/go-ns/audit" - "github.com/ONSdigital/go-ns/audit/auditortest" - "github.com/ONSdigital/go-ns/common" + storetest "github.com/ONSdigital/dp-dataset-api/store/datastoretest" . "github.com/smartystreets/goconvey/convey" ) @@ -42,8 +39,7 @@ func TestGetMetadataReturnsOk(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) @@ -54,12 +50,6 @@ func TestGetMetadataReturnsOk(t *testing.T) { So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) - auditParams := common.Params{"dataset_id": "123", "edition": "2017", "version": "1"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getMetadataAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getMetadataAction, Result: audit.Successful, Params: auditParams}, - ) - bytes, err := ioutil.ReadAll(w.Body) if err != nil { os.Exit(1) @@ -110,8 +100,7 @@ func TestGetMetadataReturnsOk(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) @@ -122,12 +111,6 @@ func TestGetMetadataReturnsOk(t *testing.T) { So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) - auditParams := common.Params{"dataset_id": "123", "edition": "2017", "version": "1"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getMetadataAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getMetadataAction, Result: audit.Successful, Params: auditParams}, - ) - bytes, err := ioutil.ReadAll(w.Body) if err != nil { os.Exit(1) @@ -168,8 +151,7 @@ func TestGetMetadataReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusInternalServerError) @@ -180,12 +162,6 @@ func TestGetMetadataReturnsError(t *testing.T) { So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 0) - - auditParams := common.Params{"dataset_id": "123", "edition": "2017", "version": "1"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getMetadataAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getMetadataAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When the dataset document cannot be found return status not found", t, func() { @@ -204,8 +180,7 @@ func TestGetMetadataReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -215,12 +190,6 @@ func TestGetMetadataReturnsError(t *testing.T) { So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 0) - - auditParams := common.Params{"dataset_id": "123", "edition": "2017", "version": "1"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getMetadataAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getMetadataAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When the dataset document has no current sub document return status not found", t, func() { @@ -246,8 +215,7 @@ func TestGetMetadataReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -258,12 +226,6 @@ func TestGetMetadataReturnsError(t *testing.T) { So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 0) - - auditParams := common.Params{"dataset_id": "123", "edition": "2017", "version": "1"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getMetadataAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getMetadataAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When the edition document cannot be found for version return status not found", t, func() { @@ -288,8 +250,7 @@ func TestGetMetadataReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -301,12 +262,6 @@ func TestGetMetadataReturnsError(t *testing.T) { So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) - - auditParams := common.Params{"dataset_id": "123", "edition": "2017", "version": "1"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getMetadataAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getMetadataAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When the version document cannot be found return status not found", t, func() { @@ -330,8 +285,7 @@ func TestGetMetadataReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -343,12 +297,6 @@ func TestGetMetadataReturnsError(t *testing.T) { So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 0) So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 0) - - auditParams := common.Params{"dataset_id": "123", "edition": "2017", "version": "1"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getMetadataAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getMetadataAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When the version document state is invalid return an internal server error", t, func() { @@ -374,8 +322,7 @@ func TestGetMetadataReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) assertInternalServerErr(w) @@ -385,267 +332,6 @@ func TestGetMetadataReturnsError(t *testing.T) { So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) - - auditParams := common.Params{"dataset_id": "123", "edition": "2017", "version": "1"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getMetadataAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getMetadataAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) -} - -func TestGetMetadataAuditingErrors(t *testing.T) { - auditParams := common.Params{"dataset_id": "123", "edition": "2017", "version": "1"} - - versionDoc := createPublishedVersionDoc() - - Convey("given auditing action attempted returns an error", t, func() { - auditor := auditortest.NewErroring(getMetadataAction, audit.Attempted) - - Convey("when get metadata is called", func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123/editions/2017/versions/1/metadata", nil) - w := httptest.NewRecorder() - - mockedDataStore := &storetest.StorerMock{} - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - Convey("then a 500 status is returned", func() { - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - - So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 0) - So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 0) - So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{ - Action: getMetadataAction, - Result: audit.Attempted, - Params: auditParams, - }, - ) - }) - }) - }) - - Convey("given auditing action unsuccessful returns an error", t, func() { - auditor := auditortest.NewErroring(getMetadataAction, audit.Unsuccessful) - - Convey("when datastore getDataset returns dataset not found error", func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123/editions/2017/versions/1/metadata", nil) - w := httptest.NewRecorder() - - mockedDataStore := &storetest.StorerMock{ - GetDatasetFunc: func(ID string) (*models.DatasetUpdate, error) { - return nil, errs.ErrDatasetNotFound - }, - GetVersionFunc: func(datasetID, edition, version, state string) (*models.Version, error) { - return versionDoc, nil - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - Convey("then a 500 status is returned", func() { - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - - So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) - So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getMetadataAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getMetadataAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) - }) - - Convey("when dataset.current is empty", func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123/editions/2017/versions/1/metadata", nil) - w := httptest.NewRecorder() - - mockedDataStore := &storetest.StorerMock{ - GetDatasetFunc: func(ID string) (*models.DatasetUpdate, error) { - return &models.DatasetUpdate{}, nil - }, - GetVersionFunc: func(datasetID, edition, version, state string) (*models.Version, error) { - return versionDoc, nil - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - Convey("then a 500 status is returned", func() { - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - - So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) - So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getMetadataAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getMetadataAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) - }) - - Convey("when dataset edition does not exist", func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123/editions/2017/versions/1/metadata", nil) - w := httptest.NewRecorder() - - mockedDataStore := &storetest.StorerMock{ - GetDatasetFunc: func(ID string) (*models.DatasetUpdate, error) { - return createDatasetDoc(), nil - }, - CheckEditionExistsFunc: func(ID string, editionID string, state string) error { - return errs.ErrEditionNotFound - }, - GetVersionFunc: func(datasetID string, editionID string, version string, state string) (*models.Version, error) { - return versionDoc, nil - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - Convey("then a 500 status is returned", func() { - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - - So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getMetadataAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getMetadataAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) - }) - - Convey("when dataset version does not exist", func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123/editions/2017/versions/1/metadata", nil) - w := httptest.NewRecorder() - - mockedDataStore := &storetest.StorerMock{ - GetVersionFunc: func(datasetID string, editionID string, version string, state string) (*models.Version, error) { - return nil, errs.ErrVersionNotFound - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - Convey("then a 500 status is returned", func() { - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - - So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getMetadataAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getMetadataAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) - }) - - Convey("when version not published", func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123/editions/2017/versions/1/metadata", nil) - w := httptest.NewRecorder() - versionDoc := createUnpublishedVersionDoc() - - mockedDataStore := &storetest.StorerMock{ - GetDatasetFunc: func(ID string) (*models.DatasetUpdate, error) { - return createDatasetDoc(), nil - }, - CheckEditionExistsFunc: func(ID string, editionID string, state string) error { - return nil - }, - GetVersionFunc: func(datasetID string, editionID string, version string, state string) (*models.Version, error) { - return versionDoc, nil - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - Convey("then a 500 status is returned", func() { - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - - So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) - So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getMetadataAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getMetadataAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) - }) - }) - - Convey("given auditing action successful returns an error", t, func() { - auditor := auditortest.NewErroring(getMetadataAction, audit.Successful) - - Convey("when get metadata is called", func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123/editions/2017/versions/1/metadata", nil) - w := httptest.NewRecorder() - - mockedDataStore := &storetest.StorerMock{ - GetDatasetFunc: func(ID string) (*models.DatasetUpdate, error) { - return createDatasetDoc(), nil - }, - CheckEditionExistsFunc: func(ID string, editionID string, state string) error { - return nil - }, - GetVersionFunc: func(datasetID string, editionID string, version string, state string) (*models.Version, error) { - return createPublishedVersionDoc(), nil - }, - } - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - Convey("then a 500 status is returned", func() { - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - - So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) - So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getMetadataAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getMetadataAction, Result: audit.Successful, Params: auditParams}, - ) - }) - }) }) } diff --git a/api/observation.go b/api/observation.go index 7a87d507..699bc08c 100644 --- a/api/observation.go +++ b/api/observation.go @@ -14,8 +14,6 @@ import ( errs "github.com/ONSdigital/dp-dataset-api/apierrors" "github.com/ONSdigital/dp-dataset-api/models" "github.com/ONSdigital/dp-graph/v2/observation" - "github.com/ONSdigital/go-ns/audit" - "github.com/ONSdigital/go-ns/common" "github.com/ONSdigital/log.go/log" "github.com/gorilla/mux" "github.com/pkg/errors" @@ -75,14 +73,7 @@ func (api *DatasetAPI) getObservations(w http.ResponseWriter, r *http.Request) { datasetID := vars["dataset_id"] edition := vars["edition"] version := vars["version"] - - auditParams := common.Params{"dataset_id": datasetID, "edition": edition, "version": version} - logData := audit.ToLogData(auditParams) - - if auditErr := api.auditor.Record(ctx, getObservationsAction, audit.Attempted, auditParams); auditErr != nil { - handleObservationsErrorType(ctx, w, auditErr, logData) - return - } + logData := log.Data{"dataset_id": datasetID, "edition": edition, "version": version} observationsDoc, err := func() (*models.ObservationsDoc, error) { // get dataset document @@ -166,18 +157,10 @@ func (api *DatasetAPI) getObservations(w http.ResponseWriter, r *http.Request) { }() if err != nil { - if auditErr := api.auditor.Record(ctx, getObservationsAction, audit.Unsuccessful, auditParams); auditErr != nil { - err = auditErr - } handleObservationsErrorType(ctx, w, err, logData) return } - if auditErr := api.auditor.Record(ctx, getObservationsAction, audit.Successful, auditParams); auditErr != nil { - handleObservationsErrorType(ctx, w, auditErr, logData) - return - } - setJSONContentType(w) // The ampersand "&" is escaped to "\u0026" to keep some browsers from diff --git a/api/observation_test.go b/api/observation_test.go index c38332b5..ba3ad324 100644 --- a/api/observation_test.go +++ b/api/observation_test.go @@ -17,9 +17,6 @@ import ( storetest "github.com/ONSdigital/dp-dataset-api/store/datastoretest" "github.com/ONSdigital/dp-graph/v2/observation" observationtest "github.com/ONSdigital/dp-graph/v2/observation/observationtest" - "github.com/ONSdigital/go-ns/audit" - "github.com/ONSdigital/go-ns/audit/auditortest" - "github.com/ONSdigital/go-ns/common" "github.com/ONSdigital/log.go/log" . "github.com/smartystreets/goconvey/convey" ) @@ -97,8 +94,7 @@ func TestGetObservationsReturnsOK(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) Convey("When request contains query parameters where the dimension name is in lower casing", func() { r := httptest.NewRequest("GET", "http://localhost:8080/datasets/cpih012/editions/2017/versions/1/observations?time=16-Aug&aggregate=cpi1dim1S40403&geography=K02000001", nil) @@ -115,12 +111,6 @@ func TestGetObservationsReturnsOK(t *testing.T) { So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) So(len(mockedDataStore.StreamCSVRowsCalls()), ShouldEqual, 1) So(len(mockRowReader.ReadCalls()), ShouldEqual, 3) - - auditParams := common.Params{"dataset_id": "cpih012", "edition": "2017", "version": "1"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getObservationsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getObservationsAction, Result: audit.Successful, Params: auditParams}, - ) }) Convey("When request contains query parameters where the dimension name is in upper casing", func() { @@ -136,12 +126,6 @@ func TestGetObservationsReturnsOK(t *testing.T) { So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) So(len(mockedDataStore.StreamCSVRowsCalls()), ShouldEqual, 1) So(len(mockRowReader.ReadCalls()), ShouldEqual, 3) - - auditParams := common.Params{"dataset_id": "cpih012", "edition": "2017", "version": "1"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getObservationsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getObservationsAction, Result: audit.Successful, Params: auditParams}, - ) }) }) @@ -211,8 +195,7 @@ func TestGetObservationsReturnsOK(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) @@ -225,12 +208,6 @@ func TestGetObservationsReturnsOK(t *testing.T) { So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) So(len(mockedDataStore.StreamCSVRowsCalls()), ShouldEqual, 1) So(len(mockRowReader.ReadCalls()), ShouldEqual, 4) - - auditParams := common.Params{"dataset_id": "cpih012", "edition": "2017", "version": "1"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getObservationsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getObservationsAction, Result: audit.Successful, Params: auditParams}, - ) }) } @@ -247,8 +224,7 @@ func TestGetObservationsReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusInternalServerError) @@ -258,12 +234,6 @@ func TestGetObservationsReturnsError(t *testing.T) { So(permissions.Required.Calls, ShouldEqual, 0) So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 0) - - auditParams := common.Params{"dataset_id": "cpih012", "edition": "2017", "version": "1"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getObservationsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getObservationsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When the dataset does not exist return status not found", t, func() { @@ -277,8 +247,7 @@ func TestGetObservationsReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -288,12 +257,6 @@ func TestGetObservationsReturnsError(t *testing.T) { So(permissions.Required.Calls, ShouldEqual, 0) So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 0) - - auditParams := common.Params{"dataset_id": "cpih012", "edition": "2017", "version": "1"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getObservationsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getObservationsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When the dataset exists but is unpublished return status not found", t, func() { @@ -307,8 +270,7 @@ func TestGetObservationsReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -318,12 +280,6 @@ func TestGetObservationsReturnsError(t *testing.T) { So(permissions.Required.Calls, ShouldEqual, 0) So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 0) - - auditParams := common.Params{"dataset_id": "cpih012", "edition": "2017", "version": "1"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getObservationsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getObservationsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When the edition of a dataset does not exist return status not found", t, func() { @@ -340,8 +296,7 @@ func TestGetObservationsReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -352,12 +307,6 @@ func TestGetObservationsReturnsError(t *testing.T) { So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetVersionsCalls()), ShouldEqual, 0) - - auditParams := common.Params{"dataset_id": "cpih012", "edition": "2017", "version": "1"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getObservationsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getObservationsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When version does not exist for an edition of a dataset returns status not found", t, func() { @@ -377,8 +326,7 @@ func TestGetObservationsReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) So(w.Body.String(), ShouldContainSubstring, errs.ErrVersionNotFound.Error()) @@ -388,12 +336,6 @@ func TestGetObservationsReturnsError(t *testing.T) { So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) - - auditParams := common.Params{"dataset_id": "cpih012", "edition": "2017", "version": "1"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getObservationsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getObservationsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When an unpublished version has an incorrect state for an edition of a dataset return an internal error", t, func() { @@ -413,8 +355,7 @@ func TestGetObservationsReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) assertInternalServerErr(w) @@ -423,12 +364,6 @@ func TestGetObservationsReturnsError(t *testing.T) { So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) - - auditParams := common.Params{"dataset_id": "cpih012", "edition": "2017", "version": "1"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getObservationsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getObservationsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When a version document has not got a headers field return an internal server error", t, func() { @@ -451,8 +386,7 @@ func TestGetObservationsReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusInternalServerError) @@ -462,12 +396,6 @@ func TestGetObservationsReturnsError(t *testing.T) { So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) - - auditParams := common.Params{"dataset_id": "cpih012", "edition": "2017", "version": "1"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getObservationsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getObservationsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When a version document has not got any dimensions field return an internal server error", t, func() { @@ -490,8 +418,7 @@ func TestGetObservationsReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusInternalServerError) @@ -501,12 +428,6 @@ func TestGetObservationsReturnsError(t *testing.T) { So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) - - auditParams := common.Params{"dataset_id": "cpih012", "edition": "2017", "version": "1"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getObservationsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getObservationsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When the first header in array does not describe the header row correctly return internal error", t, func() { @@ -530,8 +451,7 @@ func TestGetObservationsReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) assertInternalServerErr(w) @@ -540,12 +460,6 @@ func TestGetObservationsReturnsError(t *testing.T) { So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) - - auditParams := common.Params{"dataset_id": "cpih012", "edition": "2017", "version": "1"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getObservationsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getObservationsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When an invalid query parameter is set in request return 400 bad request with an error message containing a list of incorrect query parameters", t, func() { @@ -569,8 +483,7 @@ func TestGetObservationsReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusBadRequest) @@ -581,12 +494,6 @@ func TestGetObservationsReturnsError(t *testing.T) { So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) - - auditParams := common.Params{"dataset_id": "cpih012", "edition": "2017", "version": "1"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getObservationsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getObservationsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When there is a missing query parameter that is expected to be set in request return 400 bad request with an error message containing a list of missing query parameters", t, func() { @@ -610,8 +517,7 @@ func TestGetObservationsReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusBadRequest) @@ -622,12 +528,6 @@ func TestGetObservationsReturnsError(t *testing.T) { So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) - - auditParams := common.Params{"dataset_id": "cpih012", "edition": "2017", "version": "1"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getObservationsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getObservationsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When there are too many query parameters that are set to wildcard (*) value request returns 400 bad request", t, func() { @@ -652,8 +552,7 @@ func TestGetObservationsReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusBadRequest) @@ -664,12 +563,6 @@ func TestGetObservationsReturnsError(t *testing.T) { So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) - - auditParams := common.Params{"dataset_id": "cpih012", "edition": "2017", "version": "1"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getObservationsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getObservationsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When requested query does not find a unique observation return no observations found", t, func() { @@ -697,8 +590,7 @@ func TestGetObservationsReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -710,12 +602,6 @@ func TestGetObservationsReturnsError(t *testing.T) { So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) So(len(mockedDataStore.StreamCSVRowsCalls()), ShouldEqual, 1) - - auditParams := common.Params{"dataset_id": "cpih012", "edition": "2017", "version": "1"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getObservationsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getObservationsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When requested query has a multi-valued dimension return bad request", t, func() { @@ -763,8 +649,7 @@ func TestGetObservationsReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusBadRequest) @@ -776,12 +661,6 @@ func TestGetObservationsReturnsError(t *testing.T) { So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) So(len(mockedDataStore.StreamCSVRowsCalls()), ShouldEqual, 0) - - auditParams := common.Params{"dataset_id": "cpih012", "edition": "2017", "version": "1"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getObservationsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getObservationsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) } @@ -981,285 +860,6 @@ func TestExtractQueryParameters(t *testing.T) { }) } -func TestGetObservationAuditAttemptedError(t *testing.T) { - Convey("given audit action attempted returns an error", t, func() { - auditor := auditortest.NewErroring(getObservationsAction, audit.Attempted) - - mockedDataStore := &storetest.StorerMock{} - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - - Convey("when get observation is called", func() { - r := httptest.NewRequest("GET", "http://localhost:8080/datasets/cpih012/editions/2017/versions/1/observations?time=16-Aug&aggregate=cpi1dim1S40403&geography=K02000001", nil) - w := httptest.NewRecorder() - - api.Router.ServeHTTP(w, r) - - Convey("then a 500 response status is returned", func() { - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 0) - So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 0) - So(len(mockedDataStore.GetVersionsCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{ - Action: getObservationsAction, - Result: audit.Attempted, - Params: common.Params{"dataset_id": "cpih012", "edition": "2017", "version": "1"}}, - ) - }) - }) - }) -} - -func TestGetObservationAuditUnsuccessfulError(t *testing.T) { - auditParams := common.Params{"dataset_id": "cpih012", "edition": "2017", "version": "1"} - - Convey("given audit action unsuccessful returns an error", t, func() { - - Convey("when datastore.getDataset returns an error", func() { - auditor := auditortest.NewErroring(getObservationsAction, audit.Unsuccessful) - - mockedDataStore := &storetest.StorerMock{ - GetDatasetFunc: func(string) (*models.DatasetUpdate, error) { - return nil, errs.ErrDatasetNotFound - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - r := httptest.NewRequest("GET", "http://localhost:8080/datasets/cpih012/editions/2017/versions/1/observations?time=16-Aug&aggregate=cpi1dim1S40403&geography=K02000001", nil) - w := httptest.NewRecorder() - - api.Router.ServeHTTP(w, r) - - Convey("then a 500 response status is returned", func() { - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) - So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 0) - So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 0) - So(len(mockedDataStore.StreamCSVRowsCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getObservationsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getObservationsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) - }) - - Convey("when datastore.getEdition returns an error", func() { - auditor := auditortest.NewErroring(getObservationsAction, audit.Unsuccessful) - - mockedDataStore := &storetest.StorerMock{ - GetDatasetFunc: func(string) (*models.DatasetUpdate, error) { - return &models.DatasetUpdate{Current: &models.Dataset{State: models.PublishedState}}, nil - }, - CheckEditionExistsFunc: func(ID string, editionID string, state string) error { - return errs.ErrEditionNotFound - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - r := httptest.NewRequest("GET", "http://localhost:8080/datasets/cpih012/editions/2017/versions/1/observations?time=16-Aug&aggregate=cpi1dim1S40403&geography=K02000001", nil) - w := httptest.NewRecorder() - - api.Router.ServeHTTP(w, r) - - Convey("then a 500 response status is returned", func() { - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) - So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 0) - So(len(mockedDataStore.StreamCSVRowsCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getObservationsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getObservationsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) - }) - - Convey("when datastore.getVersion returns an error", func() { - auditor := auditortest.NewErroring(getObservationsAction, audit.Unsuccessful) - - mockedDataStore := &storetest.StorerMock{ - GetDatasetFunc: func(string) (*models.DatasetUpdate, error) { - return &models.DatasetUpdate{Current: &models.Dataset{State: models.PublishedState}}, nil - }, - CheckEditionExistsFunc: func(ID string, editionID string, state string) error { - return nil - }, - GetVersionFunc: func(datasetID string, editionID string, version string, state string) (*models.Version, error) { - return nil, errs.ErrVersionNotFound - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - r := httptest.NewRequest("GET", "http://localhost:8080/datasets/cpih012/editions/2017/versions/1/observations?time=16-Aug&aggregate=cpi1dim1S40403&geography=K02000001", nil) - w := httptest.NewRecorder() - - api.Router.ServeHTTP(w, r) - - Convey("then a 500 response status is returned", func() { - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) - So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) - So(len(mockedDataStore.StreamCSVRowsCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getObservationsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getObservationsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) - }) - - Convey("when the version does not have no header data", func() { - auditor := auditortest.NewErroring(getObservationsAction, audit.Unsuccessful) - - mockedDataStore := &storetest.StorerMock{ - GetDatasetFunc: func(string) (*models.DatasetUpdate, error) { - return &models.DatasetUpdate{Current: &models.Dataset{State: models.PublishedState}}, nil - }, - CheckEditionExistsFunc: func(ID string, editionID string, state string) error { - return nil - }, - GetVersionFunc: func(datasetID string, editionID string, version string, state string) (*models.Version, error) { - return &models.Version{}, nil - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - r := httptest.NewRequest("GET", "http://localhost:8080/datasets/cpih012/editions/2017/versions/1/observations?time=16-Aug&aggregate=cpi1dim1S40403&geography=K02000001", nil) - w := httptest.NewRecorder() - - api.Router.ServeHTTP(w, r) - - Convey("then a 500 response status is returned", func() { - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) - So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) - So(len(mockedDataStore.StreamCSVRowsCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getObservationsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getObservationsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) - }) - }) -} - -func TestGetObservationAuditSuccessfulError(t *testing.T) { - Convey("given audit action successful returns an error", t, func() { - auditor := auditortest.NewErroring(getObservationsAction, audit.Successful) - - Convey("when get observations is called with a valid request", func() { - - dimensions := []models.Dimension{ - models.Dimension{ - Name: "aggregate", - HRef: "http://localhost:8081/code-lists/cpih1dim1aggid", - }, - models.Dimension{ - Name: "geography", - HRef: "http://localhost:8081/code-lists/uk-only", - }, - models.Dimension{ - Name: "time", - HRef: "http://localhost:8081/code-lists/time", - }, - } - usagesNotes := &[]models.UsageNote{models.UsageNote{Title: "data_marking", Note: "this marks the obsevation with a special character"}} - - count := 0 - mockRowReader := &observationtest.StreamRowReaderMock{ - ReadFunc: func() (string, error) { - count++ - if count == 1 { - return "v4_2,data_marking,confidence_interval,time,time,geography_code,geography,aggregate_code,aggregate", nil - } else if count == 2 { - return "146.3,p,2,Month,Aug-16,K02000001,,cpi1dim1G10100,01.1 Food", nil - } - return "", io.EOF - }, - CloseFunc: func(context.Context) error { - return nil - }, - } - - mockedDataStore := &storetest.StorerMock{ - GetDatasetFunc: func(string) (*models.DatasetUpdate, error) { - return &models.DatasetUpdate{Current: &models.Dataset{State: models.PublishedState}}, nil - }, - CheckEditionExistsFunc: func(datasetID, editionID, state string) error { - return nil - }, - GetVersionFunc: func(string, string, string, string) (*models.Version, error) { - return &models.Version{ - Dimensions: dimensions, - Headers: []string{"v4_2", "data_marking", "confidence_interval", "aggregate_code", "aggregate", "geography_code", "geography", "time", "time"}, - Links: &models.VersionLinks{ - Version: &models.LinkObject{ - HRef: "http://localhost:8080/datasets/cpih012/editions/2017/versions/1", - ID: "1", - }, - }, - State: models.PublishedState, - UsageNotes: usagesNotes, - }, nil - }, - StreamCSVRowsFunc: func(context.Context, string, string, *observation.DimensionFilters, *int) (observation.StreamRowReader, error) { - return mockRowReader, nil - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - r := httptest.NewRequest("GET", "http://localhost:8080/datasets/cpih012/editions/2017/versions/1/observations?time=16-Aug&aggregate=cpi1dim1S40403&geography=K02000001", nil) - w := httptest.NewRecorder() - - api.Router.ServeHTTP(w, r) - - Convey("then a 500 status response is returned", func() { - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 1) - So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) - So(len(mockedDataStore.StreamCSVRowsCalls()), ShouldEqual, 1) - - auditParams := common.Params{"dataset_id": "cpih012", "edition": "2017", "version": "1"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getObservationsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getObservationsAction, Result: audit.Successful, Params: auditParams}, - ) - }) - }) - }) -} - func getTestData(ctx context.Context, filename string) string { jsonBytes, err := ioutil.ReadFile("./observation_test_data/" + filename + ".json") if err != nil { diff --git a/api/publish_state_checker.go b/api/publish_state_checker.go index 8b551467..f5311300 100644 --- a/api/publish_state_checker.go +++ b/api/publish_state_checker.go @@ -9,9 +9,7 @@ import ( errs "github.com/ONSdigital/dp-dataset-api/apierrors" "github.com/ONSdigital/dp-dataset-api/models" "github.com/ONSdigital/dp-dataset-api/store" - "github.com/ONSdigital/go-ns/audit" - "github.com/ONSdigital/go-ns/common" - "github.com/ONSdigital/go-ns/request" + dphttp "github.com/ONSdigital/dp-net/http" "github.com/ONSdigital/log.go/log" "github.com/gorilla/mux" "github.com/pkg/errors" @@ -20,7 +18,6 @@ import ( // PublishCheck Checks if an version has been published type PublishCheck struct { Datastore store.Storer - Auditor audit.AuditorService } // Check wraps a HTTP handle. Checks that the state is not published @@ -33,18 +30,12 @@ func (d *PublishCheck) Check(handle func(http.ResponseWriter, *http.Request), ac edition := vars["edition"] version := vars["version"] data := log.Data{"dataset_id": datasetID, "edition": edition, "version": version} - auditParams := common.Params{"dataset_id": datasetID, "edition": edition, "version": version} currentVersion, err := d.Datastore.GetVersion(datasetID, edition, version, "") if err != nil { if err != errs.ErrVersionNotFound { log.Event(ctx, "errored whilst retrieving version resource", log.ERROR, log.Error(err), data) - - if auditErr := d.Auditor.Record(ctx, action, audit.Unsuccessful, auditParams); auditErr != nil { - err = errs.ErrInternalServer - } - - request.DrainBody(r) + dphttp.DrainBody(r) http.Error(w, err.Error(), http.StatusInternalServerError) return } @@ -67,14 +58,7 @@ func (d *PublishCheck) Check(handle func(http.ResponseWriter, *http.Request), ac versionDoc, err := models.CreateVersion(r.Body) if err != nil { log.Event(ctx, "failed to model version resource based on request", log.ERROR, log.Error(err), data) - - if auditErr := d.Auditor.Record(ctx, action, audit.Unsuccessful, auditParams); auditErr != nil { - request.DrainBody(r) - http.Error(w, errs.ErrInternalServer.Error(), http.StatusInternalServerError) - return - } - - request.DrainBody(r) + dphttp.DrainBody(r) http.Error(w, err.Error(), http.StatusBadRequest) return } @@ -110,14 +94,7 @@ func (d *PublishCheck) Check(handle func(http.ResponseWriter, *http.Request), ac b, err = json.Marshal(newVersion) if err != nil { log.Event(ctx, "failed to marshal new version resource based on request", log.ERROR, log.Error(err), data) - - if auditErr := d.Auditor.Record(ctx, action, audit.Unsuccessful, auditParams); auditErr != nil { - request.DrainBody(r) - http.Error(w, errs.ErrInternalServer.Error(), http.StatusInternalServerError) - return - } - - request.DrainBody(r) + dphttp.DrainBody(r) http.Error(w, err.Error(), http.StatusForbidden) return } @@ -139,13 +116,7 @@ func (d *PublishCheck) Check(handle func(http.ResponseWriter, *http.Request), ac err = errors.New("unable to update version as it has been published") data["version"] = currentVersion log.Event(ctx, "failed to update version", log.ERROR, log.Error(err), data) - if auditErr := d.Auditor.Record(ctx, action, audit.Unsuccessful, auditParams); auditErr != nil { - request.DrainBody(r) - http.Error(w, errs.ErrInternalServer.Error(), http.StatusInternalServerError) - return - } - - request.DrainBody(r) + dphttp.DrainBody(r) http.Error(w, err.Error(), http.StatusForbidden) return } diff --git a/api/versions.go b/api/versions.go index c3fddf4e..78c90f5e 100644 --- a/api/versions.go +++ b/api/versions.go @@ -9,14 +9,18 @@ import ( errs "github.com/ONSdigital/dp-dataset-api/apierrors" "github.com/ONSdigital/dp-dataset-api/models" - "github.com/ONSdigital/go-ns/audit" - "github.com/ONSdigital/go-ns/common" - "github.com/ONSdigital/go-ns/request" + dphttp "github.com/ONSdigital/dp-net/http" + dprequest "github.com/ONSdigital/dp-net/request" "github.com/ONSdigital/log.go/log" "github.com/gorilla/mux" "github.com/pkg/errors" ) +const ( + reqUser = "req_user" + reqCaller = "req_caller" +) + var ( // errors that map to a HTTP 404 response notFound = map[error]bool{ @@ -46,8 +50,8 @@ type VersionDetails struct { version string } -func (v VersionDetails) baseAuditParams() common.Params { - return common.Params{"dataset_id": v.datasetID, "edition": v.edition, "version": v.version} +func (v VersionDetails) baseLogData() log.Data { + return log.Data{"dataset_id": v.datasetID, "edition": v.edition, "version": v.version} } func (api *DatasetAPI) getVersions(w http.ResponseWriter, r *http.Request) { @@ -55,13 +59,7 @@ func (api *DatasetAPI) getVersions(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) datasetID := vars["dataset_id"] edition := vars["edition"] - auditParams := common.Params{"dataset_id": datasetID, "edition": edition} - logData := audit.ToLogData(auditParams) - - if auditErr := api.auditor.Record(ctx, getVersionsAction, audit.Attempted, auditParams); auditErr != nil { - handleVersionAPIErr(ctx, errs.ErrInternalServer, w, logData) - return - } + logData := log.Data{"dataset_id": datasetID, "edition": edition} b, err := func() ([]byte, error) { authorised := api.authenticate(r, logData) @@ -127,18 +125,10 @@ func (api *DatasetAPI) getVersions(w http.ResponseWriter, r *http.Request) { }() if err != nil { - if auditErr := api.auditor.Record(ctx, getVersionsAction, audit.Unsuccessful, auditParams); auditErr != nil { - err = auditErr - } handleVersionAPIErr(ctx, err, w, logData) return } - if auditErr := api.auditor.Record(ctx, getVersionsAction, audit.Successful, auditParams); auditErr != nil { - handleVersionAPIErr(ctx, auditErr, w, logData) - return - } - setJSONContentType(w) _, err = w.Write(b) if err != nil { @@ -154,13 +144,7 @@ func (api *DatasetAPI) getVersion(w http.ResponseWriter, r *http.Request) { datasetID := vars["dataset_id"] edition := vars["edition"] version := vars["version"] - auditParams := common.Params{"dataset_id": datasetID, "edition": edition, "version": version} - logData := audit.ToLogData(auditParams) - - if auditErr := api.auditor.Record(ctx, getVersionAction, audit.Attempted, auditParams); auditErr != nil { - handleVersionAPIErr(ctx, auditErr, w, logData) - return - } + logData := log.Data{"dataset_id": datasetID, "edition": edition, "version": version} b, getVersionErr := func() ([]byte, error) { authorised := api.authenticate(r, logData) @@ -221,18 +205,10 @@ func (api *DatasetAPI) getVersion(w http.ResponseWriter, r *http.Request) { }() if getVersionErr != nil { - if auditErr := api.auditor.Record(ctx, getVersionAction, audit.Unsuccessful, auditParams); auditErr != nil { - getVersionErr = auditErr - } handleVersionAPIErr(ctx, getVersionErr, w, logData) return } - if auditErr := api.auditor.Record(ctx, getVersionAction, audit.Successful, auditParams); auditErr != nil { - handleVersionAPIErr(ctx, auditErr, w, logData) - return - } - setJSONContentType(w) _, err := w.Write(b) if err != nil { @@ -244,7 +220,7 @@ func (api *DatasetAPI) getVersion(w http.ResponseWriter, r *http.Request) { func (api *DatasetAPI) putVersion(w http.ResponseWriter, r *http.Request) { - defer request.DrainBody(r) + defer dphttp.DrainBody(r) ctx := r.Context() vars := mux.Vars(r) @@ -289,7 +265,7 @@ func (api *DatasetAPI) putVersion(w http.ResponseWriter, r *http.Request) { func (api *DatasetAPI) detachVersion(w http.ResponseWriter, r *http.Request) { - defer request.DrainBody(r) + defer dphttp.DrainBody(r) ctx := r.Context() vars := mux.Vars(r) @@ -300,13 +276,7 @@ func (api *DatasetAPI) detachVersion(w http.ResponseWriter, r *http.Request) { edition := vars["edition"] version := vars["version"] - auditParams := common.Params{"dataset_id": datasetID, "edition": edition, "version": version} - logData := audit.ToLogData(auditParams) - - if auditErr := api.auditor.Record(ctx, detachVersionAction, audit.Attempted, auditParams); auditErr != nil { - handleVersionAPIErr(ctx, auditErr, w, logData) - return - } + logData := log.Data{"dataset_id": datasetID, "edition": edition, "version": version} err := func() error { @@ -375,26 +345,16 @@ func (api *DatasetAPI) detachVersion(w http.ResponseWriter, r *http.Request) { }() if err != nil { - - if auditErr := api.auditor.Record(ctx, detachVersionAction, audit.Unsuccessful, auditParams); auditErr != nil { - err = auditErr - } handleVersionAPIErr(ctx, err, w, logData) return } - if auditErr := api.auditor.Record(ctx, detachVersionAction, audit.Successful, auditParams); auditErr != nil { - handleVersionAPIErr(ctx, auditErr, w, logData) - return - } - w.WriteHeader(http.StatusOK) log.Event(ctx, "detachVersion endpoint: request successful", log.INFO, logData) } func (api *DatasetAPI) updateVersion(ctx context.Context, body io.ReadCloser, versionDetails VersionDetails) (*models.DatasetUpdate, *models.Version, *models.Version, error) { - ap := versionDetails.baseAuditParams() - data := audit.ToLogData(ap) + data := versionDetails.baseLogData() // attempt to update the version currentDataset, currentVersion, versionUpdate, err := func() (*models.DatasetUpdate, *models.Version, *models.Version, error) { @@ -440,29 +400,15 @@ func (api *DatasetAPI) updateVersion(ctx context.Context, body io.ReadCloser, ve // audit update unsuccessful if error if err != nil { - if auditErr := api.auditor.Record(ctx, updateVersionAction, audit.Unsuccessful, ap); auditErr != nil { - audit.LogActionFailure(ctx, updateVersionAction, audit.Unsuccessful, auditErr, data) - } return nil, nil, nil, err } - if auditErr := api.auditor.Record(ctx, updateVersionAction, audit.Successful, ap); auditErr != nil { - audit.LogActionFailure(ctx, updateVersionAction, audit.Successful, auditErr, data) - } - log.Event(ctx, "update version completed successfully", log.INFO, data) return currentDataset, currentVersion, versionUpdate, nil } func (api *DatasetAPI) publishVersion(ctx context.Context, currentDataset *models.DatasetUpdate, currentVersion *models.Version, versionDoc *models.Version, versionDetails VersionDetails) error { - ap := versionDetails.baseAuditParams() - data := audit.ToLogData(ap) - - if auditErr := api.auditor.Record(ctx, publishVersionAction, audit.Attempted, ap); auditErr != nil { - audit.LogActionFailure(ctx, publishVersionAction, audit.Attempted, auditErr, data) - return auditErr - } - + data := versionDetails.baseLogData() log.Event(ctx, "attempting to publish version", log.INFO, data) err := func() error { @@ -486,7 +432,14 @@ func (api *DatasetAPI) publishVersion(ctx context.Context, currentDataset *model } if err := api.dataStore.Backend.SetInstanceIsPublished(ctx, versionDoc.ID); err != nil { - audit.LogError(ctx, errors.WithMessage(err, "putVersion endpoint: failed to set instance node is_published"), data) + if user := dprequest.User(ctx); user != "" { + data[reqUser] = user + } + if caller := dprequest.Caller(ctx); caller != "" { + data[reqCaller] = caller + } + err := errors.WithMessage(err, "putVersion endpoint: failed to set instance node is_published") + log.Event(ctx, "failed to publish instance version", log.ERROR, log.Error(err), data) return err } @@ -511,28 +464,15 @@ func (api *DatasetAPI) publishVersion(ctx context.Context, currentDataset *model }() if err != nil { - if auditErr := api.auditor.Record(ctx, publishVersionAction, audit.Unsuccessful, ap); auditErr != nil { - audit.LogActionFailure(ctx, publishVersionAction, audit.Unsuccessful, auditErr, data) - } return err } - if auditErr := api.auditor.Record(ctx, publishVersionAction, audit.Successful, ap); auditErr != nil { - audit.LogActionFailure(ctx, publishVersionAction, audit.Successful, auditErr, data) - } - log.Event(ctx, "publish version completed successfully", log.INFO, data) return nil } func (api *DatasetAPI) associateVersion(ctx context.Context, currentVersion *models.Version, versionDoc *models.Version, versionDetails VersionDetails) error { - ap := versionDetails.baseAuditParams() - data := audit.ToLogData(ap) - - if auditErr := api.auditor.Record(ctx, associateVersionAction, audit.Attempted, ap); auditErr != nil { - audit.LogActionFailure(ctx, associateVersionAction, audit.Attempted, auditErr, data) - return auditErr - } + data := versionDetails.baseLogData() associateVersionErr := func() error { if err := api.dataStore.Backend.UpdateDatasetWithAssociation(versionDetails.datasetID, versionDoc.State, versionDoc); err != nil { @@ -552,16 +492,9 @@ func (api *DatasetAPI) associateVersion(ctx context.Context, currentVersion *mod }() if associateVersionErr != nil { - if auditErr := api.auditor.Record(ctx, associateVersionAction, audit.Unsuccessful, ap); auditErr != nil { - audit.LogActionFailure(ctx, associateVersionAction, audit.Unsuccessful, auditErr, data) - } return associateVersionErr } - if auditErr := api.auditor.Record(ctx, associateVersionAction, audit.Successful, ap); auditErr != nil { - audit.LogActionFailure(ctx, associateVersionAction, audit.Successful, auditErr, data) - } - log.Event(ctx, "associate version completed successfully", log.INFO, data) return associateVersionErr } diff --git a/api/versions_test.go b/api/versions_test.go index a4016e72..1cfd179a 100644 --- a/api/versions_test.go +++ b/api/versions_test.go @@ -18,9 +18,6 @@ import ( "github.com/ONSdigital/dp-dataset-api/mocks" "github.com/ONSdigital/dp-dataset-api/models" storetest "github.com/ONSdigital/dp-dataset-api/store/datastoretest" - "github.com/ONSdigital/go-ns/audit" - "github.com/ONSdigital/go-ns/audit/auditortest" - "github.com/ONSdigital/go-ns/common" "github.com/ONSdigital/log.go/log" "github.com/pkg/errors" . "github.com/smartystreets/goconvey/convey" @@ -51,8 +48,7 @@ func TestGetVersionsReturnsOK(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) @@ -61,18 +57,11 @@ func TestGetVersionsReturnsOK(t *testing.T) { So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetVersionsCalls()), ShouldEqual, 1) - - auditParams := common.Params{"dataset_id": "123-456", "edition": "678"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getVersionsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getVersionsAction, Result: audit.Successful, Params: auditParams}, - ) }) } func TestGetVersionsReturnsError(t *testing.T) { t.Parallel() - auditParams := common.Params{"dataset_id": "123-456", "edition": "678"} Convey("When the api cannot connect to datastore return an internal server error", t, func() { r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123-456/editions/678/versions", nil) @@ -85,8 +74,7 @@ func TestGetVersionsReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) assertInternalServerErr(w) @@ -95,11 +83,6 @@ func TestGetVersionsReturnsError(t *testing.T) { So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 0) So(len(mockedDataStore.GetVersionsCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getVersionsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getVersionsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When the dataset does not exist return status not found", t, func() { @@ -113,8 +96,7 @@ func TestGetVersionsReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -125,11 +107,6 @@ func TestGetVersionsReturnsError(t *testing.T) { So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 0) So(len(mockedDataStore.GetVersionsCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getVersionsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getVersionsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When the edition of a dataset does not exist return status not found", t, func() { @@ -146,8 +123,7 @@ func TestGetVersionsReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -158,11 +134,6 @@ func TestGetVersionsReturnsError(t *testing.T) { So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetVersionsCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getVersionsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getVersionsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When version does not exist for an edition of a dataset returns status not found", t, func() { @@ -183,8 +154,7 @@ func TestGetVersionsReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -195,11 +165,6 @@ func TestGetVersionsReturnsError(t *testing.T) { So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetVersionsCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getVersionsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getVersionsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When version is not published against an edition of a dataset return status not found", t, func() { @@ -219,8 +184,7 @@ func TestGetVersionsReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -231,11 +195,6 @@ func TestGetVersionsReturnsError(t *testing.T) { So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetVersionsCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getVersionsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getVersionsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When a published version has an incorrect state for an edition of a dataset return an internal error", t, func() { @@ -258,8 +217,7 @@ func TestGetVersionsReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusInternalServerError) @@ -270,236 +228,6 @@ func TestGetVersionsReturnsError(t *testing.T) { So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetVersionsCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getVersionsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getVersionsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) -} - -func TestGetVersionsAuditError(t *testing.T) { - t.Parallel() - auditParams := common.Params{"dataset_id": "123-456", "edition": "678"} - err := errors.New("error") - - Convey("when auditing get versions attempted action errors then a 500 status is returned", t, func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123-456/editions/678/versions", nil) - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{} - - auditor := auditortest.New() - auditor.RecordFunc = func(ctx context.Context, action string, result string, params common.Params) error { - return err - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 0) - So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 0) - So(len(mockedDataStore.GetVersionsCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getVersionsAction, Result: audit.Attempted, Params: auditParams}, - ) - }) - - Convey("when auditing check dataset exists error returns an error then a 500 status is returned", t, func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123-456/editions/678/versions", nil) - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - CheckDatasetExistsFunc: func(ID string, state string) error { - return err - }, - } - - auditor := auditortest.New() - auditor.RecordFunc = func(ctx context.Context, action string, result string, params common.Params) error { - if action == getVersionsAction && result == audit.Unsuccessful { - return errors.New("error") - } - return nil - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) - So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 0) - So(len(mockedDataStore.GetVersionsCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getVersionsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getVersionsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) - - Convey("when auditing check edition exists error returns an error then a 500 status is returned", t, func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123-456/editions/678/versions", nil) - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - CheckDatasetExistsFunc: func(ID string, state string) error { - return nil - }, - CheckEditionExistsFunc: func(ID string, editionID string, state string) error { - return err - }, - } - - auditor := auditortest.New() - auditor.RecordFunc = func(ctx context.Context, action string, result string, params common.Params) error { - if action == getVersionsAction && result == audit.Unsuccessful { - return errors.New("error") - } - return nil - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) - So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetVersionsCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getVersionsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getVersionsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) - - Convey("when auditing get versions error returns an error then a 500 status is returned", t, func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123-456/editions/678/versions", nil) - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - CheckDatasetExistsFunc: func(ID string, state string) error { - return nil - }, - CheckEditionExistsFunc: func(ID string, editionID string, state string) error { - return nil - }, - GetVersionsFunc: func(ctx context.Context, datasetID string, editionID string, state string) (*models.VersionResults, error) { - return nil, err - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - auditor := auditortest.NewErroring(getVersionAction, audit.Unsuccessful) - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) - So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetVersionsCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getVersionsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getVersionsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) - - Convey("when auditing invalid state returns an error then a 500 status is returned", t, func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123-456/editions/678/versions", nil) - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - CheckDatasetExistsFunc: func(ID string, state string) error { - return nil - }, - CheckEditionExistsFunc: func(ID string, editionID string, state string) error { - return nil - }, - GetVersionsFunc: func(ctx context.Context, datasetID string, editionID string, state string) (*models.VersionResults, error) { - return &models.VersionResults{ - Items: []models.Version{{State: "not valid"}}, - }, nil - }, - } - - auditor := auditortest.New() - auditor.RecordFunc = func(ctx context.Context, action string, result string, params common.Params) error { - if action == getVersionsAction && result == audit.Unsuccessful { - return errors.New("error") - } - return nil - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) - So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetVersionsCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getVersionsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getVersionsAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) - - Convey("when auditing get versions successful event errors then an 500 status is returned", t, func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123-456/editions/678/versions", nil) - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - CheckDatasetExistsFunc: func(datasetID, state string) error { - return nil - }, - CheckEditionExistsFunc: func(datasetID, editionID, state string) error { - return nil - }, - GetVersionsFunc: func(ctx context.Context, datasetID, editionID, state string) (*models.VersionResults, error) { - return &models.VersionResults{}, nil - }, - } - - auditor := auditortest.New() - auditor.RecordFunc = func(ctx context.Context, action string, result string, params common.Params) error { - if action == getVersionsAction && result == audit.Successful { - return errors.New("error") - } - return nil - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) - So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetVersionsCalls()), ShouldEqual, 1) - - auditParams := common.Params{"dataset_id": "123-456", "edition": "678"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getVersionsAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getVersionsAction, Result: audit.Successful, Params: auditParams}, - ) }) } @@ -531,8 +259,7 @@ func TestGetVersionReturnsOK(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) @@ -541,17 +268,10 @@ func TestGetVersionReturnsOK(t *testing.T) { So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) - - auditParams := common.Params{"dataset_id": "123-456", "edition": "678", "version": "1"} - auditor.AssertRecordCalls( - auditortest.Expected{Action: getVersionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getVersionAction, Result: audit.Successful, Params: auditParams}, - ) }) } func TestGetVersionReturnsError(t *testing.T) { - auditParams := common.Params{"dataset_id": "123-456", "edition": "678", "version": "1"} t.Parallel() Convey("When the api cannot connect to datastore return an internal server error", t, func() { r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123-456/editions/678/versions/1", nil) @@ -564,19 +284,13 @@ func TestGetVersionReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) assertInternalServerErr(w) So(datasetPermissions.Required.Calls, ShouldEqual, 1) So(permissions.Required.Calls, ShouldEqual, 0) So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getVersionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getVersionAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When the dataset does not exist for return status not found", t, func() { @@ -591,8 +305,7 @@ func TestGetVersionReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -603,11 +316,6 @@ func TestGetVersionReturnsError(t *testing.T) { So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 0) So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getVersionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getVersionAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When the edition of a dataset does not exist return status not found", t, func() { @@ -625,8 +333,7 @@ func TestGetVersionReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -637,11 +344,6 @@ func TestGetVersionReturnsError(t *testing.T) { So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getVersionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getVersionAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When version does not exist for an edition of a dataset return status not found", t, func() { @@ -662,8 +364,7 @@ func TestGetVersionReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -674,11 +375,6 @@ func TestGetVersionReturnsError(t *testing.T) { So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getVersionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getVersionAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When version is not published for an edition of a dataset return status not found", t, func() { @@ -692,254 +388,30 @@ func TestGetVersionReturnsError(t *testing.T) { return nil }, GetVersionFunc: func(datasetID, editionID, version, state string) (*models.Version, error) { - return nil, errs.ErrVersionNotFound - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - So(w.Code, ShouldEqual, http.StatusNotFound) - So(w.Body.String(), ShouldContainSubstring, errs.ErrVersionNotFound.Error()) - - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) - So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getVersionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getVersionAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) - - Convey("When an unpublished version has an incorrect state for an edition of a dataset return an internal error", t, func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123-456/editions/678/versions/1", nil) - r.Header.Add("internal_token", "coffee") - w := httptest.NewRecorder() - - mockedDataStore := &storetest.StorerMock{ - CheckDatasetExistsFunc: func(datasetID, state string) error { - return nil - }, - CheckEditionExistsFunc: func(datasetID, editionID, state string) error { - return nil - }, - GetVersionFunc: func(datasetID, editionID, version, state string) (*models.Version, error) { - return &models.Version{ - State: "gobbly-gook", - Links: &models.VersionLinks{ - Self: &models.LinkObject{}, - Version: &models.LinkObject{ - HRef: "href", - }, - }, - }, nil - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(w.Body.String(), ShouldContainSubstring, errs.ErrResourceState.Error()) - - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) - So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getVersionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getVersionAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) -} - -func TestGetVersionAuditErrors(t *testing.T) { - auditParams := common.Params{"dataset_id": "123-456", "edition": "678", "version": "1"} - t.Parallel() - Convey("When auditing get version action attempted errors then a 500 status is returned", t, func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123-456/editions/678/versions/1", nil) - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - CheckDatasetExistsFunc: func(datasetID, state string) error { - return errs.ErrInternalServer - }, - } - - auditor := auditortest.New() - auditor.RecordFunc = func(ctx context.Context, action string, result string, params common.Params) error { - if action == getVersionAction && result == audit.Attempted { - return errors.New("error") - } - return nil - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getVersionAction, Result: audit.Attempted, Params: auditParams}, - ) - }) - - Convey("When the dataset does not exist and audit errors then return a 500 status", t, func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123-456/editions/678/versions/1", nil) - r.Header.Add("internal_token", "coffee") - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - CheckDatasetExistsFunc: func(datasetID, state string) error { - return errs.ErrDatasetNotFound - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - auditor := auditortest.NewErroring(getVersionAction, audit.Unsuccessful) - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) - So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 0) - So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getVersionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getVersionAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) - - Convey("When the edition does not exist for a dataset and auditing errors then a 500 status", t, func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123-456/editions/678/versions/1", nil) - r.Header.Add("internal_token", "coffee") - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - CheckDatasetExistsFunc: func(datasetID, state string) error { - return nil - }, - CheckEditionExistsFunc: func(datasetID, editionID, state string) error { - return errs.ErrEditionNotFound - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - auditor := auditortest.NewErroring(getVersionAction, audit.Unsuccessful) - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 0) - So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) - So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getVersionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getVersionAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) - - Convey("When version does not exist for an edition of a dataset and auditing errors then a 500 status", t, func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123-456/editions/678/versions/1", nil) - r.Header.Add("internal_token", "coffee") - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - CheckDatasetExistsFunc: func(datasetID, state string) error { - return nil - }, - CheckEditionExistsFunc: func(datasetID, editionID, state string) error { - return nil - }, - GetVersionFunc: func(datasetID, editionID, version, state string) (*models.Version, error) { - return nil, errs.ErrVersionNotFound - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - auditor := auditortest.NewErroring(getVersionAction, audit.Unsuccessful) - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - - assertInternalServerErr(w) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) - So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) - So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getVersionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getVersionAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) - - Convey("When version does not exist for an edition of a dataset and auditing errors then a 500 status", t, func() { - r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123-456/editions/678/versions/1", nil) - r.Header.Add("internal_token", "coffee") - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - CheckDatasetExistsFunc: func(datasetID, state string) error { - return nil - }, - CheckEditionExistsFunc: func(datasetID, editionID, state string) error { - return nil - }, - GetVersionFunc: func(datasetID, editionID, version, state string) (*models.Version, error) { - return &models.Version{ - State: "indifferent", - Links: &models.VersionLinks{ - Self: &models.LinkObject{HRef: "self"}, - Version: &models.LinkObject{HRef: "version"}, - }, - }, nil + return nil, errs.ErrVersionNotFound }, } datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.NewErroring(getVersionAction, audit.Unsuccessful) - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) - assertInternalServerErr(w) + So(w.Code, ShouldEqual, http.StatusNotFound) + So(w.Body.String(), ShouldContainSubstring, errs.ErrVersionNotFound.Error()) + So(datasetPermissions.Required.Calls, ShouldEqual, 1) So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getVersionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getVersionAction, Result: audit.Unsuccessful, Params: auditParams}, - ) + So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) }) - Convey("when auditing a successful request to get a version errors then return a 500 status", t, func() { + Convey("When an unpublished version has an incorrect state for an edition of a dataset return an internal error", t, func() { r := httptest.NewRequest("GET", "http://localhost:22000/datasets/123-456/editions/678/versions/1", nil) - + r.Header.Add("internal_token", "coffee") w := httptest.NewRecorder() + mockedDataStore := &storetest.StorerMock{ CheckDatasetExistsFunc: func(datasetID, state string) error { return nil @@ -949,7 +421,7 @@ func TestGetVersionAuditErrors(t *testing.T) { }, GetVersionFunc: func(datasetID, editionID, version, state string) (*models.Version, error) { return &models.Version{ - State: models.EditionConfirmedState, + State: "gobbly-gook", Links: &models.VersionLinks{ Self: &models.LinkObject{}, Version: &models.LinkObject{ @@ -962,28 +434,21 @@ func TestGetVersionAuditErrors(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.NewErroring(getVersionAction, audit.Successful) - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) - assertInternalServerErr(w) + So(w.Code, ShouldEqual, http.StatusInternalServerError) + So(w.Body.String(), ShouldContainSubstring, errs.ErrResourceState.Error()) + So(datasetPermissions.Required.Calls, ShouldEqual, 1) So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) So(len(mockedDataStore.CheckDatasetExistsCalls()), ShouldEqual, 1) So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: getVersionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: getVersionAction, Result: audit.Successful, Params: auditParams}, - ) + So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) }) } func TestPutVersionReturnsSuccessfully(t *testing.T) { - auditParams := common.Params{"dataset_id": "123", "edition": "2017", "version": "1"} - auditParamsWithCallerIdentity := common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123", "edition": "2017", "version": "1"} - t.Parallel() Convey("When state is unchanged", t, func() { generatorMock := &mocks.DownloadsGeneratorMock{ @@ -1036,8 +501,7 @@ func TestPutVersionReturnsSuccessfully(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) @@ -1053,11 +517,6 @@ func TestPutVersionReturnsSuccessfully(t *testing.T) { So(len(mockedDataStore.UpdateDatasetWithAssociationCalls()), ShouldEqual, 0) So(len(generatorMock.GenerateCalls()), ShouldEqual, 0) - auditor.AssertRecordCalls( - auditortest.Expected{Action: updateVersionAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: updateVersionAction, Result: audit.Successful, Params: auditParams}, - ) - Convey("then the request body has been drained", func() { _, err = r.Body.Read(make([]byte, 1)) So(err, ShouldEqual, io.EOF) @@ -1100,8 +559,7 @@ func TestPutVersionReturnsSuccessfully(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) @@ -1117,11 +575,6 @@ func TestPutVersionReturnsSuccessfully(t *testing.T) { So(len(mockedDataStore.UpsertDatasetCalls()), ShouldEqual, 0) So(len(generatorMock.GenerateCalls()), ShouldEqual, 0) - auditor.AssertRecordCalls( - auditortest.Expected{Action: updateVersionAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: updateVersionAction, Result: audit.Successful, Params: auditParams}, - ) - Convey("then the request body has been drained", func() { _, err = r.Body.Read(make([]byte, 1)) So(err, ShouldEqual, io.EOF) @@ -1167,8 +620,7 @@ func TestPutVersionReturnsSuccessfully(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, generatorMock, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, generatorMock, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) ctx := context.Background() @@ -1194,13 +646,6 @@ func TestPutVersionReturnsSuccessfully(t *testing.T) { So(len(mockedDataStore.UpsertDatasetCalls()), ShouldEqual, 0) So(len(generatorMock.GenerateCalls()), ShouldEqual, 1) - auditor.AssertRecordCalls( - auditortest.Expected{Action: updateVersionAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: updateVersionAction, Result: audit.Successful, Params: auditParams}, - auditortest.Expected{Action: associateVersionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: associateVersionAction, Result: audit.Successful, Params: auditParams}, - ) - Convey("then the request body has been drained", func() { _, err = r.Body.Read(make([]byte, 1)) So(err, ShouldEqual, io.EOF) @@ -1300,8 +745,7 @@ func TestPutVersionReturnsSuccessfully(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, generatorMock, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, generatorMock, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) @@ -1317,13 +761,6 @@ func TestPutVersionReturnsSuccessfully(t *testing.T) { So(len(mockedDataStore.UpdateDatasetWithAssociationCalls()), ShouldEqual, 0) So(len(generatorMock.GenerateCalls()), ShouldEqual, 1) - auditor.AssertRecordCalls( - auditortest.Expected{Action: updateVersionAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: updateVersionAction, Result: audit.Successful, Params: auditParams}, - auditortest.Expected{Action: publishVersionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: publishVersionAction, Result: audit.Successful, Params: auditParams}, - ) - Convey("then the request body has been drained", func() { _, err = r.Body.Read(make([]byte, 1)) So(err, ShouldEqual, io.EOF) @@ -1337,10 +774,10 @@ func TestPutVersionReturnsSuccessfully(t *testing.T) { r, err := createRequestWithAuth("PUT", "http://localhost:22000/datasets/123/editions/2017/versions/1", bytes.NewBufferString(b)) So(err, ShouldBeNil) - updateVersionDownloadTest(r, auditParamsWithCallerIdentity, auditParams) + updateVersionDownloadTest(r) Convey("then the request body has been drained", func() { - _, err = r.Body.Read(make([]byte, 1)) + _, err := r.Body.Read(make([]byte, 1)) So(err, ShouldEqual, io.EOF) }) }) @@ -1351,7 +788,7 @@ func TestPutVersionReturnsSuccessfully(t *testing.T) { r, err := createRequestWithAuth("PUT", "http://localhost:22000/datasets/123/editions/2017/versions/1", bytes.NewBufferString(b)) So(err, ShouldBeNil) - updateVersionDownloadTest(r, auditParamsWithCallerIdentity, auditParams) + updateVersionDownloadTest(r) Convey("then the request body has been drained", func() { _, err = r.Body.Read(make([]byte, 1)) @@ -1361,7 +798,7 @@ func TestPutVersionReturnsSuccessfully(t *testing.T) { }) } -func updateVersionDownloadTest(r *http.Request, firstAuditParams, secondAuditParams common.Params) { +func updateVersionDownloadTest(r *http.Request) { w := httptest.NewRecorder() generatorMock := &mocks.DownloadsGeneratorMock{ @@ -1430,8 +867,7 @@ func updateVersionDownloadTest(r *http.Request, firstAuditParams, secondAuditPar datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, generatorMock, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, generatorMock, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) @@ -1446,18 +882,10 @@ func updateVersionDownloadTest(r *http.Request, firstAuditParams, secondAuditPar So(len(mockedDataStore.UpsertDatasetCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateDatasetWithAssociationCalls()), ShouldEqual, 0) So(len(generatorMock.GenerateCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: updateVersionAction, Result: audit.Attempted, Params: firstAuditParams}, - auditortest.Expected{Action: updateVersionAction, Result: audit.Successful, Params: secondAuditParams}, - ) } func TestPutVersionGenerateDownloadsError(t *testing.T) { Convey("given download generator returns an error", t, func() { - auditParams := common.Params{"dataset_id": "123", "edition": "2017", "version": "1"} - auditParamsWithCallerIdentity := common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123", "edition": "2017", "version": "1"} - mockedErr := errors.New("spectacular explosion") var v models.Version json.Unmarshal([]byte(versionAssociatedPayload), &v) @@ -1498,9 +926,8 @@ func TestPutVersionGenerateDownloadsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, mockDownloadGenerator, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, mockDownloadGenerator, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) Convey("then an internal server error response is returned", func() { @@ -1530,13 +957,6 @@ func TestPutVersionGenerateDownloadsError(t *testing.T) { So(genCalls[0].DatasetID, ShouldEqual, "123") So(genCalls[0].Edition, ShouldEqual, "2017") So(genCalls[0].Version, ShouldEqual, "1") - - auditor.AssertRecordCalls( - auditortest.Expected{Action: updateVersionAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: updateVersionAction, Result: audit.Successful, Params: auditParams}, - auditortest.Expected{Action: associateVersionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: associateVersionAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("then the request body has been drained", func() { @@ -1548,9 +968,6 @@ func TestPutVersionGenerateDownloadsError(t *testing.T) { } func TestPutEmptyVersion(t *testing.T) { - auditParams := common.Params{"dataset_id": "123", "edition": "2017", "version": "1"} - auditParamsWithCallerIdentity := common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123", "edition": "2017", "version": "1"} - var v models.Version json.Unmarshal([]byte(versionAssociatedPayload), &v) v.State = models.AssociatedState @@ -1580,8 +997,7 @@ func TestPutEmptyVersion(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) Convey("then a http status ok is returned", func() { @@ -1594,11 +1010,6 @@ func TestPutEmptyVersion(t *testing.T) { So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 2) So(len(mockedDataStore.UpdateVersionCalls()), ShouldEqual, 1) So(mockedDataStore.UpdateVersionCalls()[0].Version.Downloads, ShouldBeNil) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: updateVersionAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: updateVersionAction, Result: audit.Successful, Params: auditParams}, - ) }) }) }) @@ -1629,8 +1040,7 @@ func TestPutEmptyVersion(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) Convey("then a http status ok is returned", func() { @@ -1662,502 +1072,12 @@ func TestPutEmptyVersion(t *testing.T) { So(len(mockedDataStore.UpsertEditionCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateDatasetWithAssociationCalls()), ShouldEqual, 0) So(len(mockDownloadGenerator.GenerateCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: updateVersionAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: updateVersionAction, Result: audit.Successful, Params: auditParams}, - ) - }) - }) - }) -} - -func TestUpdateVersionAuditErrors(t *testing.T) { - auditParams := common.Params{"dataset_id": "123", "edition": "2017", "version": "1"} - auditParamsWithCallerIdentity := common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123", "edition": "2017", "version": "1"} - - t.Parallel() - Convey("given audit action attempted returns an error", t, func() { - auditor := auditortest.NewErroring(updateVersionAction, audit.Attempted) - - Convey("when updateVersion is called with a valid request", func() { - r, err := createRequestWithAuth("PUT", "http://localhost:22000/datasets/123/editions/2017/versions/1", bytes.NewBufferString(versionPayload)) - So(err, ShouldBeNil) - - w := httptest.NewRecorder() - - store := &storetest.StorerMock{} - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(store, nil, auditor, datasetPermissions, permissions) - - api.Router.ServeHTTP(w, r) - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) - - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 0) - - Convey("then an error is returned and updateVersion fails", func() { - // Check no calls have been made to the datastore - So(len(store.GetDatasetCalls()), ShouldEqual, 0) - So(len(store.CheckEditionExistsCalls()), ShouldEqual, 0) - So(len(store.GetVersionCalls()), ShouldEqual, 0) - So(len(store.UpdateVersionCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: updateVersionAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - ) - }) - - Convey("then the request body has been drained", func() { - _, err = r.Body.Read(make([]byte, 1)) - So(err, ShouldEqual, io.EOF) - }) - }) - }) - - currentVersion := &models.Version{ - ID: "789", - Links: &models.VersionLinks{ - Dataset: &models.LinkObject{ - HRef: "http://localhost:22000/datasets/123", - ID: "123", - }, - Dimensions: &models.LinkObject{ - HRef: "http://localhost:22000/datasets/123/editions/2017/versions/1/dimensions", - }, - Edition: &models.LinkObject{ - HRef: "http://localhost:22000/datasets/123/editions/2017", - ID: "456", - }, - Self: &models.LinkObject{ - HRef: "http://localhost:22000/datasets/123/editions/2017/versions/1", - }, - }, - ReleaseDate: "2017", - State: models.EditionConfirmedState, - } - - Convey("given audit action successful returns an error", t, func() { - auditor := auditortest.NewErroring(updateVersionAction, audit.Successful) - - Convey("when updateVersion is called with a valid request", func() { - - store := &storetest.StorerMock{ - GetDatasetFunc: func(datasetID string) (*models.DatasetUpdate, error) { - return &models.DatasetUpdate{}, nil - }, - CheckEditionExistsFunc: func(string, string, string) error { - return nil - }, - GetVersionFunc: func(string, string, string, string) (*models.Version, error) { - return currentVersion, nil - }, - UpdateVersionFunc: func(string, *models.Version) error { - return nil - }, - } - - var expectedUpdateVersion models.Version - err := json.Unmarshal([]byte(versionPayload), &expectedUpdateVersion) - So(err, ShouldBeNil) - expectedUpdateVersion.Downloads = currentVersion.Downloads - expectedUpdateVersion.Links = currentVersion.Links - expectedUpdateVersion.ID = currentVersion.ID - expectedUpdateVersion.State = models.EditionConfirmedState - - w := httptest.NewRecorder() - - r, err := createRequestWithAuth("PUT", "http://localhost:22000/datasets/123/editions/2017/versions/1", bytes.NewBufferString(versionPayload)) - So(err, ShouldBeNil) - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(store, nil, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - So(w.Code, ShouldEqual, http.StatusOK) - - Convey("then the expected audit events are recorded and the expected error is returned", func() { - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(store.GetDatasetCalls()), ShouldEqual, 1) - So(len(store.CheckEditionExistsCalls()), ShouldEqual, 1) - So(len(store.GetVersionCalls()), ShouldEqual, 2) - So(len(store.UpdateVersionCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: updateVersionAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: updateVersionAction, Result: audit.Successful, Params: auditParams}, - ) - }) - - Convey("then the request body has been drained", func() { - _, err = r.Body.Read(make([]byte, 1)) - So(err, ShouldEqual, io.EOF) - }) - }) - }) - - Convey("given audit action unsuccessful returns an error", t, func() { - auditor := auditortest.NewErroring(updateVersionAction, audit.Unsuccessful) - - Convey("when update version is unsuccessful", func() { - store := &storetest.StorerMock{ - GetVersionFunc: func(string, string, string, string) (*models.Version, error) { - return nil, errs.ErrVersionNotFound - }, - GetDatasetFunc: func(datasetID string) (*models.DatasetUpdate, error) { - return nil, errs.ErrDatasetNotFound - }, - } - r, err := createRequestWithAuth("PUT", "http://localhost:22000/datasets/123/editions/2017/versions/1", bytes.NewBufferString(versionPayload)) - So(err, ShouldBeNil) - - w := httptest.NewRecorder() - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(store, nil, auditor, datasetPermissions, permissions) - api.Router.ServeHTTP(w, r) - So(w.Code, ShouldEqual, http.StatusNotFound) - So(w.Body.String(), ShouldContainSubstring, errs.ErrDatasetNotFound.Error()) - So(datasetPermissions.Required.Calls, ShouldEqual, 1) - So(permissions.Required.Calls, ShouldEqual, 0) - - Convey("then the expected audit events are recorded and the expected error is returned", func() { - So(len(store.GetVersionCalls()), ShouldEqual, 1) - So(len(store.GetDatasetCalls()), ShouldEqual, 1) - So(len(store.CheckEditionExistsCalls()), ShouldEqual, 0) - So(len(store.UpdateVersionCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: updateVersionAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: updateVersionAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) - }) - }) -} - -func TestPublishVersionAuditErrors(t *testing.T) { - auditParams := common.Params{"dataset_id": "123", "edition": "2017", "version": "1"} - versionDetails := VersionDetails{ - datasetID: "123", - edition: "2017", - version: "1", - } - - Convey("given audit action attempted returns an error", t, func() { - auditor := auditortest.NewErroring(publishVersionAction, audit.Attempted) - - Convey("when publish version is called", func() { - store := &storetest.StorerMock{} - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(store, nil, auditor, datasetPermissions, permissions) - - err := api.publishVersion(context.Background(), nil, nil, nil, versionDetails) - So(err, ShouldNotBeNil) - - Convey("then the expected audit events are recorded and an error is returned", func() { - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 0) - auditor.AssertRecordCalls( - auditortest.Expected{Action: publishVersionAction, Result: audit.Attempted, Params: auditParams}, - ) - }) - }) - }) - - Convey("given audit action unsuccessful returns an error", t, func() { - auditor := auditortest.NewErroring(publishVersionAction, audit.Unsuccessful) - - Convey("when publish version returns an error", func() { - store := &storetest.StorerMock{ - GetEditionFunc: func(ID, editionID, state string) (*models.EditionUpdate, error) { - return nil, errs.ErrEditionNotFound - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(store, nil, auditor, datasetPermissions, permissions) - err := api.publishVersion(context.Background(), nil, nil, nil, versionDetails) - So(err, ShouldNotBeNil) - - Convey("then the expected audit events are recorded and the expected error is returned", func() { - So(len(store.GetEditionCalls()), ShouldEqual, 1) - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: publishVersionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: publishVersionAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) - }) - }) - - Convey("given audit action successful returns an error", t, func() { - auditor := auditortest.NewErroring(publishVersionAction, audit.Successful) - - Convey("when publish version returns an error", func() { - store := &storetest.StorerMock{ - GetEditionFunc: func(string, string, string) (*models.EditionUpdate, error) { - return &models.EditionUpdate{ - ID: "123", - Next: &models.Edition{ - State: models.PublishedState, - Links: &models.EditionUpdateLinks{ - Self: &models.LinkObject{ - HRef: "http://localhost:22000/datasets/123/editions/2017", - }, - LatestVersion: &models.LinkObject{ - HRef: "http://localhost:22000/datasets/123/editions/2017/versions/1", - ID: "1", - }, - }, - }, - Current: &models.Edition{}, - }, nil - }, - UpsertEditionFunc: func(datasetID string, edition string, editionDoc *models.EditionUpdate) error { - return nil - }, - UpsertDatasetFunc: func(ID string, datasetDoc *models.DatasetUpdate) error { - return nil - }, - SetInstanceIsPublishedFunc: func(ctx context.Context, instanceID string) error { - return nil - }, - } - - currentDataset := &models.DatasetUpdate{ - ID: "123", - Next: &models.Dataset{Links: &models.DatasetLinks{}}, - Current: &models.Dataset{Links: &models.DatasetLinks{}}, - } - - currentVersion := &models.Version{ - ID: "789", - Links: &models.VersionLinks{ - Dataset: &models.LinkObject{ - HRef: "http://localhost:22000/datasets/123", - ID: "123", - }, - Dimensions: &models.LinkObject{ - HRef: "http://localhost:22000/datasets/123/editions/2017/versions/1/dimensions", - }, - Edition: &models.LinkObject{ - HRef: "http://localhost:22000/datasets/123/editions/2017", - ID: "456", - }, - Self: &models.LinkObject{ - HRef: "http://localhost:22000/datasets/123/editions/2017/versions/1", - }, - Version: &models.LinkObject{ - HRef: "", - ID: "1", - }, - }, - ReleaseDate: "2017-12-12", - State: models.EditionConfirmedState, - } - - var updateVersion models.Version - err := json.Unmarshal([]byte(versionPublishedPayload), &updateVersion) - So(err, ShouldBeNil) - updateVersion.Links = currentVersion.Links - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(store, nil, auditor, datasetPermissions, permissions) - - err = api.publishVersion(context.Background(), currentDataset, currentVersion, &updateVersion, versionDetails) - So(err, ShouldBeNil) - - Convey("then the expected audit events are recorded and the expected error is returned", func() { - So(len(store.GetEditionCalls()), ShouldEqual, 1) - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: publishVersionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: publishVersionAction, Result: audit.Successful, Params: auditParams}, - ) - }) - }) - }) -} - -func TestAssociateVersionAuditErrors(t *testing.T) { - auditParams := common.Params{"dataset_id": "123", "edition": "2018", "version": "1"} - currentVersion := &models.Version{ - ID: "789", - Links: &models.VersionLinks{ - Dataset: &models.LinkObject{ - HRef: "http://localhost:22000/datasets/123", - ID: "123", - }, - Dimensions: &models.LinkObject{ - HRef: "http://localhost:22000/datasets/123/editions/2017/versions/1/dimensions", - }, - Edition: &models.LinkObject{ - HRef: "http://localhost:22000/datasets/123/editions/2017", - ID: "456", - }, - Self: &models.LinkObject{ - HRef: "http://localhost:22000/datasets/123/editions/2017/versions/1", - }, - Version: &models.LinkObject{ - HRef: "", - }, - }, - ReleaseDate: "2017-12-12", - State: models.EditionConfirmedState, - } - - var versionDoc models.Version - json.Unmarshal([]byte(versionAssociatedPayload), &versionDoc) - - versionDetails := VersionDetails{ - datasetID: "123", - edition: "2018", - version: "1", - } - - expectedErr := errors.New("err") - - Convey("given audit action attempted returns an error", t, func() { - auditor := auditortest.NewErroring(associateVersionAction, audit.Attempted) - - Convey("when associate version is called", func() { - - store := &storetest.StorerMock{} - gen := &mocks.DownloadsGeneratorMock{} - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(store, gen, auditor, datasetPermissions, permissions) - - err := api.associateVersion(context.Background(), currentVersion, &versionDoc, versionDetails) - So(err, ShouldEqual, auditortest.ErrAudit) - - Convey("then the expected audit event is captured and the expected error is returned", func() { - So(len(store.UpdateDatasetWithAssociationCalls()), ShouldEqual, 0) - So(len(gen.GenerateCalls()), ShouldEqual, 0) - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: associateVersionAction, Result: audit.Attempted, Params: auditParams}, - ) - }) - }) - }) - - Convey("given audit action unsuccessful returns an error", t, func() { - auditor := auditortest.NewErroring(associateVersionAction, audit.Unsuccessful) - - Convey("when datastore.UpdateDatasetWithAssociation returns an error", func() { - store := &storetest.StorerMock{ - UpdateDatasetWithAssociationFunc: func(ID string, state string, version *models.Version) error { - return expectedErr - }, - } - gen := &mocks.DownloadsGeneratorMock{} - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(store, gen, auditor, datasetPermissions, permissions) - - err := api.associateVersion(context.Background(), currentVersion, &versionDoc, versionDetails) - So(err, ShouldEqual, expectedErr) - - Convey("then the expected audit event is captured and the expected error is returned", func() { - So(len(store.UpdateDatasetWithAssociationCalls()), ShouldEqual, 1) - So(len(gen.GenerateCalls()), ShouldEqual, 0) - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: associateVersionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: associateVersionAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) - }) - - Convey("when generating downloads returns an error", func() { - store := &storetest.StorerMock{ - UpdateDatasetWithAssociationFunc: func(ID string, state string, version *models.Version) error { - return nil - }, - } - gen := &mocks.DownloadsGeneratorMock{ - GenerateFunc: func(ctx context.Context, datasetID string, instanceID string, edition string, version string) error { - return expectedErr - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(store, gen, auditor, datasetPermissions, permissions) - - err := api.associateVersion(context.Background(), currentVersion, &versionDoc, versionDetails) - - Convey("then the expected audit event is captured and the expected error is returned", func() { - So(expectedErr.Error(), ShouldEqual, errors.Cause(err).Error()) - So(len(store.UpdateDatasetWithAssociationCalls()), ShouldEqual, 1) - So(len(gen.GenerateCalls()), ShouldEqual, 1) - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: associateVersionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: associateVersionAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) - }) - }) - - Convey("given audit action successful returns an error", t, func() { - auditor := auditortest.NewErroring(associateVersionAction, audit.Successful) - - Convey("when associateVersion is called", func() { - store := &storetest.StorerMock{ - UpdateDatasetWithAssociationFunc: func(ID string, state string, version *models.Version) error { - return nil - }, - } - gen := &mocks.DownloadsGeneratorMock{ - GenerateFunc: func(ctx context.Context, datasetID string, instanceID string, edition string, version string) error { - return nil - }, - } - - datasetPermissions := getAuthorisationHandlerMock() - permissions := getAuthorisationHandlerMock() - api := GetAPIWithMocks(store, gen, auditor, datasetPermissions, permissions) - err := api.associateVersion(context.Background(), currentVersion, &versionDoc, versionDetails) - So(err, ShouldBeNil) - - Convey("then the expected audit event is captured and the expected error is returned", func() { - So(len(store.UpdateDatasetWithAssociationCalls()), ShouldEqual, 1) - So(len(gen.GenerateCalls()), ShouldEqual, 1) - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: associateVersionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: associateVersionAction, Result: audit.Successful, Params: auditParams}, - ) }) }) }) } func TestPutVersionReturnsError(t *testing.T) { - auditParams := common.Params{"dataset_id": "123", "edition": "2017", "version": "1"} - auditParamsWithCallerIdentity := common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123", "edition": "2017", "version": "1"} t.Parallel() Convey("When the request contain malformed json a bad request status is returned", t, func() { generatorMock := &mocks.DownloadsGeneratorMock{ @@ -2183,8 +1103,7 @@ func TestPutVersionReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, generatorMock, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, generatorMock, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusBadRequest) @@ -2196,11 +1115,6 @@ func TestPutVersionReturnsError(t *testing.T) { So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 0) So(len(generatorMock.GenerateCalls()), ShouldEqual, 0) - auditor.AssertRecordCalls( - auditortest.Expected{Action: updateVersionAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: updateVersionAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - Convey("then the request body has been drained", func() { _, err = r.Body.Read(make([]byte, 1)) So(err, ShouldEqual, io.EOF) @@ -2231,8 +1145,7 @@ func TestPutVersionReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, generatorMock, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, generatorMock, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusInternalServerError) @@ -2244,11 +1157,6 @@ func TestPutVersionReturnsError(t *testing.T) { So(len(mockedDataStore.GetDatasetCalls()), ShouldEqual, 0) So(len(generatorMock.GenerateCalls()), ShouldEqual, 0) - auditor.AssertRecordCalls( - auditortest.Expected{Action: updateVersionAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: updateVersionAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - Convey("then the request body has been drained", func() { _, err = r.Body.Read(make([]byte, 1)) So(err, ShouldEqual, io.EOF) @@ -2282,8 +1190,7 @@ func TestPutVersionReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, generatorMock, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, generatorMock, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -2296,11 +1203,6 @@ func TestPutVersionReturnsError(t *testing.T) { So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 0) So(len(generatorMock.GenerateCalls()), ShouldEqual, 0) - auditor.AssertRecordCalls( - auditortest.Expected{Action: updateVersionAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: updateVersionAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - Convey("then the request body has been drained", func() { _, err = r.Body.Read(make([]byte, 1)) So(err, ShouldEqual, io.EOF) @@ -2334,8 +1236,7 @@ func TestPutVersionReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, generatorMock, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, generatorMock, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -2348,11 +1249,6 @@ func TestPutVersionReturnsError(t *testing.T) { So(len(mockedDataStore.CheckEditionExistsCalls()), ShouldEqual, 1) So(len(generatorMock.GenerateCalls()), ShouldEqual, 0) - auditor.AssertRecordCalls( - auditortest.Expected{Action: updateVersionAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: updateVersionAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - Convey("then the request body has been drained", func() { _, err = r.Body.Read(make([]byte, 1)) So(err, ShouldEqual, io.EOF) @@ -2389,8 +1285,7 @@ func TestPutVersionReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, generatorMock, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, generatorMock, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -2404,11 +1299,6 @@ func TestPutVersionReturnsError(t *testing.T) { So(len(mockedDataStore.UpdateVersionCalls()), ShouldEqual, 0) So(len(generatorMock.GenerateCalls()), ShouldEqual, 0) - auditor.AssertRecordCalls( - auditortest.Expected{Action: updateVersionAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: updateVersionAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - Convey("then the request body has been drained", func() { _, err = r.Body.Read(make([]byte, 1)) So(err, ShouldEqual, io.EOF) @@ -2437,8 +1327,7 @@ func TestPutVersionReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, generatorMock, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, generatorMock, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusUnauthorized) @@ -2448,10 +1337,6 @@ func TestPutVersionReturnsError(t *testing.T) { So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 0) So(len(generatorMock.GenerateCalls()), ShouldEqual, 0) - auditor.AssertRecordCalls( - auditortest.Expected{Action: updateVersionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: updateVersionAction, Result: audit.Unsuccessful, Params: auditParams}, - ) Convey("then the request body has been drained", func() { _, err = r.Body.Read(make([]byte, 1)) @@ -2485,8 +1370,7 @@ func TestPutVersionReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, generatorMock, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, generatorMock, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusForbidden) @@ -2497,11 +1381,6 @@ func TestPutVersionReturnsError(t *testing.T) { So(datasetPermissions.Required.Calls, ShouldEqual, 1) So(permissions.Required.Calls, ShouldEqual, 0) - auditor.AssertRecordCalls( - auditortest.Expected{Action: updateVersionAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: updateVersionAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - Convey("then the request body has been drained", func() { _, err = r.Body.Read(make([]byte, 1)) So(err, ShouldEqual, io.EOF) @@ -2538,8 +1417,7 @@ func TestPutVersionReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, generatorMock, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, generatorMock, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusBadRequest) @@ -2553,11 +1431,6 @@ func TestPutVersionReturnsError(t *testing.T) { So(len(mockedDataStore.UpdateVersionCalls()), ShouldEqual, 0) So(len(generatorMock.GenerateCalls()), ShouldEqual, 0) - auditor.AssertRecordCalls( - auditortest.Expected{Action: updateVersionAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: updateVersionAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - Convey("then the request body has been drained", func() { _, err = r.Body.Read(make([]byte, 1)) So(err, ShouldEqual, io.EOF) @@ -2664,8 +1537,7 @@ func TestPutVersionReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, generatorMock, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, generatorMock, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) @@ -2682,13 +1554,6 @@ func TestPutVersionReturnsError(t *testing.T) { So(len(mockedDataStore.UpdateDatasetWithAssociationCalls()), ShouldEqual, 0) So(len(generatorMock.GenerateCalls()), ShouldEqual, 0) - auditor.AssertRecordCalls( - auditortest.Expected{Action: updateVersionAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: updateVersionAction, Result: audit.Successful, Params: auditParams}, - auditortest.Expected{Action: publishVersionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: publishVersionAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - Convey("then the request body has been drained", func() { _, err = r.Body.Read(make([]byte, 1)) So(err, ShouldEqual, io.EOF) @@ -2821,8 +1686,6 @@ func TestDetachVersionReturnOK(t *testing.T) { return } - auditParams := common.Params{"dataset_id": "123", "edition": "2017", "version": "1"} - auditParamsWithCallerIdentity := common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123", "edition": "2017", "version": "1"} t.Parallel() Convey("A successful detach request against a version of a published dataset returns 200 OK response.", t, func() { @@ -2867,8 +1730,7 @@ func TestDetachVersionReturnOK(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, generatorMock, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, generatorMock, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) @@ -2883,12 +1745,6 @@ func TestDetachVersionReturnOK(t *testing.T) { So(len(mockedDataStore.UpsertEditionCalls()), ShouldEqual, 1) So(len(mockedDataStore.UpsertDatasetCalls()), ShouldEqual, 1) So(len(generatorMock.GenerateCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: detachVersionAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: detachVersionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: detachVersionAction, Result: audit.Successful, Params: auditParams}, - ) }) Convey("A successful detach request against a version of a unpublished dataset returns 200 OK response.", t, func() { @@ -2933,8 +1789,7 @@ func TestDetachVersionReturnOK(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, generatorMock, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, generatorMock, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) @@ -2949,12 +1804,6 @@ func TestDetachVersionReturnOK(t *testing.T) { So(len(mockedDataStore.UpsertEditionCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpsertDatasetCalls()), ShouldEqual, 0) So(len(generatorMock.GenerateCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: detachVersionAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: detachVersionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: detachVersionAction, Result: audit.Successful, Params: auditParams}, - ) }) } @@ -2967,8 +1816,6 @@ func TestDetachVersionReturnsError(t *testing.T) { return } - auditParams := common.Params{"dataset_id": "123", "edition": "2017", "version": "1"} - auditParamsWithCallerIdentity := common.Params{"caller_identity": "someone@ons.gov.uk", "dataset_id": "123", "edition": "2017", "version": "1"} t.Parallel() Convey("When the api cannot connect to datastore return an internal server error.", t, func() { @@ -2990,8 +1837,7 @@ func TestDetachVersionReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, generatorMock, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, generatorMock, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) @@ -3003,12 +1849,6 @@ func TestDetachVersionReturnsError(t *testing.T) { So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 0) So(len(mockedDataStore.GetEditionCalls()), ShouldEqual, 1) So(len(generatorMock.GenerateCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: detachVersionAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: detachVersionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: detachVersionAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When the provided edition cannot be found, return a 404 not found error.", t, func() { @@ -3030,8 +1870,7 @@ func TestDetachVersionReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, generatorMock, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, generatorMock, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) @@ -3043,12 +1882,6 @@ func TestDetachVersionReturnsError(t *testing.T) { So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 0) So(len(mockedDataStore.GetEditionCalls()), ShouldEqual, 1) So(len(generatorMock.GenerateCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: detachVersionAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: detachVersionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: detachVersionAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When detached is called against a version other than latest, return an internal server error", t, func() { @@ -3073,8 +1906,7 @@ func TestDetachVersionReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, generatorMock, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, generatorMock, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) @@ -3086,12 +1918,6 @@ func TestDetachVersionReturnsError(t *testing.T) { So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 0) So(len(mockedDataStore.GetEditionCalls()), ShouldEqual, 1) So(len(generatorMock.GenerateCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: detachVersionAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: detachVersionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: detachVersionAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When state is neither edition-confirmed or associated, return an internal server error", t, func() { @@ -3119,8 +1945,7 @@ func TestDetachVersionReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, generatorMock, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, generatorMock, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) @@ -3132,12 +1957,6 @@ func TestDetachVersionReturnsError(t *testing.T) { So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 0) So(len(mockedDataStore.GetEditionCalls()), ShouldEqual, 1) So(len(generatorMock.GenerateCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: detachVersionAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: detachVersionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: detachVersionAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When the requested version cannot be found, return a not found error", t, func() { @@ -3165,8 +1984,7 @@ func TestDetachVersionReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, generatorMock, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, generatorMock, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) @@ -3178,12 +1996,6 @@ func TestDetachVersionReturnsError(t *testing.T) { So(len(mockedDataStore.GetVersionCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetEditionCalls()), ShouldEqual, 1) So(len(generatorMock.GenerateCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: detachVersionAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: detachVersionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: detachVersionAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When updating the version fails, return an internal server error", t, func() { @@ -3219,8 +2031,7 @@ func TestDetachVersionReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, generatorMock, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, generatorMock, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) @@ -3233,12 +2044,6 @@ func TestDetachVersionReturnsError(t *testing.T) { So(len(mockedDataStore.GetEditionCalls()), ShouldEqual, 1) So(len(mockedDataStore.UpdateVersionCalls()), ShouldEqual, 1) So(len(generatorMock.GenerateCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: detachVersionAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: detachVersionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: detachVersionAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) Convey("When edition update fails whilst rolling back the edition, return an internal server error", t, func() { @@ -3277,8 +2082,7 @@ func TestDetachVersionReturnsError(t *testing.T) { datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - auditor := auditortest.New() - api := GetAPIWithMocks(mockedDataStore, generatorMock, auditor, datasetPermissions, permissions) + api := GetAPIWithMocks(mockedDataStore, generatorMock, datasetPermissions, permissions) api.Router.ServeHTTP(w, r) @@ -3292,12 +2096,6 @@ func TestDetachVersionReturnsError(t *testing.T) { So(len(mockedDataStore.UpdateVersionCalls()), ShouldEqual, 1) So(len(mockedDataStore.UpsertEditionCalls()), ShouldEqual, 1) So(len(generatorMock.GenerateCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: detachVersionAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: detachVersionAction, Result: audit.Attempted, Params: auditParams}, - auditortest.Expected{Action: detachVersionAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) } diff --git a/api/webendpoints_test.go b/api/webendpoints_test.go index 21fb32e9..0c868c46 100644 --- a/api/webendpoints_test.go +++ b/api/webendpoints_test.go @@ -8,7 +8,6 @@ import ( "net/http/httptest" "testing" - "github.com/ONSdigital/go-ns/audit/auditortest" "github.com/globalsign/mgo/bson" "github.com/ONSdigital/dp-dataset-api/config" @@ -44,7 +43,7 @@ func TestWebSubnetDatasetsEndpoint(t *testing.T) { } Convey("Calling the datasets endpoint should allow only published items", func() { - api := GetWebAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditortest.New(), nil, nil) + api := GetWebAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, nil, nil) api.Router.ServeHTTP(w, r) a, _ := ioutil.ReadAll(w.Body) @@ -78,7 +77,7 @@ func TestWebSubnetDatasetEndpoint(t *testing.T) { } Convey("Calling the dataset endpoint should allow only published items", func() { - api := GetWebAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditortest.New(), nil, nil) + api := GetWebAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, nil, nil) api.Router.ServeHTTP(w, r) a, _ := ioutil.ReadAll(w.Body) @@ -114,7 +113,7 @@ func TestWebSubnetEditionsEndpoint(t *testing.T) { } Convey("Calling the editions endpoint should allow only published items", func() { - api := GetWebAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditortest.New(), nil, nil) + api := GetWebAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, nil, nil) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) @@ -145,7 +144,7 @@ func TestWebSubnetEditionEndpoint(t *testing.T) { } Convey("Calling the edition endpoint should allow only published items", func() { - api := GetWebAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditortest.New(), nil, nil) + api := GetWebAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, nil, nil) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) @@ -180,7 +179,7 @@ func TestWebSubnetVersionsEndpoint(t *testing.T) { } Convey("Calling the versions endpoint should allow only published items", func() { - api := GetWebAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditortest.New(), nil, nil) + api := GetWebAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, nil, nil) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) @@ -217,7 +216,7 @@ func TestWebSubnetVersionEndpoint(t *testing.T) { } Convey("Calling the version endpoint should allow only published items", func() { - api := GetWebAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditortest.New(), nil, nil) + api := GetWebAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, nil, nil) api.Router.ServeHTTP(w, r) @@ -250,7 +249,7 @@ func TestWebSubnetDimensionsEndpoint(t *testing.T) { } Convey("Calling dimension endpoint should allow only published items", func() { - api := GetWebAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditortest.New(), nil, nil) + api := GetWebAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, nil, nil) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) @@ -281,7 +280,7 @@ func TestWebSubnetDimensionOptionsEndpoint(t *testing.T) { Convey("Calling dimension option endpoint should allow only published items", func() { - api := GetWebAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditortest.New(), nil, nil) + api := GetWebAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, nil, nil) api.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) @@ -330,7 +329,7 @@ func TestPublishedSubnetEndpointsAreDisabled(t *testing.T) { w := httptest.NewRecorder() mockedDataStore := &storetest.StorerMock{} - api := GetWebAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditortest.New(), nil, nil) + api := GetWebAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, nil, nil) api.Router.ServeHTTP(w, r) @@ -340,12 +339,12 @@ func TestPublishedSubnetEndpointsAreDisabled(t *testing.T) { }) } -func GetWebAPIWithMocks(ctx context.Context, mockedDataStore store.Storer, mockedGeneratedDownloads DownloadsGenerator, auditor Auditor, datasetPermissions AuthHandler, permissions AuthHandler) *DatasetAPI { +func GetWebAPIWithMocks(ctx context.Context, mockedDataStore store.Storer, mockedGeneratedDownloads DownloadsGenerator, datasetPermissions AuthHandler, permissions AuthHandler) *DatasetAPI { cfg, err := config.Get() So(err, ShouldBeNil) cfg.ServiceAuthToken = authToken cfg.DatasetAPIURL = host cfg.EnablePrivateEndpoints = false - return NewDatasetAPI(ctx, *cfg, mux.NewRouter(), store.DataStore{Backend: mockedDataStore}, urlBuilder, mockedGeneratedDownloads, auditor, datasetPermissions, permissions) + return NewDatasetAPI(ctx, *cfg, mux.NewRouter(), store.DataStore{Backend: mockedDataStore}, urlBuilder, mockedGeneratedDownloads, datasetPermissions, permissions) } diff --git a/config/config.go b/config/config.go index c8d73fcd..365f1da0 100644 --- a/config/config.go +++ b/config/config.go @@ -11,7 +11,6 @@ import ( type Configuration struct { BindAddr string `envconfig:"BIND_ADDR"` KafkaAddr []string `envconfig:"KAFKA_ADDR" json:"-"` - AuditEventsTopic string `envconfig:"AUDIT_EVENTS_TOPIC"` GenerateDownloadsTopic string `envconfig:"GENERATE_DOWNLOADS_TOPIC"` CodeListAPIURL string `envconfig:"CODE_LIST_API_URL"` DatasetAPIURL string `envconfig:"DATASET_API_URL"` @@ -47,7 +46,6 @@ func Get() (*Configuration, error) { cfg = &Configuration{ BindAddr: ":22000", KafkaAddr: []string{"localhost:9092"}, - AuditEventsTopic: "audit-events", GenerateDownloadsTopic: "filter-job-submitted", CodeListAPIURL: "http://localhost:22400", DatasetAPIURL: "http://localhost:22000", diff --git a/config/config_test.go b/config/config_test.go index 3f11b88e..70e5fef7 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -20,14 +20,12 @@ func TestSpec(t *testing.T) { Convey("The values should be set to the expected defaults", func() { So(cfg.BindAddr, ShouldEqual, ":22000") So(cfg.KafkaAddr, ShouldResemble, []string{"localhost:9092"}) - So(cfg.AuditEventsTopic, ShouldEqual, "audit-events") So(cfg.GenerateDownloadsTopic, ShouldEqual, "filter-job-submitted") So(cfg.DatasetAPIURL, ShouldEqual, "http://localhost:22000") So(cfg.CodeListAPIURL, ShouldEqual, "http://localhost:22400") So(cfg.DownloadServiceSecretKey, ShouldEqual, "QB0108EZ-825D-412C-9B1D-41EF7747F462") So(cfg.WebsiteURL, ShouldEqual, "http://localhost:20000") So(cfg.ZebedeeURL, ShouldEqual, "http://localhost:8082") - So(cfg.AuditEventsTopic, ShouldEqual, "audit-events") So(cfg.ServiceAuthToken, ShouldEqual, "FD0108EA-825D-411C-9B1D-41EF7727F465") So(cfg.GracefulShutdownTimeout, ShouldEqual, 5*time.Second) So(cfg.MongoConfig.BindAddr, ShouldEqual, "localhost:27017") diff --git a/dimension/dimension.go b/dimension/dimension.go index af4a5d68..1dfc82e1 100644 --- a/dimension/dimension.go +++ b/dimension/dimension.go @@ -7,16 +7,13 @@ import ( "github.com/ONSdigital/dp-dataset-api/models" "github.com/ONSdigital/dp-dataset-api/store" - "github.com/ONSdigital/go-ns/audit" - "github.com/ONSdigital/go-ns/common" - "github.com/ONSdigital/go-ns/request" + dphttp "github.com/ONSdigital/dp-net/http" "github.com/ONSdigital/log.go/log" "github.com/gorilla/mux" ) // Store provides a backend for dimensions type Store struct { - Auditor audit.AuditorService store.Storer } @@ -33,27 +30,15 @@ func (s *Store) GetDimensionsHandler(w http.ResponseWriter, r *http.Request) { ctx := r.Context() vars := mux.Vars(r) instanceID := vars["instance_id"] - auditParams := common.Params{"instance_id": instanceID} - logData := audit.ToLogData(auditParams) + logData := log.Data{"instance_id": instanceID} logData["action"] = GetDimensions b, err := s.getDimensions(ctx, instanceID, logData) if err != nil { - if auditErr := s.Auditor.Record(ctx, GetDimensions, audit.Unsuccessful, auditParams); auditErr != nil { - err = auditErr - } - handleDimensionErr(ctx, w, err, logData) return } - - if auditErr := s.Auditor.Record(ctx, GetDimensions, audit.Successful, auditParams); auditErr != nil { - handleDimensionErr(ctx, w, auditErr, logData) - return - } - writeBody(ctx, w, b, logData) - log.Event(ctx, "successfully get dimensions for an instance resource", log.INFO, logData) } @@ -92,27 +77,15 @@ func (s *Store) GetUniqueDimensionAndOptionsHandler(w http.ResponseWriter, r *ht vars := mux.Vars(r) instanceID := vars["instance_id"] dimension := vars["dimension"] - auditParams := common.Params{"instance_id": instanceID, "dimension": dimension} - logData := audit.ToLogData(auditParams) + logData := log.Data{"instance_id": instanceID, "dimension": dimension} logData["action"] = GetUniqueDimensionAndOptionsAction b, err := s.getUniqueDimensionAndOptions(ctx, instanceID, dimension, logData) if err != nil { - if auditErr := s.Auditor.Record(ctx, GetUniqueDimensionAndOptionsAction, audit.Unsuccessful, auditParams); auditErr != nil { - err = auditErr - } - handleDimensionErr(ctx, w, err, logData) return } - - if auditErr := s.Auditor.Record(ctx, GetUniqueDimensionAndOptionsAction, audit.Successful, auditParams); auditErr != nil { - handleDimensionErr(ctx, w, auditErr, logData) - return - } - writeBody(ctx, w, b, logData) - log.Event(ctx, "successfully get unique dimension options for an instance resource", log.INFO, logData) } @@ -147,39 +120,26 @@ func (s *Store) getUniqueDimensionAndOptions(ctx context.Context, instanceID, di // AddHandler represents adding a dimension to a specific instance func (s *Store) AddHandler(w http.ResponseWriter, r *http.Request) { - defer request.DrainBody(r) + defer dphttp.DrainBody(r) ctx := r.Context() vars := mux.Vars(r) instanceID := vars["instance_id"] - auditParams := common.Params{"instance_id": instanceID} - logData := audit.ToLogData(auditParams) + logData := log.Data{"instance_id": instanceID} logData["action"] = AddDimensionAction option, err := unmarshalDimensionCache(r.Body) if err != nil { log.Event(ctx, "failed to unmarshal dimension cache", log.ERROR, log.Error(err), logData) - - if auditErr := s.Auditor.Record(ctx, AddDimensionAction, audit.Unsuccessful, auditParams); auditErr != nil { - err = auditErr - } - handleDimensionErr(ctx, w, err, logData) return } if err := s.add(ctx, instanceID, option, logData); err != nil { - if auditErr := s.Auditor.Record(ctx, AddDimensionAction, audit.Unsuccessful, auditParams); auditErr != nil { - err = auditErr - } - handleDimensionErr(ctx, w, err, logData) return } - - s.Auditor.Record(ctx, AddDimensionAction, audit.Successful, auditParams) - log.Event(ctx, "added dimension to instance resource", log.INFO, logData) } @@ -217,20 +177,15 @@ func (s *Store) AddNodeIDHandler(w http.ResponseWriter, r *http.Request) { dimensionName := vars["dimension"] option := vars["option"] nodeID := vars["node_id"] - auditParams := common.Params{"instance_id": instanceID, "dimension": dimensionName, "option": option, "node_id": nodeID} - logData := audit.ToLogData(auditParams) - logData["action"] = UpdateNodeIDAction + logData := log.Data{"instance_id": instanceID, "dimension": dimensionName, "option": option, "node_id": nodeID, "action": UpdateNodeIDAction} dim := models.DimensionOption{Name: dimensionName, Option: option, NodeID: nodeID, InstanceID: instanceID} if err := s.addNodeID(ctx, dim, logData); err != nil { - s.Auditor.Record(ctx, UpdateNodeIDAction, audit.Unsuccessful, auditParams) handleDimensionErr(ctx, w, err, logData) return } - s.Auditor.Record(ctx, UpdateNodeIDAction, audit.Successful, auditParams) - logData["action"] = AddDimensionAction log.Event(ctx, "added node id to dimension of an instance resource", log.INFO, logData) } diff --git a/dimension/dimension_test.go b/dimension/dimension_test.go index 377a3df9..cdce5a44 100644 --- a/dimension/dimension_test.go +++ b/dimension/dimension_test.go @@ -2,7 +2,6 @@ package dimension_test import ( "context" - "errors" "io" "net/http" "net/http/httptest" @@ -13,15 +12,12 @@ import ( "github.com/ONSdigital/dp-dataset-api/api" errs "github.com/ONSdigital/dp-dataset-api/apierrors" "github.com/ONSdigital/dp-dataset-api/config" - "github.com/ONSdigital/dp-dataset-api/dimension" "github.com/ONSdigital/dp-dataset-api/mocks" "github.com/ONSdigital/dp-dataset-api/models" "github.com/ONSdigital/dp-dataset-api/store" storetest "github.com/ONSdigital/dp-dataset-api/store/datastoretest" "github.com/ONSdigital/dp-dataset-api/url" - "github.com/ONSdigital/go-ns/audit" - "github.com/ONSdigital/go-ns/audit/auditortest" - "github.com/ONSdigital/go-ns/common" + dprequest "github.com/ONSdigital/dp-net/request" "github.com/gorilla/mux" . "github.com/smartystreets/goconvey/convey" ) @@ -35,7 +31,7 @@ var ( func createRequestWithToken(method, url string, body io.Reader) (*http.Request, error) { r, err := http.NewRequest(method, url, body) ctx := r.Context() - ctx = common.SetCaller(ctx, "someone@ons.gov.uk") + ctx = dprequest.SetCaller(ctx, "someone@ons.gov.uk") r = r.WithContext(ctx) return r, err } @@ -57,8 +53,7 @@ func TestAddNodeIDToDimensionReturnsOK(t *testing.T) { }, } - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) @@ -66,19 +61,6 @@ func TestAddNodeIDToDimensionReturnsOK(t *testing.T) { // checks the instance is not published before entering handler So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 2) So(len(mockedDataStore.UpdateDimensionNodeIDCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{ - Action: dimension.UpdateNodeIDAction, - Result: audit.Attempted, - Params: common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123", "dimension": "age", "node_id": "11", "option": "55"}, - }, - auditortest.Expected{ - Action: dimension.UpdateNodeIDAction, - Result: audit.Successful, - Params: common.Params{"instance_id": "123", "dimension": "age", "node_id": "11", "option": "55"}, - }, - ) }) } @@ -99,8 +81,7 @@ func TestAddNodeIDToDimensionReturnsBadRequest(t *testing.T) { }, } - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -108,19 +89,6 @@ func TestAddNodeIDToDimensionReturnsBadRequest(t *testing.T) { // checks the instance is not published before entering handler So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 2) So(len(mockedDataStore.UpdateDimensionNodeIDCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{ - Action: dimension.UpdateNodeIDAction, - Result: audit.Attempted, - Params: common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123", "dimension": "age", "node_id": "11", "option": "55"}, - }, - auditortest.Expected{ - Action: dimension.UpdateNodeIDAction, - Result: audit.Unsuccessful, - Params: common.Params{"instance_id": "123", "dimension": "age", "node_id": "11", "option": "55"}, - }, - ) }) } @@ -138,26 +106,12 @@ func TestAddNodeIDToDimensionReturnsInternalError(t *testing.T) { }, } - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusInternalServerError) So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) So(len(mockedDataStore.UpdateDimensionNodeIDCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{ - Action: dimension.UpdateNodeIDAction, - Result: audit.Attempted, - Params: common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123", "dimension": "age", "node_id": "11", "option": "55"}, - }, - auditortest.Expected{ - Action: dimension.UpdateNodeIDAction, - Result: audit.Unsuccessful, - Params: common.Params{"instance_id": "123", "dimension": "age"}, - }, - ) }) Convey("Given instance state is invalid, then response returns an internal error", t, func() { @@ -172,8 +126,7 @@ func TestAddNodeIDToDimensionReturnsInternalError(t *testing.T) { }, } - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusInternalServerError) @@ -181,19 +134,6 @@ func TestAddNodeIDToDimensionReturnsInternalError(t *testing.T) { // checks the instance is not published before entering handler So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) So(len(mockedDataStore.UpdateDimensionNodeIDCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{ - Action: dimension.UpdateNodeIDAction, - Result: audit.Attempted, - Params: common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123", "dimension": "age", "node_id": "11", "option": "55"}, - }, - auditortest.Expected{ - Action: dimension.UpdateNodeIDAction, - Result: audit.Unsuccessful, - Params: common.Params{"instance_id": "123", "dimension": "age", "instance_state": "gobbledygook"}, - }, - ) }) } @@ -211,26 +151,12 @@ func TestAddNodeIDToDimensionReturnsForbidden(t *testing.T) { }, } - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusForbidden) So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) So(len(mockedDataStore.UpdateDimensionNodeIDCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{ - Action: dimension.UpdateNodeIDAction, - Result: audit.Attempted, - Params: common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123", "dimension": "age", "node_id": "11", "option": "55"}, - }, - auditortest.Expected{ - Action: dimension.UpdateNodeIDAction, - Result: audit.Unsuccessful, - Params: common.Params{"instance_id": "123", "dimension": "age", "instance_state": models.PublishedState}, - }, - ) }) } @@ -248,148 +174,12 @@ func TestAddNodeIDToDimensionReturnsUnauthorized(t *testing.T) { }, } - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusUnauthorized) So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateDimensionNodeIDCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{ - Action: dimension.UpdateNodeIDAction, - Result: audit.Attempted, - Params: common.Params{"instance_id": "123", "dimension": "age", "node_id": "11", "option": "55"}, - }, - auditortest.Expected{ - Action: dimension.UpdateNodeIDAction, - Result: audit.Unsuccessful, - Params: common.Params{"instance_id": "123", "dimension": "age", "node_id": "11", "option": "55"}, - }, - ) - }) -} - -func TestAddNodeIDToDimensionAuditFailure(t *testing.T) { - t.Parallel() - Convey("When auditing add node id to dimension attempt fails return an error of internal server error", t, func() { - r, err := createRequestWithToken("PUT", "http://localhost:21800/instances/123/dimensions/age/options/55/node_id/11", nil) - So(err, ShouldBeNil) - - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - GetInstanceFunc: func(ID string) (*models.Instance, error) { - return nil, nil - }, - } - - auditor := auditortest.New() - auditor.RecordFunc = func(ctx context.Context, action string, result string, params common.Params) error { - return errors.New("unable to send message to kafka audit topic") - } - - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor) - datasetAPI.Router.ServeHTTP(w, r) - - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) - So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 0) - auditor.AssertRecordCalls( - auditortest.Expected{ - Action: dimension.UpdateNodeIDAction, - Result: audit.Attempted, - Params: common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123", "dimension": "age", "node_id": "11", "option": "55"}, - }) - }) - - Convey("When request to add node id to dimension is forbidden but audit fails returns an error of internal server error", t, func() { - r, err := createRequestWithToken("PUT", "http://localhost:21800/instances/123/dimensions/age/options/55/node_id/11", nil) - So(err, ShouldBeNil) - - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - GetInstanceFunc: func(ID string) (*models.Instance, error) { - return &models.Instance{State: models.PublishedState}, nil - }, - } - - count := 1 - auditor := auditortest.New() - auditor.RecordFunc = func(ctx context.Context, action string, result string, params common.Params) error { - if count == 1 { - count++ - return nil - } - return errors.New("unable to send message to kafka audit topic") - } - - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor) - datasetAPI.Router.ServeHTTP(w, r) - - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) - So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{ - Action: dimension.UpdateNodeIDAction, - Result: audit.Attempted, - Params: common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123", "dimension": "age", "node_id": "11", "option": "55"}, - }, - auditortest.Expected{ - Action: dimension.UpdateNodeIDAction, - Result: audit.Unsuccessful, - Params: common.Params{"instance_id": "123", "dimension": "age", "instance_state": models.PublishedState}, - }, - ) - }) - - Convey("When request to add node id to dimension and audit fails to send success message return 200 response", t, func() { - r, err := createRequestWithToken("PUT", "http://localhost:21800/instances/123/dimensions/age/options/55/node_id/11", nil) - So(err, ShouldBeNil) - - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - GetInstanceFunc: func(ID string) (*models.Instance, error) { - return &models.Instance{State: models.CreatedState}, nil - }, - UpdateDimensionNodeIDFunc: func(event *models.DimensionOption) error { - return nil - }, - } - - count := 1 - auditor := auditortest.New() - auditor.RecordFunc = func(ctx context.Context, action string, result string, params common.Params) error { - if count <= 2 { - count++ - return nil - } - return errors.New("unable to send message to kafka audit topic") - } - - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor) - datasetAPI.Router.ServeHTTP(w, r) - - So(w.Code, ShouldEqual, http.StatusOK) - // Gets called twice as there is a check wrapper around this route which - // checks the instance is not published before entering handler - So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 2) - So(len(mockedDataStore.UpdateDimensionNodeIDCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{ - Action: dimension.UpdateNodeIDAction, - Result: audit.Attempted, - Params: common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123", "dimension": "age", "node_id": "11", "option": "55"}, - }, - auditortest.Expected{ - Action: dimension.UpdateNodeIDAction, - Result: audit.Successful, - Params: common.Params{"instance_id": "123", "dimension": "age", "node_id": "11", "option": "55"}, - }, - ) }) } @@ -410,8 +200,7 @@ func TestAddDimensionToInstanceReturnsOk(t *testing.T) { }, } - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) @@ -419,19 +208,6 @@ func TestAddDimensionToInstanceReturnsOk(t *testing.T) { // checks the instance is not published before entering handler So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 2) So(len(mockedDataStore.AddDimensionToInstanceCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{ - Action: dimension.AddDimensionAction, - Result: audit.Attempted, - Params: common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123"}, - }, - auditortest.Expected{ - Action: dimension.AddDimensionAction, - Result: audit.Successful, - Params: common.Params{"instance_id": "123"}, - }, - ) }) } @@ -453,8 +229,7 @@ func TestAddDimensionToInstanceReturnsNotFound(t *testing.T) { }, } - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -463,19 +238,6 @@ func TestAddDimensionToInstanceReturnsNotFound(t *testing.T) { // checks the instance is not published before entering handler So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 2) So(len(mockedDataStore.AddDimensionToInstanceCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{ - Action: dimension.AddDimensionAction, - Result: audit.Attempted, - Params: common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123"}, - }, - auditortest.Expected{ - Action: dimension.AddDimensionAction, - Result: audit.Unsuccessful, - Params: common.Params{"instance_id": "123"}, - }, - ) }) } @@ -497,27 +259,13 @@ func TestAddDimensionToInstanceReturnsForbidden(t *testing.T) { }, } - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusForbidden) So(w.Body.String(), ShouldContainSubstring, errs.ErrResourcePublished.Error()) So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) So(len(mockedDataStore.AddDimensionToInstanceCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{ - Action: dimension.AddDimensionAction, - Result: audit.Attempted, - Params: common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123"}, - }, - auditortest.Expected{ - Action: dimension.AddDimensionAction, - Result: audit.Unsuccessful, - Params: common.Params{"instance_id": "123", "instance_state": models.PublishedState}, - }, - ) }) } @@ -536,26 +284,12 @@ func TestAddDimensionToInstanceReturnsUnauthorized(t *testing.T) { }, } - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusUnauthorized) So(w.Body.String(), ShouldContainSubstring, "unauthenticated request") So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{ - Action: dimension.AddDimensionAction, - Result: audit.Attempted, - Params: common.Params{"instance_id": "123"}, - }, - auditortest.Expected{ - Action: dimension.AddDimensionAction, - Result: audit.Unsuccessful, - Params: common.Params{"instance_id": "123"}, - }, - ) }) } @@ -577,8 +311,7 @@ func TestAddDimensionToInstanceReturnsInternalError(t *testing.T) { }, } - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusInternalServerError) @@ -586,19 +319,6 @@ func TestAddDimensionToInstanceReturnsInternalError(t *testing.T) { So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) So(len(mockedDataStore.AddDimensionToInstanceCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{ - Action: dimension.AddDimensionAction, - Result: audit.Attempted, - Params: common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123"}, - }, - auditortest.Expected{ - Action: dimension.AddDimensionAction, - Result: audit.Unsuccessful, - Params: common.Params{"instance_id": "123"}, - }, - ) }) Convey("Given instance state is invalid, then response returns an internal error", t, func() { @@ -617,8 +337,7 @@ func TestAddDimensionToInstanceReturnsInternalError(t *testing.T) { }, } - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusInternalServerError) @@ -627,144 +346,6 @@ func TestAddDimensionToInstanceReturnsInternalError(t *testing.T) { // checks the instance is not published before entering handler So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) So(len(mockedDataStore.AddDimensionToInstanceCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{ - Action: dimension.AddDimensionAction, - Result: audit.Attempted, - Params: common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123"}, - }, - auditortest.Expected{ - Action: dimension.AddDimensionAction, - Result: audit.Unsuccessful, - Params: common.Params{"instance_id": "123", "instance_state": "gobbledygook"}, - }, - ) - }) -} - -func TestAddDimensionAuditFailure(t *testing.T) { - t.Parallel() - Convey("When a valid request to add dimension is made but the audit attempt fails returns an error of internal server error", t, func() { - json := strings.NewReader(`{"value":"24", "code_list":"123-456", "dimension": "test"}`) - r, err := createRequestWithToken("POST", "http://localhost:21800/instances/123/dimensions", json) - So(err, ShouldBeNil) - - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - GetInstanceFunc: func(ID string) (*models.Instance, error) { - return nil, nil - }, - } - - auditor := auditortest.New() - auditor.RecordFunc = func(ctx context.Context, action string, result string, params common.Params) error { - return errors.New("unable to send message to kafka audit topic") - } - - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor) - datasetAPI.Router.ServeHTTP(w, r) - - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) - So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls(auditortest.Expected{ - Action: dimension.AddDimensionAction, - Result: audit.Attempted, - Params: common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123"}, - }) - }) - - Convey("When request to add a dimension is forbidden but audit fails returns an error of internal server error", t, func() { - json := strings.NewReader(`{"value":"24", "code_list":"123-456", "dimension": "test"}`) - r, err := createRequestWithToken("POST", "http://localhost:21800/instances/123/dimensions", json) - So(err, ShouldBeNil) - - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - GetInstanceFunc: func(ID string) (*models.Instance, error) { - return &models.Instance{State: models.PublishedState}, nil - }, - } - - count := 1 - auditor := auditortest.New() - auditor.RecordFunc = func(ctx context.Context, action string, result string, params common.Params) error { - if count == 1 { - count++ - return nil - } - return errors.New("unable to send message to kafka audit topic") - } - - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor) - datasetAPI.Router.ServeHTTP(w, r) - - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) - So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{ - Action: dimension.AddDimensionAction, - Result: audit.Attempted, - Params: common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123"}, - }, - auditortest.Expected{ - Action: dimension.AddDimensionAction, - Result: audit.Unsuccessful, - Params: common.Params{"instance_id": "123", "instance_state": models.PublishedState}, - }, - ) - }) - - Convey("When request to add dimension and audit fails to send success message return 200 response", t, func() { - json := strings.NewReader(`{"value":"24", "code_list":"123-456", "dimension": "test"}`) - r, err := createRequestWithToken("POST", "http://localhost:21800/instances/123/dimensions", json) - So(err, ShouldBeNil) - - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - GetInstanceFunc: func(ID string) (*models.Instance, error) { - return &models.Instance{State: models.CreatedState}, nil - }, - AddDimensionToInstanceFunc: func(event *models.CachedDimensionOption) error { - return nil - }, - } - - count := 1 - auditor := auditortest.New() - auditor.RecordFunc = func(ctx context.Context, action string, result string, params common.Params) error { - if count <= 2 { - count++ - return nil - } - return errors.New("unable to send message to kafka audit topic") - } - - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor) - datasetAPI.Router.ServeHTTP(w, r) - - So(w.Code, ShouldEqual, http.StatusOK) - // Gets called twice as there is a check wrapper around this route which - // checks the instance is not published before entering handler - So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 2) - So(len(mockedDataStore.AddDimensionToInstanceCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{ - Action: dimension.AddDimensionAction, - Result: audit.Attempted, - Params: common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123"}, - }, - auditortest.Expected{ - Action: dimension.AddDimensionAction, - Result: audit.Successful, - Params: common.Params{"instance_id": "123"}, - }, - ) }) } @@ -785,26 +366,12 @@ func TestGetDimensionsReturnsOk(t *testing.T) { }, } - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetDimensionsFromInstanceCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{ - Action: dimension.GetDimensions, - Result: audit.Attempted, - Params: common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123"}, - }, - auditortest.Expected{ - Action: dimension.GetDimensions, - Result: audit.Successful, - Params: common.Params{"instance_id": "123"}, - }, - ) }) } @@ -825,27 +392,13 @@ func TestGetDimensionsReturnsNotFound(t *testing.T) { }, } - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) So(w.Body.String(), ShouldContainSubstring, errs.ErrDimensionNodeNotFound.Error()) So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetDimensionsFromInstanceCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{ - Action: dimension.GetDimensions, - Result: audit.Attempted, - Params: common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123"}, - }, - auditortest.Expected{ - Action: dimension.GetDimensions, - Result: audit.Unsuccessful, - Params: common.Params{"instance_id": "123"}, - }, - ) }) } @@ -866,27 +419,13 @@ func TestGetDimensionsAndOptionsReturnsInternalError(t *testing.T) { }, } - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusInternalServerError) So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetDimensionsFromInstanceCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{ - Action: dimension.GetDimensions, - Result: audit.Attempted, - Params: common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123"}, - }, - auditortest.Expected{ - Action: dimension.GetDimensions, - Result: audit.Unsuccessful, - Params: common.Params{"instance_id": "123"}, - }, - ) }) Convey("Given instance state is invalid, then response returns an internal error", t, func() { @@ -904,144 +443,13 @@ func TestGetDimensionsAndOptionsReturnsInternalError(t *testing.T) { }, } - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusInternalServerError) So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetDimensionsFromInstanceCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{ - Action: dimension.GetDimensions, - Result: audit.Attempted, - Params: common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123"}, - }, - auditortest.Expected{ - Action: dimension.GetDimensions, - Result: audit.Unsuccessful, - Params: common.Params{"instance_id": "123"}, - }, - ) - }) -} - -func TestGetDimensionsAndOptionsAuditFailure(t *testing.T) { - t.Parallel() - Convey("When a request to get a list of dimensions is made but the audit attempt fails return internal server error", t, func() { - r, err := createRequestWithToken("GET", "http://localhost:21800/instances/123/dimensions", nil) - So(err, ShouldBeNil) - - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{} - - auditor := auditortest.New() - auditor.RecordFunc = func(ctx context.Context, action string, result string, params common.Params) error { - return errors.New("unable to send message to kafka audit topic") - } - - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor) - datasetAPI.Router.ServeHTTP(w, r) - - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) - - auditor.AssertRecordCalls(auditortest.Expected{ - Action: dimension.GetDimensions, - Result: audit.Attempted, - Params: common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123"}, - }) - }) - - Convey("When a request to get a list of dimensions is unsuccessful and audit fails returns internal server error", t, func() { - r, err := createRequestWithToken("GET", "http://localhost:21800/instances/123/dimensions", nil) - So(err, ShouldBeNil) - - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - GetInstanceFunc: func(ID string) (*models.Instance, error) { - return &models.Instance{State: "gobbly gook"}, nil - }, - } - - count := 1 - auditor := auditortest.New() - auditor.RecordFunc = func(ctx context.Context, action string, result string, params common.Params) error { - if count == 1 { - count++ - return nil - } - return errors.New("unable to send message to kafka audit topic") - } - - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor) - datasetAPI.Router.ServeHTTP(w, r) - - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) - So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{ - Action: dimension.GetDimensions, - Result: audit.Attempted, - Params: common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123"}, - }, - auditortest.Expected{ - Action: dimension.GetDimensions, - Result: audit.Unsuccessful, - Params: common.Params{"instance_id": "123"}, - }, - ) - }) - - Convey("When a request to get a list of dimensions is made and audit fails to send success message return internal server error", t, func() { - r, err := createRequestWithToken("GET", "http://localhost:21800/instances/123/dimensions", nil) - So(err, ShouldBeNil) - - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - GetInstanceFunc: func(ID string) (*models.Instance, error) { - return &models.Instance{State: models.CreatedState}, nil - }, - GetDimensionsFromInstanceFunc: func(id string) (*models.DimensionNodeResults, error) { - return &models.DimensionNodeResults{}, nil - }, - } - - var count int - auditor := auditortest.New() - auditor.RecordFunc = func(ctx context.Context, action string, result string, params common.Params) error { - count++ - if count == 1 { - return nil - } - return errors.New("unable to send message to kafka audit topic") - } - - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor) - datasetAPI.Router.ServeHTTP(w, r) - - So(w.Code, ShouldEqual, http.StatusInternalServerError) - // Gets called twice as there is a check wrapper around this route which - // checks the instance is not published before entering handler - So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetDimensionsFromInstanceCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{ - Action: dimension.GetDimensions, - Result: audit.Attempted, - Params: common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123"}, - }, - auditortest.Expected{ - Action: dimension.GetDimensions, - Result: audit.Successful, - Params: common.Params{"instance_id": "123"}, - }, - ) }) } @@ -1062,26 +470,12 @@ func TestGetUniqueDimensionAndOptionsReturnsOk(t *testing.T) { }, } - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetUniqueDimensionAndOptionsCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{ - Action: dimension.GetUniqueDimensionAndOptionsAction, - Result: audit.Attempted, - Params: common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123", "dimension": "age"}, - }, - auditortest.Expected{ - Action: dimension.GetUniqueDimensionAndOptionsAction, - Result: audit.Successful, - Params: common.Params{"instance_id": "123", "dimension": "age"}, - }, - ) }) } @@ -1101,27 +495,13 @@ func TestGetUniqueDimensionAndOptionsReturnsNotFound(t *testing.T) { }, } - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) So(w.Body.String(), ShouldContainSubstring, errs.ErrInstanceNotFound.Error()) So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetUniqueDimensionAndOptionsCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{ - Action: dimension.GetUniqueDimensionAndOptionsAction, - Result: audit.Attempted, - Params: common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123", "dimension": "age"}, - }, - auditortest.Expected{ - Action: dimension.GetUniqueDimensionAndOptionsAction, - Result: audit.Unsuccessful, - Params: common.Params{"instance_id": "123", "dimension": "age"}, - }, - ) }) } @@ -1141,27 +521,13 @@ func TestGetUniqueDimensionAndOptionsReturnsInternalError(t *testing.T) { }, } - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusInternalServerError) So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetUniqueDimensionAndOptionsCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{ - Action: dimension.GetUniqueDimensionAndOptionsAction, - Result: audit.Attempted, - Params: common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123", "dimension": "age"}, - }, - auditortest.Expected{ - Action: dimension.GetUniqueDimensionAndOptionsAction, - Result: audit.Unsuccessful, - Params: common.Params{"instance_id": "123", "dimension": "age"}, - }, - ) }) Convey("Given instance state is invalid, then response returns an internal error", t, func() { @@ -1178,148 +544,17 @@ func TestGetUniqueDimensionAndOptionsReturnsInternalError(t *testing.T) { }, } - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusInternalServerError) So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) So(len(mockedDataStore.GetUniqueDimensionAndOptionsCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{ - Action: dimension.GetUniqueDimensionAndOptionsAction, - Result: audit.Attempted, - Params: common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123", "dimension": "age"}, - }, - auditortest.Expected{ - Action: dimension.GetUniqueDimensionAndOptionsAction, - Result: audit.Unsuccessful, - Params: common.Params{"instance_id": "123", "dimension": "age"}, - }, - ) - }) -} - -func TestGetUniqueDimensionAndOptionsAuditFailure(t *testing.T) { - t.Parallel() - Convey("When a request to get unique dimension options is made but the audit attempt fails returns internal server error", t, func() { - r, err := createRequestWithToken("GET", "http://localhost:21800/instances/123/dimensions/age/options", nil) - So(err, ShouldBeNil) - - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{} - - auditor := auditortest.New() - auditor.RecordFunc = func(ctx context.Context, action string, result string, params common.Params) error { - return errors.New("unable to send message to kafka audit topic") - } - - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor) - datasetAPI.Router.ServeHTTP(w, r) - - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) - - auditor.AssertRecordCalls(auditortest.Expected{ - Action: dimension.GetUniqueDimensionAndOptionsAction, - Result: audit.Attempted, - Params: common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123", "dimension": "age"}, - }) - }) - - Convey("When a request to get unique dimension options is unsuccessful and audit fails returns internal server error", t, func() { - r, err := createRequestWithToken("GET", "http://localhost:21800/instances/123/dimensions/age/options", nil) - So(err, ShouldBeNil) - - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - GetInstanceFunc: func(ID string) (*models.Instance, error) { - return &models.Instance{State: "gobbly gook"}, nil - }, - } - - count := 1 - auditor := auditortest.New() - auditor.RecordFunc = func(ctx context.Context, action string, result string, params common.Params) error { - if count == 1 { - count++ - return nil - } - return errors.New("unable to send message to kafka audit topic") - } - - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor) - datasetAPI.Router.ServeHTTP(w, r) - - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) - So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{ - Action: dimension.GetUniqueDimensionAndOptionsAction, - Result: audit.Attempted, - Params: common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123", "dimension": "age"}, - }, - auditortest.Expected{ - Action: dimension.GetUniqueDimensionAndOptionsAction, - Result: audit.Unsuccessful, - Params: common.Params{"instance_id": "123", "dimension": "age"}, - }, - ) - }) - - Convey("When a request to get unique dimension options is made and audit fails to send success message return internal server error", t, func() { - r, err := createRequestWithToken("GET", "http://localhost:21800/instances/123/dimensions/age/options", nil) - So(err, ShouldBeNil) - - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - GetInstanceFunc: func(ID string) (*models.Instance, error) { - return &models.Instance{State: models.CreatedState}, nil - }, - GetUniqueDimensionAndOptionsFunc: func(id, dimension string) (*models.DimensionValues, error) { - return &models.DimensionValues{}, nil - }, - } - - count := 1 - auditor := auditortest.New() - auditor.RecordFunc = func(ctx context.Context, action string, result string, params common.Params) error { - if count == 1 { - count++ - return nil - } - return errors.New("unable to send message to kafka audit topic") - } - - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor) - datasetAPI.Router.ServeHTTP(w, r) - - So(w.Code, ShouldEqual, http.StatusInternalServerError) - // Gets called twice as there is a check wrapper around this route which - // checks the instance is not published before entering handler - So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) - So(len(mockedDataStore.GetUniqueDimensionAndOptionsCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{ - Action: dimension.GetUniqueDimensionAndOptionsAction, - Result: audit.Attempted, - Params: common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123", "dimension": "age"}, - }, - auditortest.Expected{ - Action: dimension.GetUniqueDimensionAndOptionsAction, - Result: audit.Successful, - Params: common.Params{"instance_id": "123", "dimension": "age"}, - }, - ) }) } -func getAPIWithMocks(ctx context.Context, mockedDataStore store.Storer, mockedGeneratedDownloads api.DownloadsGenerator, mockAuditor api.Auditor) *api.DatasetAPI { +func getAPIWithMocks(ctx context.Context, mockedDataStore store.Storer, mockedGeneratedDownloads api.DownloadsGenerator) *api.DatasetAPI { mu.Lock() defer mu.Unlock() @@ -1332,7 +567,7 @@ func getAPIWithMocks(ctx context.Context, mockedDataStore store.Storer, mockedGe datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - return api.NewDatasetAPI(ctx, *cfg, mux.NewRouter(), store.DataStore{Backend: mockedDataStore}, urlBuilder, mockedGeneratedDownloads, mockAuditor, datasetPermissions, permissions) + return api.NewDatasetAPI(ctx, *cfg, mux.NewRouter(), store.DataStore{Backend: mockedDataStore}, urlBuilder, mockedGeneratedDownloads, datasetPermissions, permissions) } func getAuthorisationHandlerMock() *mocks.AuthHandlerMock { diff --git a/dimension/helpers.go b/dimension/helpers.go index 50b81139..932a2a5c 100644 --- a/dimension/helpers.go +++ b/dimension/helpers.go @@ -9,11 +9,16 @@ import ( errs "github.com/ONSdigital/dp-dataset-api/apierrors" "github.com/ONSdigital/dp-dataset-api/models" - "github.com/ONSdigital/go-ns/audit" + dprequest "github.com/ONSdigital/dp-net/request" "github.com/ONSdigital/log.go/log" "github.com/pkg/errors" ) +const ( + reqUser = "req_user" + reqCaller = "req_caller" +) + func unmarshalDimensionCache(reader io.Reader) (*models.CachedDimensionOption, error) { b, err := ioutil.ReadAll(reader) if err != nil { @@ -52,6 +57,18 @@ func handleDimensionErr(ctx context.Context, w http.ResponseWriter, err error, d } data["response_status"] = status - audit.LogError(ctx, errors.WithMessage(err, "request unsuccessful"), data) + logError(ctx, errors.WithMessage(err, "request unsuccessful"), data) http.Error(w, resource.Error(), status) } + +func logError(ctx context.Context, err error, data log.Data) error { + if user := dprequest.User(ctx); user != "" { + data[reqUser] = user + } + if caller := dprequest.Caller(ctx); caller != "" { + data[reqCaller] = caller + } + err = errors.WithMessage(err, "putVersion endpoint: failed to set instance node is_published") + log.Event(ctx, "failed to publish instance version", log.ERROR, log.Error(err), data) + return err +} diff --git a/go.mod b/go.mod index df974b13..a2a977b6 100644 --- a/go.mod +++ b/go.mod @@ -3,17 +3,17 @@ module github.com/ONSdigital/dp-dataset-api go 1.13 require ( - github.com/ONSdigital/dp-api-clients-go v1.9.0 - github.com/ONSdigital/dp-authorisation v0.0.0-20191018110224-d4543527d6cb - github.com/ONSdigital/dp-graph/v2 v2.0.4 - github.com/ONSdigital/dp-healthcheck v1.0.2 - github.com/ONSdigital/dp-kafka v1.1.5 - github.com/ONSdigital/dp-mongodb v1.2.0 - github.com/ONSdigital/dp-rchttp v1.0.0 + github.com/ONSdigital/dp-api-clients-go v1.26.0 + github.com/ONSdigital/dp-authorisation v0.1.0 + github.com/ONSdigital/dp-graph/v2 v2.1.3 + github.com/ONSdigital/dp-healthcheck v1.0.5 + github.com/ONSdigital/dp-kafka v1.1.7 + github.com/ONSdigital/dp-mongodb v1.4.0 + github.com/ONSdigital/dp-net v1.0.7 github.com/ONSdigital/go-ns v0.0.0-20200205115900-a11716f93bad - github.com/ONSdigital/log.go v1.0.0 + github.com/ONSdigital/log.go v1.0.1 github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8 - github.com/gorilla/mux v1.7.4 + github.com/gorilla/mux v1.8.0 github.com/justinas/alice v1.2.0 github.com/kelseyhightower/envconfig v1.4.0 github.com/pkg/errors v0.9.1 @@ -21,3 +21,5 @@ require ( github.com/smartystreets/goconvey v1.6.4 gopkg.in/avro.v0 v0.0.0-20171217001914-a730b5802183 // indirect ) + +replace github.com/ONSdigital/dp-net => ../dp-net diff --git a/go.sum b/go.sum index c95b8ecf..1261622d 100644 --- a/go.sum +++ b/go.sum @@ -2,21 +2,25 @@ github.com/ONSdigital/dp-api-clients-go v1.1.0 h1:j2zmSFcWWRbHs58m0+LltmijHBqbnO github.com/ONSdigital/dp-api-clients-go v1.1.0/go.mod h1:9lqor0I7caCnRWr04gU/r7x5dqxgoODob8L48q+cE4E= github.com/ONSdigital/dp-api-clients-go v1.9.0 h1:ru8jBPAxXfibYOF41/tU/ZtOt4tUVEszpMraHAbmvxA= github.com/ONSdigital/dp-api-clients-go v1.9.0/go.mod h1:SM0b/NXDWndJ9EulmAGdfDY4DxPxK+pNsP8eZlIWiqM= -github.com/ONSdigital/dp-authorisation v0.0.0-20191018110224-d4543527d6cb h1:k58Fs56RCIHAL3GToXYwO3IfKKyIN2JvvkQHANpIZ2Q= -github.com/ONSdigital/dp-authorisation v0.0.0-20191018110224-d4543527d6cb/go.mod h1:0KlUytscZEmrm4+rI+VvRzbMqXRoqECwXGKivF0zWxI= +github.com/ONSdigital/dp-api-clients-go v1.26.0 h1:dDWL5+m+dtPVJpkmXAqm/5xRFhyIO5vgsEKJRZpnfMI= +github.com/ONSdigital/dp-api-clients-go v1.26.0/go.mod h1:Ds0lw6Rejqu46iyZTd5tiHriQW6CRhh56ucmmlCy6O8= +github.com/ONSdigital/dp-authorisation v0.1.0 h1:HzYwJdvk7ZAeB56KMAH6MP5+5uZuuJnEyGq6CViDoCg= +github.com/ONSdigital/dp-authorisation v0.1.0/go.mod h1:rT81tcvWto5/cUWUFd0Q6gTqBoRfQmD6Qp0sq7FyiMg= github.com/ONSdigital/dp-frontend-models v1.1.0/go.mod h1:TT96P7Mi69N3Tc/jFNdbjiwG4GAaMjP26HLotFQ6BPw= -github.com/ONSdigital/dp-graph/v2 v2.0.4 h1:KwACJNL5r3P41yc3gZPF1fpSfWVSzCfd3DpL2qLgUZI= -github.com/ONSdigital/dp-graph/v2 v2.0.4/go.mod h1:jh7BsDGMG0VgNtSvc3hlA2wXs3H1cwdWCp84VGzMVB8= +github.com/ONSdigital/dp-graph/v2 v2.1.3 h1:7BJsRE9FDf7tFtJvI5v7RX94q4BAbiJFDWpxQCNfM18= +github.com/ONSdigital/dp-graph/v2 v2.1.3/go.mod h1:6C59rOY0qBKblczkQrJZZKa8ZLR3yKkyunSCeIUavtU= github.com/ONSdigital/dp-healthcheck v0.0.0-20200131122546-9db6d3f0494e/go.mod h1:zighxZ/0m5u7zo0eAr8XFlA+Dz2ic7A1vna6YXvhCjQ= github.com/ONSdigital/dp-healthcheck v1.0.0/go.mod h1:zighxZ/0m5u7zo0eAr8XFlA+Dz2ic7A1vna6YXvhCjQ= github.com/ONSdigital/dp-healthcheck v1.0.2 h1:N8SzpYzdixVgJS9NMzTBA2RZ2bi3Am1wE5F8ROEpTYw= github.com/ONSdigital/dp-healthcheck v1.0.2/go.mod h1:zighxZ/0m5u7zo0eAr8XFlA+Dz2ic7A1vna6YXvhCjQ= -github.com/ONSdigital/dp-kafka v1.1.5 h1:viB+ajyTx0RNEUMz5Qoi5h6xAHSWwsJWWwokk3WN+1k= -github.com/ONSdigital/dp-kafka v1.1.5/go.mod h1:s/8OV37Sx35wgNXw3VYlpRxJfldJLnXWPepY+SI45w8= +github.com/ONSdigital/dp-healthcheck v1.0.5 h1:DXnohGIqXaLLeYGdaGOhgkZjAbWMNoLAjQ3EgZeMT3M= +github.com/ONSdigital/dp-healthcheck v1.0.5/go.mod h1:2wbVAUHMl9+4tWhUlxYUuA1dnf2+NrwzC+So5f5BMLk= +github.com/ONSdigital/dp-kafka v1.1.7 h1:/XjDYHZDxA0r4JR5Ua/99z8ocVN6OUU/VyPTeWh95Qc= +github.com/ONSdigital/dp-kafka v1.1.7/go.mod h1:iEoaot8ojwSUjxA7FPZx3rT/pQJzh5kA9DV4N+1ibDU= github.com/ONSdigital/dp-mocking v0.0.0-20190905163309-fee2702ad1b9 h1:+WXVfTDyWXY1DQRDFSmt1b/ORKk5c7jGiPu7NoeaM/0= github.com/ONSdigital/dp-mocking v0.0.0-20190905163309-fee2702ad1b9/go.mod h1:BcIRgitUju//qgNePRBmNjATarTtynAgc0yV29VpLEk= -github.com/ONSdigital/dp-mongodb v1.2.0 h1:WFE4p2cJPgTLMICuvU9y4n+3hcbP4WSDeOGz0rwe0lQ= -github.com/ONSdigital/dp-mongodb v1.2.0/go.mod h1:Yq2GazmrVEn1GEZ0Qw/Igmeo3mzsmKAJst1s7EbSkOo= +github.com/ONSdigital/dp-mongodb v1.4.0 h1:nDyRgGLfLYkQnS1SZgpq9y3BD87IqfjihZERn9pudy0= +github.com/ONSdigital/dp-mongodb v1.4.0/go.mod h1:kJRKmL4JUub+DGlWGeqaV8D13Jaj9939UEaPXfSIdVg= github.com/ONSdigital/dp-rchttp v0.0.0-20190919143000-bb5699e6fd59/go.mod h1:KkW68U3FPuivW4ogi9L8CPKNj9ZxGko4qcUY7KoAAkQ= github.com/ONSdigital/dp-rchttp v0.0.0-20200114090501-463a529590e8 h1:MWIHCr/ud5ur9elhfvKtSjMJInqf3iUY8F4J27qGQPA= github.com/ONSdigital/dp-rchttp v0.0.0-20200114090501-463a529590e8/go.mod h1:821jZtK0oBsV8hjIkNr8vhAWuv0FxJBPJuAHa2B70Gk= @@ -29,11 +33,13 @@ github.com/ONSdigital/golang-neo4j-bolt-driver v0.0.0-20190228153339-da534111531 github.com/ONSdigital/golang-neo4j-bolt-driver v0.0.0-20190228153339-da534111531d/go.mod h1:75Sxr59AMz2RiPskqSymLFxdeaIEhnkNaJE5lonMS3M= github.com/ONSdigital/graphson v0.0.0-20190718134034-c13ceacd109d h1:yrCtEGlohmA3OnXtke0nOOp/m9O83orpSnTGOfYOw1Q= github.com/ONSdigital/graphson v0.0.0-20190718134034-c13ceacd109d/go.mod h1:zQ+8pTnCLGuy4eUek81pWUxZo4/f71ri3VYz97Wby+4= -github.com/ONSdigital/gremgo-neptune v0.0.0-20190806135047-c3c614e5b650 h1:GmVUMOd+k7Czv87P7vJ1QTpws9THtzmCFX3z/BlKd0I= -github.com/ONSdigital/gremgo-neptune v0.0.0-20190806135047-c3c614e5b650/go.mod h1:oYyEo2KY54bzMSkdUpP0ouombGyaTN+P4ckKTuo+bog= +github.com/ONSdigital/gremgo-neptune v1.0.0 h1:l0Pizt2goXK5oCFeqs2sOkosZbF4sva0RpcR150VvNE= +github.com/ONSdigital/gremgo-neptune v1.0.0/go.mod h1:GZz/N6xjNY+EN0x4FmfBDrM73R+Pr3aI5iCwYbY1oYQ= github.com/ONSdigital/log.go v0.0.0-20191127134126-2a610b254f20/go.mod h1:BD7D8FWP1fzwUWsrCopEG72jl9cchCaVNIGSz6YvL+Y= github.com/ONSdigital/log.go v1.0.0 h1:hZQTuitFv4nSrpzMhpGvafUC5/8xMVnLI0CWe1rAJNc= github.com/ONSdigital/log.go v1.0.0/go.mod h1:UnGu9Q14gNC+kz0DOkdnLYGoqugCvnokHBRBxFRpVoQ= +github.com/ONSdigital/log.go v1.0.1 h1:SZ5wRZAwlt2jQUZ9AUzBB/PL+iG15KapfQpJUdA18/4= +github.com/ONSdigital/log.go v1.0.1/go.mod h1:dIwSXuvFB5EsZG5x44JhsXZKMd80zlb0DZxmiAtpL4M= github.com/Shopify/sarama v1.24.1 h1:svn9vfN3R1Hz21WR2Gj0VW9ehaDGkiOS+VqlIcZOkMI= github.com/Shopify/sarama v1.24.1/go.mod h1:fGP8eQ6PugKEI0iUETYYtnP6d1pH/bdDMTel1X5ajsU= github.com/Shopify/toxiproxy v2.1.4+incompatible h1:TKdv8HiTLgE5wdJuEML90aBgNWsokNbMijUGhmcoBJc= @@ -65,9 +71,11 @@ github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8 h1:DujepqpGd1hyOd7a github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/go-avro/avro v0.0.0-20171219232920-444163702c11 h1:yswqe8UdKNWn4kjh1YTaAbvOSPeg95xhW7h4qeICL5E= github.com/go-avro/avro v0.0.0-20171219232920-444163702c11/go.mod h1:kxj6THYP0dmFPk4Z+bijIAhJoGgeBfyOKXMduhvdJPA= +github.com/go-test/deep v1.0.6/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8= github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE= github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= @@ -79,6 +87,8 @@ github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORR github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc= github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/schema v1.1.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU= github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= @@ -111,6 +121,10 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= +github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= +github.com/mongo-go/testdb v0.0.0-20190724200850-a72a12eee610/go.mod h1:xyZcxcSxyRLfj4CDZzyycsGRcwfpY07ncmD2keFr548= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU= github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= @@ -133,6 +147,7 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1 github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/square/mongo-lock v0.0.0-20191001051310-282c90e422d0/go.mod h1:wR5++/O5fpa0UtI+9T8gKIi5jjl10va/EIEMRySqic4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -142,11 +157,15 @@ github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5 h1:bselrhR0Or1vomJZC8ZIjWtbDmn9OYFLX5Ik9alpJpE= golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 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-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -154,9 +173,12 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e h1:N7DeIrjYszNmSW409R3frPPwglRwMkXSBzwVbkOjLLA= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/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/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -167,6 +189,8 @@ gopkg.in/avro.v0 v0.0.0-20171217001914-a730b5802183 h1:PGIdqvwfpMUyUP+QAlAnKTSWQ gopkg.in/avro.v0 v0.0.0-20171217001914-a730b5802183/go.mod h1:FvqrFXt+jCsyQibeRv4xxEJBL5iG2DDW5aeJwzDiq4A= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/jcmturner/aescts.v1 v1.0.1 h1:cVVZBK2b1zY26haWB4vbBiZrfFQnfbTVrE3xZq6hrEw= diff --git a/initialise/initialise.go b/initialise/initialise.go index f12e7022..5633ea3a 100644 --- a/initialise/initialise.go +++ b/initialise/initialise.go @@ -2,7 +2,6 @@ package initialise import ( "context" - "fmt" "github.com/ONSdigital/dp-dataset-api/config" "github.com/ONSdigital/dp-dataset-api/mongo" @@ -15,46 +14,20 @@ import ( // ExternalServiceList represents a list of services type ExternalServiceList struct { - AuditProducer bool GenerateDownloadsProducer bool Graph bool HealthCheck bool MongoDB bool } -// KafkaProducerName : Type for kafka producer name used by iota constants -type KafkaProducerName int - -// Possible names of Kafa Producers -const ( - Audit = iota - GenerateDownloads -) - -var kafkaProducerNames = []string{"Audit", "GenerateDownloads"} - -// Values of the kafka producers names -func (k KafkaProducerName) String() string { - return kafkaProducerNames[k] -} - // GetProducer returns a kafka producer, which might not be initialised yet. -func (e *ExternalServiceList) GetProducer(ctx context.Context, kafkaBrokers []string, topic string, name KafkaProducerName, envMax int) (kafkaProducer *kafka.Producer, err error) { +func (e *ExternalServiceList) GetProducer(ctx context.Context, kafkaBrokers []string, topic string, envMax int) (kafkaProducer *kafka.Producer, err error) { pChannels := kafka.CreateProducerChannels() kafkaProducer, err = kafka.NewProducer(ctx, kafkaBrokers, topic, envMax, pChannels) if err != nil { return } - - switch { - case name == Audit: - e.AuditProducer = true - case name == GenerateDownloads: - e.GenerateDownloadsProducer = true - default: - err = fmt.Errorf("Kafka producer name not recognised: '%s'. Valid names: %v", name.String(), kafkaProducerNames) - } - + e.GenerateDownloadsProducer = true return } diff --git a/instance/dimensions.go b/instance/dimensions.go index 34cd8a5d..eb27814f 100644 --- a/instance/dimensions.go +++ b/instance/dimensions.go @@ -7,9 +7,7 @@ import ( errs "github.com/ONSdigital/dp-dataset-api/apierrors" "github.com/ONSdigital/dp-dataset-api/models" - "github.com/ONSdigital/go-ns/audit" - "github.com/ONSdigital/go-ns/common" - "github.com/ONSdigital/go-ns/request" + dphttp "github.com/ONSdigital/dp-net/http" "github.com/ONSdigital/log.go/log" "github.com/gorilla/mux" ) @@ -18,15 +16,13 @@ import ( // for a specific dimension within an instance func (s *Store) UpdateDimension(w http.ResponseWriter, r *http.Request) { - defer request.DrainBody(r) + defer dphttp.DrainBody(r) ctx := r.Context() vars := mux.Vars(r) instanceID := vars["instance_id"] dimension := vars["dimension"] - auditParams := common.Params{"instance_id": instanceID, "dimension": dimension} - logData := audit.ToLogData(auditParams) - logData["action"] = UpdateDimensionAction + logData := log.Data{"instance_id": instanceID, "dimension": dimension, "action": UpdateDimensionAction} log.Event(ctx, "update instance dimension: update instance dimension", log.INFO, logData) @@ -36,7 +32,6 @@ func (s *Store) UpdateDimension(w http.ResponseWriter, r *http.Request) { log.Event(ctx, "update instance dimension: Failed to GET instance", log.ERROR, log.Error(err), logData) return err } - auditParams["instance_state"] = instance.State // Early return if instance state is invalid if err = models.CheckState("instance", instance.State); err != nil { @@ -98,14 +93,9 @@ func (s *Store) UpdateDimension(w http.ResponseWriter, r *http.Request) { return nil }(); err != nil { - if auditErr := s.Auditor.Record(ctx, UpdateDimensionAction, audit.Unsuccessful, auditParams); auditErr != nil { - err = auditErr - } handleInstanceErr(ctx, err, w, logData) return } - s.Auditor.Record(ctx, UpdateDimensionAction, audit.Successful, auditParams) - log.Event(ctx, "updated instance dimension: request successful", log.INFO, logData) } diff --git a/instance/dimensions_external_test.go b/instance/dimensions_external_test.go index f39957eb..13a352d5 100644 --- a/instance/dimensions_external_test.go +++ b/instance/dimensions_external_test.go @@ -8,13 +8,9 @@ import ( "testing" errs "github.com/ONSdigital/dp-dataset-api/apierrors" - "github.com/ONSdigital/dp-dataset-api/instance" "github.com/ONSdigital/dp-dataset-api/mocks" "github.com/ONSdigital/dp-dataset-api/models" storetest "github.com/ONSdigital/dp-dataset-api/store/datastoretest" - "github.com/ONSdigital/go-ns/audit" - "github.com/ONSdigital/go-ns/audit/auditortest" - "github.com/ONSdigital/go-ns/common" . "github.com/smartystreets/goconvey/convey" ) @@ -41,8 +37,7 @@ func Test_UpdateDimensionReturnsOk(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) @@ -50,21 +45,12 @@ func Test_UpdateDimensionReturnsOk(t *testing.T) { So(permissions.Required.Calls, ShouldEqual, 1) So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 2) So(len(mockedDataStore.UpdateInstanceCalls()), ShouldEqual, 1) - - auditParams := common.Params{"instance_id": "123", "dimension": "age", "instance_state": "edition-confirmed"} - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateDimensionAction, audit.Attempted, common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123", "dimension": "age"}), - auditortest.NewExpectation(instance.UpdateDimensionAction, audit.Successful, auditParams), - ) }) }) }) } func Test_UpdateDimensionReturnsInternalError(t *testing.T) { - auditParams := common.Params{"instance_id": "123", "dimension": "age"} - auditParamsWithCallerIdentity := common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123", "dimension": "age"} - t.Parallel() Convey("Given a PUT request to update a dimension on an instance resource", t, func() { Convey("When service is unable to connect to datastore", func() { @@ -85,8 +71,7 @@ func Test_UpdateDimensionReturnsInternalError(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusInternalServerError) @@ -97,11 +82,6 @@ func Test_UpdateDimensionReturnsInternalError(t *testing.T) { So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) So(len(mockedDataStore.UpdateInstanceCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateDimensionAction, audit.Attempted, auditParamsWithCallerIdentity), - auditortest.NewExpectation(instance.UpdateDimensionAction, audit.Unsuccessful, auditParams), - ) }) }) @@ -122,8 +102,7 @@ func Test_UpdateDimensionReturnsInternalError(t *testing.T) { } datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusInternalServerError) @@ -134,12 +113,6 @@ func Test_UpdateDimensionReturnsInternalError(t *testing.T) { So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) So(len(mockedDataStore.UpdateInstanceCalls()), ShouldEqual, 0) - - auditParamsWithState := common.Params{"instance_id": "123", "dimension": "age", "instance_state": "gobbly gook"} - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateDimensionAction, audit.Attempted, auditParamsWithCallerIdentity), - auditortest.NewExpectation(instance.UpdateDimensionAction, audit.Unsuccessful, auditParamsWithState), - ) }) }) @@ -156,8 +129,7 @@ func Test_UpdateDimensionReturnsInternalError(t *testing.T) { } datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusForbidden) @@ -168,12 +140,6 @@ func Test_UpdateDimensionReturnsInternalError(t *testing.T) { So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) So(len(mockedDataStore.UpdateInstanceCalls()), ShouldEqual, 0) - - auditParamsWithState := common.Params{"instance_id": "123", "dimension": "age", "instance_state": models.PublishedState} - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateDimensionAction, audit.Attempted, auditParamsWithCallerIdentity), - auditortest.NewExpectation(instance.UpdateDimensionAction, audit.Unsuccessful, auditParamsWithState), - ) }) }) @@ -190,8 +156,7 @@ func Test_UpdateDimensionReturnsInternalError(t *testing.T) { } datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -202,11 +167,6 @@ func Test_UpdateDimensionReturnsInternalError(t *testing.T) { So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) So(len(mockedDataStore.UpdateInstanceCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateDimensionAction, audit.Attempted, auditParamsWithCallerIdentity), - auditortest.NewExpectation(instance.UpdateDimensionAction, audit.Unsuccessful, auditParams), - ) }) }) @@ -230,8 +190,7 @@ func Test_UpdateDimensionReturnsInternalError(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -242,12 +201,6 @@ func Test_UpdateDimensionReturnsInternalError(t *testing.T) { So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 2) So(len(mockedDataStore.UpdateInstanceCalls()), ShouldEqual, 0) - - auditParamsWithState := common.Params{"instance_id": "123", "dimension": "notage", "instance_state": models.EditionConfirmedState} - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateDimensionAction, audit.Attempted, common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123", "dimension": "notage"}), - auditortest.NewExpectation(instance.UpdateDimensionAction, audit.Unsuccessful, auditParamsWithState), - ) }) }) @@ -266,8 +219,7 @@ func Test_UpdateDimensionReturnsInternalError(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusBadRequest) @@ -278,128 +230,6 @@ func Test_UpdateDimensionReturnsInternalError(t *testing.T) { So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 2) So(len(mockedDataStore.UpdateInstanceCalls()), ShouldEqual, 0) - - auditParamsWithState := common.Params{"instance_id": "123", "dimension": "age", "instance_state": models.CompletedState} - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateDimensionAction, audit.Attempted, auditParamsWithCallerIdentity), - auditortest.NewExpectation(instance.UpdateDimensionAction, audit.Unsuccessful, auditParamsWithState), - ) - }) - }) - }) -} - -func Test_UpdateDimensionAuditErrors(t *testing.T) { - auditParamsWithCallerIdentity := common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123", "dimension": "age"} - - t.Parallel() - Convey("Given audit action 'attempted' fails", t, func() { - auditor := auditortest.NewErroring(instance.UpdateDimensionAction, audit.Attempted) - - Convey("When a PUT request is made to update dimension on an instance resource", func() { - body := strings.NewReader(`{"label":"ages", "description": "A range of ages between 18 and 60"}`) - r, err := createRequestWithToken("PUT", "http://localhost:22000/instances/123/dimensions/age", body) - So(err, ShouldBeNil) - w := httptest.NewRecorder() - - mockedDataStore := &storetest.StorerMock{} - - datasetPermissions := mocks.NewAuthHandlerMock() - permissions := mocks.NewAuthHandlerMock() - - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - datasetAPI.Router.ServeHTTP(w, r) - - Convey("Then response returns internal server error (500)", func() { - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateDimensionAction, audit.Attempted, auditParamsWithCallerIdentity), - ) - }) - }) - }) - - Convey("Given audit action 'unsuccessful' fails", t, func() { - auditor := auditortest.NewErroring(instance.UpdateDimensionAction, audit.Unsuccessful) - - Convey("When a PUT request is made to update dimension on an instance resource", func() { - body := strings.NewReader("{") - r, err := createRequestWithToken("PUT", "http://localhost:22000/instances/123/dimensions/age", body) - So(err, ShouldBeNil) - w := httptest.NewRecorder() - - mockedDataStore := &storetest.StorerMock{ - GetInstanceFunc: func(id string) (*models.Instance, error) { - return &models.Instance{State: models.CreatedState}, nil - }, - } - - datasetPermissions := mocks.NewAuthHandlerMock() - permissions := mocks.NewAuthHandlerMock() - - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - datasetAPI.Router.ServeHTTP(w, r) - - Convey("Then response returns internal server error (500)", func() { - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 1) - So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 2) - So(len(mockedDataStore.UpdateInstanceCalls()), ShouldEqual, 0) - - auditParamsWithState := common.Params{"instance_id": "123", "dimension": "age", "instance_state": models.CreatedState} - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateDimensionAction, audit.Attempted, auditParamsWithCallerIdentity), - auditortest.NewExpectation(instance.UpdateDimensionAction, audit.Unsuccessful, auditParamsWithState), - ) - }) - }) - }) - - Convey("Given audit action 'successful' fails", t, func() { - auditor := auditortest.NewErroring(instance.AddInstanceAction, audit.Successful) - - Convey("When a PUT request is made to update dimension on an instance resource", func() { - body := strings.NewReader(`{"label":"ages", "description": "A range of ages between 18 and 60"}`) - r, err := createRequestWithToken("PUT", "http://localhost:22000/instances/123/dimensions/age", body) - So(err, ShouldBeNil) - w := httptest.NewRecorder() - - mockedDataStore := &storetest.StorerMock{ - GetInstanceFunc: func(id string) (*models.Instance, error) { - return &models.Instance{State: models.EditionConfirmedState, - InstanceID: "123", - Dimensions: []models.Dimension{{Name: "age", ID: "age"}}}, nil - }, - UpdateInstanceFunc: func(ctx context.Context, id string, i *models.Instance) error { - return nil - }, - } - - datasetPermissions := mocks.NewAuthHandlerMock() - permissions := mocks.NewAuthHandlerMock() - - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - datasetAPI.Router.ServeHTTP(w, r) - - Convey("Then response returns status ok (200)", func() { - So(w.Code, ShouldEqual, http.StatusOK) - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 1) - So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 2) - So(len(mockedDataStore.UpdateInstanceCalls()), ShouldEqual, 1) - - auditParamsWithState := common.Params{"instance_id": "123", "dimension": "age", "instance_state": "edition-confirmed"} - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateDimensionAction, audit.Attempted, auditParamsWithCallerIdentity), - auditortest.NewExpectation(instance.UpdateDimensionAction, audit.Successful, auditParamsWithState), - ) }) }) }) diff --git a/instance/editions.go b/instance/editions.go index 039ddd61..a4757c7d 100644 --- a/instance/editions.go +++ b/instance/editions.go @@ -5,15 +5,11 @@ import ( errs "github.com/ONSdigital/dp-dataset-api/apierrors" "github.com/ONSdigital/dp-dataset-api/models" - "github.com/ONSdigital/go-ns/audit" - "github.com/ONSdigital/go-ns/common" "github.com/ONSdigital/log.go/log" ) func (s *Store) confirmEdition(ctx context.Context, datasetID, edition, instanceID string) (*models.EditionUpdate, error) { - auditParams := common.Params{"dataset_id": datasetID, "instance_id": instanceID, "edition": edition} - logData := audit.ToLogData(auditParams) - + logData := log.Data{"dataset_id": datasetID, "instance_id": instanceID, "edition": edition} var editionDoc *models.EditionUpdate var action string var err error @@ -30,10 +26,6 @@ func (s *Store) confirmEdition(ctx context.Context, datasetID, edition, instance log.Event(ctx, "confirm edition: edition not found, creating", log.INFO, logData) action = CreateEditionAction - if auditErr := s.Auditor.Record(ctx, action, audit.Attempted, auditParams); auditErr != nil { - return nil, action, auditErr - } - editionDoc, err = models.CreateEdition(s.Host, datasetID, edition) if err != nil { return nil, action, err @@ -54,9 +46,6 @@ func (s *Store) confirmEdition(ctx context.Context, datasetID, edition, instance } log.Event(ctx, "confirm edition: edition found, updating", log.INFO, logData) - if auditErr := s.Auditor.Record(ctx, action, audit.Attempted, auditParams); auditErr != nil { - return nil, action, auditErr - } if err = editionDoc.UpdateLinks(ctx, s.Host); err != nil { log.Event(ctx, "confirm edition: unable to update edition links", log.ERROR, log.Error(err), logData) @@ -73,13 +62,9 @@ func (s *Store) confirmEdition(ctx context.Context, datasetID, edition, instance return editionDoc, action, nil }(); err != nil { - if auditErr := s.Auditor.Record(ctx, action, audit.Unsuccessful, auditParams); auditErr != nil { - return nil, auditErr - } return nil, err } - s.Auditor.Record(ctx, action, audit.Successful, auditParams) log.Event(ctx, "confirm edition: created/updated edition", log.INFO, logData) return editionDoc, nil } diff --git a/instance/editions_internal_test.go b/instance/editions_internal_test.go index 574318e2..cb9c6932 100644 --- a/instance/editions_internal_test.go +++ b/instance/editions_internal_test.go @@ -7,10 +7,10 @@ import ( "testing" "context" + errs "github.com/ONSdigital/dp-dataset-api/apierrors" "github.com/ONSdigital/dp-dataset-api/models" - "github.com/ONSdigital/dp-dataset-api/store/datastoretest" - "github.com/ONSdigital/go-ns/audit/auditortest" + storetest "github.com/ONSdigital/dp-dataset-api/store/datastoretest" . "github.com/smartystreets/goconvey/convey" ) @@ -28,9 +28,8 @@ func Test_ConfirmEditionReturnsOK(t *testing.T) { host := "example.com" s := Store{ - Storer: mockedDataStore, - Host: host, - Auditor: auditortest.New(), + Storer: mockedDataStore, + Host: host, } Convey("when confirmEdition is called", func() { @@ -100,7 +99,6 @@ func Test_ConfirmEditionReturnsOK(t *testing.T) { EnableDetachDataset: true, Storer: mockedDataStore, Host: host, - Auditor: auditortest.New(), } Convey("when confirmEdition is called again", func() { @@ -165,9 +163,8 @@ func Test_ConfirmEditionReturnsOK(t *testing.T) { host := "example.com" s := Store{ - Storer: mockedDataStore, - Host: host, - Auditor: auditortest.New(), + Storer: mockedDataStore, + Host: host, } Convey("when confirmEdition is called", func() { datasetID := "1234" @@ -204,9 +201,8 @@ func Test_ConfirmEditionReturnsError(t *testing.T) { host := "example.com" s := Store{ - Storer: mockedDataStore, - Host: host, - Auditor: auditortest.New(), + Storer: mockedDataStore, + Host: host, } Convey("when confirmEdition is called", func() { datasetID := "1234" @@ -245,9 +241,8 @@ func Test_ConfirmEditionReturnsError(t *testing.T) { host := "example.com" s := Store{ - Storer: mockedDataStore, - Host: host, - Auditor: auditortest.New(), + Storer: mockedDataStore, + Host: host, } Convey("when confirmEdition is called", func() { @@ -283,7 +278,6 @@ func Test_ConfirmEditionReturnsError(t *testing.T) { s := Store{ Storer: mockedDataStore, Host: host, - Auditor: auditortest.New(), EnableDetachDataset: true, } @@ -320,7 +314,6 @@ func Test_ConfirmEditionReturnsError(t *testing.T) { s := Store{ Storer: mockedDataStore, Host: host, - Auditor: auditortest.New(), EnableDetachDataset: true, } @@ -386,9 +379,8 @@ func Test_ConfirmEditionReturnsError(t *testing.T) { host := "example.com" s := Store{ - Storer: mockedDataStore, - Host: host, - Auditor: auditortest.New(), + Storer: mockedDataStore, + Host: host, } Convey("when confirmEdition is called and updating the datastore for the edition fails", func() { diff --git a/instance/event.go b/instance/event.go index 0a14284f..91678c83 100644 --- a/instance/event.go +++ b/instance/event.go @@ -8,8 +8,6 @@ import ( errs "github.com/ONSdigital/dp-dataset-api/apierrors" "github.com/ONSdigital/dp-dataset-api/models" - "github.com/ONSdigital/go-ns/audit" - "github.com/ONSdigital/go-ns/common" "github.com/ONSdigital/log.go/log" "github.com/gorilla/mux" ) @@ -38,7 +36,6 @@ func (s *Store) AddEvent(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) instanceID := vars["instance_id"] data := log.Data{"instance_id": instanceID, "action": AddInstanceEventAction} - ap := common.Params{"instance_id": instanceID} if err := func() error { event, err := unmarshalEvent(r.Body) @@ -59,17 +56,9 @@ func (s *Store) AddEvent(w http.ResponseWriter, r *http.Request) { return nil }(); err != nil { - if auditErr := s.Auditor.Record(ctx, AddInstanceEventAction, audit.Unsuccessful, ap); auditErr != nil { - err = auditErr - } handleInstanceErr(ctx, err, w, data) return } - if auditErr := s.Auditor.Record(ctx, AddInstanceEventAction, audit.Successful, ap); auditErr != nil { - handleInstanceErr(ctx, auditErr, w, data) - return - } - log.Event(ctx, "add instance event: request successful", log.INFO, data) } diff --git a/instance/import.go b/instance/import.go index 68afa973..7ecd169b 100644 --- a/instance/import.go +++ b/instance/import.go @@ -10,9 +10,7 @@ import ( errs "github.com/ONSdigital/dp-dataset-api/apierrors" "github.com/ONSdigital/dp-dataset-api/models" - "github.com/ONSdigital/go-ns/audit" - "github.com/ONSdigital/go-ns/common" - "github.com/ONSdigital/go-ns/request" + dphttp "github.com/ONSdigital/dp-net/http" "github.com/ONSdigital/log.go/log" "github.com/gorilla/mux" "github.com/pkg/errors" @@ -25,9 +23,7 @@ func (s *Store) UpdateObservations(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) instanceID := vars["instance_id"] insert := vars["inserted_observations"] - auditParams := common.Params{"instance_id": instanceID, "inserted_observations": insert} - logData := audit.ToLogData(auditParams) - logData["action"] = UpdateInsertedObservationsAction + logData := log.Data{"instance_id": instanceID, "inserted_observations": insert, "action": UpdateInsertedObservationsAction} if err := func() error { observations, err := strconv.ParseInt(insert, 10, 64) @@ -43,29 +39,22 @@ func (s *Store) UpdateObservations(w http.ResponseWriter, r *http.Request) { return nil }(); err != nil { - if auditErr := s.Auditor.Record(ctx, UpdateInsertedObservationsAction, audit.Unsuccessful, auditParams); auditErr != nil { - err = auditErr - } handleInstanceErr(ctx, err, w, logData) return } - s.Auditor.Record(ctx, UpdateInsertedObservationsAction, audit.Successful, auditParams) - log.Event(ctx, "update imported observations: request successful", log.INFO, logData) } // UpdateImportTask updates any task in the request body against an instance func (s *Store) UpdateImportTask(w http.ResponseWriter, r *http.Request) { - defer request.DrainBody(r) + defer dphttp.DrainBody(r) ctx := r.Context() vars := mux.Vars(r) instanceID := vars["instance_id"] - auditParams := common.Params{"instance_id": instanceID} - logData := audit.ToLogData(auditParams) - logData["action"] = UpdateImportTasksAction + logData := log.Data{"instance_id": instanceID, "action": UpdateImportTasksAction} defer r.Body.Close() updateErr := func() *taskError { @@ -157,18 +146,11 @@ func (s *Store) UpdateImportTask(w http.ResponseWriter, r *http.Request) { }() if updateErr != nil { - if auditErr := s.Auditor.Record(ctx, UpdateImportTasksAction, audit.Unsuccessful, auditParams); auditErr != nil { - updateErr = &taskError{errs.ErrInternalServer, http.StatusInternalServerError} - } log.Event(ctx, "updateImportTask endpoint: request unsuccessful", log.ERROR, log.Error(updateErr), logData) http.Error(w, updateErr.Error(), updateErr.status) return } - if auditErr := s.Auditor.Record(ctx, UpdateImportTasksAction, audit.Successful, auditParams); auditErr != nil { - return - } - log.Event(ctx, "updateImportTask endpoint: request successful", log.INFO, logData) } diff --git a/instance/import_external_test.go b/instance/import_external_test.go index f82241ad..579cb07e 100644 --- a/instance/import_external_test.go +++ b/instance/import_external_test.go @@ -9,13 +9,9 @@ import ( "testing" errs "github.com/ONSdigital/dp-dataset-api/apierrors" - "github.com/ONSdigital/dp-dataset-api/instance" "github.com/ONSdigital/dp-dataset-api/mocks" "github.com/ONSdigital/dp-dataset-api/models" storetest "github.com/ONSdigital/dp-dataset-api/store/datastoretest" - "github.com/ONSdigital/go-ns/audit" - "github.com/ONSdigital/go-ns/audit/auditortest" - "github.com/ONSdigital/go-ns/common" . "github.com/smartystreets/goconvey/convey" ) @@ -39,9 +35,8 @@ func Test_InsertedObservationsReturnsOk(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) @@ -49,11 +44,6 @@ func Test_InsertedObservationsReturnsOk(t *testing.T) { So(permissions.Required.Calls, ShouldEqual, 1) So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) So(len(mockedDataStore.UpdateObservationInsertedCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{instance.UpdateInsertedObservationsAction, audit.Attempted, common.Params{"caller_identity": "someone@ons.gov.uk", "inserted_observations": "200", "instance_id": "123"}}, - auditortest.Expected{instance.UpdateInsertedObservationsAction, audit.Successful, common.Params{"instance_id": "123", "inserted_observations": "200"}}, - ) }) }) }) @@ -76,9 +66,8 @@ func Test_InsertedObservationsReturnsError(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusInternalServerError) @@ -89,11 +78,6 @@ func Test_InsertedObservationsReturnsError(t *testing.T) { So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) So(len(mockedDataStore.UpdateObservationInsertedCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{instance.UpdateInsertedObservationsAction, audit.Attempted, common.Params{"caller_identity": "someone@ons.gov.uk", "inserted_observations": "200", "instance_id": "123"}}, - auditortest.Expected{instance.UpdateInsertedObservationsAction, audit.Unsuccessful, common.Params{"instance_id": "123"}}, - ) }) }) @@ -113,9 +97,8 @@ func Test_InsertedObservationsReturnsError(t *testing.T) { } datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -126,11 +109,6 @@ func Test_InsertedObservationsReturnsError(t *testing.T) { So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) So(len(mockedDataStore.UpdateObservationInsertedCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{instance.UpdateInsertedObservationsAction, audit.Attempted, common.Params{"caller_identity": "someone@ons.gov.uk", "inserted_observations": "200", "instance_id": "123"}}, - auditortest.Expected{instance.UpdateInsertedObservationsAction, audit.Unsuccessful, common.Params{"instance_id": "123", "inserted_observations": "200"}}, - ) }) }) @@ -147,9 +125,8 @@ func Test_InsertedObservationsReturnsError(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusBadRequest) @@ -160,118 +137,6 @@ func Test_InsertedObservationsReturnsError(t *testing.T) { So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) So(len(mockedDataStore.UpdateObservationInsertedCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{instance.UpdateInsertedObservationsAction, audit.Attempted, common.Params{"caller_identity": "someone@ons.gov.uk", "inserted_observations": "aa12a", "instance_id": "123"}}, - auditortest.Expected{instance.UpdateInsertedObservationsAction, audit.Unsuccessful, common.Params{"instance_id": "123", "inserted_observations": "aa12a"}}, - ) - }) - }) - }) -} - -func Test_InsertedObservations_AuditFailure(t *testing.T) { - t.Parallel() - Convey("Given a request to update instance resource with inserted observations is made", t, func() { - Convey(`When the subsequent audit action 'attempted' fails`, func() { - r, err := createRequestWithToken("PUT", "http://localhost:21800/instances/123/inserted_observations/200", nil) - So(err, ShouldBeNil) - w := httptest.NewRecorder() - - mockedDataStore := &storetest.StorerMock{} - datasetPermissions := mocks.NewAuthHandlerMock() - permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.NewErroring(instance.UpdateInsertedObservationsAction, audit.Attempted) - - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - datasetAPI.Router.ServeHTTP(w, r) - - Convey("Then a 500 status is returned", func() { - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 0) - - auditParams := common.Params{"caller_identity": "someone@ons.gov.uk", "inserted_observations": "200", "instance_id": "123"} - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateInsertedObservationsAction, audit.Attempted, auditParams), - ) - }) - }) - - Convey(`When the request parameter 'inserted_observations' is not an integer - and the subsequent audit action 'unsuccessful' fails`, func() { - r, err := createRequestWithToken("PUT", "http://localhost:21800/instances/123/inserted_observations/1.5", nil) - So(err, ShouldBeNil) - w := httptest.NewRecorder() - - mockedDataStore := &storetest.StorerMock{ - GetInstanceFunc: func(id string) (*models.Instance, error) { - return &models.Instance{State: models.CreatedState}, nil - }, - } - - datasetPermissions := mocks.NewAuthHandlerMock() - permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.NewErroring(instance.UpdateInsertedObservationsAction, audit.Unsuccessful) - - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - datasetAPI.Router.ServeHTTP(w, r) - - Convey("Then a 500 status is returned", func() { - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) - - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 1) - - So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) - So(len(mockedDataStore.UpdateObservationInsertedCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateInsertedObservationsAction, audit.Attempted, common.Params{"caller_identity": "someone@ons.gov.uk", "inserted_observations": "1.5", "instance_id": "123"}), - auditortest.NewExpectation(instance.UpdateInsertedObservationsAction, audit.Unsuccessful, common.Params{"instance_id": "123", "inserted_observations": "1.5"}), - ) - }) - }) - - Convey(`When the request successfully updates instance resource but - the subsequent audit action 'successful' fails`, func() { - - r, err := createRequestWithToken("PUT", "http://localhost:21800/instances/123/inserted_observations/200", nil) - So(err, ShouldBeNil) - w := httptest.NewRecorder() - - mockedDataStore := &storetest.StorerMock{ - GetInstanceFunc: func(id string) (*models.Instance, error) { - return &models.Instance{State: models.CreatedState}, nil - }, - UpdateObservationInsertedFunc: func(id string, observations int64) error { - return nil - }, - } - - datasetPermissions := mocks.NewAuthHandlerMock() - permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.NewErroring(instance.UpdateInsertedObservationsAction, audit.Unsuccessful) - - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - datasetAPI.Router.ServeHTTP(w, r) - - Convey("Then a 200 status is returned", func() { - So(w.Code, ShouldEqual, http.StatusOK) - - So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) - So(len(mockedDataStore.UpdateObservationInsertedCalls()), ShouldEqual, 1) - - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateInsertedObservationsAction, audit.Attempted, common.Params{"caller_identity": "someone@ons.gov.uk", "inserted_observations": "200", "instance_id": "123"}), - auditortest.NewExpectation(instance.UpdateInsertedObservationsAction, audit.Successful, common.Params{"instance_id": "123", "inserted_observations": "200"}), - ) }) }) }) @@ -298,9 +163,8 @@ func Test_UpdateImportTask_UpdateImportObservationsReturnsOk(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) @@ -309,11 +173,6 @@ func Test_UpdateImportTask_UpdateImportObservationsReturnsOk(t *testing.T) { So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) So(len(mockedDataStore.UpdateImportObservationsTaskStateCalls()), ShouldEqual, 1) So(len(mockedDataStore.UpdateBuildHierarchyTaskStateCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Attempted, common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123"}), - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Successful, common.Params{"instance_id": "123"}), - ) }) }) }) @@ -337,9 +196,8 @@ func Test_UpdateImportTaskRetrunsError(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusInternalServerError) @@ -351,11 +209,6 @@ func Test_UpdateImportTaskRetrunsError(t *testing.T) { So(len(mockedDataStore.UpdateImportObservationsTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildHierarchyTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildSearchTaskStateCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Attempted, common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123"}), - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Unsuccessful, common.Params{"instance_id": "123"}), - ) }) }) @@ -374,9 +227,8 @@ func Test_UpdateImportTaskRetrunsError(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -388,11 +240,6 @@ func Test_UpdateImportTaskRetrunsError(t *testing.T) { So(len(mockedDataStore.UpdateImportObservationsTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildHierarchyTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildSearchTaskStateCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Attempted, common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123"}), - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Unsuccessful, common.Params{"instance_id": "123"}), - ) }) }) @@ -414,9 +261,8 @@ func Test_UpdateImportTaskRetrunsError(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusForbidden) @@ -426,20 +272,12 @@ func Test_UpdateImportTaskRetrunsError(t *testing.T) { So(permissions.Required.Calls, ShouldEqual, 1) So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) So(len(mockedDataStore.AddVersionDetailsToInstanceCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateInstanceAction, audit.Attempted, common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123"}), - auditortest.NewExpectation(instance.UpdateInstanceAction, audit.Unsuccessful, common.Params{"instance_id": "123", "instance_state": models.PublishedState}), - ) }) }) }) } func Test_UpdateImportTask_UpdateImportObservationsReturnsError(t *testing.T) { - auditParamsWithCallerIdentity := common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123"} - auditParams := common.Params{"instance_id": "123"} - t.Parallel() Convey("Given a PUT request to update an instance resource with import observations", t, func() { Convey("When the request body contains invalid json", func() { @@ -460,9 +298,8 @@ func Test_UpdateImportTask_UpdateImportObservationsReturnsError(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusBadRequest) @@ -474,11 +311,6 @@ func Test_UpdateImportTask_UpdateImportObservationsReturnsError(t *testing.T) { So(len(mockedDataStore.UpdateImportObservationsTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildHierarchyTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildSearchTaskStateCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Attempted, auditParamsWithCallerIdentity), - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Unsuccessful, auditParams), - ) }) }) @@ -500,9 +332,8 @@ func Test_UpdateImportTask_UpdateImportObservationsReturnsError(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusBadRequest) @@ -513,11 +344,6 @@ func Test_UpdateImportTask_UpdateImportObservationsReturnsError(t *testing.T) { So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) So(len(mockedDataStore.UpdateImportObservationsTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildHierarchyTaskStateCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Attempted, auditParamsWithCallerIdentity), - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Unsuccessful, auditParams), - ) }) }) @@ -538,9 +364,8 @@ func Test_UpdateImportTask_UpdateImportObservationsReturnsError(t *testing.T) { } datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusBadRequest) @@ -551,11 +376,6 @@ func Test_UpdateImportTask_UpdateImportObservationsReturnsError(t *testing.T) { So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) So(len(mockedDataStore.UpdateImportObservationsTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildHierarchyTaskStateCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Attempted, auditParamsWithCallerIdentity), - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Unsuccessful, auditParams), - ) }) }) @@ -577,9 +397,8 @@ func Test_UpdateImportTask_UpdateImportObservationsReturnsError(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusInternalServerError) @@ -589,20 +408,12 @@ func Test_UpdateImportTask_UpdateImportObservationsReturnsError(t *testing.T) { So(permissions.Required.Calls, ShouldEqual, 1) So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) So(len(mockedDataStore.UpdateImportObservationsTaskStateCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Attempted, auditParamsWithCallerIdentity), - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Unsuccessful, auditParams), - ) }) }) }) } func Test_UpdateImportTask_BuildHierarchyTaskReturnsError(t *testing.T) { - auditParamsWithCallerIdentity := common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123"} - auditParams := common.Params{"instance_id": "123"} - t.Parallel() Convey("Given a PUT request to update an instance resource with import task 'build hierarchies'", t, func() { Convey("When the request body contains invalid json", func() { @@ -623,9 +434,8 @@ func Test_UpdateImportTask_BuildHierarchyTaskReturnsError(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusBadRequest) @@ -637,11 +447,6 @@ func Test_UpdateImportTask_BuildHierarchyTaskReturnsError(t *testing.T) { So(len(mockedDataStore.UpdateImportObservationsTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildHierarchyTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildSearchTaskStateCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Attempted, auditParamsWithCallerIdentity), - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Unsuccessful, auditParams), - ) }) }) @@ -663,9 +468,8 @@ func Test_UpdateImportTask_BuildHierarchyTaskReturnsError(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusBadRequest) @@ -677,11 +481,6 @@ func Test_UpdateImportTask_BuildHierarchyTaskReturnsError(t *testing.T) { So(len(mockedDataStore.UpdateImportObservationsTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildHierarchyTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildSearchTaskStateCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Attempted, auditParamsWithCallerIdentity), - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Unsuccessful, auditParams), - ) }) }) @@ -704,9 +503,8 @@ func Test_UpdateImportTask_BuildHierarchyTaskReturnsError(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusBadRequest) @@ -718,11 +516,6 @@ func Test_UpdateImportTask_BuildHierarchyTaskReturnsError(t *testing.T) { So(len(mockedDataStore.UpdateImportObservationsTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildHierarchyTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildSearchTaskStateCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Attempted, auditParamsWithCallerIdentity), - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Unsuccessful, auditParams), - ) }) }) @@ -744,9 +537,8 @@ func Test_UpdateImportTask_BuildHierarchyTaskReturnsError(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusBadRequest) @@ -758,11 +550,6 @@ func Test_UpdateImportTask_BuildHierarchyTaskReturnsError(t *testing.T) { So(len(mockedDataStore.UpdateImportObservationsTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildHierarchyTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildSearchTaskStateCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Attempted, auditParamsWithCallerIdentity), - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Unsuccessful, auditParams), - ) }) }) @@ -784,9 +571,8 @@ func Test_UpdateImportTask_BuildHierarchyTaskReturnsError(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusBadRequest) @@ -798,11 +584,6 @@ func Test_UpdateImportTask_BuildHierarchyTaskReturnsError(t *testing.T) { So(len(mockedDataStore.UpdateImportObservationsTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildHierarchyTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildSearchTaskStateCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Attempted, auditParamsWithCallerIdentity), - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Unsuccessful, auditParams), - ) }) }) @@ -824,9 +605,8 @@ func Test_UpdateImportTask_BuildHierarchyTaskReturnsError(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusBadRequest) @@ -838,11 +618,6 @@ func Test_UpdateImportTask_BuildHierarchyTaskReturnsError(t *testing.T) { So(len(mockedDataStore.UpdateImportObservationsTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildHierarchyTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildSearchTaskStateCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Attempted, auditParamsWithCallerIdentity), - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Unsuccessful, auditParams), - ) }) }) @@ -864,9 +639,8 @@ func Test_UpdateImportTask_BuildHierarchyTaskReturnsError(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -878,11 +652,6 @@ func Test_UpdateImportTask_BuildHierarchyTaskReturnsError(t *testing.T) { So(len(mockedDataStore.UpdateImportObservationsTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildHierarchyTaskStateCalls()), ShouldEqual, 1) So(len(mockedDataStore.UpdateBuildSearchTaskStateCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Attempted, auditParamsWithCallerIdentity), - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Unsuccessful, auditParams), - ) }) }) @@ -904,9 +673,8 @@ func Test_UpdateImportTask_BuildHierarchyTaskReturnsError(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusInternalServerError) @@ -918,18 +686,12 @@ func Test_UpdateImportTask_BuildHierarchyTaskReturnsError(t *testing.T) { So(len(mockedDataStore.UpdateImportObservationsTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildHierarchyTaskStateCalls()), ShouldEqual, 1) So(len(mockedDataStore.UpdateBuildSearchTaskStateCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Attempted, auditParamsWithCallerIdentity), - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Unsuccessful, auditParams), - ) }) }) }) } func Test_UpdateImportTask_BuildHierarchyTaskReturnsOk(t *testing.T) { - t.Parallel() Convey("Given a PUT request to update an instance resource with import task 'build hierarchies'", t, func() { Convey("When the request body is valid", func() { @@ -950,9 +712,8 @@ func Test_UpdateImportTask_BuildHierarchyTaskReturnsOk(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) @@ -961,20 +722,12 @@ func Test_UpdateImportTask_BuildHierarchyTaskReturnsOk(t *testing.T) { So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) So(len(mockedDataStore.UpdateImportObservationsTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildHierarchyTaskStateCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Attempted, common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123"}), - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Successful, common.Params{"instance_id": "123"}), - ) }) }) }) } func Test_UpdateImportTask_UpdateBuildSearchIndexTask_Failure(t *testing.T) { - auditParams := common.Params{"instance_id": "123"} - auditParamsWithCallerIdentity := common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123"} - t.Parallel() Convey("Given a PUT request to update an instance resource with import task 'build search indexes'", t, func() { Convey("When the request body contains invalid json", func() { @@ -995,9 +748,8 @@ func Test_UpdateImportTask_UpdateBuildSearchIndexTask_Failure(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusBadRequest) @@ -1009,11 +761,6 @@ func Test_UpdateImportTask_UpdateBuildSearchIndexTask_Failure(t *testing.T) { So(len(mockedDataStore.UpdateImportObservationsTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildHierarchyTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildSearchTaskStateCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Attempted, auditParamsWithCallerIdentity), - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Unsuccessful, auditParams), - ) }) }) @@ -1035,9 +782,8 @@ func Test_UpdateImportTask_UpdateBuildSearchIndexTask_Failure(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusBadRequest) @@ -1049,11 +795,6 @@ func Test_UpdateImportTask_UpdateBuildSearchIndexTask_Failure(t *testing.T) { So(len(mockedDataStore.UpdateImportObservationsTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildHierarchyTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildSearchTaskStateCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Attempted, auditParamsWithCallerIdentity), - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Unsuccessful, auditParams), - ) }) }) @@ -1074,9 +815,8 @@ func Test_UpdateImportTask_UpdateBuildSearchIndexTask_Failure(t *testing.T) { } datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusBadRequest) @@ -1088,11 +828,6 @@ func Test_UpdateImportTask_UpdateBuildSearchIndexTask_Failure(t *testing.T) { So(len(mockedDataStore.UpdateImportObservationsTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildHierarchyTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildSearchTaskStateCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Attempted, auditParamsWithCallerIdentity), - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Unsuccessful, auditParams), - ) }) }) @@ -1114,9 +849,8 @@ func Test_UpdateImportTask_UpdateBuildSearchIndexTask_Failure(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusBadRequest) @@ -1128,11 +862,6 @@ func Test_UpdateImportTask_UpdateBuildSearchIndexTask_Failure(t *testing.T) { So(len(mockedDataStore.UpdateImportObservationsTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildHierarchyTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildSearchTaskStateCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Attempted, auditParamsWithCallerIdentity), - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Unsuccessful, auditParams), - ) }) }) @@ -1154,9 +883,8 @@ func Test_UpdateImportTask_UpdateBuildSearchIndexTask_Failure(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusBadRequest) @@ -1168,11 +896,6 @@ func Test_UpdateImportTask_UpdateBuildSearchIndexTask_Failure(t *testing.T) { So(len(mockedDataStore.UpdateImportObservationsTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildHierarchyTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildSearchTaskStateCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Attempted, auditParamsWithCallerIdentity), - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Unsuccessful, auditParams), - ) }) }) @@ -1194,9 +917,8 @@ func Test_UpdateImportTask_UpdateBuildSearchIndexTask_Failure(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusBadRequest) @@ -1208,11 +930,6 @@ func Test_UpdateImportTask_UpdateBuildSearchIndexTask_Failure(t *testing.T) { So(len(mockedDataStore.UpdateImportObservationsTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildHierarchyTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildSearchTaskStateCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Attempted, auditParamsWithCallerIdentity), - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Unsuccessful, auditParams), - ) }) }) @@ -1234,8 +951,8 @@ func Test_UpdateImportTask_UpdateBuildSearchIndexTask_Failure(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -1247,11 +964,6 @@ func Test_UpdateImportTask_UpdateBuildSearchIndexTask_Failure(t *testing.T) { So(len(mockedDataStore.UpdateImportObservationsTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildHierarchyTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildSearchTaskStateCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Attempted, auditParamsWithCallerIdentity), - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Unsuccessful, auditParams), - ) }) }) @@ -1273,9 +985,8 @@ func Test_UpdateImportTask_UpdateBuildSearchIndexTask_Failure(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusInternalServerError) @@ -1287,18 +998,12 @@ func Test_UpdateImportTask_UpdateBuildSearchIndexTask_Failure(t *testing.T) { So(len(mockedDataStore.UpdateImportObservationsTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildHierarchyTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildSearchTaskStateCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Attempted, auditParamsWithCallerIdentity), - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Unsuccessful, auditParams), - ) }) }) }) } func Test_UpdateImportTask_UpdateBuildSearchIndexReturnsOk(t *testing.T) { - t.Parallel() Convey("Given a PUT request to update an instance resource with import task 'build_search_indexes'", t, func() { Convey("When the request body is valid", func() { @@ -1319,9 +1024,8 @@ func Test_UpdateImportTask_UpdateBuildSearchIndexReturnsOk(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) @@ -1331,257 +1035,6 @@ func Test_UpdateImportTask_UpdateBuildSearchIndexReturnsOk(t *testing.T) { So(len(mockedDataStore.UpdateImportObservationsTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildHierarchyTaskStateCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateBuildSearchTaskStateCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Attempted, common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123"}), - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Successful, common.Params{"instance_id": "123"}), - ) - }) - }) - }) -} - -func Test_UpdateImportTask_AuditAttemptFailure(t *testing.T) { - t.Parallel() - Convey("Given audit action attempted returns an error", t, func() { - auditor := auditortest.NewErroring(instance.UpdateImportTasksAction, audit.Attempted) - - Convey("When update import task is called", func() { - body := strings.NewReader(`{"build_search_indexes":[{"state":"completed"}]}`) - r, err := createRequestWithToken("PUT", "http://localhost:21800/instances/123/import_tasks", body) - So(err, ShouldBeNil) - w := httptest.NewRecorder() - - mockedDataStore := &storetest.StorerMock{} - datasetPermissions := mocks.NewAuthHandlerMock() - permissions := mocks.NewAuthHandlerMock() - - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - datasetAPI.Router.ServeHTTP(w, r) - - Convey("Then a 500 status is returned", func() { - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) - - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 0) - So(len(mockedDataStore.UpdateImportObservationsTaskStateCalls()), ShouldEqual, 0) - So(len(mockedDataStore.UpdateBuildHierarchyTaskStateCalls()), ShouldEqual, 0) - So(len(mockedDataStore.UpdateBuildSearchTaskStateCalls()), ShouldEqual, 0) - - auditParams := common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123"} - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Attempted, auditParams), - ) - }) - }) - }) -} - -func Test_UpdateImportTask_AuditUnsuccessfulError(t *testing.T) { - auditParams := common.Params{"instance_id": "123"} - auditParamsWithCallerIdentity := common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123"} - - t.Parallel() - Convey("Given audit action unsuccessful returns an error", t, func() { - Convey("When the request body fails to marshal into the updateImportTask model", func() { - auditor := auditortest.NewErroring(instance.UpdateImportTasksAction, audit.Unsuccessful) - body := strings.NewReader(`THIS IS NOT JSON`) - r, err := createRequestWithToken("PUT", "http://localhost:21800/instances/123/import_tasks", body) - So(err, ShouldBeNil) - w := httptest.NewRecorder() - - mockedDataStore := &storetest.StorerMock{ - GetInstanceFunc: func(id string) (*models.Instance, error) { - return &models.Instance{State: models.CreatedState}, nil - }, - } - - datasetPermissions := mocks.NewAuthHandlerMock() - permissions := mocks.NewAuthHandlerMock() - - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - datasetAPI.Router.ServeHTTP(w, r) - - Convey("Then a 500 status is returned", func() { - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) - - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 1) - So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) - So(len(mockedDataStore.UpdateImportObservationsTaskStateCalls()), ShouldEqual, 0) - So(len(mockedDataStore.UpdateBuildHierarchyTaskStateCalls()), ShouldEqual, 0) - So(len(mockedDataStore.UpdateBuildSearchTaskStateCalls()), ShouldEqual, 0) - - auditParams := common.Params{"instance_id": "123"} - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Attempted, auditParamsWithCallerIdentity), - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Unsuccessful, auditParams), - ) - }) - }) - - Convey("When UpdateImportObservationsTaskState returns an error", func() { - auditor := auditortest.NewErroring(instance.UpdateImportTasksAction, audit.Unsuccessful) - body := strings.NewReader(`{"import_observations":{"state":"completed"}}`) - r, err := createRequestWithToken("PUT", "http://localhost:21800/instances/123/import_tasks", body) - So(err, ShouldBeNil) - w := httptest.NewRecorder() - - mockedDataStore := &storetest.StorerMock{ - GetInstanceFunc: func(id string) (*models.Instance, error) { - return &models.Instance{State: models.CreatedState}, nil - }, - UpdateImportObservationsTaskStateFunc: func(id string, state string) error { - return errors.New("error") - }, - } - - datasetPermissions := mocks.NewAuthHandlerMock() - permissions := mocks.NewAuthHandlerMock() - - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - datasetAPI.Router.ServeHTTP(w, r) - - Convey("Then a 500 status is returned", func() { - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) - - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 1) - So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) - So(len(mockedDataStore.UpdateImportObservationsTaskStateCalls()), ShouldEqual, 1) - So(len(mockedDataStore.UpdateBuildHierarchyTaskStateCalls()), ShouldEqual, 0) - So(len(mockedDataStore.UpdateBuildSearchTaskStateCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Attempted, auditParamsWithCallerIdentity), - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Unsuccessful, auditParams), - ) - }) - }) - - Convey("When UpdateBuildHierarchyTaskState returns an error", func() { - auditor := auditortest.NewErroring(instance.UpdateImportTasksAction, audit.Unsuccessful) - body := strings.NewReader(`{"build_hierarchies":[{"dimension_name": "geography", "state":"completed"}]}`) - r, err := createRequestWithToken("PUT", "http://localhost:21800/instances/123/import_tasks", body) - So(err, ShouldBeNil) - w := httptest.NewRecorder() - - mockedDataStore := &storetest.StorerMock{ - GetInstanceFunc: func(id string) (*models.Instance, error) { - return &models.Instance{State: models.CreatedState}, nil - }, - UpdateBuildHierarchyTaskStateFunc: func(id string, dimension string, state string) error { - return errors.New("error") - }, - } - datasetPermissions := mocks.NewAuthHandlerMock() - permissions := mocks.NewAuthHandlerMock() - - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - datasetAPI.Router.ServeHTTP(w, r) - - Convey("Then a 500 status is returned", func() { - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) - - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 1) - So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) - So(len(mockedDataStore.UpdateImportObservationsTaskStateCalls()), ShouldEqual, 0) - So(len(mockedDataStore.UpdateBuildHierarchyTaskStateCalls()), ShouldEqual, 1) - So(len(mockedDataStore.UpdateBuildSearchTaskStateCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Attempted, auditParamsWithCallerIdentity), - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Unsuccessful, auditParams), - ) - }) - }) - - Convey("When UpdateBuildSearchTaskState returns an error", func() { - auditor := auditortest.NewErroring(instance.UpdateImportTasksAction, audit.Unsuccessful) - body := strings.NewReader(`{"build_search_indexes":[{"dimension_name": "geography", "state":"completed"}]}`) - r, err := createRequestWithToken("PUT", "http://localhost:21800/instances/123/import_tasks", body) - So(err, ShouldBeNil) - w := httptest.NewRecorder() - - mockedDataStore := &storetest.StorerMock{ - GetInstanceFunc: func(id string) (*models.Instance, error) { - return &models.Instance{State: models.CreatedState}, nil - }, - UpdateBuildSearchTaskStateFunc: func(id string, dimension string, state string) error { - return errors.New("error") - }, - } - datasetPermissions := mocks.NewAuthHandlerMock() - permissions := mocks.NewAuthHandlerMock() - - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - datasetAPI.Router.ServeHTTP(w, r) - - Convey("Then a 500 status is returned", func() { - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) - - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 1) - So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) - So(len(mockedDataStore.UpdateImportObservationsTaskStateCalls()), ShouldEqual, 0) - So(len(mockedDataStore.UpdateBuildHierarchyTaskStateCalls()), ShouldEqual, 0) - So(len(mockedDataStore.UpdateBuildSearchTaskStateCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Attempted, auditParamsWithCallerIdentity), - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Unsuccessful, auditParams), - ) - }) - }) - }) -} - -func Test_UpdateImportTask_AuditSuccessfulError(t *testing.T) { - t.Parallel() - Convey("Given audit action successful returns an error", t, func() { - auditor := auditortest.NewErroring(instance.UpdateImportTasksAction, audit.Successful) - - Convey("When update import task is called", func() { - body := strings.NewReader(`{"import_observations":{"state":"completed"}}`) - r, err := createRequestWithToken("PUT", "http://localhost:21800/instances/123/import_tasks", body) - So(err, ShouldBeNil) - w := httptest.NewRecorder() - - mockedDataStore := &storetest.StorerMock{ - GetInstanceFunc: func(id string) (*models.Instance, error) { - return &models.Instance{State: models.CreatedState}, nil - }, - UpdateImportObservationsTaskStateFunc: func(id string, state string) error { - return nil - }, - } - - datasetPermissions := mocks.NewAuthHandlerMock() - permissions := mocks.NewAuthHandlerMock() - - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - datasetAPI.Router.ServeHTTP(w, r) - - Convey("Then a 500 status is returned", func() { - So(w.Code, ShouldEqual, http.StatusOK) - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 1) - So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) - So(len(mockedDataStore.UpdateImportObservationsTaskStateCalls()), ShouldEqual, 1) - So(len(mockedDataStore.UpdateBuildHierarchyTaskStateCalls()), ShouldEqual, 0) - So(len(mockedDataStore.UpdateBuildSearchTaskStateCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Attempted, common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123"}), - auditortest.NewExpectation(instance.UpdateImportTasksAction, audit.Successful, common.Params{"instance_id": "123"}), - ) }) }) }) diff --git a/instance/instance.go b/instance/instance.go index 64924812..4cfdea56 100644 --- a/instance/instance.go +++ b/instance/instance.go @@ -13,9 +13,8 @@ import ( errs "github.com/ONSdigital/dp-dataset-api/apierrors" "github.com/ONSdigital/dp-dataset-api/models" "github.com/ONSdigital/dp-dataset-api/store" - "github.com/ONSdigital/go-ns/audit" - "github.com/ONSdigital/go-ns/common" - "github.com/ONSdigital/go-ns/request" + dphttp "github.com/ONSdigital/dp-net/http" + dprequest "github.com/ONSdigital/dp-net/request" "github.com/ONSdigital/log.go/log" "github.com/gorilla/mux" "github.com/pkg/errors" @@ -26,7 +25,6 @@ import ( type Store struct { store.Storer Host string - Auditor audit.AuditorService EnableDetachDataset bool } @@ -42,7 +40,7 @@ func (e taskError) Error() string { return "" } -// List of audit actions for instances +// List of actions for instances const ( AddInstanceAction = "addInstance" CreateEditionAction = "createEditionForInstance" @@ -60,24 +58,17 @@ func (s *Store) GetList(w http.ResponseWriter, r *http.Request) { ctx := r.Context() stateFilterQuery := r.URL.Query().Get("state") datasetFilterQuery := r.URL.Query().Get("dataset") - var auditParams common.Params var stateFilterList []string var datasetFilterList []string logData := log.Data{"action": GetInstancesAction} - if stateFilterQuery != "" || datasetFilterQuery != "" { - auditParams = make(common.Params) - } - if stateFilterQuery != "" { logData["state_query"] = stateFilterQuery - auditParams["state_query"] = stateFilterQuery stateFilterList = strings.Split(stateFilterQuery, ",") } if datasetFilterQuery != "" { logData["dataset_query"] = datasetFilterQuery - auditParams["dataset_query"] = datasetFilterQuery datasetFilterList = strings.Split(datasetFilterQuery, ",") } @@ -106,18 +97,10 @@ func (s *Store) GetList(w http.ResponseWriter, r *http.Request) { }() if err != nil { - if auditErr := s.Auditor.Record(ctx, GetInstancesAction, audit.Unsuccessful, auditParams); auditErr != nil { - err = auditErr - } handleInstanceErr(ctx, err, w, logData) return } - if auditErr := s.Auditor.Record(ctx, GetInstancesAction, audit.Successful, auditParams); auditErr != nil { - handleInstanceErr(ctx, auditErr, w, logData) - return - } - writeBody(ctx, w, b, logData) log.Event(ctx, "get instances: request successful", log.INFO, logData) } @@ -127,9 +110,7 @@ func (s *Store) Get(w http.ResponseWriter, r *http.Request) { ctx := r.Context() vars := mux.Vars(r) instanceID := vars["instance_id"] - auditParams := common.Params{"instance_id": instanceID} - logData := audit.ToLogData(auditParams) - logData["action"] = GetInstanceAction + logData := log.Data{"instance_id": instanceID, "action": GetInstanceAction} log.Event(ctx, "get instance", log.INFO, logData) @@ -160,18 +141,10 @@ func (s *Store) Get(w http.ResponseWriter, r *http.Request) { log.Event(ctx, "get instance: auditing outcome", log.INFO, logData) if err != nil { - if auditErr := s.Auditor.Record(ctx, GetInstanceAction, audit.Unsuccessful, auditParams); auditErr != nil { - err = auditErr - } handleInstanceErr(ctx, err, w, logData) return } - if auditErr := s.Auditor.Record(ctx, GetInstanceAction, audit.Successful, auditParams); auditErr != nil { - handleInstanceErr(ctx, auditErr, w, logData) - return - } - writeBody(ctx, w, b, logData) log.Event(ctx, "get instance: request successful", log.INFO, logData) } @@ -179,11 +152,11 @@ func (s *Store) Get(w http.ResponseWriter, r *http.Request) { //Add an instance func (s *Store) Add(w http.ResponseWriter, r *http.Request) { - defer request.DrainBody(r) + defer dphttp.DrainBody(r) ctx := r.Context() logData := log.Data{"action": AddInstanceAction} - auditParams := common.Params{} + auditParams := dprequest.Params{} log.Event(ctx, "add instance", log.INFO, logData) @@ -215,15 +188,10 @@ func (s *Store) Add(w http.ResponseWriter, r *http.Request) { return b, nil }() if err != nil { - if auditErr := s.Auditor.Record(ctx, AddInstanceAction, audit.Unsuccessful, auditParams); auditErr != nil { - err = auditErr - } handleInstanceErr(ctx, err, w, logData) return } - s.Auditor.Record(ctx, AddInstanceAction, audit.Successful, auditParams) - w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusCreated) writeBody(ctx, w, b, logData) @@ -234,14 +202,12 @@ func (s *Store) Add(w http.ResponseWriter, r *http.Request) { //Update a specific instance func (s *Store) Update(w http.ResponseWriter, r *http.Request) { - defer request.DrainBody(r) + defer dphttp.DrainBody(r) ctx := r.Context() vars := mux.Vars(r) instanceID := vars["instance_id"] - auditParams := common.Params{"instance_id": instanceID} - logData := audit.ToLogData(auditParams) - logData["action"] = UpdateInstanceAction + logData := log.Data{"instance_id": instanceID, "action": UpdateInstanceAction} var b []byte var err error @@ -331,10 +297,6 @@ func (s *Store) Update(w http.ResponseWriter, r *http.Request) { return b, nil }(); err != nil { - if auditErr := s.Auditor.Record(ctx, UpdateInstanceAction, audit.Unsuccessful, auditParams); auditErr != nil { - err = auditErr - } - handleInstanceErr(ctx, err, w, logData) return } @@ -343,8 +305,6 @@ func (s *Store) Update(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) writeBody(ctx, w, b, logData) - s.Auditor.Record(ctx, UpdateInstanceAction, audit.Successful, auditParams) - log.Event(ctx, "update instance: request successful", log.INFO, logData) } @@ -497,7 +457,6 @@ func writeBody(ctx context.Context, w http.ResponseWriter, b []byte, logData log // PublishCheck Checks if an instance has been published type PublishCheck struct { Datastore store.Storer - Auditor audit.AuditorService } // Check wraps a HTTP handle. Checks that the state is not published @@ -507,19 +466,9 @@ func (d *PublishCheck) Check(handle func(http.ResponseWriter, *http.Request), ac vars := mux.Vars(r) instanceID := vars["instance_id"] logData := log.Data{"action": "CheckAction", "instance_id": instanceID} - auditParams := common.Params{"instance_id": instanceID} - if vars["dimension"] != "" { - auditParams["dimension"] = vars["dimension"] - } - - if err := d.checkState(instanceID, logData, auditParams); err != nil { + if err := d.checkState(instanceID); err != nil { log.Event(ctx, "errored whilst checking instance state", log.ERROR, log.Error(err), logData) - if auditErr := d.Auditor.Record(ctx, action, audit.Unsuccessful, auditParams); auditErr != nil { - handleInstanceErr(ctx, errs.ErrAuditActionAttemptedFailure, w, logData) - return - } - handleInstanceErr(ctx, err, w, logData) return } @@ -528,12 +477,11 @@ func (d *PublishCheck) Check(handle func(http.ResponseWriter, *http.Request), ac }) } -func (d *PublishCheck) checkState(instanceID string, logData log.Data, auditParams common.Params) error { +func (d *PublishCheck) checkState(instanceID string) error { instance, err := d.Datastore.GetInstance(instanceID) if err != nil { return err } - auditParams["instance_state"] = instance.State if instance.State == models.PublishedState { return errs.ErrResourcePublished diff --git a/instance/instance_editions_external_test.go b/instance/instance_editions_external_test.go index 443daaeb..7a6d1cc8 100644 --- a/instance/instance_editions_external_test.go +++ b/instance/instance_editions_external_test.go @@ -9,20 +9,13 @@ import ( "testing" errs "github.com/ONSdigital/dp-dataset-api/apierrors" - "github.com/ONSdigital/dp-dataset-api/instance" "github.com/ONSdigital/dp-dataset-api/mocks" "github.com/ONSdigital/dp-dataset-api/models" storetest "github.com/ONSdigital/dp-dataset-api/store/datastoretest" - "github.com/ONSdigital/go-ns/audit" - "github.com/ONSdigital/go-ns/audit/auditortest" - "github.com/ONSdigital/go-ns/common" . "github.com/smartystreets/goconvey/convey" ) func Test_UpdateInstanceToEditionConfirmedReturnsOk(t *testing.T) { - auditParams := common.Params{"instance_id": "123"} - auditParamsWithCallerIdentity := common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123"} - Convey("Given a PUT request to update an instance resource", t, func() { Convey("When the requested state change is to 'edition-confirmed'", func() { Convey("Then return status ok (200)", func() { @@ -71,9 +64,8 @@ func Test_UpdateInstanceToEditionConfirmedReturnsOk(t *testing.T) { } datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) @@ -85,23 +77,12 @@ func Test_UpdateInstanceToEditionConfirmedReturnsOk(t *testing.T) { // So(len(mockedDataStore.GetNextVersionCalls()), ShouldEqual, 1) So(len(mockedDataStore.UpdateInstanceCalls()), ShouldEqual, 1) So(len(mockedDataStore.AddVersionDetailsToInstanceCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{instance.UpdateInstanceAction, audit.Attempted, auditParamsWithCallerIdentity}, - auditortest.Expected{instance.CreateEditionAction, audit.Attempted, common.Params{"instance_id": "123", "dataset_id": "4567", "edition": "2017"}}, - auditortest.Expected{instance.CreateEditionAction, audit.Successful, common.Params{"instance_id": "123", "dataset_id": "4567", "edition": "2017"}}, - auditortest.Expected{instance.UpdateInstanceAction, audit.Successful, auditParams}, - ) }) }) }) } func Test_UpdateInstanceToEditionConfirmedReturnsError(t *testing.T) { - auditParams := common.Params{"instance_id": "123"} - auditParamsWithCallerIdentity := common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123"} - editionAuditParams := common.Params{"instance_id": "123", "dataset_id": "4567", "edition": "2017"} - t.Parallel() Convey("Given a PUT request to update state of an instance resource is made", t, func() { @@ -154,9 +135,8 @@ func Test_UpdateInstanceToEditionConfirmedReturnsError(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusInternalServerError) @@ -167,13 +147,6 @@ func Test_UpdateInstanceToEditionConfirmedReturnsError(t *testing.T) { So(len(mockedDataStore.UpsertEditionCalls()), ShouldEqual, 1) So(len(mockedDataStore.AddVersionDetailsToInstanceCalls()), ShouldEqual, 1) So(len(mockedDataStore.UpdateInstanceCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{instance.UpdateInstanceAction, audit.Attempted, auditParamsWithCallerIdentity}, - auditortest.Expected{instance.CreateEditionAction, audit.Attempted, editionAuditParams}, - auditortest.Expected{instance.CreateEditionAction, audit.Successful, editionAuditParams}, - auditortest.Expected{instance.UpdateInstanceAction, audit.Unsuccessful, auditParams}, - ) }) }) @@ -204,9 +177,8 @@ func Test_UpdateInstanceToEditionConfirmedReturnsError(t *testing.T) { } datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusForbidden) @@ -217,279 +189,6 @@ func Test_UpdateInstanceToEditionConfirmedReturnsError(t *testing.T) { So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 2) So(len(mockedDataStore.UpdateInstanceCalls()), ShouldEqual, 0) So(len(mockedDataStore.AddVersionDetailsToInstanceCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{instance.UpdateInstanceAction, audit.Attempted, auditParamsWithCallerIdentity}, - auditortest.Expected{instance.UpdateInstanceAction, audit.Unsuccessful, auditParams}, - ) - }) - }) - - Convey(`When the requested state change is to 'edition-confirmed' and attempt to audit request to create edition fails`, func() { - Convey("Then return status internal server error (500)", func() { - body := strings.NewReader(`{"state":"edition-confirmed", "edition": "2017"}`) - r, err := createRequestWithToken("PUT", "http://localhost:21800/instances/123", body) - So(err, ShouldBeNil) - w := httptest.NewRecorder() - - currentInstanceTest_Data := &models.Instance{ - Edition: "2017", - Links: &models.InstanceLinks{ - Job: &models.LinkObject{ - ID: "7654", - HRef: "job-link", - }, - Dataset: &models.LinkObject{ - ID: "4567", - HRef: "dataset-link", - }, - Self: &models.LinkObject{ - HRef: "self-link", - }, - }, - State: models.CompletedState, - } - - mockedDataStore := &storetest.StorerMock{ - GetInstanceFunc: func(id string) (*models.Instance, error) { - return currentInstanceTest_Data, nil - }, - GetEditionFunc: func(datasetID string, edition string, state string) (*models.EditionUpdate, error) { - return nil, errs.ErrEditionNotFound - }, - } - - datasetPermissions := mocks.NewAuthHandlerMock() - permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.NewErroring(instance.CreateEditionAction, audit.Attempted) - - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - datasetAPI.Router.ServeHTTP(w, r) - - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) - - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 1) - So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 2) - So(len(mockedDataStore.GetEditionCalls()), ShouldEqual, 1) - So(len(mockedDataStore.UpsertEditionCalls()), ShouldEqual, 0) - So(len(mockedDataStore.UpdateInstanceCalls()), ShouldEqual, 0) - So(len(mockedDataStore.AddVersionDetailsToInstanceCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{instance.UpdateInstanceAction, audit.Attempted, auditParamsWithCallerIdentity}, - auditortest.Expected{instance.CreateEditionAction, audit.Attempted, editionAuditParams}, - auditortest.Expected{instance.CreateEditionAction, audit.Unsuccessful, editionAuditParams}, - auditortest.Expected{instance.UpdateInstanceAction, audit.Unsuccessful, auditParams}, - ) - }) - }) - - Convey(`When the requested state changes to 'associated' and the edition is updated - but unable to update instance and then the auditor attempts an unsuccessful message and fails`, func() { - Convey("Then return status internal server error (500)", func() { - body := strings.NewReader(`{"state":"edition-confirmed", "edition": "2017"}`) - r, err := createRequestWithToken("PUT", "http://localhost:21800/instances/123", body) - So(err, ShouldBeNil) - w := httptest.NewRecorder() - - currentInstanceTest_Data := &models.Instance{ - Edition: "2017", - Links: &models.InstanceLinks{ - Job: &models.LinkObject{ - ID: "7654", - HRef: "job-link", - }, - Dataset: &models.LinkObject{ - ID: "4567", - HRef: "dataset-link", - }, - Self: &models.LinkObject{ - HRef: "self-link", - }, - }, - State: models.CompletedState, - } - - mockedDataStore := &storetest.StorerMock{ - GetInstanceFunc: func(id string) (*models.Instance, error) { - return currentInstanceTest_Data, nil - }, - GetEditionFunc: func(datasetID string, edition string, state string) (*models.EditionUpdate, error) { - return &models.EditionUpdate{ - Current: &models.Edition{ - Links: &models.EditionUpdateLinks{ - Dataset: &models.LinkObject{ - HRef: "/dataset/test/href", - ID: "cpih01", - }, - LatestVersion: &models.LinkObject{ - ID: "1", - }, - Self: &models.LinkObject{ - HRef: "/edition/test/href", - ID: "test", - }, - }, - State: models.PublishedState, - }, - Next: &models.Edition{ - Links: &models.EditionUpdateLinks{ - Dataset: &models.LinkObject{ - HRef: "/dataset/test/href", - ID: "cpih01", - }, - LatestVersion: &models.LinkObject{ - ID: "1", - }, - Self: &models.LinkObject{ - HRef: "/edition/test/href", - ID: "test", - }, - }, - State: models.EditionConfirmedState, - }, - }, nil - }, - UpsertEditionFunc: func(datasetID, edition string, editionDoc *models.EditionUpdate) error { - return nil - }, - GetNextVersionFunc: func(string, string) (int, error) { - return 2, nil - }, - UpdateInstanceFunc: func(ctx context.Context, id string, i *models.Instance) error { - return errs.ErrInternalServer - }, - AddVersionDetailsToInstanceFunc: func(ctx context.Context, instanceID string, datasetID string, edition string, version int) error { - return nil - }, - } - - datasetPermissions := mocks.NewAuthHandlerMock() - permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.NewErroring(instance.UpdateInstanceAction, audit.Unsuccessful) - - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - datasetAPI.Router.ServeHTTP(w, r) - - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) - - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 1) - So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 2) - So(len(mockedDataStore.GetEditionCalls()), ShouldEqual, 1) - So(len(mockedDataStore.UpsertEditionCalls()), ShouldEqual, 1) - So(len(mockedDataStore.UpdateInstanceCalls()), ShouldEqual, 1) - So(len(mockedDataStore.AddVersionDetailsToInstanceCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{instance.UpdateInstanceAction, audit.Attempted, auditParamsWithCallerIdentity}, - auditortest.Expected{instance.UpdateEditionAction, audit.Attempted, editionAuditParams}, - auditortest.Expected{instance.UpdateEditionAction, audit.Successful, editionAuditParams}, - auditortest.Expected{instance.UpdateInstanceAction, audit.Unsuccessful, auditParams}, - ) - }) - }) - - Convey(`When the requested state changes to 'associated' and the edition - is updated, yet the auditor fails is unsuccessful in writing success message`, func() { - Convey("Then return status internal server error (500)", func() { - body := strings.NewReader(`{"state":"edition-confirmed", "edition": "2017"}`) - r, err := createRequestWithToken("PUT", "http://localhost:21800/instances/123", body) - So(err, ShouldBeNil) - w := httptest.NewRecorder() - - currentInstanceTest_Data := &models.Instance{ - Edition: "2017", - Links: &models.InstanceLinks{ - Job: &models.LinkObject{ - ID: "7654", - HRef: "job-link", - }, - Dataset: &models.LinkObject{ - ID: "4567", - HRef: "dataset-link", - }, - Self: &models.LinkObject{ - HRef: "self-link", - }, - }, - State: models.CompletedState, - } - - mockedDataStore := &storetest.StorerMock{ - GetInstanceFunc: func(id string) (*models.Instance, error) { - return currentInstanceTest_Data, nil - }, - GetEditionFunc: func(datasetID string, edition string, state string) (*models.EditionUpdate, error) { - return &models.EditionUpdate{ - Current: &models.Edition{ - State: models.PublishedState, - Links: &models.EditionUpdateLinks{ - LatestVersion: &models.LinkObject{ - ID: "1", - }, - Self: &models.LinkObject{ - HRef: "/edition/test/href", - }, - }, - }, - Next: &models.Edition{ - Links: &models.EditionUpdateLinks{ - Dataset: &models.LinkObject{ - HRef: "/dataset/test/href", - ID: "cpih01", - }, - LatestVersion: &models.LinkObject{ - ID: "1", - }, - Self: &models.LinkObject{ - HRef: "/edition/test/href", - ID: "test", - }, - }, - State: models.EditionConfirmedState, - }, - }, nil - }, - UpsertEditionFunc: func(datasetID, edition string, editionDoc *models.EditionUpdate) error { - return nil - }, - GetNextVersionFunc: func(string, string) (int, error) { - return 1, nil - }, - UpdateInstanceFunc: func(ctx context.Context, id string, i *models.Instance) error { - return nil - }, - AddVersionDetailsToInstanceFunc: func(ctx context.Context, instanceID string, datasetID string, edition string, version int) error { - return nil - }, - } - - datasetPermissions := mocks.NewAuthHandlerMock() - permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.NewErroring(instance.UpdateInstanceAction, audit.Unsuccessful) - - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - datasetAPI.Router.ServeHTTP(w, r) - - So(w.Code, ShouldEqual, http.StatusOK) - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 1) - So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 3) - So(len(mockedDataStore.GetEditionCalls()), ShouldEqual, 1) - So(len(mockedDataStore.UpsertEditionCalls()), ShouldEqual, 1) - So(len(mockedDataStore.UpdateInstanceCalls()), ShouldEqual, 1) - So(len(mockedDataStore.AddVersionDetailsToInstanceCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{instance.UpdateInstanceAction, audit.Attempted, auditParamsWithCallerIdentity}, - auditortest.Expected{instance.UpdateEditionAction, audit.Attempted, editionAuditParams}, - auditortest.Expected{instance.UpdateEditionAction, audit.Successful, editionAuditParams}, - auditortest.Expected{instance.UpdateInstanceAction, audit.Successful, auditParams}, - ) }) }) }) diff --git a/instance/instance_external_test.go b/instance/instance_external_test.go index 1312b27c..61381184 100644 --- a/instance/instance_external_test.go +++ b/instance/instance_external_test.go @@ -13,15 +13,12 @@ import ( "github.com/ONSdigital/dp-dataset-api/api" errs "github.com/ONSdigital/dp-dataset-api/apierrors" "github.com/ONSdigital/dp-dataset-api/config" - "github.com/ONSdigital/dp-dataset-api/instance" "github.com/ONSdigital/dp-dataset-api/mocks" "github.com/ONSdigital/dp-dataset-api/models" "github.com/ONSdigital/dp-dataset-api/store" storetest "github.com/ONSdigital/dp-dataset-api/store/datastoretest" "github.com/ONSdigital/dp-dataset-api/url" - "github.com/ONSdigital/go-ns/audit" - "github.com/ONSdigital/go-ns/audit/auditortest" - "github.com/ONSdigital/go-ns/common" + dprequest "github.com/ONSdigital/dp-net/request" "github.com/gorilla/mux" . "github.com/smartystreets/goconvey/convey" ) @@ -37,7 +34,7 @@ var ( func createRequestWithToken(method, url string, body io.Reader) (*http.Request, error) { r, err := http.NewRequest(method, url, body) ctx := r.Context() - ctx = common.SetCaller(ctx, "someone@ons.gov.uk") + ctx = dprequest.SetCaller(ctx, "someone@ons.gov.uk") r = r.WithContext(ctx) return r, err } @@ -59,19 +56,13 @@ func Test_GetInstancesReturnsOK(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) So(datasetPermissions.Required.Calls, ShouldEqual, 0) So(permissions.Required.Calls, ShouldEqual, 1) So(len(mockedDataStore.GetInstancesCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.GetInstancesAction, audit.Attempted, common.Params{"caller_identity": "someone@ons.gov.uk"}), - auditortest.NewExpectation(instance.GetInstancesAction, audit.Successful, nil), - ) }) }) @@ -91,8 +82,7 @@ func Test_GetInstancesReturnsOK(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) @@ -100,11 +90,6 @@ func Test_GetInstancesReturnsOK(t *testing.T) { So(permissions.Required.Calls, ShouldEqual, 1) So(result, ShouldResemble, []string{models.CompletedState}) So(len(mockedDataStore.GetInstancesCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.GetInstancesAction, audit.Attempted, common.Params{"caller_identity": "someone@ons.gov.uk"}), - auditortest.NewExpectation(instance.GetInstancesAction, audit.Successful, common.Params{"state_query": "completed"}), - ) }) }) @@ -124,8 +109,7 @@ func Test_GetInstancesReturnsOK(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) @@ -133,11 +117,6 @@ func Test_GetInstancesReturnsOK(t *testing.T) { So(permissions.Required.Calls, ShouldEqual, 1) So(result, ShouldResemble, []string{"test"}) So(len(mockedDataStore.GetInstancesCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.GetInstancesAction, audit.Attempted, common.Params{"caller_identity": "someone@ons.gov.uk"}), - auditortest.NewExpectation(instance.GetInstancesAction, audit.Successful, common.Params{"dataset_query": "test"}), - ) }) }) @@ -157,8 +136,7 @@ func Test_GetInstancesReturnsOK(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) @@ -166,11 +144,6 @@ func Test_GetInstancesReturnsOK(t *testing.T) { So(permissions.Required.Calls, ShouldEqual, 1) So(result, ShouldResemble, []string{models.CompletedState, models.EditionConfirmedState}) So(len(mockedDataStore.GetInstancesCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.GetInstancesAction, audit.Attempted, common.Params{"caller_identity": "someone@ons.gov.uk"}), - auditortest.NewExpectation(instance.GetInstancesAction, audit.Successful, common.Params{"state_query": "completed,edition-confirmed"}), - ) }) }) @@ -191,8 +164,7 @@ func Test_GetInstancesReturnsOK(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) @@ -200,11 +172,6 @@ func Test_GetInstancesReturnsOK(t *testing.T) { So(permissions.Required.Calls, ShouldEqual, 1) So(result, ShouldResemble, []string{models.CompletedState, "test"}) So(len(mockedDataStore.GetInstancesCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.GetInstancesAction, audit.Attempted, common.Params{"caller_identity": "someone@ons.gov.uk"}), - auditortest.NewExpectation(instance.GetInstancesAction, audit.Successful, common.Params{"state_query": "completed", "dataset_query": "test"}), - ) }) }) }) @@ -227,8 +194,7 @@ func Test_GetInstancesReturnsError(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusInternalServerError) @@ -236,11 +202,6 @@ func Test_GetInstancesReturnsError(t *testing.T) { So(permissions.Required.Calls, ShouldEqual, 1) So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) So(len(mockedDataStore.GetInstancesCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.GetInstancesAction, audit.Attempted, common.Params{"caller_identity": "someone@ons.gov.uk"}), - auditortest.NewExpectation(instance.GetInstancesAction, audit.Unsuccessful, nil), - ) }) }) @@ -254,123 +215,13 @@ func Test_GetInstancesReturnsError(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusBadRequest) So(w.Body.String(), ShouldContainSubstring, "bad request - invalid filter state values: [foo]") So(datasetPermissions.Required.Calls, ShouldEqual, 0) So(permissions.Required.Calls, ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.GetInstancesAction, audit.Attempted, common.Params{"caller_identity": "someone@ons.gov.uk"}), - auditortest.NewExpectation(instance.GetInstancesAction, audit.Unsuccessful, common.Params{"state_query": "foo"}), - ) - }) - }) - }) -} - -func Test_GetInstancesAuditErrors(t *testing.T) { - t.Parallel() - Convey("Given audit action attempted returns an error", t, func() { - auditor := auditortest.NewErroring(instance.GetInstancesAction, audit.Attempted) - - Convey("When get instances is called", func() { - r, err := createRequestWithToken("GET", "http://localhost:21800/instances", nil) - So(err, ShouldBeNil) - w := httptest.NewRecorder() - - mockedDataStore := &storetest.StorerMock{} - - datasetPermissions := mocks.NewAuthHandlerMock() - permissions := mocks.NewAuthHandlerMock() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - datasetAPI.Router.ServeHTTP(w, r) - - Convey("Then a 500 status is returned", func() { - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 0) - - So(len(mockedDataStore.GetInstancesCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.GetInstancesAction, audit.Attempted, common.Params{"caller_identity": "someone@ons.gov.uk"}), - ) - }) - }) - }) - - Convey("Given audit action unsuccessful returns an error", t, func() { - auditor := auditortest.NewErroring(instance.GetInstancesAction, audit.Unsuccessful) - - Convey("When get instances return an error", func() { - r, err := createRequestWithToken("GET", "http://localhost:21800/instances", nil) - So(err, ShouldBeNil) - w := httptest.NewRecorder() - - mockedDataStore := &storetest.StorerMock{ - GetInstancesFunc: func(context.Context, []string, []string) (*models.InstanceResults, error) { - return nil, errs.ErrInternalServer - }, - } - datasetPermissions := mocks.NewAuthHandlerMock() - permissions := mocks.NewAuthHandlerMock() - - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - datasetAPI.Router.ServeHTTP(w, r) - - Convey("Then a 500 status is returned", func() { - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 1) - - So(len(mockedDataStore.GetInstancesCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.GetInstancesAction, audit.Attempted, common.Params{"caller_identity": "someone@ons.gov.uk"}), - auditortest.NewExpectation(instance.GetInstancesAction, audit.Unsuccessful, nil), - ) - }) - }) - }) - - Convey("Given audit action successful returns an error", t, func() { - auditor := auditortest.NewErroring(instance.GetInstancesAction, audit.Successful) - - Convey("When get instances is called", func() { - r, err := createRequestWithToken("GET", "http://localhost:21800/instances", nil) - So(err, ShouldBeNil) - w := httptest.NewRecorder() - - mockedDataStore := &storetest.StorerMock{ - GetInstancesFunc: func(context.Context, []string, []string) (*models.InstanceResults, error) { - return &models.InstanceResults{}, nil - }, - } - datasetPermissions := mocks.NewAuthHandlerMock() - permissions := mocks.NewAuthHandlerMock() - - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - datasetAPI.Router.ServeHTTP(w, r) - - Convey("Then a 500 status is returned", func() { - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) - - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 1) - - So(len(mockedDataStore.GetInstancesCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.NewExpectation(instance.GetInstancesAction, audit.Attempted, common.Params{"caller_identity": "someone@ons.gov.uk"}), - auditortest.NewExpectation(instance.GetInstancesAction, audit.Successful, nil), - ) }) }) }) @@ -394,28 +245,19 @@ func Test_GetInstanceReturnsOK(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) So(datasetPermissions.Required.Calls, ShouldEqual, 0) So(permissions.Required.Calls, ShouldEqual, 1) So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: instance.GetInstanceAction, Result: audit.Attempted, Params: common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123"}}, - auditortest.Expected{Action: instance.GetInstanceAction, Result: audit.Successful, Params: common.Params{"instance_id": "123"}}, - ) }) }) }) } func Test_GetInstanceReturnsError(t *testing.T) { - auditParams := common.Params{"instance_id": "123"} - auditParamsWithCallerIdentity := common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123"} - t.Parallel() Convey("Given a GET request to retrieve an instance resource is made", t, func() { Convey("When the service is unable to connect to the datastore", func() { @@ -433,8 +275,7 @@ func Test_GetInstanceReturnsError(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusInternalServerError) @@ -442,11 +283,6 @@ func Test_GetInstanceReturnsError(t *testing.T) { So(datasetPermissions.Required.Calls, ShouldEqual, 0) So(permissions.Required.Calls, ShouldEqual, 1) So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: instance.GetInstanceAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: instance.GetInstanceAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) }) @@ -464,8 +300,7 @@ func Test_GetInstanceReturnsError(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusInternalServerError) @@ -473,11 +308,6 @@ func Test_GetInstanceReturnsError(t *testing.T) { So(datasetPermissions.Required.Calls, ShouldEqual, 0) So(permissions.Required.Calls, ShouldEqual, 1) So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: instance.GetInstanceAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: instance.GetInstanceAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) }) @@ -496,8 +326,7 @@ func Test_GetInstanceReturnsError(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -505,121 +334,6 @@ func Test_GetInstanceReturnsError(t *testing.T) { So(datasetPermissions.Required.Calls, ShouldEqual, 0) So(permissions.Required.Calls, ShouldEqual, 1) So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: instance.GetInstanceAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: instance.GetInstanceAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) - }) - }) -} - -func Test_GetInstanceAuditErrors(t *testing.T) { - auditParams := common.Params{"instance_id": "123"} - auditParamsWithCallerIdentity := common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123"} - - t.Parallel() - Convey("Given audit action 'attempted' fails", t, func() { - auditor := auditortest.NewErroring(instance.GetInstanceAction, audit.Attempted) - - Convey("When a GET request is made to get an instance resource", func() { - r, err := createRequestWithToken("GET", "http://localhost:21800/instances/123", nil) - So(err, ShouldBeNil) - w := httptest.NewRecorder() - - mockedDataStore := &storetest.StorerMock{ - GetInstanceFunc: func(ID string) (*models.Instance, error) { - return nil, errs.ErrInternalServer - }, - } - - datasetPermissions := mocks.NewAuthHandlerMock() - permissions := mocks.NewAuthHandlerMock() - - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - datasetAPI.Router.ServeHTTP(w, r) - - Convey("Then response returns internal server error (500)", func() { - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: instance.GetInstanceAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - ) - }) - }) - }) - - Convey("Given audit action 'unsuccessful' fails", t, func() { - auditor := auditortest.NewErroring(instance.GetInstanceAction, audit.Unsuccessful) - - Convey("When a GET request is made to get an instance resource", func() { - r, err := createRequestWithToken("GET", "http://localhost:21800/instances/123", nil) - So(err, ShouldBeNil) - w := httptest.NewRecorder() - - mockedDataStore := &storetest.StorerMock{ - GetInstanceFunc: func(ID string) (*models.Instance, error) { - return nil, errs.ErrInternalServer - }, - } - - datasetPermissions := mocks.NewAuthHandlerMock() - permissions := mocks.NewAuthHandlerMock() - - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - datasetAPI.Router.ServeHTTP(w, r) - - Convey("Then response returns internal server error (500)", func() { - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 1) - So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: instance.GetInstanceAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: instance.GetInstanceAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) - }) - }) - - Convey("Given audit action 'successful' fails", t, func() { - auditor := auditortest.NewErroring(instance.GetInstanceAction, audit.Successful) - - Convey("When a GET request is made to get an instance resource", func() { - r, err := createRequestWithToken("GET", "http://localhost:21800/instances/123", nil) - So(err, ShouldBeNil) - w := httptest.NewRecorder() - - mockedDataStore := &storetest.StorerMock{ - GetInstanceFunc: func(ID string) (*models.Instance, error) { - return &models.Instance{State: models.CreatedState}, nil - }, - } - - datasetPermissions := mocks.NewAuthHandlerMock() - permissions := mocks.NewAuthHandlerMock() - - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - datasetAPI.Router.ServeHTTP(w, r) - - Convey("Then response returns internal server error (500)", func() { - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 1) - So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: instance.GetInstanceAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: instance.GetInstanceAction, Result: audit.Successful, Params: auditParams}, - ) }) }) }) @@ -631,22 +345,6 @@ type expectedPostInstanceAuditObject struct { Result string } -// function specifically used for POST instance as instance_id cannot be -// determined due to the nature of the handler method creating it's value -func checkAuditRecord(auditor auditortest.MockAuditor, expected []expectedPostInstanceAuditObject) { - So(len(auditor.RecordCalls()), ShouldEqual, len(expected)) - for i, _ := range expected { - // Instance_id is created with a new uuid every time the Test_ is run and - // hence cannot use the AssertRecordCalls helper method - So(auditor.RecordCalls()[i].Action, ShouldEqual, expected[i].Action) - So(auditor.RecordCalls()[i].Result, ShouldEqual, expected[i].Result) - if expected[i].ContainsKey != "" { - So(auditor.RecordCalls()[i].Params, ShouldNotBeNil) - So(auditor.RecordCalls()[i].Params, ShouldContainKey, expected[i].ContainsKey) - } - } -} - func Test_AddInstanceReturnsCreated(t *testing.T) { t.Parallel() Convey("Given a POST request to create an instance resource", t, func() { @@ -665,8 +363,7 @@ func Test_AddInstanceReturnsCreated(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusCreated) @@ -674,15 +371,6 @@ func Test_AddInstanceReturnsCreated(t *testing.T) { So(datasetPermissions.Required.Calls, ShouldEqual, 0) So(permissions.Required.Calls, ShouldEqual, 1) - - checkAuditRecord(*auditor, []expectedPostInstanceAuditObject{ - expectedPostInstanceAuditObject{ - Action: instance.AddInstanceAction, Result: audit.Attempted, ContainsKey: "caller_identity", - }, - expectedPostInstanceAuditObject{ - Action: instance.AddInstanceAction, Result: audit.Successful, ContainsKey: "", - }, - }) }) }) }) @@ -705,8 +393,7 @@ func Test_AddInstanceReturnsError(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusInternalServerError) @@ -714,15 +401,6 @@ func Test_AddInstanceReturnsError(t *testing.T) { So(datasetPermissions.Required.Calls, ShouldEqual, 0) So(permissions.Required.Calls, ShouldEqual, 1) So(len(mockedDataStore.AddInstanceCalls()), ShouldEqual, 1) - - checkAuditRecord(*auditor, []expectedPostInstanceAuditObject{ - expectedPostInstanceAuditObject{ - Action: instance.AddInstanceAction, Result: audit.Attempted, ContainsKey: "caller_identity", - }, - expectedPostInstanceAuditObject{ - Action: instance.AddInstanceAction, Result: audit.Unsuccessful, ContainsKey: "", - }, - }) }) }) @@ -741,8 +419,7 @@ func Test_AddInstanceReturnsError(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusBadRequest) @@ -750,15 +427,6 @@ func Test_AddInstanceReturnsError(t *testing.T) { So(datasetPermissions.Required.Calls, ShouldEqual, 0) So(permissions.Required.Calls, ShouldEqual, 1) So(len(mockedDataStore.AddInstanceCalls()), ShouldEqual, 0) - - checkAuditRecord(*auditor, []expectedPostInstanceAuditObject{ - expectedPostInstanceAuditObject{ - Action: instance.AddInstanceAction, Result: audit.Attempted, ContainsKey: "caller_identity", - }, - expectedPostInstanceAuditObject{ - Action: instance.AddInstanceAction, Result: audit.Unsuccessful, ContainsKey: "", - }, - }) }) }) @@ -777,8 +445,7 @@ func Test_AddInstanceReturnsError(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusBadRequest) @@ -786,136 +453,12 @@ func Test_AddInstanceReturnsError(t *testing.T) { So(datasetPermissions.Required.Calls, ShouldEqual, 0) So(permissions.Required.Calls, ShouldEqual, 1) So(len(mockedDataStore.AddInstanceCalls()), ShouldEqual, 0) - - checkAuditRecord(*auditor, []expectedPostInstanceAuditObject{ - expectedPostInstanceAuditObject{ - Action: instance.AddInstanceAction, Result: audit.Attempted, ContainsKey: "caller_identity", - }, - expectedPostInstanceAuditObject{ - Action: instance.AddInstanceAction, Result: audit.Unsuccessful, ContainsKey: "", - }, - }) - }) - }) - }) -} - -func Test_AddInstanceAuditErrors(t *testing.T) { - t.Parallel() - Convey("Given audit action 'attempted' fails", t, func() { - auditor := auditortest.NewErroring(instance.AddInstanceAction, audit.Attempted) - - Convey("When a POST request is made to create an instance resource", func() { - body := strings.NewReader(`{"links": { "job": { "id":"123-456", "href":"http://localhost:2200/jobs/123-456" } } }`) - r, err := createRequestWithToken("POST", "http://localhost:21800/instances", body) - So(err, ShouldBeNil) - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{} - datasetPermissions := mocks.NewAuthHandlerMock() - permissions := mocks.NewAuthHandlerMock() - - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - datasetAPI.Router.ServeHTTP(w, r) - - Convey("Then response returns internal server error (500)", func() { - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) - - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 0) - So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 0) - - checkAuditRecord(*auditor, []expectedPostInstanceAuditObject{ - expectedPostInstanceAuditObject{ - Action: instance.AddInstanceAction, Result: audit.Attempted, ContainsKey: "caller_identity", - }, - }) - }) - }) - }) - - Convey("Given audit action 'unsuccessful' fails", t, func() { - auditor := auditortest.NewErroring(instance.AddInstanceAction, audit.Unsuccessful) - - Convey("When a POST request is made to create an instance resource", func() { - body := strings.NewReader(`{"links": {"job": { "id":"123-456", "href":"http://localhost:2200/jobs/123-456" } } }`) - r, err := createRequestWithToken("POST", "http://localhost:21800/instances", body) - So(err, ShouldBeNil) - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - AddInstanceFunc: func(*models.Instance) (*models.Instance, error) { - return nil, errs.ErrInternalServer - }, - } - - datasetPermissions := mocks.NewAuthHandlerMock() - permissions := mocks.NewAuthHandlerMock() - - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - datasetAPI.Router.ServeHTTP(w, r) - - Convey("Then response returns internal server error (500)", func() { - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 1) - So(len(mockedDataStore.AddInstanceCalls()), ShouldEqual, 1) - - checkAuditRecord(*auditor, []expectedPostInstanceAuditObject{ - expectedPostInstanceAuditObject{ - Action: instance.AddInstanceAction, Result: audit.Attempted, ContainsKey: "caller_identity", - }, - expectedPostInstanceAuditObject{ - Action: instance.AddInstanceAction, Result: audit.Unsuccessful, ContainsKey: "", - }, - }) - }) - }) - }) - - Convey("Given audit action 'successful' fails", t, func() { - auditor := auditortest.NewErroring(instance.AddInstanceAction, audit.Successful) - - Convey("When a POST request is made to create an instance resource", func() { - body := strings.NewReader(`{"links": {"job": { "id":"123-456", "href":"http://localhost:2200/jobs/123-456" } } }`) - r, err := createRequestWithToken("POST", "http://localhost:21800/instances", body) - So(err, ShouldBeNil) - w := httptest.NewRecorder() - mockedDataStore := &storetest.StorerMock{ - AddInstanceFunc: func(*models.Instance) (*models.Instance, error) { - return &models.Instance{}, nil - }, - } - - datasetPermissions := mocks.NewAuthHandlerMock() - permissions := mocks.NewAuthHandlerMock() - - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - datasetAPI.Router.ServeHTTP(w, r) - - Convey("Then response returns status created (201)", func() { - So(w.Code, ShouldEqual, http.StatusCreated) - So(len(mockedDataStore.AddInstanceCalls()), ShouldEqual, 1) - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 1) - - checkAuditRecord(*auditor, []expectedPostInstanceAuditObject{ - expectedPostInstanceAuditObject{ - Action: instance.AddInstanceAction, Result: audit.Attempted, ContainsKey: "caller_identity", - }, - expectedPostInstanceAuditObject{ - Action: instance.AddInstanceAction, Result: audit.Successful, ContainsKey: "", - }, - }) }) }) }) } func Test_UpdateInstanceReturnsOk(t *testing.T) { - auditParams := common.Params{"instance_id": "123"} - auditParamsWithCallerIdentity := common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123"} - t.Parallel() Convey("Given a PUT request to update state of an instance resource is made", t, func() { Convey("When the requested state change is to 'submitted'", func() { @@ -948,8 +491,7 @@ func Test_UpdateInstanceReturnsOk(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusOK) @@ -958,11 +500,6 @@ func Test_UpdateInstanceReturnsOk(t *testing.T) { So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 3) So(len(mockedDataStore.UpdateInstanceCalls()), ShouldEqual, 1) So(len(mockedDataStore.AddVersionDetailsToInstanceCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: instance.UpdateInstanceAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: instance.UpdateInstanceAction, Result: audit.Successful, Params: auditParams}, - ) }) }) @@ -970,9 +507,6 @@ func Test_UpdateInstanceReturnsOk(t *testing.T) { } func Test_UpdateInstanceReturnsError(t *testing.T) { - auditParams := common.Params{"instance_id": "123"} - auditParamsWithCallerIdentity := common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123"} - t.Parallel() Convey("Given a PUT request to update state of an instance resource is made", t, func() { Convey("When the service is unable to connect to the datastore", func() { @@ -990,8 +524,7 @@ func Test_UpdateInstanceReturnsError(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusInternalServerError) @@ -1003,11 +536,6 @@ func Test_UpdateInstanceReturnsError(t *testing.T) { So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) So(len(mockedDataStore.UpdateInstanceCalls()), ShouldEqual, 0) So(len(mockedDataStore.AddVersionDetailsToInstanceCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: instance.UpdateInstanceAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: instance.UpdateInstanceAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) }) @@ -1025,8 +553,7 @@ func Test_UpdateInstanceReturnsError(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusInternalServerError) @@ -1036,11 +563,6 @@ func Test_UpdateInstanceReturnsError(t *testing.T) { So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) So(len(mockedDataStore.UpdateInstanceCalls()), ShouldEqual, 0) So(len(mockedDataStore.AddVersionDetailsToInstanceCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: instance.UpdateInstanceAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: instance.UpdateInstanceAction, Result: audit.Unsuccessful, Params: common.Params{"instance_id": "123", "instance_state": "gobbledygook"}}, - ) }) }) @@ -1057,9 +579,8 @@ func Test_UpdateInstanceReturnsError(t *testing.T) { } datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusBadRequest) @@ -1070,11 +591,6 @@ func Test_UpdateInstanceReturnsError(t *testing.T) { So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) So(len(mockedDataStore.AddVersionDetailsToInstanceCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: instance.UpdateInstanceAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: instance.UpdateInstanceAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) }) @@ -1096,8 +612,7 @@ func Test_UpdateInstanceReturnsError(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusBadRequest) @@ -1109,11 +624,6 @@ func Test_UpdateInstanceReturnsError(t *testing.T) { So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) So(len(mockedDataStore.AddVersionDetailsToInstanceCalls()), ShouldEqual, 0) So(len(mockedDataStore.UpdateInstanceCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: instance.UpdateInstanceAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: instance.UpdateInstanceAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) }) @@ -1132,8 +642,7 @@ func Test_UpdateInstanceReturnsError(t *testing.T) { datasetPermissions := mocks.NewAuthHandlerMock() permissions := mocks.NewAuthHandlerMock() - auditor := auditortest.New() - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) + datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, datasetPermissions, permissions) datasetAPI.Router.ServeHTTP(w, r) So(w.Code, ShouldEqual, http.StatusNotFound) @@ -1145,156 +654,6 @@ func Test_UpdateInstanceReturnsError(t *testing.T) { So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) So(len(mockedDataStore.UpdateInstanceCalls()), ShouldEqual, 0) So(len(mockedDataStore.AddVersionDetailsToInstanceCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: instance.UpdateInstanceAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: instance.UpdateInstanceAction, Result: audit.Unsuccessful, Params: auditParams}, - ) - }) - }) - }) -} - -func Test_UpdateInstance_AuditFailure(t *testing.T) { - auditParams := common.Params{"instance_id": "123"} - auditParamsWithCallerIdentity := common.Params{"caller_identity": "someone@ons.gov.uk", "instance_id": "123"} - //editionAuditParams := common.Params{"instance_id": "123", "dataset_id": "4567", "edition": "2017"} - - t.Parallel() - Convey("Given a PUT request to update state of an instance resource is made", t, func() { - Convey(`When the auditor attempts to audit request attempt fails`, func() { - Convey("Then return status internal server error (500)", func() { - body := strings.NewReader(`{"state":"completed"}`) - r, err := createRequestWithToken("PUT", "http://localhost:21800/instances/123", body) - So(err, ShouldBeNil) - w := httptest.NewRecorder() - - mockedDataStore := &storetest.StorerMock{ - GetInstanceFunc: func(id string) (*models.Instance, error) { - return nil, nil - }, - } - - datasetPermissions := mocks.NewAuthHandlerMock() - permissions := mocks.NewAuthHandlerMock() - - auditor := auditortest.NewErroring(instance.UpdateInstanceAction, audit.Attempted) - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - datasetAPI.Router.ServeHTTP(w, r) - - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) - - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 0) - - So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 0) - So(len(mockedDataStore.UpdateInstanceCalls()), ShouldEqual, 0) - So(len(mockedDataStore.AddVersionDetailsToInstanceCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: instance.UpdateInstanceAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - ) - }) - }) - - Convey(`When the instance resource is already published and hence request is - forbidden and so auditor attempts to audit unsuccessful request but it fails to do so`, func() { - Convey("Then return status internal server error (500)", func() { - body := strings.NewReader(`{"state":"completed"}`) - r, err := createRequestWithToken("PUT", "http://localhost:21800/instances/123", body) - So(err, ShouldBeNil) - w := httptest.NewRecorder() - - currentInstanceTest_Data := &models.Instance{ - Edition: "2017", - Links: &models.InstanceLinks{ - Dataset: &models.LinkObject{ - ID: "4567", - }, - }, - State: models.PublishedState, - } - - mockedDataStore := &storetest.StorerMock{ - GetInstanceFunc: func(id string) (*models.Instance, error) { - return currentInstanceTest_Data, nil - }, - UpdateInstanceFunc: func(ctx context.Context, id string, i *models.Instance) error { - return nil - }, - } - - datasetPermissions := mocks.NewAuthHandlerMock() - permissions := mocks.NewAuthHandlerMock() - - auditor := auditortest.NewErroring(instance.UpdateInstanceAction, audit.Unsuccessful) - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - datasetAPI.Router.ServeHTTP(w, r) - - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) - - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 1) - So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 1) - So(len(mockedDataStore.UpdateInstanceCalls()), ShouldEqual, 0) - So(len(mockedDataStore.AddVersionDetailsToInstanceCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: instance.UpdateInstanceAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: instance.UpdateInstanceAction, Result: audit.Unsuccessful, Params: common.Params{"instance_id": "123", "instance_state": models.PublishedState}}, - ) - }) - }) - - Convey(`When the request state change is invalid and the attempt to audit unsuccessful fails`, func() { - Convey("Then return status internal server error (500)", func() { - body := strings.NewReader(`{"state":"completed"}`) - r, err := createRequestWithToken("PUT", "http://localhost:21800/instances/123", body) - So(err, ShouldBeNil) - w := httptest.NewRecorder() - - currentInstanceTest_Data := &models.Instance{ - Edition: "2017", - Links: &models.InstanceLinks{ - Dataset: &models.LinkObject{ - ID: "4567", - }, - }, - State: models.AssociatedState, - } - - mockedDataStore := &storetest.StorerMock{ - GetInstanceFunc: func(id string) (*models.Instance, error) { - return currentInstanceTest_Data, nil - }, - UpdateInstanceFunc: func(ctx context.Context, id string, i *models.Instance) error { - return nil - }, - } - - datasetPermissions := mocks.NewAuthHandlerMock() - permissions := mocks.NewAuthHandlerMock() - - auditor := auditortest.NewErroring(instance.UpdateInstanceAction, audit.Unsuccessful) - datasetAPI := getAPIWithMocks(testContext, mockedDataStore, &mocks.DownloadsGeneratorMock{}, auditor, datasetPermissions, permissions) - datasetAPI.Router.ServeHTTP(w, r) - - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) - - So(datasetPermissions.Required.Calls, ShouldEqual, 0) - So(permissions.Required.Calls, ShouldEqual, 1) - - So(len(mockedDataStore.GetInstanceCalls()), ShouldEqual, 2) - So(len(mockedDataStore.UpdateInstanceCalls()), ShouldEqual, 0) - So(len(mockedDataStore.AddVersionDetailsToInstanceCalls()), ShouldEqual, 0) - - auditor.AssertRecordCalls( - auditortest.Expected{Action: instance.UpdateInstanceAction, Result: audit.Attempted, Params: auditParamsWithCallerIdentity}, - auditortest.Expected{Action: instance.UpdateInstanceAction, Result: audit.Unsuccessful, Params: auditParams}, - ) }) }) }) @@ -1302,7 +661,7 @@ func Test_UpdateInstance_AuditFailure(t *testing.T) { var urlBuilder = url.NewBuilder("localhost:20000") -func getAPIWithMocks(ctx context.Context, mockedDataStore store.Storer, mockedGeneratedDownloads api.DownloadsGenerator, mockAuditor api.Auditor, datasetPermissions api.AuthHandler, permissions api.AuthHandler) *api.DatasetAPI { +func getAPIWithMocks(ctx context.Context, mockedDataStore store.Storer, mockedGeneratedDownloads api.DownloadsGenerator, datasetPermissions api.AuthHandler, permissions api.AuthHandler) *api.DatasetAPI { mu.Lock() defer mu.Unlock() cfg, err := config.Get() @@ -1311,5 +670,5 @@ func getAPIWithMocks(ctx context.Context, mockedDataStore store.Storer, mockedGe cfg.DatasetAPIURL = "http://localhost:22000" cfg.EnablePrivateEndpoints = true - return api.NewDatasetAPI(ctx, *cfg, mux.NewRouter(), store.DataStore{Backend: mockedDataStore}, urlBuilder, mockedGeneratedDownloads, mockAuditor, datasetPermissions, permissions) + return api.NewDatasetAPI(ctx, *cfg, mux.NewRouter(), store.DataStore{Backend: mockedDataStore}, urlBuilder, mockedGeneratedDownloads, datasetPermissions, permissions) } diff --git a/main.go b/main.go index 64eb658e..1d8816f8 100644 --- a/main.go +++ b/main.go @@ -24,8 +24,7 @@ import ( kafka "github.com/ONSdigital/dp-kafka" mongolib "github.com/ONSdigital/dp-mongodb" mongoHealth "github.com/ONSdigital/dp-mongodb/health" - rchttp "github.com/ONSdigital/dp-rchttp" - "github.com/ONSdigital/go-ns/audit" + dphttp "github.com/ONSdigital/dp-net/http" "github.com/ONSdigital/log.go/log" "github.com/gorilla/mux" ) @@ -75,31 +74,6 @@ func run(ctx context.Context) error { // External services and their initialization state var serviceList initialise.ExternalServiceList - var auditor audit.AuditorService - var auditProducer *kafka.Producer - - if cfg.EnablePrivateEndpoints { - log.Event(ctx, "private endpoints enabled, enabling action auditing", log.INFO, log.Data{"auditTopicName": cfg.AuditEventsTopic}) - - auditProducer, err = serviceList.GetProducer( - ctx, - cfg.KafkaAddr, - cfg.AuditEventsTopic, - initialise.Audit, - 0, - ) - if err != nil { - log.Event(ctx, "could not obtain audit producer", log.FATAL, log.Error(err)) - return err - } - - auditProducerAdapter := adapter.NewProducerAdapter(auditProducer) - auditor = audit.New(auditProducerAdapter, "dp-dataset-api") - } else { - log.Event(ctx, "private endpoints disabled, auditing will not be enabled", log.INFO) - auditor = &audit.NopAuditor{} - } - mongoClient, mongodb, err := serviceList.GetMongoDB(ctx, cfg) if err != nil { log.Event(ctx, "could not obtain mongo session", log.ERROR, log.Error(err)) @@ -119,7 +93,6 @@ func run(ctx context.Context) error { ctx, cfg.KafkaAddr, cfg.GenerateDownloadsTopic, - initialise.GenerateDownloads, 0, ) if err != nil { @@ -146,7 +119,6 @@ func run(ctx context.Context) error { ctx, &hc, generateDownloadsProducer, - auditProducer, graphDB, mongoClient, zebedeeClient, @@ -162,7 +134,7 @@ func run(ctx context.Context) error { datasetPermissions, permissions := getAuthorisationHandlers(ctx, cfg) hc.Start(ctx) - api.CreateAndInitialiseDatasetAPI(ctx, *cfg, &hc, store, urlBuilder, apiErrors, downloadGenerator, auditor, datasetPermissions, permissions) + api.CreateAndInitialiseDatasetAPI(ctx, *cfg, &hc, store, urlBuilder, apiErrors, downloadGenerator, datasetPermissions, permissions) // block until a fatal error occurs select { @@ -204,15 +176,6 @@ func run(ctx context.Context) error { log.Event(shutdownContext, "closed generated downloads kafka producer", log.INFO, log.Data{"producer": "DimensionExtracted"}) } - if cfg.EnablePrivateEndpoints { - // If audit events kafka producer exists, close it - if serviceList.AuditProducer { - log.Event(shutdownContext, "closing audit events kafka producer", log.INFO, log.Data{"producer": "DimensionExtracted"}) - auditProducer.Close(shutdownContext) - log.Event(shutdownContext, "closed audit events kafka producer", log.INFO, log.Data{"producer": "DimensionExtracted"}) - } - } - if serviceList.Graph { err = graphDB.Close(ctx) if err != nil { @@ -249,7 +212,7 @@ func getAuthorisationHandlers(ctx context.Context, cfg *config.Configuration) (a log.Event(ctx, "feature flag enabled", log.INFO, log.Data{"feature": "ENABLE_PERMISSIONS_AUTH"}) auth.LoggerNamespace("dp-dataset-api-auth") - authClient := auth.NewPermissionsClient(rchttp.NewClient()) + authClient := auth.NewPermissionsClient(dphttp.NewClient()) authVerifier := auth.DefaultPermissionsVerifier() // for checking caller permissions when we have a datasetID, collection ID and user/service token @@ -272,7 +235,7 @@ func getAuthorisationHandlers(ctx context.Context, cfg *config.Configuration) (a // registerCheckers adds the checkers for the provided clients to the health check object func registerCheckers(ctx context.Context, hc *healthcheck.HealthCheck, - generateDownloads, auditProducer *kafka.Producer, + generateDownloads *kafka.Producer, graphDB *graph.DB, mongoClient *mongoHealth.Client, zebedeeClient *zebedee.Client, @@ -282,11 +245,6 @@ func registerCheckers(ctx context.Context, hasErrors := false if enablePrivateEndpoints { - if err = hc.AddCheck("Kafka Audit Producer", auditProducer.Checker); err != nil { - hasErrors = true - log.Event(ctx, "error adding check for kafka audit producer", log.ERROR, log.Error(err)) - } - if err = hc.AddCheck("Zebedee", zebedeeClient.Checker); err != nil { hasErrors = true log.Event(ctx, "error adding check for zebedeee", log.ERROR, log.Error(err)) From bfaf59b0b0c783c740fc647a7e41a9fede72337b Mon Sep 17 00:00:00 2001 From: David Subiros Date: Tue, 1 Sep 2020 09:43:03 +0200 Subject: [PATCH 05/13] Moved service logic from main to service, and, refactored api setup logic, according to the new API code structure --- api/api.go | 62 +----- api/dataset_test.go | 2 +- api/webendpoints_test.go | 2 +- dimension/dimension_test.go | 2 +- go.mod | 8 +- go.sum | 20 +- initialise/initialise.go | 97 ---------- instance/instance_external_test.go | 2 +- kafka/adapter.go | 4 +- main.go | 250 ++----------------------- mongo/dataset_store.go | 40 ++-- service/initialise.go | 124 ++++++++++++ service/interfaces.go | 39 ++++ service/service.go | 291 +++++++++++++++++++++++++++++ 14 files changed, 528 insertions(+), 415 deletions(-) delete mode 100644 initialise/initialise.go create mode 100644 service/initialise.go create mode 100644 service/interfaces.go create mode 100644 service/service.go diff --git a/api/api.go b/api/api.go index b06cd851..9e9b3cd0 100644 --- a/api/api.go +++ b/api/api.go @@ -14,13 +14,11 @@ import ( "github.com/ONSdigital/dp-dataset-api/instance" "github.com/ONSdigital/dp-dataset-api/store" "github.com/ONSdigital/dp-dataset-api/url" - "github.com/ONSdigital/dp-healthcheck/healthcheck" dphandlers "github.com/ONSdigital/dp-net/handlers" dphttp "github.com/ONSdigital/dp-net/http" dprequest "github.com/ONSdigital/dp-net/request" "github.com/ONSdigital/log.go/log" "github.com/gorilla/mux" - "github.com/justinas/alice" ) var httpServer *dphttp.Server @@ -78,16 +76,13 @@ type AuthHandler interface { // DatasetAPI manages importing filters against a dataset type DatasetAPI struct { + Router *mux.Router dataStore store.DataStore + urlBuilder *url.Builder host string - zebedeeURL string - internalToken string downloadServiceToken string EnablePrePublishView bool - Router *mux.Router - urlBuilder *url.Builder downloadGenerator DownloadsGenerator - serviceAuthToken string enablePrivateEndpoints bool enableDetachDataset bool enableObservationEndpoint bool @@ -97,61 +92,12 @@ type DatasetAPI struct { versionPublishedChecker *PublishCheck } -// CreateAndInitialiseDatasetAPI create a new DatasetAPI instance based on the configuration provided, apply middleware and starts the HTTP server. -func CreateAndInitialiseDatasetAPI(ctx context.Context, cfg config.Configuration, hc *healthcheck.HealthCheck, dataStore store.DataStore, urlBuilder *url.Builder, errorChan chan error, downloadGenerator DownloadsGenerator, datasetPermissions AuthHandler, permissions AuthHandler) { - router := mux.NewRouter() - api := NewDatasetAPI(ctx, cfg, router, dataStore, urlBuilder, downloadGenerator, datasetPermissions, permissions) - - healthcheckHandler := newMiddleware(hc.Handler, "/health") - middleware := alice.New(healthcheckHandler) - - // TODO can be removed once upstream services start calling the new health endpoint - oldHealthcheckHandler := newMiddleware(hc.Handler, "/healthcheck") - middleware = middleware.Append(oldHealthcheckHandler) - - // Only add the identity middleware when running in publishing. - if cfg.EnablePrivateEndpoints { - middleware = middleware.Append(dphandlers.Identity(cfg.ZebedeeURL)) - } - - middleware = middleware.Append(dphandlers.CheckHeader(dphandlers.CollectionID)) - - httpServer = dphttp.NewServer(cfg.BindAddr, middleware.Then(api.Router)) - - // Disable this here to allow main to manage graceful shutdown of the entire app. - httpServer.HandleOSSignals = false - - go func() { - log.Event(ctx, "Starting api...", log.INFO) - if err := httpServer.ListenAndServe(); err != nil { - log.Event(ctx, "api http server returned error", log.ERROR, log.Error(err)) - errorChan <- err - } - }() -} - -// newMiddleware creates a new http.Handler to intercept /health requests. -func newMiddleware(healthcheckHandler func(http.ResponseWriter, *http.Request), path string) func(http.Handler) http.Handler { - return func(h http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - - if req.Method == "GET" && req.URL.Path == path { - healthcheckHandler(w, req) - return - } - - h.ServeHTTP(w, req) - }) - } -} +// Setup creates a new Dataset API instance and register the API routes based on the application configuration. +func Setup(ctx context.Context, cfg *config.Configuration, router *mux.Router, dataStore store.DataStore, urlBuilder *url.Builder, downloadGenerator DownloadsGenerator, datasetPermissions AuthHandler, permissions AuthHandler) *DatasetAPI { -// NewDatasetAPI create a new Dataset API instance and register the API routes based on the application configuration. -func NewDatasetAPI(ctx context.Context, cfg config.Configuration, router *mux.Router, dataStore store.DataStore, urlBuilder *url.Builder, downloadGenerator DownloadsGenerator, datasetPermissions AuthHandler, permissions AuthHandler) *DatasetAPI { api := &DatasetAPI{ dataStore: dataStore, host: cfg.DatasetAPIURL, - zebedeeURL: cfg.ZebedeeURL, - serviceAuthToken: cfg.ServiceAuthToken, downloadServiceToken: cfg.DownloadServiceSecretKey, EnablePrePublishView: cfg.EnablePrivateEndpoints, Router: router, diff --git a/api/dataset_test.go b/api/dataset_test.go index bae35a2e..d7925ef6 100644 --- a/api/dataset_test.go +++ b/api/dataset_test.go @@ -55,7 +55,7 @@ func GetAPIWithMocks(mockedDataStore store.Storer, mockedGeneratedDownloads Down cfg.DatasetAPIURL = host cfg.EnablePrivateEndpoints = true - return NewDatasetAPI(testContext, *cfg, mux.NewRouter(), store.DataStore{Backend: mockedDataStore}, urlBuilder, mockedGeneratedDownloads, datasetPermissions, permissions) + return Setup(testContext, cfg, mux.NewRouter(), store.DataStore{Backend: mockedDataStore}, urlBuilder, mockedGeneratedDownloads, datasetPermissions, permissions) } func createRequestWithAuth(method, URL string, body io.Reader) (*http.Request, error) { diff --git a/api/webendpoints_test.go b/api/webendpoints_test.go index 0c868c46..df417211 100644 --- a/api/webendpoints_test.go +++ b/api/webendpoints_test.go @@ -346,5 +346,5 @@ func GetWebAPIWithMocks(ctx context.Context, mockedDataStore store.Storer, mocke cfg.DatasetAPIURL = host cfg.EnablePrivateEndpoints = false - return NewDatasetAPI(ctx, *cfg, mux.NewRouter(), store.DataStore{Backend: mockedDataStore}, urlBuilder, mockedGeneratedDownloads, datasetPermissions, permissions) + return Setup(ctx, cfg, mux.NewRouter(), store.DataStore{Backend: mockedDataStore}, urlBuilder, mockedGeneratedDownloads, datasetPermissions, permissions) } diff --git a/dimension/dimension_test.go b/dimension/dimension_test.go index cdce5a44..16fcf9ba 100644 --- a/dimension/dimension_test.go +++ b/dimension/dimension_test.go @@ -567,7 +567,7 @@ func getAPIWithMocks(ctx context.Context, mockedDataStore store.Storer, mockedGe datasetPermissions := getAuthorisationHandlerMock() permissions := getAuthorisationHandlerMock() - return api.NewDatasetAPI(ctx, *cfg, mux.NewRouter(), store.DataStore{Backend: mockedDataStore}, urlBuilder, mockedGeneratedDownloads, datasetPermissions, permissions) + return api.Setup(ctx, cfg, mux.NewRouter(), store.DataStore{Backend: mockedDataStore}, urlBuilder, mockedGeneratedDownloads, datasetPermissions, permissions) } func getAuthorisationHandlerMock() *mocks.AuthHandlerMock { diff --git a/go.mod b/go.mod index a2a977b6..36a3c02f 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/ONSdigital/dp-dataset-api go 1.13 require ( - github.com/ONSdigital/dp-api-clients-go v1.26.0 + github.com/ONSdigital/dp-api-clients-go v1.27.0 github.com/ONSdigital/dp-authorisation v0.1.0 github.com/ONSdigital/dp-graph/v2 v2.1.3 github.com/ONSdigital/dp-healthcheck v1.0.5 @@ -13,13 +13,19 @@ require ( github.com/ONSdigital/go-ns v0.0.0-20200205115900-a11716f93bad github.com/ONSdigital/log.go v1.0.1 github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8 + github.com/golang/protobuf v1.3.2 // indirect github.com/gorilla/mux v1.8.0 + github.com/hashicorp/go-uuid v1.0.2 // indirect github.com/justinas/alice v1.2.0 github.com/kelseyhightower/envconfig v1.4.0 github.com/pkg/errors v0.9.1 github.com/satori/go.uuid v1.2.0 github.com/smartystreets/goconvey v1.6.4 + github.com/stretchr/testify v1.5.1 // indirect + golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db // indirect gopkg.in/avro.v0 v0.0.0-20171217001914-a730b5802183 // indirect ) replace github.com/ONSdigital/dp-net => ../dp-net + +replace github.com/ONSdigital/dp-api-clients-go => ../dp-api-clients-go diff --git a/go.sum b/go.sum index 1261622d..cb74b128 100644 --- a/go.sum +++ b/go.sum @@ -1,16 +1,8 @@ -github.com/ONSdigital/dp-api-clients-go v1.1.0 h1:j2zmSFcWWRbHs58m0+LltmijHBqbnOJivqBHWPaVgoI= -github.com/ONSdigital/dp-api-clients-go v1.1.0/go.mod h1:9lqor0I7caCnRWr04gU/r7x5dqxgoODob8L48q+cE4E= -github.com/ONSdigital/dp-api-clients-go v1.9.0 h1:ru8jBPAxXfibYOF41/tU/ZtOt4tUVEszpMraHAbmvxA= -github.com/ONSdigital/dp-api-clients-go v1.9.0/go.mod h1:SM0b/NXDWndJ9EulmAGdfDY4DxPxK+pNsP8eZlIWiqM= -github.com/ONSdigital/dp-api-clients-go v1.26.0 h1:dDWL5+m+dtPVJpkmXAqm/5xRFhyIO5vgsEKJRZpnfMI= -github.com/ONSdigital/dp-api-clients-go v1.26.0/go.mod h1:Ds0lw6Rejqu46iyZTd5tiHriQW6CRhh56ucmmlCy6O8= github.com/ONSdigital/dp-authorisation v0.1.0 h1:HzYwJdvk7ZAeB56KMAH6MP5+5uZuuJnEyGq6CViDoCg= github.com/ONSdigital/dp-authorisation v0.1.0/go.mod h1:rT81tcvWto5/cUWUFd0Q6gTqBoRfQmD6Qp0sq7FyiMg= github.com/ONSdigital/dp-frontend-models v1.1.0/go.mod h1:TT96P7Mi69N3Tc/jFNdbjiwG4GAaMjP26HLotFQ6BPw= github.com/ONSdigital/dp-graph/v2 v2.1.3 h1:7BJsRE9FDf7tFtJvI5v7RX94q4BAbiJFDWpxQCNfM18= github.com/ONSdigital/dp-graph/v2 v2.1.3/go.mod h1:6C59rOY0qBKblczkQrJZZKa8ZLR3yKkyunSCeIUavtU= -github.com/ONSdigital/dp-healthcheck v0.0.0-20200131122546-9db6d3f0494e/go.mod h1:zighxZ/0m5u7zo0eAr8XFlA+Dz2ic7A1vna6YXvhCjQ= -github.com/ONSdigital/dp-healthcheck v1.0.0/go.mod h1:zighxZ/0m5u7zo0eAr8XFlA+Dz2ic7A1vna6YXvhCjQ= github.com/ONSdigital/dp-healthcheck v1.0.2 h1:N8SzpYzdixVgJS9NMzTBA2RZ2bi3Am1wE5F8ROEpTYw= github.com/ONSdigital/dp-healthcheck v1.0.2/go.mod h1:zighxZ/0m5u7zo0eAr8XFlA+Dz2ic7A1vna6YXvhCjQ= github.com/ONSdigital/dp-healthcheck v1.0.5 h1:DXnohGIqXaLLeYGdaGOhgkZjAbWMNoLAjQ3EgZeMT3M= @@ -74,10 +66,11 @@ github.com/go-avro/avro v0.0.0-20171219232920-444163702c11/go.mod h1:kxj6THYP0dm github.com/go-test/deep v1.0.6/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8= github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE= github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/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/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= @@ -94,6 +87,8 @@ github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE= +github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hokaccha/go-prettyjson v0.0.0-20190818114111-108c894c2c0e h1:0aewS5NTyxftZHSnFaJmWE5oCCrj4DyEXkAiMa1iZJM= github.com/hokaccha/go-prettyjson v0.0.0-20190818114111-108c894c2c0e/go.mod h1:pFlLw2CfqZiIBOx6BuCeRLCrfxBJipTY0nIOF/VbGcI= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= @@ -147,10 +142,13 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1 github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/square/mongo-lock v0.0.0-20191001051310-282c90e422d0 h1:Ae3eHg4QrqbpLdF/Y6jeREKvgqlgrftOglYY4RHdv9s= github.com/square/mongo-lock v0.0.0-20191001051310-282c90e422d0/go.mod h1:wR5++/O5fpa0UtI+9T8gKIi5jjl10va/EIEMRySqic4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/unrolled/render v1.0.2/go.mod h1:gN9T0NhL4Bfbwu8ann7Ry/TGHYfosul+J0obPf6NBdM= github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= @@ -181,6 +179,9 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20u golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/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.20181227161524-e6919f6577db h1:6/JqlYfC1CCaLnGceQTI+sDGhC9UBSPAsBqI0Gun6kU= +golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc= @@ -205,5 +206,6 @@ gopkg.in/jcmturner/rpc.v1 v1.1.0 h1:QHIUxTX1ISuAv9dD2wJ9HWQVuWDX/Zc0PfeC2tjc4rU= gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/initialise/initialise.go b/initialise/initialise.go deleted file mode 100644 index 5633ea3a..00000000 --- a/initialise/initialise.go +++ /dev/null @@ -1,97 +0,0 @@ -package initialise - -import ( - "context" - - "github.com/ONSdigital/dp-dataset-api/config" - "github.com/ONSdigital/dp-dataset-api/mongo" - "github.com/ONSdigital/dp-graph/v2/graph" - "github.com/ONSdigital/dp-healthcheck/healthcheck" - kafka "github.com/ONSdigital/dp-kafka" - mongoHealth "github.com/ONSdigital/dp-mongodb/health" - "github.com/ONSdigital/log.go/log" -) - -// ExternalServiceList represents a list of services -type ExternalServiceList struct { - GenerateDownloadsProducer bool - Graph bool - HealthCheck bool - MongoDB bool -} - -// GetProducer returns a kafka producer, which might not be initialised yet. -func (e *ExternalServiceList) GetProducer(ctx context.Context, kafkaBrokers []string, topic string, envMax int) (kafkaProducer *kafka.Producer, err error) { - pChannels := kafka.CreateProducerChannels() - kafkaProducer, err = kafka.NewProducer(ctx, kafkaBrokers, topic, envMax, pChannels) - if err != nil { - return - } - e.GenerateDownloadsProducer = true - return -} - -// GetGraphDB returns a graphDB -func (e *ExternalServiceList) GetGraphDB(ctx context.Context, cfg *config.Configuration) (*graph.DB, error) { - - // the graph DB is only used for the observation and private endpoint - if !cfg.EnableObservationEndpoint && !cfg.EnablePrivateEndpoints { - log.Event(ctx, "skipping graph DB client creation, because it is not required by the enabled endpoints", log.INFO, log.Data{ - "EnableObservationEndpoint": cfg.EnableObservationEndpoint, - "EnablePrivateEndpoints": cfg.EnablePrivateEndpoints, - }) - return nil, nil - } - - graphDB, err := graph.New(ctx, graph.Subsets{Observation: true, Instance: true}) - if err != nil { - return nil, err - } - - e.Graph = true - - return graphDB, nil -} - -// GetMongoDB returns a mongodb client and dataset mongo object -func (e *ExternalServiceList) GetMongoDB(ctx context.Context, cfg *config.Configuration) (*mongoHealth.Client, *mongo.Mongo, error) { - mongodb := &mongo.Mongo{ - CodeListURL: cfg.CodeListAPIURL, - Collection: cfg.MongoConfig.Collection, - Database: cfg.MongoConfig.Database, - DatasetURL: cfg.DatasetAPIURL, - URI: cfg.MongoConfig.BindAddr, - } - - session, err := mongodb.Init() - if err != nil { - log.Event(ctx, "failed to initialise mongo", log.ERROR, log.Error(err)) - return nil, nil, err - } else { - mongodb.Session = session - log.Event(ctx, "listening to mongo db session", log.INFO, log.Data{ - "bind_address": cfg.BindAddr, - }) - } - - client := mongoHealth.NewClient(session) - - e.MongoDB = true - - return client, mongodb, nil -} - -// GetHealthCheck creates a healthcheck with versionInfo -func (e *ExternalServiceList) GetHealthCheck(cfg *config.Configuration, buildTime, gitCommit, version string) (healthcheck.HealthCheck, error) { - - // Create healthcheck object with versionInfo - versionInfo, err := healthcheck.NewVersionInfo(buildTime, gitCommit, version) - if err != nil { - return healthcheck.HealthCheck{}, err - } - hc := healthcheck.New(versionInfo, cfg.HealthCheckCriticalTimeout, cfg.HealthCheckInterval) - - e.HealthCheck = true - - return hc, nil -} diff --git a/instance/instance_external_test.go b/instance/instance_external_test.go index 61381184..7093f243 100644 --- a/instance/instance_external_test.go +++ b/instance/instance_external_test.go @@ -670,5 +670,5 @@ func getAPIWithMocks(ctx context.Context, mockedDataStore store.Storer, mockedGe cfg.DatasetAPIURL = "http://localhost:22000" cfg.EnablePrivateEndpoints = true - return api.NewDatasetAPI(ctx, *cfg, mux.NewRouter(), store.DataStore{Backend: mockedDataStore}, urlBuilder, mockedGeneratedDownloads, datasetPermissions, permissions) + return api.Setup(ctx, cfg, mux.NewRouter(), store.DataStore{Backend: mockedDataStore}, urlBuilder, mockedGeneratedDownloads, datasetPermissions, permissions) } diff --git a/kafka/adapter.go b/kafka/adapter.go index 6c27ac67..51c2cbf6 100644 --- a/kafka/adapter.go +++ b/kafka/adapter.go @@ -3,13 +3,13 @@ package kafka import kafka "github.com/ONSdigital/dp-kafka" // NewProducerAdapter creates a new kafka producer with access to Output function -func NewProducerAdapter(producer *kafka.Producer) *Producer { +func NewProducerAdapter(producer kafka.IProducer) *Producer { return &Producer{kafkaProducer: producer} } // Producer exposes an output function, to satisfy the interface used by go-ns libraries type Producer struct { - kafkaProducer *kafka.Producer + kafkaProducer kafka.IProducer } // Output returns the output channel diff --git a/main.go b/main.go index 1d8816f8..5819df6a 100644 --- a/main.go +++ b/main.go @@ -2,41 +2,17 @@ package main import ( "context" - "errors" - "fmt" "os" "os/signal" "syscall" - "github.com/ONSdigital/dp-api-clients-go/zebedee" - "github.com/ONSdigital/dp-authorisation/auth" - "github.com/ONSdigital/dp-dataset-api/api" "github.com/ONSdigital/dp-dataset-api/config" - "github.com/ONSdigital/dp-dataset-api/download" - "github.com/ONSdigital/dp-dataset-api/initialise" - adapter "github.com/ONSdigital/dp-dataset-api/kafka" - "github.com/ONSdigital/dp-dataset-api/mongo" - "github.com/ONSdigital/dp-dataset-api/schema" - "github.com/ONSdigital/dp-dataset-api/store" - "github.com/ONSdigital/dp-dataset-api/url" - "github.com/ONSdigital/dp-graph/v2/graph" - "github.com/ONSdigital/dp-healthcheck/healthcheck" - kafka "github.com/ONSdigital/dp-kafka" - mongolib "github.com/ONSdigital/dp-mongodb" - mongoHealth "github.com/ONSdigital/dp-mongodb/health" - dphttp "github.com/ONSdigital/dp-net/http" + "github.com/ONSdigital/dp-dataset-api/service" "github.com/ONSdigital/log.go/log" - "github.com/gorilla/mux" + "github.com/pkg/errors" ) -// check that DatsetAPIStore satifies the the store.Storer interface -var _ store.Storer = (*DatsetAPIStore)(nil) - -//DatsetAPIStore is a wrapper which embeds Neo4j Mongo structs which between them satisfy the store.Storer interface. -type DatsetAPIStore struct { - *mongo.Mongo - *graph.DB -} +const serviceName = "dp-dataset-api" var ( // BuildTime represents the time in which the service was built @@ -48,233 +24,43 @@ var ( ) func main() { - log.Namespace = "dp-dataset-api" + log.Namespace = serviceName ctx := context.Background() if err := run(ctx); err != nil { log.Event(ctx, "application unexpectedly failed", log.ERROR, log.Error(err)) os.Exit(1) } - - os.Exit(0) } func run(ctx context.Context) error { signals := make(chan os.Signal, 1) signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM) + // Create the service, providing an error channel for fatal errors + svcErrors := make(chan error, 1) + svcList := service.NewServiceList(&service.Init{}) + + // Read config cfg, err := config.Get() if err != nil { log.Event(ctx, "failed to retrieve configuration", log.FATAL, log.Error(err)) return err } - log.Event(ctx, "config on startup", log.INFO, log.Data{"config": cfg, "build_time": BuildTime, "git-commit": GitCommit}) - // External services and their initialization state - var serviceList initialise.ExternalServiceList - - mongoClient, mongodb, err := serviceList.GetMongoDB(ctx, cfg) - if err != nil { - log.Event(ctx, "could not obtain mongo session", log.ERROR, log.Error(err)) - return err - } - - // Get graphDB connection for observation store - graphDB, err := serviceList.GetGraphDB(ctx, cfg) - if err != nil { - log.Event(ctx, "failed to initialise graph driver", log.FATAL, log.Error(err)) - return err - } - - store := store.DataStore{Backend: DatsetAPIStore{mongodb, graphDB}} - - generateDownloadsProducer, err := serviceList.GetProducer( - ctx, - cfg.KafkaAddr, - cfg.GenerateDownloadsTopic, - 0, - ) - if err != nil { - log.Event(ctx, "could not obtain generate downloads producer", log.FATAL, log.Error(err)) - return err - } - - downloadGenerator := &download.Generator{ - Producer: adapter.NewProducerAdapter(generateDownloadsProducer), - Marshaller: schema.GenerateDownloadsEvent, - } - - // Get HealthCheck - hc, err := serviceList.GetHealthCheck(cfg, BuildTime, GitCommit, Version) + // Run the service + svc, err := service.Run(ctx, cfg, svcList, BuildTime, GitCommit, Version, svcErrors) if err != nil { - log.Event(ctx, "could not instantiate healthcheck", log.FATAL, log.Error(err)) - return err - } - - zebedeeClient := zebedee.New(cfg.ZebedeeURL) - - // Add dataset API and graph checks - if err := registerCheckers( - ctx, - &hc, - generateDownloadsProducer, - graphDB, - mongoClient, - zebedeeClient, - cfg.EnablePrivateEndpoints, - cfg.EnableObservationEndpoint); err != nil { - return err + return errors.Wrap(err, "running service failed") } - apiErrors := make(chan error, 1) - - urlBuilder := url.NewBuilder(cfg.WebsiteURL) - - datasetPermissions, permissions := getAuthorisationHandlers(ctx, cfg) - - hc.Start(ctx) - api.CreateAndInitialiseDatasetAPI(ctx, *cfg, &hc, store, urlBuilder, apiErrors, downloadGenerator, datasetPermissions, permissions) - - // block until a fatal error occurs + // Blocks until an os interrupt or a fatal error occurs select { - case err := <-apiErrors: - log.Event(ctx, "api error received", log.ERROR, log.Error(err)) - case <-signals: - log.Event(ctx, "os signal received", log.INFO) - } - - log.Event(ctx, fmt.Sprintf("shutdown with timeout: %s", cfg.GracefulShutdownTimeout), log.INFO) - shutdownContext, cancel := context.WithTimeout(context.Background(), cfg.GracefulShutdownTimeout) - - // track shutdown gracefully closes app - var gracefulShutdown bool - - // Gracefully shutdown the application closing any open resources. - go func() { - defer cancel() - var hasShutdownError bool - - if serviceList.HealthCheck { - hc.Stop() - } - - // stop any incoming requests before closing any outbound connections - api.Close(shutdownContext) - - if serviceList.MongoDB { - if err = mongolib.Close(ctx, mongodb.Session); err != nil { - log.Event(shutdownContext, "failed to close mongo db session", log.ERROR, log.Error(err)) - hasShutdownError = true - } - } - - // If generate downloads kafka producer exists, close it - if serviceList.GenerateDownloadsProducer { - log.Event(shutdownContext, "closing generated downloads kafka producer", log.INFO, log.Data{"producer": "DimensionExtracted"}) - generateDownloadsProducer.Close(shutdownContext) - log.Event(shutdownContext, "closed generated downloads kafka producer", log.INFO, log.Data{"producer": "DimensionExtracted"}) - } - - if serviceList.Graph { - err = graphDB.Close(ctx) - if err != nil { - log.Event(ctx, "failed to close graph db", log.ERROR, log.Error(err)) - hasShutdownError = true - } - } - - if !hasShutdownError { - gracefulShutdown = true - } - }() - - // wait for shutdown success (via cancel) or failure (timeout) - <-shutdownContext.Done() - - if !gracefulShutdown { - err = errors.New("failed to shutdown gracefully") - log.Event(shutdownContext, "failed to shutdown gracefully ", log.ERROR, log.Error(err)) - return err - } - - log.Event(shutdownContext, "graceful shutdown was successful", log.INFO) - - return nil -} - -func getAuthorisationHandlers(ctx context.Context, cfg *config.Configuration) (api.AuthHandler, api.AuthHandler) { - if !cfg.EnablePermissionsAuth { - log.Event(ctx, "feature flag not enabled defaulting to nop auth impl", log.INFO, log.Data{"feature": "ENABLE_PERMISSIONS_AUTH"}) - return &auth.NopHandler{}, &auth.NopHandler{} - } - - log.Event(ctx, "feature flag enabled", log.INFO, log.Data{"feature": "ENABLE_PERMISSIONS_AUTH"}) - auth.LoggerNamespace("dp-dataset-api-auth") - - authClient := auth.NewPermissionsClient(dphttp.NewClient()) - authVerifier := auth.DefaultPermissionsVerifier() - - // for checking caller permissions when we have a datasetID, collection ID and user/service token - datasetPermissions := auth.NewHandler( - auth.NewDatasetPermissionsRequestBuilder(cfg.ZebedeeURL, "dataset_id", mux.Vars), - authClient, - authVerifier, - ) - - // for checking caller permissions when we only have a user/service token - permissions := auth.NewHandler( - auth.NewPermissionsRequestBuilder(cfg.ZebedeeURL), - authClient, - authVerifier, - ) - - return datasetPermissions, permissions -} - -// registerCheckers adds the checkers for the provided clients to the health check object -func registerCheckers(ctx context.Context, - hc *healthcheck.HealthCheck, - generateDownloads *kafka.Producer, - graphDB *graph.DB, - mongoClient *mongoHealth.Client, - zebedeeClient *zebedee.Client, - enablePrivateEndpoints, - enableObservationEndpoint bool) (err error) { - - hasErrors := false - - if enablePrivateEndpoints { - if err = hc.AddCheck("Zebedee", zebedeeClient.Checker); err != nil { - hasErrors = true - log.Event(ctx, "error adding check for zebedeee", log.ERROR, log.Error(err)) - } - } - - if err = hc.AddCheck("Kafka Generate Downloads Producer", generateDownloads.Checker); err != nil { - hasErrors = true - log.Event(ctx, "error adding check for kafka downloads producer", log.ERROR, log.Error(err)) - } - - mongoHealth := mongoHealth.CheckMongoClient{ - Client: *mongoClient, - Healthcheck: mongoClient.Healthcheck, - } - if err = hc.AddCheck("Mongo DB", mongoHealth.Checker); err != nil { - hasErrors = true - log.Event(ctx, "error adding check for mongo db", log.ERROR, log.Error(err)) - } - - if enablePrivateEndpoints || enableObservationEndpoint { - log.Event(ctx, "adding graph db health check as the private or observation endpoints are enabled", log.INFO) - if err = hc.AddCheck("Graph DB", graphDB.Driver.Checker); err != nil { - hasErrors = true - log.Event(ctx, "error adding check for graph db", log.ERROR, log.Error(err)) - } - } - - if hasErrors { - return errors.New("Error(s) registering checkers for healthcheck") + case err := <-svcErrors: + log.Event(ctx, "service error received", log.ERROR, log.Error(err)) + case sig := <-signals: + log.Event(ctx, "os signal received", log.Data{"signal": sig}, log.INFO) } - return nil + return svc.Close(ctx) } diff --git a/mongo/dataset_store.go b/mongo/dataset_store.go index 469cc671..c8f2d810 100644 --- a/mongo/dataset_store.go +++ b/mongo/dataset_store.go @@ -7,12 +7,13 @@ import ( "sync" "time" - "github.com/globalsign/mgo" - "github.com/globalsign/mgo/bson" - errs "github.com/ONSdigital/dp-dataset-api/apierrors" "github.com/ONSdigital/dp-dataset-api/models" + "github.com/ONSdigital/dp-healthcheck/healthcheck" + dpMongoHealth "github.com/ONSdigital/dp-mongodb/health" "github.com/ONSdigital/log.go/log" + "github.com/globalsign/mgo" + "github.com/globalsign/mgo/bson" ) // Mongo represents a simplistic MongoDB configuration. @@ -25,25 +26,40 @@ type Mongo struct { URI string lastPingTime time.Time lastPingResult error + client *dpMongoHealth.Client + healthClient *dpMongoHealth.CheckMongoClient } const ( editionsCollection = "editions" ) -// Init creates a new mgo.Session with a strong consistency and a write mode of "majortiy". -func (m *Mongo) Init() (session *mgo.Session, err error) { - if session != nil { - return nil, errors.New("session already exists") +// Init creates a new mgo.Session with a strong consistency and a write mode of "majortiy"; and initialises the mongo health client. +func (m *Mongo) Init() (err error) { + if m.Session != nil { + return errors.New("session already exists") } - if session, err = mgo.Dial(m.URI); err != nil { - return nil, err + // Create session + if m.Session, err = mgo.Dial(m.URI); err != nil { + return err + } + m.Session.EnsureSafe(&mgo.Safe{WMode: "majority"}) + m.Session.SetMode(mgo.Strong, true) + + // Create client and healthclient from session + m.client = dpMongoHealth.NewClient(m.Session) + m.healthClient = &dpMongoHealth.CheckMongoClient{ + Client: *m.client, + Healthcheck: m.client.Healthcheck, } - session.EnsureSafe(&mgo.Safe{WMode: "majority"}) - session.SetMode(mgo.Strong, true) - return session, nil + return nil +} + +// Checker is called by the healthcheck library to check the health state of this mongoDB instance +func (m *Mongo) Checker(ctx context.Context, state *healthcheck.CheckState) error { + return m.healthClient.Checker(ctx, state) } // GetDatasets retrieves all dataset documents diff --git a/service/initialise.go b/service/initialise.go new file mode 100644 index 00000000..e1145591 --- /dev/null +++ b/service/initialise.go @@ -0,0 +1,124 @@ +package service + +import ( + "context" + "net/http" + + "github.com/ONSdigital/dp-dataset-api/config" + "github.com/ONSdigital/dp-dataset-api/mongo" + "github.com/ONSdigital/dp-graph/v2/graph" + "github.com/ONSdigital/dp-healthcheck/healthcheck" + kafka "github.com/ONSdigital/dp-kafka" + dphttp "github.com/ONSdigital/dp-net/http" + "github.com/ONSdigital/log.go/log" +) + +// ExternalServiceList holds the initialiser and initialisation state of external services. +type ExternalServiceList struct { + GenerateDownloadsProducer bool + Graph bool + HealthCheck bool + MongoDB bool + Init Initialiser +} + +// NewServiceList creates a new service list with the provided initialiser +func NewServiceList(initialiser Initialiser) *ExternalServiceList { + return &ExternalServiceList{ + Init: initialiser, + } +} + +// Init implements the Initialiser interface to initialise dependencies +type Init struct{} + +// GetHTTPServer creates an http server +func (e *ExternalServiceList) GetHTTPServer(bindAddr string, router http.Handler) HTTPServer { + s := e.Init.DoGetHTTPServer(bindAddr, router) + return s +} + +// GetHealthCheck creates a healthcheck with versionInfo and sets the HealthCheck flag to true +func (e *ExternalServiceList) GetHealthCheck(cfg *config.Configuration, buildTime, gitCommit, version string) (HealthChecker, error) { + hc, err := e.Init.DoGetHealthCheck(cfg, buildTime, gitCommit, version) + if err != nil { + return nil, err + } + e.HealthCheck = true + return hc, nil +} + +// GetProducer returns a kafka producer, which might not be initialised yet. +func (e *ExternalServiceList) GetProducer(ctx context.Context, cfg *config.Configuration) (kafkaProducer kafka.IProducer, err error) { + kafkaProducer, err = e.Init.DoGetKafkaProducer(ctx, cfg) + if err != nil { + return + } + e.GenerateDownloadsProducer = true + return +} + +// GetGraphDB returns a graphDB (only if observation and private endpoint are enabled) +func (e *ExternalServiceList) GetGraphDB(ctx context.Context) (*graph.DB, error) { + graphDB, err := e.Init.DoGetGraphDB(ctx) + if err != nil { + return nil, err + } + e.Graph = true + return graphDB, nil +} + +// GetMongoDB returns a mongodb health client and dataset mongo object +func (e *ExternalServiceList) GetMongoDB(ctx context.Context, cfg *config.Configuration) (*mongo.Mongo, error) { + mongodb, err := e.Init.DoGetMongoDB(cfg) + if err != nil { + log.Event(ctx, "failed to initialise mongo", log.ERROR, log.Error(err)) + return nil, err + } + log.Event(ctx, "listening to mongo db session", log.INFO, log.Data{"URI": mongodb.URI}) + e.MongoDB = true + return mongodb, nil +} + +// DoGetHTTPServer creates an HTTP Server with the provided bind address and router +func (e *Init) DoGetHTTPServer(bindAddr string, router http.Handler) HTTPServer { + s := dphttp.NewServer(bindAddr, router) + s.HandleOSSignals = false + return s +} + +// DoGetHealthCheck creates a healthcheck with versionInfo +func (e *Init) DoGetHealthCheck(cfg *config.Configuration, buildTime, gitCommit, version string) (HealthChecker, error) { + versionInfo, err := healthcheck.NewVersionInfo(buildTime, gitCommit, version) + if err != nil { + return nil, err + } + hc := healthcheck.New(versionInfo, cfg.HealthCheckCriticalTimeout, cfg.HealthCheckInterval) + return &hc, nil +} + +// DoGetKafkaProducer creates a new Kafka Producer +func (e *Init) DoGetKafkaProducer(ctx context.Context, cfg *config.Configuration) (kafka.IProducer, error) { + pChannels := kafka.CreateProducerChannels() + return kafka.NewProducer(ctx, cfg.KafkaAddr, cfg.GenerateDownloadsTopic, 0, pChannels) +} + +// DoGetGraphDB creates a new GraphDB +func (e *Init) DoGetGraphDB(ctx context.Context) (*graph.DB, error) { + return graph.New(ctx, graph.Subsets{Observation: true, Instance: true}) +} + +// DoGetMongoDB returns a MongoDB +func (e *Init) DoGetMongoDB(cfg *config.Configuration) (*mongo.Mongo, error) { + mongodb := &mongo.Mongo{ + CodeListURL: cfg.CodeListAPIURL, + Collection: cfg.MongoConfig.Collection, + Database: cfg.MongoConfig.Database, + DatasetURL: cfg.DatasetAPIURL, + URI: cfg.MongoConfig.BindAddr, + } + if err := mongodb.Init(); err != nil { + return nil, err + } + return mongodb, nil +} diff --git a/service/interfaces.go b/service/interfaces.go new file mode 100644 index 00000000..514bc2f6 --- /dev/null +++ b/service/interfaces.go @@ -0,0 +1,39 @@ +package service + +import ( + "context" + "net/http" + + "github.com/ONSdigital/dp-dataset-api/config" + "github.com/ONSdigital/dp-dataset-api/mongo" + "github.com/ONSdigital/dp-graph/v2/graph" + "github.com/ONSdigital/dp-healthcheck/healthcheck" + kafka "github.com/ONSdigital/dp-kafka" +) + +//go:generate moq -out mock/initialiser.go -pkg mock . Initialiser +//go:generate moq -out mock/server.go -pkg mock . HTTPServer +//go:generate moq -out mock/healthcheck.go -pkg mock . HealthChecker + +// Initialiser defines the methods to initialise external services +type Initialiser interface { + DoGetHTTPServer(bindAddr string, router http.Handler) HTTPServer + DoGetHealthCheck(cfg *config.Configuration, buildTime, gitCommit, version string) (HealthChecker, error) + DoGetKafkaProducer(ctx context.Context, cfg *config.Configuration) (kafka.IProducer, error) + DoGetGraphDB(ctx context.Context) (*graph.DB, error) + DoGetMongoDB(cfg *config.Configuration) (*mongo.Mongo, error) +} + +// HTTPServer defines the required methods from the HTTP server +type HTTPServer interface { + ListenAndServe() error + Shutdown(ctx context.Context) error +} + +// HealthChecker defines the required methods from Healthcheck +type HealthChecker interface { + Handler(w http.ResponseWriter, req *http.Request) + Start(ctx context.Context) + Stop() + AddCheck(name string, checker healthcheck.Checker) (err error) +} diff --git a/service/service.go b/service/service.go new file mode 100644 index 00000000..5bc9f179 --- /dev/null +++ b/service/service.go @@ -0,0 +1,291 @@ +package service + +import ( + "context" + "net/http" + + clientsidentity "github.com/ONSdigital/dp-api-clients-go/identity" + "github.com/ONSdigital/dp-authorisation/auth" + "github.com/ONSdigital/dp-dataset-api/api" + "github.com/ONSdigital/dp-dataset-api/config" + "github.com/ONSdigital/dp-dataset-api/download" + adapter "github.com/ONSdigital/dp-dataset-api/kafka" + "github.com/ONSdigital/dp-dataset-api/mongo" + "github.com/ONSdigital/dp-dataset-api/schema" + "github.com/ONSdigital/dp-dataset-api/store" + "github.com/ONSdigital/dp-dataset-api/url" + "github.com/ONSdigital/dp-graph/v2/graph" + kafka "github.com/ONSdigital/dp-kafka" + mongolib "github.com/ONSdigital/dp-mongodb" + dphandlers "github.com/ONSdigital/dp-net/handlers" + dphttp "github.com/ONSdigital/dp-net/http" + "github.com/ONSdigital/log.go/log" + "github.com/gorilla/mux" + "github.com/justinas/alice" + "github.com/pkg/errors" +) + +// check that DatsetAPIStore satifies the the store.Storer interface +var _ store.Storer = (*DatsetAPIStore)(nil) + +//DatsetAPIStore is a wrapper which embeds Neo4j Mongo structs which between them satisfy the store.Storer interface. +type DatsetAPIStore struct { + *mongo.Mongo + *graph.DB +} + +// Service contains all the configs, server and clients to run the Dataset API +type Service struct { + Config *config.Configuration + ServiceList *ExternalServiceList + graphDB *graph.DB + generateDownloadsProducer kafka.IProducer + identityClient *clientsidentity.Client + Server HTTPServer + HealthCheck HealthChecker + mongoDB *mongo.Mongo + API *api.DatasetAPI +} + +// Run the service +func Run(ctx context.Context, cfg *config.Configuration, serviceList *ExternalServiceList, buildTime, gitCommit, version string, svcErrors chan error) (svc *Service, err error) { + + svc = &Service{ + Config: cfg, + ServiceList: serviceList, + } + + // Get MongoDB connection + svc.mongoDB, err = serviceList.GetMongoDB(ctx, cfg) + if err != nil { + log.Event(ctx, "could not obtain mongo session", log.ERROR, log.Error(err)) + return nil, err + } + + // Get graphDB connection for observation store + if !cfg.EnableObservationEndpoint && !cfg.EnablePrivateEndpoints { + log.Event(ctx, "skipping graph DB client creation, because it is not required by the enabled endpoints", log.INFO, log.Data{ + "EnableObservationEndpoint": cfg.EnableObservationEndpoint, + "EnablePrivateEndpoints": cfg.EnablePrivateEndpoints, + }) + } else { + svc.graphDB, err = serviceList.GetGraphDB(ctx) + if err != nil { + log.Event(ctx, "failed to initialise graph driver", log.FATAL, log.Error(err)) + return nil, err + } + } + store := store.DataStore{Backend: DatsetAPIStore{svc.mongoDB, svc.graphDB}} + + // Get GenerateDownloads Kafka Producer + svc.generateDownloadsProducer, err = serviceList.GetProducer(ctx, cfg) + if err != nil { + log.Event(ctx, "could not obtain generate downloads producer", log.FATAL, log.Error(err)) + return nil, err + } + + downloadGenerator := &download.Generator{ + Producer: adapter.NewProducerAdapter(svc.generateDownloadsProducer), + Marshaller: schema.GenerateDownloadsEvent, + } + + // Get Identity Client (only if private endpoints are enabled) + if cfg.EnablePrivateEndpoints { + svc.identityClient = clientsidentity.New(cfg.ZebedeeURL) + } + + // Get HealthCheck + svc.HealthCheck, err = serviceList.GetHealthCheck(cfg, buildTime, gitCommit, version) + if err != nil { + log.Event(ctx, "could not instantiate healthcheck", log.FATAL, log.Error(err)) + return nil, err + } + if err := svc.registerCheckers(ctx); err != nil { + return nil, errors.Wrap(err, "unable to register checkers") + } + + // Get HTTP router and server with middleware + r := mux.NewRouter() + m := svc.createMiddleware(cfg) + svc.Server = serviceList.GetHTTPServer(cfg.BindAddr, m.Then(r)) + + // Create Dataset API + urlBuilder := url.NewBuilder(cfg.WebsiteURL) + datasetPermissions, permissions := getAuthorisationHandlers(ctx, cfg) + svc.API = api.Setup(ctx, cfg, r, store, urlBuilder, downloadGenerator, datasetPermissions, permissions) + + svc.HealthCheck.Start(ctx) + + // Run the http server in a new go-routine + go func() { + if err := svc.Server.ListenAndServe(); err != nil { + svcErrors <- errors.Wrap(err, "failure in http listen and serve") + } + }() + + return svc, nil +} + +func getAuthorisationHandlers(ctx context.Context, cfg *config.Configuration) (api.AuthHandler, api.AuthHandler) { + if !cfg.EnablePermissionsAuth { + log.Event(ctx, "feature flag not enabled defaulting to nop auth impl", log.INFO, log.Data{"feature": "ENABLE_PERMISSIONS_AUTH"}) + return &auth.NopHandler{}, &auth.NopHandler{} + } + + log.Event(ctx, "feature flag enabled", log.INFO, log.Data{"feature": "ENABLE_PERMISSIONS_AUTH"}) + auth.LoggerNamespace("dp-dataset-api-auth") + + authClient := auth.NewPermissionsClient(dphttp.NewClient()) + authVerifier := auth.DefaultPermissionsVerifier() + + // for checking caller permissions when we have a datasetID, collection ID and user/service token + datasetPermissions := auth.NewHandler( + auth.NewDatasetPermissionsRequestBuilder(cfg.ZebedeeURL, "dataset_id", mux.Vars), + authClient, + authVerifier, + ) + + // for checking caller permissions when we only have a user/service token + permissions := auth.NewHandler( + auth.NewPermissionsRequestBuilder(cfg.ZebedeeURL), + authClient, + authVerifier, + ) + + return datasetPermissions, permissions +} + +// CreateMiddleware creates an Alice middleware chain of handlers +// to forward collectionID from cookie from header +func (svc *Service) createMiddleware(cfg *config.Configuration) alice.Chain { + + // healthcheck + healthcheckHandler := newMiddleware(svc.HealthCheck.Handler, "/health") + middleware := alice.New(healthcheckHandler) + + // Only add the identity middleware when running in publishing. + if cfg.EnablePrivateEndpoints { + middleware = middleware.Append(dphandlers.IdentityWithHTTPClient(svc.identityClient)) + } + + // collection ID + middleware = middleware.Append(dphandlers.CheckHeader(dphandlers.CollectionID)) + + return middleware +} + +// newMiddleware creates a new http.Handler to intercept /health requests. +func newMiddleware(healthcheckHandler func(http.ResponseWriter, *http.Request), path string) func(http.Handler) http.Handler { + return func(h http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + + if req.Method == "GET" && req.URL.Path == path { + healthcheckHandler(w, req) + return + } + + h.ServeHTTP(w, req) + }) + } +} + +// Close gracefully shuts the service down in the required order, with timeout +func (svc *Service) Close(ctx context.Context) error { + timeout := svc.Config.GracefulShutdownTimeout + log.Event(ctx, "commencing graceful shutdown", log.Data{"graceful_shutdown_timeout": timeout}, log.INFO) + shutdownContext, cancel := context.WithTimeout(ctx, timeout) + hasShutdownError := false + + // Gracefully shutdown the application closing any open resources. + go func() { + defer cancel() + + // stop healthcheck, as it depends on everything else + if svc.ServiceList.HealthCheck { + svc.HealthCheck.Stop() + } + + // stop any incoming requests + if err := svc.Server.Shutdown(ctx); err != nil { + log.Event(ctx, "failed to shutdown http server", log.Error(err), log.ERROR) + hasShutdownError = true + } + + // Close MongoDB (if it exists) + if svc.ServiceList.MongoDB { + if err := mongolib.Close(ctx, svc.mongoDB.Session); err != nil { + log.Event(shutdownContext, "failed to close mongo db session", log.ERROR, log.Error(err)) + hasShutdownError = true + } + } + + // Close GenerateDownloadsProducer (if it exists) + if svc.ServiceList.GenerateDownloadsProducer { + log.Event(shutdownContext, "closing generated downloads kafka producer", log.INFO, log.Data{"producer": "DimensionExtracted"}) + svc.generateDownloadsProducer.Close(shutdownContext) + log.Event(shutdownContext, "closed generated downloads kafka producer", log.INFO, log.Data{"producer": "DimensionExtracted"}) + } + + // Close GraphDB (if it exists) + if svc.ServiceList.Graph { + if err := svc.graphDB.Close(ctx); err != nil { + log.Event(ctx, "failed to close graph db", log.ERROR, log.Error(err)) + hasShutdownError = true + } + } + }() + + // wait for shutdown success (via cancel) or failure (timeout) + <-shutdownContext.Done() + + // timeout expired + if ctx.Err() == context.DeadlineExceeded { + log.Event(ctx, "shutdown timed out", log.ERROR, log.Error(ctx.Err())) + return ctx.Err() + } + + // other error + if hasShutdownError { + err := errors.New("failed to shutdown gracefully") + log.Event(shutdownContext, "failed to shutdown gracefully ", log.ERROR, log.Error(err)) + return err + } + + log.Event(shutdownContext, "graceful shutdown was successful", log.INFO) + return nil +} + +// registerCheckers adds the checkers for the provided clients to the health check object +func (svc *Service) registerCheckers(ctx context.Context) (err error) { + hasErrors := false + + if svc.Config.EnablePrivateEndpoints { + if err = svc.HealthCheck.AddCheck("Zebedee", svc.identityClient.Checker); err != nil { + hasErrors = true + log.Event(ctx, "error adding check for zebedeee", log.ERROR, log.Error(err)) + } + } + + if err = svc.HealthCheck.AddCheck("Kafka Generate Downloads Producer", svc.generateDownloadsProducer.Checker); err != nil { + hasErrors = true + log.Event(ctx, "error adding check for kafka downloads producer", log.ERROR, log.Error(err)) + } + + if err = svc.HealthCheck.AddCheck("Mongo DB", svc.mongoDB.Checker); err != nil { + hasErrors = true + log.Event(ctx, "error adding check for mongo db", log.ERROR, log.Error(err)) + } + + if svc.Config.EnablePrivateEndpoints || svc.Config.EnableObservationEndpoint { + log.Event(ctx, "adding graph db health check as the private or observation endpoints are enabled", log.INFO) + if err = svc.HealthCheck.AddCheck("Graph DB", svc.graphDB.Driver.Checker); err != nil { + hasErrors = true + log.Event(ctx, "error adding check for graph db", log.ERROR, log.Error(err)) + } + } + + if hasErrors { + return errors.New("Error(s) registering checkers for healthcheck") + } + return nil +} From 927c5b03bd63bec545392a24aefd2f2d86d9303f Mon Sep 17 00:00:00 2001 From: David Subiros Date: Tue, 1 Sep 2020 13:52:19 +0200 Subject: [PATCH 06/13] Created service test, with required interfaces and mocks for mongoDB and graphDB --- go.mod | 9 +- go.sum | 24 +- mongo/dataset_store.go | 9 + service/initialise.go | 13 +- service/interfaces.go | 7 +- service/mock/healthcheck.go | 214 ++++ service/mock/initialiser.go | 290 ++++++ service/mock/server.go | 114 +++ service/service.go | 47 +- service/service_test.go | 436 +++++++++ store/datastore.go | 30 +- store/datastoretest/graph.go | 312 ++++++ store/datastoretest/mongo.go | 1783 ++++++++++++++++++++++++++++++++++ 13 files changed, 3247 insertions(+), 41 deletions(-) create mode 100644 service/mock/healthcheck.go create mode 100644 service/mock/initialiser.go create mode 100644 service/mock/server.go create mode 100644 service/service_test.go create mode 100644 store/datastoretest/graph.go create mode 100644 store/datastoretest/mongo.go diff --git a/go.mod b/go.mod index 36a3c02f..0b075d4f 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/ONSdigital/dp-dataset-api go 1.13 require ( - github.com/ONSdigital/dp-api-clients-go v1.27.0 + github.com/ONSdigital/dp-api-clients-go v1.28.0 github.com/ONSdigital/dp-authorisation v0.1.0 github.com/ONSdigital/dp-graph/v2 v2.1.3 github.com/ONSdigital/dp-healthcheck v1.0.5 @@ -12,17 +12,22 @@ require ( github.com/ONSdigital/dp-net v1.0.7 github.com/ONSdigital/go-ns v0.0.0-20200205115900-a11716f93bad github.com/ONSdigital/log.go v1.0.1 + github.com/frankban/quicktest v1.9.0 // indirect github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8 github.com/golang/protobuf v1.3.2 // indirect github.com/gorilla/mux v1.8.0 + github.com/gorilla/websocket v1.4.1 // indirect github.com/hashicorp/go-uuid v1.0.2 // indirect github.com/justinas/alice v1.2.0 github.com/kelseyhightower/envconfig v1.4.0 + github.com/klauspost/compress v1.9.5 // indirect + github.com/mattn/go-isatty v0.0.12 // indirect + github.com/pierrec/lz4 v2.4.1+incompatible // indirect github.com/pkg/errors v0.9.1 github.com/satori/go.uuid v1.2.0 github.com/smartystreets/goconvey v1.6.4 github.com/stretchr/testify v1.5.1 // indirect - golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db // indirect + golang.org/x/text v0.3.3 // indirect gopkg.in/avro.v0 v0.0.0-20171217001914-a730b5802183 // indirect ) diff --git a/go.sum b/go.sum index cb74b128..fa90e180 100644 --- a/go.sum +++ b/go.sum @@ -57,6 +57,8 @@ github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8 github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/frankban/quicktest v1.4.1 h1:Wv2VwvNn73pAdFIVUQRXYDFp31lXKbqblIXo/Q5GPSg= github.com/frankban/quicktest v1.4.1/go.mod h1:36zfPVQyHxymz4cH7wlDmVwDrJuljRB60qkgn7rorfQ= +github.com/frankban/quicktest v1.9.0 h1:jfEA+Psfr/pHsRJYPpHiNu7PGJnGctNxvTaM3K1EyXk= +github.com/frankban/quicktest v1.9.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8 h1:DujepqpGd1hyOd7aW59XpK7Qymp8iy83xq74fLr21is= @@ -75,6 +77,8 @@ github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= @@ -82,9 +86,12 @@ github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc= github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/schema v1.1.0 h1:CamqUDOFUBqzrvxuz2vEwo8+SUdwsluFh7IlzJh30LY= github.com/gorilla/schema v1.1.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU= github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE= @@ -103,10 +110,14 @@ github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dv github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= github.com/klauspost/compress v1.8.2 h1:Bx0qjetmNjdFXASH02NSAREKpiaDwkO1DRZ3dV2KCcs= github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.9.5 h1:U+CaK85mrNNb4k8BNOfgJtJ/gr6kswUCFj6miSzVC6M= +github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/cpuid v1.2.3 h1:CCtW0xUnWGVINKvE/WWOYKdsPV6mawAtvQuSl8guwQs= github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= @@ -115,6 +126,8 @@ github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVc github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/mongo-go/testdb v0.0.0-20190724200850-a72a12eee610/go.mod h1:xyZcxcSxyRLfj4CDZzyycsGRcwfpY07ncmD2keFr548= @@ -128,6 +141,8 @@ github.com/onsi/gomega v1.9.0 h1:R1uwffexN6Pr340GtYRIdZmAiN4J+iw6WG4wog1DUXg= github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/pierrec/lz4 v2.2.6+incompatible h1:6aCX4/YZ9v8q69hTyiR7dNLnTA3fgtKHVVW5BCd5Znw= github.com/pierrec/lz4 v2.2.6+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pierrec/lz4 v2.4.1+incompatible h1:mFe7ttWaflA46Mhqh+jUfjp2qTbPYxLB2/OyBppH9dg= +github.com/pierrec/lz4 v2.4.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -150,7 +165,9 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/unrolled/render v1.0.2/go.mod h1:gN9T0NhL4Bfbwu8ann7Ry/TGHYfosul+J0obPf6NBdM= +github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c h1:u40Z8hqBAAQyv+vATcGgV0YCnDjqSL7/q/JyPhhJSPk= github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= +github.com/xdg/stringprep v1.0.0 h1:d9X0esnoa3dFsV0FG35rAT0RIhYFlPq7MiP+DW89La0= github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5 h1:bselrhR0Or1vomJZC8ZIjWtbDmn9OYFLX5Ik9alpJpE= @@ -175,17 +192,20 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e h1:N7DeIrjYszNmSW409R3frPPwglRwMkXSBzwVbkOjLLA= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/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.20181227161524-e6919f6577db h1:6/JqlYfC1CCaLnGceQTI+sDGhC9UBSPAsBqI0Gun6kU= -golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/avro.v0 v0.0.0-20171217001914-a730b5802183 h1:PGIdqvwfpMUyUP+QAlAnKTSWQ671SmYjoou2/5j7HXk= gopkg.in/avro.v0 v0.0.0-20171217001914-a730b5802183/go.mod h1:FvqrFXt+jCsyQibeRv4xxEJBL5iG2DDW5aeJwzDiq4A= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= diff --git a/mongo/dataset_store.go b/mongo/dataset_store.go index c8f2d810..4d8626d0 100644 --- a/mongo/dataset_store.go +++ b/mongo/dataset_store.go @@ -10,6 +10,7 @@ import ( errs "github.com/ONSdigital/dp-dataset-api/apierrors" "github.com/ONSdigital/dp-dataset-api/models" "github.com/ONSdigital/dp-healthcheck/healthcheck" + dpmongo "github.com/ONSdigital/dp-mongodb" dpMongoHealth "github.com/ONSdigital/dp-mongodb/health" "github.com/ONSdigital/log.go/log" "github.com/globalsign/mgo" @@ -57,6 +58,14 @@ func (m *Mongo) Init() (err error) { return nil } +// Close represents mongo session closing within the context deadline +func (m *Mongo) Close(ctx context.Context) error { + if m.Session == nil { + return errors.New("cannot close a mongoDB connection without a valid session") + } + return dpmongo.Close(ctx, m.Session) +} + // Checker is called by the healthcheck library to check the health state of this mongoDB instance func (m *Mongo) Checker(ctx context.Context, state *healthcheck.CheckState) error { return m.healthClient.Checker(ctx, state) diff --git a/service/initialise.go b/service/initialise.go index e1145591..02eea363 100644 --- a/service/initialise.go +++ b/service/initialise.go @@ -6,6 +6,7 @@ import ( "github.com/ONSdigital/dp-dataset-api/config" "github.com/ONSdigital/dp-dataset-api/mongo" + "github.com/ONSdigital/dp-dataset-api/store" "github.com/ONSdigital/dp-graph/v2/graph" "github.com/ONSdigital/dp-healthcheck/healthcheck" kafka "github.com/ONSdigital/dp-kafka" @@ -59,7 +60,7 @@ func (e *ExternalServiceList) GetProducer(ctx context.Context, cfg *config.Confi } // GetGraphDB returns a graphDB (only if observation and private endpoint are enabled) -func (e *ExternalServiceList) GetGraphDB(ctx context.Context) (*graph.DB, error) { +func (e *ExternalServiceList) GetGraphDB(ctx context.Context) (store.GraphDB, error) { graphDB, err := e.Init.DoGetGraphDB(ctx) if err != nil { return nil, err @@ -69,13 +70,12 @@ func (e *ExternalServiceList) GetGraphDB(ctx context.Context) (*graph.DB, error) } // GetMongoDB returns a mongodb health client and dataset mongo object -func (e *ExternalServiceList) GetMongoDB(ctx context.Context, cfg *config.Configuration) (*mongo.Mongo, error) { - mongodb, err := e.Init.DoGetMongoDB(cfg) +func (e *ExternalServiceList) GetMongoDB(ctx context.Context, cfg *config.Configuration) (store.MongoDB, error) { + mongodb, err := e.Init.DoGetMongoDB(ctx, cfg) if err != nil { log.Event(ctx, "failed to initialise mongo", log.ERROR, log.Error(err)) return nil, err } - log.Event(ctx, "listening to mongo db session", log.INFO, log.Data{"URI": mongodb.URI}) e.MongoDB = true return mongodb, nil } @@ -104,12 +104,12 @@ func (e *Init) DoGetKafkaProducer(ctx context.Context, cfg *config.Configuration } // DoGetGraphDB creates a new GraphDB -func (e *Init) DoGetGraphDB(ctx context.Context) (*graph.DB, error) { +func (e *Init) DoGetGraphDB(ctx context.Context) (store.GraphDB, error) { return graph.New(ctx, graph.Subsets{Observation: true, Instance: true}) } // DoGetMongoDB returns a MongoDB -func (e *Init) DoGetMongoDB(cfg *config.Configuration) (*mongo.Mongo, error) { +func (e *Init) DoGetMongoDB(ctx context.Context, cfg *config.Configuration) (store.MongoDB, error) { mongodb := &mongo.Mongo{ CodeListURL: cfg.CodeListAPIURL, Collection: cfg.MongoConfig.Collection, @@ -120,5 +120,6 @@ func (e *Init) DoGetMongoDB(cfg *config.Configuration) (*mongo.Mongo, error) { if err := mongodb.Init(); err != nil { return nil, err } + log.Event(ctx, "listening to mongo db session", log.INFO, log.Data{"URI": mongodb.URI}) return mongodb, nil } diff --git a/service/interfaces.go b/service/interfaces.go index 514bc2f6..2f083117 100644 --- a/service/interfaces.go +++ b/service/interfaces.go @@ -5,8 +5,7 @@ import ( "net/http" "github.com/ONSdigital/dp-dataset-api/config" - "github.com/ONSdigital/dp-dataset-api/mongo" - "github.com/ONSdigital/dp-graph/v2/graph" + "github.com/ONSdigital/dp-dataset-api/store" "github.com/ONSdigital/dp-healthcheck/healthcheck" kafka "github.com/ONSdigital/dp-kafka" ) @@ -20,8 +19,8 @@ type Initialiser interface { DoGetHTTPServer(bindAddr string, router http.Handler) HTTPServer DoGetHealthCheck(cfg *config.Configuration, buildTime, gitCommit, version string) (HealthChecker, error) DoGetKafkaProducer(ctx context.Context, cfg *config.Configuration) (kafka.IProducer, error) - DoGetGraphDB(ctx context.Context) (*graph.DB, error) - DoGetMongoDB(cfg *config.Configuration) (*mongo.Mongo, error) + DoGetGraphDB(ctx context.Context) (store.GraphDB, error) + DoGetMongoDB(ctx context.Context, cfg *config.Configuration) (store.MongoDB, error) } // HTTPServer defines the required methods from the HTTP server diff --git a/service/mock/healthcheck.go b/service/mock/healthcheck.go new file mode 100644 index 00000000..f91f78dd --- /dev/null +++ b/service/mock/healthcheck.go @@ -0,0 +1,214 @@ +// Code generated by moq; DO NOT EDIT. +// github.com/matryer/moq + +package mock + +import ( + "context" + "github.com/ONSdigital/dp-dataset-api/service" + "github.com/ONSdigital/dp-healthcheck/healthcheck" + "net/http" + "sync" +) + +var ( + lockHealthCheckerMockAddCheck sync.RWMutex + lockHealthCheckerMockHandler sync.RWMutex + lockHealthCheckerMockStart sync.RWMutex + lockHealthCheckerMockStop sync.RWMutex +) + +// Ensure, that HealthCheckerMock does implement service.HealthChecker. +// If this is not the case, regenerate this file with moq. +var _ service.HealthChecker = &HealthCheckerMock{} + +// HealthCheckerMock is a mock implementation of service.HealthChecker. +// +// func TestSomethingThatUsesHealthChecker(t *testing.T) { +// +// // make and configure a mocked service.HealthChecker +// mockedHealthChecker := &HealthCheckerMock{ +// AddCheckFunc: func(name string, checker healthcheck.Checker) error { +// panic("mock out the AddCheck method") +// }, +// HandlerFunc: func(w http.ResponseWriter, req *http.Request) { +// panic("mock out the Handler method") +// }, +// StartFunc: func(ctx context.Context) { +// panic("mock out the Start method") +// }, +// StopFunc: func() { +// panic("mock out the Stop method") +// }, +// } +// +// // use mockedHealthChecker in code that requires service.HealthChecker +// // and then make assertions. +// +// } +type HealthCheckerMock struct { + // AddCheckFunc mocks the AddCheck method. + AddCheckFunc func(name string, checker healthcheck.Checker) error + + // HandlerFunc mocks the Handler method. + HandlerFunc func(w http.ResponseWriter, req *http.Request) + + // StartFunc mocks the Start method. + StartFunc func(ctx context.Context) + + // StopFunc mocks the Stop method. + StopFunc func() + + // calls tracks calls to the methods. + calls struct { + // AddCheck holds details about calls to the AddCheck method. + AddCheck []struct { + // Name is the name argument value. + Name string + // Checker is the checker argument value. + Checker healthcheck.Checker + } + // Handler holds details about calls to the Handler method. + Handler []struct { + // W is the w argument value. + W http.ResponseWriter + // Req is the req argument value. + Req *http.Request + } + // Start holds details about calls to the Start method. + Start []struct { + // Ctx is the ctx argument value. + Ctx context.Context + } + // Stop holds details about calls to the Stop method. + Stop []struct { + } + } +} + +// AddCheck calls AddCheckFunc. +func (mock *HealthCheckerMock) AddCheck(name string, checker healthcheck.Checker) error { + if mock.AddCheckFunc == nil { + panic("HealthCheckerMock.AddCheckFunc: method is nil but HealthChecker.AddCheck was just called") + } + callInfo := struct { + Name string + Checker healthcheck.Checker + }{ + Name: name, + Checker: checker, + } + lockHealthCheckerMockAddCheck.Lock() + mock.calls.AddCheck = append(mock.calls.AddCheck, callInfo) + lockHealthCheckerMockAddCheck.Unlock() + return mock.AddCheckFunc(name, checker) +} + +// AddCheckCalls gets all the calls that were made to AddCheck. +// Check the length with: +// len(mockedHealthChecker.AddCheckCalls()) +func (mock *HealthCheckerMock) AddCheckCalls() []struct { + Name string + Checker healthcheck.Checker +} { + var calls []struct { + Name string + Checker healthcheck.Checker + } + lockHealthCheckerMockAddCheck.RLock() + calls = mock.calls.AddCheck + lockHealthCheckerMockAddCheck.RUnlock() + return calls +} + +// Handler calls HandlerFunc. +func (mock *HealthCheckerMock) Handler(w http.ResponseWriter, req *http.Request) { + if mock.HandlerFunc == nil { + panic("HealthCheckerMock.HandlerFunc: method is nil but HealthChecker.Handler was just called") + } + callInfo := struct { + W http.ResponseWriter + Req *http.Request + }{ + W: w, + Req: req, + } + lockHealthCheckerMockHandler.Lock() + mock.calls.Handler = append(mock.calls.Handler, callInfo) + lockHealthCheckerMockHandler.Unlock() + mock.HandlerFunc(w, req) +} + +// HandlerCalls gets all the calls that were made to Handler. +// Check the length with: +// len(mockedHealthChecker.HandlerCalls()) +func (mock *HealthCheckerMock) HandlerCalls() []struct { + W http.ResponseWriter + Req *http.Request +} { + var calls []struct { + W http.ResponseWriter + Req *http.Request + } + lockHealthCheckerMockHandler.RLock() + calls = mock.calls.Handler + lockHealthCheckerMockHandler.RUnlock() + return calls +} + +// Start calls StartFunc. +func (mock *HealthCheckerMock) Start(ctx context.Context) { + if mock.StartFunc == nil { + panic("HealthCheckerMock.StartFunc: method is nil but HealthChecker.Start was just called") + } + callInfo := struct { + Ctx context.Context + }{ + Ctx: ctx, + } + lockHealthCheckerMockStart.Lock() + mock.calls.Start = append(mock.calls.Start, callInfo) + lockHealthCheckerMockStart.Unlock() + mock.StartFunc(ctx) +} + +// StartCalls gets all the calls that were made to Start. +// Check the length with: +// len(mockedHealthChecker.StartCalls()) +func (mock *HealthCheckerMock) StartCalls() []struct { + Ctx context.Context +} { + var calls []struct { + Ctx context.Context + } + lockHealthCheckerMockStart.RLock() + calls = mock.calls.Start + lockHealthCheckerMockStart.RUnlock() + return calls +} + +// Stop calls StopFunc. +func (mock *HealthCheckerMock) Stop() { + if mock.StopFunc == nil { + panic("HealthCheckerMock.StopFunc: method is nil but HealthChecker.Stop was just called") + } + callInfo := struct { + }{} + lockHealthCheckerMockStop.Lock() + mock.calls.Stop = append(mock.calls.Stop, callInfo) + lockHealthCheckerMockStop.Unlock() + mock.StopFunc() +} + +// StopCalls gets all the calls that were made to Stop. +// Check the length with: +// len(mockedHealthChecker.StopCalls()) +func (mock *HealthCheckerMock) StopCalls() []struct { +} { + var calls []struct { + } + lockHealthCheckerMockStop.RLock() + calls = mock.calls.Stop + lockHealthCheckerMockStop.RUnlock() + return calls +} diff --git a/service/mock/initialiser.go b/service/mock/initialiser.go new file mode 100644 index 00000000..42396962 --- /dev/null +++ b/service/mock/initialiser.go @@ -0,0 +1,290 @@ +// Code generated by moq; DO NOT EDIT. +// github.com/matryer/moq + +package mock + +import ( + "context" + "github.com/ONSdigital/dp-dataset-api/config" + "github.com/ONSdigital/dp-dataset-api/service" + "github.com/ONSdigital/dp-dataset-api/store" + "github.com/ONSdigital/dp-kafka" + "net/http" + "sync" +) + +var ( + lockInitialiserMockDoGetGraphDB sync.RWMutex + lockInitialiserMockDoGetHTTPServer sync.RWMutex + lockInitialiserMockDoGetHealthCheck sync.RWMutex + lockInitialiserMockDoGetKafkaProducer sync.RWMutex + lockInitialiserMockDoGetMongoDB sync.RWMutex +) + +// Ensure, that InitialiserMock does implement service.Initialiser. +// If this is not the case, regenerate this file with moq. +var _ service.Initialiser = &InitialiserMock{} + +// InitialiserMock is a mock implementation of service.Initialiser. +// +// func TestSomethingThatUsesInitialiser(t *testing.T) { +// +// // make and configure a mocked service.Initialiser +// mockedInitialiser := &InitialiserMock{ +// DoGetGraphDBFunc: func(ctx context.Context) (store.GraphDB, error) { +// panic("mock out the DoGetGraphDB method") +// }, +// DoGetHTTPServerFunc: func(bindAddr string, router http.Handler) service.HTTPServer { +// panic("mock out the DoGetHTTPServer method") +// }, +// DoGetHealthCheckFunc: func(cfg *config.Configuration, buildTime string, gitCommit string, version string) (service.HealthChecker, error) { +// panic("mock out the DoGetHealthCheck method") +// }, +// DoGetKafkaProducerFunc: func(ctx context.Context, cfg *config.Configuration) (kafka.IProducer, error) { +// panic("mock out the DoGetKafkaProducer method") +// }, +// DoGetMongoDBFunc: func(ctx context.Context, cfg *config.Configuration) (store.MongoDB, error) { +// panic("mock out the DoGetMongoDB method") +// }, +// } +// +// // use mockedInitialiser in code that requires service.Initialiser +// // and then make assertions. +// +// } +type InitialiserMock struct { + // DoGetGraphDBFunc mocks the DoGetGraphDB method. + DoGetGraphDBFunc func(ctx context.Context) (store.GraphDB, error) + + // DoGetHTTPServerFunc mocks the DoGetHTTPServer method. + DoGetHTTPServerFunc func(bindAddr string, router http.Handler) service.HTTPServer + + // DoGetHealthCheckFunc mocks the DoGetHealthCheck method. + DoGetHealthCheckFunc func(cfg *config.Configuration, buildTime string, gitCommit string, version string) (service.HealthChecker, error) + + // DoGetKafkaProducerFunc mocks the DoGetKafkaProducer method. + DoGetKafkaProducerFunc func(ctx context.Context, cfg *config.Configuration) (kafka.IProducer, error) + + // DoGetMongoDBFunc mocks the DoGetMongoDB method. + DoGetMongoDBFunc func(ctx context.Context, cfg *config.Configuration) (store.MongoDB, error) + + // calls tracks calls to the methods. + calls struct { + // DoGetGraphDB holds details about calls to the DoGetGraphDB method. + DoGetGraphDB []struct { + // Ctx is the ctx argument value. + Ctx context.Context + } + // DoGetHTTPServer holds details about calls to the DoGetHTTPServer method. + DoGetHTTPServer []struct { + // BindAddr is the bindAddr argument value. + BindAddr string + // Router is the router argument value. + Router http.Handler + } + // DoGetHealthCheck holds details about calls to the DoGetHealthCheck method. + DoGetHealthCheck []struct { + // Cfg is the cfg argument value. + Cfg *config.Configuration + // BuildTime is the buildTime argument value. + BuildTime string + // GitCommit is the gitCommit argument value. + GitCommit string + // Version is the version argument value. + Version string + } + // DoGetKafkaProducer holds details about calls to the DoGetKafkaProducer method. + DoGetKafkaProducer []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // Cfg is the cfg argument value. + Cfg *config.Configuration + } + // DoGetMongoDB holds details about calls to the DoGetMongoDB method. + DoGetMongoDB []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // Cfg is the cfg argument value. + Cfg *config.Configuration + } + } +} + +// DoGetGraphDB calls DoGetGraphDBFunc. +func (mock *InitialiserMock) DoGetGraphDB(ctx context.Context) (store.GraphDB, error) { + if mock.DoGetGraphDBFunc == nil { + panic("InitialiserMock.DoGetGraphDBFunc: method is nil but Initialiser.DoGetGraphDB was just called") + } + callInfo := struct { + Ctx context.Context + }{ + Ctx: ctx, + } + lockInitialiserMockDoGetGraphDB.Lock() + mock.calls.DoGetGraphDB = append(mock.calls.DoGetGraphDB, callInfo) + lockInitialiserMockDoGetGraphDB.Unlock() + return mock.DoGetGraphDBFunc(ctx) +} + +// DoGetGraphDBCalls gets all the calls that were made to DoGetGraphDB. +// Check the length with: +// len(mockedInitialiser.DoGetGraphDBCalls()) +func (mock *InitialiserMock) DoGetGraphDBCalls() []struct { + Ctx context.Context +} { + var calls []struct { + Ctx context.Context + } + lockInitialiserMockDoGetGraphDB.RLock() + calls = mock.calls.DoGetGraphDB + lockInitialiserMockDoGetGraphDB.RUnlock() + return calls +} + +// DoGetHTTPServer calls DoGetHTTPServerFunc. +func (mock *InitialiserMock) DoGetHTTPServer(bindAddr string, router http.Handler) service.HTTPServer { + if mock.DoGetHTTPServerFunc == nil { + panic("InitialiserMock.DoGetHTTPServerFunc: method is nil but Initialiser.DoGetHTTPServer was just called") + } + callInfo := struct { + BindAddr string + Router http.Handler + }{ + BindAddr: bindAddr, + Router: router, + } + lockInitialiserMockDoGetHTTPServer.Lock() + mock.calls.DoGetHTTPServer = append(mock.calls.DoGetHTTPServer, callInfo) + lockInitialiserMockDoGetHTTPServer.Unlock() + return mock.DoGetHTTPServerFunc(bindAddr, router) +} + +// DoGetHTTPServerCalls gets all the calls that were made to DoGetHTTPServer. +// Check the length with: +// len(mockedInitialiser.DoGetHTTPServerCalls()) +func (mock *InitialiserMock) DoGetHTTPServerCalls() []struct { + BindAddr string + Router http.Handler +} { + var calls []struct { + BindAddr string + Router http.Handler + } + lockInitialiserMockDoGetHTTPServer.RLock() + calls = mock.calls.DoGetHTTPServer + lockInitialiserMockDoGetHTTPServer.RUnlock() + return calls +} + +// DoGetHealthCheck calls DoGetHealthCheckFunc. +func (mock *InitialiserMock) DoGetHealthCheck(cfg *config.Configuration, buildTime string, gitCommit string, version string) (service.HealthChecker, error) { + if mock.DoGetHealthCheckFunc == nil { + panic("InitialiserMock.DoGetHealthCheckFunc: method is nil but Initialiser.DoGetHealthCheck was just called") + } + callInfo := struct { + Cfg *config.Configuration + BuildTime string + GitCommit string + Version string + }{ + Cfg: cfg, + BuildTime: buildTime, + GitCommit: gitCommit, + Version: version, + } + lockInitialiserMockDoGetHealthCheck.Lock() + mock.calls.DoGetHealthCheck = append(mock.calls.DoGetHealthCheck, callInfo) + lockInitialiserMockDoGetHealthCheck.Unlock() + return mock.DoGetHealthCheckFunc(cfg, buildTime, gitCommit, version) +} + +// DoGetHealthCheckCalls gets all the calls that were made to DoGetHealthCheck. +// Check the length with: +// len(mockedInitialiser.DoGetHealthCheckCalls()) +func (mock *InitialiserMock) DoGetHealthCheckCalls() []struct { + Cfg *config.Configuration + BuildTime string + GitCommit string + Version string +} { + var calls []struct { + Cfg *config.Configuration + BuildTime string + GitCommit string + Version string + } + lockInitialiserMockDoGetHealthCheck.RLock() + calls = mock.calls.DoGetHealthCheck + lockInitialiserMockDoGetHealthCheck.RUnlock() + return calls +} + +// DoGetKafkaProducer calls DoGetKafkaProducerFunc. +func (mock *InitialiserMock) DoGetKafkaProducer(ctx context.Context, cfg *config.Configuration) (kafka.IProducer, error) { + if mock.DoGetKafkaProducerFunc == nil { + panic("InitialiserMock.DoGetKafkaProducerFunc: method is nil but Initialiser.DoGetKafkaProducer was just called") + } + callInfo := struct { + Ctx context.Context + Cfg *config.Configuration + }{ + Ctx: ctx, + Cfg: cfg, + } + lockInitialiserMockDoGetKafkaProducer.Lock() + mock.calls.DoGetKafkaProducer = append(mock.calls.DoGetKafkaProducer, callInfo) + lockInitialiserMockDoGetKafkaProducer.Unlock() + return mock.DoGetKafkaProducerFunc(ctx, cfg) +} + +// DoGetKafkaProducerCalls gets all the calls that were made to DoGetKafkaProducer. +// Check the length with: +// len(mockedInitialiser.DoGetKafkaProducerCalls()) +func (mock *InitialiserMock) DoGetKafkaProducerCalls() []struct { + Ctx context.Context + Cfg *config.Configuration +} { + var calls []struct { + Ctx context.Context + Cfg *config.Configuration + } + lockInitialiserMockDoGetKafkaProducer.RLock() + calls = mock.calls.DoGetKafkaProducer + lockInitialiserMockDoGetKafkaProducer.RUnlock() + return calls +} + +// DoGetMongoDB calls DoGetMongoDBFunc. +func (mock *InitialiserMock) DoGetMongoDB(ctx context.Context, cfg *config.Configuration) (store.MongoDB, error) { + if mock.DoGetMongoDBFunc == nil { + panic("InitialiserMock.DoGetMongoDBFunc: method is nil but Initialiser.DoGetMongoDB was just called") + } + callInfo := struct { + Ctx context.Context + Cfg *config.Configuration + }{ + Ctx: ctx, + Cfg: cfg, + } + lockInitialiserMockDoGetMongoDB.Lock() + mock.calls.DoGetMongoDB = append(mock.calls.DoGetMongoDB, callInfo) + lockInitialiserMockDoGetMongoDB.Unlock() + return mock.DoGetMongoDBFunc(ctx, cfg) +} + +// DoGetMongoDBCalls gets all the calls that were made to DoGetMongoDB. +// Check the length with: +// len(mockedInitialiser.DoGetMongoDBCalls()) +func (mock *InitialiserMock) DoGetMongoDBCalls() []struct { + Ctx context.Context + Cfg *config.Configuration +} { + var calls []struct { + Ctx context.Context + Cfg *config.Configuration + } + lockInitialiserMockDoGetMongoDB.RLock() + calls = mock.calls.DoGetMongoDB + lockInitialiserMockDoGetMongoDB.RUnlock() + return calls +} diff --git a/service/mock/server.go b/service/mock/server.go new file mode 100644 index 00000000..5b0d31e2 --- /dev/null +++ b/service/mock/server.go @@ -0,0 +1,114 @@ +// Code generated by moq; DO NOT EDIT. +// github.com/matryer/moq + +package mock + +import ( + "context" + "github.com/ONSdigital/dp-dataset-api/service" + "sync" +) + +var ( + lockHTTPServerMockListenAndServe sync.RWMutex + lockHTTPServerMockShutdown sync.RWMutex +) + +// Ensure, that HTTPServerMock does implement service.HTTPServer. +// If this is not the case, regenerate this file with moq. +var _ service.HTTPServer = &HTTPServerMock{} + +// HTTPServerMock is a mock implementation of service.HTTPServer. +// +// func TestSomethingThatUsesHTTPServer(t *testing.T) { +// +// // make and configure a mocked service.HTTPServer +// mockedHTTPServer := &HTTPServerMock{ +// ListenAndServeFunc: func() error { +// panic("mock out the ListenAndServe method") +// }, +// ShutdownFunc: func(ctx context.Context) error { +// panic("mock out the Shutdown method") +// }, +// } +// +// // use mockedHTTPServer in code that requires service.HTTPServer +// // and then make assertions. +// +// } +type HTTPServerMock struct { + // ListenAndServeFunc mocks the ListenAndServe method. + ListenAndServeFunc func() error + + // ShutdownFunc mocks the Shutdown method. + ShutdownFunc func(ctx context.Context) error + + // calls tracks calls to the methods. + calls struct { + // ListenAndServe holds details about calls to the ListenAndServe method. + ListenAndServe []struct { + } + // Shutdown holds details about calls to the Shutdown method. + Shutdown []struct { + // Ctx is the ctx argument value. + Ctx context.Context + } + } +} + +// ListenAndServe calls ListenAndServeFunc. +func (mock *HTTPServerMock) ListenAndServe() error { + if mock.ListenAndServeFunc == nil { + panic("HTTPServerMock.ListenAndServeFunc: method is nil but HTTPServer.ListenAndServe was just called") + } + callInfo := struct { + }{} + lockHTTPServerMockListenAndServe.Lock() + mock.calls.ListenAndServe = append(mock.calls.ListenAndServe, callInfo) + lockHTTPServerMockListenAndServe.Unlock() + return mock.ListenAndServeFunc() +} + +// ListenAndServeCalls gets all the calls that were made to ListenAndServe. +// Check the length with: +// len(mockedHTTPServer.ListenAndServeCalls()) +func (mock *HTTPServerMock) ListenAndServeCalls() []struct { +} { + var calls []struct { + } + lockHTTPServerMockListenAndServe.RLock() + calls = mock.calls.ListenAndServe + lockHTTPServerMockListenAndServe.RUnlock() + return calls +} + +// Shutdown calls ShutdownFunc. +func (mock *HTTPServerMock) Shutdown(ctx context.Context) error { + if mock.ShutdownFunc == nil { + panic("HTTPServerMock.ShutdownFunc: method is nil but HTTPServer.Shutdown was just called") + } + callInfo := struct { + Ctx context.Context + }{ + Ctx: ctx, + } + lockHTTPServerMockShutdown.Lock() + mock.calls.Shutdown = append(mock.calls.Shutdown, callInfo) + lockHTTPServerMockShutdown.Unlock() + return mock.ShutdownFunc(ctx) +} + +// ShutdownCalls gets all the calls that were made to Shutdown. +// Check the length with: +// len(mockedHTTPServer.ShutdownCalls()) +func (mock *HTTPServerMock) ShutdownCalls() []struct { + Ctx context.Context +} { + var calls []struct { + Ctx context.Context + } + lockHTTPServerMockShutdown.RLock() + calls = mock.calls.Shutdown + lockHTTPServerMockShutdown.RUnlock() + return calls +} diff --git a/service/service.go b/service/service.go index 5bc9f179..d6907a83 100644 --- a/service/service.go +++ b/service/service.go @@ -10,13 +10,10 @@ import ( "github.com/ONSdigital/dp-dataset-api/config" "github.com/ONSdigital/dp-dataset-api/download" adapter "github.com/ONSdigital/dp-dataset-api/kafka" - "github.com/ONSdigital/dp-dataset-api/mongo" "github.com/ONSdigital/dp-dataset-api/schema" "github.com/ONSdigital/dp-dataset-api/store" "github.com/ONSdigital/dp-dataset-api/url" - "github.com/ONSdigital/dp-graph/v2/graph" kafka "github.com/ONSdigital/dp-kafka" - mongolib "github.com/ONSdigital/dp-mongodb" dphandlers "github.com/ONSdigital/dp-net/handlers" dphttp "github.com/ONSdigital/dp-net/http" "github.com/ONSdigital/log.go/log" @@ -30,20 +27,20 @@ var _ store.Storer = (*DatsetAPIStore)(nil) //DatsetAPIStore is a wrapper which embeds Neo4j Mongo structs which between them satisfy the store.Storer interface. type DatsetAPIStore struct { - *mongo.Mongo - *graph.DB + store.MongoDB + store.GraphDB } // Service contains all the configs, server and clients to run the Dataset API type Service struct { Config *config.Configuration ServiceList *ExternalServiceList - graphDB *graph.DB - generateDownloadsProducer kafka.IProducer + GraphDB store.GraphDB + MongoDB store.MongoDB + GenerateDownloadsProducer kafka.IProducer identityClient *clientsidentity.Client Server HTTPServer HealthCheck HealthChecker - mongoDB *mongo.Mongo API *api.DatasetAPI } @@ -56,7 +53,7 @@ func Run(ctx context.Context, cfg *config.Configuration, serviceList *ExternalSe } // Get MongoDB connection - svc.mongoDB, err = serviceList.GetMongoDB(ctx, cfg) + svc.MongoDB, err = serviceList.GetMongoDB(ctx, cfg) if err != nil { log.Event(ctx, "could not obtain mongo session", log.ERROR, log.Error(err)) return nil, err @@ -69,23 +66,23 @@ func Run(ctx context.Context, cfg *config.Configuration, serviceList *ExternalSe "EnablePrivateEndpoints": cfg.EnablePrivateEndpoints, }) } else { - svc.graphDB, err = serviceList.GetGraphDB(ctx) + svc.GraphDB, err = serviceList.GetGraphDB(ctx) if err != nil { log.Event(ctx, "failed to initialise graph driver", log.FATAL, log.Error(err)) return nil, err } } - store := store.DataStore{Backend: DatsetAPIStore{svc.mongoDB, svc.graphDB}} + store := store.DataStore{Backend: DatsetAPIStore{svc.MongoDB, svc.GraphDB}} // Get GenerateDownloads Kafka Producer - svc.generateDownloadsProducer, err = serviceList.GetProducer(ctx, cfg) + svc.GenerateDownloadsProducer, err = serviceList.GetProducer(ctx, cfg) if err != nil { log.Event(ctx, "could not obtain generate downloads producer", log.FATAL, log.Error(err)) return nil, err } downloadGenerator := &download.Generator{ - Producer: adapter.NewProducerAdapter(svc.generateDownloadsProducer), + Producer: adapter.NewProducerAdapter(svc.GenerateDownloadsProducer), Marshaller: schema.GenerateDownloadsEvent, } @@ -206,14 +203,14 @@ func (svc *Service) Close(ctx context.Context) error { } // stop any incoming requests - if err := svc.Server.Shutdown(ctx); err != nil { - log.Event(ctx, "failed to shutdown http server", log.Error(err), log.ERROR) + if err := svc.Server.Shutdown(shutdownContext); err != nil { + log.Event(shutdownContext, "failed to shutdown http server", log.Error(err), log.ERROR) hasShutdownError = true } // Close MongoDB (if it exists) if svc.ServiceList.MongoDB { - if err := mongolib.Close(ctx, svc.mongoDB.Session); err != nil { + if err := svc.MongoDB.Close(shutdownContext); err != nil { log.Event(shutdownContext, "failed to close mongo db session", log.ERROR, log.Error(err)) hasShutdownError = true } @@ -222,14 +219,14 @@ func (svc *Service) Close(ctx context.Context) error { // Close GenerateDownloadsProducer (if it exists) if svc.ServiceList.GenerateDownloadsProducer { log.Event(shutdownContext, "closing generated downloads kafka producer", log.INFO, log.Data{"producer": "DimensionExtracted"}) - svc.generateDownloadsProducer.Close(shutdownContext) + svc.GenerateDownloadsProducer.Close(shutdownContext) log.Event(shutdownContext, "closed generated downloads kafka producer", log.INFO, log.Data{"producer": "DimensionExtracted"}) } // Close GraphDB (if it exists) if svc.ServiceList.Graph { - if err := svc.graphDB.Close(ctx); err != nil { - log.Event(ctx, "failed to close graph db", log.ERROR, log.Error(err)) + if err := svc.GraphDB.Close(shutdownContext); err != nil { + log.Event(shutdownContext, "failed to close graph db", log.ERROR, log.Error(err)) hasShutdownError = true } } @@ -239,9 +236,9 @@ func (svc *Service) Close(ctx context.Context) error { <-shutdownContext.Done() // timeout expired - if ctx.Err() == context.DeadlineExceeded { - log.Event(ctx, "shutdown timed out", log.ERROR, log.Error(ctx.Err())) - return ctx.Err() + if shutdownContext.Err() == context.DeadlineExceeded { + log.Event(shutdownContext, "shutdown timed out", log.ERROR, log.Error(shutdownContext.Err())) + return shutdownContext.Err() } // other error @@ -266,19 +263,19 @@ func (svc *Service) registerCheckers(ctx context.Context) (err error) { } } - if err = svc.HealthCheck.AddCheck("Kafka Generate Downloads Producer", svc.generateDownloadsProducer.Checker); err != nil { + if err = svc.HealthCheck.AddCheck("Kafka Generate Downloads Producer", svc.GenerateDownloadsProducer.Checker); err != nil { hasErrors = true log.Event(ctx, "error adding check for kafka downloads producer", log.ERROR, log.Error(err)) } - if err = svc.HealthCheck.AddCheck("Mongo DB", svc.mongoDB.Checker); err != nil { + if err = svc.HealthCheck.AddCheck("Mongo DB", svc.MongoDB.Checker); err != nil { hasErrors = true log.Event(ctx, "error adding check for mongo db", log.ERROR, log.Error(err)) } if svc.Config.EnablePrivateEndpoints || svc.Config.EnableObservationEndpoint { log.Event(ctx, "adding graph db health check as the private or observation endpoints are enabled", log.INFO) - if err = svc.HealthCheck.AddCheck("Graph DB", svc.graphDB.Driver.Checker); err != nil { + if err = svc.HealthCheck.AddCheck("Graph DB", svc.GraphDB.Checker); err != nil { hasErrors = true log.Event(ctx, "error adding check for graph db", log.ERROR, log.Error(err)) } diff --git a/service/service_test.go b/service/service_test.go new file mode 100644 index 00000000..df342dc1 --- /dev/null +++ b/service/service_test.go @@ -0,0 +1,436 @@ +package service_test + +import ( + "context" + "fmt" + "net/http" + "sync" + "testing" + + "github.com/ONSdigital/dp-dataset-api/config" + "github.com/ONSdigital/dp-dataset-api/service" + "github.com/ONSdigital/dp-dataset-api/service/mock" + serviceMock "github.com/ONSdigital/dp-dataset-api/service/mock" + "github.com/ONSdigital/dp-dataset-api/store" + storeMock "github.com/ONSdigital/dp-dataset-api/store/datastoretest" + "github.com/ONSdigital/dp-healthcheck/healthcheck" + kafka "github.com/ONSdigital/dp-kafka" + "github.com/ONSdigital/dp-kafka/kafkatest" + "github.com/pkg/errors" + . "github.com/smartystreets/goconvey/convey" +) + +var ( + ctx = context.Background() + testBuildTime = "BuildTime" + testGitCommit = "GitCommit" + testVersion = "Version" +) + +var ( + errMongo = errors.New("MongoDB error") + errGraph = errors.New("GraphDB error") + errKafka = errors.New("Kafka producer error") + errServer = errors.New("HTTP Server error") + errHealthcheck = errors.New("healthCheck error") +) + +var funcDoGetHealthcheckErr = func(cfg *config.Configuration, buildTime string, gitCommit string, version string) (service.HealthChecker, error) { + return nil, errHealthcheck +} + +var funcDoGetHTTPServerNil = func(bindAddr string, router http.Handler) service.HTTPServer { + return nil +} + +var funcDoGetMongoDBErr = func(ctx context.Context, cfg *config.Configuration) (store.MongoDB, error) { + return nil, errMongo +} + +var funcDoGetGraphDBErr = func(ctx context.Context) (store.GraphDB, error) { + return nil, errGraph +} + +var funcDoGetKafkaProducerErr = func(ctx context.Context, cfg *config.Configuration) (kafka.IProducer, error) { + return nil, errKafka +} + +func TestRun(t *testing.T) { + + Convey("Having a set of mocked dependencies", t, func() { + + cfg, err := config.Get() + cfg.EnablePrivateEndpoints = true + So(err, ShouldBeNil) + + hcMock := &mock.HealthCheckerMock{ + AddCheckFunc: func(name string, checker healthcheck.Checker) error { return nil }, + StartFunc: func(ctx context.Context) {}, + } + + serverWg := &sync.WaitGroup{} + serverMock := &mock.HTTPServerMock{ + ListenAndServeFunc: func() error { + serverWg.Done() + return nil + }, + } + + failingServerMock := &serviceMock.HTTPServerMock{ + ListenAndServeFunc: func() error { + serverWg.Done() + return errServer + }, + } + + funcDoGetHealthcheckOk := func(cfg *config.Configuration, buildTime string, gitCommit string, version string) (service.HealthChecker, error) { + return hcMock, nil + } + + funcDoGetHTTPServer := func(bindAddr string, router http.Handler) service.HTTPServer { + return serverMock + } + + funcDoGetFailingHTTPSerer := func(bindAddr string, router http.Handler) service.HTTPServer { + return failingServerMock + } + + funcDoGetMongoDBOk := func(ctx context.Context, cfg *config.Configuration) (store.MongoDB, error) { + return &storeMock.MongoDBMock{}, nil + } + + funcDoGetGraphDBOk := func(ctx context.Context) (store.GraphDB, error) { + return &storeMock.GraphDBMock{}, nil + } + + funcDoGetKafkaProducerOk := func(ctx context.Context, cfg *config.Configuration) (kafka.IProducer, error) { + return &kafkatest.IProducerMock{}, nil + } + + Convey("Given that initialising MongoDB returns an error", func() { + initMock := &serviceMock.InitialiserMock{ + DoGetMongoDBFunc: funcDoGetMongoDBErr, + } + svcErrors := make(chan error, 1) + svcList := service.NewServiceList(initMock) + _, err := service.Run(ctx, cfg, svcList, testBuildTime, testGitCommit, testVersion, svcErrors) + + Convey("Then service Run fails with the same error and the flag is not set. No further initialisations are attempted", func() { + So(err, ShouldResemble, errMongo) + So(svcList.MongoDB, ShouldBeFalse) + So(svcList.Graph, ShouldBeFalse) + So(svcList.GenerateDownloadsProducer, ShouldBeFalse) + So(svcList.HealthCheck, ShouldBeFalse) + }) + }) + + Convey("Given that initialising GraphDB returns an error", func() { + initMock := &mock.InitialiserMock{ + DoGetMongoDBFunc: funcDoGetMongoDBOk, + DoGetGraphDBFunc: funcDoGetGraphDBErr, + } + svcErrors := make(chan error, 1) + svcList := service.NewServiceList(initMock) + _, err := service.Run(ctx, cfg, svcList, testBuildTime, testGitCommit, testVersion, svcErrors) + + Convey("Then service Run fails with the same error and the flag is not set. No further initialisations are attempted", func() { + So(err, ShouldResemble, errGraph) + So(svcList.MongoDB, ShouldBeTrue) + So(svcList.Graph, ShouldBeFalse) + So(svcList.GenerateDownloadsProducer, ShouldBeFalse) + So(svcList.HealthCheck, ShouldBeFalse) + }) + }) + + Convey("Given that initialising Kafka producer returns an error", func() { + initMock := &mock.InitialiserMock{ + DoGetMongoDBFunc: funcDoGetMongoDBOk, + DoGetGraphDBFunc: funcDoGetGraphDBOk, + DoGetKafkaProducerFunc: funcDoGetKafkaProducerErr, + } + svcErrors := make(chan error, 1) + svcList := service.NewServiceList(initMock) + _, err := service.Run(ctx, cfg, svcList, testBuildTime, testGitCommit, testVersion, svcErrors) + + Convey("Then service Run fails with the same error and the flag is not set. No further initialisations are attempted", func() { + So(err, ShouldResemble, errKafka) + So(svcList.MongoDB, ShouldBeTrue) + So(svcList.Graph, ShouldBeTrue) + So(svcList.GenerateDownloadsProducer, ShouldBeFalse) + So(svcList.HealthCheck, ShouldBeFalse) + }) + }) + + Convey("Given that initialising Helthcheck returns an error", func() { + initMock := &serviceMock.InitialiserMock{ + DoGetMongoDBFunc: funcDoGetMongoDBOk, + DoGetGraphDBFunc: funcDoGetGraphDBOk, + DoGetKafkaProducerFunc: funcDoGetKafkaProducerOk, + DoGetHealthCheckFunc: funcDoGetHealthcheckErr, + } + svcErrors := make(chan error, 1) + svcList := service.NewServiceList(initMock) + _, err := service.Run(ctx, cfg, svcList, testBuildTime, testGitCommit, testVersion, svcErrors) + + Convey("Then service Run fails with the same error and the flag is not set. No further initialisations are attempted", func() { + So(err, ShouldResemble, errHealthcheck) + So(svcList.MongoDB, ShouldBeTrue) + So(svcList.Graph, ShouldBeTrue) + So(svcList.GenerateDownloadsProducer, ShouldBeTrue) + So(svcList.HealthCheck, ShouldBeFalse) + }) + }) + + Convey("Given that Checkers cannot be registered", func() { + + errAddheckFail := errors.New("Error(s) registering checkers for healthcheck") + hcMockAddFail := &serviceMock.HealthCheckerMock{ + AddCheckFunc: func(name string, checker healthcheck.Checker) error { return errAddheckFail }, + StartFunc: func(ctx context.Context) {}, + } + + initMock := &serviceMock.InitialiserMock{ + DoGetMongoDBFunc: funcDoGetMongoDBOk, + DoGetGraphDBFunc: funcDoGetGraphDBOk, + DoGetKafkaProducerFunc: funcDoGetKafkaProducerOk, + DoGetHealthCheckFunc: func(cfg *config.Configuration, buildTime string, gitCommit string, version string) (service.HealthChecker, error) { + return hcMockAddFail, nil + }, + } + svcErrors := make(chan error, 1) + svcList := service.NewServiceList(initMock) + _, err := service.Run(ctx, cfg, svcList, testBuildTime, testGitCommit, testVersion, svcErrors) + + Convey("Then service Run fails, but all checks try to register", func() { + So(err, ShouldNotBeNil) + So(err.Error(), ShouldResemble, fmt.Sprintf("unable to register checkers: %s", errAddheckFail.Error())) + So(svcList.MongoDB, ShouldBeTrue) + So(svcList.Graph, ShouldBeTrue) + So(svcList.GenerateDownloadsProducer, ShouldBeTrue) + So(svcList.HealthCheck, ShouldBeTrue) + So(len(hcMockAddFail.AddCheckCalls()), ShouldEqual, 4) + So(hcMockAddFail.AddCheckCalls()[0].Name, ShouldResemble, "Zebedee") + So(hcMockAddFail.AddCheckCalls()[1].Name, ShouldResemble, "Kafka Generate Downloads Producer") + So(hcMockAddFail.AddCheckCalls()[2].Name, ShouldResemble, "Mongo DB") + So(hcMockAddFail.AddCheckCalls()[3].Name, ShouldResemble, "Graph DB") + }) + }) + + Convey("Given that all dependencies are successfully initialised", func() { + initMock := &serviceMock.InitialiserMock{ + DoGetMongoDBFunc: funcDoGetMongoDBOk, + DoGetGraphDBFunc: funcDoGetGraphDBOk, + DoGetKafkaProducerFunc: funcDoGetKafkaProducerOk, + DoGetHealthCheckFunc: funcDoGetHealthcheckOk, + DoGetHTTPServerFunc: funcDoGetHTTPServer, + } + svcErrors := make(chan error, 1) + svcList := service.NewServiceList(initMock) + serverWg.Add(1) + _, err := service.Run(ctx, cfg, svcList, testBuildTime, testGitCommit, testVersion, svcErrors) + + Convey("Then service Run succeeds and all the flags are set", func() { + So(err, ShouldBeNil) + So(svcList.MongoDB, ShouldBeTrue) + So(svcList.Graph, ShouldBeTrue) + So(svcList.GenerateDownloadsProducer, ShouldBeTrue) + So(svcList.HealthCheck, ShouldBeTrue) + }) + + Convey("The checkers are registered and the healthcheck and http server started", func() { + So(len(hcMock.AddCheckCalls()), ShouldEqual, 4) + So(hcMock.AddCheckCalls()[0].Name, ShouldResemble, "Zebedee") + So(hcMock.AddCheckCalls()[1].Name, ShouldResemble, "Kafka Generate Downloads Producer") + So(hcMock.AddCheckCalls()[2].Name, ShouldResemble, "Mongo DB") + So(hcMock.AddCheckCalls()[3].Name, ShouldResemble, "Graph DB") + So(len(initMock.DoGetHTTPServerCalls()), ShouldEqual, 1) + So(initMock.DoGetHTTPServerCalls()[0].BindAddr, ShouldEqual, ":22000") + So(len(hcMock.StartCalls()), ShouldEqual, 1) + serverWg.Wait() // Wait for HTTP server go-routine to finish + So(len(serverMock.ListenAndServeCalls()), ShouldEqual, 1) + }) + }) + + Convey("Given that all dependencies are successfully initialised, observation and private endpoints are disabled", func() { + cfg.EnableObservationEndpoint = false + cfg.EnablePrivateEndpoints = false + initMock := &serviceMock.InitialiserMock{ + DoGetMongoDBFunc: funcDoGetMongoDBOk, + DoGetKafkaProducerFunc: funcDoGetKafkaProducerOk, + DoGetHealthCheckFunc: funcDoGetHealthcheckOk, + DoGetHTTPServerFunc: funcDoGetHTTPServer, + } + svcErrors := make(chan error, 1) + svcList := service.NewServiceList(initMock) + serverWg.Add(1) + _, err := service.Run(ctx, cfg, svcList, testBuildTime, testGitCommit, testVersion, svcErrors) + + Convey("Then service Run succeeds and all the flags except Graph are set", func() { + So(err, ShouldBeNil) + So(svcList.MongoDB, ShouldBeTrue) + So(svcList.Graph, ShouldBeFalse) + So(svcList.GenerateDownloadsProducer, ShouldBeTrue) + So(svcList.HealthCheck, ShouldBeTrue) + }) + + Convey("Only the checkers for Kafka and MongoDB are registered, and the healthcheck and http server started", func() { + So(len(hcMock.AddCheckCalls()), ShouldEqual, 2) + So(hcMock.AddCheckCalls()[0].Name, ShouldResemble, "Kafka Generate Downloads Producer") + So(hcMock.AddCheckCalls()[1].Name, ShouldResemble, "Mongo DB") + So(len(initMock.DoGetHTTPServerCalls()), ShouldEqual, 1) + So(initMock.DoGetHTTPServerCalls()[0].BindAddr, ShouldEqual, ":22000") + So(len(hcMock.StartCalls()), ShouldEqual, 1) + serverWg.Wait() // Wait for HTTP server go-routine to finish + So(len(serverMock.ListenAndServeCalls()), ShouldEqual, 1) + }) + }) + + Convey("Given that all dependencies are successfully initialised but the http server fails", func() { + + initMock := &serviceMock.InitialiserMock{ + DoGetMongoDBFunc: funcDoGetMongoDBOk, + DoGetGraphDBFunc: funcDoGetGraphDBOk, + DoGetKafkaProducerFunc: funcDoGetKafkaProducerOk, + DoGetHealthCheckFunc: funcDoGetHealthcheckOk, + DoGetHTTPServerFunc: funcDoGetFailingHTTPSerer, + } + svcErrors := make(chan error, 1) + svcList := service.NewServiceList(initMock) + serverWg.Add(1) + _, err := service.Run(ctx, cfg, svcList, testBuildTime, testGitCommit, testVersion, svcErrors) + So(err, ShouldBeNil) + + Convey("Then the error is returned in the error channel", func() { + sErr := <-svcErrors + So(sErr.Error(), ShouldResemble, fmt.Sprintf("failure in http listen and serve: %s", errServer.Error())) + So(len(failingServerMock.ListenAndServeCalls()), ShouldEqual, 1) + }) + }) + }) +} + +func TestClose(t *testing.T) { + + Convey("Having a correctly initialised service", t, func(c C) { + + cfg, err := config.Get() + So(err, ShouldBeNil) + + hcStopped := false + serverStopped := false + + // healthcheck Stop does not depend on any other service being closed/stopped + hcMock := &serviceMock.HealthCheckerMock{ + AddCheckFunc: func(name string, checker healthcheck.Checker) error { return nil }, + StartFunc: func(ctx context.Context) {}, + StopFunc: func() { hcStopped = true }, + } + + // server Shutdown will fail if healthcheck is not stopped + serverMock := &serviceMock.HTTPServerMock{ + ListenAndServeFunc: func() error { return nil }, + ShutdownFunc: func(ctx context.Context) error { + if !hcStopped { + return errors.New("Server was stopped before healthcheck") + } + serverStopped = true + return nil + }, + } + + funcClose := func(ctx context.Context) error { + if !hcStopped { + return errors.New("Dependency was closed before healthcheck") + } + if !serverStopped { + return errors.New("Dependency was closed before http server") + } + return nil + } + + // mongoDB will fail if healthcheck or http server are not stopped + mongoMock := &storeMock.MongoDBMock{ + CloseFunc: funcClose, + } + + // graphDB will fail if healthcheck or http server are not stopped + graphMock := &storeMock.GraphDBMock{ + CloseFunc: funcClose, + } + + // Kafka producer will fail if healthcheck or http server are not stopped + kafkaProducerMock := &kafkatest.IProducerMock{ + CloseFunc: funcClose, + } + + Convey("Closing a service does not close uninitialised dependencies", func() { + svcList := service.NewServiceList(nil) + svcList.HealthCheck = true + svc := service.Service{ + Config: cfg, + ServiceList: svcList, + Server: serverMock, + HealthCheck: hcMock, + } + err = svc.Close(context.Background()) + So(err, ShouldBeNil) + So(len(hcMock.StopCalls()), ShouldEqual, 1) + So(len(serverMock.ShutdownCalls()), ShouldEqual, 1) + }) + + fullSvcList := &service.ExternalServiceList{ + GenerateDownloadsProducer: true, + Graph: true, + HealthCheck: true, + MongoDB: true, + Init: nil, + } + + Convey("Closing the service results in all the initialised dependencies being closed in the expected order", func() { + svc := service.Service{ + Config: cfg, + ServiceList: fullSvcList, + Server: serverMock, + HealthCheck: hcMock, + GenerateDownloadsProducer: kafkaProducerMock, + MongoDB: mongoMock, + GraphDB: graphMock, + } + err = svc.Close(context.Background()) + So(err, ShouldBeNil) + So(len(hcMock.StopCalls()), ShouldEqual, 1) + So(len(serverMock.ShutdownCalls()), ShouldEqual, 1) + So(len(mongoMock.CloseCalls()), ShouldEqual, 1) + So(len(graphMock.CloseCalls()), ShouldEqual, 1) + So(len(kafkaProducerMock.CloseCalls()), ShouldEqual, 1) + }) + + Convey("If services fail to stop, the Close operation tries to close all dependencies and returns an error", func() { + failingserverMock := &serviceMock.HTTPServerMock{ + ListenAndServeFunc: func() error { return nil }, + ShutdownFunc: func(ctx context.Context) error { + return errors.New("Failed to stop http server") + }, + } + + svc := service.Service{ + Config: cfg, + ServiceList: fullSvcList, + Server: failingserverMock, + HealthCheck: hcMock, + GenerateDownloadsProducer: kafkaProducerMock, + MongoDB: mongoMock, + GraphDB: graphMock, + } + err = svc.Close(context.Background()) + So(err, ShouldNotBeNil) + So(err.Error(), ShouldResemble, "failed to shutdown gracefully") + So(len(hcMock.StopCalls()), ShouldEqual, 1) + So(len(failingserverMock.ShutdownCalls()), ShouldEqual, 1) + So(len(mongoMock.CloseCalls()), ShouldEqual, 1) + So(len(graphMock.CloseCalls()), ShouldEqual, 1) + So(len(kafkaProducerMock.CloseCalls()), ShouldEqual, 1) + + }) + }) +} diff --git a/store/datastore.go b/store/datastore.go index c1f5549a..512f3ad9 100644 --- a/store/datastore.go +++ b/store/datastore.go @@ -5,6 +5,7 @@ import ( "github.com/ONSdigital/dp-dataset-api/models" "github.com/ONSdigital/dp-graph/v2/observation" + "github.com/ONSdigital/dp-healthcheck/healthcheck" "github.com/globalsign/mgo/bson" ) @@ -13,10 +14,12 @@ type DataStore struct { Backend Storer } +//go:generate moq -out datastoretest/mongo.go -pkg storetest . MongoDB +//go:generate moq -out datastoretest/graph.go -pkg storetest . GraphDB //go:generate moq -out datastoretest/datastore.go -pkg storetest . Storer -// Storer represents basic data access via Get, Remove and Upsert methods. -type Storer interface { +// dataMongoDB represents the required methos to access data from mongoDB +type dataMongoDB interface { AddDimensionToInstance(dimension *models.CachedDimensionOption) error AddEventToInstance(instanceID string, event *models.Event) error AddInstance(instance *models.Instance) (*models.Instance, error) @@ -50,8 +53,31 @@ type Storer interface { UpsertVersion(ID string, versionDoc *models.Version) error DeleteDataset(ID string) error DeleteEdition(ID string) error +} +// MongoDB represents all the required methods from mongo DB +type MongoDB interface { + dataMongoDB + Close(context.Context) error + Checker(context.Context, *healthcheck.CheckState) error +} + +// dataGraphDB represents the required methods to access data from GraphDB +type dataGraphDB interface { AddVersionDetailsToInstance(ctx context.Context, instanceID string, datasetID string, edition string, version int) error SetInstanceIsPublished(ctx context.Context, instanceID string) error StreamCSVRows(ctx context.Context, instanceID, filterID string, filters *observation.DimensionFilters, limit *int) (observation.StreamRowReader, error) } + +// GraphDB represents all the required methods from graph DB +type GraphDB interface { + dataGraphDB + Close(ctx context.Context) error + Checker(context.Context, *healthcheck.CheckState) error +} + +// Storer represents basic data access via Get, Remove and Upsert methods, abstracting it from mongoDB or graphDB +type Storer interface { + dataMongoDB + dataGraphDB +} diff --git a/store/datastoretest/graph.go b/store/datastoretest/graph.go new file mode 100644 index 00000000..6e6e2490 --- /dev/null +++ b/store/datastoretest/graph.go @@ -0,0 +1,312 @@ +// Code generated by moq; DO NOT EDIT. +// github.com/matryer/moq + +package storetest + +import ( + "context" + "github.com/ONSdigital/dp-dataset-api/store" + "github.com/ONSdigital/dp-graph/v2/observation" + "github.com/ONSdigital/dp-healthcheck/healthcheck" + "sync" +) + +var ( + lockGraphDBMockAddVersionDetailsToInstance sync.RWMutex + lockGraphDBMockChecker sync.RWMutex + lockGraphDBMockClose sync.RWMutex + lockGraphDBMockSetInstanceIsPublished sync.RWMutex + lockGraphDBMockStreamCSVRows sync.RWMutex +) + +// Ensure, that GraphDBMock does implement store.GraphDB. +// If this is not the case, regenerate this file with moq. +var _ store.GraphDB = &GraphDBMock{} + +// GraphDBMock is a mock implementation of store.GraphDB. +// +// func TestSomethingThatUsesGraphDB(t *testing.T) { +// +// // make and configure a mocked store.GraphDB +// mockedGraphDB := &GraphDBMock{ +// AddVersionDetailsToInstanceFunc: func(ctx context.Context, instanceID string, datasetID string, edition string, version int) error { +// panic("mock out the AddVersionDetailsToInstance method") +// }, +// CheckerFunc: func(in1 context.Context, in2 *healthcheck.CheckState) error { +// panic("mock out the Checker method") +// }, +// CloseFunc: func(ctx context.Context) error { +// panic("mock out the Close method") +// }, +// SetInstanceIsPublishedFunc: func(ctx context.Context, instanceID string) error { +// panic("mock out the SetInstanceIsPublished method") +// }, +// StreamCSVRowsFunc: func(ctx context.Context, instanceID string, filterID string, filters *observation.DimensionFilters, limit *int) (observation.StreamRowReader, error) { +// panic("mock out the StreamCSVRows method") +// }, +// } +// +// // use mockedGraphDB in code that requires store.GraphDB +// // and then make assertions. +// +// } +type GraphDBMock struct { + // AddVersionDetailsToInstanceFunc mocks the AddVersionDetailsToInstance method. + AddVersionDetailsToInstanceFunc func(ctx context.Context, instanceID string, datasetID string, edition string, version int) error + + // CheckerFunc mocks the Checker method. + CheckerFunc func(in1 context.Context, in2 *healthcheck.CheckState) error + + // CloseFunc mocks the Close method. + CloseFunc func(ctx context.Context) error + + // SetInstanceIsPublishedFunc mocks the SetInstanceIsPublished method. + SetInstanceIsPublishedFunc func(ctx context.Context, instanceID string) error + + // StreamCSVRowsFunc mocks the StreamCSVRows method. + StreamCSVRowsFunc func(ctx context.Context, instanceID string, filterID string, filters *observation.DimensionFilters, limit *int) (observation.StreamRowReader, error) + + // calls tracks calls to the methods. + calls struct { + // AddVersionDetailsToInstance holds details about calls to the AddVersionDetailsToInstance method. + AddVersionDetailsToInstance []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // InstanceID is the instanceID argument value. + InstanceID string + // DatasetID is the datasetID argument value. + DatasetID string + // Edition is the edition argument value. + Edition string + // Version is the version argument value. + Version int + } + // Checker holds details about calls to the Checker method. + Checker []struct { + // In1 is the in1 argument value. + In1 context.Context + // In2 is the in2 argument value. + In2 *healthcheck.CheckState + } + // Close holds details about calls to the Close method. + Close []struct { + // Ctx is the ctx argument value. + Ctx context.Context + } + // SetInstanceIsPublished holds details about calls to the SetInstanceIsPublished method. + SetInstanceIsPublished []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // InstanceID is the instanceID argument value. + InstanceID string + } + // StreamCSVRows holds details about calls to the StreamCSVRows method. + StreamCSVRows []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // InstanceID is the instanceID argument value. + InstanceID string + // FilterID is the filterID argument value. + FilterID string + // Filters is the filters argument value. + Filters *observation.DimensionFilters + // Limit is the limit argument value. + Limit *int + } + } +} + +// AddVersionDetailsToInstance calls AddVersionDetailsToInstanceFunc. +func (mock *GraphDBMock) AddVersionDetailsToInstance(ctx context.Context, instanceID string, datasetID string, edition string, version int) error { + if mock.AddVersionDetailsToInstanceFunc == nil { + panic("GraphDBMock.AddVersionDetailsToInstanceFunc: method is nil but GraphDB.AddVersionDetailsToInstance was just called") + } + callInfo := struct { + Ctx context.Context + InstanceID string + DatasetID string + Edition string + Version int + }{ + Ctx: ctx, + InstanceID: instanceID, + DatasetID: datasetID, + Edition: edition, + Version: version, + } + lockGraphDBMockAddVersionDetailsToInstance.Lock() + mock.calls.AddVersionDetailsToInstance = append(mock.calls.AddVersionDetailsToInstance, callInfo) + lockGraphDBMockAddVersionDetailsToInstance.Unlock() + return mock.AddVersionDetailsToInstanceFunc(ctx, instanceID, datasetID, edition, version) +} + +// AddVersionDetailsToInstanceCalls gets all the calls that were made to AddVersionDetailsToInstance. +// Check the length with: +// len(mockedGraphDB.AddVersionDetailsToInstanceCalls()) +func (mock *GraphDBMock) AddVersionDetailsToInstanceCalls() []struct { + Ctx context.Context + InstanceID string + DatasetID string + Edition string + Version int +} { + var calls []struct { + Ctx context.Context + InstanceID string + DatasetID string + Edition string + Version int + } + lockGraphDBMockAddVersionDetailsToInstance.RLock() + calls = mock.calls.AddVersionDetailsToInstance + lockGraphDBMockAddVersionDetailsToInstance.RUnlock() + return calls +} + +// Checker calls CheckerFunc. +func (mock *GraphDBMock) Checker(in1 context.Context, in2 *healthcheck.CheckState) error { + if mock.CheckerFunc == nil { + panic("GraphDBMock.CheckerFunc: method is nil but GraphDB.Checker was just called") + } + callInfo := struct { + In1 context.Context + In2 *healthcheck.CheckState + }{ + In1: in1, + In2: in2, + } + lockGraphDBMockChecker.Lock() + mock.calls.Checker = append(mock.calls.Checker, callInfo) + lockGraphDBMockChecker.Unlock() + return mock.CheckerFunc(in1, in2) +} + +// CheckerCalls gets all the calls that were made to Checker. +// Check the length with: +// len(mockedGraphDB.CheckerCalls()) +func (mock *GraphDBMock) CheckerCalls() []struct { + In1 context.Context + In2 *healthcheck.CheckState +} { + var calls []struct { + In1 context.Context + In2 *healthcheck.CheckState + } + lockGraphDBMockChecker.RLock() + calls = mock.calls.Checker + lockGraphDBMockChecker.RUnlock() + return calls +} + +// Close calls CloseFunc. +func (mock *GraphDBMock) Close(ctx context.Context) error { + if mock.CloseFunc == nil { + panic("GraphDBMock.CloseFunc: method is nil but GraphDB.Close was just called") + } + callInfo := struct { + Ctx context.Context + }{ + Ctx: ctx, + } + lockGraphDBMockClose.Lock() + mock.calls.Close = append(mock.calls.Close, callInfo) + lockGraphDBMockClose.Unlock() + return mock.CloseFunc(ctx) +} + +// CloseCalls gets all the calls that were made to Close. +// Check the length with: +// len(mockedGraphDB.CloseCalls()) +func (mock *GraphDBMock) CloseCalls() []struct { + Ctx context.Context +} { + var calls []struct { + Ctx context.Context + } + lockGraphDBMockClose.RLock() + calls = mock.calls.Close + lockGraphDBMockClose.RUnlock() + return calls +} + +// SetInstanceIsPublished calls SetInstanceIsPublishedFunc. +func (mock *GraphDBMock) SetInstanceIsPublished(ctx context.Context, instanceID string) error { + if mock.SetInstanceIsPublishedFunc == nil { + panic("GraphDBMock.SetInstanceIsPublishedFunc: method is nil but GraphDB.SetInstanceIsPublished was just called") + } + callInfo := struct { + Ctx context.Context + InstanceID string + }{ + Ctx: ctx, + InstanceID: instanceID, + } + lockGraphDBMockSetInstanceIsPublished.Lock() + mock.calls.SetInstanceIsPublished = append(mock.calls.SetInstanceIsPublished, callInfo) + lockGraphDBMockSetInstanceIsPublished.Unlock() + return mock.SetInstanceIsPublishedFunc(ctx, instanceID) +} + +// SetInstanceIsPublishedCalls gets all the calls that were made to SetInstanceIsPublished. +// Check the length with: +// len(mockedGraphDB.SetInstanceIsPublishedCalls()) +func (mock *GraphDBMock) SetInstanceIsPublishedCalls() []struct { + Ctx context.Context + InstanceID string +} { + var calls []struct { + Ctx context.Context + InstanceID string + } + lockGraphDBMockSetInstanceIsPublished.RLock() + calls = mock.calls.SetInstanceIsPublished + lockGraphDBMockSetInstanceIsPublished.RUnlock() + return calls +} + +// StreamCSVRows calls StreamCSVRowsFunc. +func (mock *GraphDBMock) StreamCSVRows(ctx context.Context, instanceID string, filterID string, filters *observation.DimensionFilters, limit *int) (observation.StreamRowReader, error) { + if mock.StreamCSVRowsFunc == nil { + panic("GraphDBMock.StreamCSVRowsFunc: method is nil but GraphDB.StreamCSVRows was just called") + } + callInfo := struct { + Ctx context.Context + InstanceID string + FilterID string + Filters *observation.DimensionFilters + Limit *int + }{ + Ctx: ctx, + InstanceID: instanceID, + FilterID: filterID, + Filters: filters, + Limit: limit, + } + lockGraphDBMockStreamCSVRows.Lock() + mock.calls.StreamCSVRows = append(mock.calls.StreamCSVRows, callInfo) + lockGraphDBMockStreamCSVRows.Unlock() + return mock.StreamCSVRowsFunc(ctx, instanceID, filterID, filters, limit) +} + +// StreamCSVRowsCalls gets all the calls that were made to StreamCSVRows. +// Check the length with: +// len(mockedGraphDB.StreamCSVRowsCalls()) +func (mock *GraphDBMock) StreamCSVRowsCalls() []struct { + Ctx context.Context + InstanceID string + FilterID string + Filters *observation.DimensionFilters + Limit *int +} { + var calls []struct { + Ctx context.Context + InstanceID string + FilterID string + Filters *observation.DimensionFilters + Limit *int + } + lockGraphDBMockStreamCSVRows.RLock() + calls = mock.calls.StreamCSVRows + lockGraphDBMockStreamCSVRows.RUnlock() + return calls +} diff --git a/store/datastoretest/mongo.go b/store/datastoretest/mongo.go new file mode 100644 index 00000000..871ac170 --- /dev/null +++ b/store/datastoretest/mongo.go @@ -0,0 +1,1783 @@ +// Code generated by moq; DO NOT EDIT. +// github.com/matryer/moq + +package storetest + +import ( + "context" + "github.com/ONSdigital/dp-dataset-api/models" + "github.com/ONSdigital/dp-dataset-api/store" + "github.com/ONSdigital/dp-healthcheck/healthcheck" + "github.com/globalsign/mgo/bson" + "sync" +) + +var ( + lockMongoDBMockAddDimensionToInstance sync.RWMutex + lockMongoDBMockAddEventToInstance sync.RWMutex + lockMongoDBMockAddInstance sync.RWMutex + lockMongoDBMockCheckDatasetExists sync.RWMutex + lockMongoDBMockCheckEditionExists sync.RWMutex + lockMongoDBMockChecker sync.RWMutex + lockMongoDBMockClose sync.RWMutex + lockMongoDBMockDeleteDataset sync.RWMutex + lockMongoDBMockDeleteEdition sync.RWMutex + lockMongoDBMockGetDataset sync.RWMutex + lockMongoDBMockGetDatasets sync.RWMutex + lockMongoDBMockGetDimensionOptions sync.RWMutex + lockMongoDBMockGetDimensions sync.RWMutex + lockMongoDBMockGetDimensionsFromInstance sync.RWMutex + lockMongoDBMockGetEdition sync.RWMutex + lockMongoDBMockGetEditions sync.RWMutex + lockMongoDBMockGetInstance sync.RWMutex + lockMongoDBMockGetInstances sync.RWMutex + lockMongoDBMockGetNextVersion sync.RWMutex + lockMongoDBMockGetUniqueDimensionAndOptions sync.RWMutex + lockMongoDBMockGetVersion sync.RWMutex + lockMongoDBMockGetVersions sync.RWMutex + lockMongoDBMockUpdateBuildHierarchyTaskState sync.RWMutex + lockMongoDBMockUpdateBuildSearchTaskState sync.RWMutex + lockMongoDBMockUpdateDataset sync.RWMutex + lockMongoDBMockUpdateDatasetWithAssociation sync.RWMutex + lockMongoDBMockUpdateDimensionNodeID sync.RWMutex + lockMongoDBMockUpdateImportObservationsTaskState sync.RWMutex + lockMongoDBMockUpdateInstance sync.RWMutex + lockMongoDBMockUpdateObservationInserted sync.RWMutex + lockMongoDBMockUpdateVersion sync.RWMutex + lockMongoDBMockUpsertContact sync.RWMutex + lockMongoDBMockUpsertDataset sync.RWMutex + lockMongoDBMockUpsertEdition sync.RWMutex + lockMongoDBMockUpsertVersion sync.RWMutex +) + +// Ensure, that MongoDBMock does implement store.MongoDB. +// If this is not the case, regenerate this file with moq. +var _ store.MongoDB = &MongoDBMock{} + +// MongoDBMock is a mock implementation of store.MongoDB. +// +// func TestSomethingThatUsesMongoDB(t *testing.T) { +// +// // make and configure a mocked store.MongoDB +// mockedMongoDB := &MongoDBMock{ +// AddDimensionToInstanceFunc: func(dimension *models.CachedDimensionOption) error { +// panic("mock out the AddDimensionToInstance method") +// }, +// AddEventToInstanceFunc: func(instanceID string, event *models.Event) error { +// panic("mock out the AddEventToInstance method") +// }, +// AddInstanceFunc: func(instance *models.Instance) (*models.Instance, error) { +// panic("mock out the AddInstance method") +// }, +// CheckDatasetExistsFunc: func(ID string, state string) error { +// panic("mock out the CheckDatasetExists method") +// }, +// CheckEditionExistsFunc: func(ID string, editionID string, state string) error { +// panic("mock out the CheckEditionExists method") +// }, +// CheckerFunc: func(in1 context.Context, in2 *healthcheck.CheckState) error { +// panic("mock out the Checker method") +// }, +// CloseFunc: func(in1 context.Context) error { +// panic("mock out the Close method") +// }, +// DeleteDatasetFunc: func(ID string) error { +// panic("mock out the DeleteDataset method") +// }, +// DeleteEditionFunc: func(ID string) error { +// panic("mock out the DeleteEdition method") +// }, +// GetDatasetFunc: func(ID string) (*models.DatasetUpdate, error) { +// panic("mock out the GetDataset method") +// }, +// GetDatasetsFunc: func(ctx context.Context) ([]models.DatasetUpdate, error) { +// panic("mock out the GetDatasets method") +// }, +// GetDimensionOptionsFunc: func(version *models.Version, dimension string) (*models.DimensionOptionResults, error) { +// panic("mock out the GetDimensionOptions method") +// }, +// GetDimensionsFunc: func(datasetID string, versionID string) ([]bson.M, error) { +// panic("mock out the GetDimensions method") +// }, +// GetDimensionsFromInstanceFunc: func(ID string) (*models.DimensionNodeResults, error) { +// panic("mock out the GetDimensionsFromInstance method") +// }, +// GetEditionFunc: func(ID string, editionID string, state string) (*models.EditionUpdate, error) { +// panic("mock out the GetEdition method") +// }, +// GetEditionsFunc: func(ctx context.Context, ID string, state string) (*models.EditionUpdateResults, error) { +// panic("mock out the GetEditions method") +// }, +// GetInstanceFunc: func(ID string) (*models.Instance, error) { +// panic("mock out the GetInstance method") +// }, +// GetInstancesFunc: func(ctx context.Context, states []string, datasets []string) (*models.InstanceResults, error) { +// panic("mock out the GetInstances method") +// }, +// GetNextVersionFunc: func(datasetID string, editionID string) (int, error) { +// panic("mock out the GetNextVersion method") +// }, +// GetUniqueDimensionAndOptionsFunc: func(ID string, dimension string) (*models.DimensionValues, error) { +// panic("mock out the GetUniqueDimensionAndOptions method") +// }, +// GetVersionFunc: func(datasetID string, editionID string, version string, state string) (*models.Version, error) { +// panic("mock out the GetVersion method") +// }, +// GetVersionsFunc: func(ctx context.Context, datasetID string, editionID string, state string) (*models.VersionResults, error) { +// panic("mock out the GetVersions method") +// }, +// UpdateBuildHierarchyTaskStateFunc: func(id string, dimension string, state string) error { +// panic("mock out the UpdateBuildHierarchyTaskState method") +// }, +// UpdateBuildSearchTaskStateFunc: func(id string, dimension string, state string) error { +// panic("mock out the UpdateBuildSearchTaskState method") +// }, +// UpdateDatasetFunc: func(ctx context.Context, ID string, dataset *models.Dataset, currentState string) error { +// panic("mock out the UpdateDataset method") +// }, +// UpdateDatasetWithAssociationFunc: func(ID string, state string, version *models.Version) error { +// panic("mock out the UpdateDatasetWithAssociation method") +// }, +// UpdateDimensionNodeIDFunc: func(dimension *models.DimensionOption) error { +// panic("mock out the UpdateDimensionNodeID method") +// }, +// UpdateImportObservationsTaskStateFunc: func(id string, state string) error { +// panic("mock out the UpdateImportObservationsTaskState method") +// }, +// UpdateInstanceFunc: func(ctx context.Context, ID string, instance *models.Instance) error { +// panic("mock out the UpdateInstance method") +// }, +// UpdateObservationInsertedFunc: func(ID string, observationInserted int64) error { +// panic("mock out the UpdateObservationInserted method") +// }, +// UpdateVersionFunc: func(ID string, version *models.Version) error { +// panic("mock out the UpdateVersion method") +// }, +// UpsertContactFunc: func(ID string, update interface{}) error { +// panic("mock out the UpsertContact method") +// }, +// UpsertDatasetFunc: func(ID string, datasetDoc *models.DatasetUpdate) error { +// panic("mock out the UpsertDataset method") +// }, +// UpsertEditionFunc: func(datasetID string, edition string, editionDoc *models.EditionUpdate) error { +// panic("mock out the UpsertEdition method") +// }, +// UpsertVersionFunc: func(ID string, versionDoc *models.Version) error { +// panic("mock out the UpsertVersion method") +// }, +// } +// +// // use mockedMongoDB in code that requires store.MongoDB +// // and then make assertions. +// +// } +type MongoDBMock struct { + // AddDimensionToInstanceFunc mocks the AddDimensionToInstance method. + AddDimensionToInstanceFunc func(dimension *models.CachedDimensionOption) error + + // AddEventToInstanceFunc mocks the AddEventToInstance method. + AddEventToInstanceFunc func(instanceID string, event *models.Event) error + + // AddInstanceFunc mocks the AddInstance method. + AddInstanceFunc func(instance *models.Instance) (*models.Instance, error) + + // CheckDatasetExistsFunc mocks the CheckDatasetExists method. + CheckDatasetExistsFunc func(ID string, state string) error + + // CheckEditionExistsFunc mocks the CheckEditionExists method. + CheckEditionExistsFunc func(ID string, editionID string, state string) error + + // CheckerFunc mocks the Checker method. + CheckerFunc func(in1 context.Context, in2 *healthcheck.CheckState) error + + // CloseFunc mocks the Close method. + CloseFunc func(in1 context.Context) error + + // DeleteDatasetFunc mocks the DeleteDataset method. + DeleteDatasetFunc func(ID string) error + + // DeleteEditionFunc mocks the DeleteEdition method. + DeleteEditionFunc func(ID string) error + + // GetDatasetFunc mocks the GetDataset method. + GetDatasetFunc func(ID string) (*models.DatasetUpdate, error) + + // GetDatasetsFunc mocks the GetDatasets method. + GetDatasetsFunc func(ctx context.Context) ([]models.DatasetUpdate, error) + + // GetDimensionOptionsFunc mocks the GetDimensionOptions method. + GetDimensionOptionsFunc func(version *models.Version, dimension string) (*models.DimensionOptionResults, error) + + // GetDimensionsFunc mocks the GetDimensions method. + GetDimensionsFunc func(datasetID string, versionID string) ([]bson.M, error) + + // GetDimensionsFromInstanceFunc mocks the GetDimensionsFromInstance method. + GetDimensionsFromInstanceFunc func(ID string) (*models.DimensionNodeResults, error) + + // GetEditionFunc mocks the GetEdition method. + GetEditionFunc func(ID string, editionID string, state string) (*models.EditionUpdate, error) + + // GetEditionsFunc mocks the GetEditions method. + GetEditionsFunc func(ctx context.Context, ID string, state string) (*models.EditionUpdateResults, error) + + // GetInstanceFunc mocks the GetInstance method. + GetInstanceFunc func(ID string) (*models.Instance, error) + + // GetInstancesFunc mocks the GetInstances method. + GetInstancesFunc func(ctx context.Context, states []string, datasets []string) (*models.InstanceResults, error) + + // GetNextVersionFunc mocks the GetNextVersion method. + GetNextVersionFunc func(datasetID string, editionID string) (int, error) + + // GetUniqueDimensionAndOptionsFunc mocks the GetUniqueDimensionAndOptions method. + GetUniqueDimensionAndOptionsFunc func(ID string, dimension string) (*models.DimensionValues, error) + + // GetVersionFunc mocks the GetVersion method. + GetVersionFunc func(datasetID string, editionID string, version string, state string) (*models.Version, error) + + // GetVersionsFunc mocks the GetVersions method. + GetVersionsFunc func(ctx context.Context, datasetID string, editionID string, state string) (*models.VersionResults, error) + + // UpdateBuildHierarchyTaskStateFunc mocks the UpdateBuildHierarchyTaskState method. + UpdateBuildHierarchyTaskStateFunc func(id string, dimension string, state string) error + + // UpdateBuildSearchTaskStateFunc mocks the UpdateBuildSearchTaskState method. + UpdateBuildSearchTaskStateFunc func(id string, dimension string, state string) error + + // UpdateDatasetFunc mocks the UpdateDataset method. + UpdateDatasetFunc func(ctx context.Context, ID string, dataset *models.Dataset, currentState string) error + + // UpdateDatasetWithAssociationFunc mocks the UpdateDatasetWithAssociation method. + UpdateDatasetWithAssociationFunc func(ID string, state string, version *models.Version) error + + // UpdateDimensionNodeIDFunc mocks the UpdateDimensionNodeID method. + UpdateDimensionNodeIDFunc func(dimension *models.DimensionOption) error + + // UpdateImportObservationsTaskStateFunc mocks the UpdateImportObservationsTaskState method. + UpdateImportObservationsTaskStateFunc func(id string, state string) error + + // UpdateInstanceFunc mocks the UpdateInstance method. + UpdateInstanceFunc func(ctx context.Context, ID string, instance *models.Instance) error + + // UpdateObservationInsertedFunc mocks the UpdateObservationInserted method. + UpdateObservationInsertedFunc func(ID string, observationInserted int64) error + + // UpdateVersionFunc mocks the UpdateVersion method. + UpdateVersionFunc func(ID string, version *models.Version) error + + // UpsertContactFunc mocks the UpsertContact method. + UpsertContactFunc func(ID string, update interface{}) error + + // UpsertDatasetFunc mocks the UpsertDataset method. + UpsertDatasetFunc func(ID string, datasetDoc *models.DatasetUpdate) error + + // UpsertEditionFunc mocks the UpsertEdition method. + UpsertEditionFunc func(datasetID string, edition string, editionDoc *models.EditionUpdate) error + + // UpsertVersionFunc mocks the UpsertVersion method. + UpsertVersionFunc func(ID string, versionDoc *models.Version) error + + // calls tracks calls to the methods. + calls struct { + // AddDimensionToInstance holds details about calls to the AddDimensionToInstance method. + AddDimensionToInstance []struct { + // Dimension is the dimension argument value. + Dimension *models.CachedDimensionOption + } + // AddEventToInstance holds details about calls to the AddEventToInstance method. + AddEventToInstance []struct { + // InstanceID is the instanceID argument value. + InstanceID string + // Event is the event argument value. + Event *models.Event + } + // AddInstance holds details about calls to the AddInstance method. + AddInstance []struct { + // Instance is the instance argument value. + Instance *models.Instance + } + // CheckDatasetExists holds details about calls to the CheckDatasetExists method. + CheckDatasetExists []struct { + // ID is the ID argument value. + ID string + // State is the state argument value. + State string + } + // CheckEditionExists holds details about calls to the CheckEditionExists method. + CheckEditionExists []struct { + // ID is the ID argument value. + ID string + // EditionID is the editionID argument value. + EditionID string + // State is the state argument value. + State string + } + // Checker holds details about calls to the Checker method. + Checker []struct { + // In1 is the in1 argument value. + In1 context.Context + // In2 is the in2 argument value. + In2 *healthcheck.CheckState + } + // Close holds details about calls to the Close method. + Close []struct { + // In1 is the in1 argument value. + In1 context.Context + } + // DeleteDataset holds details about calls to the DeleteDataset method. + DeleteDataset []struct { + // ID is the ID argument value. + ID string + } + // DeleteEdition holds details about calls to the DeleteEdition method. + DeleteEdition []struct { + // ID is the ID argument value. + ID string + } + // GetDataset holds details about calls to the GetDataset method. + GetDataset []struct { + // ID is the ID argument value. + ID string + } + // GetDatasets holds details about calls to the GetDatasets method. + GetDatasets []struct { + // Ctx is the ctx argument value. + Ctx context.Context + } + // GetDimensionOptions holds details about calls to the GetDimensionOptions method. + GetDimensionOptions []struct { + // Version is the version argument value. + Version *models.Version + // Dimension is the dimension argument value. + Dimension string + } + // GetDimensions holds details about calls to the GetDimensions method. + GetDimensions []struct { + // DatasetID is the datasetID argument value. + DatasetID string + // VersionID is the versionID argument value. + VersionID string + } + // GetDimensionsFromInstance holds details about calls to the GetDimensionsFromInstance method. + GetDimensionsFromInstance []struct { + // ID is the ID argument value. + ID string + } + // GetEdition holds details about calls to the GetEdition method. + GetEdition []struct { + // ID is the ID argument value. + ID string + // EditionID is the editionID argument value. + EditionID string + // State is the state argument value. + State string + } + // GetEditions holds details about calls to the GetEditions method. + GetEditions []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // ID is the ID argument value. + ID string + // State is the state argument value. + State string + } + // GetInstance holds details about calls to the GetInstance method. + GetInstance []struct { + // ID is the ID argument value. + ID string + } + // GetInstances holds details about calls to the GetInstances method. + GetInstances []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // States is the states argument value. + States []string + // Datasets is the datasets argument value. + Datasets []string + } + // GetNextVersion holds details about calls to the GetNextVersion method. + GetNextVersion []struct { + // DatasetID is the datasetID argument value. + DatasetID string + // EditionID is the editionID argument value. + EditionID string + } + // GetUniqueDimensionAndOptions holds details about calls to the GetUniqueDimensionAndOptions method. + GetUniqueDimensionAndOptions []struct { + // ID is the ID argument value. + ID string + // Dimension is the dimension argument value. + Dimension string + } + // GetVersion holds details about calls to the GetVersion method. + GetVersion []struct { + // DatasetID is the datasetID argument value. + DatasetID string + // EditionID is the editionID argument value. + EditionID string + // Version is the version argument value. + Version string + // State is the state argument value. + State string + } + // GetVersions holds details about calls to the GetVersions method. + GetVersions []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // DatasetID is the datasetID argument value. + DatasetID string + // EditionID is the editionID argument value. + EditionID string + // State is the state argument value. + State string + } + // UpdateBuildHierarchyTaskState holds details about calls to the UpdateBuildHierarchyTaskState method. + UpdateBuildHierarchyTaskState []struct { + // ID is the id argument value. + ID string + // Dimension is the dimension argument value. + Dimension string + // State is the state argument value. + State string + } + // UpdateBuildSearchTaskState holds details about calls to the UpdateBuildSearchTaskState method. + UpdateBuildSearchTaskState []struct { + // ID is the id argument value. + ID string + // Dimension is the dimension argument value. + Dimension string + // State is the state argument value. + State string + } + // UpdateDataset holds details about calls to the UpdateDataset method. + UpdateDataset []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // ID is the ID argument value. + ID string + // Dataset is the dataset argument value. + Dataset *models.Dataset + // CurrentState is the currentState argument value. + CurrentState string + } + // UpdateDatasetWithAssociation holds details about calls to the UpdateDatasetWithAssociation method. + UpdateDatasetWithAssociation []struct { + // ID is the ID argument value. + ID string + // State is the state argument value. + State string + // Version is the version argument value. + Version *models.Version + } + // UpdateDimensionNodeID holds details about calls to the UpdateDimensionNodeID method. + UpdateDimensionNodeID []struct { + // Dimension is the dimension argument value. + Dimension *models.DimensionOption + } + // UpdateImportObservationsTaskState holds details about calls to the UpdateImportObservationsTaskState method. + UpdateImportObservationsTaskState []struct { + // ID is the id argument value. + ID string + // State is the state argument value. + State string + } + // UpdateInstance holds details about calls to the UpdateInstance method. + UpdateInstance []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // ID is the ID argument value. + ID string + // Instance is the instance argument value. + Instance *models.Instance + } + // UpdateObservationInserted holds details about calls to the UpdateObservationInserted method. + UpdateObservationInserted []struct { + // ID is the ID argument value. + ID string + // ObservationInserted is the observationInserted argument value. + ObservationInserted int64 + } + // UpdateVersion holds details about calls to the UpdateVersion method. + UpdateVersion []struct { + // ID is the ID argument value. + ID string + // Version is the version argument value. + Version *models.Version + } + // UpsertContact holds details about calls to the UpsertContact method. + UpsertContact []struct { + // ID is the ID argument value. + ID string + // Update is the update argument value. + Update interface{} + } + // UpsertDataset holds details about calls to the UpsertDataset method. + UpsertDataset []struct { + // ID is the ID argument value. + ID string + // DatasetDoc is the datasetDoc argument value. + DatasetDoc *models.DatasetUpdate + } + // UpsertEdition holds details about calls to the UpsertEdition method. + UpsertEdition []struct { + // DatasetID is the datasetID argument value. + DatasetID string + // Edition is the edition argument value. + Edition string + // EditionDoc is the editionDoc argument value. + EditionDoc *models.EditionUpdate + } + // UpsertVersion holds details about calls to the UpsertVersion method. + UpsertVersion []struct { + // ID is the ID argument value. + ID string + // VersionDoc is the versionDoc argument value. + VersionDoc *models.Version + } + } +} + +// AddDimensionToInstance calls AddDimensionToInstanceFunc. +func (mock *MongoDBMock) AddDimensionToInstance(dimension *models.CachedDimensionOption) error { + if mock.AddDimensionToInstanceFunc == nil { + panic("MongoDBMock.AddDimensionToInstanceFunc: method is nil but MongoDB.AddDimensionToInstance was just called") + } + callInfo := struct { + Dimension *models.CachedDimensionOption + }{ + Dimension: dimension, + } + lockMongoDBMockAddDimensionToInstance.Lock() + mock.calls.AddDimensionToInstance = append(mock.calls.AddDimensionToInstance, callInfo) + lockMongoDBMockAddDimensionToInstance.Unlock() + return mock.AddDimensionToInstanceFunc(dimension) +} + +// AddDimensionToInstanceCalls gets all the calls that were made to AddDimensionToInstance. +// Check the length with: +// len(mockedMongoDB.AddDimensionToInstanceCalls()) +func (mock *MongoDBMock) AddDimensionToInstanceCalls() []struct { + Dimension *models.CachedDimensionOption +} { + var calls []struct { + Dimension *models.CachedDimensionOption + } + lockMongoDBMockAddDimensionToInstance.RLock() + calls = mock.calls.AddDimensionToInstance + lockMongoDBMockAddDimensionToInstance.RUnlock() + return calls +} + +// AddEventToInstance calls AddEventToInstanceFunc. +func (mock *MongoDBMock) AddEventToInstance(instanceID string, event *models.Event) error { + if mock.AddEventToInstanceFunc == nil { + panic("MongoDBMock.AddEventToInstanceFunc: method is nil but MongoDB.AddEventToInstance was just called") + } + callInfo := struct { + InstanceID string + Event *models.Event + }{ + InstanceID: instanceID, + Event: event, + } + lockMongoDBMockAddEventToInstance.Lock() + mock.calls.AddEventToInstance = append(mock.calls.AddEventToInstance, callInfo) + lockMongoDBMockAddEventToInstance.Unlock() + return mock.AddEventToInstanceFunc(instanceID, event) +} + +// AddEventToInstanceCalls gets all the calls that were made to AddEventToInstance. +// Check the length with: +// len(mockedMongoDB.AddEventToInstanceCalls()) +func (mock *MongoDBMock) AddEventToInstanceCalls() []struct { + InstanceID string + Event *models.Event +} { + var calls []struct { + InstanceID string + Event *models.Event + } + lockMongoDBMockAddEventToInstance.RLock() + calls = mock.calls.AddEventToInstance + lockMongoDBMockAddEventToInstance.RUnlock() + return calls +} + +// AddInstance calls AddInstanceFunc. +func (mock *MongoDBMock) AddInstance(instance *models.Instance) (*models.Instance, error) { + if mock.AddInstanceFunc == nil { + panic("MongoDBMock.AddInstanceFunc: method is nil but MongoDB.AddInstance was just called") + } + callInfo := struct { + Instance *models.Instance + }{ + Instance: instance, + } + lockMongoDBMockAddInstance.Lock() + mock.calls.AddInstance = append(mock.calls.AddInstance, callInfo) + lockMongoDBMockAddInstance.Unlock() + return mock.AddInstanceFunc(instance) +} + +// AddInstanceCalls gets all the calls that were made to AddInstance. +// Check the length with: +// len(mockedMongoDB.AddInstanceCalls()) +func (mock *MongoDBMock) AddInstanceCalls() []struct { + Instance *models.Instance +} { + var calls []struct { + Instance *models.Instance + } + lockMongoDBMockAddInstance.RLock() + calls = mock.calls.AddInstance + lockMongoDBMockAddInstance.RUnlock() + return calls +} + +// CheckDatasetExists calls CheckDatasetExistsFunc. +func (mock *MongoDBMock) CheckDatasetExists(ID string, state string) error { + if mock.CheckDatasetExistsFunc == nil { + panic("MongoDBMock.CheckDatasetExistsFunc: method is nil but MongoDB.CheckDatasetExists was just called") + } + callInfo := struct { + ID string + State string + }{ + ID: ID, + State: state, + } + lockMongoDBMockCheckDatasetExists.Lock() + mock.calls.CheckDatasetExists = append(mock.calls.CheckDatasetExists, callInfo) + lockMongoDBMockCheckDatasetExists.Unlock() + return mock.CheckDatasetExistsFunc(ID, state) +} + +// CheckDatasetExistsCalls gets all the calls that were made to CheckDatasetExists. +// Check the length with: +// len(mockedMongoDB.CheckDatasetExistsCalls()) +func (mock *MongoDBMock) CheckDatasetExistsCalls() []struct { + ID string + State string +} { + var calls []struct { + ID string + State string + } + lockMongoDBMockCheckDatasetExists.RLock() + calls = mock.calls.CheckDatasetExists + lockMongoDBMockCheckDatasetExists.RUnlock() + return calls +} + +// CheckEditionExists calls CheckEditionExistsFunc. +func (mock *MongoDBMock) CheckEditionExists(ID string, editionID string, state string) error { + if mock.CheckEditionExistsFunc == nil { + panic("MongoDBMock.CheckEditionExistsFunc: method is nil but MongoDB.CheckEditionExists was just called") + } + callInfo := struct { + ID string + EditionID string + State string + }{ + ID: ID, + EditionID: editionID, + State: state, + } + lockMongoDBMockCheckEditionExists.Lock() + mock.calls.CheckEditionExists = append(mock.calls.CheckEditionExists, callInfo) + lockMongoDBMockCheckEditionExists.Unlock() + return mock.CheckEditionExistsFunc(ID, editionID, state) +} + +// CheckEditionExistsCalls gets all the calls that were made to CheckEditionExists. +// Check the length with: +// len(mockedMongoDB.CheckEditionExistsCalls()) +func (mock *MongoDBMock) CheckEditionExistsCalls() []struct { + ID string + EditionID string + State string +} { + var calls []struct { + ID string + EditionID string + State string + } + lockMongoDBMockCheckEditionExists.RLock() + calls = mock.calls.CheckEditionExists + lockMongoDBMockCheckEditionExists.RUnlock() + return calls +} + +// Checker calls CheckerFunc. +func (mock *MongoDBMock) Checker(in1 context.Context, in2 *healthcheck.CheckState) error { + if mock.CheckerFunc == nil { + panic("MongoDBMock.CheckerFunc: method is nil but MongoDB.Checker was just called") + } + callInfo := struct { + In1 context.Context + In2 *healthcheck.CheckState + }{ + In1: in1, + In2: in2, + } + lockMongoDBMockChecker.Lock() + mock.calls.Checker = append(mock.calls.Checker, callInfo) + lockMongoDBMockChecker.Unlock() + return mock.CheckerFunc(in1, in2) +} + +// CheckerCalls gets all the calls that were made to Checker. +// Check the length with: +// len(mockedMongoDB.CheckerCalls()) +func (mock *MongoDBMock) CheckerCalls() []struct { + In1 context.Context + In2 *healthcheck.CheckState +} { + var calls []struct { + In1 context.Context + In2 *healthcheck.CheckState + } + lockMongoDBMockChecker.RLock() + calls = mock.calls.Checker + lockMongoDBMockChecker.RUnlock() + return calls +} + +// Close calls CloseFunc. +func (mock *MongoDBMock) Close(in1 context.Context) error { + if mock.CloseFunc == nil { + panic("MongoDBMock.CloseFunc: method is nil but MongoDB.Close was just called") + } + callInfo := struct { + In1 context.Context + }{ + In1: in1, + } + lockMongoDBMockClose.Lock() + mock.calls.Close = append(mock.calls.Close, callInfo) + lockMongoDBMockClose.Unlock() + return mock.CloseFunc(in1) +} + +// CloseCalls gets all the calls that were made to Close. +// Check the length with: +// len(mockedMongoDB.CloseCalls()) +func (mock *MongoDBMock) CloseCalls() []struct { + In1 context.Context +} { + var calls []struct { + In1 context.Context + } + lockMongoDBMockClose.RLock() + calls = mock.calls.Close + lockMongoDBMockClose.RUnlock() + return calls +} + +// DeleteDataset calls DeleteDatasetFunc. +func (mock *MongoDBMock) DeleteDataset(ID string) error { + if mock.DeleteDatasetFunc == nil { + panic("MongoDBMock.DeleteDatasetFunc: method is nil but MongoDB.DeleteDataset was just called") + } + callInfo := struct { + ID string + }{ + ID: ID, + } + lockMongoDBMockDeleteDataset.Lock() + mock.calls.DeleteDataset = append(mock.calls.DeleteDataset, callInfo) + lockMongoDBMockDeleteDataset.Unlock() + return mock.DeleteDatasetFunc(ID) +} + +// DeleteDatasetCalls gets all the calls that were made to DeleteDataset. +// Check the length with: +// len(mockedMongoDB.DeleteDatasetCalls()) +func (mock *MongoDBMock) DeleteDatasetCalls() []struct { + ID string +} { + var calls []struct { + ID string + } + lockMongoDBMockDeleteDataset.RLock() + calls = mock.calls.DeleteDataset + lockMongoDBMockDeleteDataset.RUnlock() + return calls +} + +// DeleteEdition calls DeleteEditionFunc. +func (mock *MongoDBMock) DeleteEdition(ID string) error { + if mock.DeleteEditionFunc == nil { + panic("MongoDBMock.DeleteEditionFunc: method is nil but MongoDB.DeleteEdition was just called") + } + callInfo := struct { + ID string + }{ + ID: ID, + } + lockMongoDBMockDeleteEdition.Lock() + mock.calls.DeleteEdition = append(mock.calls.DeleteEdition, callInfo) + lockMongoDBMockDeleteEdition.Unlock() + return mock.DeleteEditionFunc(ID) +} + +// DeleteEditionCalls gets all the calls that were made to DeleteEdition. +// Check the length with: +// len(mockedMongoDB.DeleteEditionCalls()) +func (mock *MongoDBMock) DeleteEditionCalls() []struct { + ID string +} { + var calls []struct { + ID string + } + lockMongoDBMockDeleteEdition.RLock() + calls = mock.calls.DeleteEdition + lockMongoDBMockDeleteEdition.RUnlock() + return calls +} + +// GetDataset calls GetDatasetFunc. +func (mock *MongoDBMock) GetDataset(ID string) (*models.DatasetUpdate, error) { + if mock.GetDatasetFunc == nil { + panic("MongoDBMock.GetDatasetFunc: method is nil but MongoDB.GetDataset was just called") + } + callInfo := struct { + ID string + }{ + ID: ID, + } + lockMongoDBMockGetDataset.Lock() + mock.calls.GetDataset = append(mock.calls.GetDataset, callInfo) + lockMongoDBMockGetDataset.Unlock() + return mock.GetDatasetFunc(ID) +} + +// GetDatasetCalls gets all the calls that were made to GetDataset. +// Check the length with: +// len(mockedMongoDB.GetDatasetCalls()) +func (mock *MongoDBMock) GetDatasetCalls() []struct { + ID string +} { + var calls []struct { + ID string + } + lockMongoDBMockGetDataset.RLock() + calls = mock.calls.GetDataset + lockMongoDBMockGetDataset.RUnlock() + return calls +} + +// GetDatasets calls GetDatasetsFunc. +func (mock *MongoDBMock) GetDatasets(ctx context.Context) ([]models.DatasetUpdate, error) { + if mock.GetDatasetsFunc == nil { + panic("MongoDBMock.GetDatasetsFunc: method is nil but MongoDB.GetDatasets was just called") + } + callInfo := struct { + Ctx context.Context + }{ + Ctx: ctx, + } + lockMongoDBMockGetDatasets.Lock() + mock.calls.GetDatasets = append(mock.calls.GetDatasets, callInfo) + lockMongoDBMockGetDatasets.Unlock() + return mock.GetDatasetsFunc(ctx) +} + +// GetDatasetsCalls gets all the calls that were made to GetDatasets. +// Check the length with: +// len(mockedMongoDB.GetDatasetsCalls()) +func (mock *MongoDBMock) GetDatasetsCalls() []struct { + Ctx context.Context +} { + var calls []struct { + Ctx context.Context + } + lockMongoDBMockGetDatasets.RLock() + calls = mock.calls.GetDatasets + lockMongoDBMockGetDatasets.RUnlock() + return calls +} + +// GetDimensionOptions calls GetDimensionOptionsFunc. +func (mock *MongoDBMock) GetDimensionOptions(version *models.Version, dimension string) (*models.DimensionOptionResults, error) { + if mock.GetDimensionOptionsFunc == nil { + panic("MongoDBMock.GetDimensionOptionsFunc: method is nil but MongoDB.GetDimensionOptions was just called") + } + callInfo := struct { + Version *models.Version + Dimension string + }{ + Version: version, + Dimension: dimension, + } + lockMongoDBMockGetDimensionOptions.Lock() + mock.calls.GetDimensionOptions = append(mock.calls.GetDimensionOptions, callInfo) + lockMongoDBMockGetDimensionOptions.Unlock() + return mock.GetDimensionOptionsFunc(version, dimension) +} + +// GetDimensionOptionsCalls gets all the calls that were made to GetDimensionOptions. +// Check the length with: +// len(mockedMongoDB.GetDimensionOptionsCalls()) +func (mock *MongoDBMock) GetDimensionOptionsCalls() []struct { + Version *models.Version + Dimension string +} { + var calls []struct { + Version *models.Version + Dimension string + } + lockMongoDBMockGetDimensionOptions.RLock() + calls = mock.calls.GetDimensionOptions + lockMongoDBMockGetDimensionOptions.RUnlock() + return calls +} + +// GetDimensions calls GetDimensionsFunc. +func (mock *MongoDBMock) GetDimensions(datasetID string, versionID string) ([]bson.M, error) { + if mock.GetDimensionsFunc == nil { + panic("MongoDBMock.GetDimensionsFunc: method is nil but MongoDB.GetDimensions was just called") + } + callInfo := struct { + DatasetID string + VersionID string + }{ + DatasetID: datasetID, + VersionID: versionID, + } + lockMongoDBMockGetDimensions.Lock() + mock.calls.GetDimensions = append(mock.calls.GetDimensions, callInfo) + lockMongoDBMockGetDimensions.Unlock() + return mock.GetDimensionsFunc(datasetID, versionID) +} + +// GetDimensionsCalls gets all the calls that were made to GetDimensions. +// Check the length with: +// len(mockedMongoDB.GetDimensionsCalls()) +func (mock *MongoDBMock) GetDimensionsCalls() []struct { + DatasetID string + VersionID string +} { + var calls []struct { + DatasetID string + VersionID string + } + lockMongoDBMockGetDimensions.RLock() + calls = mock.calls.GetDimensions + lockMongoDBMockGetDimensions.RUnlock() + return calls +} + +// GetDimensionsFromInstance calls GetDimensionsFromInstanceFunc. +func (mock *MongoDBMock) GetDimensionsFromInstance(ID string) (*models.DimensionNodeResults, error) { + if mock.GetDimensionsFromInstanceFunc == nil { + panic("MongoDBMock.GetDimensionsFromInstanceFunc: method is nil but MongoDB.GetDimensionsFromInstance was just called") + } + callInfo := struct { + ID string + }{ + ID: ID, + } + lockMongoDBMockGetDimensionsFromInstance.Lock() + mock.calls.GetDimensionsFromInstance = append(mock.calls.GetDimensionsFromInstance, callInfo) + lockMongoDBMockGetDimensionsFromInstance.Unlock() + return mock.GetDimensionsFromInstanceFunc(ID) +} + +// GetDimensionsFromInstanceCalls gets all the calls that were made to GetDimensionsFromInstance. +// Check the length with: +// len(mockedMongoDB.GetDimensionsFromInstanceCalls()) +func (mock *MongoDBMock) GetDimensionsFromInstanceCalls() []struct { + ID string +} { + var calls []struct { + ID string + } + lockMongoDBMockGetDimensionsFromInstance.RLock() + calls = mock.calls.GetDimensionsFromInstance + lockMongoDBMockGetDimensionsFromInstance.RUnlock() + return calls +} + +// GetEdition calls GetEditionFunc. +func (mock *MongoDBMock) GetEdition(ID string, editionID string, state string) (*models.EditionUpdate, error) { + if mock.GetEditionFunc == nil { + panic("MongoDBMock.GetEditionFunc: method is nil but MongoDB.GetEdition was just called") + } + callInfo := struct { + ID string + EditionID string + State string + }{ + ID: ID, + EditionID: editionID, + State: state, + } + lockMongoDBMockGetEdition.Lock() + mock.calls.GetEdition = append(mock.calls.GetEdition, callInfo) + lockMongoDBMockGetEdition.Unlock() + return mock.GetEditionFunc(ID, editionID, state) +} + +// GetEditionCalls gets all the calls that were made to GetEdition. +// Check the length with: +// len(mockedMongoDB.GetEditionCalls()) +func (mock *MongoDBMock) GetEditionCalls() []struct { + ID string + EditionID string + State string +} { + var calls []struct { + ID string + EditionID string + State string + } + lockMongoDBMockGetEdition.RLock() + calls = mock.calls.GetEdition + lockMongoDBMockGetEdition.RUnlock() + return calls +} + +// GetEditions calls GetEditionsFunc. +func (mock *MongoDBMock) GetEditions(ctx context.Context, ID string, state string) (*models.EditionUpdateResults, error) { + if mock.GetEditionsFunc == nil { + panic("MongoDBMock.GetEditionsFunc: method is nil but MongoDB.GetEditions was just called") + } + callInfo := struct { + Ctx context.Context + ID string + State string + }{ + Ctx: ctx, + ID: ID, + State: state, + } + lockMongoDBMockGetEditions.Lock() + mock.calls.GetEditions = append(mock.calls.GetEditions, callInfo) + lockMongoDBMockGetEditions.Unlock() + return mock.GetEditionsFunc(ctx, ID, state) +} + +// GetEditionsCalls gets all the calls that were made to GetEditions. +// Check the length with: +// len(mockedMongoDB.GetEditionsCalls()) +func (mock *MongoDBMock) GetEditionsCalls() []struct { + Ctx context.Context + ID string + State string +} { + var calls []struct { + Ctx context.Context + ID string + State string + } + lockMongoDBMockGetEditions.RLock() + calls = mock.calls.GetEditions + lockMongoDBMockGetEditions.RUnlock() + return calls +} + +// GetInstance calls GetInstanceFunc. +func (mock *MongoDBMock) GetInstance(ID string) (*models.Instance, error) { + if mock.GetInstanceFunc == nil { + panic("MongoDBMock.GetInstanceFunc: method is nil but MongoDB.GetInstance was just called") + } + callInfo := struct { + ID string + }{ + ID: ID, + } + lockMongoDBMockGetInstance.Lock() + mock.calls.GetInstance = append(mock.calls.GetInstance, callInfo) + lockMongoDBMockGetInstance.Unlock() + return mock.GetInstanceFunc(ID) +} + +// GetInstanceCalls gets all the calls that were made to GetInstance. +// Check the length with: +// len(mockedMongoDB.GetInstanceCalls()) +func (mock *MongoDBMock) GetInstanceCalls() []struct { + ID string +} { + var calls []struct { + ID string + } + lockMongoDBMockGetInstance.RLock() + calls = mock.calls.GetInstance + lockMongoDBMockGetInstance.RUnlock() + return calls +} + +// GetInstances calls GetInstancesFunc. +func (mock *MongoDBMock) GetInstances(ctx context.Context, states []string, datasets []string) (*models.InstanceResults, error) { + if mock.GetInstancesFunc == nil { + panic("MongoDBMock.GetInstancesFunc: method is nil but MongoDB.GetInstances was just called") + } + callInfo := struct { + Ctx context.Context + States []string + Datasets []string + }{ + Ctx: ctx, + States: states, + Datasets: datasets, + } + lockMongoDBMockGetInstances.Lock() + mock.calls.GetInstances = append(mock.calls.GetInstances, callInfo) + lockMongoDBMockGetInstances.Unlock() + return mock.GetInstancesFunc(ctx, states, datasets) +} + +// GetInstancesCalls gets all the calls that were made to GetInstances. +// Check the length with: +// len(mockedMongoDB.GetInstancesCalls()) +func (mock *MongoDBMock) GetInstancesCalls() []struct { + Ctx context.Context + States []string + Datasets []string +} { + var calls []struct { + Ctx context.Context + States []string + Datasets []string + } + lockMongoDBMockGetInstances.RLock() + calls = mock.calls.GetInstances + lockMongoDBMockGetInstances.RUnlock() + return calls +} + +// GetNextVersion calls GetNextVersionFunc. +func (mock *MongoDBMock) GetNextVersion(datasetID string, editionID string) (int, error) { + if mock.GetNextVersionFunc == nil { + panic("MongoDBMock.GetNextVersionFunc: method is nil but MongoDB.GetNextVersion was just called") + } + callInfo := struct { + DatasetID string + EditionID string + }{ + DatasetID: datasetID, + EditionID: editionID, + } + lockMongoDBMockGetNextVersion.Lock() + mock.calls.GetNextVersion = append(mock.calls.GetNextVersion, callInfo) + lockMongoDBMockGetNextVersion.Unlock() + return mock.GetNextVersionFunc(datasetID, editionID) +} + +// GetNextVersionCalls gets all the calls that were made to GetNextVersion. +// Check the length with: +// len(mockedMongoDB.GetNextVersionCalls()) +func (mock *MongoDBMock) GetNextVersionCalls() []struct { + DatasetID string + EditionID string +} { + var calls []struct { + DatasetID string + EditionID string + } + lockMongoDBMockGetNextVersion.RLock() + calls = mock.calls.GetNextVersion + lockMongoDBMockGetNextVersion.RUnlock() + return calls +} + +// GetUniqueDimensionAndOptions calls GetUniqueDimensionAndOptionsFunc. +func (mock *MongoDBMock) GetUniqueDimensionAndOptions(ID string, dimension string) (*models.DimensionValues, error) { + if mock.GetUniqueDimensionAndOptionsFunc == nil { + panic("MongoDBMock.GetUniqueDimensionAndOptionsFunc: method is nil but MongoDB.GetUniqueDimensionAndOptions was just called") + } + callInfo := struct { + ID string + Dimension string + }{ + ID: ID, + Dimension: dimension, + } + lockMongoDBMockGetUniqueDimensionAndOptions.Lock() + mock.calls.GetUniqueDimensionAndOptions = append(mock.calls.GetUniqueDimensionAndOptions, callInfo) + lockMongoDBMockGetUniqueDimensionAndOptions.Unlock() + return mock.GetUniqueDimensionAndOptionsFunc(ID, dimension) +} + +// GetUniqueDimensionAndOptionsCalls gets all the calls that were made to GetUniqueDimensionAndOptions. +// Check the length with: +// len(mockedMongoDB.GetUniqueDimensionAndOptionsCalls()) +func (mock *MongoDBMock) GetUniqueDimensionAndOptionsCalls() []struct { + ID string + Dimension string +} { + var calls []struct { + ID string + Dimension string + } + lockMongoDBMockGetUniqueDimensionAndOptions.RLock() + calls = mock.calls.GetUniqueDimensionAndOptions + lockMongoDBMockGetUniqueDimensionAndOptions.RUnlock() + return calls +} + +// GetVersion calls GetVersionFunc. +func (mock *MongoDBMock) GetVersion(datasetID string, editionID string, version string, state string) (*models.Version, error) { + if mock.GetVersionFunc == nil { + panic("MongoDBMock.GetVersionFunc: method is nil but MongoDB.GetVersion was just called") + } + callInfo := struct { + DatasetID string + EditionID string + Version string + State string + }{ + DatasetID: datasetID, + EditionID: editionID, + Version: version, + State: state, + } + lockMongoDBMockGetVersion.Lock() + mock.calls.GetVersion = append(mock.calls.GetVersion, callInfo) + lockMongoDBMockGetVersion.Unlock() + return mock.GetVersionFunc(datasetID, editionID, version, state) +} + +// GetVersionCalls gets all the calls that were made to GetVersion. +// Check the length with: +// len(mockedMongoDB.GetVersionCalls()) +func (mock *MongoDBMock) GetVersionCalls() []struct { + DatasetID string + EditionID string + Version string + State string +} { + var calls []struct { + DatasetID string + EditionID string + Version string + State string + } + lockMongoDBMockGetVersion.RLock() + calls = mock.calls.GetVersion + lockMongoDBMockGetVersion.RUnlock() + return calls +} + +// GetVersions calls GetVersionsFunc. +func (mock *MongoDBMock) GetVersions(ctx context.Context, datasetID string, editionID string, state string) (*models.VersionResults, error) { + if mock.GetVersionsFunc == nil { + panic("MongoDBMock.GetVersionsFunc: method is nil but MongoDB.GetVersions was just called") + } + callInfo := struct { + Ctx context.Context + DatasetID string + EditionID string + State string + }{ + Ctx: ctx, + DatasetID: datasetID, + EditionID: editionID, + State: state, + } + lockMongoDBMockGetVersions.Lock() + mock.calls.GetVersions = append(mock.calls.GetVersions, callInfo) + lockMongoDBMockGetVersions.Unlock() + return mock.GetVersionsFunc(ctx, datasetID, editionID, state) +} + +// GetVersionsCalls gets all the calls that were made to GetVersions. +// Check the length with: +// len(mockedMongoDB.GetVersionsCalls()) +func (mock *MongoDBMock) GetVersionsCalls() []struct { + Ctx context.Context + DatasetID string + EditionID string + State string +} { + var calls []struct { + Ctx context.Context + DatasetID string + EditionID string + State string + } + lockMongoDBMockGetVersions.RLock() + calls = mock.calls.GetVersions + lockMongoDBMockGetVersions.RUnlock() + return calls +} + +// UpdateBuildHierarchyTaskState calls UpdateBuildHierarchyTaskStateFunc. +func (mock *MongoDBMock) UpdateBuildHierarchyTaskState(id string, dimension string, state string) error { + if mock.UpdateBuildHierarchyTaskStateFunc == nil { + panic("MongoDBMock.UpdateBuildHierarchyTaskStateFunc: method is nil but MongoDB.UpdateBuildHierarchyTaskState was just called") + } + callInfo := struct { + ID string + Dimension string + State string + }{ + ID: id, + Dimension: dimension, + State: state, + } + lockMongoDBMockUpdateBuildHierarchyTaskState.Lock() + mock.calls.UpdateBuildHierarchyTaskState = append(mock.calls.UpdateBuildHierarchyTaskState, callInfo) + lockMongoDBMockUpdateBuildHierarchyTaskState.Unlock() + return mock.UpdateBuildHierarchyTaskStateFunc(id, dimension, state) +} + +// UpdateBuildHierarchyTaskStateCalls gets all the calls that were made to UpdateBuildHierarchyTaskState. +// Check the length with: +// len(mockedMongoDB.UpdateBuildHierarchyTaskStateCalls()) +func (mock *MongoDBMock) UpdateBuildHierarchyTaskStateCalls() []struct { + ID string + Dimension string + State string +} { + var calls []struct { + ID string + Dimension string + State string + } + lockMongoDBMockUpdateBuildHierarchyTaskState.RLock() + calls = mock.calls.UpdateBuildHierarchyTaskState + lockMongoDBMockUpdateBuildHierarchyTaskState.RUnlock() + return calls +} + +// UpdateBuildSearchTaskState calls UpdateBuildSearchTaskStateFunc. +func (mock *MongoDBMock) UpdateBuildSearchTaskState(id string, dimension string, state string) error { + if mock.UpdateBuildSearchTaskStateFunc == nil { + panic("MongoDBMock.UpdateBuildSearchTaskStateFunc: method is nil but MongoDB.UpdateBuildSearchTaskState was just called") + } + callInfo := struct { + ID string + Dimension string + State string + }{ + ID: id, + Dimension: dimension, + State: state, + } + lockMongoDBMockUpdateBuildSearchTaskState.Lock() + mock.calls.UpdateBuildSearchTaskState = append(mock.calls.UpdateBuildSearchTaskState, callInfo) + lockMongoDBMockUpdateBuildSearchTaskState.Unlock() + return mock.UpdateBuildSearchTaskStateFunc(id, dimension, state) +} + +// UpdateBuildSearchTaskStateCalls gets all the calls that were made to UpdateBuildSearchTaskState. +// Check the length with: +// len(mockedMongoDB.UpdateBuildSearchTaskStateCalls()) +func (mock *MongoDBMock) UpdateBuildSearchTaskStateCalls() []struct { + ID string + Dimension string + State string +} { + var calls []struct { + ID string + Dimension string + State string + } + lockMongoDBMockUpdateBuildSearchTaskState.RLock() + calls = mock.calls.UpdateBuildSearchTaskState + lockMongoDBMockUpdateBuildSearchTaskState.RUnlock() + return calls +} + +// UpdateDataset calls UpdateDatasetFunc. +func (mock *MongoDBMock) UpdateDataset(ctx context.Context, ID string, dataset *models.Dataset, currentState string) error { + if mock.UpdateDatasetFunc == nil { + panic("MongoDBMock.UpdateDatasetFunc: method is nil but MongoDB.UpdateDataset was just called") + } + callInfo := struct { + Ctx context.Context + ID string + Dataset *models.Dataset + CurrentState string + }{ + Ctx: ctx, + ID: ID, + Dataset: dataset, + CurrentState: currentState, + } + lockMongoDBMockUpdateDataset.Lock() + mock.calls.UpdateDataset = append(mock.calls.UpdateDataset, callInfo) + lockMongoDBMockUpdateDataset.Unlock() + return mock.UpdateDatasetFunc(ctx, ID, dataset, currentState) +} + +// UpdateDatasetCalls gets all the calls that were made to UpdateDataset. +// Check the length with: +// len(mockedMongoDB.UpdateDatasetCalls()) +func (mock *MongoDBMock) UpdateDatasetCalls() []struct { + Ctx context.Context + ID string + Dataset *models.Dataset + CurrentState string +} { + var calls []struct { + Ctx context.Context + ID string + Dataset *models.Dataset + CurrentState string + } + lockMongoDBMockUpdateDataset.RLock() + calls = mock.calls.UpdateDataset + lockMongoDBMockUpdateDataset.RUnlock() + return calls +} + +// UpdateDatasetWithAssociation calls UpdateDatasetWithAssociationFunc. +func (mock *MongoDBMock) UpdateDatasetWithAssociation(ID string, state string, version *models.Version) error { + if mock.UpdateDatasetWithAssociationFunc == nil { + panic("MongoDBMock.UpdateDatasetWithAssociationFunc: method is nil but MongoDB.UpdateDatasetWithAssociation was just called") + } + callInfo := struct { + ID string + State string + Version *models.Version + }{ + ID: ID, + State: state, + Version: version, + } + lockMongoDBMockUpdateDatasetWithAssociation.Lock() + mock.calls.UpdateDatasetWithAssociation = append(mock.calls.UpdateDatasetWithAssociation, callInfo) + lockMongoDBMockUpdateDatasetWithAssociation.Unlock() + return mock.UpdateDatasetWithAssociationFunc(ID, state, version) +} + +// UpdateDatasetWithAssociationCalls gets all the calls that were made to UpdateDatasetWithAssociation. +// Check the length with: +// len(mockedMongoDB.UpdateDatasetWithAssociationCalls()) +func (mock *MongoDBMock) UpdateDatasetWithAssociationCalls() []struct { + ID string + State string + Version *models.Version +} { + var calls []struct { + ID string + State string + Version *models.Version + } + lockMongoDBMockUpdateDatasetWithAssociation.RLock() + calls = mock.calls.UpdateDatasetWithAssociation + lockMongoDBMockUpdateDatasetWithAssociation.RUnlock() + return calls +} + +// UpdateDimensionNodeID calls UpdateDimensionNodeIDFunc. +func (mock *MongoDBMock) UpdateDimensionNodeID(dimension *models.DimensionOption) error { + if mock.UpdateDimensionNodeIDFunc == nil { + panic("MongoDBMock.UpdateDimensionNodeIDFunc: method is nil but MongoDB.UpdateDimensionNodeID was just called") + } + callInfo := struct { + Dimension *models.DimensionOption + }{ + Dimension: dimension, + } + lockMongoDBMockUpdateDimensionNodeID.Lock() + mock.calls.UpdateDimensionNodeID = append(mock.calls.UpdateDimensionNodeID, callInfo) + lockMongoDBMockUpdateDimensionNodeID.Unlock() + return mock.UpdateDimensionNodeIDFunc(dimension) +} + +// UpdateDimensionNodeIDCalls gets all the calls that were made to UpdateDimensionNodeID. +// Check the length with: +// len(mockedMongoDB.UpdateDimensionNodeIDCalls()) +func (mock *MongoDBMock) UpdateDimensionNodeIDCalls() []struct { + Dimension *models.DimensionOption +} { + var calls []struct { + Dimension *models.DimensionOption + } + lockMongoDBMockUpdateDimensionNodeID.RLock() + calls = mock.calls.UpdateDimensionNodeID + lockMongoDBMockUpdateDimensionNodeID.RUnlock() + return calls +} + +// UpdateImportObservationsTaskState calls UpdateImportObservationsTaskStateFunc. +func (mock *MongoDBMock) UpdateImportObservationsTaskState(id string, state string) error { + if mock.UpdateImportObservationsTaskStateFunc == nil { + panic("MongoDBMock.UpdateImportObservationsTaskStateFunc: method is nil but MongoDB.UpdateImportObservationsTaskState was just called") + } + callInfo := struct { + ID string + State string + }{ + ID: id, + State: state, + } + lockMongoDBMockUpdateImportObservationsTaskState.Lock() + mock.calls.UpdateImportObservationsTaskState = append(mock.calls.UpdateImportObservationsTaskState, callInfo) + lockMongoDBMockUpdateImportObservationsTaskState.Unlock() + return mock.UpdateImportObservationsTaskStateFunc(id, state) +} + +// UpdateImportObservationsTaskStateCalls gets all the calls that were made to UpdateImportObservationsTaskState. +// Check the length with: +// len(mockedMongoDB.UpdateImportObservationsTaskStateCalls()) +func (mock *MongoDBMock) UpdateImportObservationsTaskStateCalls() []struct { + ID string + State string +} { + var calls []struct { + ID string + State string + } + lockMongoDBMockUpdateImportObservationsTaskState.RLock() + calls = mock.calls.UpdateImportObservationsTaskState + lockMongoDBMockUpdateImportObservationsTaskState.RUnlock() + return calls +} + +// UpdateInstance calls UpdateInstanceFunc. +func (mock *MongoDBMock) UpdateInstance(ctx context.Context, ID string, instance *models.Instance) error { + if mock.UpdateInstanceFunc == nil { + panic("MongoDBMock.UpdateInstanceFunc: method is nil but MongoDB.UpdateInstance was just called") + } + callInfo := struct { + Ctx context.Context + ID string + Instance *models.Instance + }{ + Ctx: ctx, + ID: ID, + Instance: instance, + } + lockMongoDBMockUpdateInstance.Lock() + mock.calls.UpdateInstance = append(mock.calls.UpdateInstance, callInfo) + lockMongoDBMockUpdateInstance.Unlock() + return mock.UpdateInstanceFunc(ctx, ID, instance) +} + +// UpdateInstanceCalls gets all the calls that were made to UpdateInstance. +// Check the length with: +// len(mockedMongoDB.UpdateInstanceCalls()) +func (mock *MongoDBMock) UpdateInstanceCalls() []struct { + Ctx context.Context + ID string + Instance *models.Instance +} { + var calls []struct { + Ctx context.Context + ID string + Instance *models.Instance + } + lockMongoDBMockUpdateInstance.RLock() + calls = mock.calls.UpdateInstance + lockMongoDBMockUpdateInstance.RUnlock() + return calls +} + +// UpdateObservationInserted calls UpdateObservationInsertedFunc. +func (mock *MongoDBMock) UpdateObservationInserted(ID string, observationInserted int64) error { + if mock.UpdateObservationInsertedFunc == nil { + panic("MongoDBMock.UpdateObservationInsertedFunc: method is nil but MongoDB.UpdateObservationInserted was just called") + } + callInfo := struct { + ID string + ObservationInserted int64 + }{ + ID: ID, + ObservationInserted: observationInserted, + } + lockMongoDBMockUpdateObservationInserted.Lock() + mock.calls.UpdateObservationInserted = append(mock.calls.UpdateObservationInserted, callInfo) + lockMongoDBMockUpdateObservationInserted.Unlock() + return mock.UpdateObservationInsertedFunc(ID, observationInserted) +} + +// UpdateObservationInsertedCalls gets all the calls that were made to UpdateObservationInserted. +// Check the length with: +// len(mockedMongoDB.UpdateObservationInsertedCalls()) +func (mock *MongoDBMock) UpdateObservationInsertedCalls() []struct { + ID string + ObservationInserted int64 +} { + var calls []struct { + ID string + ObservationInserted int64 + } + lockMongoDBMockUpdateObservationInserted.RLock() + calls = mock.calls.UpdateObservationInserted + lockMongoDBMockUpdateObservationInserted.RUnlock() + return calls +} + +// UpdateVersion calls UpdateVersionFunc. +func (mock *MongoDBMock) UpdateVersion(ID string, version *models.Version) error { + if mock.UpdateVersionFunc == nil { + panic("MongoDBMock.UpdateVersionFunc: method is nil but MongoDB.UpdateVersion was just called") + } + callInfo := struct { + ID string + Version *models.Version + }{ + ID: ID, + Version: version, + } + lockMongoDBMockUpdateVersion.Lock() + mock.calls.UpdateVersion = append(mock.calls.UpdateVersion, callInfo) + lockMongoDBMockUpdateVersion.Unlock() + return mock.UpdateVersionFunc(ID, version) +} + +// UpdateVersionCalls gets all the calls that were made to UpdateVersion. +// Check the length with: +// len(mockedMongoDB.UpdateVersionCalls()) +func (mock *MongoDBMock) UpdateVersionCalls() []struct { + ID string + Version *models.Version +} { + var calls []struct { + ID string + Version *models.Version + } + lockMongoDBMockUpdateVersion.RLock() + calls = mock.calls.UpdateVersion + lockMongoDBMockUpdateVersion.RUnlock() + return calls +} + +// UpsertContact calls UpsertContactFunc. +func (mock *MongoDBMock) UpsertContact(ID string, update interface{}) error { + if mock.UpsertContactFunc == nil { + panic("MongoDBMock.UpsertContactFunc: method is nil but MongoDB.UpsertContact was just called") + } + callInfo := struct { + ID string + Update interface{} + }{ + ID: ID, + Update: update, + } + lockMongoDBMockUpsertContact.Lock() + mock.calls.UpsertContact = append(mock.calls.UpsertContact, callInfo) + lockMongoDBMockUpsertContact.Unlock() + return mock.UpsertContactFunc(ID, update) +} + +// UpsertContactCalls gets all the calls that were made to UpsertContact. +// Check the length with: +// len(mockedMongoDB.UpsertContactCalls()) +func (mock *MongoDBMock) UpsertContactCalls() []struct { + ID string + Update interface{} +} { + var calls []struct { + ID string + Update interface{} + } + lockMongoDBMockUpsertContact.RLock() + calls = mock.calls.UpsertContact + lockMongoDBMockUpsertContact.RUnlock() + return calls +} + +// UpsertDataset calls UpsertDatasetFunc. +func (mock *MongoDBMock) UpsertDataset(ID string, datasetDoc *models.DatasetUpdate) error { + if mock.UpsertDatasetFunc == nil { + panic("MongoDBMock.UpsertDatasetFunc: method is nil but MongoDB.UpsertDataset was just called") + } + callInfo := struct { + ID string + DatasetDoc *models.DatasetUpdate + }{ + ID: ID, + DatasetDoc: datasetDoc, + } + lockMongoDBMockUpsertDataset.Lock() + mock.calls.UpsertDataset = append(mock.calls.UpsertDataset, callInfo) + lockMongoDBMockUpsertDataset.Unlock() + return mock.UpsertDatasetFunc(ID, datasetDoc) +} + +// UpsertDatasetCalls gets all the calls that were made to UpsertDataset. +// Check the length with: +// len(mockedMongoDB.UpsertDatasetCalls()) +func (mock *MongoDBMock) UpsertDatasetCalls() []struct { + ID string + DatasetDoc *models.DatasetUpdate +} { + var calls []struct { + ID string + DatasetDoc *models.DatasetUpdate + } + lockMongoDBMockUpsertDataset.RLock() + calls = mock.calls.UpsertDataset + lockMongoDBMockUpsertDataset.RUnlock() + return calls +} + +// UpsertEdition calls UpsertEditionFunc. +func (mock *MongoDBMock) UpsertEdition(datasetID string, edition string, editionDoc *models.EditionUpdate) error { + if mock.UpsertEditionFunc == nil { + panic("MongoDBMock.UpsertEditionFunc: method is nil but MongoDB.UpsertEdition was just called") + } + callInfo := struct { + DatasetID string + Edition string + EditionDoc *models.EditionUpdate + }{ + DatasetID: datasetID, + Edition: edition, + EditionDoc: editionDoc, + } + lockMongoDBMockUpsertEdition.Lock() + mock.calls.UpsertEdition = append(mock.calls.UpsertEdition, callInfo) + lockMongoDBMockUpsertEdition.Unlock() + return mock.UpsertEditionFunc(datasetID, edition, editionDoc) +} + +// UpsertEditionCalls gets all the calls that were made to UpsertEdition. +// Check the length with: +// len(mockedMongoDB.UpsertEditionCalls()) +func (mock *MongoDBMock) UpsertEditionCalls() []struct { + DatasetID string + Edition string + EditionDoc *models.EditionUpdate +} { + var calls []struct { + DatasetID string + Edition string + EditionDoc *models.EditionUpdate + } + lockMongoDBMockUpsertEdition.RLock() + calls = mock.calls.UpsertEdition + lockMongoDBMockUpsertEdition.RUnlock() + return calls +} + +// UpsertVersion calls UpsertVersionFunc. +func (mock *MongoDBMock) UpsertVersion(ID string, versionDoc *models.Version) error { + if mock.UpsertVersionFunc == nil { + panic("MongoDBMock.UpsertVersionFunc: method is nil but MongoDB.UpsertVersion was just called") + } + callInfo := struct { + ID string + VersionDoc *models.Version + }{ + ID: ID, + VersionDoc: versionDoc, + } + lockMongoDBMockUpsertVersion.Lock() + mock.calls.UpsertVersion = append(mock.calls.UpsertVersion, callInfo) + lockMongoDBMockUpsertVersion.Unlock() + return mock.UpsertVersionFunc(ID, versionDoc) +} + +// UpsertVersionCalls gets all the calls that were made to UpsertVersion. +// Check the length with: +// len(mockedMongoDB.UpsertVersionCalls()) +func (mock *MongoDBMock) UpsertVersionCalls() []struct { + ID string + VersionDoc *models.Version +} { + var calls []struct { + ID string + VersionDoc *models.Version + } + lockMongoDBMockUpsertVersion.RLock() + calls = mock.calls.UpsertVersion + lockMongoDBMockUpsertVersion.RUnlock() + return calls +} From a90ddde7e366f4ce6f98b8b1e3728dcf971c8849 Mon Sep 17 00:00:00 2001 From: David Subiros Date: Tue, 1 Sep 2020 15:12:04 +0200 Subject: [PATCH 07/13] Removed old code and update dependencies --- api/api.go | 14 +------------- api/dimensions.go | 5 ----- go.mod | 6 +----- go.sum | 16 ++++++++++++++++ 4 files changed, 18 insertions(+), 23 deletions(-) diff --git a/api/api.go b/api/api.go index 9e9b3cd0..19ac5086 100644 --- a/api/api.go +++ b/api/api.go @@ -15,14 +15,11 @@ import ( "github.com/ONSdigital/dp-dataset-api/store" "github.com/ONSdigital/dp-dataset-api/url" dphandlers "github.com/ONSdigital/dp-net/handlers" - dphttp "github.com/ONSdigital/dp-net/http" dprequest "github.com/ONSdigital/dp-net/request" "github.com/ONSdigital/log.go/log" "github.com/gorilla/mux" ) -var httpServer *dphttp.Server - const ( downloadServiceToken = "X-Download-Service-Token" @@ -363,7 +360,7 @@ func (api *DatasetAPI) enablePrivateDimensionsEndpoints(dimensionAPI *dimension. } // isAuthenticated wraps a http handler func in another http handler func that checks the caller is authenticated to -// perform the requested action action. action is the audit event name, handler is the http.HandlerFunc to wrap in an +// perform the requested action. action is the audit event name, handler is the http.HandlerFunc to wrap in an // authentication check. The wrapped handler is only called is the caller is authenticated func (api *DatasetAPI) isAuthenticated(action string, handler http.HandlerFunc) http.HandlerFunc { return dphandlers.CheckIdentity(handler) @@ -447,12 +444,3 @@ func (api *DatasetAPI) authenticate(r *http.Request, logData log.Data) bool { func setJSONContentType(w http.ResponseWriter) { w.Header().Set("Content-Type", "application/json") } - -// Close represents the graceful shutting down of the http server -func Close(ctx context.Context) error { - if err := httpServer.Shutdown(ctx); err != nil { - return err - } - log.Event(ctx, "graceful shutdown of http server complete", log.INFO) - return nil -} diff --git a/api/dimensions.go b/api/dimensions.go index 3ee7791c..b405d64c 100644 --- a/api/dimensions.go +++ b/api/dimensions.go @@ -5,11 +5,9 @@ import ( "encoding/json" "fmt" "net/http" - "strconv" errs "github.com/ONSdigital/dp-dataset-api/apierrors" "github.com/ONSdigital/dp-dataset-api/models" - dprequest "github.com/ONSdigital/dp-net/request" "github.com/ONSdigital/log.go/log" "github.com/globalsign/mgo/bson" "github.com/gorilla/mux" @@ -134,10 +132,7 @@ func (api *DatasetAPI) getDimensionOptions(w http.ResponseWriter, r *http.Reques dimension := vars["dimension"] logData := log.Data{"dataset_id": datasetID, "edition": edition, "version": versionID, "dimension": dimension, "func": "getDimensionOptions"} - auditParams := dprequest.Params{"dataset_id": datasetID, "edition": edition, "version": versionID, "dimension": dimension} - authorised := api.authenticate(r, logData) - auditParams["authorised"] = strconv.FormatBool(authorised) var state string if !authorised { diff --git a/go.mod b/go.mod index 0b075d4f..59156f49 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/ONSdigital/dp-healthcheck v1.0.5 github.com/ONSdigital/dp-kafka v1.1.7 github.com/ONSdigital/dp-mongodb v1.4.0 - github.com/ONSdigital/dp-net v1.0.7 + github.com/ONSdigital/dp-net v1.0.8-0.20200901091958-2df9a102ca3d github.com/ONSdigital/go-ns v0.0.0-20200205115900-a11716f93bad github.com/ONSdigital/log.go v1.0.1 github.com/frankban/quicktest v1.9.0 // indirect @@ -30,7 +30,3 @@ require ( golang.org/x/text v0.3.3 // indirect gopkg.in/avro.v0 v0.0.0-20171217001914-a730b5802183 // indirect ) - -replace github.com/ONSdigital/dp-net => ../dp-net - -replace github.com/ONSdigital/dp-api-clients-go => ../dp-api-clients-go diff --git a/go.sum b/go.sum index fa90e180..4e002132 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,14 @@ +github.com/ONSdigital/dp-api-clients-go v1.1.0/go.mod h1:9lqor0I7caCnRWr04gU/r7x5dqxgoODob8L48q+cE4E= +github.com/ONSdigital/dp-api-clients-go v1.9.0/go.mod h1:SM0b/NXDWndJ9EulmAGdfDY4DxPxK+pNsP8eZlIWiqM= +github.com/ONSdigital/dp-api-clients-go v1.28.0 h1:ExIUlHC6uBdBlFwt/gAI0ApSzpyigy0NWJFK3XCwSVc= +github.com/ONSdigital/dp-api-clients-go v1.28.0/go.mod h1:iyJy6uRL4B6OYOJA0XMr5UHt6+Q8XmN9uwmURO+9Oj4= github.com/ONSdigital/dp-authorisation v0.1.0 h1:HzYwJdvk7ZAeB56KMAH6MP5+5uZuuJnEyGq6CViDoCg= github.com/ONSdigital/dp-authorisation v0.1.0/go.mod h1:rT81tcvWto5/cUWUFd0Q6gTqBoRfQmD6Qp0sq7FyiMg= github.com/ONSdigital/dp-frontend-models v1.1.0/go.mod h1:TT96P7Mi69N3Tc/jFNdbjiwG4GAaMjP26HLotFQ6BPw= github.com/ONSdigital/dp-graph/v2 v2.1.3 h1:7BJsRE9FDf7tFtJvI5v7RX94q4BAbiJFDWpxQCNfM18= github.com/ONSdigital/dp-graph/v2 v2.1.3/go.mod h1:6C59rOY0qBKblczkQrJZZKa8ZLR3yKkyunSCeIUavtU= +github.com/ONSdigital/dp-healthcheck v0.0.0-20200131122546-9db6d3f0494e/go.mod h1:zighxZ/0m5u7zo0eAr8XFlA+Dz2ic7A1vna6YXvhCjQ= +github.com/ONSdigital/dp-healthcheck v1.0.0/go.mod h1:zighxZ/0m5u7zo0eAr8XFlA+Dz2ic7A1vna6YXvhCjQ= github.com/ONSdigital/dp-healthcheck v1.0.2 h1:N8SzpYzdixVgJS9NMzTBA2RZ2bi3Am1wE5F8ROEpTYw= github.com/ONSdigital/dp-healthcheck v1.0.2/go.mod h1:zighxZ/0m5u7zo0eAr8XFlA+Dz2ic7A1vna6YXvhCjQ= github.com/ONSdigital/dp-healthcheck v1.0.5 h1:DXnohGIqXaLLeYGdaGOhgkZjAbWMNoLAjQ3EgZeMT3M= @@ -13,6 +19,12 @@ github.com/ONSdigital/dp-mocking v0.0.0-20190905163309-fee2702ad1b9 h1:+WXVfTDyW github.com/ONSdigital/dp-mocking v0.0.0-20190905163309-fee2702ad1b9/go.mod h1:BcIRgitUju//qgNePRBmNjATarTtynAgc0yV29VpLEk= github.com/ONSdigital/dp-mongodb v1.4.0 h1:nDyRgGLfLYkQnS1SZgpq9y3BD87IqfjihZERn9pudy0= github.com/ONSdigital/dp-mongodb v1.4.0/go.mod h1:kJRKmL4JUub+DGlWGeqaV8D13Jaj9939UEaPXfSIdVg= +github.com/ONSdigital/dp-net v1.0.5-0.20200805082802-e518bc287596/go.mod h1:wDVhk2pYosQ1q6PXxuFIRYhYk2XX5+1CeRRnXpSczPY= +github.com/ONSdigital/dp-net v1.0.5-0.20200805145012-9227a11caddb/go.mod h1:MrSZwDUvp8u1VJEqa+36Gwq4E7/DdceW+BDCvGes6Cs= +github.com/ONSdigital/dp-net v1.0.5-0.20200805150805-cac050646ab5/go.mod h1:de3LB9tedE0tObBwa12dUOt5rvTW4qQkF5rXtt4b6CE= +github.com/ONSdigital/dp-net v1.0.7/go.mod h1:1QFzx32FwPKD2lgZI6MtcsUXritsBdJihlzIWDrQ/gc= +github.com/ONSdigital/dp-net v1.0.8-0.20200901091958-2df9a102ca3d h1:oPcqBxBSYs0kjnNdkzf9buxjuRyX9sOCDiSpsu3iz4U= +github.com/ONSdigital/dp-net v1.0.8-0.20200901091958-2df9a102ca3d/go.mod h1:2lvIKOlD4T3BjWQwjHhBUO2UNWDk82u/+mHRn0R3C9A= github.com/ONSdigital/dp-rchttp v0.0.0-20190919143000-bb5699e6fd59/go.mod h1:KkW68U3FPuivW4ogi9L8CPKNj9ZxGko4qcUY7KoAAkQ= github.com/ONSdigital/dp-rchttp v0.0.0-20200114090501-463a529590e8 h1:MWIHCr/ud5ur9elhfvKtSjMJInqf3iUY8F4J27qGQPA= github.com/ONSdigital/dp-rchttp v0.0.0-20200114090501-463a529590e8/go.mod h1:821jZtK0oBsV8hjIkNr8vhAWuv0FxJBPJuAHa2B70Gk= @@ -30,6 +42,8 @@ github.com/ONSdigital/gremgo-neptune v1.0.0/go.mod h1:GZz/N6xjNY+EN0x4FmfBDrM73R github.com/ONSdigital/log.go v0.0.0-20191127134126-2a610b254f20/go.mod h1:BD7D8FWP1fzwUWsrCopEG72jl9cchCaVNIGSz6YvL+Y= github.com/ONSdigital/log.go v1.0.0 h1:hZQTuitFv4nSrpzMhpGvafUC5/8xMVnLI0CWe1rAJNc= github.com/ONSdigital/log.go v1.0.0/go.mod h1:UnGu9Q14gNC+kz0DOkdnLYGoqugCvnokHBRBxFRpVoQ= +github.com/ONSdigital/log.go v1.0.1-0.20200805084515-ee61165ea36a/go.mod h1:dDnQATFXCBOknvj6ZQuKfmDhbOWf3e8mtV+dPEfWJqs= +github.com/ONSdigital/log.go v1.0.1-0.20200805145532-1f25087a0744/go.mod h1:y4E9MYC+cV9VfjRD0UBGj8PA7H3wABqQi87/ejrDhYc= github.com/ONSdigital/log.go v1.0.1 h1:SZ5wRZAwlt2jQUZ9AUzBB/PL+iG15KapfQpJUdA18/4= github.com/ONSdigital/log.go v1.0.1/go.mod h1:dIwSXuvFB5EsZG5x44JhsXZKMd80zlb0DZxmiAtpL4M= github.com/Shopify/sarama v1.24.1 h1:svn9vfN3R1Hz21WR2Gj0VW9ehaDGkiOS+VqlIcZOkMI= @@ -68,6 +82,7 @@ github.com/go-avro/avro v0.0.0-20171219232920-444163702c11/go.mod h1:kxj6THYP0dm github.com/go-test/deep v1.0.6/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8= github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE= github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -179,6 +194,7 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 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-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From 72ab8e33a7275256c27fe07af95a37d7feb2a889 Mon Sep 17 00:00:00 2001 From: David Subiros Date: Tue, 1 Sep 2020 15:41:17 +0200 Subject: [PATCH 08/13] Removed remaining audit comments, Error definitions and redundant test --- api/api.go | 4 ++-- apierrors/errors.go | 1 - dimension/dimension.go | 2 +- dimension/helpers_test.go | 11 ----------- instance/event.go | 2 +- instance/instance.go | 4 ---- instance/instance_external_test.go | 2 -- 7 files changed, 4 insertions(+), 22 deletions(-) diff --git a/api/api.go b/api/api.go index 19ac5086..2212e11c 100644 --- a/api/api.go +++ b/api/api.go @@ -23,7 +23,7 @@ import ( const ( downloadServiceToken = "X-Download-Service-Token" - // audit actions + // actions addDatasetAction = "addDataset" deleteDatasetAction = "deleteDataset" getDatasetsAction = "getDatasets" @@ -360,7 +360,7 @@ func (api *DatasetAPI) enablePrivateDimensionsEndpoints(dimensionAPI *dimension. } // isAuthenticated wraps a http handler func in another http handler func that checks the caller is authenticated to -// perform the requested action. action is the audit event name, handler is the http.HandlerFunc to wrap in an +// perform the requested action. action is the event name, handler is the http.HandlerFunc to wrap in an // authentication check. The wrapped handler is only called is the caller is authenticated func (api *DatasetAPI) isAuthenticated(action string, handler http.HandlerFunc) http.HandlerFunc { return dphandlers.CheckIdentity(handler) diff --git a/apierrors/errors.go b/apierrors/errors.go index 62fbd5c3..03e53acd 100644 --- a/apierrors/errors.go +++ b/apierrors/errors.go @@ -8,7 +8,6 @@ import ( var ( ErrAddDatasetAlreadyExists = errors.New("forbidden - dataset already exists") ErrAddUpdateDatasetBadRequest = errors.New("failed to parse json body") - ErrAuditActionAttemptedFailure = errors.New("internal server error") ErrConflictUpdatingInstance = errors.New("conflict updating instance resource") ErrDatasetNotFound = errors.New("dataset not found") ErrDeleteDatasetNotFound = errors.New("dataset not found") diff --git a/dimension/dimension.go b/dimension/dimension.go index 1dfc82e1..d9b639fa 100644 --- a/dimension/dimension.go +++ b/dimension/dimension.go @@ -17,7 +17,7 @@ type Store struct { store.Storer } -// List of audit actions for dimensions +// List of actions for dimensions const ( GetDimensions = "getInstanceDimensions" GetUniqueDimensionAndOptionsAction = "getInstanceUniqueDimensionAndOptions" diff --git a/dimension/helpers_test.go b/dimension/helpers_test.go index c25c1f18..54b3643f 100644 --- a/dimension/helpers_test.go +++ b/dimension/helpers_test.go @@ -86,15 +86,4 @@ func TestHandleDimensionErr(t *testing.T) { So(w.Code, ShouldEqual, http.StatusInternalServerError) So(w.Body.String(), ShouldContainSubstring, dimensionError.Error()) }) - - Convey("Correctly handle failure to audit", t, func() { - w := httptest.NewRecorder() - dimensionError := errs.ErrAuditActionAttemptedFailure - logData := log.Data{"test": "audit failure"} - - handleDimensionErr(ctx, w, dimensionError, logData) - - So(w.Code, ShouldEqual, http.StatusInternalServerError) - So(w.Body.String(), ShouldContainSubstring, errs.ErrInternalServer.Error()) - }) } diff --git a/instance/event.go b/instance/event.go index 91678c83..148c58e1 100644 --- a/instance/event.go +++ b/instance/event.go @@ -12,7 +12,7 @@ import ( "github.com/gorilla/mux" ) -// AddInstanceEventAction represents the audit action to add event +// AddInstanceEventAction represents the action to add event const AddInstanceEventAction = "addInstanceEvent" func unmarshalEvent(reader io.Reader) (*models.Event, error) { diff --git a/instance/instance.go b/instance/instance.go index 4cfdea56..2dca5bf9 100644 --- a/instance/instance.go +++ b/instance/instance.go @@ -14,7 +14,6 @@ import ( "github.com/ONSdigital/dp-dataset-api/models" "github.com/ONSdigital/dp-dataset-api/store" dphttp "github.com/ONSdigital/dp-net/http" - dprequest "github.com/ONSdigital/dp-net/request" "github.com/ONSdigital/log.go/log" "github.com/gorilla/mux" "github.com/pkg/errors" @@ -139,7 +138,6 @@ func (s *Store) Get(w http.ResponseWriter, r *http.Request) { return b, nil }() - log.Event(ctx, "get instance: auditing outcome", log.INFO, logData) if err != nil { handleInstanceErr(ctx, err, w, logData) return @@ -156,7 +154,6 @@ func (s *Store) Add(w http.ResponseWriter, r *http.Request) { ctx := r.Context() logData := log.Data{"action": AddInstanceAction} - auditParams := dprequest.Params{} log.Event(ctx, "add instance", log.INFO, logData) @@ -167,7 +164,6 @@ func (s *Store) Add(w http.ResponseWriter, r *http.Request) { } logData["instance_id"] = instance.InstanceID - auditParams["instance_id"] = instance.InstanceID instance.Links.Self = &models.LinkObject{ HRef: fmt.Sprintf("%s/instances/%s", s.Host, instance.InstanceID), diff --git a/instance/instance_external_test.go b/instance/instance_external_test.go index 7093f243..07249b6d 100644 --- a/instance/instance_external_test.go +++ b/instance/instance_external_test.go @@ -2,7 +2,6 @@ package instance_test import ( "context" - "errors" "io" "net/http" "net/http/httptest" @@ -26,7 +25,6 @@ import ( const host = "http://localhost:8080" var ( - errAudit = errors.New("auditing error") mu sync.Mutex testContext = context.Background() ) From ccefff8def8ea64883af785a681af32dbb7746b1 Mon Sep 17 00:00:00 2001 From: David Subiros Date: Tue, 1 Sep 2020 17:16:28 +0200 Subject: [PATCH 09/13] Made service fields private --- main.go | 4 +- service/service.go | 139 ++++++++++++++++++++++++---------------- service/service_test.go | 63 +++++++++--------- 3 files changed, 117 insertions(+), 89 deletions(-) diff --git a/main.go b/main.go index 5819df6a..e02b54f5 100644 --- a/main.go +++ b/main.go @@ -50,8 +50,8 @@ func run(ctx context.Context) error { log.Event(ctx, "config on startup", log.INFO, log.Data{"config": cfg, "build_time": BuildTime, "git-commit": GitCommit}) // Run the service - svc, err := service.Run(ctx, cfg, svcList, BuildTime, GitCommit, Version, svcErrors) - if err != nil { + svc := service.New(cfg, svcList) + if err := svc.Run(ctx, BuildTime, GitCommit, Version, svcErrors); err != nil { return errors.Wrap(err, "running service failed") } diff --git a/service/service.go b/service/service.go index d6907a83..8b625d21 100644 --- a/service/service.go +++ b/service/service.go @@ -33,94 +33,123 @@ type DatsetAPIStore struct { // Service contains all the configs, server and clients to run the Dataset API type Service struct { - Config *config.Configuration - ServiceList *ExternalServiceList - GraphDB store.GraphDB - MongoDB store.MongoDB - GenerateDownloadsProducer kafka.IProducer + config *config.Configuration + serviceList *ExternalServiceList + graphDB store.GraphDB + mongoDB store.MongoDB + generateDownloadsProducer kafka.IProducer identityClient *clientsidentity.Client - Server HTTPServer - HealthCheck HealthChecker - API *api.DatasetAPI + server HTTPServer + healthCheck HealthChecker + api *api.DatasetAPI } -// Run the service -func Run(ctx context.Context, cfg *config.Configuration, serviceList *ExternalServiceList, buildTime, gitCommit, version string, svcErrors chan error) (svc *Service, err error) { - - svc = &Service{ - Config: cfg, - ServiceList: serviceList, +// New creates a new service +func New(cfg *config.Configuration, serviceList *ExternalServiceList) *Service { + svc := &Service{ + config: cfg, + serviceList: serviceList, } + return svc +} + +// SetServer sets the http server for a service +func (svc *Service) SetServer(server HTTPServer) { + svc.server = server +} + +// SetHealthCheck sets the healthchecker for a service +func (svc *Service) SetHealthCheck(healthCheck HealthChecker) { + svc.healthCheck = healthCheck +} + +// SetDownloadsProducer sets the downloads kafka producer for a service +func (svc *Service) SetDownloadsProducer(producer kafka.IProducer) { + svc.generateDownloadsProducer = producer +} + +// SetMongoDB sets the mongoDB connection for a service +func (svc *Service) SetMongoDB(mongoDB store.MongoDB) { + svc.mongoDB = mongoDB +} + +// SetGraphDB sets the graphDB connection for a service +func (svc *Service) SetGraphDB(graphDB store.GraphDB) { + svc.graphDB = graphDB +} + +// Run the service +func (svc *Service) Run(ctx context.Context, buildTime, gitCommit, version string, svcErrors chan error) (err error) { // Get MongoDB connection - svc.MongoDB, err = serviceList.GetMongoDB(ctx, cfg) + svc.mongoDB, err = svc.serviceList.GetMongoDB(ctx, svc.config) if err != nil { log.Event(ctx, "could not obtain mongo session", log.ERROR, log.Error(err)) - return nil, err + return err } // Get graphDB connection for observation store - if !cfg.EnableObservationEndpoint && !cfg.EnablePrivateEndpoints { + if !svc.config.EnableObservationEndpoint && !svc.config.EnablePrivateEndpoints { log.Event(ctx, "skipping graph DB client creation, because it is not required by the enabled endpoints", log.INFO, log.Data{ - "EnableObservationEndpoint": cfg.EnableObservationEndpoint, - "EnablePrivateEndpoints": cfg.EnablePrivateEndpoints, + "EnableObservationEndpoint": svc.config.EnableObservationEndpoint, + "EnablePrivateEndpoints": svc.config.EnablePrivateEndpoints, }) } else { - svc.GraphDB, err = serviceList.GetGraphDB(ctx) + svc.graphDB, err = svc.serviceList.GetGraphDB(ctx) if err != nil { log.Event(ctx, "failed to initialise graph driver", log.FATAL, log.Error(err)) - return nil, err + return err } } - store := store.DataStore{Backend: DatsetAPIStore{svc.MongoDB, svc.GraphDB}} + store := store.DataStore{Backend: DatsetAPIStore{svc.mongoDB, svc.graphDB}} // Get GenerateDownloads Kafka Producer - svc.GenerateDownloadsProducer, err = serviceList.GetProducer(ctx, cfg) + svc.generateDownloadsProducer, err = svc.serviceList.GetProducer(ctx, svc.config) if err != nil { log.Event(ctx, "could not obtain generate downloads producer", log.FATAL, log.Error(err)) - return nil, err + return err } downloadGenerator := &download.Generator{ - Producer: adapter.NewProducerAdapter(svc.GenerateDownloadsProducer), + Producer: adapter.NewProducerAdapter(svc.generateDownloadsProducer), Marshaller: schema.GenerateDownloadsEvent, } // Get Identity Client (only if private endpoints are enabled) - if cfg.EnablePrivateEndpoints { - svc.identityClient = clientsidentity.New(cfg.ZebedeeURL) + if svc.config.EnablePrivateEndpoints { + svc.identityClient = clientsidentity.New(svc.config.ZebedeeURL) } // Get HealthCheck - svc.HealthCheck, err = serviceList.GetHealthCheck(cfg, buildTime, gitCommit, version) + svc.healthCheck, err = svc.serviceList.GetHealthCheck(svc.config, buildTime, gitCommit, version) if err != nil { log.Event(ctx, "could not instantiate healthcheck", log.FATAL, log.Error(err)) - return nil, err + return err } if err := svc.registerCheckers(ctx); err != nil { - return nil, errors.Wrap(err, "unable to register checkers") + return errors.Wrap(err, "unable to register checkers") } // Get HTTP router and server with middleware r := mux.NewRouter() - m := svc.createMiddleware(cfg) - svc.Server = serviceList.GetHTTPServer(cfg.BindAddr, m.Then(r)) + m := svc.createMiddleware(svc.config) + svc.server = svc.serviceList.GetHTTPServer(svc.config.BindAddr, m.Then(r)) // Create Dataset API - urlBuilder := url.NewBuilder(cfg.WebsiteURL) - datasetPermissions, permissions := getAuthorisationHandlers(ctx, cfg) - svc.API = api.Setup(ctx, cfg, r, store, urlBuilder, downloadGenerator, datasetPermissions, permissions) + urlBuilder := url.NewBuilder(svc.config.WebsiteURL) + datasetPermissions, permissions := getAuthorisationHandlers(ctx, svc.config) + svc.api = api.Setup(ctx, svc.config, r, store, urlBuilder, downloadGenerator, datasetPermissions, permissions) - svc.HealthCheck.Start(ctx) + svc.healthCheck.Start(ctx) // Run the http server in a new go-routine go func() { - if err := svc.Server.ListenAndServe(); err != nil { + if err := svc.server.ListenAndServe(); err != nil { svcErrors <- errors.Wrap(err, "failure in http listen and serve") } }() - return svc, nil + return nil } func getAuthorisationHandlers(ctx context.Context, cfg *config.Configuration) (api.AuthHandler, api.AuthHandler) { @@ -157,7 +186,7 @@ func getAuthorisationHandlers(ctx context.Context, cfg *config.Configuration) (a func (svc *Service) createMiddleware(cfg *config.Configuration) alice.Chain { // healthcheck - healthcheckHandler := newMiddleware(svc.HealthCheck.Handler, "/health") + healthcheckHandler := newMiddleware(svc.healthCheck.Handler, "/health") middleware := alice.New(healthcheckHandler) // Only add the identity middleware when running in publishing. @@ -188,7 +217,7 @@ func newMiddleware(healthcheckHandler func(http.ResponseWriter, *http.Request), // Close gracefully shuts the service down in the required order, with timeout func (svc *Service) Close(ctx context.Context) error { - timeout := svc.Config.GracefulShutdownTimeout + timeout := svc.config.GracefulShutdownTimeout log.Event(ctx, "commencing graceful shutdown", log.Data{"graceful_shutdown_timeout": timeout}, log.INFO) shutdownContext, cancel := context.WithTimeout(ctx, timeout) hasShutdownError := false @@ -198,34 +227,34 @@ func (svc *Service) Close(ctx context.Context) error { defer cancel() // stop healthcheck, as it depends on everything else - if svc.ServiceList.HealthCheck { - svc.HealthCheck.Stop() + if svc.serviceList.HealthCheck { + svc.healthCheck.Stop() } // stop any incoming requests - if err := svc.Server.Shutdown(shutdownContext); err != nil { + if err := svc.server.Shutdown(shutdownContext); err != nil { log.Event(shutdownContext, "failed to shutdown http server", log.Error(err), log.ERROR) hasShutdownError = true } // Close MongoDB (if it exists) - if svc.ServiceList.MongoDB { - if err := svc.MongoDB.Close(shutdownContext); err != nil { + if svc.serviceList.MongoDB { + if err := svc.mongoDB.Close(shutdownContext); err != nil { log.Event(shutdownContext, "failed to close mongo db session", log.ERROR, log.Error(err)) hasShutdownError = true } } // Close GenerateDownloadsProducer (if it exists) - if svc.ServiceList.GenerateDownloadsProducer { + if svc.serviceList.GenerateDownloadsProducer { log.Event(shutdownContext, "closing generated downloads kafka producer", log.INFO, log.Data{"producer": "DimensionExtracted"}) - svc.GenerateDownloadsProducer.Close(shutdownContext) + svc.generateDownloadsProducer.Close(shutdownContext) log.Event(shutdownContext, "closed generated downloads kafka producer", log.INFO, log.Data{"producer": "DimensionExtracted"}) } // Close GraphDB (if it exists) - if svc.ServiceList.Graph { - if err := svc.GraphDB.Close(shutdownContext); err != nil { + if svc.serviceList.Graph { + if err := svc.graphDB.Close(shutdownContext); err != nil { log.Event(shutdownContext, "failed to close graph db", log.ERROR, log.Error(err)) hasShutdownError = true } @@ -256,26 +285,26 @@ func (svc *Service) Close(ctx context.Context) error { func (svc *Service) registerCheckers(ctx context.Context) (err error) { hasErrors := false - if svc.Config.EnablePrivateEndpoints { - if err = svc.HealthCheck.AddCheck("Zebedee", svc.identityClient.Checker); err != nil { + if svc.config.EnablePrivateEndpoints { + if err = svc.healthCheck.AddCheck("Zebedee", svc.identityClient.Checker); err != nil { hasErrors = true log.Event(ctx, "error adding check for zebedeee", log.ERROR, log.Error(err)) } } - if err = svc.HealthCheck.AddCheck("Kafka Generate Downloads Producer", svc.GenerateDownloadsProducer.Checker); err != nil { + if err = svc.healthCheck.AddCheck("Kafka Generate Downloads Producer", svc.generateDownloadsProducer.Checker); err != nil { hasErrors = true log.Event(ctx, "error adding check for kafka downloads producer", log.ERROR, log.Error(err)) } - if err = svc.HealthCheck.AddCheck("Mongo DB", svc.MongoDB.Checker); err != nil { + if err = svc.healthCheck.AddCheck("Mongo DB", svc.mongoDB.Checker); err != nil { hasErrors = true log.Event(ctx, "error adding check for mongo db", log.ERROR, log.Error(err)) } - if svc.Config.EnablePrivateEndpoints || svc.Config.EnableObservationEndpoint { + if svc.config.EnablePrivateEndpoints || svc.config.EnableObservationEndpoint { log.Event(ctx, "adding graph db health check as the private or observation endpoints are enabled", log.INFO) - if err = svc.HealthCheck.AddCheck("Graph DB", svc.GraphDB.Checker); err != nil { + if err = svc.healthCheck.AddCheck("Graph DB", svc.graphDB.Checker); err != nil { hasErrors = true log.Event(ctx, "error adding check for graph db", log.ERROR, log.Error(err)) } diff --git a/service/service_test.go b/service/service_test.go index df342dc1..c3e86ae7 100644 --- a/service/service_test.go +++ b/service/service_test.go @@ -113,7 +113,8 @@ func TestRun(t *testing.T) { } svcErrors := make(chan error, 1) svcList := service.NewServiceList(initMock) - _, err := service.Run(ctx, cfg, svcList, testBuildTime, testGitCommit, testVersion, svcErrors) + svc := service.New(cfg, svcList) + err := svc.Run(ctx, testBuildTime, testGitCommit, testVersion, svcErrors) Convey("Then service Run fails with the same error and the flag is not set. No further initialisations are attempted", func() { So(err, ShouldResemble, errMongo) @@ -131,7 +132,8 @@ func TestRun(t *testing.T) { } svcErrors := make(chan error, 1) svcList := service.NewServiceList(initMock) - _, err := service.Run(ctx, cfg, svcList, testBuildTime, testGitCommit, testVersion, svcErrors) + svc := service.New(cfg, svcList) + err := svc.Run(ctx, testBuildTime, testGitCommit, testVersion, svcErrors) Convey("Then service Run fails with the same error and the flag is not set. No further initialisations are attempted", func() { So(err, ShouldResemble, errGraph) @@ -150,7 +152,8 @@ func TestRun(t *testing.T) { } svcErrors := make(chan error, 1) svcList := service.NewServiceList(initMock) - _, err := service.Run(ctx, cfg, svcList, testBuildTime, testGitCommit, testVersion, svcErrors) + svc := service.New(cfg, svcList) + err := svc.Run(ctx, testBuildTime, testGitCommit, testVersion, svcErrors) Convey("Then service Run fails with the same error and the flag is not set. No further initialisations are attempted", func() { So(err, ShouldResemble, errKafka) @@ -170,7 +173,8 @@ func TestRun(t *testing.T) { } svcErrors := make(chan error, 1) svcList := service.NewServiceList(initMock) - _, err := service.Run(ctx, cfg, svcList, testBuildTime, testGitCommit, testVersion, svcErrors) + svc := service.New(cfg, svcList) + err := svc.Run(ctx, testBuildTime, testGitCommit, testVersion, svcErrors) Convey("Then service Run fails with the same error and the flag is not set. No further initialisations are attempted", func() { So(err, ShouldResemble, errHealthcheck) @@ -199,7 +203,8 @@ func TestRun(t *testing.T) { } svcErrors := make(chan error, 1) svcList := service.NewServiceList(initMock) - _, err := service.Run(ctx, cfg, svcList, testBuildTime, testGitCommit, testVersion, svcErrors) + svc := service.New(cfg, svcList) + err := svc.Run(ctx, testBuildTime, testGitCommit, testVersion, svcErrors) Convey("Then service Run fails, but all checks try to register", func() { So(err, ShouldNotBeNil) @@ -226,8 +231,9 @@ func TestRun(t *testing.T) { } svcErrors := make(chan error, 1) svcList := service.NewServiceList(initMock) + svc := service.New(cfg, svcList) + err := svc.Run(ctx, testBuildTime, testGitCommit, testVersion, svcErrors) serverWg.Add(1) - _, err := service.Run(ctx, cfg, svcList, testBuildTime, testGitCommit, testVersion, svcErrors) Convey("Then service Run succeeds and all the flags are set", func() { So(err, ShouldBeNil) @@ -262,8 +268,9 @@ func TestRun(t *testing.T) { } svcErrors := make(chan error, 1) svcList := service.NewServiceList(initMock) + svc := service.New(cfg, svcList) + err := svc.Run(ctx, testBuildTime, testGitCommit, testVersion, svcErrors) serverWg.Add(1) - _, err := service.Run(ctx, cfg, svcList, testBuildTime, testGitCommit, testVersion, svcErrors) Convey("Then service Run succeeds and all the flags except Graph are set", func() { So(err, ShouldBeNil) @@ -296,8 +303,9 @@ func TestRun(t *testing.T) { } svcErrors := make(chan error, 1) svcList := service.NewServiceList(initMock) + svc := service.New(cfg, svcList) + err := svc.Run(ctx, testBuildTime, testGitCommit, testVersion, svcErrors) serverWg.Add(1) - _, err := service.Run(ctx, cfg, svcList, testBuildTime, testGitCommit, testVersion, svcErrors) So(err, ShouldBeNil) Convey("Then the error is returned in the error channel", func() { @@ -366,12 +374,9 @@ func TestClose(t *testing.T) { Convey("Closing a service does not close uninitialised dependencies", func() { svcList := service.NewServiceList(nil) svcList.HealthCheck = true - svc := service.Service{ - Config: cfg, - ServiceList: svcList, - Server: serverMock, - HealthCheck: hcMock, - } + svc := service.New(cfg, svcList) + svc.SetServer(serverMock) + svc.SetHealthCheck(hcMock) err = svc.Close(context.Background()) So(err, ShouldBeNil) So(len(hcMock.StopCalls()), ShouldEqual, 1) @@ -387,15 +392,12 @@ func TestClose(t *testing.T) { } Convey("Closing the service results in all the initialised dependencies being closed in the expected order", func() { - svc := service.Service{ - Config: cfg, - ServiceList: fullSvcList, - Server: serverMock, - HealthCheck: hcMock, - GenerateDownloadsProducer: kafkaProducerMock, - MongoDB: mongoMock, - GraphDB: graphMock, - } + svc := service.New(cfg, fullSvcList) + svc.SetServer(serverMock) + svc.SetHealthCheck(hcMock) + svc.SetDownloadsProducer(kafkaProducerMock) + svc.SetMongoDB(mongoMock) + svc.SetGraphDB(graphMock) err = svc.Close(context.Background()) So(err, ShouldBeNil) So(len(hcMock.StopCalls()), ShouldEqual, 1) @@ -413,15 +415,12 @@ func TestClose(t *testing.T) { }, } - svc := service.Service{ - Config: cfg, - ServiceList: fullSvcList, - Server: failingserverMock, - HealthCheck: hcMock, - GenerateDownloadsProducer: kafkaProducerMock, - MongoDB: mongoMock, - GraphDB: graphMock, - } + svc := service.New(cfg, fullSvcList) + svc.SetServer(failingserverMock) + svc.SetHealthCheck(hcMock) + svc.SetDownloadsProducer(kafkaProducerMock) + svc.SetMongoDB(mongoMock) + svc.SetGraphDB(graphMock) err = svc.Close(context.Background()) So(err, ShouldNotBeNil) So(err.Error(), ShouldResemble, "failed to shutdown gracefully") From 0c6518e431a48e9aecf3a154e712100c9e0026f5 Mon Sep 17 00:00:00 2001 From: David Subiros Date: Wed, 2 Sep 2020 15:08:21 +0200 Subject: [PATCH 10/13] Added kafka error logging --- service/service.go | 3 +++ service/service_test.go | 15 +++++++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/service/service.go b/service/service.go index 8b625d21..990d1f46 100644 --- a/service/service.go +++ b/service/service.go @@ -142,6 +142,9 @@ func (svc *Service) Run(ctx context.Context, buildTime, gitCommit, version strin svc.healthCheck.Start(ctx) + // Log kafka producer errors in parallel go-routine + svc.generateDownloadsProducer.Channels().LogErrors(ctx, "generate downloads producer error") + // Run the http server in a new go-routine go func() { if err := svc.server.ListenAndServe(); err != nil { diff --git a/service/service_test.go b/service/service_test.go index c3e86ae7..b7216cf8 100644 --- a/service/service_test.go +++ b/service/service_test.go @@ -104,7 +104,11 @@ func TestRun(t *testing.T) { } funcDoGetKafkaProducerOk := func(ctx context.Context, cfg *config.Configuration) (kafka.IProducer, error) { - return &kafkatest.IProducerMock{}, nil + return &kafkatest.IProducerMock{ + ChannelsFunc: func() *kafka.ProducerChannels { + return &kafka.ProducerChannels{} + }, + }, nil } Convey("Given that initialising MongoDB returns an error", func() { @@ -232,8 +236,8 @@ func TestRun(t *testing.T) { svcErrors := make(chan error, 1) svcList := service.NewServiceList(initMock) svc := service.New(cfg, svcList) - err := svc.Run(ctx, testBuildTime, testGitCommit, testVersion, svcErrors) serverWg.Add(1) + err := svc.Run(ctx, testBuildTime, testGitCommit, testVersion, svcErrors) Convey("Then service Run succeeds and all the flags are set", func() { So(err, ShouldBeNil) @@ -269,8 +273,8 @@ func TestRun(t *testing.T) { svcErrors := make(chan error, 1) svcList := service.NewServiceList(initMock) svc := service.New(cfg, svcList) - err := svc.Run(ctx, testBuildTime, testGitCommit, testVersion, svcErrors) serverWg.Add(1) + err := svc.Run(ctx, testBuildTime, testGitCommit, testVersion, svcErrors) Convey("Then service Run succeeds and all the flags except Graph are set", func() { So(err, ShouldBeNil) @@ -304,8 +308,8 @@ func TestRun(t *testing.T) { svcErrors := make(chan error, 1) svcList := service.NewServiceList(initMock) svc := service.New(cfg, svcList) - err := svc.Run(ctx, testBuildTime, testGitCommit, testVersion, svcErrors) serverWg.Add(1) + err := svc.Run(ctx, testBuildTime, testGitCommit, testVersion, svcErrors) So(err, ShouldBeNil) Convey("Then the error is returned in the error channel", func() { @@ -368,6 +372,9 @@ func TestClose(t *testing.T) { // Kafka producer will fail if healthcheck or http server are not stopped kafkaProducerMock := &kafkatest.IProducerMock{ + ChannelsFunc: func() *kafka.ProducerChannels { + return &kafka.ProducerChannels{} + }, CloseFunc: funcClose, } From f4b29fe4393fb2875ab9038b370a639ee940a624 Mon Sep 17 00:00:00 2001 From: David Subiros Date: Wed, 2 Sep 2020 17:41:24 +0200 Subject: [PATCH 11/13] Updated to tagged version of dp-net --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 59156f49..9cb79ff9 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/ONSdigital/dp-healthcheck v1.0.5 github.com/ONSdigital/dp-kafka v1.1.7 github.com/ONSdigital/dp-mongodb v1.4.0 - github.com/ONSdigital/dp-net v1.0.8-0.20200901091958-2df9a102ca3d + github.com/ONSdigital/dp-net v1.0.8 github.com/ONSdigital/go-ns v0.0.0-20200205115900-a11716f93bad github.com/ONSdigital/log.go v1.0.1 github.com/frankban/quicktest v1.9.0 // indirect diff --git a/go.sum b/go.sum index 4e002132..d56a4063 100644 --- a/go.sum +++ b/go.sum @@ -23,8 +23,8 @@ github.com/ONSdigital/dp-net v1.0.5-0.20200805082802-e518bc287596/go.mod h1:wDVh github.com/ONSdigital/dp-net v1.0.5-0.20200805145012-9227a11caddb/go.mod h1:MrSZwDUvp8u1VJEqa+36Gwq4E7/DdceW+BDCvGes6Cs= github.com/ONSdigital/dp-net v1.0.5-0.20200805150805-cac050646ab5/go.mod h1:de3LB9tedE0tObBwa12dUOt5rvTW4qQkF5rXtt4b6CE= github.com/ONSdigital/dp-net v1.0.7/go.mod h1:1QFzx32FwPKD2lgZI6MtcsUXritsBdJihlzIWDrQ/gc= -github.com/ONSdigital/dp-net v1.0.8-0.20200901091958-2df9a102ca3d h1:oPcqBxBSYs0kjnNdkzf9buxjuRyX9sOCDiSpsu3iz4U= -github.com/ONSdigital/dp-net v1.0.8-0.20200901091958-2df9a102ca3d/go.mod h1:2lvIKOlD4T3BjWQwjHhBUO2UNWDk82u/+mHRn0R3C9A= +github.com/ONSdigital/dp-net v1.0.8 h1:fcOw+PBZWgp14ryz61daMvkqFKIK7lp7AceRbaBLa24= +github.com/ONSdigital/dp-net v1.0.8/go.mod h1:2lvIKOlD4T3BjWQwjHhBUO2UNWDk82u/+mHRn0R3C9A= github.com/ONSdigital/dp-rchttp v0.0.0-20190919143000-bb5699e6fd59/go.mod h1:KkW68U3FPuivW4ogi9L8CPKNj9ZxGko4qcUY7KoAAkQ= github.com/ONSdigital/dp-rchttp v0.0.0-20200114090501-463a529590e8 h1:MWIHCr/ud5ur9elhfvKtSjMJInqf3iUY8F4J27qGQPA= github.com/ONSdigital/dp-rchttp v0.0.0-20200114090501-463a529590e8/go.mod h1:821jZtK0oBsV8hjIkNr8vhAWuv0FxJBPJuAHa2B70Gk= From d710c55eb17c7593d5a7f45045771370d1a628df Mon Sep 17 00:00:00 2001 From: David Subiros Date: Thu, 3 Sep 2020 13:31:26 +0200 Subject: [PATCH 12/13] Removed superfulous action constants, removed action param from methos where is no longer required, fixed generic dimension error logging and removed mongoDB client from struct (only used to create the healthcheck client) --- api/api.go | 87 ++++++++++++++--------------------------- api/observation.go | 2 - api/observation_test.go | 24 ++++++------ dimension/helpers.go | 14 +++---- instance/dimensions.go | 2 +- instance/editions.go | 3 -- instance/import.go | 4 +- instance/instance.go | 23 +++-------- mongo/dataset_store.go | 7 ++-- 9 files changed, 58 insertions(+), 108 deletions(-) diff --git a/api/api.go b/api/api.go index 2212e11c..55da9a96 100644 --- a/api/api.go +++ b/api/api.go @@ -22,29 +22,8 @@ import ( const ( downloadServiceToken = "X-Download-Service-Token" - - // actions - addDatasetAction = "addDataset" - deleteDatasetAction = "deleteDataset" - getDatasetsAction = "getDatasets" - getDatasetAction = "getDataset" - - getEditionsAction = "getEditions" - getEditionAction = "getEdition" - - getVersionsAction = "getVersions" - getVersionAction = "getVersion" - updateDatasetAction = "updateDataset" - updateVersionAction = "updateVersion" - associateVersionAction = "associateVersionAction" - publishVersionAction = "publishVersion" - detachVersionAction = "detachVersion" - - getDimensionsAction = "getDimensions" - getDimensionOptionsAction = "getDimensionOptionsAction" - getMetadataAction = "getMetadata" - - hasDownloads = "has_downloads" + updateVersionAction = "updateVersion" + hasDownloads = "has_downloads" ) var ( @@ -224,28 +203,28 @@ func (api *DatasetAPI) enablePrivateDatasetEndpoints(ctx context.Context) { api.post( "/datasets/{dataset_id}", - api.isAuthenticated(addDatasetAction, + api.isAuthenticated( api.isAuthorisedForDatasets(createPermission, api.addDataset)), ) api.put( "/datasets/{dataset_id}", - api.isAuthenticated(updateDatasetAction, + api.isAuthenticated( api.isAuthorisedForDatasets(updatePermission, api.putDataset)), ) api.delete( "/datasets/{dataset_id}", - api.isAuthenticated(deleteDatasetAction, + api.isAuthenticated( api.isAuthorisedForDatasets(deletePermission, api.deleteDataset)), ) api.put( "/datasets/{dataset_id}/editions/{edition}/versions/{version}", - api.isAuthenticated(updateVersionAction, + api.isAuthenticated( api.isAuthorisedForDatasets(updatePermission, api.isVersionPublished(updateVersionAction, api.putVersion))), @@ -254,7 +233,7 @@ func (api *DatasetAPI) enablePrivateDatasetEndpoints(ctx context.Context) { if api.enableDetachDataset { api.delete( "/datasets/{dataset_id}/editions/{edition}/versions/{version}", - api.isAuthenticated(detachVersionAction, + api.isAuthenticated( api.isAuthorisedForDatasets(deletePermission, api.detachVersion)), ) @@ -266,62 +245,58 @@ func (api *DatasetAPI) enablePrivateDatasetEndpoints(ctx context.Context) { func (api *DatasetAPI) enablePrivateInstancesEndpoints(instanceAPI *instance.Store) { api.get( "/instances", - api.isAuthenticated(instance.GetInstancesAction, + api.isAuthenticated( api.isAuthorised(readPermission, instanceAPI.GetList)), ) api.post( "/instances", - api.isAuthenticated(instance.AddInstanceAction, + api.isAuthenticated( api.isAuthorised(createPermission, instanceAPI.Add)), ) api.get( "/instances/{instance_id}", - api.isAuthenticated(instance.GetInstanceAction, + api.isAuthenticated( api.isAuthorised(readPermission, instanceAPI.Get)), ) api.put( "/instances/{instance_id}", - api.isAuthenticated(instance.UpdateInstanceAction, + api.isAuthenticated( api.isAuthorised(updatePermission, - api.isInstancePublished(instance.UpdateInstanceAction, - instanceAPI.Update))), + api.isInstancePublished(instanceAPI.Update))), ) api.put( "/instances/{instance_id}/dimensions/{dimension}", - api.isAuthenticated(instance.UpdateDimensionAction, + api.isAuthenticated( api.isAuthorised(updatePermission, - api.isInstancePublished(instance.UpdateDimensionAction, - instanceAPI.UpdateDimension))), + api.isInstancePublished(instanceAPI.UpdateDimension))), ) api.post( "/instances/{instance_id}/events", - api.isAuthenticated(instance.AddInstanceEventAction, + api.isAuthenticated( api.isAuthorised(createPermission, instanceAPI.AddEvent)), ) api.put( "/instances/{instance_id}/inserted_observations/{inserted_observations}", - api.isAuthenticated(instance.UpdateInsertedObservationsAction, + api.isAuthenticated( api.isAuthorised(updatePermission, - api.isInstancePublished(instance.UpdateInsertedObservationsAction, - instanceAPI.UpdateObservations))), + api.isInstancePublished(instanceAPI.UpdateObservations))), ) api.put( "/instances/{instance_id}/import_tasks", - api.isAuthenticated(instance.UpdateImportTasksAction, + api.isAuthenticated( api.isAuthorised(updatePermission, - api.isInstancePublished(instance.UpdateImportTasksAction, - instanceAPI.UpdateImportTask))), + api.isInstancePublished(instanceAPI.UpdateImportTask))), ) } @@ -330,39 +305,37 @@ func (api *DatasetAPI) enablePrivateInstancesEndpoints(instanceAPI *instance.Sto func (api *DatasetAPI) enablePrivateDimensionsEndpoints(dimensionAPI *dimension.Store) { api.get( "/instances/{instance_id}/dimensions", - api.isAuthenticated(dimension.GetDimensions, + api.isAuthenticated( api.isAuthorised(readPermission, dimensionAPI.GetDimensionsHandler)), ) api.post( "/instances/{instance_id}/dimensions", - api.isAuthenticated(dimension.AddDimensionAction, + api.isAuthenticated( api.isAuthorised(createPermission, - api.isInstancePublished(dimension.AddDimensionAction, - dimensionAPI.AddHandler))), + api.isInstancePublished(dimensionAPI.AddHandler))), ) api.get( "/instances/{instance_id}/dimensions/{dimension}/options", - api.isAuthenticated(dimension.GetUniqueDimensionAndOptionsAction, + api.isAuthenticated( api.isAuthorised(readPermission, dimensionAPI.GetUniqueDimensionAndOptionsHandler)), ) api.put( "/instances/{instance_id}/dimensions/{dimension}/options/{option}/node_id/{node_id}", - api.isAuthenticated(dimension.UpdateNodeIDAction, + api.isAuthenticated( api.isAuthorised(updatePermission, - api.isInstancePublished(dimension.UpdateNodeIDAction, - dimensionAPI.AddNodeIDHandler))), + api.isInstancePublished(dimensionAPI.AddNodeIDHandler))), ) } // isAuthenticated wraps a http handler func in another http handler func that checks the caller is authenticated to -// perform the requested action. action is the event name, handler is the http.HandlerFunc to wrap in an -// authentication check. The wrapped handler is only called is the caller is authenticated -func (api *DatasetAPI) isAuthenticated(action string, handler http.HandlerFunc) http.HandlerFunc { +// perform the requested action. handler is the http.HandlerFunc to wrap in an +// authentication check. The wrapped handler is only called if the caller is authenticated +func (api *DatasetAPI) isAuthenticated(handler http.HandlerFunc) http.HandlerFunc { return dphandlers.CheckIdentity(handler) } @@ -383,8 +356,8 @@ func (api *DatasetAPI) isAuthorisedForDatasets(required auth.Permissions, handle // isInstancePublished wraps a http.HandlerFunc checking the instance state. The wrapped handler is only invoked if the // requested instance is not in a published state. -func (api *DatasetAPI) isInstancePublished(action string, handler http.HandlerFunc) http.HandlerFunc { - return api.instancePublishedChecker.Check(handler, action) +func (api *DatasetAPI) isInstancePublished(handler http.HandlerFunc) http.HandlerFunc { + return api.instancePublishedChecker.Check(handler) } // isInstancePublished wraps a http.HandlerFunc checking the version state. The wrapped handler is only invoked if the diff --git a/api/observation.go b/api/observation.go index 699bc08c..df77d8a3 100644 --- a/api/observation.go +++ b/api/observation.go @@ -24,8 +24,6 @@ import ( const ( defaultObservationLimit = 10000 defaultOffset = 0 - - getObservationsAction = "getObservations" ) var ( diff --git a/api/observation_test.go b/api/observation_test.go index ba3ad324..43578c91 100644 --- a/api/observation_test.go +++ b/api/observation_test.go @@ -35,20 +35,20 @@ func TestGetObservationsReturnsOK(t *testing.T) { Convey("Given a request to get a single observation for a version of a dataset returns 200 OK response", t, func() { dimensions := []models.Dimension{ - models.Dimension{ + { Name: "aggregate", HRef: "http://localhost:8081/code-lists/cpih1dim1aggid", }, - models.Dimension{ + { Name: "geography", HRef: "http://localhost:8081/code-lists/uk-only", }, - models.Dimension{ + { Name: "time", HRef: "http://localhost:8081/code-lists/time", }, } - usagesNotes := &[]models.UsageNote{models.UsageNote{Title: "data_marking", Note: "this marks the obsevation with a special character"}} + usagesNotes := &[]models.UsageNote{{Title: "data_marking", Note: "this marks the obsevation with a special character"}} count := 0 mockRowReader := &observationtest.StreamRowReaderMock{ @@ -134,20 +134,20 @@ func TestGetObservationsReturnsOK(t *testing.T) { w := httptest.NewRecorder() dimensions := []models.Dimension{ - models.Dimension{ + { Name: "aggregate", HRef: "http://localhost:8081/code-lists/cpih1dim1aggid", }, - models.Dimension{ + { Name: "geography", HRef: "http://localhost:8081/code-lists/uk-only", }, - models.Dimension{ + { Name: "time", HRef: "http://localhost:8081/code-lists/time", }, } - usagesNotes := &[]models.UsageNote{models.UsageNote{Title: "data_marking", Note: "this marks the observation with a special character"}} + usagesNotes := &[]models.UsageNote{{Title: "data_marking", Note: "this marks the observation with a special character"}} count := 0 mockRowReader := &observationtest.StreamRowReaderMock{ @@ -609,20 +609,20 @@ func TestGetObservationsReturnsError(t *testing.T) { w := httptest.NewRecorder() dimensions := []models.Dimension{ - models.Dimension{ + { Name: "aggregate", HRef: "http://localhost:8081/code-lists/cpih1dim1aggid", }, - models.Dimension{ + { Name: "geography", HRef: "http://localhost:8081/code-lists/uk-only", }, - models.Dimension{ + { Name: "time", HRef: "http://localhost:8081/code-lists/time", }, } - usagesNotes := &[]models.UsageNote{models.UsageNote{Title: "data_marking", Note: "this marks the obsevation with a special character"}} + usagesNotes := &[]models.UsageNote{{Title: "data_marking", Note: "this marks the obsevation with a special character"}} mockedDataStore := &storetest.StorerMock{ GetDatasetFunc: func(string) (*models.DatasetUpdate, error) { diff --git a/dimension/helpers.go b/dimension/helpers.go index 932a2a5c..7631f01a 100644 --- a/dimension/helpers.go +++ b/dimension/helpers.go @@ -11,7 +11,6 @@ import ( "github.com/ONSdigital/dp-dataset-api/models" dprequest "github.com/ONSdigital/dp-net/request" "github.com/ONSdigital/log.go/log" - "github.com/pkg/errors" ) const ( @@ -45,7 +44,6 @@ func handleDimensionErr(ctx context.Context, w http.ResponseWriter, err error, d } var status int - resource := err switch { case errs.NotFoundMap[err]: status = http.StatusNotFound @@ -53,22 +51,20 @@ func handleDimensionErr(ctx context.Context, w http.ResponseWriter, err error, d status = http.StatusBadRequest default: status = http.StatusInternalServerError - resource = errs.ErrInternalServer + err = errs.ErrInternalServer } data["response_status"] = status - logError(ctx, errors.WithMessage(err, "request unsuccessful"), data) - http.Error(w, resource.Error(), status) + logError(ctx, err, data) + http.Error(w, err.Error(), status) } -func logError(ctx context.Context, err error, data log.Data) error { +func logError(ctx context.Context, err error, data log.Data) { if user := dprequest.User(ctx); user != "" { data[reqUser] = user } if caller := dprequest.Caller(ctx); caller != "" { data[reqCaller] = caller } - err = errors.WithMessage(err, "putVersion endpoint: failed to set instance node is_published") - log.Event(ctx, "failed to publish instance version", log.ERROR, log.Error(err), data) - return err + log.Event(ctx, "unsuccessful request", log.ERROR, log.Error(err), data) } diff --git a/instance/dimensions.go b/instance/dimensions.go index eb27814f..a25373f6 100644 --- a/instance/dimensions.go +++ b/instance/dimensions.go @@ -22,7 +22,7 @@ func (s *Store) UpdateDimension(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) instanceID := vars["instance_id"] dimension := vars["dimension"] - logData := log.Data{"instance_id": instanceID, "dimension": dimension, "action": UpdateDimensionAction} + logData := log.Data{"instance_id": instanceID, "dimension": dimension} log.Event(ctx, "update instance dimension: update instance dimension", log.INFO, logData) diff --git a/instance/editions.go b/instance/editions.go index a4757c7d..5e744ad2 100644 --- a/instance/editions.go +++ b/instance/editions.go @@ -25,7 +25,6 @@ func (s *Store) confirmEdition(ctx context.Context, datasetID, edition, instance } log.Event(ctx, "confirm edition: edition not found, creating", log.INFO, logData) - action = CreateEditionAction editionDoc, err = models.CreateEdition(s.Host, datasetID, edition) if err != nil { return nil, action, err @@ -34,8 +33,6 @@ func (s *Store) confirmEdition(ctx context.Context, datasetID, edition, instance log.Event(ctx, "confirm edition: created new edition", log.INFO, logData) } else { - action = UpdateEditionAction - // TODO - feature flag. Will need removing eventually. if s.EnableDetachDataset { // Abort if a new/next version is already in flight diff --git a/instance/import.go b/instance/import.go index 7ecd169b..edb81a80 100644 --- a/instance/import.go +++ b/instance/import.go @@ -23,7 +23,7 @@ func (s *Store) UpdateObservations(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) instanceID := vars["instance_id"] insert := vars["inserted_observations"] - logData := log.Data{"instance_id": instanceID, "inserted_observations": insert, "action": UpdateInsertedObservationsAction} + logData := log.Data{"instance_id": instanceID, "inserted_observations": insert} if err := func() error { observations, err := strconv.ParseInt(insert, 10, 64) @@ -54,7 +54,7 @@ func (s *Store) UpdateImportTask(w http.ResponseWriter, r *http.Request) { ctx := r.Context() vars := mux.Vars(r) instanceID := vars["instance_id"] - logData := log.Data{"instance_id": instanceID, "action": UpdateImportTasksAction} + logData := log.Data{"instance_id": instanceID} defer r.Body.Close() updateErr := func() *taskError { diff --git a/instance/instance.go b/instance/instance.go index 2dca5bf9..27d04a67 100644 --- a/instance/instance.go +++ b/instance/instance.go @@ -39,19 +39,6 @@ func (e taskError) Error() string { return "" } -// List of actions for instances -const ( - AddInstanceAction = "addInstance" - CreateEditionAction = "createEditionForInstance" - GetInstanceAction = "getInstance" - GetInstancesAction = "getInstances" - UpdateInstanceAction = "updateInstance" - UpdateDimensionAction = "updateDimension" - UpdateEditionAction = "updateEditionNextSubDocForInstance" - UpdateInsertedObservationsAction = "updateInsertedObservations" - UpdateImportTasksAction = "updateImportTasks" -) - //GetList a list of all instances func (s *Store) GetList(w http.ResponseWriter, r *http.Request) { ctx := r.Context() @@ -59,7 +46,7 @@ func (s *Store) GetList(w http.ResponseWriter, r *http.Request) { datasetFilterQuery := r.URL.Query().Get("dataset") var stateFilterList []string var datasetFilterList []string - logData := log.Data{"action": GetInstancesAction} + logData := log.Data{} if stateFilterQuery != "" { logData["state_query"] = stateFilterQuery @@ -109,7 +96,7 @@ func (s *Store) Get(w http.ResponseWriter, r *http.Request) { ctx := r.Context() vars := mux.Vars(r) instanceID := vars["instance_id"] - logData := log.Data{"instance_id": instanceID, "action": GetInstanceAction} + logData := log.Data{"instance_id": instanceID} log.Event(ctx, "get instance", log.INFO, logData) @@ -153,7 +140,7 @@ func (s *Store) Add(w http.ResponseWriter, r *http.Request) { defer dphttp.DrainBody(r) ctx := r.Context() - logData := log.Data{"action": AddInstanceAction} + logData := log.Data{} log.Event(ctx, "add instance", log.INFO, logData) @@ -203,7 +190,7 @@ func (s *Store) Update(w http.ResponseWriter, r *http.Request) { ctx := r.Context() vars := mux.Vars(r) instanceID := vars["instance_id"] - logData := log.Data{"instance_id": instanceID, "action": UpdateInstanceAction} + logData := log.Data{"instance_id": instanceID} var b []byte var err error @@ -456,7 +443,7 @@ type PublishCheck struct { } // Check wraps a HTTP handle. Checks that the state is not published -func (d *PublishCheck) Check(handle func(http.ResponseWriter, *http.Request), action string) http.HandlerFunc { +func (d *PublishCheck) Check(handle func(http.ResponseWriter, *http.Request)) http.HandlerFunc { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ctx := r.Context() vars := mux.Vars(r) diff --git a/mongo/dataset_store.go b/mongo/dataset_store.go index 4d8626d0..23366bdc 100644 --- a/mongo/dataset_store.go +++ b/mongo/dataset_store.go @@ -27,7 +27,6 @@ type Mongo struct { URI string lastPingTime time.Time lastPingResult error - client *dpMongoHealth.Client healthClient *dpMongoHealth.CheckMongoClient } @@ -49,10 +48,10 @@ func (m *Mongo) Init() (err error) { m.Session.SetMode(mgo.Strong, true) // Create client and healthclient from session - m.client = dpMongoHealth.NewClient(m.Session) + client := dpMongoHealth.NewClient(m.Session) m.healthClient = &dpMongoHealth.CheckMongoClient{ - Client: *m.client, - Healthcheck: m.client.Healthcheck, + Client: *client, + Healthcheck: client.Healthcheck, } return nil From 0f2885adac6a874a009704191fd0a84e8d766e92 Mon Sep 17 00:00:00 2001 From: Dave Llewellyn <439837@gmail.com> Date: Thu, 24 Sep 2020 10:57:20 +0100 Subject: [PATCH 13/13] Removed log namespace for auth lib - overwriting app namespace and misplacing logs --- service/service.go | 1 - 1 file changed, 1 deletion(-) diff --git a/service/service.go b/service/service.go index 990d1f46..3b7eacab 100644 --- a/service/service.go +++ b/service/service.go @@ -162,7 +162,6 @@ func getAuthorisationHandlers(ctx context.Context, cfg *config.Configuration) (a } log.Event(ctx, "feature flag enabled", log.INFO, log.Data{"feature": "ENABLE_PERMISSIONS_AUTH"}) - auth.LoggerNamespace("dp-dataset-api-auth") authClient := auth.NewPermissionsClient(dphttp.NewClient()) authVerifier := auth.DefaultPermissionsVerifier()