diff --git a/go-backend/api/coreValues.go b/go-backend/api/coreValues.go new file mode 100644 index 000000000..a56208e23 --- /dev/null +++ b/go-backend/api/coreValues.go @@ -0,0 +1,110 @@ +package api + +import ( + "encoding/json" + "fmt" + "net/http" + + "joshsoftware/peerly/apperrors" + "joshsoftware/peerly/pkg/dto" + corevalues "joshsoftware/peerly/service/coreValues" + + "github.com/gorilla/mux" + logger "github.com/sirupsen/logrus" +) + +func listCoreValuesHandler(coreValueSvc corevalues.Service) http.HandlerFunc { + return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + vars := mux.Vars(req) + var organisationID string = "" + if vars["organisation_id"] != "" { + organisationID = vars["organisation_id"] + } + + coreValues, err := coreValueSvc.ListCoreValues(req.Context(), organisationID) + if err != nil { + + apperrors.ErrorResp(rw, err) + return + } + + dto.Repsonse(rw, http.StatusOK, dto.SuccessResponse{Data: coreValues}) + }) +} + +func getCoreValueHandler(coreValueSvc corevalues.Service) http.HandlerFunc { + return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + vars := mux.Vars(req) + + coreValue, err := coreValueSvc.GetCoreValue(req.Context(), vars["organisation_id"], vars["id"]) + if err != nil { + apperrors.ErrorResp(rw, err) + return + } + + dto.Repsonse(rw, http.StatusOK, dto.SuccessResponse{Data: coreValue}) + }) +} + +func createCoreValueHandler(coreValueSvc corevalues.Service) http.HandlerFunc { + return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + vars := mux.Vars(req) + const userId int64 = 1 + var coreValue dto.CreateCoreValueReq + err := json.NewDecoder(req.Body).Decode(&coreValue) + if err != nil { + logger.WithField("err", err.Error()).Error("Error while decoding request data") + err = apperrors.JSONParsingErrorReq + apperrors.ErrorResp(rw, err) + return + } + + fmt.Println("orgId (vars) = ", vars["organisation_id"]) + resp, err := coreValueSvc.CreateCoreValue(req.Context(), vars["organisation_id"], userId, coreValue) + if err != nil { + + apperrors.ErrorResp(rw, err) + return + } + + dto.Repsonse(rw, http.StatusCreated, dto.SuccessResponse{Data: resp}) + }) +} + +func deleteCoreValueHandler(coreValueSvc corevalues.Service) http.HandlerFunc { + return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + vars := mux.Vars(req) + const userId int64 = 1 + err := coreValueSvc.DeleteCoreValue(req.Context(), vars["organisation_id"], vars["id"], userId) + if err != nil { + + apperrors.ErrorResp(rw, err) + return + } + + dto.Repsonse(rw, http.StatusOK, dto.SuccessResponse{Data: "Delete successful"}) + }) +} + +func updateCoreValueHandler(coreValueSvc corevalues.Service) http.HandlerFunc { + return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + vars := mux.Vars(req) + + var updateReq dto.UpdateQueryRequest + err := json.NewDecoder(req.Body).Decode(&updateReq) + if err != nil { + logger.WithField("err", err.Error()).Error("Error while decoding request data") + err = apperrors.JSONParsingErrorReq + apperrors.ErrorResp(rw, err) + return + } + + resp, err := coreValueSvc.UpdateCoreValue(req.Context(), vars["organisation_id"], vars["id"], updateReq) + if err != nil { + apperrors.ErrorResp(rw, err) + return + } + + dto.Repsonse(rw, http.StatusOK, dto.SuccessResponse{Data: resp}) + }) +} diff --git a/go-backend/api/coreValues_test.go b/go-backend/api/coreValues_test.go new file mode 100644 index 000000000..567d87e90 --- /dev/null +++ b/go-backend/api/coreValues_test.go @@ -0,0 +1,441 @@ +package api + +import ( + "bytes" + "fmt" + "joshsoftware/peerly/apperrors" + "joshsoftware/peerly/pkg/dto" + "joshsoftware/peerly/service/coreValues/mocks" + + "net/http" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/mock" +) + +func TestListCoreValuesHandler(t *testing.T) { + coreValueSvc := mocks.NewService(t) + listCoreValuesHandler := listCoreValuesHandler(coreValueSvc) + + tests := []struct { + name string + organisationId int + setup func(mock *mocks.Service) + expectedStatusCode int + }{ + { + name: "Success for list corevalues", + organisationId: 1, + setup: func(mockSvc *mocks.Service) { + mockSvc.On("ListCoreValues", mock.Anything, mock.Anything).Return([]dto.ListCoreValuesResp{}, nil).Once() + }, + expectedStatusCode: http.StatusOK, + }, + { + name: "Wrong organisation id for list corevalues", + organisationId: 1, + setup: func(mockSvc *mocks.Service) { + mockSvc.On("ListCoreValues", mock.Anything, mock.Anything).Return([]dto.ListCoreValuesResp{}, apperrors.InvalidOrgId).Once() + }, + expectedStatusCode: http.StatusNotFound, + }, + { + name: "Error in vars string to int conversion", + organisationId: 1, + setup: func(mockSvc *mocks.Service) { + mockSvc.On("ListCoreValues", mock.Anything, mock.Anything).Return([]dto.ListCoreValuesResp{}, apperrors.InternalServerError).Once() + }, + expectedStatusCode: http.StatusInternalServerError, + }, + { + name: "Error in vars ListCoreValues db functions", + organisationId: 1, + setup: func(mockSvc *mocks.Service) { + mockSvc.On("ListCoreValues", mock.Anything, mock.Anything).Return([]dto.ListCoreValuesResp{}, apperrors.InternalServerError).Once() + }, + expectedStatusCode: http.StatusInternalServerError, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + test.setup(coreValueSvc) + + req, err := http.NewRequest("GET", fmt.Sprintf("/organisations/%d/core_values", test.organisationId), bytes.NewBuffer([]byte(""))) + if err != nil { + t.Fatal(err) + return + } + + rr := httptest.NewRecorder() + handler := http.HandlerFunc(listCoreValuesHandler) + handler.ServeHTTP(rr, req) + + fmt.Println("Error") + + if rr.Result().StatusCode != test.expectedStatusCode { + t.Errorf("Expected %d but got %d", test.expectedStatusCode, rr.Result().StatusCode) + } + }) + } +} + +func TestGetCoreValueHandler(t *testing.T) { + coreValueSvc := mocks.NewService(t) + getCoreValueHandler := getCoreValueHandler(coreValueSvc) + + tests := []struct { + name string + organisationId int + coreValueId int + setup func(mock *mocks.Service) + expectedStatusCode int + }{ + { + name: "Success for get corevalue", + organisationId: 1, + coreValueId: 1, + setup: func(mockSvc *mocks.Service) { + mockSvc.On("GetCoreValue", mock.Anything, mock.Anything, mock.Anything).Return(dto.GetCoreValueResp{}, nil).Once() + }, + expectedStatusCode: http.StatusOK, + }, + { + name: "Wrong organisation id for list corevalues", + organisationId: 1, + coreValueId: 1, + setup: func(mockSvc *mocks.Service) { + mockSvc.On("GetCoreValue", mock.Anything, mock.Anything, mock.Anything).Return(dto.GetCoreValueResp{}, apperrors.InvalidOrgId).Once() + }, + expectedStatusCode: http.StatusNotFound, + }, + { + name: "Error in vars string to int conversion", + organisationId: 1, + coreValueId: 1, + setup: func(mockSvc *mocks.Service) { + mockSvc.On("GetCoreValue", mock.Anything, mock.Anything, mock.Anything).Return(dto.GetCoreValueResp{}, apperrors.InternalServerError).Once() + }, + expectedStatusCode: http.StatusInternalServerError, + }, + { + name: "Error in GetCoreValue db function", + organisationId: 1, + coreValueId: 1, + setup: func(mockSvc *mocks.Service) { + mockSvc.On("GetCoreValue", mock.Anything, mock.Anything, mock.Anything).Return(dto.GetCoreValueResp{}, apperrors.InvalidCoreValueData).Once() + }, + expectedStatusCode: http.StatusNotFound, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + test.setup(coreValueSvc) + + req, err := http.NewRequest("GET", fmt.Sprintf("/organisations/%d/core_values/%d", test.organisationId, test.coreValueId), bytes.NewBuffer([]byte(""))) + if err != nil { + t.Fatal(err) + return + } + + rr := httptest.NewRecorder() + handler := http.HandlerFunc(getCoreValueHandler) + handler.ServeHTTP(rr, req) + + fmt.Println("Error") + + if rr.Result().StatusCode != test.expectedStatusCode { + t.Errorf("Expected %d but got %d", test.expectedStatusCode, rr.Result().StatusCode) + } + }) + } +} + +func TestCreateCoreValueHandler(t *testing.T) { + coreValueSvc := mocks.NewService(t) + createCoreValueHandler := createCoreValueHandler(coreValueSvc) + + tests := []struct { + name string + organisationId int + userId int + coreValue string + setup func(mock *mocks.Service) + expectedStatusCode int + }{ + { + name: "Success for create corevalue", + organisationId: 1, + userId: 1, + coreValue: `{ + "text": "corevalue3", + "description": "desc", + "thumbnail_url": "abc" + }`, + setup: func(mockSvc *mocks.Service) { + mockSvc.On("CreateCoreValue", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(dto.CreateCoreValueResp{}, nil).Once() + }, + expectedStatusCode: http.StatusCreated, + }, + { + name: "Text missing in json request", + organisationId: 1, + userId: 1, + coreValue: `{ + "description": "desc", + "thumbnail_url": "abc" + }`, + setup: func(mockSvc *mocks.Service) { + mockSvc.On("CreateCoreValue", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(dto.CreateCoreValueResp{}, apperrors.TextFieldBlank).Once() + }, + expectedStatusCode: http.StatusBadRequest, + }, + { + name: "Description missing in json request", + organisationId: 1, + userId: 1, + coreValue: `{ + "text": "corevalue3", + "thumbnail_url": "abc" + }`, + setup: func(mockSvc *mocks.Service) { + mockSvc.On("CreateCoreValue", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(dto.CreateCoreValueResp{}, apperrors.DescFieldBlank).Once() + }, + expectedStatusCode: http.StatusBadRequest, + }, + { + name: "Wrong parent id", + organisationId: 1, + userId: 1, + coreValue: `{ + "text": "corevalue3", + "description": "desc", + "thumbnail_url": "abc", + "parent_id": 0 + }`, + setup: func(mockSvc *mocks.Service) { + mockSvc.On("CreateCoreValue", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(dto.CreateCoreValueResp{}, apperrors.InvalidParentValue).Once() + }, + expectedStatusCode: http.StatusNotFound, + }, + { + name: "Error in CreateCoreValues db function", + organisationId: 1, + userId: 1, + coreValue: `{ + "text": "corevalue3", + "description": "desc", + "thumbnail_url": "abc", + "parent_id": 1 + }`, + setup: func(mockSvc *mocks.Service) { + mockSvc.On("CreateCoreValue", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(dto.CreateCoreValueResp{}, apperrors.InternalServerError).Once() + }, + expectedStatusCode: http.StatusInternalServerError, + }, + { + name: "Wrong organisation id", + organisationId: 0, + userId: 1, + coreValue: `{ + "text": "corevalue3", + "description": "desc", + "thumbnail_url": "abc", + "parent_id": 1 + }`, + setup: func(mockSvc *mocks.Service) { + mockSvc.On("CreateCoreValue", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(dto.CreateCoreValueResp{}, apperrors.InvalidOrgId).Once() + }, + expectedStatusCode: http.StatusNotFound, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + test.setup(coreValueSvc) + + req, err := http.NewRequest("POST", fmt.Sprintf("/organisations/%d/core_values", test.organisationId), bytes.NewBuffer([]byte(test.coreValue))) + if err != nil { + t.Fatal(err) + return + } + + rr := httptest.NewRecorder() + handler := http.HandlerFunc(createCoreValueHandler) + handler.ServeHTTP(rr, req) + + fmt.Println("Error") + + if rr.Result().StatusCode != test.expectedStatusCode { + t.Errorf("Expected %d but got %d", test.expectedStatusCode, rr.Result().StatusCode) + } + }) + } +} + +func TestDeleteCoreValueHandler(t *testing.T) { + coreValueSvc := mocks.NewService(t) + deleteCoreValueHandler := deleteCoreValueHandler(coreValueSvc) + + tests := []struct { + name string + organisationId int + coreValueId int + setup func(mock *mocks.Service) + expectedStatusCode int + }{ + { + name: "Success for delete corevalue", + organisationId: 1, + coreValueId: 1, + setup: func(mockSvc *mocks.Service) { + mockSvc.On("DeleteCoreValue", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Once() + }, + expectedStatusCode: http.StatusOK, + }, + { + name: "Wrong organisation id", + organisationId: 0, + coreValueId: 1, + setup: func(mockSvc *mocks.Service) { + mockSvc.On("DeleteCoreValue", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(apperrors.InvalidOrgId).Once() + }, + expectedStatusCode: http.StatusNotFound, + }, + { + name: "Wrong corevalue id", + organisationId: 1, + coreValueId: 1, + setup: func(mockSvc *mocks.Service) { + mockSvc.On("DeleteCoreValue", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(apperrors.InvalidCoreValueData).Once() + }, + expectedStatusCode: http.StatusNotFound, + }, + { + name: "Error in DeleteCoreValue db function", + organisationId: 1, + coreValueId: 1, + setup: func(mockSvc *mocks.Service) { + mockSvc.On("DeleteCoreValue", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(apperrors.InternalServerError).Once() + }, + expectedStatusCode: http.StatusInternalServerError, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + test.setup(coreValueSvc) + + req, err := http.NewRequest("DELETE", fmt.Sprintf("/organisations/%d/core_values/%d", test.organisationId, test.coreValueId), bytes.NewBuffer([]byte(""))) + if err != nil { + t.Fatal(err) + return + } + + rr := httptest.NewRecorder() + handler := http.HandlerFunc(deleteCoreValueHandler) + handler.ServeHTTP(rr, req) + + fmt.Println("Error") + + if rr.Result().StatusCode != test.expectedStatusCode { + t.Errorf("Expected %d but got %d", test.expectedStatusCode, rr.Result().StatusCode) + } + }) + } +} + +func TestUpdateCoreValueHandler(t *testing.T) { + coreValueSvc := mocks.NewService(t) + updateCoreValueHandler := updateCoreValueHandler(coreValueSvc) + + tests := []struct { + name string + organisationId int + coreValueId int + input string + setup func(mock *mocks.Service) + expectedStatusCode int + }{ + { + name: "Success for update corevalue", + organisationId: 1, + coreValueId: 1, + input: `{ + "text": "corevalue3", + "description": "desc", + "thumbnail_url": "abc" + }`, + setup: func(mockSvc *mocks.Service) { + mockSvc.On("UpdateCoreValue", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(dto.UpdateCoreValuesResp{}, nil).Once() + }, + expectedStatusCode: http.StatusOK, + }, + { + name: "Wrong organisation id", + organisationId: 1, + coreValueId: 1, + input: `{ + "text": "corevalue3", + "description": "desc", + "thumbnail_url": "abc" + }`, + setup: func(mockSvc *mocks.Service) { + mockSvc.On("UpdateCoreValue", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(dto.UpdateCoreValuesResp{}, apperrors.InvalidOrgId).Once() + }, + expectedStatusCode: http.StatusNotFound, + }, + { + name: "Wrong corevalue id", + organisationId: 1, + coreValueId: 1, + input: `{ + "text": "corevalue3", + "description": "desc", + "thumbnail_url": "abc" + }`, + setup: func(mockSvc *mocks.Service) { + mockSvc.On("UpdateCoreValue", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(dto.UpdateCoreValuesResp{}, apperrors.InvalidCoreValueData).Once() + }, + expectedStatusCode: http.StatusNotFound, + }, + { + name: "Error in UpdateCoreValue db function", + organisationId: 1, + coreValueId: 1, + input: `{ + "text": "corevalue3", + "description": "desc", + "thumbnail_url": "abc" + }`, + setup: func(mockSvc *mocks.Service) { + mockSvc.On("UpdateCoreValue", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(dto.UpdateCoreValuesResp{}, apperrors.InternalServerError).Once() + }, + expectedStatusCode: http.StatusInternalServerError, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + test.setup(coreValueSvc) + + req, err := http.NewRequest("PUT", fmt.Sprintf("/organisations/%d/core_values/%d", test.organisationId, test.coreValueId), bytes.NewBuffer([]byte(test.input))) + if err != nil { + t.Fatal(err) + return + } + + rr := httptest.NewRecorder() + handler := http.HandlerFunc(updateCoreValueHandler) + handler.ServeHTTP(rr, req) + + fmt.Println("Error") + + if rr.Result().StatusCode != test.expectedStatusCode { + t.Errorf("Expected %d but got %d", test.expectedStatusCode, rr.Result().StatusCode) + } + }) + } +} diff --git a/go-backend/api/ping_http.go b/go-backend/api/ping_http.go new file mode 100644 index 000000000..e50616696 --- /dev/null +++ b/go-backend/api/ping_http.go @@ -0,0 +1,26 @@ +package api + +import ( + "encoding/json" + "net/http" + + logger "github.com/sirupsen/logrus" +) + +// PingResponse - a basic struct to represent the JSON response for /ping +type PingResponse struct { + Message string `json:"message"` +} + +func pingHandler(rw http.ResponseWriter, req *http.Request) { + response := PingResponse{Message: "pong"} + + respBytes, err := json.Marshal(response) + if err != nil { + logger.WithField("err", err.Error()).Error("Error marshalling ping response") + rw.WriteHeader(http.StatusInternalServerError) + } + + rw.Header().Add("Content-Type", "application/json") + rw.Write(respBytes) +} diff --git a/go-backend/api/router.go b/go-backend/api/router.go new file mode 100644 index 000000000..f5a2d8428 --- /dev/null +++ b/go-backend/api/router.go @@ -0,0 +1,45 @@ +package api + +import ( + "fmt" + "net/http" + + "joshsoftware/peerly/config" + "joshsoftware/peerly/service" + + "github.com/gorilla/mux" +) + +const ( + versionHeader = "Accept-Version" + authHeader = "X-Auth-Token" +) + +// InitRouter - The routing mechanism. Mux helps us define handler functions and the access methods +func InitRouter(deps service.Dependencies) (router *mux.Router) { + router = mux.NewRouter() + + router.HandleFunc("/ping", pingHandler).Methods(http.MethodGet) + // Version 1 API management + v1 := fmt.Sprintf("application/vnd.%s.v1", config.AppName()) + + //core values + router.Handle("/organisations/{organisation_id:[0-9]+}/core_values/{id:[0-9]+}", jwtAuthMiddleware(getCoreValueHandler(deps.CoreValueService))).Methods(http.MethodGet).Headers(versionHeader, v1) + + router.Handle("/organisations/{organisation_id:[0-9]+}/core_values", jwtAuthMiddleware(listCoreValuesHandler(deps.CoreValueService))).Methods(http.MethodGet).Headers(versionHeader, v1) + + router.Handle("/organisations/{organisation_id:[0-9]+}/core_values", jwtAuthMiddleware(createCoreValueHandler(deps.CoreValueService))).Methods(http.MethodPost).Headers(versionHeader, v1) + + router.Handle("/organisations/{organisation_id:[0-9]+}/core_values/{id:[0-9]+}", jwtAuthMiddleware(deleteCoreValueHandler(deps.CoreValueService))).Methods(http.MethodDelete).Headers(versionHeader, v1) + + router.Handle("/organisations/{organisation_id:[0-9]+}/core_values/{id:[0-9]+}", jwtAuthMiddleware(updateCoreValueHandler(deps.CoreValueService))).Methods(http.MethodPut).Headers(versionHeader, v1) + + return +} + +// JWT token verification +func jwtAuthMiddleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + next.ServeHTTP(w, r) + }) +} diff --git a/go-backend/api/validations/coreValues.go b/go-backend/api/validations/coreValues.go new file mode 100644 index 000000000..958ae1a62 --- /dev/null +++ b/go-backend/api/validations/coreValues.go @@ -0,0 +1 @@ +package validation diff --git a/go-backend/apperrors/apperrors.go b/go-backend/apperrors/apperrors.go index e633b0759..971567562 100644 --- a/go-backend/apperrors/apperrors.go +++ b/go-backend/apperrors/apperrors.go @@ -115,3 +115,63 @@ var ErrFailedToCreate = errors.New("Failed to create database record") // ErrUnknown - Used when an unknown/unexpected error has ocurred. Try to avoid over-using this. var ErrUnknown = errors.New("unknown/unexpected error has occurred") + +//coreValues + +type CustomError string + +func (e CustomError) Error() string { + return string(e) +} + +const ( + BadRequest = CustomError("Bad request") + InvalidId = CustomError("Invalid id") + InternalServerError = CustomError("Internal server error") + JSONParsingErrorReq = CustomError("error in parsing request in json") + JSONParsingErrorResp = CustomError("error in parsing response in json") + OutOfRange = CustomError("request value is out of range") + //repeated + OrganizationNotFound = CustomError("organization of given id not found") + InvalidContactEmail = CustomError("Contact email is already present") + InvalidDomainName = CustomError("Domain name is already present") + InvalidCoreValueData = CustomError("Invalid corevalue data") + TextFieldBlank = CustomError("Text field cannot be blank") + DescFieldBlank = CustomError("Description cannot be blank") + InvalidParentValue = CustomError("Invalid parent core value") + InvalidOrgId = CustomError("Invalid organisation") + UniqueCoreValue = CustomError("Choose a unique coreValue name") +) + +// helper functions +func ErrorResp(rw http.ResponseWriter, err error) { + // Create the ErrorStruct object for later use + statusCode := GetHTTPStatusCode(err) + errObj := ErrorStruct{ + Message: err.Error(), + Status: statusCode, + } + + errJSON, err := json.Marshal(&errObj) + if err != nil { + log.Warn(err, "Error in AppErrors marshalling JSON", err) + } + rw.WriteHeader(statusCode) + rw.Header().Add("Content-Type", "application/json") + rw.Write(errJSON) +} + +func GetHTTPStatusCode(err error) int { + switch err { + case InternalServerError, JSONParsingErrorResp: + return http.StatusInternalServerError + case OrganizationNotFound, InvalidCoreValueData, InvalidParentValue, InvalidOrgId: + return http.StatusNotFound + case InvalidId, JSONParsingErrorReq, TextFieldBlank, DescFieldBlank, UniqueCoreValue: + return http.StatusBadRequest + case InvalidContactEmail, InvalidDomainName: + return http.StatusConflict + default: + return http.StatusInternalServerError + } +} diff --git a/go-backend/db/core_value.go b/go-backend/db/core_value.go index 5f9af5511..592075cb3 100644 --- a/go-backend/db/core_value.go +++ b/go-backend/db/core_value.go @@ -2,20 +2,49 @@ package db import ( "context" + "fmt" + "joshsoftware/peerly/apperrors" + "joshsoftware/peerly/pkg/dto" "time" + "github.com/jmoiron/sqlx" logger "github.com/sirupsen/logrus" ) +type coreValueStore struct { + DB *sqlx.DB +} + +type CoreValueStorer interface { + ListCoreValues(ctx context.Context, organisationID int64) (coreValues []dto.ListCoreValuesResp, err error) + GetCoreValue(ctx context.Context, organisationID, coreValueID int64) (coreValue dto.GetCoreValueResp, err error) + CreateCoreValue(ctx context.Context, organisationID int64, userId int64, coreValue dto.CreateCoreValueReq) (resp dto.CreateCoreValueResp, err error) + DeleteCoreValue(ctx context.Context, organisationID, coreValueID int64, userId int64) (err error) + UpdateCoreValue(ctx context.Context, organisationID, coreValueID int64, coreValue dto.UpdateQueryRequest) (resp dto.UpdateCoreValuesResp, err error) + CheckOrganisation(ctx context.Context, organisationId int64) (err error) + CheckUniqueCoreVal(ctx context.Context, organisationId int64, text string) (res bool, err error) +} + +func NewCoreValueRepo(db *sqlx.DB) CoreValueStorer { + return &coreValueStore{ + DB: db, + } +} + const ( - listCoreValuesQuery = `SELECT id, org_id, text, description, parent_id FROM core_values WHERE org_id = $1` - getCoreValueQuery = `SELECT id, org_id, text, description, parent_id FROM core_values WHERE org_id = $1 and id = $2` + listCoreValuesQuery = `SELECT id, org_id, text, description, parent_id, created_at, updated_at FROM core_values WHERE org_id = $1 and soft_delete = false` + getCoreValueQuery = `SELECT id, org_id, text, description, parent_id, soft_delete FROM core_values WHERE org_id = $1 and id = $2` createCoreValueQuery = `INSERT INTO core_values (org_id, text, - description, parent_id, thumbnail_url, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING id, org_id, text, description, parent_id, thumbnail_url` - deleteSubCoreValueQuery = `DELETE FROM core_values WHERE org_id = $1 and parent_id = $2` - deleteCoreValueQuery = `DELETE FROM core_values WHERE org_id = $1 and id = $2` - updateCoreValueQuery = `UPDATE core_values SET (text, description, updated_at) = - ($1, $2, $3) where id = $4 and org_id = $5 RETURNING id, org_id, text, description, parent_id` + description, parent_id, thumbnail_url,created_by, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING id, org_id, text, description, parent_id, thumbnail_url, created_by, created_at` + // deleteSubCoreValueQuery = `DELETE FROM core_values WHERE orgId = $1 and parentId = $2` + deleteSubCoreValueQuery = `UPDATE core_values SET soft_delete = true, soft_delete_by = $1, updated_at = $2 WHERE org_id = $3 and parent_id = $4` + // deleteCoreValueQuery = `DELETE FROM core_values WHERE orgId = $1 and id = $2` + deleteCoreValueQuery = `UPDATE core_values SET soft_delete = true, soft_delete_by = $1, updated_at = $2 WHERE org_id = $3 and id = $4` + updateCoreValueQuery = `UPDATE core_values SET (text, description, thumbnail_url, updated_at) = + ($1, $2, $3, $4) where id = $5 and org_id = $6 RETURNING id, org_id, text, description, parent_id, thumbnail_url, updated_at` + + checkOrganisationQuery = `SELECT id from organizations WHERE id = $1` + checkUniqueCoreVal = `SELECT id from core_values WHERE org_id = $1 and text = $2` ) // CoreValue - struct representing a core value object @@ -26,50 +55,15 @@ type CoreValue struct { Description string `db:"description" json:"description"` ParentID *int64 `db:"parent_id" json:"parent_id"` ThumbnailURL *string `db:"thumbnail_url" json:"thumbnail_url"` - CreatedAt time.Time `db:"created_at" json:"-"` - UpdatedAt time.Time `db:"updated_at" json:"-"` + CreatedAt time.Time `db:"created_at"` + UpdatedAt time.Time `db:"updated_at"` + SoftDelete bool `db:"soft_delete"` + SoftDeleteBy int64 `db:"soft_delete_by"` + CreatedBy int64 `db:"created_by"` } -func validateParentCoreValue(ctx context.Context, storer Storer, organisationID, coreValueID int64) (ok bool) { - coreValue, err := storer.GetCoreValue(ctx, organisationID, coreValueID) - if err != nil { - logger.WithField("err", err.Error()).Error("Parent core value id not present") - return - } - - if coreValue.ParentID != nil { - logger.Error("Invalid parent core value id") - return - } - - return true -} - -// Validate - ensures the core value object has all the info it needs -func (coreValue CoreValue) Validate(ctx context.Context, storer Storer, organisationID int64) (valid bool, errFields map[string]string) { - errFields = make(map[string]string) - - if coreValue.Text == "" { - errFields["text"] = "Can't be blank" - } - if coreValue.Description == "" { - errFields["description"] = "Can't be blank" - } - if coreValue.ParentID != nil { - if !validateParentCoreValue(ctx, storer, organisationID, *coreValue.ParentID) { - errFields["parent_id"] = "Invalid parent core value" - } - } - - if len(errFields) == 0 { - valid = true - } - return -} - -func (s *pgStore) ListCoreValues(ctx context.Context, organisationID int64) (coreValues []CoreValue, err error) { - coreValues = make([]CoreValue, 0) - err = s.db.SelectContext( +func (cs *coreValueStore) ListCoreValues(ctx context.Context, organisationID int64) (coreValues []dto.ListCoreValuesResp, err error) { + err = cs.DB.SelectContext( ctx, &coreValues, listCoreValuesQuery, @@ -78,8 +72,8 @@ func (s *pgStore) ListCoreValues(ctx context.Context, organisationID int64) (cor if err != nil { logger.WithFields(logger.Fields{ - "err": err.Error(), - "org_id": organisationID, + "err": err.Error(), + "orgId": organisationID, }).Error("Error while getting core values") return } @@ -87,8 +81,8 @@ func (s *pgStore) ListCoreValues(ctx context.Context, organisationID int64) (cor return } -func (s *pgStore) GetCoreValue(ctx context.Context, organisationID, coreValueID int64) (coreValue CoreValue, err error) { - err = s.db.GetContext( +func (cs *coreValueStore) GetCoreValue(ctx context.Context, organisationID, coreValueID int64) (coreValue dto.GetCoreValueResp, err error) { + err = cs.DB.GetContext( ctx, &coreValue, getCoreValueQuery, @@ -97,19 +91,20 @@ func (s *pgStore) GetCoreValue(ctx context.Context, organisationID, coreValueID ) if err != nil { logger.WithFields(logger.Fields{ - "err": err.Error(), - "org_id": organisationID, - "core_value_id": coreValueID, + "err": err.Error(), + "orgId": organisationID, + "coreValueId": coreValueID, }).Error("Error while getting core value") + err = apperrors.InvalidCoreValueData return } return } -func (s *pgStore) CreateCoreValue(ctx context.Context, organisationID int64, coreValue CoreValue) (resp CoreValue, err error) { +func (cs *coreValueStore) CreateCoreValue(ctx context.Context, organisationID int64, userId int64, coreValue dto.CreateCoreValueReq) (resp dto.CreateCoreValueResp, err error) { now := time.Now() - err = s.db.GetContext( + err = cs.DB.GetContext( ctx, &resp, createCoreValueQuery, @@ -118,6 +113,7 @@ func (s *pgStore) CreateCoreValue(ctx context.Context, organisationID int64, cor coreValue.Description, coreValue.ParentID, coreValue.ThumbnailURL, + userId, now, now, ) @@ -133,25 +129,30 @@ func (s *pgStore) CreateCoreValue(ctx context.Context, organisationID int64, cor return } -func (s *pgStore) DeleteCoreValue(ctx context.Context, organisationID, coreValueID int64) (err error) { - _, err = s.db.ExecContext( +func (cs *coreValueStore) DeleteCoreValue(ctx context.Context, organisationID, coreValueID int64, userId int64) (err error) { + now := time.Now() + _, err = cs.DB.ExecContext( ctx, deleteSubCoreValueQuery, + userId, + now, organisationID, coreValueID, ) if err != nil { logger.WithFields(logger.Fields{ - "err": err.Error(), - "org_id": organisationID, - "core_value_id": coreValueID, + "err": err.Error(), + "orgId": organisationID, + "coreValueId": coreValueID, }).Error("Error while deleting sub core value") return } - _, err = s.db.ExecContext( + _, err = cs.DB.ExecContext( ctx, deleteCoreValueQuery, + userId, + now, organisationID, coreValueID, ) @@ -167,27 +168,81 @@ func (s *pgStore) DeleteCoreValue(ctx context.Context, organisationID, coreValue return } -func (s *pgStore) UpdateCoreValue(ctx context.Context, organisationID, coreValueID int64, coreValue CoreValue) (resp CoreValue, err error) { +func (cs *coreValueStore) UpdateCoreValue(ctx context.Context, organisationID int64, coreValueID int64, updateReq dto.UpdateQueryRequest) (resp dto.UpdateCoreValuesResp, err error) { now := time.Now() - err = s.db.GetContext( + err = cs.DB.GetContext( ctx, &resp, updateCoreValueQuery, - coreValue.Text, - coreValue.Description, + updateReq.Text, + updateReq.Description, + updateReq.ThumbnailUrl, now, coreValueID, organisationID, ) if err != nil { logger.WithFields(logger.Fields{ - "err": err.Error(), - "org_id": organisationID, - "core_value_id": coreValueID, - "core_value_params": coreValue, + "err": err.Error(), + "org_id": organisationID, + "core_value_id": coreValueID, }).Error("Error while updating core value") return } return } + +func (cs *coreValueStore) CheckOrganisation(ctx context.Context, organisationId int64) (err error) { + resp := []int64{} + err = cs.DB.SelectContext( + ctx, + &resp, + checkOrganisationQuery, + organisationId, + ) + + if len(resp) <= 0 { + err = apperrors.InvalidOrgId + } + + if err != nil { + logger.WithFields(logger.Fields{ + "err": err.Error(), + "org_id": organisationId, + }).Error("Error while checking organisation") + err = apperrors.InvalidOrgId + } + + return +} + +func (cs *coreValueStore) CheckUniqueCoreVal(ctx context.Context, organisationId int64, text string) (isUnique bool, err error) { + isUnique = false + resp := []int64{} + err = cs.DB.SelectContext( + ctx, + &resp, + checkUniqueCoreVal, + organisationId, + text, + ) + + fmt.Println("resp: ", resp) + fmt.Println("err: ", err) + + if err != nil { + logger.WithFields(logger.Fields{ + "err": err.Error(), + }).Error("Error while checking organisation") + err = apperrors.InternalServerError + return + } + + if len(resp) <= 0 { + isUnique = true + return + } + + return +} diff --git a/go-backend/db/db.go b/go-backend/db/db.go index b08447e00..792d71d14 100644 --- a/go-backend/db/db.go +++ b/go-backend/db/db.go @@ -41,13 +41,6 @@ type Storer interface { GetRoleByID(context.Context, int) (Role, error) GetRoleByName(context.Context, string) (Role, error) - // Core values - ListCoreValues(context.Context, int64) ([]CoreValue, error) - GetCoreValue(context.Context, int64, int64) (CoreValue, error) - CreateCoreValue(context.Context, int64, CoreValue) (CoreValue, error) - DeleteCoreValue(context.Context, int64, int64) error - UpdateCoreValue(context.Context, int64, int64, CoreValue) (CoreValue, error) - //RecognitionHi5 CreateRecognitionHi5(context.Context, RecognitionHi5, int) error diff --git a/go-backend/db/mock.go b/go-backend/db/mock.go deleted file mode 100644 index 6edc591c3..000000000 --- a/go-backend/db/mock.go +++ /dev/null @@ -1,210 +0,0 @@ -package db - -import ( - "context" - "fmt" - - "github.com/bxcodec/faker/v3" - "github.com/stretchr/testify/mock" -) - -// DBMockStore - test mock struct -type DBMockStore struct { - mock.Mock -} - -// GetRoleByID - test mock -func (m *DBMockStore) GetRoleByID(ctx context.Context, id int) (role Role, err error) { - args := m.Called(ctx) - return args.Get(0).(Role), args.Error(1) -} - -// GetRoleByName - test mock -func (m *DBMockStore) GetRoleByName(ctx context.Context, name string) (role Role, err error) { - args := m.Called(ctx) - return args.Get(0).(Role), args.Error(1) -} - -// GetOrganizationByDomainName - test mock -func (m *DBMockStore) GetOrganizationByDomainName(ctx context.Context, domainName string) (organization Organization, err error) { - args := m.Called(ctx) - return args.Get(0).(Organization), args.Error(1) -} - -// ListUsers - test mock -func (m *DBMockStore) ListUsers(ctx context.Context) (users []User, err error) { - args := m.Called(ctx) - return args.Get(0).([]User), args.Error(1) -} - -// CleanBlacklistedTokens - test mock -func (m *DBMockStore) CleanBlacklistedTokens() (err error) { - return -} - -// CreateUserBlacklistedToken - Mock for testing -func (m *DBMockStore) CreateUserBlacklistedToken(ctx context.Context, blacklistedToken UserBlacklistedToken) (err error) { - return -} - -// GetUserByEmail - Mock for retrieving a user. Just return a fake user object. -func (m *DBMockStore) GetUserByEmail(ctx context.Context, email string) (user User, err error) { - user = User{} - err = faker.FakeData(&user) - if err != nil { - fmt.Printf("Error creating mock user for db.GetUserByEmail. %+v", user) - } - - user.Email = email // Alter the user's email to be what was passed in since faker will create it at random - return -} - -// CreateNewUser - Mock for database new user creation. Just returns a fake user object -func (m *DBMockStore) CreateNewUser(ctx context.Context, u User) (newUser User, err error) { - args := m.Called(ctx, u) - return args.Get(0).(User), args.Error(1) -} - -// GetUserByID - Mock to retrieve a user by their ID (BIGSERIAL in PostgreSQL, int in Golang) -func (m *DBMockStore) GetUserByID(ctx context.Context, id int) (user User, err error) { - args := m.Called(ctx, id) - return args.Get(0).(User), args.Error(1) -} - -// ListOrganizations - returns a list of organization objects from the database -func (m *DBMockStore) ListOrganizations(ctx context.Context) (organizations []Organization, err error) { - args := m.Called(ctx) - return args.Get(0).([]Organization), args.Error(1) -} - -// ListCoreValues - returns a list of core value objects from the database -func (m *DBMockStore) ListCoreValues(ctx context.Context, organisationID int64) (coreValues []CoreValue, err error) { - args := m.Called(ctx, organisationID) - return args.Get(0).([]CoreValue), args.Error(1) -} - -// GetCoreValue - Mock to retrieve a core value by their organization ID and core value ID -func (m *DBMockStore) GetCoreValue(ctx context.Context, organisationID, coreValueID int64) (coreValue CoreValue, err error) { - args := m.Called(ctx, organisationID, coreValueID) - return args.Get(0).(CoreValue), args.Error(1) -} - -// CreateCoreValue - Creates core value for an organization -func (m *DBMockStore) CreateCoreValue(ctx context.Context, organisationID int64, coreValue CoreValue) (CoreValue, error) { - args := m.Called(ctx, organisationID, coreValue) - return args.Get(0).(CoreValue), args.Error(1) -} - -// DeleteCoreValue - Deletes the core value of the organization -func (m *DBMockStore) DeleteCoreValue(ctx context.Context, organisationID, coreValueID int64) (err error) { - args := m.Called(ctx, organisationID, coreValueID) - return args.Error(0) -} - -// UpdateCoreValue - updates core value for organization -func (m *DBMockStore) UpdateCoreValue(ctx context.Context, organisationID, coreValueID int64, coreValue CoreValue) (CoreValue, error) { - args := m.Called(ctx, organisationID, coreValueID, coreValue) - return args.Get(0).(CoreValue), args.Error(1) -} - -// CreateOrganization - creates an organization -func (m *DBMockStore) CreateOrganization(ctx context.Context, org Organization) (updatedOrg Organization, err error) { - args := m.Called(ctx, org) - return args.Get(0).(Organization), args.Error(1) -} - -// GetOrganization - retrieves an organization by its id -func (m *DBMockStore) GetOrganization(ctx context.Context, id int) (organization Organization, err error) { - args := m.Called(ctx, id) - return args.Get(0).(Organization), args.Error(1) -} - -// DeleteOrganization - removes an organization from the database given its id -// TODO: How do we want to handle deleting an org when the user's org_id is a foreign key to the org being deleted? -func (m *DBMockStore) DeleteOrganization(ctx context.Context, id int) (err error) { - args := m.Called(ctx, id) - return args.Error(0) -} - -// UpdateOrganization - given the id and an organization object, update the database to match that organization object -func (m *DBMockStore) UpdateOrganization(ctx context.Context, org Organization, id int) (updatedOrg Organization, err error) { - args := m.Called(ctx, org, id) - return args.Get(0).(Organization), args.Error(1) -} -func (m *DBMockStore) ShowRecognition(ctx context.Context, recognitionID int) (recognition Recognition, err error) { - args := m.Called(ctx) - return args.Get(0).(Recognition), args.Error(1) -} - -func (m *DBMockStore) CreateBadge(ctx context.Context, badge Badge) (createdBadge Badge, err error) { - args := m.Called(ctx, badge) - return args.Get(0).(Badge), args.Error(1) -} - -func (m *DBMockStore) ListBadges(ctx context.Context, org_id int) (badges []Badge, err error) { - args := m.Called(ctx, org_id) - return args.Get(0).([]Badge), args.Error(1) -} - -func (m *DBMockStore) ShowBadge(ctx context.Context, badge Badge) (badges Badge, err error) { - args := m.Called(ctx, badge) - return args.Get(0).(Badge), args.Error(1) -} - -func (m *DBMockStore) UpdateBadge(ctx context.Context, badge Badge) (badges Badge, err error) { - args := m.Called(ctx, badge) - return args.Get(0).(Badge), args.Error(1) -} - -func (m *DBMockStore) DeleteBadge(ctx context.Context, org_id int, id int) (err error) { - args := m.Called(ctx, org_id, id) - return args.Error(1) -} - -func (m *DBMockStore) CreateRecognitionHi5(ctx context.Context, recognitionHi5 RecognitionHi5, recognitionID int) (err error) { - args := m.Called(ctx, recognitionHi5, recognitionID) - return args.Error(0) -} - -func (m *DBMockStore) GetUser(ctx context.Context, id int) (user User, err error) { - args := m.Called(ctx, id) - return args.Get(0).(User), args.Error(1) -} -func (m *DBMockStore) UpdateUser(ctx context.Context, user User, id int) (updatedUser User, err error) { - args := m.Called(ctx, user, id) - return args.Get(0).(User), args.Error(1) -} -func (m *DBMockStore) GetUserByOrganization(ctx context.Context, id, orgID int) (user User, err error) { - args := m.Called(ctx, id, orgID) - return args.Get(0).(User), args.Error(1) -} - -// ResetHi5QuotaBalanceJob - test mock -func (m *DBMockStore) ResetHi5QuotaBalanceJob() (err error) { - return -} - -func (m *DBMockStore) CreateRecognition(ctx context.Context, recognition Recognition) (createdRecognition Recognition, err error) { - args := m.Called(ctx) - return args.Get(0).(Recognition), args.Error(1) -} - -func (m *DBMockStore) ListRecognitions(ctx context.Context) (users []Recognition, err error) { - args := m.Called(ctx) - return args.Get(0).([]Recognition), args.Error(1) -} - -func (m *DBMockStore) ListRecognitionsWithFilter(ctx context.Context, filters map[string]int) (users []Recognition, err error) { - args := m.Called(ctx) - return args.Get(0).([]Recognition), args.Error(1) -} - -func (m *DBMockStore) CreateReportedRecognition(ctx context.Context, recognitionID int64, reportedRecognition ReportedRecognition) (resp ReportedRecognition, err error) { - args := m.Called(ctx, recognitionID, reportedRecognition) - return args.Get(0).(ReportedRecognition), args.Error(1) -} - -func (m *DBMockStore) CreateRecognitionModeration(ctx context.Context, recognitionID int64, recognitionModeration RecognitionModeration) (resp RecognitionModeration, err error) { - args := m.Called(ctx, recognitionID, recognitionModeration) - return args.Get(0).(RecognitionModeration), args.Error(1) -} diff --git a/go-backend/db/mocks/CoreValueStorer.go b/go-backend/db/mocks/CoreValueStorer.go new file mode 100644 index 000000000..82a416105 --- /dev/null +++ b/go-backend/db/mocks/CoreValueStorer.go @@ -0,0 +1,163 @@ +// Code generated by mockery v1.0.0. DO NOT EDIT. + +package mocks + +import context "context" + +import dto "joshsoftware/peerly/pkg/dto" +import mock "github.com/stretchr/testify/mock" + +// CoreValueStorer is an autogenerated mock type for the CoreValueStorer type +type CoreValueStorer struct { + mock.Mock +} + +// CheckOrganisation provides a mock function with given fields: ctx, organisationId +func (_m *CoreValueStorer) CheckOrganisation(ctx context.Context, organisationId int64) error { + ret := _m.Called(ctx, organisationId) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, int64) error); ok { + r0 = rf(ctx, organisationId) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// CheckUniqueCoreVal provides a mock function with given fields: ctx, organisationId, text +func (_m *CoreValueStorer) CheckUniqueCoreVal(ctx context.Context, organisationId int64, text string) (bool, error) { + ret := _m.Called(ctx, organisationId, text) + + var r0 bool + if rf, ok := ret.Get(0).(func(context.Context, int64, string) bool); ok { + r0 = rf(ctx, organisationId, text) + } else { + r0 = ret.Get(0).(bool) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, int64, string) error); ok { + r1 = rf(ctx, organisationId, text) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CreateCoreValue provides a mock function with given fields: ctx, organisationID, userId, coreValue +func (_m *CoreValueStorer) CreateCoreValue(ctx context.Context, organisationID int64, userId int64, coreValue dto.CreateCoreValueReq) (dto.CreateCoreValueResp, error) { + ret := _m.Called(ctx, organisationID, userId, coreValue) + + var r0 dto.CreateCoreValueResp + if rf, ok := ret.Get(0).(func(context.Context, int64, int64, dto.CreateCoreValueReq) dto.CreateCoreValueResp); ok { + r0 = rf(ctx, organisationID, userId, coreValue) + } else { + r0 = ret.Get(0).(dto.CreateCoreValueResp) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, int64, int64, dto.CreateCoreValueReq) error); ok { + r1 = rf(ctx, organisationID, userId, coreValue) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DeleteCoreValue provides a mock function with given fields: ctx, organisationID, coreValueID, userId +func (_m *CoreValueStorer) DeleteCoreValue(ctx context.Context, organisationID int64, coreValueID int64, userId int64) error { + ret := _m.Called(ctx, organisationID, coreValueID, userId) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, int64, int64, int64) error); ok { + r0 = rf(ctx, organisationID, coreValueID, userId) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// GetCoreValue provides a mock function with given fields: ctx, organisationID, coreValueID +func (_m *CoreValueStorer) GetCoreValue(ctx context.Context, organisationID int64, coreValueID int64) (dto.GetCoreValueResp, error) { + ret := _m.Called(ctx, organisationID, coreValueID) + + var r0 dto.GetCoreValueResp + if rf, ok := ret.Get(0).(func(context.Context, int64, int64) dto.GetCoreValueResp); ok { + r0 = rf(ctx, organisationID, coreValueID) + } else { + r0 = ret.Get(0).(dto.GetCoreValueResp) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, int64, int64) error); ok { + r1 = rf(ctx, organisationID, coreValueID) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ListCoreValues provides a mock function with given fields: ctx, organisationID +func (_m *CoreValueStorer) ListCoreValues(ctx context.Context, organisationID int64) ([]dto.ListCoreValuesResp, error) { + ret := _m.Called(ctx, organisationID) + + var r0 []dto.ListCoreValuesResp + if rf, ok := ret.Get(0).(func(context.Context, int64) []dto.ListCoreValuesResp); ok { + r0 = rf(ctx, organisationID) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]dto.ListCoreValuesResp) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { + r1 = rf(ctx, organisationID) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// UpdateCoreValue provides a mock function with given fields: ctx, organisationID, coreValueID, coreValue +func (_m *CoreValueStorer) UpdateCoreValue(ctx context.Context, organisationID int64, coreValueID int64, coreValue dto.UpdateQueryRequest) (dto.UpdateCoreValuesResp, error) { + ret := _m.Called(ctx, organisationID, coreValueID, coreValue) + + var r0 dto.UpdateCoreValuesResp + if rf, ok := ret.Get(0).(func(context.Context, int64, int64, dto.UpdateQueryRequest) dto.UpdateCoreValuesResp); ok { + r0 = rf(ctx, organisationID, coreValueID, coreValue) + } else { + r0 = ret.Get(0).(dto.UpdateCoreValuesResp) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, int64, int64, dto.UpdateQueryRequest) error); ok { + r1 = rf(ctx, organisationID, coreValueID, coreValue) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// NewArtworkStorer creates a new instance of ArtworkStorer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewCoreValueStorer(t interface { + mock.TestingT + Cleanup(func()) +}) *CoreValueStorer { + mock := &CoreValueStorer{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} + diff --git a/go-backend/db/mocks/Storer.go b/go-backend/db/mocks/Storer.go new file mode 100644 index 000000000..2594163aa --- /dev/null +++ b/go-backend/db/mocks/Storer.go @@ -0,0 +1,624 @@ +// Code generated by mockery v1.0.0. DO NOT EDIT. + +package mocks + +import context "context" +import db "joshsoftware/peerly/db" +import mock "github.com/stretchr/testify/mock" + +// Storer is an autogenerated mock type for the Storer type +type Storer struct { + mock.Mock +} + +// CleanBlacklistedTokens provides a mock function with given fields: +func (_m *Storer) CleanBlacklistedTokens() error { + ret := _m.Called() + + var r0 error + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// CreateBadge provides a mock function with given fields: _a0, _a1 +func (_m *Storer) CreateBadge(_a0 context.Context, _a1 db.Badge) (db.Badge, error) { + ret := _m.Called(_a0, _a1) + + var r0 db.Badge + if rf, ok := ret.Get(0).(func(context.Context, db.Badge) db.Badge); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Get(0).(db.Badge) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, db.Badge) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CreateNewUser provides a mock function with given fields: _a0, _a1 +func (_m *Storer) CreateNewUser(_a0 context.Context, _a1 db.User) (db.User, error) { + ret := _m.Called(_a0, _a1) + + var r0 db.User + if rf, ok := ret.Get(0).(func(context.Context, db.User) db.User); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Get(0).(db.User) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, db.User) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CreateOrganization provides a mock function with given fields: _a0, _a1 +func (_m *Storer) CreateOrganization(_a0 context.Context, _a1 db.Organization) (db.Organization, error) { + ret := _m.Called(_a0, _a1) + + var r0 db.Organization + if rf, ok := ret.Get(0).(func(context.Context, db.Organization) db.Organization); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Get(0).(db.Organization) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, db.Organization) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CreateRecognition provides a mock function with given fields: _a0, _a1 +func (_m *Storer) CreateRecognition(_a0 context.Context, _a1 db.Recognition) (db.Recognition, error) { + ret := _m.Called(_a0, _a1) + + var r0 db.Recognition + if rf, ok := ret.Get(0).(func(context.Context, db.Recognition) db.Recognition); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Get(0).(db.Recognition) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, db.Recognition) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CreateRecognitionHi5 provides a mock function with given fields: _a0, _a1, _a2 +func (_m *Storer) CreateRecognitionHi5(_a0 context.Context, _a1 db.RecognitionHi5, _a2 int) error { + ret := _m.Called(_a0, _a1, _a2) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, db.RecognitionHi5, int) error); ok { + r0 = rf(_a0, _a1, _a2) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// CreateRecognitionModeration provides a mock function with given fields: _a0, _a1, _a2 +func (_m *Storer) CreateRecognitionModeration(_a0 context.Context, _a1 int64, _a2 db.RecognitionModeration) (db.RecognitionModeration, error) { + ret := _m.Called(_a0, _a1, _a2) + + var r0 db.RecognitionModeration + if rf, ok := ret.Get(0).(func(context.Context, int64, db.RecognitionModeration) db.RecognitionModeration); ok { + r0 = rf(_a0, _a1, _a2) + } else { + r0 = ret.Get(0).(db.RecognitionModeration) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, int64, db.RecognitionModeration) error); ok { + r1 = rf(_a0, _a1, _a2) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CreateReportedRecognition provides a mock function with given fields: _a0, _a1, _a2 +func (_m *Storer) CreateReportedRecognition(_a0 context.Context, _a1 int64, _a2 db.ReportedRecognition) (db.ReportedRecognition, error) { + ret := _m.Called(_a0, _a1, _a2) + + var r0 db.ReportedRecognition + if rf, ok := ret.Get(0).(func(context.Context, int64, db.ReportedRecognition) db.ReportedRecognition); ok { + r0 = rf(_a0, _a1, _a2) + } else { + r0 = ret.Get(0).(db.ReportedRecognition) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, int64, db.ReportedRecognition) error); ok { + r1 = rf(_a0, _a1, _a2) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CreateUserBlacklistedToken provides a mock function with given fields: _a0, _a1 +func (_m *Storer) CreateUserBlacklistedToken(_a0 context.Context, _a1 db.UserBlacklistedToken) error { + ret := _m.Called(_a0, _a1) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, db.UserBlacklistedToken) error); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// DeleteBadge provides a mock function with given fields: _a0, _a1, _a2 +func (_m *Storer) DeleteBadge(_a0 context.Context, _a1 int, _a2 int) error { + ret := _m.Called(_a0, _a1, _a2) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, int, int) error); ok { + r0 = rf(_a0, _a1, _a2) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// DeleteOrganization provides a mock function with given fields: _a0, _a1 +func (_m *Storer) DeleteOrganization(_a0 context.Context, _a1 int) error { + ret := _m.Called(_a0, _a1) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, int) error); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// GetOrganization provides a mock function with given fields: _a0, _a1 +func (_m *Storer) GetOrganization(_a0 context.Context, _a1 int) (db.Organization, error) { + ret := _m.Called(_a0, _a1) + + var r0 db.Organization + if rf, ok := ret.Get(0).(func(context.Context, int) db.Organization); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Get(0).(db.Organization) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, int) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetOrganizationByDomainName provides a mock function with given fields: _a0, _a1 +func (_m *Storer) GetOrganizationByDomainName(_a0 context.Context, _a1 string) (db.Organization, error) { + ret := _m.Called(_a0, _a1) + + var r0 db.Organization + if rf, ok := ret.Get(0).(func(context.Context, string) db.Organization); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Get(0).(db.Organization) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetRoleByID provides a mock function with given fields: _a0, _a1 +func (_m *Storer) GetRoleByID(_a0 context.Context, _a1 int) (db.Role, error) { + ret := _m.Called(_a0, _a1) + + var r0 db.Role + if rf, ok := ret.Get(0).(func(context.Context, int) db.Role); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Get(0).(db.Role) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, int) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetRoleByName provides a mock function with given fields: _a0, _a1 +func (_m *Storer) GetRoleByName(_a0 context.Context, _a1 string) (db.Role, error) { + ret := _m.Called(_a0, _a1) + + var r0 db.Role + if rf, ok := ret.Get(0).(func(context.Context, string) db.Role); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Get(0).(db.Role) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetUser provides a mock function with given fields: _a0, _a1 +func (_m *Storer) GetUser(_a0 context.Context, _a1 int) (db.User, error) { + ret := _m.Called(_a0, _a1) + + var r0 db.User + if rf, ok := ret.Get(0).(func(context.Context, int) db.User); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Get(0).(db.User) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, int) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetUserByEmail provides a mock function with given fields: _a0, _a1 +func (_m *Storer) GetUserByEmail(_a0 context.Context, _a1 string) (db.User, error) { + ret := _m.Called(_a0, _a1) + + var r0 db.User + if rf, ok := ret.Get(0).(func(context.Context, string) db.User); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Get(0).(db.User) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetUserByID provides a mock function with given fields: _a0, _a1 +func (_m *Storer) GetUserByID(_a0 context.Context, _a1 int) (db.User, error) { + ret := _m.Called(_a0, _a1) + + var r0 db.User + if rf, ok := ret.Get(0).(func(context.Context, int) db.User); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Get(0).(db.User) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, int) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetUserByOrganization provides a mock function with given fields: _a0, _a1, _a2 +func (_m *Storer) GetUserByOrganization(_a0 context.Context, _a1 int, _a2 int) (db.User, error) { + ret := _m.Called(_a0, _a1, _a2) + + var r0 db.User + if rf, ok := ret.Get(0).(func(context.Context, int, int) db.User); ok { + r0 = rf(_a0, _a1, _a2) + } else { + r0 = ret.Get(0).(db.User) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, int, int) error); ok { + r1 = rf(_a0, _a1, _a2) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ListBadges provides a mock function with given fields: _a0, _a1 +func (_m *Storer) ListBadges(_a0 context.Context, _a1 int) ([]db.Badge, error) { + ret := _m.Called(_a0, _a1) + + var r0 []db.Badge + if rf, ok := ret.Get(0).(func(context.Context, int) []db.Badge); ok { + r0 = rf(_a0, _a1) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]db.Badge) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, int) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ListOrganizations provides a mock function with given fields: _a0 +func (_m *Storer) ListOrganizations(_a0 context.Context) ([]db.Organization, error) { + ret := _m.Called(_a0) + + var r0 []db.Organization + if rf, ok := ret.Get(0).(func(context.Context) []db.Organization); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]db.Organization) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ListRecognitions provides a mock function with given fields: _a0 +func (_m *Storer) ListRecognitions(_a0 context.Context) ([]db.Recognition, error) { + ret := _m.Called(_a0) + + var r0 []db.Recognition + if rf, ok := ret.Get(0).(func(context.Context) []db.Recognition); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]db.Recognition) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ListRecognitionsWithFilter provides a mock function with given fields: _a0, _a1 +func (_m *Storer) ListRecognitionsWithFilter(_a0 context.Context, _a1 map[string]int) ([]db.Recognition, error) { + ret := _m.Called(_a0, _a1) + + var r0 []db.Recognition + if rf, ok := ret.Get(0).(func(context.Context, map[string]int) []db.Recognition); ok { + r0 = rf(_a0, _a1) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]db.Recognition) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, map[string]int) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ListUsers provides a mock function with given fields: _a0 +func (_m *Storer) ListUsers(_a0 context.Context) ([]db.User, error) { + ret := _m.Called(_a0) + + var r0 []db.User + if rf, ok := ret.Get(0).(func(context.Context) []db.User); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]db.User) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ResetHi5QuotaBalanceJob provides a mock function with given fields: +func (_m *Storer) ResetHi5QuotaBalanceJob() error { + ret := _m.Called() + + var r0 error + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ShowBadge provides a mock function with given fields: _a0, _a1 +func (_m *Storer) ShowBadge(_a0 context.Context, _a1 db.Badge) (db.Badge, error) { + ret := _m.Called(_a0, _a1) + + var r0 db.Badge + if rf, ok := ret.Get(0).(func(context.Context, db.Badge) db.Badge); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Get(0).(db.Badge) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, db.Badge) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ShowRecognition provides a mock function with given fields: _a0, _a1 +func (_m *Storer) ShowRecognition(_a0 context.Context, _a1 int) (db.Recognition, error) { + ret := _m.Called(_a0, _a1) + + var r0 db.Recognition + if rf, ok := ret.Get(0).(func(context.Context, int) db.Recognition); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Get(0).(db.Recognition) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, int) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// UpdateBadge provides a mock function with given fields: _a0, _a1 +func (_m *Storer) UpdateBadge(_a0 context.Context, _a1 db.Badge) (db.Badge, error) { + ret := _m.Called(_a0, _a1) + + var r0 db.Badge + if rf, ok := ret.Get(0).(func(context.Context, db.Badge) db.Badge); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Get(0).(db.Badge) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, db.Badge) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// UpdateHi5QuotaRenewalFrequencyOfUsers provides a mock function with given fields: _a0 +func (_m *Storer) UpdateHi5QuotaRenewalFrequencyOfUsers(_a0 db.Organization) error { + ret := _m.Called(_a0) + + var r0 error + if rf, ok := ret.Get(0).(func(db.Organization) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// UpdateOrganization provides a mock function with given fields: _a0, _a1, _a2 +func (_m *Storer) UpdateOrganization(_a0 context.Context, _a1 db.Organization, _a2 int) (db.Organization, error) { + ret := _m.Called(_a0, _a1, _a2) + + var r0 db.Organization + if rf, ok := ret.Get(0).(func(context.Context, db.Organization, int) db.Organization); ok { + r0 = rf(_a0, _a1, _a2) + } else { + r0 = ret.Get(0).(db.Organization) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, db.Organization, int) error); ok { + r1 = rf(_a0, _a1, _a2) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// UpdateUser provides a mock function with given fields: _a0, _a1, _a2 +func (_m *Storer) UpdateUser(_a0 context.Context, _a1 db.User, _a2 int) (db.User, error) { + ret := _m.Called(_a0, _a1, _a2) + + var r0 db.User + if rf, ok := ret.Get(0).(func(context.Context, db.User, int) db.User); ok { + r0 = rf(_a0, _a1, _a2) + } else { + r0 = ret.Get(0).(db.User) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, db.User, int) error); ok { + r1 = rf(_a0, _a1, _a2) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} diff --git a/go-backend/db/pg.go b/go-backend/db/pg.go index 378897daf..2b6a43e4c 100644 --- a/go-backend/db/pg.go +++ b/go-backend/db/pg.go @@ -146,3 +146,7 @@ func getMigrationPath() string { func getDBConn() *sqlx.DB { return pgStoreConn.db } + +func GetSqlInstance() *sqlx.DB { + return pgStoreConn.db +} diff --git a/go-backend/go.mod b/go-backend/go.mod index bd760586f..025c447ed 100644 --- a/go-backend/go.mod +++ b/go-backend/go.mod @@ -1,28 +1,64 @@ module joshsoftware/peerly -go 1.12 +go 1.21 + +toolchain go1.22.4 require ( github.com/DATA-DOG/go-sqlmock v1.4.1 github.com/auth0/go-jwt-middleware v0.0.0-20200507191422-d30d7b9ece63 github.com/aws/aws-sdk-go v1.32.1 - github.com/aws/aws-sdk-go-v2 v0.23.0 // indirect github.com/bxcodec/faker/v3 v3.3.1 github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/go-co-op/gocron v0.1.1 - github.com/go-delve/delve v1.4.0 // indirect github.com/golang-migrate/migrate v3.5.4+incompatible - github.com/google/uuid v1.1.1 github.com/gorilla/mux v1.7.4 github.com/gorilla/schema v1.1.0 github.com/jmoiron/sqlx v1.2.0 github.com/lib/pq v1.4.0 - github.com/mattes/migrate v3.0.1+incompatible - github.com/sirupsen/logrus v1.5.0 + github.com/sirupsen/logrus v1.9.3 github.com/spf13/viper v1.6.3 - github.com/stretchr/testify v1.5.1 + github.com/stretchr/testify v1.9.0 github.com/urfave/cli v1.22.4 github.com/urfave/negroni v1.0.0 - golang.org/x/net v0.0.0-20200602114024-627f9648deb9 // indirect - golang.org/x/text v0.3.2 // indirect +) + +require ( + github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/distribution/reference v0.6.0 // indirect + github.com/docker/docker v26.1.4+incompatible // indirect + github.com/docker/go-connections v0.5.0 // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/fsnotify/fsnotify v1.4.7 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/jmespath/go-jmespath v0.3.0 // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/magiconair/properties v1.8.1 // indirect + github.com/mattn/go-sqlite3 v1.14.16 // indirect + github.com/mitchellh/mapstructure v1.1.2 // indirect + github.com/moby/docker-image-spec v1.3.1 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.0 // indirect + github.com/pelletier/go-toml v1.2.0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect + github.com/rs/cors v1.11.0 // indirect + github.com/russross/blackfriday/v2 v2.0.1 // indirect + github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect + github.com/spf13/afero v1.10.0 // indirect + github.com/spf13/cast v1.3.0 // indirect + github.com/spf13/jwalterweatherman v1.0.0 // indirect + github.com/spf13/pflag v1.0.3 // indirect + github.com/stretchr/objx v0.5.2 // indirect + github.com/subosito/gotenv v1.2.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0 // indirect + go.opentelemetry.io/otel/trace v1.27.0 // indirect + golang.org/x/net v0.25.0 // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/text v0.15.0 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect + gopkg.in/ini.v1 v1.51.0 // indirect + gopkg.in/yaml.v2 v2.2.4 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go-backend/go.sum b/go-backend/go.sum index 1ec8bdab2..1b6ea7ed3 100644 --- a/go-backend/go.sum +++ b/go-backend/go.sum @@ -1,10 +1,48 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= -cloud.google.com/go v0.30.0 h1:xKvyLgk56d0nksWq49J0UyGEeUIicTl4+UBiX1NPX9g= -cloud.google.com/go v0.30.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DATA-DOG/go-sqlmock v1.4.1 h1:ThlnYciV1iM/V0OSF/dtkqWb6xo5qITT1TJBG1MRDJM= github.com/DATA-DOG/go-sqlmock v1.4.1/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= +github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU= +github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -13,204 +51,261 @@ github.com/auth0/go-jwt-middleware v0.0.0-20200507191422-d30d7b9ece63 h1:LY/kRH+ github.com/auth0/go-jwt-middleware v0.0.0-20200507191422-d30d7b9ece63/go.mod h1:mF0ip7kTEFtnhBJbd/gJe62US3jykNN+dcZoZakJCCA= github.com/aws/aws-sdk-go v1.32.1 h1:0dy5DkMKNPH9mLWveAWA9ZTiKIEEvJJA6fbe0eCs19k= github.com/aws/aws-sdk-go v1.32.1/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= -github.com/aws/aws-sdk-go-v2 v0.23.0 h1:+E1q1LLSfHSDn/DzOtdJOX+pLZE2HiNV2yO5AjZINwM= -github.com/aws/aws-sdk-go-v2 v0.23.0/go.mod h1:2LhT7UgHOXK3UXONKI5OMgIyoQL6zTAw/jwIeX6yqzw= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/bxcodec/faker v1.5.0 h1:RIWOeAcM3ZHye1i8bQtHU2LfNOaLmHuRiCo60mNMOcQ= -github.com/bxcodec/faker v2.0.1+incompatible h1:P0KUpUw5w6WJXwrPfv35oc91i4d8nf40Nwln+M/+faA= github.com/bxcodec/faker/v3 v3.3.1 h1:G7uldFk+iO/ES7W4v7JlI/WU9FQ6op9VJ15YZlDEhGQ= github.com/bxcodec/faker/v3 v3.3.1/go.mod h1:gF31YgnMSMKgkvl+fyEo1xuSMbEuieyqfeslGYFjneM= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cosiner/argv v0.0.0-20170225145430-13bacc38a0a5 h1:rIXlvz2IWiupMFlC45cZCXZFvKX/ExBcSLrDy2G0Lp8= -github.com/cosiner/argv v0.0.0-20170225145430-13bacc38a0a5/go.mod h1:p/NrK5tF6ICIly4qwEDsf6VDirFiWWz0FenfYBwJaKQ= -github.com/cpuguy83/go-md2man v1.0.8 h1:DwoNytLphI8hzS2Af4D0dfaEaiSq2bN05mEm4R6vf8M= -github.com/cpuguy83/go-md2man v1.0.8/go.mod h1:N6JayAiVKtlHSnuTCeuLSQVs75hb8q+dYQLjr7cDsKY= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/docker v26.1.4+incompatible h1:vuTpXDuoga+Z38m1OZHzl7NKisKWaWlhjQk7IDPSLsU= +github.com/docker/docker v26.1.4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= +github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= 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/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-co-op/gocron v0.1.1 h1:OfDmkqkCguFtFMsm6Eaayci3DADLa8pXvdmOlPU/JcU= github.com/go-co-op/gocron v0.1.1/go.mod h1:Y9PWlYqDChf2Nbgg7kfS+ZsXHDTZbMZYPEQ0MILqH+M= -github.com/go-delve/delve v1.4.0 h1:O+1dw1XBZXqhC6fIPQwGxLlbd2wDRau7NxNhVpw02ag= -github.com/go-delve/delve v1.4.0/go.mod h1:gQM0ReOJLNAvPuKAXfjHngtE93C2yc/ekTbo7YbAHSo= -github.com/go-co-op/gocron v0.1.1 h1:OfDmkqkCguFtFMsm6Eaayci3DADLa8pXvdmOlPU/JcU= -github.com/go-co-op/gocron v0.1.1/go.mod h1:Y9PWlYqDChf2Nbgg7kfS+ZsXHDTZbMZYPEQ0MILqH+M= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= github.com/go-redis/redis v6.15.5+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= -github.com/go-redis/redis v6.15.5+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/golang-migrate/migrate v1.3.2 h1:QAlFV1QF9zdkzy/jujlBVkVu+L/+k18cg8tuY1/4JDY= github.com/golang-migrate/migrate v3.5.4+incompatible h1:R7OzwvCJTCgwapPCiX6DyBiu2czIUMDCB118gFTKTUA= github.com/golang-migrate/migrate v3.5.4+incompatible/go.mod h1:IsVUlFN5puWOmXrqjgGUfIRIbU7mr8oNBE2tyERd9Wk= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 h1:l5lAOZEym3oK3SQ2HBHWsJUfbNBiTXJDeW2QDxw9AQ0= github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= -github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/mux v1.6.2/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/pat v0.0.0-20180118222023-199c85a7f6d1/go.mod h1:YeAe0gNeiNT5hoiZRI4yiOky6jVdNvfO2N6Kav/HmxY= -github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= -github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= -github.com/gorilla/sessions v1.1.1 h1:YMDmfaK68mUixINzY/XjscuJ47uXFWSSHzFbBQM0PrE= -github.com/gorilla/sessions v1.1.1/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w= 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/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/jarcoal/httpmock v0.0.0-20180424175123-9c70cfe4a1da/go.mod h1:ks+b9deReOc7jgqp+e7LuFiCBH6Rm5hL32cLcEAArb4= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/jmespath/go-jmespath v0.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2yCeUc= github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA= github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/lestrrat-go/jwx v0.9.0/go.mod h1:iEoxlYfZjvoGpuWwxUz+eR5e6KTJGsaRcy/YNA/UnBk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.3.0 h1:/qkRGz8zljWiDcFvgpwUpwIAPu3r07TDvs3Rws+o/pU= -github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.4.0 h1:TmtCFbH+Aw0AixwyttznSMQDgbR5Yed/Gg6S8Funrhc= github.com/lib/pq v1.4.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/markbates/going v1.0.0/go.mod h1:I6mnB4BPnEeqo85ynXIx1ZFLLbtiLHNXVgWeFO9OGOA= -github.com/markbates/goth v1.64.0 h1:TXmIGRrY3Rf/a5qbx8MIGnz1rD9SkIn0UzRoDqHyJLs= -github.com/markbates/goth v1.64.0/go.mod h1:qh2QfwZoWRucQ+DR5KVKC6dUGkNCToWh4vS45GIzFsY= -github.com/mattes/migrate v3.0.1+incompatible h1:PhAZP82Vqejw8JZLF4U5UkLGzEVaCnbtJpB6DONcDow= -github.com/mattes/migrate v3.0.1+incompatible/go.mod h1:LJcqgpj1jQoxv3m2VXd3drv0suK5CbN/RCX7MXwgnVI= -github.com/mattn/go-colorable v0.0.0-20170327083344-ded68f7a9561 h1:isR/L+BIZ+rqODWYR/f526ygrBMGKZYFhaaFRDGvuZ8= -github.com/mattn/go-colorable v0.0.0-20170327083344-ded68f7a9561/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-isatty v0.0.3 h1:ns/ykhmWi7G9O+8a448SecJU3nSMBXJfqQkl0upE1jI= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= +github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= +github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/mrjones/oauth v0.0.0-20180629183705-f4e24b6d100c/go.mod h1:skjdDftzkFALcuGzYSklqYd8gvat6F1gZJ4YPVbkZpM= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/peterh/liner v0.0.0-20170317030525-88609521dc4b h1:8uaXtUkxiy+T/zdLWuxa/PG4so0TPZDZfafFNNSaptE= -github.com/peterh/liner v0.0.0-20170317030525-88609521dc4b/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -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= -github.com/pkg/profile v0.0.0-20170413231811-06b906832ed0/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/russross/blackfriday v0.0.0-20180428102519-11635eb403ff h1:g9ZlAHmkc/h5So+OjNCkZWh+FjuKEOOOoyRkqlGA8+c= -github.com/russross/blackfriday v0.0.0-20180428102519-11635eb403ff/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rs/cors v1.11.0 h1:0B9GE/r9Bc2UxRMMtymBkHTenPkHDv0CW4Y98GBY+po= +github.com/rs/cors v1.11.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v0.0.0-20180523074243-ea8897e79973/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.5.0 h1:1N5EYkVAPEywqZRJd7cwnRtCb6xJx7NH3T3WUTF980Q= -github.com/sirupsen/logrus v1.5.0/go.mod h1:+F7Ogzej0PZc/94MaYx/nvG9jOFMD2osvC3s+Squfpo= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/assertions v1.1.0 h1:MkTeG1DMwsrdH7QtLXy5W+fUxWq+vmb6cLmyJ7aRtF0= github.com/smartystreets/assertions v1.1.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= +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/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY= +github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.0-20170417170307-b6cb39589372 h1:eRfW1vRS4th8IX2iQeyqQ8cOUNOySvAYJ0IUvTXGoYA= -github.com/spf13/cobra v0.0.0-20170417170307-b6cb39589372/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v0.0.0-20170417173400-9e4c21054fa1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/viper v1.6.3 h1:pDDu1OyEDTKzpJwdq4TiuLyMsUgRa/BT5cn5O62NoHs= github.com/spf13/viper v1.6.3/go.mod h1:jUMtyi0/lB5yZH/FjyGAoH7IMNrIhlBf6pXZmbMDvzw= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -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/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -220,77 +315,330 @@ github.com/urfave/negroni v1.0.0 h1:kIimOitoypq34K7TG7DUaJ9kq/N4Ofuwi1sjz0KipXc= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.starlark.net v0.0.0-20190702223751-32f345186213 h1:lkYv5AKwvvduv5XWP6szk/bvvgO6aDeUujhZQXIFTes= -go.starlark.net v0.0.0-20190702223751-32f345186213/go.mod h1:c1/X6cHgvdXj6pUlmWKMkuqRnW4K8x2vwt6JAaaircg= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0 h1:9l89oX4ba9kHbBol3Xin3leYJ+252h0zszDtBwyKe2A= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0/go.mod h1:XLZfZboOJWHNKUv7eH0inh0E9VV6eWDFB/9yJyTLPp0= +go.opentelemetry.io/otel v1.27.0 h1:9BZoF3yMK/O1AafMiQTVu0YDj5Ea4hPhxCs7sGva+cg= +go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ= +go.opentelemetry.io/otel/metric v1.27.0 h1:hvj3vdEKyeCi4YaYfNjv2NUje8FqKqUY8IlF0FxV/ik= +go.opentelemetry.io/otel/metric v1.27.0/go.mod h1:mVFgmRlhljgBiuk/MP/oKylr4hs85GZAylncepAX/ak= +go.opentelemetry.io/otel/trace v1.27.0 h1:IqYb813p7cmbHk0a5y6pD5JPakbVfftRXABGt5/Rscw= +go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -golang.org/x/arch v0.0.0-20190927153633-4e8777c89be4 h1:QlVATYS7JBoZMVaf+cNjb90WD/beKVHnIxFKT4QaHVI= -golang.org/x/arch v0.0.0-20190927153633-4e8777c89be4/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/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-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200602114024-627f9648deb9 h1:pNX+40auqi2JqRfOP1akLGtYcn15TUbkhwuCO3foqqM= -golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/oauth2 v0.0.0-20180620175406-ef147856a6dd/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/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-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb h1:fgwFCsaw9buMuxNd6+DQfAuSFqbNiQZpcgJQAgJsK6k= -golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20191127201027-ecd32218bd7f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.2.0 h1:S0iUepdCWODXRvtE+gcRDd15L+k+k1AiHlMiMjefH24= -google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= @@ -301,6 +649,16 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 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= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099 h1:XJP7lxbSxWLOMNdBE4B/STaqVy6L73o0knwj2vIlxnw= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/go-backend/main.go b/go-backend/main.go index 3c74c4ae9..f8a9831b1 100644 --- a/go-backend/main.go +++ b/go-backend/main.go @@ -6,15 +6,18 @@ package main import ( "errors" "fmt" - "joshsoftware/peerly/aws" + "joshsoftware/peerly/api" "joshsoftware/peerly/config" "joshsoftware/peerly/db" + "joshsoftware/peerly/tasks" + "net/http" "joshsoftware/peerly/service" - "joshsoftware/peerly/tasks" + "os" "strconv" + "github.com/rs/cors" logger "github.com/sirupsen/logrus" "github.com/urfave/cli" "github.com/urfave/negroni" @@ -77,24 +80,33 @@ func startApp() (err error) { logger.WithField("err", err.Error()).Error("Database init failed") return } - awsstore, err := aws.Init() - if err != nil { - logger.WithField("err", err.Error()).Error("AWS service init failed") - return - } - - deps := service.Dependencies{ - Store: store, - AWSStore: awsstore, - } - + // awsstore, err := aws.Init() + // if err != nil { + // logger.WithField("err", err.Error()).Error("AWS service init failed") + // return + // } + dbInstance := db.GetSqlInstance() + // deps := service.Dependencies{ + // Store: store, + // AWSStore: awsstore, + // } + dep := service.NewServices(dbInstance, store) // Start up all the background tasks Peerly depends upon - tasks.Init(deps) + tasks.Init(dep) + + //cors + c := cors.New(cors.Options{ + AllowedOrigins: []string{"*"}, + AllowCredentials: true, + AllowedMethods: []string{http.MethodGet, http.MethodPost, http.MethodPut, http.MethodDelete, http.MethodOptions}, + AllowedHeaders: []string{"*"}, + }) // mux router - router := service.InitRouter(deps) + router := api.InitRouter(dep) // init web server server := negroni.Classic() + server.Use(c) server.UseHandler(router) port := config.AppPort() // This can be changed to the service port number via environment variable. diff --git a/go-backend/migrations/.keep b/go-backend/migrations/.keep deleted file mode 100644 index e69de29bb..000000000 diff --git a/go-backend/migrations/1718704272_corevalues.down.sql b/go-backend/migrations/1718704272_corevalues.down.sql new file mode 100644 index 000000000..19c5be624 --- /dev/null +++ b/go-backend/migrations/1718704272_corevalues.down.sql @@ -0,0 +1 @@ +DROP TABLE core_values; \ No newline at end of file diff --git a/go-backend/migrations/1718704272_corevalues.up.sql b/go-backend/migrations/1718704272_corevalues.up.sql new file mode 100644 index 000000000..402bcb44e --- /dev/null +++ b/go-backend/migrations/1718704272_corevalues.up.sql @@ -0,0 +1,18 @@ +CREATE TABLE core_values ( + id SERIAL PRIMARY KEY, + org_id INTEGER NOT NULL, + text VARCHAR(225) NOT NULL, + thumbnail_url VARCHAR(225), + description VARCHAR(225), + parent_id INTEGER, + created_at TIMESTAMPTZ DEFAULT current_timestamp, + updated_at TIMESTAMPTZ DEFAULT current_timestamp, + soft_delete BOOLEAN DEFAULT false, + soft_delete_by BIGINT, + created_by BIGINT, + CONSTRAINT unique_org_core UNIQUE (org_id, id), + CONSTRAINT fk_org_id FOREIGN KEY (org_id) REFERENCES organizations(id), + CONSTRAINT fk_parent_id FOREIGN KEY (parent_id) REFERENCES corevalues(id), + CONSTRAINT fk_soft_delete_by FOREIGN KEY (soft_delete_by) REFERENCES users(id), + CONSTRAINT fk_created_by FOREIGN KEY (created_by) REFERENCES users(id) +); \ No newline at end of file diff --git a/go-backend/pkg/dto/coreValues.go b/go-backend/pkg/dto/coreValues.go new file mode 100644 index 000000000..e464de9cb --- /dev/null +++ b/go-backend/pkg/dto/coreValues.go @@ -0,0 +1,68 @@ +package dto + +import "time" + +type UpdateQueryRequest struct { + Text string `db:"text" json:"text"` + Description string `db:"description" json:"description"` + ThumbnailUrl string `db:"thumbnailurl" json:"thumbnail_url"` +} + +type UpdateCoreValuesResp struct { + ID int64 `json:"id" db:"id"` + OrgID int64 `json:"org_id" db:"org_id"` + Text string `json:"text" db:"text"` + Description string `json:"description" db:"description"` + ParentID *int64 `json:"parent_id" db:"parent_id"` + ThumbnailURL *string `json:"thumbnail_url" db:"thumbnail_url"` + CreatedAt time.Time `json:"created_at" db:"created_at"` + UpdatedAt time.Time `json:"updated_at" db:"updated_at"` + CreatedBy int64 `json:"created_by" db:"created_by"` +} + +type ListCoreValuesResp struct { + ID int64 `json:"id" db:"id"` + OrgID int64 `json:"org_id" db:"org_id"` + Text string `json:"text" db:"text"` + Description string `json:"description" db:"description"` + ParentID *int64 `json:"parent_id" db:"parent_id"` + ThumbnailURL *string `json:"thumbnail_url" db:"thumbnail_url"` + CreatedAt time.Time `json:"created_at" db:"created_at"` + UpdatedAt time.Time `json:"updated_at" db:"updated_at"` + CreatedBy int64 `json:"created_by" db:"created_by"` +} + +type GetCoreValueResp struct { + ID int64 `json:"id" db:"id"` + OrgID int64 `json:"org_id" db:"org_id"` + Text string `json:"text" db:"text"` + Description string `json:"description" db:"description"` + ParentID *int64 `json:"parent_id" db:"parent_id"` + ThumbnailURL *string `json:"thumbnail_url" db:"thumbnail_url"` + CreatedAt time.Time `json:"created_at" db:"created_at"` + UpdatedAt time.Time `json:"updated_at" db:"updated_at"` + CreatedBy int64 `json:"created_by" db:"created_by"` + SoftDelete bool `json:"soft_delete" db:"soft_delete"` + SoftDeleteBy int64 `json:"soft_delete_by" db:"soft_delete_by"` +} + +type CreateCoreValueReq struct { + Text string `json:"text" db:"text"` + Description string `json:"description" db:"description"` + ParentID *int64 `json:"parent_id" db:"parent_id"` + ThumbnailURL string `json:"thumbnail_url" db:"thumbnail_url"` +} + +type CreateCoreValueResp struct { + ID int64 `json:"id" db:"id"` + OrgID int64 `json:"org_id" db:"org_id"` + Text string `json:"text" db:"text"` + Description string `json:"description" db:"description"` + ParentID *int64 `json:"parent_id" db:"parent_id"` + ThumbnailURL *string `json:"thumbnail_url" db:"thumbnail_url"` + CreatedAt time.Time `json:"created_at" db:"created_at"` + UpdatedAt time.Time `json:"updated_at" db:"updated_at"` + CreatedBy int64 `json:"created_by" db:"created_by"` + SoftDelete bool `json:"soft_delete" db:"soft_delete"` + SoftDeleteBy int64 `json:"soft_delete_by" db:"soft_delete_by"` +} diff --git a/go-backend/pkg/dto/response.go b/go-backend/pkg/dto/response.go new file mode 100644 index 000000000..d64edf03a --- /dev/null +++ b/go-backend/pkg/dto/response.go @@ -0,0 +1,39 @@ +package dto + +import ( + "encoding/json" + "net/http" + + logger "github.com/sirupsen/logrus" +) + +type SuccessResponse struct { + Data interface{} `json:"data"` +} + +type ErrorResponse struct { + Error interface{} `json:"error"` +} + +type MessageObject struct { + Message string `json:"message"` +} + +type ErrorObject struct { + Code string `json:"code"` + MessageObject + Fields map[string]string `json:"fields"` +} + +func Repsonse(rw http.ResponseWriter, status int, responseBody interface{}) { + respBytes, err := json.Marshal(responseBody) + if err != nil { + logger.WithField("err", err.Error()).Error("Error while marshaling core values data") + rw.WriteHeader(http.StatusInternalServerError) + return + } + + rw.Header().Add("Content-Type", "application/json") + rw.WriteHeader(status) + rw.Write(respBytes) +} diff --git a/go-backend/service/aws_s3_service_http.go b/go-backend/service/aws_s3_service_http.go index 7455b998f..025b3ce70 100644 --- a/go-backend/service/aws_s3_service_http.go +++ b/go-backend/service/aws_s3_service_http.go @@ -1,32 +1,32 @@ package service -import ( - "net/http" +// import ( +// "net/http" - logger "github.com/sirupsen/logrus" -) +// logger "github.com/sirupsen/logrus" +// ) -func getS3SignedURLHandler(deps Dependencies) http.HandlerFunc { - return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { - if req.FormValue("type") == "" || req.FormValue("filename") == "" { - rw.WriteHeader(http.StatusInternalServerError) - repsonse(rw, http.StatusInternalServerError, errorResponse{ - Error: messageObject{ - Message: "Error while retrieving bucket type and filename in URL", - }, - }) - return - } - S3SignedURLData, err := deps.AWSStore.GetAWSS3SignedURL(req.Context(), req.FormValue("type"), req.FormValue("filename")) - if err != nil { - logger.WithField("err", err.Error()).Error("Error while retrieving URL") - rw.WriteHeader(http.StatusInternalServerError) - repsonse(rw, http.StatusInternalServerError, errorResponse{ - Error: messageObject{ - Message: "Error while retrieving URL", - }, - }) - } - repsonse(rw, http.StatusOK, successResponse{Data: S3SignedURLData}) - }) -} +// func getS3SignedURLHandler(deps Dependencies) http.HandlerFunc { +// return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { +// if req.FormValue("type") == "" || req.FormValue("filename") == "" { +// rw.WriteHeader(http.StatusInternalServerError) +// repsonse(rw, http.StatusInternalServerError, errorResponse{ +// Error: messageObject{ +// Message: "Error while retrieving bucket type and filename in URL", +// }, +// }) +// return +// } +// S3SignedURLData, err := deps.AWSStore.GetAWSS3SignedURL(req.Context(), req.FormValue("type"), req.FormValue("filename")) +// if err != nil { +// logger.WithField("err", err.Error()).Error("Error while retrieving URL") +// rw.WriteHeader(http.StatusInternalServerError) +// repsonse(rw, http.StatusInternalServerError, errorResponse{ +// Error: messageObject{ +// Message: "Error while retrieving URL", +// }, +// }) +// } +// repsonse(rw, http.StatusOK, successResponse{Data: S3SignedURLData}) +// }) +// } diff --git a/go-backend/service/coreValues/helper.go b/go-backend/service/coreValues/helper.go new file mode 100644 index 000000000..e1a3df7a6 --- /dev/null +++ b/go-backend/service/coreValues/helper.go @@ -0,0 +1,83 @@ +package corevalues + +import ( + "context" + "fmt" + "joshsoftware/peerly/apperrors" + "joshsoftware/peerly/db" + "joshsoftware/peerly/pkg/dto" + "strconv" + + logger "github.com/sirupsen/logrus" +) + +func validateParentCoreValue(ctx context.Context, storer db.CoreValueStorer, organisationID, coreValueID int64) (ok bool) { + coreValue, err := storer.GetCoreValue(ctx, organisationID, coreValueID) + if err != nil { + logger.WithField("err", err.Error()).Error("Parent core value id not present") + return + } + + if coreValue.ParentID != nil || coreValue.SoftDelete { + logger.Error("Invalid parent core value id") + return + } + + return true +} + +// Validate - ensures the core value object has all the info it needs +// func Validate(ctx context.Context, coreValue db.CoreValue, storer db.CoreValueStorer, organisationID int64) (valid bool, errFields map[string]string) { +// errFields = make(map[string]string) + +// if coreValue.Text == "" { +// errFields["text"] = "Can't be blank" +// } +// if coreValue.Description == "" { +// errFields["description"] = "Can't be blank" +// } +// if coreValue.ParentID != nil { +// if !validateParentCoreValue(ctx, storer, organisationID, *coreValue.ParentID) { +// errFields["parent_id"] = "Invalid parent core value" +// } +// } + +// if len(errFields) == 0 { +// valid = true +// } +// return +// } + +func Validate(ctx context.Context, coreValue dto.CreateCoreValueReq, storer db.CoreValueStorer, organisationID int64) (err error) { + + if coreValue.Text == "" { + err = apperrors.TextFieldBlank + } + if coreValue.Description == "" { + err = apperrors.DescFieldBlank + } + if coreValue.ParentID != nil { + if !validateParentCoreValue(ctx, storer, organisationID, *coreValue.ParentID) { + err = apperrors.InvalidParentValue + } + } + + return +} + +func VarsStringToInt(inp string, label string) (result int64, err error) { + + if len(inp) <= 0 { + err = apperrors.InvalidOrgId + return + } + result, err = strconv.ParseInt(inp, 10, 64) + if err != nil { + logger.WithField("err", err.Error()).Error(fmt.Scanf("Error while parsing %s from url", label)) + err = apperrors.InternalServerError + return + + } + + return +} diff --git a/go-backend/service/coreValues/mocks/Service.go b/go-backend/service/coreValues/mocks/Service.go new file mode 100644 index 000000000..e2b660d78 --- /dev/null +++ b/go-backend/service/coreValues/mocks/Service.go @@ -0,0 +1,127 @@ +// Code generated by mockery v1.0.0. DO NOT EDIT. + +package mocks + +import context "context" + +import dto "joshsoftware/peerly/pkg/dto" +import mock "github.com/stretchr/testify/mock" + +// Service is an autogenerated mock type for the Service type +type Service struct { + mock.Mock +} + +// CreateCoreValue provides a mock function with given fields: ctx, organisationID, userId, coreValue +func (_m *Service) CreateCoreValue(ctx context.Context, organisationID string, userId int64, coreValue dto.CreateCoreValueReq) (dto.CreateCoreValueResp, error) { + ret := _m.Called(ctx, organisationID, userId, coreValue) + + var r0 dto.CreateCoreValueResp + if rf, ok := ret.Get(0).(func(context.Context, string, int64, dto.CreateCoreValueReq) dto.CreateCoreValueResp); ok { + r0 = rf(ctx, organisationID, userId, coreValue) + } else { + r0 = ret.Get(0).(dto.CreateCoreValueResp) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, string, int64, dto.CreateCoreValueReq) error); ok { + r1 = rf(ctx, organisationID, userId, coreValue) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DeleteCoreValue provides a mock function with given fields: ctx, organisationID, coreValueID, userId +func (_m *Service) DeleteCoreValue(ctx context.Context, organisationID string, coreValueID string, userId int64) error { + ret := _m.Called(ctx, organisationID, coreValueID, userId) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string, string, int64) error); ok { + r0 = rf(ctx, organisationID, coreValueID, userId) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// GetCoreValue provides a mock function with given fields: ctx, organisationID, coreValueID +func (_m *Service) GetCoreValue(ctx context.Context, organisationID string, coreValueID string) (dto.GetCoreValueResp, error) { + ret := _m.Called(ctx, organisationID, coreValueID) + + var r0 dto.GetCoreValueResp + if rf, ok := ret.Get(0).(func(context.Context, string, string) dto.GetCoreValueResp); ok { + r0 = rf(ctx, organisationID, coreValueID) + } else { + r0 = ret.Get(0).(dto.GetCoreValueResp) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok { + r1 = rf(ctx, organisationID, coreValueID) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ListCoreValues provides a mock function with given fields: ctx, organisationID +func (_m *Service) ListCoreValues(ctx context.Context, organisationID string) ([]dto.ListCoreValuesResp, error) { + ret := _m.Called(ctx, organisationID) + + var r0 []dto.ListCoreValuesResp + if rf, ok := ret.Get(0).(func(context.Context, string) []dto.ListCoreValuesResp); ok { + r0 = rf(ctx, organisationID) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]dto.ListCoreValuesResp) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(ctx, organisationID) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// UpdateCoreValue provides a mock function with given fields: ctx, organisationID, coreValueID, coreValue +func (_m *Service) UpdateCoreValue(ctx context.Context, organisationID string, coreValueID string, coreValue dto.UpdateQueryRequest) (dto.UpdateCoreValuesResp, error) { + ret := _m.Called(ctx, organisationID, coreValueID, coreValue) + + var r0 dto.UpdateCoreValuesResp + if rf, ok := ret.Get(0).(func(context.Context, string, string, dto.UpdateQueryRequest) dto.UpdateCoreValuesResp); ok { + r0 = rf(ctx, organisationID, coreValueID, coreValue) + } else { + r0 = ret.Get(0).(dto.UpdateCoreValuesResp) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, string, string, dto.UpdateQueryRequest) error); ok { + r1 = rf(ctx, organisationID, coreValueID, coreValue) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// NewService creates a new instance of Service. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewService(t interface { + mock.TestingT + Cleanup(func()) +}) *Service { + mock := &Service{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/go-backend/service/coreValues/openapi.yml b/go-backend/service/coreValues/openapi.yml new file mode 100644 index 000000000..f63801bbd --- /dev/null +++ b/go-backend/service/coreValues/openapi.yml @@ -0,0 +1,350 @@ +openapi: 3.0.3 +info: + title: Swagger Peerly + description: |- + Peer to peer appreciations + version: 1.0.11 +servers: + - url: http://localhost:33001/ +tags: + - name: Core Values + description: Core Value cruds + +paths: + + /organisations/{organisationId}/core_values/{coreValueId}: + put: + tags: + - Core Values + summary: Update an existing core value + description: Update an existing core value by Id + operationId: updateCoreValue + parameters: + - name: organisationId + in: path + description: ID of organisation + required: true + schema: + type: integer + format: int64 + example: 1 + - name: coreValueId + in: path + description: ID of corevalue + required: true + schema: + type: integer + format: int64 + example: 32 + - in: header + name: Accept-Version + required: true + description: Defines the media type and version of the API endpoint + schema: + enum: + - 'application/vnd.peerly.v1' + type: string + requestBody: + description: Update an existing core value in the organisation + content: + application/json: + schema: + $ref: '#/components/schemas/UpdateCoreValues' + required: true + responses: + '200': + description: Successful operation + '400': + description: Invalid input data + '404': + description: Orgnisation id not found / Core value id not found + '500': + description: Internal server error + + get: + tags: + - Core Values + summary: Finds corevalue by id + description: get a corevalue by organisation id and corevalue id + operationId: get a corevalue by id + parameters: + - name: organisationId + in: path + description: ID of organisation + required: true + schema: + type: integer + format: int64 + example: 1 + - name: coreValueId + in: path + description: ID of corevalue + required: true + schema: + type: integer + format: int64 + example: 30 + - in: header + name: Accept-Version + required: true + description: Defines the media type and version of the API endpoint + schema: + enum: + - 'application/vnd.peerly.v1' + type: string + responses: + '200': + description: successful operation + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/GetCoreValuesResp' + '404': + description: Invalid organisation id / Invalid core value id + + delete: + tags: + - Core Values + summary: Deletes a corevalue + description: delete a corevalue + operationId: deleteCoreValue + parameters: + - name: organisationId + in: path + description: ID of organisation + required: true + schema: + type: integer + format: int64 + example: 1 + - name: coreValueId + in: path + description: ID of corevalue + required: true + schema: + type: integer + format: int64 + example: 30 + - in: header + name: Accept-Version + required: true + description: Defines the media type and version of the API endpoint + schema: + enum: + - 'application/vnd.peerly.v1' + type: string + responses: + '200': + description: Delete sucessfull + '404': + description: Invalid organisation id/ invalid corevalue id + '500': + description: Internal server error + + /organisations/{organisationId}/core_values: + post: + tags: + - Core Values + summary: Add a new core value + description: Add a new core value + operationId: addCoreValue + parameters: + - name: organisationId + in: path + description: ID of organisation + required: true + schema: + type: integer + format: int64 + example: 1 + - in: header + name: Accept-Version + required: true + description: Defines the media type and version of the API endpoint + schema: + enum: + - 'application/vnd.peerly.v1' + type: string + requestBody: + description: Create a new core value + content: + application/json: + schema: + $ref: '#/components/schemas/CreateCoreValues' + required: true + responses: + '201': + description: Successfully created + content: + application/json: + schema: + $ref: '#/components/schemas/CreateCoreValuesResp' + + '400': + description: Invalid input + '404': + description: Invalid organisation id + '500' : + description: Internal server error + + get: + tags: + - Core Values + summary: List all corevalues of the organisation + description: List all the core values of the specified organisation + operationId: listCoreValues + parameters: + - name: organisationId + in: path + description: ID of organisation + required: true + schema: + type: integer + format: int64 + example: 1 + - in: header + name: Accept-Version + required: true + description: Defines the media type and version of the API endpoint + schema: + enum: + - 'application/vnd.peerly.v1' + type: string + + responses: + '200': + description: successful operation + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ListCoreValuesResp' + '404': + description: Invalid organisation id + '500': + description: Internal server error + +components: + schemas: + + UpdateCoreValues: + type: object + properties: + text: + type: string + example: Updated core value + description: + type: string + example: updated description + thumbnail_url: + type: string + example: url string + + CreateCoreValues: + type: object + properties: + text: + type: string + example: Updated core value + description: + type: string + example: updated description + thumbnail_url: + type: string + example: url string + parent_id: + type: integer + format: int64 + example: 1 + + CreateCoreValuesResp: + type: object + properties: + id: + type: integer + format: int64 + org_id: + type: integer + format: int64 + text: + type: string + description: + type: string + parent_id: + type: integer + format: int64 + thumbnail_url: + type: string + created_at: + type: string + updated_at: + type: string + created_by: + type: integer + format: int64 + soft_delete: + type: boolean + soft_delete_by: + type: integer + format: int64 + + GetCoreValuesResp: + type: object + properties: + id: + type: integer + format: int64 + org_id: + type: integer + format: int64 + text: + type: string + description: + type: string + parent_id: + type: integer + format: int64 + thumbnail_url: + type: string + created_at: + type: string + updated_at: + type: string + created_by: + type: integer + format: int64 + soft_delete: + type: boolean + soft_delete_by: + type: integer + format: int64 + + ListCoreValuesResp: + type: object + properties: + id: + type: integer + format: int64 + org_id: + type: integer + format: int64 + text: + type: string + description: + type: string + parent_id: + type: integer + format: int64 + thumbnail_url: + type: string + created_at: + type: string + updated_at: + type: string + created_by: + type: integer + format: int64 + \ No newline at end of file diff --git a/go-backend/service/coreValues/service.go b/go-backend/service/coreValues/service.go new file mode 100644 index 000000000..7366f2a29 --- /dev/null +++ b/go-backend/service/coreValues/service.go @@ -0,0 +1,219 @@ +package corevalues + +import ( + "context" + + "joshsoftware/peerly/apperrors" + "joshsoftware/peerly/db" + "joshsoftware/peerly/pkg/dto" + + logger "github.com/sirupsen/logrus" +) + +type service struct { + coreValuesRepo db.CoreValueStorer +} + +type Service interface { + ListCoreValues(ctx context.Context, organisationID string) (resp []dto.ListCoreValuesResp, err error) + GetCoreValue(ctx context.Context, organisationID string, coreValueID string) (coreValue dto.GetCoreValueResp, err error) + CreateCoreValue(ctx context.Context, organisationID string, userId int64, coreValue dto.CreateCoreValueReq) (resp dto.CreateCoreValueResp, err error) + DeleteCoreValue(ctx context.Context, organisationID string, coreValueID string, userId int64) (err error) + UpdateCoreValue(ctx context.Context, organisationID string, coreValueID string, coreValue dto.UpdateQueryRequest) (resp dto.UpdateCoreValuesResp, err error) +} + +func NewService(coreValuesRepo db.CoreValueStorer) Service { + return &service{ + coreValuesRepo: coreValuesRepo, + } +} + +func (cs *service) ListCoreValues(ctx context.Context, organisationID string) (resp []dto.ListCoreValuesResp, err error) { + + if organisationID == "" { + err = apperrors.InvalidOrgId + return + } + + orgId, err := VarsStringToInt(organisationID, "organisationId") + if err != nil { + return + } + + err = cs.coreValuesRepo.CheckOrganisation(ctx, orgId) + if err != nil { + return + } + + resp, err = cs.coreValuesRepo.ListCoreValues(ctx, orgId) + if err != nil { + logger.WithField("err", err.Error()).Error("Error while fetching data") + err = apperrors.InternalServerError + } + + return + +} + +func (cs *service) GetCoreValue(ctx context.Context, organisationID string, coreValueID string) (coreValue dto.GetCoreValueResp, err error) { + + orgId, err := VarsStringToInt(organisationID, "organisationId") + if err != nil { + return + } + + err = cs.coreValuesRepo.CheckOrganisation(ctx, orgId) + if err != nil { + return + } + + coreValId, err := VarsStringToInt(coreValueID, "coreValueId") + if err != err { + return + } + + coreValue, err = cs.coreValuesRepo.GetCoreValue(ctx, orgId, coreValId) + if err != nil { + logger.WithField("err", err.Error()).Error("Error while fetching data") + return + } + + return +} + +func (cs *service) CreateCoreValue(ctx context.Context, organisationID string, userId int64, coreValue dto.CreateCoreValueReq) (resp dto.CreateCoreValueResp, err error) { + + orgId, err := VarsStringToInt(organisationID, "organisationId") + if err != nil { + return + } + + err = cs.coreValuesRepo.CheckOrganisation(ctx, orgId) + if err != nil { + return + } + + isUnique, err := cs.coreValuesRepo.CheckUniqueCoreVal(ctx, orgId, coreValue.Text) + if err != nil { + return + } + if !isUnique { + err = apperrors.UniqueCoreValue + return + } + + err = Validate(ctx, coreValue, cs.coreValuesRepo, orgId) + if err != nil { + return + } + + resp, err = cs.coreValuesRepo.CreateCoreValue(ctx, orgId, userId, coreValue) + if err != nil { + logger.WithField("err", err.Error()).Error("Error while creating core value") + err = apperrors.InternalServerError + return + } + + return +} + +func (cs *service) DeleteCoreValue(ctx context.Context, organisationID string, coreValueID string, userId int64) (err error) { + + orgId, err := VarsStringToInt(organisationID, "organisationId") + if err != nil { + return + } + + err = cs.coreValuesRepo.CheckOrganisation(ctx, orgId) + if err != nil { + return + } + + coreValId, err := VarsStringToInt(coreValueID, "coreValueId") + if err != nil { + return + } + + coreValue, err := cs.coreValuesRepo.GetCoreValue(ctx, orgId, coreValId) + if err != nil { + logger.WithField("err", err.Error()).Error("Error while fetching data") + return + } + + if coreValue.SoftDelete { + err = apperrors.InvalidCoreValueData + return + } + + err = cs.coreValuesRepo.DeleteCoreValue(ctx, orgId, coreValId, userId) + if err != nil { + logger.WithField("err", err.Error()).Error("Error while deleting core value") + err = apperrors.InternalServerError + + return + } + + return +} + +func (cs *service) UpdateCoreValue(ctx context.Context, organisationID string, coreValueID string, reqData dto.UpdateQueryRequest) (resp dto.UpdateCoreValuesResp, err error) { + + orgId, err := VarsStringToInt(organisationID, "organisationId") + if err != nil { + return + } + + coreValId, err := VarsStringToInt(coreValueID, "coreValueId") + if err != nil { + return + } + + //validate organisation + err = cs.coreValuesRepo.CheckOrganisation(ctx, orgId) + if err != nil { + return + } + + //validate corevalue + //get data + coreValue, err := cs.coreValuesRepo.GetCoreValue(ctx, orgId, coreValId) + if err != nil { + logger.WithField("err", err.Error()).Error("Error while fetching data") + return + } + + if coreValue.SoftDelete { + err = apperrors.InvalidCoreValueData + return + } + + //set empty fields + if reqData.Text == "" { + reqData.Text = coreValue.Text + } + if reqData.Description == "" { + reqData.Description = coreValue.Description + } + if reqData.ThumbnailUrl == "" { + reqData.ThumbnailUrl = *coreValue.ThumbnailURL + } + + isUnique, err := cs.coreValuesRepo.CheckUniqueCoreVal(ctx, orgId, reqData.Text) + if err != nil { + return + } + if !isUnique && reqData.Text != coreValue.Text { + err = apperrors.UniqueCoreValue + return + } + + resp, err = cs.coreValuesRepo.UpdateCoreValue(ctx, orgId, coreValId, reqData) + if err != nil { + logger.WithField("err", err.Error()).Error("Error while updating core value") + err = apperrors.InternalServerError + + return + } + + return +} diff --git a/go-backend/service/coreValues/service_test.go b/go-backend/service/coreValues/service_test.go new file mode 100644 index 000000000..c89667ad8 --- /dev/null +++ b/go-backend/service/coreValues/service_test.go @@ -0,0 +1,425 @@ +package corevalues + +import ( + "context" + "joshsoftware/peerly/apperrors" + "joshsoftware/peerly/db/mocks" + "joshsoftware/peerly/pkg/dto" + "testing" + + "github.com/stretchr/testify/mock" +) + +func TestListCoreValues(t *testing.T) { + coreValueRepo := mocks.NewCoreValueStorer(t) + service := NewService(coreValueRepo) + + tests := []struct { + name string + context context.Context + organizationId string + setup func(coreValueMock *mocks.CoreValueStorer) + isErrorExpected bool + }{ + { + name: "Success for list corevalues", + context: context.Background(), + organizationId: "1", + setup: func(coreValueMock *mocks.CoreValueStorer) { + coreValueMock.On("CheckOrganisation", mock.Anything, mock.Anything).Return(nil).Once() + coreValueMock.On("ListCoreValues", mock.Anything, mock.Anything).Return([]dto.ListCoreValuesResp{}, nil).Once() + }, + isErrorExpected: false, + }, + { + name: "Invalid organisation id", + context: context.Background(), + organizationId: "0", + setup: func(coreValueMock *mocks.CoreValueStorer) { + coreValueMock.On("CheckOrganisation", mock.Anything, mock.Anything).Return(apperrors.InvalidOrgId).Once() + + }, + isErrorExpected: true, + }, + { + name: "Error in list corevalues", + context: context.Background(), + organizationId: "1", + setup: func(coreValueMock *mocks.CoreValueStorer) { + coreValueMock.On("CheckOrganisation", mock.Anything, mock.Anything).Return(nil).Once() + coreValueMock.On("ListCoreValues", mock.Anything, mock.Anything).Return([]dto.ListCoreValuesResp{}, apperrors.InternalServerError).Once() + }, + isErrorExpected: true, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + test.setup(coreValueRepo) + + // test service + _, err := service.ListCoreValues(test.context, test.organizationId) + + if (err != nil) != test.isErrorExpected { + t.Errorf("Test Failed, expected error to be %v, but got err %v", test.isErrorExpected, err != nil) + } + }) + } +} + +func TestGetCoreValue(t *testing.T) { + coreValueRepo := mocks.NewCoreValueStorer(t) + service := NewService(coreValueRepo) + + tests := []struct { + name string + context context.Context + organizationId string + coreValueId string + setup func(coreValueMock *mocks.CoreValueStorer) + isErrorExpected bool + }{ + { + name: "Success for get corevalue", + context: context.Background(), + organizationId: "1", + coreValueId: "1", + setup: func(coreValueMock *mocks.CoreValueStorer) { + coreValueMock.On("CheckOrganisation", mock.Anything, mock.Anything).Return(nil).Once() + coreValueMock.On("GetCoreValue", mock.Anything, mock.Anything, mock.Anything).Return(dto.GetCoreValueResp{}, nil).Once() + }, + isErrorExpected: false, + }, + { + name: "Invalid organisation", + context: context.Background(), + organizationId: "0", + coreValueId: "1", + setup: func(coreValueMock *mocks.CoreValueStorer) { + coreValueMock.On("CheckOrganisation", mock.Anything, mock.Anything).Return(apperrors.InvalidOrgId).Once() + + }, + isErrorExpected: true, + }, + { + name: "Invalid corevalue", + context: context.Background(), + organizationId: "1", + coreValueId: "0", + setup: func(coreValueMock *mocks.CoreValueStorer) { + coreValueMock.On("CheckOrganisation", mock.Anything, mock.Anything).Return(nil).Once() + coreValueMock.On("GetCoreValue", mock.Anything, mock.Anything, mock.Anything).Return(dto.GetCoreValueResp{}, apperrors.InvalidCoreValueData).Once() + }, + isErrorExpected: true, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + test.setup(coreValueRepo) + + // test service + _, err := service.GetCoreValue(test.context, test.organizationId, test.coreValueId) + + if (err != nil) != test.isErrorExpected { + t.Errorf("Test Failed, expected error to be %v, but got err %v", test.isErrorExpected, err != nil) + } + }) + } +} + +func TestCreateCoreValue(t *testing.T) { + coreValueRepo := mocks.NewCoreValueStorer(t) + service := NewService(coreValueRepo) + + tests := []struct { + name string + context context.Context + organizationId string + userId int64 + coreValue dto.CreateCoreValueReq + setup func(coreValueMock *mocks.CoreValueStorer) + isErrorExpected bool + }{ + { + name: "Success for create corevalue", + context: context.Background(), + organizationId: "1", + userId: 1, + coreValue: dto.CreateCoreValueReq{ + Text: "CoreValue", + Description: "core value desc", + ParentID: nil, + ThumbnailURL: "thumbnail url string", + }, + setup: func(coreValueMock *mocks.CoreValueStorer) { + coreValueMock.On("CheckOrganisation", mock.Anything, mock.Anything).Return(nil).Once() + coreValueMock.On("CheckUniqueCoreVal", mock.Anything, mock.Anything, mock.Anything).Return(true, nil).Once() + coreValueMock.On("CreateCoreValue", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(dto.CreateCoreValueResp{}, nil).Once() + }, + isErrorExpected: false, + }, + { + name: "Invalid organisation", + context: context.Background(), + organizationId: "0", + userId: 1, + coreValue: dto.CreateCoreValueReq{ + Text: "CoreValue", + Description: "core value desc", + ParentID: nil, + ThumbnailURL: "thumbnail url string", + }, + setup: func(coreValueMock *mocks.CoreValueStorer) { + coreValueMock.On("CheckOrganisation", mock.Anything, mock.Anything).Return(apperrors.InvalidOrgId).Once() + + }, + isErrorExpected: true, + }, + { + name: "Error while checking organisation", + context: context.Background(), + organizationId: "0", + userId: 1, + coreValue: dto.CreateCoreValueReq{ + Text: "CoreValue", + Description: "core value desc", + ParentID: nil, + ThumbnailURL: "thumbnail url string", + }, + setup: func(coreValueMock *mocks.CoreValueStorer) { + coreValueMock.On("CheckOrganisation", mock.Anything, mock.Anything).Return(nil).Once() + coreValueMock.On("CheckUniqueCoreVal", mock.Anything, mock.Anything, mock.Anything).Return(true, apperrors.InternalServerError).Once() + + }, + isErrorExpected: true, + }, + { + name: "Repeated core value", + context: context.Background(), + organizationId: "1", + userId: 1, + coreValue: dto.CreateCoreValueReq{ + Text: "CoreValue", + Description: "core value desc", + ParentID: nil, + ThumbnailURL: "thumbnail url string", + }, + setup: func(coreValueMock *mocks.CoreValueStorer) { + coreValueMock.On("CheckOrganisation", mock.Anything, mock.Anything).Return(nil).Once() + coreValueMock.On("CheckUniqueCoreVal", mock.Anything, mock.Anything, mock.Anything).Return(false, nil).Once() + + }, + isErrorExpected: true, + }, + { + name: "Error while creating core value", + context: context.Background(), + organizationId: "1", + userId: 1, + coreValue: dto.CreateCoreValueReq{ + Text: "CoreValue", + Description: "core value desc", + ParentID: nil, + ThumbnailURL: "thumbnail url string", + }, + setup: func(coreValueMock *mocks.CoreValueStorer) { + coreValueMock.On("CheckOrganisation", mock.Anything, mock.Anything).Return(nil).Once() + coreValueMock.On("CheckUniqueCoreVal", mock.Anything, mock.Anything, mock.Anything).Return(true, nil).Once() + coreValueMock.On("CreateCoreValue", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(dto.CreateCoreValueResp{}, apperrors.InternalServerError).Once() + }, + isErrorExpected: true, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + test.setup(coreValueRepo) + + // test service + _, err := service.CreateCoreValue(test.context, test.organizationId, test.userId, test.coreValue) + + if (err != nil) != test.isErrorExpected { + t.Errorf("Test Failed, expected error to be %v, but got err %v", test.isErrorExpected, err != nil) + } + }) + } +} + +func TestDeleteCoreValue(t *testing.T) { + coreValueRepo := mocks.NewCoreValueStorer(t) + service := NewService(coreValueRepo) + + tests := []struct { + name string + context context.Context + organizationId string + coreValueId string + userId int64 + setup func(coreValueMock *mocks.CoreValueStorer) + isErrorExpected bool + }{ + { + name: "Success for delete corevalue", + context: context.Background(), + organizationId: "1", + coreValueId: "1", + userId: 1, + setup: func(coreValueMock *mocks.CoreValueStorer) { + coreValueMock.On("CheckOrganisation", mock.Anything, mock.Anything).Return(nil).Once() + coreValueMock.On("GetCoreValue", mock.Anything, mock.Anything, mock.Anything).Return(dto.GetCoreValueResp{}, nil).Once() + coreValueMock.On("DeleteCoreValue", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Once() + + }, + isErrorExpected: false, + }, + { + name: "Invalid organisation", + context: context.Background(), + organizationId: "1", + coreValueId: "1", + userId: 1, + setup: func(coreValueMock *mocks.CoreValueStorer) { + coreValueMock.On("CheckOrganisation", mock.Anything, mock.Anything).Return(apperrors.InvalidOrgId).Once() + + }, + isErrorExpected: true, + }, + { + name: "Invalid corevalue id", + context: context.Background(), + organizationId: "1", + coreValueId: "1", + userId: 1, + setup: func(coreValueMock *mocks.CoreValueStorer) { + coreValueMock.On("CheckOrganisation", mock.Anything, mock.Anything).Return(nil).Once() + coreValueMock.On("GetCoreValue", mock.Anything, mock.Anything, mock.Anything).Return(dto.GetCoreValueResp{}, apperrors.InvalidCoreValueData).Once() + }, + isErrorExpected: true, + }, + { + name: "Error in deleting core value", + context: context.Background(), + organizationId: "1", + coreValueId: "1", + userId: 1, + setup: func(coreValueMock *mocks.CoreValueStorer) { + coreValueMock.On("CheckOrganisation", mock.Anything, mock.Anything).Return(nil).Once() + coreValueMock.On("GetCoreValue", mock.Anything, mock.Anything, mock.Anything).Return(dto.GetCoreValueResp{}, nil).Once() + coreValueMock.On("DeleteCoreValue", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(apperrors.InternalServerError).Once() + + }, + isErrorExpected: true, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + test.setup(coreValueRepo) + + // test service + err := service.DeleteCoreValue(test.context, test.organizationId, test.coreValueId, test.userId) + + if (err != nil) != test.isErrorExpected { + t.Errorf("Test Failed, expected error to be %v, but got err %v", test.isErrorExpected, err != nil) + } + }) + } +} + +func TestUpdateCoreValue(t *testing.T) { + coreValueRepo := mocks.NewCoreValueStorer(t) + service := NewService(coreValueRepo) + + tests := []struct { + name string + context context.Context + organizationId string + coreValueId string + reqData dto.UpdateQueryRequest + setup func(coreValueMock *mocks.CoreValueStorer) + isErrorExpected bool + }{ + { + name: "Success for delete corevalue", + context: context.Background(), + organizationId: "1", + coreValueId: "1", + reqData: dto.UpdateQueryRequest{ + Text: "Updated core value", + Description: "updated description", + ThumbnailUrl: "updated thumbnail url", + }, + setup: func(coreValueMock *mocks.CoreValueStorer) { + coreValueMock.On("CheckOrganisation", mock.Anything, mock.Anything).Return(nil).Once() + coreValueMock.On("GetCoreValue", mock.Anything, mock.Anything, mock.Anything).Return(dto.GetCoreValueResp{}, nil).Once() + coreValueMock.On("UpdateCoreValue", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(dto.UpdateCoreValuesResp{}, nil).Once() + + }, + isErrorExpected: false, + }, + { + name: "Invalid organisation", + context: context.Background(), + organizationId: "1", + coreValueId: "1", + reqData: dto.UpdateQueryRequest{ + Text: "Updated core value", + Description: "updated description", + ThumbnailUrl: "updated thumbnail url", + }, + setup: func(coreValueMock *mocks.CoreValueStorer) { + coreValueMock.On("CheckOrganisation", mock.Anything, mock.Anything).Return(apperrors.InvalidOrgId).Once() + + }, + isErrorExpected: true, + }, + { + name: "Invalid corevalue id", + context: context.Background(), + organizationId: "1", + coreValueId: "1", + reqData: dto.UpdateQueryRequest{ + Text: "Updated core value", + Description: "updated description", + ThumbnailUrl: "updated thumbnail url", + }, + setup: func(coreValueMock *mocks.CoreValueStorer) { + coreValueMock.On("CheckOrganisation", mock.Anything, mock.Anything).Return(nil).Once() + coreValueMock.On("GetCoreValue", mock.Anything, mock.Anything, mock.Anything).Return(dto.GetCoreValueResp{}, apperrors.InvalidCoreValueData).Once() + }, + isErrorExpected: true, + }, + { + name: "Error in updating core value", + context: context.Background(), + organizationId: "1", + coreValueId: "1", + reqData: dto.UpdateQueryRequest{ + Text: "Updated core value", + Description: "updated description", + ThumbnailUrl: "updated thumbnail url", + }, + setup: func(coreValueMock *mocks.CoreValueStorer) { + coreValueMock.On("CheckOrganisation", mock.Anything, mock.Anything).Return(nil).Once() + coreValueMock.On("GetCoreValue", mock.Anything, mock.Anything, mock.Anything).Return(dto.GetCoreValueResp{}, nil).Once() + coreValueMock.On("UpdateCoreValue", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(dto.UpdateCoreValuesResp{}, apperrors.InternalServerError).Once() + + }, + isErrorExpected: true, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + test.setup(coreValueRepo) + + // test service + _, err := service.UpdateCoreValue(test.context, test.organizationId, test.coreValueId, test.reqData) + + if (err != nil) != test.isErrorExpected { + t.Errorf("Test Failed, expected error to be %v, but got err %v", test.isErrorExpected, err != nil) + } + }) + } +} diff --git a/go-backend/service/core_value_http.go b/go-backend/service/core_value_http.go index b80dab164..bd28d9369 100644 --- a/go-backend/service/core_value_http.go +++ b/go-backend/service/core_value_http.go @@ -1,206 +1,205 @@ package service import ( - "encoding/json" + // "encoding/json" "net/http" - "strconv" - "github.com/gorilla/mux" - logger "github.com/sirupsen/logrus" - "joshsoftware/peerly/db" + // "joshsoftware/peerly/db" + // "joshsoftware/peerly/pkg/dto" + corevalues "joshsoftware/peerly/service/coreValues" + // "github.com/gorilla/mux" + // logger "github.com/sirupsen/logrus" ) -func listCoreValuesHandler(deps Dependencies) http.HandlerFunc { +func listCoreValuesHandler(coreValueSvc corevalues.Service) http.HandlerFunc { return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { - vars := mux.Vars(req) - organisationID, err := strconv.ParseInt(vars["organisation_id"], 10, 64) - if err != nil { - logger.WithField("err", err.Error()).Error("Error while parsing organisation_id from url") - rw.WriteHeader(http.StatusBadRequest) - return - } - - coreValues, err := deps.Store.ListCoreValues(req.Context(), organisationID) - if err != nil { - logger.WithField("err", err.Error()).Error("Error while fetching data") - rw.WriteHeader(http.StatusInternalServerError) - repsonse(rw, http.StatusInternalServerError, errorResponse{ - Error: messageObject{ - Message: "Internal server error", - }, - }) - return - } - - repsonse(rw, http.StatusOK, successResponse{Data: coreValues}) + // vars := mux.Vars(req) + // organisationID := vars["organisation_id"] + + // coreValues, msgObj := coreValueSvc.ListCoreValues(req.Context(), organisationID) + // if (msgObj != dto.MessageObject{}) { + // rw.WriteHeader(http.StatusInternalServerError) + // repsonse(rw, http.StatusInternalServerError, errorResponse{ + // Error: msgObj, + // }) + // return + // } + + repsonse(rw, http.StatusOK, successResponse{}) }) } -func getCoreValueHandler(deps Dependencies) http.HandlerFunc { +func getCoreValueHandler(coreValueSvc corevalues.Service) http.HandlerFunc { return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { - vars := mux.Vars(req) - organisationID, err := strconv.ParseInt(vars["organisation_id"], 10, 64) - if err != nil { - logger.WithField("err", err.Error()).Error("Error while parsing organisation_id from url") - rw.WriteHeader(http.StatusBadRequest) - return - } - - coreValueID, err := strconv.ParseInt(vars["id"], 10, 64) - if err != nil { - logger.WithField("err", err.Error()).Error("Error while parsing core value id from url") - rw.WriteHeader(http.StatusBadRequest) - return - } - - coreValue, err := deps.Store.GetCoreValue(req.Context(), organisationID, coreValueID) - if err != nil { - logger.WithField("err", err.Error()).Error("Error while fetching data") - repsonse(rw, http.StatusInternalServerError, errorResponse{ - Error: messageObject{ - Message: "Internal server error", - }, - }) - return - } - - repsonse(rw, http.StatusOK, successResponse{Data: coreValue}) + // vars := mux.Vars(req) + + // coreValue, msgObj := coreValueSvc.GetCoreValue(req.Context(), vars["organisation_id"], vars["id"]) + // if (msgObj != dto.MessageObject{}) { + + // repsonse(rw, http.StatusInternalServerError, errorResponse{ + // Error: msgObj, + // }) + // return + // } + + repsonse(rw, http.StatusOK, successResponse{}) }) } -func createCoreValueHandler(deps Dependencies) http.HandlerFunc { +func createCoreValueHandler(coreValueSvc corevalues.Service) http.HandlerFunc { return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { - vars := mux.Vars(req) - organisationID, err := strconv.ParseInt(vars["organisation_id"], 10, 64) - if err != nil { - logger.WithField("err", err.Error()).Error("Error while parsing organisation_id from url") - rw.WriteHeader(http.StatusBadRequest) - return - } - - var coreValue db.CoreValue - err = json.NewDecoder(req.Body).Decode(&coreValue) - if err != nil { - logger.WithField("err", err.Error()).Error("Error while decoding request data") - repsonse(rw, http.StatusBadRequest, errorResponse{ - Error: messageObject{ - Message: "Invalid json request body", - }, - }) - return - } - - ok, errFields := coreValue.Validate(req.Context(), deps.Store, organisationID) - if !ok { - repsonse(rw, http.StatusBadRequest, errorResponse{ - Error: errorObject{ - Code: "invalid-core-value", - Fields: errFields, - messageObject: messageObject{"Invalid core value data"}, - }, - }) - return - } - - resp, err := deps.Store.CreateCoreValue(req.Context(), organisationID, coreValue) - if err != nil { - logger.WithField("err", err.Error()).Error("Error while creating core value") - repsonse(rw, http.StatusInternalServerError, errorResponse{ - Error: messageObject{ - Message: "Internal server error", - }, - }) - return - } - - repsonse(rw, http.StatusCreated, successResponse{Data: resp}) + // vars := mux.Vars(req) + // var coreValue db.CoreValue + // err := json.NewDecoder(req.Body).Decode(&coreValue) + // if err != nil { + // logger.WithField("err", err.Error()).Error("Error while decoding request data") + // repsonse(rw, http.StatusBadRequest, errorResponse{ + // Error: messageObject{ + // Message: "Invalid json request body", + // }, + // }) + // return + // } + + // resp, msgObj := coreValueSvc.CreateCoreValue(req.Context(), vars["organisation_id"], coreValue) + // if (msgObj != dto.MessageObject{}) { + + // repsonse(rw, http.StatusInternalServerError, errorResponse{ + // Error: msgObj, + // }) + // return + // } + + // ok, errFields := coreValue.Validate(req.Context(), deps.Store, organisationID) + // if !ok { + // repsonse(rw, http.StatusBadRequest, errorResponse{ + // Error: errorObject{ + // Code: "invalid-core-value", + // Fields: errFields, + // messageObject: messageObject{"Invalid core value data"}, + // }, + // }) + // return + // } + + // resp, err := deps.Store.CreateCoreValue(req.Context(), organisationID, coreValue) + // if err != nil { + // logger.WithField("err", err.Error()).Error("Error while creating core value") + // repsonse(rw, http.StatusInternalServerError, errorResponse{ + // Error: messageObject{ + // Message: "Internal server error", + // }, + // }) + // return + // } + + repsonse(rw, http.StatusCreated, successResponse{}) }) } -func deleteCoreValueHandler(deps Dependencies) http.HandlerFunc { +func deleteCoreValueHandler(coreValueSvc corevalues.Service) http.HandlerFunc { return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { - vars := mux.Vars(req) - organisationID, err := strconv.ParseInt(vars["organisation_id"], 10, 64) - if err != nil { - logger.WithField("err", err.Error()).Error("Error while parsing organisation_id from url") - rw.WriteHeader(http.StatusBadRequest) - return - } - - coreValueID, err := strconv.ParseInt(vars["id"], 10, 64) - if err != nil { - logger.WithField("err", err.Error()).Error("Error while parsing core value id from url") - rw.WriteHeader(http.StatusBadRequest) - return - } - - err = deps.Store.DeleteCoreValue(req.Context(), organisationID, coreValueID) - if err != nil { - logger.WithField("err", err.Error()).Error("Error while deleting core value") - repsonse(rw, http.StatusInternalServerError, errorResponse{ - Error: messageObject{ - Message: "Internal server error", - }, - }) - return - } + // vars := mux.Vars(req) + + // msgObj := coreValueSvc.DeleteCoreValue(req.Context(), vars["organisation_id"], vars["id"]) + // if (msgObj != dto.MessageObject{}) { + + // repsonse(rw, http.StatusInternalServerError, errorResponse{ + // Error: msgObj, + // }) + // return + // } + + // organisationID, err := strconv.ParseInt(vars["organisation_id"], 10, 64) + // if err != nil { + // logger.WithField("err", err.Error()).Error("Error while parsing organisation_id from url") + // rw.WriteHeader(http.StatusBadRequest) + // return + // } + + // coreValueID, err := strconv.ParseInt(vars["id"], 10, 64) + // if err != nil { + // logger.WithField("err", err.Error()).Error("Error while parsing core value id from url") + // rw.WriteHeader(http.StatusBadRequest) + // return + // } + + // err = deps.Store.DeleteCoreValue(req.Context(), organisationID, coreValueID) + // if err != nil { + // logger.WithField("err", err.Error()).Error("Error while deleting core value") + // repsonse(rw, http.StatusInternalServerError, errorResponse{ + // Error: messageObject{ + // Message: "Internal server error", + // }, + // }) + // return + // } repsonse(rw, http.StatusOK, nil) }) } -func updateCoreValueHandler(deps Dependencies) http.HandlerFunc { +func updateCoreValueHandler(coreValueSvc corevalues.Service) http.HandlerFunc { return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { - vars := mux.Vars(req) - organisationID, err := strconv.ParseInt(vars["organisation_id"], 10, 64) - if err != nil { - logger.WithField("err", err.Error()).Error("Error while parsing organisation_id from url") - rw.WriteHeader(http.StatusBadRequest) - return - } - - coreValueID, err := strconv.ParseInt(vars["id"], 10, 64) - if err != nil { - logger.WithField("err", err.Error()).Error("Error while parsing core value id from url") - rw.WriteHeader(http.StatusBadRequest) - return - } - - var coreValue db.CoreValue - err = json.NewDecoder(req.Body).Decode(&coreValue) - if err != nil { - logger.WithField("err", err.Error()).Error("Error while decoding request data") - repsonse(rw, http.StatusBadRequest, errorResponse{ - Error: messageObject{ - Message: "Invalid json request body", - }, - }) - return - } - - ok, errFields := coreValue.Validate(req.Context(), deps.Store, organisationID) - if !ok { - repsonse(rw, http.StatusBadRequest, errorResponse{ - Error: errorObject{ - Code: "invalid-core-value", - Fields: errFields, - messageObject: messageObject{"Invalid core value data"}, - }, - }) - return - } - - resp, err := deps.Store.UpdateCoreValue(req.Context(), organisationID, coreValueID, coreValue) - if err != nil { - logger.WithField("err", err.Error()).Error("Error while updating core value") - repsonse(rw, http.StatusInternalServerError, errorResponse{ - Error: messageObject{ - Message: "Internal server error", - }, - }) - return - } - - repsonse(rw, http.StatusOK, successResponse{Data: resp}) + // vars := mux.Vars(req) + // organisationID, err := strconv.ParseInt(vars["organisation_id"], 10, 64) + // if err != nil { + // logger.WithField("err", err.Error()).Error("Error while parsing organisation_id from url") + // rw.WriteHeader(http.StatusBadRequest) + // return + // } + + // coreValueID, err := strconv.ParseInt(vars["id"], 10, 64) + // if err != nil { + // logger.WithField("err", err.Error()).Error("Error while parsing core value id from url") + // rw.WriteHeader(http.StatusBadRequest) + // return + // } + + // var coreValue db.CoreValue + // err := json.NewDecoder(req.Body).Decode(&coreValue) + // if err != nil { + // logger.WithField("err", err.Error()).Error("Error while decoding request data") + // repsonse(rw, http.StatusBadRequest, errorResponse{ + // Error: messageObject{ + // Message: "Invalid json request body", + // }, + // }) + // return + // } + + // ok, errFields := coreValue.Validate(req.Context(), deps.Store, organisationID) + // if !ok { + // repsonse(rw, http.StatusBadRequest, errorResponse{ + // Error: errorObject{ + // Code: "invalid-core-value", + // Fields: errFields, + // messageObject: messageObject{"Invalid core value data"}, + // }, + // }) + // return + // } + + // resp, err := deps.Store.UpdateCoreValue(req.Context(), organisationID, coreValueID, coreValue) + // if err != nil { + // logger.WithField("err", err.Error()).Error("Error while updating core value") + // repsonse(rw, http.StatusInternalServerError, errorResponse{ + // Error: messageObject{ + // Message: "Internal server error", + // }, + // }) + // return + // } + + // resp, msgObj := coreValueSvc.UpdateCoreValue(req.Context(), vars["organisation_id"], vars["id"], coreValue) + // if (msgObj != dto.MessageObject{}) { + + // repsonse(rw, http.StatusInternalServerError, errorResponse{ + // Error: msgObj, + // }) + // return + // } + + repsonse(rw, http.StatusOK, successResponse{}) }) } diff --git a/go-backend/service/dependencies.go b/go-backend/service/dependencies.go index f1cec77c2..ee70f58e6 100644 --- a/go-backend/service/dependencies.go +++ b/go-backend/service/dependencies.go @@ -1,13 +1,28 @@ package service import ( - "joshsoftware/peerly/aws" + // "joshsoftware/peerly/aws" "joshsoftware/peerly/db" + DB "joshsoftware/peerly/db" + corevalues "joshsoftware/peerly/service/coreValues" + + "github.com/jmoiron/sqlx" ) // Dependencies - Stuff we need for the service package type Dependencies struct { - Store db.Storer - AWSStore aws.AWSStorer + Store DB.Storer + // AWSStore aws.AWSStorer // define other service dependencies + CoreValueService corevalues.Service +} + +func NewServices(db *sqlx.DB, store db.Storer) Dependencies { + coreValueRepo := DB.NewCoreValueRepo(db) + coreValueService := corevalues.NewService(coreValueRepo) + + return Dependencies{ + Store: store, + CoreValueService: coreValueService, + } } diff --git a/go-backend/service/router.go b/go-backend/service/router.go index c3e6de4a2..224c4410c 100644 --- a/go-backend/service/router.go +++ b/go-backend/service/router.go @@ -30,15 +30,15 @@ func InitRouter(deps Dependencies) (router *mux.Router) { v1 := fmt.Sprintf("application/vnd.%s.v1", config.AppName()) //core values - router.Handle("/organisations/{organisation_id:[0-9]+}/core_values/{id:[0-9]+}", jwtAuthMiddleware(getCoreValueHandler(deps), deps)).Methods(http.MethodGet).Headers(versionHeader, v1) + router.Handle("/organisations/{organisation_id:[0-9]+}/core_values/{id:[0-9]+}", jwtAuthMiddleware(getCoreValueHandler(deps.CoreValueService), deps)).Methods(http.MethodGet).Headers(versionHeader, v1) - router.Handle("/organisations/{organisation_id:[0-9]+}/core_values", jwtAuthMiddleware(listCoreValuesHandler(deps), deps)).Methods(http.MethodGet).Headers(versionHeader, v1) + router.Handle("/organisations/{organisation_id:[0-9]+}/core_values", jwtAuthMiddleware(listCoreValuesHandler(deps.CoreValueService), deps)).Methods(http.MethodGet).Headers(versionHeader, v1) - router.Handle("/organisations/{organisation_id:[0-9]+}/core_values", jwtAuthMiddleware(createCoreValueHandler(deps), deps)).Methods(http.MethodPost).Headers(versionHeader, v1) + router.Handle("/organisations/{organisation_id:[0-9]+}/core_values", jwtAuthMiddleware(createCoreValueHandler(deps.CoreValueService), deps)).Methods(http.MethodPost).Headers(versionHeader, v1) - router.Handle("/organisations/{organisation_id:[0-9]+}/core_values/{id:[0-9]+}", jwtAuthMiddleware(deleteCoreValueHandler(deps), deps)).Methods(http.MethodDelete).Headers(versionHeader, v1) + router.Handle("/organisations/{organisation_id:[0-9]+}/core_values/{id:[0-9]+}", jwtAuthMiddleware(deleteCoreValueHandler(deps.CoreValueService), deps)).Methods(http.MethodDelete).Headers(versionHeader, v1) - router.Handle("/organisations/{organisation_id:[0-9]+}/core_values/{id:[0-9]+}", jwtAuthMiddleware(updateCoreValueHandler(deps), deps)).Methods(http.MethodPut).Headers(versionHeader, v1) + router.Handle("/organisations/{organisation_id:[0-9]+}/core_values/{id:[0-9]+}", jwtAuthMiddleware(updateCoreValueHandler(deps.CoreValueService), deps)).Methods(http.MethodPut).Headers(versionHeader, v1) //reported recognition router.Handle("/recognitions/{recognition_id:[0-9]+}/report", jwtAuthMiddleware(createReportedRecognitionHandler(deps), deps)).Methods(http.MethodPost).Headers(versionHeader, v1) @@ -86,7 +86,7 @@ func InitRouter(deps Dependencies) (router *mux.Router) { router.Handle("/organizations/{organization_id:[0-9]+}/badges/{id:[0-9]+}", jwtAuthMiddleware(deleteBadgeHandler(deps), deps)).Methods(http.MethodDelete).Headers(versionHeader, v1) // Get S3 signed URL - router.Handle("/s3_signed_url", jwtAuthMiddleware(getS3SignedURLHandler(deps), deps)).Methods(http.MethodGet).Headers(versionHeader, v1) + // router.Handle("/s3_signed_url", jwtAuthMiddleware(getS3SignedURLHandler(deps), deps)).Methods(http.MethodGet).Headers(versionHeader, v1) // Recognition Hi5 routes