diff --git a/api/api.go b/api/api.go index 189e0c43..55da9a96 100644 --- a/api/api.go +++ b/api/api.go @@ -14,44 +14,16 @@ 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" - "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" + 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 - const ( downloadServiceToken = "X-Download-Service-Token" - - // audit 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 ( @@ -73,9 +45,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 @@ -83,17 +52,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 - auditor Auditor enablePrivateEndpoints bool enableDetachDataset bool enableObservationEndpoint bool @@ -103,67 +68,17 @@ 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, auditor Auditor, datasetPermissions AuthHandler, permissions AuthHandler) { - router := mux.NewRouter() - api := NewDatasetAPI(ctx, cfg, router, dataStore, urlBuilder, downloadGenerator, auditor, 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(identity.Handler(cfg.ZebedeeURL)) - } +// 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 { - middleware = middleware.Append(collectionID.CheckHeader) - - httpServer = server.New(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) - }) - } -} - -// 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 { api := &DatasetAPI{ dataStore: dataStore, host: cfg.DatasetAPIURL, - zebedeeURL: cfg.ZebedeeURL, - serviceAuthToken: cfg.ServiceAuthToken, downloadServiceToken: cfg.DownloadServiceSecretKey, EnablePrePublishView: cfg.EnablePrivateEndpoints, Router: router, urlBuilder: urlBuilder, downloadGenerator: downloadGenerator, - auditor: auditor, enablePrivateEndpoints: cfg.EnablePrivateEndpoints, enableDetachDataset: cfg.EnableDetachDataset, enableObservationEndpoint: cfg.EnableObservationEndpoint, @@ -177,25 +92,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.enablePrivateEndpoints, + EnableDetachDataset: api.enableDetachDataset, } dimensionAPI := &dimension.Store{ - Auditor: api.auditor, - Storer: api.dataStore.Backend, + Storer: api.dataStore.Backend, } api.enablePrivateDatasetEndpoints(ctx) @@ -292,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))), @@ -322,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)), ) @@ -334,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))), ) } @@ -398,40 +305,38 @@ 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. 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) +// 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) } // isAuthorised wraps a http.HandlerFunc another http.HandlerFunc that checks the caller is authorised to perform the @@ -451,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 @@ -487,13 +392,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 @@ -512,12 +417,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/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..d7925ef6 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 Setup(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..b405d64c 100644 --- a/api/dimensions.go +++ b/api/dimensions.go @@ -5,12 +5,9 @@ import ( "encoding/json" "fmt" "net/http" - "strconv" 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/globalsign/mgo/bson" "github.com/gorilla/mux" @@ -23,12 +20,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 +63,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,15 +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 := 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 - } - authorised := api.authenticate(r, logData) - auditParams["authorised"] = strconv.FormatBool(authorised) var state string if !authorised { @@ -198,18 +173,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..df77d8a3 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" @@ -26,8 +24,6 @@ import ( const ( defaultObservationLimit = 10000 defaultOffset = 0 - - getObservationsAction = "getObservations" ) var ( @@ -75,14 +71,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 +155,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..43578c91 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" ) @@ -38,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{ @@ -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}, - ) }) }) @@ -150,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{ @@ -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() { @@ -723,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) { @@ -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..df417211 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 Setup(ctx, cfg, mux.NewRouter(), store.DataStore{Backend: mockedDataStore}, urlBuilder, mockedGeneratedDownloads, datasetPermissions, permissions) } 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/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..d9b639fa 100644 --- a/dimension/dimension.go +++ b/dimension/dimension.go @@ -7,20 +7,17 @@ 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 } -// List of audit actions for dimensions +// List of actions for dimensions const ( GetDimensions = "getInstanceDimensions" GetUniqueDimensionAndOptionsAction = "getInstanceUniqueDimensionAndOptions" @@ -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..16fcf9ba 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.Setup(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..7631f01a 100644 --- a/dimension/helpers.go +++ b/dimension/helpers.go @@ -9,9 +9,13 @@ 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) { @@ -40,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 @@ -48,10 +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 - audit.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) { + if user := dprequest.User(ctx); user != "" { + data[reqUser] = user + } + if caller := dprequest.Caller(ctx); caller != "" { + data[reqCaller] = caller + } + log.Event(ctx, "unsuccessful request", log.ERROR, log.Error(err), data) } 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/go.mod b/go.mod index df974b13..9cb79ff9 100644 --- a/go.mod +++ b/go.mod @@ -3,21 +3,30 @@ 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.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 + github.com/ONSdigital/dp-kafka v1.1.7 + github.com/ONSdigital/dp-mongodb v1.4.0 + 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.0 + 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/gorilla/mux v1.7.4 + 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.3 // indirect gopkg.in/avro.v0 v0.0.0-20171217001914-a730b5802183 // indirect ) diff --git a/go.sum b/go.sum index c95b8ecf..d56a4063 100644 --- a/go.sum +++ b/go.sum @@ -1,22 +1,30 @@ -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-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.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.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-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 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= @@ -29,11 +37,15 @@ 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-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= github.com/Shopify/sarama v1.24.1/go.mod h1:fGP8eQ6PugKEI0iUETYYtnP6d1pH/bdDMTel1X5ajsU= github.com/Shopify/toxiproxy v2.1.4+incompatible h1:TKdv8HiTLgE5wdJuEML90aBgNWsokNbMijUGhmcoBJc= @@ -59,31 +71,46 @@ 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= 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/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= 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= 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= +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= @@ -98,10 +125,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= @@ -110,7 +141,13 @@ 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= +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= @@ -119,6 +156,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= @@ -133,20 +172,31 @@ 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 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= 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-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= 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,19 +204,30 @@ 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-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.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= 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= @@ -181,5 +242,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 f12e7022..00000000 --- a/initialise/initialise.go +++ /dev/null @@ -1,124 +0,0 @@ -package initialise - -import ( - "context" - "fmt" - - "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 { - 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) { - 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) - } - - 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/dimensions.go b/instance/dimensions.go index 34cd8a5d..a25373f6 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} 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 8ab9a51e..5e744ad2 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 @@ -29,11 +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 - 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 @@ -42,21 +33,16 @@ 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 - if editionDoc.Current == nil || 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 } } 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 +59,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 168bae44..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,80 @@ 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" + 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 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, + 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, + EnableDetachDataset: true, } Convey("when confirmEdition is called", func() { @@ -312,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..148c58e1 100644 --- a/instance/event.go +++ b/instance/event.go @@ -8,13 +8,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" "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) { @@ -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..edb81a80 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} 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} 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..27d04a67 100644 --- a/instance/instance.go +++ b/instance/instance.go @@ -13,9 +13,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" @@ -26,7 +24,6 @@ import ( type Store struct { store.Storer Host string - Auditor audit.AuditorService EnableDetachDataset bool } @@ -42,42 +39,22 @@ func (e taskError) Error() string { return "" } -// List of audit 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() 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) - } + logData := log.Data{} 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 +83,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 +96,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} log.Event(ctx, "get instance", log.INFO, logData) @@ -158,20 +125,11 @@ 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 { - 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 +137,10 @@ 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{} + logData := log.Data{} log.Event(ctx, "add instance", log.INFO, logData) @@ -194,7 +151,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), @@ -215,15 +171,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 +185,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} var b []byte var err error @@ -331,10 +280,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 +288,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,29 +440,18 @@ 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 -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) 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 +460,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..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" @@ -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/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" ) @@ -29,7 +25,6 @@ import ( const host = "http://localhost:8080" var ( - errAudit = errors.New("auditing error") mu sync.Mutex testContext = context.Background() ) @@ -37,7 +32,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 +54,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 +80,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 +88,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 +107,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 +115,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 +134,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 +142,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 +162,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 +170,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 +192,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 +200,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 +213,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 +243,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 +273,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 +281,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 +298,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 +306,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 +324,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 +332,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 +343,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 +361,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 +369,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 +391,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 +399,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 +417,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 +425,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 +443,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 +451,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 +489,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 +498,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 +505,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 +522,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 +534,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 +551,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 +561,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 +577,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 +589,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 +610,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 +622,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 +640,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 +652,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 +659,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 +668,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.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 64eb658e..e02b54f5 100644 --- a/main.go +++ b/main.go @@ -2,42 +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" - rchttp "github.com/ONSdigital/dp-rchttp" - "github.com/ONSdigital/go-ns/audit" + "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 @@ -49,274 +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 - - 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)) - 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, - initialise.GenerateDownloads, - 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, + // Run the service + svc := service.New(cfg, svcList) + if err := svc.Run(ctx, BuildTime, GitCommit, Version, svcErrors); err != nil { + return errors.Wrap(err, "running service failed") } - // Get HealthCheck - hc, err := serviceList.GetHealthCheck(cfg, BuildTime, GitCommit, Version) - 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, - auditProducer, - graphDB, - mongoClient, - zebedeeClient, - cfg.EnablePrivateEndpoints, - cfg.EnableObservationEndpoint); err != nil { - return err - } - - 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, auditor, 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 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 { - 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(rchttp.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, auditProducer *kafka.Producer, - graphDB *graph.DB, - mongoClient *mongoHealth.Client, - zebedeeClient *zebedee.Client, - enablePrivateEndpoints, - enableObservationEndpoint bool) (err error) { - - 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)) - } - } - - 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..23366bdc 100644 --- a/mongo/dataset_store.go +++ b/mongo/dataset_store.go @@ -7,12 +7,14 @@ 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" + dpmongo "github.com/ONSdigital/dp-mongodb" + 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 +27,47 @@ type Mongo struct { URI string lastPingTime time.Time lastPingResult error + 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 + client := dpMongoHealth.NewClient(m.Session) + m.healthClient = &dpMongoHealth.CheckMongoClient{ + Client: *client, + Healthcheck: client.Healthcheck, + } + + 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) +} - session.EnsureSafe(&mgo.Safe{WMode: "majority"}) - session.SetMode(mgo.Strong, true) - return session, 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..02eea363 --- /dev/null +++ b/service/initialise.go @@ -0,0 +1,125 @@ +package service + +import ( + "context" + "net/http" + + "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" + 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) (store.GraphDB, 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) (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 + } + 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) (store.GraphDB, error) { + return graph.New(ctx, graph.Subsets{Observation: true, Instance: true}) +} + +// DoGetMongoDB returns a MongoDB +func (e *Init) DoGetMongoDB(ctx context.Context, cfg *config.Configuration) (store.MongoDB, 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 + } + 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 new file mode 100644 index 00000000..2f083117 --- /dev/null +++ b/service/interfaces.go @@ -0,0 +1,38 @@ +package service + +import ( + "context" + "net/http" + + "github.com/ONSdigital/dp-dataset-api/config" + "github.com/ONSdigital/dp-dataset-api/store" + "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) (store.GraphDB, error) + DoGetMongoDB(ctx context.Context, cfg *config.Configuration) (store.MongoDB, 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/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 new file mode 100644 index 00000000..3b7eacab --- /dev/null +++ b/service/service.go @@ -0,0 +1,319 @@ +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/schema" + "github.com/ONSdigital/dp-dataset-api/store" + "github.com/ONSdigital/dp-dataset-api/url" + kafka "github.com/ONSdigital/dp-kafka" + 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 { + 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 store.GraphDB + mongoDB store.MongoDB + generateDownloadsProducer kafka.IProducer + identityClient *clientsidentity.Client + server HTTPServer + healthCheck HealthChecker + api *api.DatasetAPI +} + +// 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 = svc.serviceList.GetMongoDB(ctx, svc.config) + if err != nil { + log.Event(ctx, "could not obtain mongo session", log.ERROR, log.Error(err)) + return err + } + + // Get graphDB connection for observation store + 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": svc.config.EnableObservationEndpoint, + "EnablePrivateEndpoints": svc.config.EnablePrivateEndpoints, + }) + } else { + svc.graphDB, err = svc.serviceList.GetGraphDB(ctx) + if err != nil { + log.Event(ctx, "failed to initialise graph driver", log.FATAL, log.Error(err)) + return err + } + } + store := store.DataStore{Backend: DatsetAPIStore{svc.mongoDB, svc.graphDB}} + + // Get GenerateDownloads Kafka Producer + 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 err + } + + downloadGenerator := &download.Generator{ + Producer: adapter.NewProducerAdapter(svc.generateDownloadsProducer), + Marshaller: schema.GenerateDownloadsEvent, + } + + // Get Identity Client (only if private endpoints are enabled) + if svc.config.EnablePrivateEndpoints { + svc.identityClient = clientsidentity.New(svc.config.ZebedeeURL) + } + + // Get HealthCheck + 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 err + } + if err := svc.registerCheckers(ctx); err != nil { + return errors.Wrap(err, "unable to register checkers") + } + + // Get HTTP router and server with middleware + r := mux.NewRouter() + m := svc.createMiddleware(svc.config) + svc.server = svc.serviceList.GetHTTPServer(svc.config.BindAddr, m.Then(r)) + + // Create Dataset API + 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) + + // 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 { + svcErrors <- errors.Wrap(err, "failure in http listen and serve") + } + }() + + 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"}) + + 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(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 { + 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(shutdownContext); err != nil { + log.Event(shutdownContext, "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 shutdownContext.Err() == context.DeadlineExceeded { + log.Event(shutdownContext, "shutdown timed out", log.ERROR, log.Error(shutdownContext.Err())) + return shutdownContext.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.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 +} diff --git a/service/service_test.go b/service/service_test.go new file mode 100644 index 00000000..b7216cf8 --- /dev/null +++ b/service/service_test.go @@ -0,0 +1,442 @@ +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{ + ChannelsFunc: func() *kafka.ProducerChannels { + return &kafka.ProducerChannels{} + }, + }, nil + } + + Convey("Given that initialising MongoDB returns an error", func() { + initMock := &serviceMock.InitialiserMock{ + DoGetMongoDBFunc: funcDoGetMongoDBErr, + } + svcErrors := make(chan error, 1) + svcList := service.NewServiceList(initMock) + 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) + 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) + 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) + 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) + 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) + 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) + 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) + 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) + 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) + 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) + svc := service.New(cfg, svcList) + 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) + 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) + svc := service.New(cfg, svcList) + 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) + 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) + svc := service.New(cfg, svcList) + 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() { + 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{ + ChannelsFunc: func() *kafka.ProducerChannels { + return &kafka.ProducerChannels{} + }, + CloseFunc: funcClose, + } + + Convey("Closing a service does not close uninitialised dependencies", func() { + svcList := service.NewServiceList(nil) + svcList.HealthCheck = true + 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) + 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.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) + 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.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") + 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 +}