From d50e2d30d20b05201e385d1a9f5ff69d1b97bc82 Mon Sep 17 00:00:00 2001 From: Anton Galitsyn Date: Tue, 17 Jan 2023 19:48:41 +0700 Subject: [PATCH] rework user action logger --- Makefile | 2 +- cmd/api/main.go | 26 +- pkg/app/api/server/middleware.go | 16 +- pkg/app/api/server/permissions.go | 22 +- pkg/app/api/server/private/agents.go | 257 +++---- pkg/app/api/server/private/binaries.go | 51 +- pkg/app/api/server/private/events.go | 34 +- pkg/app/api/server/private/groups.go | 194 +++--- pkg/app/api/server/private/modules.go | 727 ++++++++++---------- pkg/app/api/server/private/notifications.go | 11 +- pkg/app/api/server/private/options.go | 32 +- pkg/app/api/server/private/policies.go | 207 +++--- pkg/app/api/server/private/porting.go | 73 +- pkg/app/api/server/private/proto.go | 12 +- pkg/app/api/server/private/roles.go | 10 +- pkg/app/api/server/private/services.go | 54 +- pkg/app/api/server/private/tags.go | 14 +- pkg/app/api/server/private/tenants.go | 48 +- pkg/app/api/server/private/upgrades.go | 133 ++-- pkg/app/api/server/private/users.go | 108 +-- pkg/app/api/server/private/versions.go | 14 +- pkg/app/api/server/proto/proto.go | 96 +-- pkg/app/api/server/public/auth.go | 40 +- pkg/app/api/server/public/info.go | 18 +- pkg/app/api/server/response/http.go | 31 +- pkg/app/api/server/router.go | 18 +- pkg/app/api/server/server_test.go | 221 ------ pkg/app/api/user_action/log.go | 32 + pkg/app/api/user_action/user_action.go | 189 +---- pkg/app/api/utils/utils.go | 92 --- pkg/app/api/utils/utils_test.go | 183 ----- 31 files changed, 1196 insertions(+), 1769 deletions(-) delete mode 100644 pkg/app/api/server/server_test.go create mode 100644 pkg/app/api/user_action/log.go delete mode 100644 pkg/app/api/utils/utils_test.go diff --git a/Makefile b/Makefile index 6211fd5f..0c3cdb92 100644 --- a/Makefile +++ b/Makefile @@ -86,7 +86,7 @@ lint: $(GOLANGCI_BIN) $(GOLANGCI_BIN) run ./... .PHONY: test -test: generate-keys +test: go test -v ./... .PHONY: generate-all diff --git a/cmd/api/main.go b/cmd/api/main.go index 1c7f2f54..df07c3ef 100644 --- a/cmd/api/main.go +++ b/cmd/api/main.go @@ -21,6 +21,7 @@ import ( "soldr/pkg/app/api/server" srvevents "soldr/pkg/app/api/server/events" "soldr/pkg/app/api/storage/mem" + useraction "soldr/pkg/app/api/user_action" "soldr/pkg/app/api/utils/meter" "soldr/pkg/app/api/worker" "soldr/pkg/log" @@ -34,14 +35,13 @@ import ( const serviceName = "vxapi" type Config struct { - Debug bool `config:"debug"` - Develop bool `config:"is_develop"` - Log LogConfig - DB DBConfig - Tracing TracingConfig - PublicAPI PublicAPIConfig - EventWorker EventWorkerConfig - UserActionWorker UserActionWorkerConfig + Debug bool `config:"debug"` + Develop bool `config:"is_develop"` + Log LogConfig + DB DBConfig + Tracing TracingConfig + PublicAPI PublicAPIConfig + EventWorker EventWorkerConfig } type LogConfig struct { @@ -75,10 +75,6 @@ type EventWorkerConfig struct { PollInterval time.Duration `config:"event_worker_poll_interval"` } -type UserActionWorkerConfig struct { - MaxMessages uint `config:"user_action_worker_max_messages"` -} - func defaultConfig() Config { return Config{ Log: LogConfig{ @@ -96,9 +92,6 @@ func defaultConfig() Config { EventWorker: EventWorkerConfig{ PollInterval: 30 * time.Second, }, - UserActionWorker: UserActionWorkerConfig{ - MaxMessages: 100, - }, } } @@ -285,9 +278,12 @@ func main() { // run worker to synchronize events retention policy to all instance DB go worker.SyncRetentionEvents(ctx, dbWithORM) + userActionWriter := useraction.NewLogWriter(logger) + router := server.NewRouter( dbWithORM, exchanger, + userActionWriter, dbConnectionStorage, s3ConnectionStorage, ) diff --git a/pkg/app/api/server/middleware.go b/pkg/app/api/server/middleware.go index b47d768b..2bb63658 100644 --- a/pkg/app/api/server/middleware.go +++ b/pkg/app/api/server/middleware.go @@ -14,7 +14,7 @@ import ( "soldr/pkg/app/api/models" "soldr/pkg/app/api/server/context" "soldr/pkg/app/api/server/private" - srverrors "soldr/pkg/app/api/server/response" + "soldr/pkg/app/api/server/response" "soldr/pkg/app/api/utils" "soldr/pkg/app/api/utils/dbencryptor" ) @@ -43,17 +43,17 @@ func authTokenProtoRequired() gin.HandlerFunc { attrs := []interface{}{uid, rid, sid, tid, prm, exp, gtm, uname} for _, attr := range attrs { if attr == nil { - utils.HTTPError(c, srverrors.ErrNotPermitted, errors.New(msg)) + response.Error(c, response.ErrNotPermitted, errors.New(msg)) return } } if prms, ok := prm.([]string); !ok { - utils.HTTPError(c, srverrors.ErrNotPermitted, nil) + response.Error(c, response.ErrNotPermitted, nil) return } else { if !lookupPerm(prms, privInteractive) { - utils.HTTPError(c, srverrors.ErrNotPermitted, nil) + response.Error(c, response.ErrNotPermitted, nil) return } c.Set("prm", prms) @@ -124,13 +124,13 @@ func authRequired() gin.HandlerFunc { attrs := []interface{}{uid, rid, sid, tid, prm, exp, gtm, uname, svc} for _, attr := range attrs { if attr == nil { - utils.HTTPError(c, srverrors.ErrAuthRequired, errors.New("token claim invalid")) + response.Error(c, response.ErrAuthRequired, errors.New("token claim invalid")) return } } if prms, ok := prm.([]string); !ok { - utils.HTTPError(c, srverrors.ErrAuthRequired, nil) + response.Error(c, response.ErrAuthRequired, nil) return } else { c.Set("prm", prms) @@ -159,7 +159,7 @@ func localUserRequired() gin.HandlerFunc { rid := session.Get("rid") if rid == nil || rid.(uint64) == models.RoleExternal { - utils.HTTPError(c, srverrors.ErrLocalUserRequired, nil) + response.Error(c, response.ErrLocalUserRequired, nil) return } @@ -237,7 +237,7 @@ func setServiceInfo(db *gorm.DB) gin.HandlerFunc { service, err := getService(c) if err != nil { - utils.HTTPError(c, srverrors.ErrInternalServiceNotFound, nil) + response.Error(c, response.ErrInternalServiceNotFound, nil) return } diff --git a/pkg/app/api/server/permissions.go b/pkg/app/api/server/permissions.go index e7c39eac..a8d67176 100644 --- a/pkg/app/api/server/permissions.go +++ b/pkg/app/api/server/permissions.go @@ -8,7 +8,7 @@ import ( "github.com/gin-gonic/gin/binding" "soldr/pkg/app/api/server/private" - srverrors "soldr/pkg/app/api/server/response" + "soldr/pkg/app/api/server/response" "soldr/pkg/app/api/utils" ) @@ -33,13 +33,13 @@ func privilegesRequiredByQueryTypeField(mprivs map[string][]string) gin.HandlerF prms, err := getPrms(c) if err != nil { - utils.HTTPError(c, srverrors.ErrPrivilegesRequired, err) + response.Error(c, response.ErrPrivilegesRequired, err) return } var query utils.TableQuery if err := c.ShouldBindQuery(&query); err != nil { - utils.HTTPError(c, srverrors.ErrPrivilegesRequired, fmt.Errorf("error binding query: %w", err)) + response.Error(c, response.ErrPrivilegesRequired, fmt.Errorf("error binding query: %w", err)) return } for _, filter := range query.Filters { @@ -47,12 +47,12 @@ func privilegesRequiredByQueryTypeField(mprivs map[string][]string) gin.HandlerF if privs, ok := mprivs[value]; ok { for _, priv := range privs { if !lookupPerm(prms, priv) { - utils.HTTPError(c, srverrors.ErrPrivilegesRequired, fmt.Errorf("'%s' is not set", priv)) + response.Error(c, response.ErrPrivilegesRequired, fmt.Errorf("'%s' is not set", priv)) return } } } else { - utils.HTTPError(c, srverrors.ErrPrivilegesRequired, fmt.Errorf("'%s' is not specified", value)) + response.Error(c, response.ErrPrivilegesRequired, fmt.Errorf("'%s' is not specified", value)) return } } @@ -69,23 +69,23 @@ func privilegesRequiredPatchAgents() gin.HandlerFunc { prms, err := getPrms(c) if err != nil { - utils.HTTPError(c, srverrors.ErrPrivilegesRequired, err) + response.Error(c, response.ErrPrivilegesRequired, err) return } var action private.AgentsAction if err := c.ShouldBindBodyWith(&action, binding.JSON); err != nil { - utils.HTTPError(c, srverrors.ErrPrivilegesRequired, fmt.Errorf("error binding query: %w", err)) + response.Error(c, response.ErrPrivilegesRequired, fmt.Errorf("error binding query: %w", err)) return } if action.Action == "delete" { if !lookupPerm(prms, "vxapi.agents.api.delete") { - utils.HTTPError(c, srverrors.ErrPrivilegesRequired, fmt.Errorf("'%s' is not set", "vxapi.agents.api.delete")) + response.Error(c, response.ErrPrivilegesRequired, fmt.Errorf("'%s' is not set", "vxapi.agents.api.delete")) return } } else { if !lookupPerm(prms, "vxapi.agents.api.edit") { - utils.HTTPError(c, srverrors.ErrPrivilegesRequired, fmt.Errorf("'%s' is not set", "vxapi.agents.api.edit")) + response.Error(c, response.ErrPrivilegesRequired, fmt.Errorf("'%s' is not set", "vxapi.agents.api.edit")) return } } @@ -102,13 +102,13 @@ func privilegesRequired(privs ...string) gin.HandlerFunc { prms, err := getPrms(c) if err != nil { - utils.HTTPError(c, srverrors.ErrPrivilegesRequired, err) + response.Error(c, response.ErrPrivilegesRequired, err) return } for _, priv := range append([]string{}, privs...) { if !lookupPerm(prms, priv) { - utils.HTTPError(c, srverrors.ErrPrivilegesRequired, fmt.Errorf("'%s' is not set", priv)) + response.Error(c, response.ErrPrivilegesRequired, fmt.Errorf("'%s' is not set", priv)) return } } diff --git a/pkg/app/api/server/private/agents.go b/pkg/app/api/server/private/agents.go index 4e011fbb..16f8d22b 100644 --- a/pkg/app/api/server/private/agents.go +++ b/pkg/app/api/server/private/agents.go @@ -5,6 +5,7 @@ import ( "net/http" "time" + "github.com/gin-contrib/sessions" "github.com/gin-gonic/gin" "github.com/gin-gonic/gin/binding" "github.com/jinzhu/gorm" @@ -12,7 +13,8 @@ import ( "soldr/pkg/app/api/client" "soldr/pkg/app/api/models" srvcontext "soldr/pkg/app/api/server/context" - srverrors "soldr/pkg/app/api/server/response" + "soldr/pkg/app/api/server/response" + useraction "soldr/pkg/app/api/user_action" "soldr/pkg/app/api/utils" ) @@ -202,29 +204,45 @@ func getActionCode(action string) string { return actionCode } -func fillAgentUserActionFields(agents []models.Agent, actionCode string) []utils.UserActionFields { - res := make([]utils.UserActionFields, len(agents)) +func fillAgentUserActionFields(c *gin.Context, agents []models.Agent, actionCode string, tStart time.Time) []useraction.Fields { + session := sessions.Default(c) + uid := session.Get("uuid") + uuidstr, _ := uid.(string) + + userName := session.Get("uname") + userNamestr, _ := userName.(string) + res := make([]useraction.Fields, len(agents)) for i, v := range agents { - res[i] = utils.UserActionFields{ + res[i] = useraction.Fields{ + StartTime: tStart, + UserName: userNamestr, + UserUUID: uuidstr, Domain: "agent", ObjectType: "agent", - ObjectId: v.Hash, + ObjectID: v.Hash, ObjectDisplayName: v.Description, ActionCode: actionCode, + Success: false, } } return res } type AgentService struct { - db *gorm.DB - serverConnector *client.AgentServerClient + db *gorm.DB + serverConnector *client.AgentServerClient + userActionWriter useraction.Writer } -func NewAgentService(db *gorm.DB, serverConnector *client.AgentServerClient) *AgentService { +func NewAgentService( + db *gorm.DB, + serverConnector *client.AgentServerClient, + userActionWriter useraction.Writer, +) *AgentService { return &AgentService{ - db: db, - serverConnector: serverConnector, + db: db, + serverConnector: serverConnector, + userActionWriter: userActionWriter, } } @@ -260,26 +278,26 @@ func (s *AgentService) GetAgents(c *gin.Context) { if err := c.ShouldBindQuery(&query); err != nil { utils.FromContext(c).WithError(err).Errorf("error binding query") - utils.HTTPError(c, srverrors.ErrGetAgentsInvalidRequest, err) + response.Error(c, response.ErrGetAgentsInvalidRequest, err) return } serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } if err = query.Init("agents", agentsSQLMappers); err != nil { utils.FromContext(c).WithError(err).Errorf("error binding query") - utils.HTTPError(c, srverrors.ErrGetAgentsInvalidRequest, err) + response.Error(c, response.ErrGetAgentsInvalidRequest, err) return } @@ -326,16 +344,16 @@ func (s *AgentService) GetAgents(c *gin.Context) { if query.Group == "" { if resp.Total, err = query.Query(iDB, &resp.Agents, funcs...); err != nil { utils.FromContext(c).WithError(err).Errorf("error finding agents") - utils.HTTPError(c, srverrors.ErrGetAgentsInvalidQuery, err) + response.Error(c, response.ErrGetAgentsInvalidQuery, err) return } } else { if groupedResp.Total, err = query.QueryGrouped(iDB, &groupedResp.Grouped, funcs...); err != nil { utils.FromContext(c).WithError(err).Errorf("error finding grouped agents") - utils.HTTPError(c, srverrors.ErrGetAgentsInvalidQuery, err) + response.Error(c, response.ErrGetAgentsInvalidQuery, err) return } - utils.HTTPSuccess(c, http.StatusOK, groupedResp) + response.Success(c, http.StatusOK, groupedResp) return } @@ -344,19 +362,19 @@ func (s *AgentService) GetAgents(c *gin.Context) { gids = append(gids, resp.Agents[i].GroupID) if err = resp.Agents[i].Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating agent data '%s'", resp.Agents[i].Hash) - utils.HTTPError(c, srverrors.ErrAgentsInvalidData, err) + response.Error(c, response.ErrAgentsInvalidData, err) return } } if err = iDB.Where("id IN (?)", gids).Find(&groupsa).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding linked groups") - utils.HTTPError(c, srverrors.ErrGetAgentsInvalidQuery, err) + response.Error(c, response.ErrGetAgentsInvalidQuery, err) return } for i := 0; i < len(groupsa); i++ { if err = groupsa[i].Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating group data '%s'", groupsa[i].Hash) - utils.HTTPError(c, srverrors.ErrAgentsInvalidData, err) + response.Error(c, response.ErrAgentsInvalidData, err) return } groups[groupsa[i].ID] = &groupsa[i] @@ -365,7 +383,7 @@ func (s *AgentService) GetAgents(c *gin.Context) { sqlQuery := sqlAgentDetails + ` WHERE a.id IN (?) AND a.deleted_at IS NULL` if err = iDB.Raw(sqlQuery, aids).Scan(&resp.Details).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error loading details agents") - utils.HTTPError(c, srverrors.ErrGetAgentsInvalidQuery, err) + response.Error(c, response.ErrGetAgentsInvalidQuery, err) return } @@ -380,7 +398,7 @@ func (s *AgentService) GetAgents(c *gin.Context) { Find(&tasks).Error if err != nil { utils.FromContext(c).WithError(err).Errorf("error finding linked agent upgrade tasks") - utils.HTTPError(c, srverrors.ErrGetAgentsInvalidQuery, err) + response.Error(c, response.ErrGetAgentsInvalidQuery, err) return } @@ -391,7 +409,7 @@ func (s *AgentService) GetAgents(c *gin.Context) { Find(&modulesa, "gtp.group_id IN (?) AND status = 'joined'", gids).Error if err != nil { utils.FromContext(c).WithError(err).Errorf("error finding group modules") - utils.HTTPError(c, srverrors.ErrGetAgentsInvalidQuery, err) + response.Error(c, response.ErrGetAgentsInvalidQuery, err) return } else { for i := 0; i < len(modulesa); i++ { @@ -400,7 +418,7 @@ func (s *AgentService) GetAgents(c *gin.Context) { policy_id := modulesa[i].PolicyID if err = modulesa[i].Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating group module data '%d' '%s'", id, name) - utils.HTTPError(c, srverrors.ErrAgentsInvalidData, err) + response.Error(c, response.ErrAgentsInvalidData, err) return } if mods, ok := modsToPolicies[policy_id]; ok { @@ -413,7 +431,7 @@ func (s *AgentService) GetAgents(c *gin.Context) { if err = iDB.Find(&gpss, "group_id IN (?)", gids).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding policy to groups links") - utils.HTTPError(c, srverrors.ErrGroupPolicyGroupsNotFound, err) + response.Error(c, response.ErrGroupPolicyGroupsNotFound, err) return } @@ -424,7 +442,7 @@ func (s *AgentService) GetAgents(c *gin.Context) { Find(&policiesa).Error if err != nil { utils.FromContext(c).WithError(err).Errorf("error finding group policies") - utils.HTTPError(c, srverrors.ErrGroupPolicyPoliciesNotFound, err) + response.Error(c, response.ErrGroupPolicyPoliciesNotFound, err) return } else { for i := 0; i < len(policiesa); i++ { @@ -432,7 +450,7 @@ func (s *AgentService) GetAgents(c *gin.Context) { name := policiesa[i].Info.Name if err = policiesa[i].Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating policy data '%d' '%s'", id, name) - utils.HTTPError(c, srverrors.ErrGetAgentsInvalidAgentModuleData, err) + response.Error(c, response.ErrGetAgentsInvalidAgentModuleData, err) return } for idx := range gpss { @@ -483,7 +501,7 @@ func (s *AgentService) GetAgents(c *gin.Context) { details.Consistency, details.Dependencies = getAgentConsistency(details.Modules, agent) } - utils.HTTPSuccess(c, http.StatusOK, resp) + response.Success(c, http.StatusOK, resp) } // PatchAgents is a function to update agents public info only by action @@ -500,22 +518,23 @@ func (s *AgentService) GetAgents(c *gin.Context) { func (s *AgentService) PatchAgents(c *gin.Context) { var ( action AgentsAction - query utils.TableQuery resp agentsActionResult - uafArr = []utils.UserActionFields{ - { - Domain: "agent", - ObjectType: "agent", - ActionCode: "undefined action", - ObjectDisplayName: utils.UnknownObjectDisplayName, - }, - } ) + tStart := time.Now() + + uaf := useraction.NewFields(c, "agent", "agent", "undefined action", "", useraction.UnknownObjectDisplayName) + uafArr := []useraction.Fields{uaf} + defer func() { + for i := range uafArr { + s.userActionWriter.WriteUserAction(uafArr[i]) + } + }() + if err := c.ShouldBindBodyWith(&action, binding.JSON); err != nil { utils.FromContext(c).WithError(err).Errorf("error binding JSON") - utils.HTTPErrorWithUAFieldsSlice(c, srverrors.ErrPatchAgentsInvalidAction, err, uafArr) + response.Error(c, response.ErrPatchAgentsInvalidAction, err) return } uafArr[0].ActionCode = getActionCode(action.Action) @@ -523,13 +542,13 @@ func (s *AgentService) PatchAgents(c *gin.Context) { serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } @@ -541,11 +560,11 @@ func (s *AgentService) PatchAgents(c *gin.Context) { var agents []models.Agent if err = iDB.Scopes(scope).Model(&models.Agent{}).Count(&resp.Total).Find(&agents).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error collecting agents by filter") - utils.HTTPErrorWithUAFieldsSlice(c, srverrors.ErrPatchAgentsInvalidQuery, err, uafArr) + response.Error(c, response.ErrPatchAgentsInvalidQuery, err) return } - uafArr = fillAgentUserActionFields(agents, getActionCode(action.Action)) + uafArr = fillAgentUserActionFields(c, agents, getActionCode(action.Action), tStart) updateAuthStatus := func(status string) bool { update_fields := map[string]interface{}{ @@ -567,7 +586,7 @@ func (s *AgentService) PatchAgents(c *gin.Context) { }).Error if err != nil { utils.FromContext(c).WithError(err).Errorf("error updating tasks by filter") - utils.HTTPErrorWithUAFieldsSlice(c, srverrors.ErrPatchAgentsUpdateTasksFail, err, uafArr) + response.Error(c, response.ErrPatchAgentsUpdateTasksFail, err) return false } } @@ -575,7 +594,7 @@ func (s *AgentService) PatchAgents(c *gin.Context) { Count(&resp.Total).UpdateColumns(update_fields).Error if err != nil { utils.FromContext(c).WithError(err).Errorf("error updating agents by filter") - utils.HTTPErrorWithUAFieldsSlice(c, srverrors.ErrPatchAgentsUpdateAgentsFail, err, uafArr) + response.Error(c, response.ErrPatchAgentsUpdateAgentsFail, err) return false } return true @@ -586,7 +605,7 @@ func (s *AgentService) PatchAgents(c *gin.Context) { for _, agent := range agents { if err = iDB.Delete(&agent).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error deleting agents by filter") - utils.HTTPErrorWithUAFieldsSlice(c, srverrors.ErrPatchAgentsDeleteAgentsFail, err, uafArr) + response.Error(c, response.ErrPatchAgentsDeleteAgentsFail, err) return } } @@ -608,7 +627,7 @@ func (s *AgentService) PatchAgents(c *gin.Context) { err = iDB.Where("id = ?", action.To).Take(&group).Error if err != nil || group.ID == 0 { utils.FromContext(c).WithError(err).Errorf("error getting agents group") - utils.HTTPErrorWithUAFieldsSlice(c, srverrors.ErrPatchAgentsMoveFail, err, uafArr) + response.Error(c, response.ErrPatchAgentsMoveFail, err) return } } @@ -616,10 +635,10 @@ func (s *AgentService) PatchAgents(c *gin.Context) { for i, v := range agents { agentIds[i] = v.ID if v.AuthStatus == "unauthorized" || v.AuthStatus == "blocked" { - uafArr = append(uafArr, utils.UserActionFields{ + uafArr = append(uafArr, useraction.Fields{ Domain: "agent", ObjectType: "agent", - ObjectId: v.Hash, + ObjectID: v.Hash, ObjectDisplayName: v.Description, ActionCode: "authorization", }) @@ -629,7 +648,7 @@ func (s *AgentService) PatchAgents(c *gin.Context) { Delete(&models.Event{}).Error if err != nil { utils.FromContext(c).WithError(err).Errorf("error deleting agents on moving") - utils.HTTPErrorWithUAFieldsSlice(c, srverrors.ErrPatchAgentsMoveFail, err, uafArr) + response.Error(c, response.ErrPatchAgentsMoveFail, err) return } update_fields := map[string]interface{}{ @@ -641,12 +660,12 @@ func (s *AgentService) PatchAgents(c *gin.Context) { UpdateColumns(update_fields).Error if err != nil { utils.FromContext(c).WithError(err).Errorf("error updating agents on moving") - utils.HTTPErrorWithUAFieldsSlice(c, srverrors.ErrPatchAgentsMoveFail, err, uafArr) + response.Error(c, response.ErrPatchAgentsMoveFail, err) return } } - utils.HTTPSuccessWithUAFieldsSlice(c, http.StatusOK, resp, uafArr) + response.Success(c, http.StatusOK, resp) } // GetAgent is a function to return agent info and details view @@ -671,34 +690,34 @@ func (s *AgentService) GetAgent(c *gin.Context) { serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } if err = iDB.Take(&resp.Agent, "hash = ?", hash).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding agent by hash") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPError(c, srverrors.ErrAgentsNotFound, err) + response.Error(c, response.ErrAgentsNotFound, err) } else { - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) } return } else if err = resp.Agent.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating agent data '%s'", resp.Agent.Hash) - utils.HTTPError(c, srverrors.ErrAgentsInvalidData, err) + response.Error(c, response.ErrAgentsInvalidData, err) return } sqlQuery := sqlAgentDetails + ` WHERE a.hash = ? AND a.deleted_at IS NULL` if err = iDB.Raw(sqlQuery, hash).Scan(&resp.Details).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error loading details by agent hash '%s'", hash) - utils.HTTPError(c, srverrors.ErrGetAgentDetailsNotFound, err) + response.Error(c, response.ErrGetAgentDetailsNotFound, err) return } @@ -716,14 +735,14 @@ func (s *AgentService) GetAgent(c *gin.Context) { if err = iDB.Take(&group, "id = ?", resp.Agent.GroupID).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding group by id") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPError(c, srverrors.ErrGetAgentGroupNotFound, err) + response.Error(c, response.ErrGetAgentGroupNotFound, err) } else { - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) } return } else if err = group.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating group data '%s'", group.Hash) - utils.HTTPError(c, srverrors.ErrGetAgentInvalidGroupData, err) + response.Error(c, response.ErrGetAgentInvalidGroupData, err) return } resp.Details.Group = &group @@ -735,7 +754,7 @@ func (s *AgentService) GetAgent(c *gin.Context) { Find(&resp.Details.Modules, "gtp.group_id = ? AND status = 'joined'", resp.Agent.GroupID).Error if err != nil { utils.FromContext(c).WithError(err).Errorf("error finding group modules by group ID '%d'", resp.Agent.GroupID) - utils.HTTPError(c, srverrors.ErrGetAgentGroupModulesNotFound, err) + response.Error(c, response.ErrGetAgentGroupModulesNotFound, err) return } else { for i := 0; i < len(resp.Details.Modules); i++ { @@ -743,7 +762,7 @@ func (s *AgentService) GetAgent(c *gin.Context) { id := resp.Details.Modules[i].ID name := resp.Details.Modules[i].Info.Name utils.FromContext(c).WithError(err).Errorf("error validating group module data '%d' '%s'", id, name) - utils.HTTPError(c, srverrors.ErrGetAgentInvalidAgentModuleData, err) + response.Error(c, response.ErrGetAgentInvalidAgentModuleData, err) return } } @@ -755,13 +774,13 @@ func (s *AgentService) GetAgent(c *gin.Context) { } if err = iDB.Model(gps).Association("policies").Find(&gps.Policies).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding group policies by group model") - utils.HTTPError(c, srverrors.ErrGetAgentPoliciesNotFound, err) + response.Error(c, response.ErrGetAgentPoliciesNotFound, err) return } resp.Details.Policies = gps.Policies } - utils.HTTPSuccess(c, http.StatusOK, resp) + response.Success(c, http.StatusOK, resp) } // PatchAgent is a function to update agent public info only @@ -778,33 +797,26 @@ func (s *AgentService) GetAgent(c *gin.Context) { // @Failure 500 {object} utils.errorResp "internal error on updating agent" // @Router /agents/{hash} [put] func (s *AgentService) PatchAgent(c *gin.Context) { - var ( - action patchAgentAction - count int64 - err error - hash = c.Param("hash") - ) - uaf := utils.UserActionFields{ - Domain: "agent", - ObjectType: "agent", - ActionCode: "undefined action", - ObjectDisplayName: utils.UnknownObjectDisplayName, - } + uaf := useraction.NewFields(c, "agent", "agent", "undefined action", "", useraction.UnknownObjectDisplayName) + defer s.userActionWriter.WriteUserAction(uaf) + + hash := c.Param("hash") serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } - if err = c.ShouldBindJSON(&action); err != nil || action.Agent.Valid() != nil { + var action patchAgentAction + if err := c.ShouldBindJSON(&action); err != nil || action.Agent.Valid() != nil { if err == nil { err = action.Agent.Valid() } @@ -813,22 +825,23 @@ func (s *AgentService) PatchAgent(c *gin.Context) { uaf.ObjectDisplayName = name } utils.FromContext(c).WithError(err).Errorf("error binding JSON") - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchAgentValidationError, err, uaf) + response.Error(c, response.ErrPatchAgentValidationError, err) return } uaf.ActionCode = getActionCode(action.Action) - uaf.ObjectId = hash + uaf.ObjectID = hash uaf.ObjectDisplayName = action.Agent.Description if hash != action.Agent.Hash { utils.FromContext(c).WithError(nil).Errorf("mismatch agent hash to requested one") - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchAgentValidationError, nil, uaf) + response.Error(c, response.ErrPatchAgentValidationError, nil) return } + var count int64 if err = iDB.Model(&action.Agent).Count(&count).Error; err != nil || count == 0 { utils.FromContext(c).WithError(nil).Errorf("error updating agent by hash '%s', agent not found", hash) - utils.HTTPErrorWithUAFields(c, srverrors.ErrAgentsNotFound, err, uaf) + response.Error(c, response.ErrAgentsNotFound, err) return } @@ -843,7 +856,7 @@ func (s *AgentService) PatchAgent(c *gin.Context) { }).Error if err != nil { utils.FromContext(c).WithError(err).Errorf("error updating tasks by agent") - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchAgentTaskUpdateFail, err, uaf) + response.Error(c, response.ErrPatchAgentTaskUpdateFail, err) return } } @@ -853,15 +866,15 @@ func (s *AgentService) PatchAgent(c *gin.Context) { if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { utils.FromContext(c).WithError(nil).Errorf("error updating agent by hash '%s', agent not found", hash) - utils.HTTPErrorWithUAFields(c, srverrors.ErrAgentsNotFound, err, uaf) + response.Error(c, response.ErrAgentsNotFound, err) return } else if err != nil { utils.FromContext(c).WithError(err).Errorf("error updating agent by hash '%s'", hash) - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } - utils.HTTPSuccessWithUAFields(c, http.StatusOK, action.Agent, uaf) + response.Success(c, http.StatusOK, action.Agent) } // CreateAgent is a function to create new agent @@ -876,18 +889,15 @@ func (s *AgentService) PatchAgent(c *gin.Context) { // @Failure 500 {object} utils.errorResp "internal error on creating agent" // @Router /agents/ [post] func (s *AgentService) CreateAgent(c *gin.Context) { + uaf := useraction.NewFields(c, "agent", "agent", "creation", "", useraction.UnknownObjectDisplayName) + defer s.userActionWriter.WriteUserAction(uaf) + logger := utils.FromContext(c) - uaf := utils.UserActionFields{ - Domain: "agent", - ObjectType: "agent", - ActionCode: "creation", - ObjectDisplayName: utils.UnknownObjectDisplayName, - } var info agentInfo if err := c.ShouldBindJSON(&info); err != nil { logger.WithError(err).Errorf("error binding JSON") - utils.HTTPErrorWithUAFields(c, srverrors.ErrCreateAgentValidationError, err, uaf) + response.Error(c, response.ErrCreateAgentValidationError, err) return } uaf.ObjectDisplayName = info.Name @@ -895,13 +905,13 @@ func (s *AgentService) CreateAgent(c *gin.Context) { serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } @@ -934,15 +944,15 @@ func (s *AgentService) CreateAgent(c *gin.Context) { }, }, } - uaf.ObjectId = newAgent.Hash + uaf.ObjectID = newAgent.Hash if err = iDB.Create(&newAgent).Error; err != nil { logger.WithError(err).Errorf("error creating agent") - utils.HTTPErrorWithUAFields(c, srverrors.ErrCreateAgentCreateError, err, uaf) + response.Error(c, response.ErrCreateAgentCreateError, err) return } - utils.HTTPSuccessWithUAFields(c, http.StatusCreated, newAgent, uaf) + response.Success(c, http.StatusCreated, newAgent) } // DeleteAgent is a function to cascade delete agent @@ -958,52 +968,47 @@ func (s *AgentService) CreateAgent(c *gin.Context) { func (s *AgentService) DeleteAgent(c *gin.Context) { var ( agent models.Agent - - hash = c.Param("hash") + hash = c.Param("hash") ) - uaf := utils.UserActionFields{ - Domain: "agent", - ObjectType: "agent", - ActionCode: "deletion", - ObjectId: hash, - ObjectDisplayName: utils.UnknownObjectDisplayName, - } + + uaf := useraction.NewFields(c, "agent", "agent", "deletion", "", useraction.UnknownObjectDisplayName) + defer s.userActionWriter.WriteUserAction(uaf) serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } if err = iDB.Take(&agent, "hash = ?", hash).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding agent by hash") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPErrorWithUAFields(c, srverrors.ErrAgentsNotFound, err, uaf) + response.Error(c, response.ErrAgentsNotFound, err) } else { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) } return } else if err = agent.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating agent data '%s'", agent.Hash) - utils.HTTPErrorWithUAFields(c, srverrors.ErrAgentsInvalidData, err, uaf) + response.Error(c, response.ErrAgentsInvalidData, err) return } uaf.ObjectDisplayName = agent.Description if err = iDB.Delete(&agent).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error deleting agent by hash '%s'", hash) - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } - utils.HTTPSuccessWithUAFields(c, http.StatusOK, struct{}{}, uaf) + response.Success(c, http.StatusOK, struct{}{}) } // GetAgentsCount is a function to return groups of counted agents @@ -1014,26 +1019,24 @@ func (s *AgentService) DeleteAgent(c *gin.Context) { // @Failure 500 {object} utils.errorResp "internal error" // @Router /agents/count [get] func (s *AgentService) GetAgentsCount(c *gin.Context) { - var resp agentCount - - logger := utils.FromContext(c) - uaf := utils.UserActionFields{ + uaf := useraction.Fields{ Domain: "agent", ObjectType: "agent", - ActionCode: getActionCode("count"), - ObjectDisplayName: utils.UnknownObjectDisplayName, + ActionCode: "counting", + ObjectDisplayName: useraction.UnknownObjectDisplayName, } + defer s.userActionWriter.WriteUserAction(uaf) serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } @@ -1046,14 +1049,16 @@ func (s *AgentService) GetAgentsCount(c *gin.Context) { SUM(group_id = 0 AND auth_status = 'authorized') AS 'without_groups' FROM agents WHERE deleted_at IS NULL` + + var resp agentCount err = iDB.Raw(q). Scan(&resp). Error if err != nil { - logger.WithError(err).Errorf("could not count agents") - utils.HTTPError(c, srverrors.ErrInternal, err) + utils.FromContext(c).WithError(err).Errorf("could not count agents") + response.Error(c, response.ErrInternal, err) return } - utils.HTTPSuccessWithUAFields(c, http.StatusOK, resp, uaf) + response.Success(c, http.StatusOK, resp) } diff --git a/pkg/app/api/server/private/binaries.go b/pkg/app/api/server/private/binaries.go index 2a8cf310..407b7d47 100644 --- a/pkg/app/api/server/private/binaries.go +++ b/pkg/app/api/server/private/binaries.go @@ -12,7 +12,8 @@ import ( "soldr/pkg/app/api/models" srvcontext "soldr/pkg/app/api/server/context" - srverrors "soldr/pkg/app/api/server/response" + "soldr/pkg/app/api/server/response" + useraction "soldr/pkg/app/api/user_action" "soldr/pkg/app/api/utils" "soldr/pkg/storage" ) @@ -41,12 +42,17 @@ var binariesSQLMappers = map[string]interface{}{ } type BinariesService struct { - db *gorm.DB + db *gorm.DB + userActionWriter useraction.Writer } -func NewBinariesService(db *gorm.DB) *BinariesService { +func NewBinariesService( + db *gorm.DB, + userActionWriter useraction.Writer, +) *BinariesService { return &BinariesService{ - db: db, + db: db, + userActionWriter: userActionWriter, } } @@ -97,7 +103,7 @@ func (s *BinariesService) GetAgentBinaries(c *gin.Context) { if err = c.ShouldBindQuery(&query); err != nil { utils.FromContext(c).WithError(err).Errorf("error binding query") - utils.HTTPError(c, srverrors.ErrAgentBinariesInvalidRequest, err) + response.Error(c, response.ErrAgentBinariesInvalidRequest, err) return } @@ -116,19 +122,19 @@ func (s *BinariesService) GetAgentBinaries(c *gin.Context) { if resp.Total, err = query.Query(s.db, &resp.Binaries); err != nil { utils.FromContext(c).WithError(err).Errorf("error finding agent binaries") - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) return } for i := 0; i < len(resp.Binaries); i++ { if err = resp.Binaries[i].Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating agent binaries data '%s'", resp.Binaries[i].Hash) - utils.HTTPError(c, srverrors.ErrAgentBinariesInvalidData, err) + response.Error(c, response.ErrAgentBinariesInvalidData, err) return } } - utils.HTTPSuccess(c, http.StatusOK, resp) + response.Success(c, http.StatusOK, resp) } // GetAgentBinaryFile is a function to return agent binary file @@ -159,11 +165,8 @@ func (s *BinariesService) GetAgentBinaryFile(c *gin.Context) { s3 storage.IStorage validate = validator.New() ) - uaf := utils.UserActionFields{ - Domain: "agent", - ObjectType: "distribution", - ActionCode: "downloading", - } + uaf := useraction.NewFields(c, "agent", "distribution", "downloading", "", useraction.UnknownObjectDisplayName) + defer s.userActionWriter.WriteUserAction(uaf) resultName = fmt.Sprintf("%s_%s_%s", agentName, agentOS, agentArch) if agentOS == "windows" { @@ -173,15 +176,15 @@ func (s *BinariesService) GetAgentBinaryFile(c *gin.Context) { uaf.ObjectDisplayName = resultName if err := validate.Var(agentOS, "oneof=windows linux darwin,required"); err != nil { - utils.HTTPErrorWithUAFields(c, srverrors.ErrAgentBinaryFileInvalidOS, err, uaf) + response.Error(c, response.ErrAgentBinaryFileInvalidOS, err) return } if err := validate.Var(agentArch, "oneof=386 amd64,required"); err != nil { - utils.HTTPErrorWithUAFields(c, srverrors.ErrAgentBinaryFileInvalidArch, err, uaf) + response.Error(c, response.ErrAgentBinaryFileInvalidArch, err) return } if err := validate.Var(agentVersion, "max=25,required"); err != nil { - utils.HTTPErrorWithUAFields(c, srverrors.ErrAgentBinaryFileInvalidArch, err, uaf) + response.Error(c, response.ErrAgentBinaryFileInvalidArch, err) return } @@ -198,42 +201,42 @@ func (s *BinariesService) GetAgentBinaryFile(c *gin.Context) { err = s.db.Scopes(scope).Model(&binary).Take(&binary).Error if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { utils.FromContext(c).WithError(nil).Errorf("error getting binary info by version '%s', record not found", agentVersion) - utils.HTTPErrorWithUAFields(c, srverrors.ErrAgentBinaryFileNotFound, err, uaf) + response.Error(c, response.ErrAgentBinaryFileNotFound, err) return } else if err != nil { utils.FromContext(c).WithError(err).Errorf("error getting binary info by version '%s'", agentVersion) - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } - uaf.ObjectId = binary.Hash + uaf.ObjectID = binary.Hash path := filepath.Join("vxagent", binary.Version, agentOS, agentArch, agentName) if chksums, ok = binary.Info.Chksums[path]; !ok { utils.FromContext(c).WithError(nil).Errorf("error getting agent binary file check sums: '%s' not found", path) - utils.HTTPErrorWithUAFields(c, srverrors.ErrAgentBinaryFileNotFound, nil, uaf) + response.Error(c, response.ErrAgentBinaryFileNotFound, nil) return } if s3, err = storage.NewS3(nil); err != nil { utils.FromContext(c).WithError(err).Errorf("error openning connection to S3") - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } if data, err = s3.ReadFile(path); err != nil { utils.FromContext(c).WithError(err).Errorf("error reading agent binary file '%s'", path) - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } if err = utils.ValidateBinaryFileByChksums(data, chksums); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating agent binary file by check sums '%s'", path) - utils.HTTPErrorWithUAFields(c, srverrors.ErrAgentBinaryFileCorrupted, err, uaf) + response.Error(c, response.ErrAgentBinaryFileCorrupted, err) return } uaf.Success = true - c.Set("uaf", []utils.UserActionFields{uaf}) + c.Set("uaf", []useraction.Fields{uaf}) c.Writer.Header().Add("Content-Disposition", fmt.Sprintf("attachment; filename=%q", resultName)) c.Data(http.StatusOK, "application/octet-stream", data) } diff --git a/pkg/app/api/server/private/events.go b/pkg/app/api/server/private/events.go index 7930b525..bf3e60ee 100644 --- a/pkg/app/api/server/private/events.go +++ b/pkg/app/api/server/private/events.go @@ -9,7 +9,7 @@ import ( "soldr/pkg/app/api/client" "soldr/pkg/app/api/models" srvcontext "soldr/pkg/app/api/server/context" - srverrors "soldr/pkg/app/api/server/response" + "soldr/pkg/app/api/server/response" "soldr/pkg/app/api/utils" ) @@ -294,40 +294,40 @@ func (s *EventService) GetEvents(c *gin.Context) { if err := c.ShouldBindQuery(&query); err != nil { utils.FromContext(c).WithError(err).Errorf("error binding query") - utils.HTTPError(c, srverrors.ErrEventsInvalidRequest, err) + response.Error(c, response.ErrEventsInvalidRequest, err) return } serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } if err = query.Init("events", eventsSQLMappers); err != nil { utils.FromContext(c).WithError(err).Errorf("error binding query") - utils.HTTPError(c, srverrors.ErrEventsInvalidRequest, err) + response.Error(c, response.ErrEventsInvalidRequest, err) return } emids, epids, err = getModuleIDs(iDB, &query) if err != nil { utils.FromContext(c).WithError(err).Errorf("error getting modules list by filter") - utils.HTTPError(c, srverrors.ErrEventsInvalidQuery, err) + response.Error(c, response.ErrEventsInvalidQuery, err) return } eaids, err = getAgentIDs(iDB, &query, epids) if err != nil { utils.FromContext(c).WithError(err).Errorf("error getting agents list by filter") - utils.HTTPError(c, srverrors.ErrEventsInvalidQuery, err) + response.Error(c, response.ErrEventsInvalidQuery, err) return } @@ -342,7 +342,7 @@ func (s *EventService) GetEvents(c *gin.Context) { copyEventsSQLMappers["policy_id"] = "`modules`.policy_id" if err = query.Init("events", copyEventsSQLMappers); err != nil { utils.FromContext(c).WithError(err).Errorf("error binding query") - utils.HTTPError(c, srverrors.ErrEventsInvalidRequest, err) + response.Error(c, response.ErrEventsInvalidRequest, err) return } @@ -356,16 +356,16 @@ func (s *EventService) GetEvents(c *gin.Context) { if query.Group == "" { if err = doQuery(iDB, &query, &resp, funcs); err != nil { utils.FromContext(c).WithError(err).Errorf("error finding events") - utils.HTTPError(c, srverrors.ErrEventsInvalidQuery, err) + response.Error(c, response.ErrEventsInvalidQuery, err) return } } else { if groupedResp.Total, err = query.QueryGrouped(iDB, &groupedResp.Grouped, funcs...); err != nil { utils.FromContext(c).WithError(err).Errorf("error finding grouped events") - utils.HTTPError(c, srverrors.ErrEventsInvalidQuery, err) + response.Error(c, response.ErrEventsInvalidQuery, err) return } - utils.HTTPSuccess(c, http.StatusOK, groupedResp) + response.Success(c, http.StatusOK, groupedResp) return } @@ -374,20 +374,20 @@ func (s *EventService) GetEvents(c *gin.Context) { mids = append(mids, resp.Events[i].ModuleID) if resp.Events[i].Valid() != nil { utils.FromContext(c).WithError(err).Errorf("error validating event data") - utils.HTTPError(c, srverrors.ErrEventsInvalidData, err) + response.Error(c, response.ErrEventsInvalidData, err) return } } aids = utils.UniqueUint64InSlice(aids) if err = iDB.Where("id IN (?)", aids).Find(&resp.Agents).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding linked agents") - utils.HTTPError(c, srverrors.ErrEventsInvalidQuery, err) + response.Error(c, response.ErrEventsInvalidQuery, err) return } mids = utils.UniqueUint64InSlice(mids) if err = iDB.Where("id IN (?)", mids).Find(&resp.Modules).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding linked modules") - utils.HTTPError(c, srverrors.ErrEventsInvalidQuery, err) + response.Error(c, response.ErrEventsInvalidQuery, err) return } @@ -397,7 +397,7 @@ func (s *EventService) GetEvents(c *gin.Context) { gids = utils.UniqueUint64InSlice(gids) if err = iDB.Where("id IN (?)", gids).Find(&resp.Groups).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding linked gloups") - utils.HTTPError(c, srverrors.ErrEventsInvalidQuery, err) + response.Error(c, response.ErrEventsInvalidQuery, err) return } @@ -407,9 +407,9 @@ func (s *EventService) GetEvents(c *gin.Context) { pids = utils.UniqueUint64InSlice(pids) if err = iDB.Where("id IN (?)", pids).Find(&resp.Policies).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding linked policies") - utils.HTTPError(c, srverrors.ErrEventsInvalidQuery, err) + response.Error(c, response.ErrEventsInvalidQuery, err) return } - utils.HTTPSuccess(c, http.StatusOK, resp) + response.Success(c, http.StatusOK, resp) } diff --git a/pkg/app/api/server/private/groups.go b/pkg/app/api/server/private/groups.go index 1810cd17..52c74e75 100644 --- a/pkg/app/api/server/private/groups.go +++ b/pkg/app/api/server/private/groups.go @@ -11,7 +11,8 @@ import ( "soldr/pkg/app/api/client" "soldr/pkg/app/api/models" srvcontext "soldr/pkg/app/api/server/context" - srverrors "soldr/pkg/app/api/server/response" + "soldr/pkg/app/api/server/response" + useraction "soldr/pkg/app/api/user_action" "soldr/pkg/app/api/utils" ) @@ -108,12 +109,12 @@ func getGroupConsistency(modules []models.ModuleAShort) (bool, []models.GroupDep return rdeps, gdeps } -func makeGroupPolicyAction(act string, iDB *gorm.DB, g models.Group, p models.Policy) (*srverrors.HttpError, error) { +func makeGroupPolicyAction(act string, iDB *gorm.DB, g models.Group, p models.Policy) (*response.HttpError, error) { gps := models.GroupPolicies{ Group: g, } if err := iDB.Model(gps).Association("policies").Find(&gps.Policies).Error; err != nil { - return srverrors.ErrGroupPolicyPoliciesNotFound, err + return response.ErrGroupPolicyPoliciesNotFound, err } isPolicyActive := false @@ -141,20 +142,20 @@ func makeGroupPolicyAction(act string, iDB *gorm.DB, g models.Group, p models.Po Having("cnt > 1"). Find(&cnts) if err := findDupsQuery.Error; err != nil { - return srverrors.ErrGroupPolicyMergeModulesFail, err + return response.ErrGroupPolicyMergeModulesFail, err } if len(cnts) != 0 { - return srverrors.ErrGroupPolicyDuplicateModules, nil + return response.ErrGroupPolicyDuplicateModules, nil } if !isPolicyActive { if err := iDB.Create(&groupToPolicy).Error; err != nil { - return srverrors.ErrGroupPolicyLinkFail, err + return response.ErrGroupPolicyLinkFail, err } return nil, nil } else { - return srverrors.ErrGroupPolicyLinkExists, nil + return response.ErrGroupPolicyLinkExists, nil } case "deactivate": @@ -162,15 +163,15 @@ func makeGroupPolicyAction(act string, iDB *gorm.DB, g models.Group, p models.Po err := iDB.Where("policy_id = ? AND group_id = ?", groupToPolicy.PolicyID, groupToPolicy.GroupID). Delete(&groupToPolicy).Error if err != nil { - return srverrors.ErrGroupPolicyRemoveLink, err + return response.ErrGroupPolicyRemoveLink, err } return nil, nil } else { - return srverrors.ErrGroupPolicyLinkNotFound, nil + return response.ErrGroupPolicyLinkNotFound, nil } default: - return srverrors.ErrGroupPolicyUnkownAction, nil + return response.ErrGroupPolicyUnkownAction, nil } } @@ -183,12 +184,17 @@ func getGroupName(db *gorm.DB, hash string) (string, error) { } type GroupService struct { - serverConnector *client.AgentServerClient + serverConnector *client.AgentServerClient + userActionWriter useraction.Writer } -func NewGroupService(serverConnector *client.AgentServerClient) *GroupService { +func NewGroupService( + serverConnector *client.AgentServerClient, + userActionWriter useraction.Writer, +) *GroupService { return &GroupService{ - serverConnector: serverConnector, + serverConnector: serverConnector, + userActionWriter: userActionWriter, } } @@ -219,26 +225,26 @@ func (s *GroupService) GetGroups(c *gin.Context) { if err := c.ShouldBindQuery(&query); err != nil { utils.FromContext(c).WithError(err).Errorf("error binding query") - utils.HTTPError(c, srverrors.ErrGroupsInvalidRequest, err) + response.Error(c, response.ErrGroupsInvalidRequest, err) return } serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } if err = query.Init("groups", groupsSQLMappers); err != nil { utils.FromContext(c).WithError(err).Errorf("error binding query") - utils.HTTPError(c, srverrors.ErrGroupsInvalidRequest, err) + response.Error(c, response.ErrGroupsInvalidRequest, err) return } @@ -287,16 +293,16 @@ func (s *GroupService) GetGroups(c *gin.Context) { if query.Group == "" { if resp.Total, err = query.Query(iDB, &resp.Groups, funcs...); err != nil { utils.FromContext(c).WithError(err).Errorf("error finding groups") - utils.HTTPError(c, srverrors.ErrGroupsInvalidQuery, err) + response.Error(c, response.ErrGroupsInvalidQuery, err) return } } else { if groupedResp.Total, err = query.QueryGrouped(iDB, &groupedResp.Grouped, funcs...); err != nil { utils.FromContext(c).WithError(err).Errorf("error finding grouped groups") - utils.HTTPError(c, srverrors.ErrGetAgentsInvalidQuery, err) + response.Error(c, response.ErrGetAgentsInvalidQuery, err) return } - utils.HTTPSuccess(c, http.StatusOK, groupedResp) + response.Success(c, http.StatusOK, groupedResp) return } @@ -304,7 +310,7 @@ func (s *GroupService) GetGroups(c *gin.Context) { gids = append(gids, resp.Groups[i].ID) if err = resp.Groups[i].Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating group data '%s'", resp.Groups[i].Hash) - utils.HTTPError(c, srverrors.ErrGroupsInvalidData, err) + response.Error(c, response.ErrGroupsInvalidData, err) return } } @@ -312,7 +318,7 @@ func (s *GroupService) GetGroups(c *gin.Context) { sqlQuery := sqlGroupDetails + ` WHERE g.id IN (?) AND g.deleted_at IS NULL` if err = iDB.Raw(sqlQuery, gids).Scan(&resp.Details).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error loading groups details") - utils.HTTPError(c, srverrors.ErrGetGroupsDetailsNotFound, err) + response.Error(c, response.ErrGetGroupsDetailsNotFound, err) return } @@ -323,7 +329,7 @@ func (s *GroupService) GetGroups(c *gin.Context) { Find(&modulesa, "gtp.group_id IN (?) AND status = 'joined'", gids).Error if err != nil { utils.FromContext(c).WithError(err).Errorf("error finding policy modules") - utils.HTTPError(c, srverrors.ErrGetGroupsModulesNotFound, err) + response.Error(c, response.ErrGetGroupsModulesNotFound, err) return } else { for i := 0; i < len(modulesa); i++ { @@ -332,7 +338,7 @@ func (s *GroupService) GetGroups(c *gin.Context) { policy_id := modulesa[i].PolicyID if err = modulesa[i].Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating policy module data '%d' '%s'", id, name) - utils.HTTPError(c, srverrors.ErrGetGroupsInvalidModuleData, err) + response.Error(c, response.ErrGetGroupsInvalidModuleData, err) return } if mods, ok := modsToPolicies[policy_id]; ok { @@ -345,7 +351,7 @@ func (s *GroupService) GetGroups(c *gin.Context) { if err = iDB.Find(&gpss, "group_id IN (?)", gids).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding policy to groups links") - utils.HTTPError(c, srverrors.ErrGroupPolicyGroupsNotFound, err) + response.Error(c, response.ErrGroupPolicyGroupsNotFound, err) return } @@ -356,7 +362,7 @@ func (s *GroupService) GetGroups(c *gin.Context) { Find(&policiesa).Error if err != nil { utils.FromContext(c).WithError(err).Errorf("error finding group policies") - utils.HTTPError(c, srverrors.ErrGroupPolicyPoliciesNotFound, err) + response.Error(c, response.ErrGroupPolicyPoliciesNotFound, err) return } else { for i := 0; i < len(policiesa); i++ { @@ -364,7 +370,7 @@ func (s *GroupService) GetGroups(c *gin.Context) { name := policiesa[i].Info.Name if err = policiesa[i].Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating policy data '%d' '%s'", id, name) - utils.HTTPError(c, srverrors.ErrGetGroupsInvalidModuleData, err) + response.Error(c, response.ErrGetGroupsInvalidModuleData, err) return } for idx := range gpss { @@ -405,7 +411,7 @@ func (s *GroupService) GetGroups(c *gin.Context) { details.Consistency, details.Dependencies = getGroupConsistency(details.Modules) } - utils.HTTPSuccess(c, http.StatusOK, resp) + response.Success(c, http.StatusOK, resp) } // GetGroup is a function to return group info and details view @@ -427,34 +433,34 @@ func (s *GroupService) GetGroup(c *gin.Context) { serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } if err = iDB.Take(&resp.Group, "hash = ?", hash).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding group by hash") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPError(c, srverrors.ErrGroupsNotFound, err) + response.Error(c, response.ErrGroupsNotFound, err) } else { - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) } return } else if err = resp.Group.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating group data '%s'", resp.Group.Hash) - utils.HTTPError(c, srverrors.ErrGroupsInvalidData, err) + response.Error(c, response.ErrGroupsInvalidData, err) return } sqlQuery := sqlGroupDetails + ` WHERE g.hash = ? AND g.deleted_at IS NULL` if err = iDB.Raw(sqlQuery, hash).Scan(&resp.Details).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error loading details by group hash '%s'", hash) - utils.HTTPError(c, srverrors.ErrGetGroupDetailsNotFound, err) + response.Error(c, response.ErrGetGroupDetailsNotFound, err) return } @@ -464,7 +470,7 @@ func (s *GroupService) GetGroup(c *gin.Context) { Find(&resp.Details.Modules, "gtp.group_id = ? AND status = 'joined'", resp.Group.ID).Error if err != nil { utils.FromContext(c).WithError(err).Errorf("error finding group modules by group ID '%d'", resp.Group.ID) - utils.HTTPError(c, srverrors.ErrGetGroupModulesNotFound, err) + response.Error(c, response.ErrGetGroupModulesNotFound, err) return } else { for i := 0; i < len(resp.Details.Modules); i++ { @@ -472,7 +478,7 @@ func (s *GroupService) GetGroup(c *gin.Context) { id := resp.Details.Modules[i].ID name := resp.Details.Modules[i].Info.Name utils.FromContext(c).WithError(err).Errorf("error validating group module data '%d' '%s'", id, name) - utils.HTTPError(c, srverrors.ErrGetGroupsInvalidModuleData, err) + response.Error(c, response.ErrGetGroupsInvalidModuleData, err) return } } @@ -484,12 +490,12 @@ func (s *GroupService) GetGroup(c *gin.Context) { } if err = iDB.Model(gps).Association("policies").Find(&gps.Policies).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding group policies by group model") - utils.HTTPError(c, srverrors.ErrGetGroupsPoliciesNotFound, err) + response.Error(c, response.ErrGetGroupsPoliciesNotFound, err) return } resp.Details.Policies = gps.Policies - utils.HTTPSuccess(c, http.StatusOK, resp) + response.Success(c, http.StatusOK, resp) } // PatchGroup is a function to update group public info only @@ -511,24 +517,20 @@ func (s *GroupService) PatchGroup(c *gin.Context) { group models.Group hash = c.Param("hash") ) - uaf := utils.UserActionFields{ - Domain: "group", - ObjectType: "group", - ActionCode: "editing", - ObjectId: hash, - ObjectDisplayName: utils.UnknownObjectDisplayName, - } + + uaf := useraction.NewFields(c, "group", "group", "editing", hash, useraction.UnknownObjectDisplayName) + defer s.userActionWriter.WriteUserAction(uaf) serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } @@ -541,7 +543,7 @@ func (s *GroupService) PatchGroup(c *gin.Context) { uaf.ObjectDisplayName = name } utils.FromContext(c).WithError(err).Errorf("error binding JSON") - utils.HTTPErrorWithUAFields(c, srverrors.ErrGroupsValidationFail, err, uaf) + response.Error(c, response.ErrGroupsValidationFail, err) return } @@ -549,13 +551,13 @@ func (s *GroupService) PatchGroup(c *gin.Context) { if hash != group.Hash { utils.FromContext(c).WithError(nil).Errorf("mismatch group hash to requested one") - utils.HTTPErrorWithUAFields(c, srverrors.ErrGroupsValidationFail, nil, uaf) + response.Error(c, response.ErrGroupsValidationFail, nil) return } if err = iDB.Model(&group).Count(&count).Error; err != nil || count == 0 { utils.FromContext(c).WithError(nil).Errorf("error updating group by hash '%s', group not found", hash) - utils.HTTPErrorWithUAFields(c, srverrors.ErrGroupsNotFound, err, uaf) + response.Error(c, response.ErrGroupsNotFound, err) return } @@ -564,15 +566,15 @@ func (s *GroupService) PatchGroup(c *gin.Context) { if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { utils.FromContext(c).WithError(nil).Errorf("error updating group by hash '%s', group not found", hash) - utils.HTTPErrorWithUAFields(c, srverrors.ErrGroupsNotFound, err, uaf) + response.Error(c, response.ErrGroupsNotFound, err) return } else if err != nil { utils.FromContext(c).WithError(err).Errorf("error updating group by hash '%s'", hash) - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } - utils.HTTPSuccessWithUAFields(c, http.StatusOK, group, uaf) + response.Success(c, http.StatusOK, group) } // PatchGroupPolicy is a function to update group policy linking @@ -595,16 +597,13 @@ func (s *GroupService) PatchGroupPolicy(c *gin.Context) { hash = c.Param("hash") policy models.Policy ) - uaf := utils.UserActionFields{ - Domain: "policy", - ObjectType: "policy", - ActionCode: "undefined action", - ObjectDisplayName: utils.UnknownObjectDisplayName, - } + + uaf := useraction.NewFields(c, "policy", "policy", "undefined action", "", useraction.UnknownObjectDisplayName) + defer s.userActionWriter.WriteUserAction(uaf) if err := c.ShouldBindJSON(&form); err != nil { utils.FromContext(c).WithError(err).Errorf("error binding JSON") - utils.HTTPErrorWithUAFields(c, srverrors.ErrGroupsInvalidRequest, err, uaf) + response.Error(c, response.ErrGroupsInvalidRequest, err) return } @@ -613,57 +612,57 @@ func (s *GroupService) PatchGroupPolicy(c *gin.Context) { } else { uaf.ActionCode = "deletion of the connection with the group" } - uaf.ObjectId = form.Policy.Hash + uaf.ObjectID = form.Policy.Hash uaf.ObjectDisplayName = form.Policy.Info.Name.En serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } if err = iDB.Take(&group, "hash = ?", hash).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding group by hash") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPErrorWithUAFields(c, srverrors.ErrGroupsNotFound, err, uaf) + response.Error(c, response.ErrGroupsNotFound, err) } else { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) } return } else if err = group.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating group data '%s'", group.Hash) - utils.HTTPErrorWithUAFields(c, srverrors.ErrGroupsInvalidData, err, uaf) + response.Error(c, response.ErrGroupsInvalidData, err) return } if err = iDB.Take(&policy, "hash = ?", form.Policy.Hash).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding policy by hash") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPErrorWithUAFields(c, srverrors.ErrGetGroupsPoliciesNotFound, err, uaf) + response.Error(c, response.ErrGetGroupsPoliciesNotFound, err) } else { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) } return } else if err = policy.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating policy data '%s'", policy.Hash) - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } httpErr, err := makeGroupPolicyAction(form.Action, iDB, group, policy) if httpErr != nil { utils.FromContext(c).WithError(err).Errorf("error patching group policy by action: %s", httpErr.Error()) - utils.HTTPErrorWithUAFields(c, httpErr, err, uaf) + response.Error(c, httpErr, err) } - utils.HTTPSuccessWithUAFields(c, http.StatusOK, struct{}{}, uaf) + response.Success(c, http.StatusOK, struct{}{}) } // CreateGroup is a function to create new group @@ -682,16 +681,13 @@ func (s *GroupService) CreateGroup(c *gin.Context) { groupFrom models.Group info groupInfo ) - uaf := utils.UserActionFields{ - Domain: "group", - ObjectType: "group", - ActionCode: "creation", - ObjectDisplayName: utils.UnknownObjectDisplayName, - } + + uaf := useraction.NewFields(c, "group", "group", "creation", "", useraction.UnknownObjectDisplayName) + defer s.userActionWriter.WriteUserAction(uaf) if err := c.ShouldBindJSON(&info); err != nil { utils.FromContext(c).WithError(err).Errorf("error binding JSON") - utils.HTTPErrorWithUAFields(c, srverrors.ErrEventsInvalidRequest, err, uaf) + response.Error(c, response.ErrEventsInvalidRequest, err) return } uaf.ObjectDisplayName = info.Name @@ -699,13 +695,13 @@ func (s *GroupService) CreateGroup(c *gin.Context) { serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } @@ -720,16 +716,16 @@ func (s *GroupService) CreateGroup(c *gin.Context) { System: false, }, } - uaf.ObjectId = group.Hash + uaf.ObjectID = group.Hash if info.From != 0 { if err = iDB.Take(&groupFrom, "id = ?", info.From).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding source group by ID") - utils.HTTPErrorWithUAFields(c, srverrors.ErrCreateGroupSourceNotFound, err, uaf) + response.Error(c, response.ErrCreateGroupSourceNotFound, err) return } else if err = groupFrom.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating group data '%s'", groupFrom.Hash) - utils.HTTPErrorWithUAFields(c, srverrors.ErrGetAgentInvalidGroupData, err, uaf) + response.Error(c, response.ErrGetAgentInvalidGroupData, err) return } @@ -754,7 +750,7 @@ func (s *GroupService) CreateGroup(c *gin.Context) { if err = iDB.Create(&group).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error creating group") - utils.HTTPErrorWithUAFields(c, srverrors.ErrCreateGroupCreateFail, err, uaf) + response.Error(c, response.ErrCreateGroupCreateFail, err) return } @@ -763,7 +759,7 @@ func (s *GroupService) CreateGroup(c *gin.Context) { err = iDB.Where("group_id = ?", groupFrom.ID).Find(&groupToPolicy).Error if err != nil { utils.FromContext(c).WithError(err).Errorf("error finding group policies by group ID") - utils.HTTPErrorWithUAFields(c, srverrors.ErrCreateGroupGetPolicies, err, uaf) + response.Error(c, response.ErrCreateGroupGetPolicies, err) return } for _, gpt := range groupToPolicy { @@ -771,13 +767,13 @@ func (s *GroupService) CreateGroup(c *gin.Context) { gpt.GroupID = group.ID if err = iDB.Create(&gpt).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error creating group policies") - utils.HTTPErrorWithUAFields(c, srverrors.ErrCreateGroupCreatePolicies, err, uaf) + response.Error(c, response.ErrCreateGroupCreatePolicies, err) return } } } - utils.HTTPSuccessWithUAFields(c, http.StatusCreated, group, uaf) + response.Success(c, http.StatusCreated, group) } // DeleteGroup is a function to cascade delete group @@ -795,38 +791,34 @@ func (s *GroupService) DeleteGroup(c *gin.Context) { group models.Group hash = c.Param("hash") ) - uaf := utils.UserActionFields{ - Domain: "group", - ObjectType: "group", - ActionCode: "deletion", - ObjectId: hash, - ObjectDisplayName: utils.UnknownObjectDisplayName, - } + + uaf := useraction.NewFields(c, "group", "group", "deletion", hash, useraction.UnknownObjectDisplayName) + defer s.userActionWriter.WriteUserAction(uaf) serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } if err = iDB.Take(&group, "hash = ?", hash).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding group by hash") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPErrorWithUAFields(c, srverrors.ErrGroupsNotFound, err, uaf) + response.Error(c, response.ErrGroupsNotFound, err) } else { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) } return } else if err = group.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating group data '%s'", group.Hash) - utils.HTTPErrorWithUAFields(c, srverrors.ErrGroupsInvalidData, err, uaf) + response.Error(c, response.ErrGroupsInvalidData, err) return } @@ -834,9 +826,9 @@ func (s *GroupService) DeleteGroup(c *gin.Context) { if err = iDB.Delete(&group).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error deleting group by hash '%s'", hash) - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } - utils.HTTPSuccessWithUAFields(c, http.StatusOK, struct{}{}, uaf) + response.Success(c, http.StatusOK, struct{}{}) } diff --git a/pkg/app/api/server/private/modules.go b/pkg/app/api/server/private/modules.go index 2e025dd2..f1b0530d 100644 --- a/pkg/app/api/server/private/modules.go +++ b/pkg/app/api/server/private/modules.go @@ -24,7 +24,8 @@ import ( "soldr/pkg/app/api/client" "soldr/pkg/app/api/models" srvcontext "soldr/pkg/app/api/server/context" - srverrors "soldr/pkg/app/api/server/response" + "soldr/pkg/app/api/server/response" + useraction "soldr/pkg/app/api/user_action" "soldr/pkg/app/api/utils" "soldr/pkg/crypto" "soldr/pkg/storage" @@ -945,7 +946,7 @@ func updatePolicyModulesByModuleS(c *gin.Context, moduleS *models.ModuleS, sv *m var modules []models.ModuleA scope := func(db *gorm.DB) *gorm.DB { - return db.Where("name LIKE ? AND version LIKE ? AND last_module_update != ?", + return db.Where("name LIKE ? AND version LIKE ? AND last_module_update NOT LIKE ?", moduleS.Info.Name, moduleS.Info.Version.String(), moduleS.LastUpdate) } if err := iDB.Scopes(scope).Find(&modules).Error; err != nil { @@ -1293,14 +1294,20 @@ func getModuleName(c *gin.Context, db *gorm.DB, name string, version string) (st } type ModuleService struct { - db *gorm.DB - serverConnector *client.AgentServerClient + db *gorm.DB + serverConnector *client.AgentServerClient + userActionWriter useraction.Writer } -func NewModuleService(db *gorm.DB, serverConnector *client.AgentServerClient) *ModuleService { +func NewModuleService( + db *gorm.DB, + serverConnector *client.AgentServerClient, + userActionWriter useraction.Writer, +) *ModuleService { return &ModuleService{ - db: db, - serverConnector: serverConnector, + db: db, + serverConnector: serverConnector, + userActionWriter: userActionWriter, } } @@ -1327,25 +1334,25 @@ func (s *ModuleService) GetAgentModules(c *gin.Context) { if err := c.ShouldBindQuery(&query); err != nil { utils.FromContext(c).WithError(err).Errorf("error binding query") - utils.HTTPError(c, srverrors.ErrModulesInvalidRequest, err) + response.Error(c, response.ErrModulesInvalidRequest, err) return } serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } if sv = getService(c); sv == nil { - utils.HTTPError(c, srverrors.ErrInternalServiceNotFound, nil) + response.Error(c, response.ErrInternalServiceNotFound, nil) return } @@ -1353,20 +1360,20 @@ func (s *ModuleService) GetAgentModules(c *gin.Context) { if err = iDB.Take(&agentPolicies, "hash = ?", hash).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding agent by hash") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPError(c, srverrors.ErrGetAgentModulesAgentNotFound, err) + response.Error(c, response.ErrGetAgentModulesAgentNotFound, err) } else { - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) } return } if err = iDB.Model(agentPolicies).Association("policies").Find(&agentPolicies.Policies).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding agent policies by agent model") - utils.HTTPError(c, srverrors.ErrGetAgentModulesAgentPoliciesNotFound, err) + response.Error(c, response.ErrGetAgentModulesAgentPoliciesNotFound, err) return } if err = agentPolicies.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating agent policies data '%s'", agentPolicies.Hash) - utils.HTTPError(c, srverrors.ErrGetAgentModulesInvalidAgentPoliciesData, err) + response.Error(c, response.ErrGetAgentModulesInvalidAgentPoliciesData, err) return } @@ -1390,7 +1397,7 @@ func (s *ModuleService) GetAgentModules(c *gin.Context) { }) if resp.Total, err = query.Query(iDB, &resp.Modules); err != nil { utils.FromContext(c).WithError(err).Errorf("error finding agent modules") - utils.HTTPError(c, srverrors.ErrGetAgentModulesInvalidQuery, err) + response.Error(c, response.ErrGetAgentModulesInvalidQuery, err) return } @@ -1398,7 +1405,7 @@ func (s *ModuleService) GetAgentModules(c *gin.Context) { if err = resp.Modules[i].Valid(); err != nil { utils.FromContext(c).WithError(err). Errorf("error validating agent module data '%s'", resp.Modules[i].Info.Name) - utils.HTTPError(c, srverrors.ErrGetAgentModulesInvalidAgentData, err) + response.Error(c, response.ErrGetAgentModulesInvalidAgentData, err) return } } @@ -1415,14 +1422,14 @@ func (s *ModuleService) GetAgentModules(c *gin.Context) { if err = s.db.Scopes(scope).Find(&modules).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding system modules list by names") - utils.HTTPError(c, srverrors.ErrGetAgentsGetSystemModulesFail, err) + response.Error(c, response.ErrGetAgentsGetSystemModulesFail, err) return } var details []agentModuleDetails if err = iDB.Raw(sqlAgentModuleDetails, agentPolicies.ID).Scan(&details).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error loading agents modules details") - utils.HTTPError(c, srverrors.ErrGetAgentModulesDetailsNotFound, err) + response.Error(c, response.ErrGetAgentModulesDetailsNotFound, err) return } @@ -1448,7 +1455,7 @@ func (s *ModuleService) GetAgentModules(c *gin.Context) { resp.Details = append(resp.Details, rmd) } - utils.HTTPSuccess(c, http.StatusOK, resp) + response.Success(c, http.StatusOK, resp) } // GetAgentModule is a function to return agent module by name @@ -1473,13 +1480,13 @@ func (s *ModuleService) GetAgentModule(c *gin.Context) { serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } @@ -1487,20 +1494,20 @@ func (s *ModuleService) GetAgentModule(c *gin.Context) { if err = iDB.Take(&agentPolicies, "hash = ?", hash).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding agent by hash") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPError(c, srverrors.ErrGetAgentModuleAgentNotFound, err) + response.Error(c, response.ErrGetAgentModuleAgentNotFound, err) } else { - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) } return } if err = iDB.Model(agentPolicies).Association("policies").Find(&agentPolicies.Policies).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding agent policies by agent model") - utils.HTTPError(c, srverrors.ErrGetAgentModuleAgentPoliceNotFound, err) + response.Error(c, response.ErrGetAgentModuleAgentPoliceNotFound, err) return } if err = agentPolicies.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating agent policies data '%s'", agentPolicies.Hash) - utils.HTTPError(c, srverrors.ErrGetAgentModuleInvalidAgentPoliceData, err) + response.Error(c, response.ErrGetAgentModuleInvalidAgentPoliceData, err) return } @@ -1513,15 +1520,15 @@ func (s *ModuleService) GetAgentModule(c *gin.Context) { } if err = iDB.Scopes(scopeModule).Take(&module).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding policy module by module name") - utils.HTTPError(c, srverrors.ErrModulesNotFound, err) + response.Error(c, response.ErrModulesNotFound, err) return } else if err = module.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating module data '%s'", module.Info.Name) - utils.HTTPError(c, srverrors.ErrModulesInvalidData, err) + response.Error(c, response.ErrModulesInvalidData, err) return } - utils.HTTPSuccess(c, http.StatusOK, module) + response.Success(c, http.StatusOK, module) } // GetAgentBModule is a function to return bmodule vue code as a file @@ -1558,13 +1565,13 @@ func (s *ModuleService) GetAgentBModule(c *gin.Context) { serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } @@ -1583,7 +1590,7 @@ func (s *ModuleService) GetAgentBModule(c *gin.Context) { } if err = agentPolicies.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating agent policies data '%s'", agentPolicies.Hash) - utils.HTTPError(c, srverrors.ErrGetAgentBModuleInvalidAgentPoliceData, err) + response.Error(c, response.ErrGetAgentBModuleInvalidAgentPoliceData, err) return } @@ -1599,7 +1606,7 @@ func (s *ModuleService) GetAgentBModule(c *gin.Context) { return } else if err = module.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating module data '%s'", module.Info.Name) - utils.HTTPError(c, srverrors.ErrModulesInvalidData, err) + response.Error(c, response.ErrModulesInvalidData, err) return } @@ -1640,45 +1647,45 @@ func (s *ModuleService) GetGroupModules(c *gin.Context) { if err := c.ShouldBindQuery(&query); err != nil { utils.FromContext(c).WithError(err).Errorf("error binding query") - utils.HTTPError(c, srverrors.ErrModulesInvalidRequest, err) + response.Error(c, response.ErrModulesInvalidRequest, err) return } serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } if sv = getService(c); sv == nil { - utils.HTTPError(c, srverrors.ErrInternalServiceNotFound, nil) + response.Error(c, response.ErrInternalServiceNotFound, nil) return } if err = iDB.Take(&gps, "hash = ?", hash).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding group by hash") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPError(c, srverrors.ErrGetGroupModulesGroupNotFound, err) + response.Error(c, response.ErrGetGroupModulesGroupNotFound, err) } else { - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) } return } if err = iDB.Model(gps).Association("policies").Find(&gps.Policies).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding group policies by group model") - utils.HTTPError(c, srverrors.ErrGetGroupModulesGroupPoliciesNotFound, err) + response.Error(c, response.ErrGetGroupModulesGroupPoliciesNotFound, err) return } if err = gps.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating group policies data '%s'", gps.Hash) - utils.HTTPError(c, srverrors.ErrGetGroupModulesInvalidGroupPoliciesData, err) + response.Error(c, response.ErrGetGroupModulesInvalidGroupPoliciesData, err) return } @@ -1702,7 +1709,7 @@ func (s *ModuleService) GetGroupModules(c *gin.Context) { }) if resp.Total, err = query.Query(iDB, &resp.Modules); err != nil { utils.FromContext(c).WithError(err).Errorf("error finding group modules") - utils.HTTPError(c, srverrors.ErrGetGroupModulesInvalidGroupQuery, err) + response.Error(c, response.ErrGetGroupModulesInvalidGroupQuery, err) return } @@ -1711,7 +1718,7 @@ func (s *ModuleService) GetGroupModules(c *gin.Context) { utils.FromContext(c).WithError(err). Errorf("error validating group module data '%s'", resp.Modules[i].Info.Name) - utils.HTTPError(c, srverrors.ErrGetGroupModulesInvalidGroupData, err) + response.Error(c, response.ErrGetGroupModulesInvalidGroupData, err) return } } @@ -1728,14 +1735,14 @@ func (s *ModuleService) GetGroupModules(c *gin.Context) { if err = s.db.Scopes(scope).Find(&modules).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding system modules list by names") - utils.HTTPError(c, srverrors.ErrGetGroupsGetSystemModulesFail, err) + response.Error(c, response.ErrGetGroupsGetSystemModulesFail, err) return } var details []groupModuleDetails if err = iDB.Raw(sqlGroupModuleDetails, gps.ID).Scan(&details).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error loading group modules details") - utils.HTTPError(c, srverrors.ErrGetGroupModulesDetailsNotFound, err) + response.Error(c, response.ErrGetGroupModulesDetailsNotFound, err) return } for _, ma := range resp.Modules { @@ -1760,7 +1767,7 @@ func (s *ModuleService) GetGroupModules(c *gin.Context) { resp.Details = append(resp.Details, rmd) } - utils.HTTPSuccess(c, http.StatusOK, resp) + response.Success(c, http.StatusOK, resp) } // GetGroupModule is a function to return group module by name @@ -1786,33 +1793,33 @@ func (s *ModuleService) GetGroupModule(c *gin.Context) { serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } if err = iDB.Take(&gps, "hash = ?", hash).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding group by hash") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPError(c, srverrors.ErrGetGroupModuleGroupNotFound, err) + response.Error(c, response.ErrGetGroupModuleGroupNotFound, err) } else { - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) } return } if err = iDB.Model(gps).Association("policies").Find(&gps.Policies).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding group policies by group model") - utils.HTTPError(c, srverrors.ErrGetGroupModuleGroupPoliciesNotFound, err) + response.Error(c, response.ErrGetGroupModuleGroupPoliciesNotFound, err) return } if err = gps.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating group policies data '%s'", gps.Hash) - utils.HTTPError(c, srverrors.ErrGetGroupModuleInvalidGroupPoliciesData, err) + response.Error(c, response.ErrGetGroupModuleInvalidGroupPoliciesData, err) return } @@ -1825,16 +1832,16 @@ func (s *ModuleService) GetGroupModule(c *gin.Context) { } if err = iDB.Scopes(scopeModule).Take(&module).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding policy module by module name") - utils.HTTPError(c, srverrors.ErrModulesNotFound, err) + response.Error(c, response.ErrModulesNotFound, err) return } else if err = module.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating module data '%s'", module.Info.Name) - utils.HTTPError(c, srverrors.ErrModulesInvalidData, err) + response.Error(c, response.ErrModulesInvalidData, err) return } - utils.HTTPSuccess(c, http.StatusOK, module) + response.Success(c, http.StatusOK, module) } // GetGroupBModule is a function to return bmodule vue code as a file @@ -1872,13 +1879,13 @@ func (s *ModuleService) GetGroupBModule(c *gin.Context) { serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } @@ -1896,7 +1903,7 @@ func (s *ModuleService) GetGroupBModule(c *gin.Context) { } if err = gps.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating group policies data '%s'", gps.Hash) - utils.HTTPError(c, srverrors.ErrGetGroupBModuleInvalidGroupPoliciesData, err) + response.Error(c, response.ErrGetGroupBModuleInvalidGroupPoliciesData, err) return } @@ -1912,7 +1919,7 @@ func (s *ModuleService) GetGroupBModule(c *gin.Context) { return } else if err = module.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating module data '%s'", module.Info.Name) - utils.HTTPError(c, srverrors.ErrModulesInvalidData, err) + response.Error(c, response.ErrModulesInvalidData, err) return } @@ -1953,39 +1960,39 @@ func (s *ModuleService) GetPolicyModules(c *gin.Context) { ) if err := c.ShouldBindQuery(&query); err != nil { - utils.HTTPError(c, srverrors.ErrModulesInvalidRequest, err) + response.Error(c, response.ErrModulesInvalidRequest, err) return } serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } if sv = getService(c); sv == nil { - utils.HTTPError(c, srverrors.ErrInternalServiceNotFound, nil) + response.Error(c, response.ErrInternalServiceNotFound, nil) return } if err = iDB.Take(&policy, "hash = ?", hash).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding policy by hash") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPError(c, srverrors.ErrGetPolicyModulesPolicyNotFound, err) + response.Error(c, response.ErrGetPolicyModulesPolicyNotFound, err) } else { - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) } return } else if err = policy.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating policy data '%s'", policy.Hash) - utils.HTTPError(c, srverrors.ErrGetPolicyModulesInvalidPolicyData, err) + response.Error(c, response.ErrGetPolicyModulesInvalidPolicyData, err) return } @@ -2006,7 +2013,7 @@ func (s *ModuleService) GetPolicyModules(c *gin.Context) { }) if _, err = queryA.Query(iDB, &modulesA); err != nil { utils.FromContext(c).WithError(err).Errorf("error finding policy modules") - utils.HTTPError(c, srverrors.ErrGetPolicyModulesInvalidPolicyQuery, err) + response.Error(c, response.ErrGetPolicyModulesInvalidPolicyQuery, err) return } @@ -2034,14 +2041,14 @@ func (s *ModuleService) GetPolicyModules(c *gin.Context) { } if resp.Total, err = queryS.Query(s.db, &modulesS, funcs...); err != nil { utils.FromContext(c).WithError(err).Errorf("error finding system modules") - utils.HTTPError(c, srverrors.ErrGetPolicyModulesInvalidModulesQuery, err) + response.Error(c, response.ErrGetPolicyModulesInvalidModulesQuery, err) return } var details []policyModuleDetails if err = iDB.Raw(sqlPolicyModuleDetails, policy.ID).Scan(&details).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error loading policies modules details") - utils.HTTPError(c, srverrors.ErrGetPolicyModulesDetailsNotFound, err) + response.Error(c, response.ErrGetPolicyModulesDetailsNotFound, err) return } @@ -2081,7 +2088,7 @@ func (s *ModuleService) GetPolicyModules(c *gin.Context) { if err = resp.Modules[i].Valid(); err != nil { utils.FromContext(c).WithError(err). Errorf("error validating policy module data '%s'", resp.Modules[i].Info.Name) - utils.HTTPError(c, srverrors.ErrGetPolicyModulesInvalidPolicyData, err) + response.Error(c, response.ErrGetPolicyModulesInvalidPolicyData, err) return } } @@ -2095,7 +2102,7 @@ func (s *ModuleService) GetPolicyModules(c *gin.Context) { duplicateMap, err := CheckMultipleModulesDuplicate(iDB, moduleNames, policy.ID) if err != nil { utils.FromContext(c).WithError(err).Errorf("error checking duplicate modules") - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) return } for i, v := range resp.Details { @@ -2103,7 +2110,7 @@ func (s *ModuleService) GetPolicyModules(c *gin.Context) { resp.Details[i].Duplicate = true } } - utils.HTTPSuccess(c, http.StatusOK, resp) + response.Success(c, http.StatusOK, resp) } // GetPolicyModule is a function to return policy module by name @@ -2128,41 +2135,41 @@ func (s *ModuleService) GetPolicyModule(c *gin.Context) { serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } if err = iDB.Take(&policy, "hash = ?", hash).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding policy by hash") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPError(c, srverrors.ErrGetPolicyModulePolicyNotFound, err) + response.Error(c, response.ErrGetPolicyModulePolicyNotFound, err) } else { - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) } return } else if err = policy.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating policy data '%s'", policy.Hash) - utils.HTTPError(c, srverrors.ErrGetPolicyModuleInvalidPolicyData, err) + response.Error(c, response.ErrGetPolicyModuleInvalidPolicyData, err) return } if err = iDB.Take(&module, "policy_id = ? AND name = ?", policy.ID, moduleName).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding policy module by name") - utils.HTTPError(c, srverrors.ErrModulesNotFound, err) + response.Error(c, response.ErrModulesNotFound, err) return } else if err = module.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating module data '%s'", module.Info.Name) - utils.HTTPError(c, srverrors.ErrModulesInvalidData, err) + response.Error(c, response.ErrModulesInvalidData, err) return } - utils.HTTPSuccess(c, http.StatusOK, module) + response.Success(c, http.StatusOK, module) } // GetPolicyBModule is a function to return bmodule vue code as a file @@ -2199,13 +2206,13 @@ func (s *ModuleService) GetPolicyBModule(c *gin.Context) { serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } @@ -2260,24 +2267,20 @@ func (s *ModuleService) PatchPolicyModule(c *gin.Context) { sv *models.Service encryptor crypto.IDBConfigEncryptor ) - uaf := utils.UserActionFields{ - Domain: "policy", - ObjectType: "policy", - ActionCode: "editing", - ObjectId: hash, - ObjectDisplayName: utils.UnknownObjectDisplayName, - } + + uaf := useraction.NewFields(c, "policy", "policy", "editing", hash, useraction.UnknownObjectDisplayName) + defer s.userActionWriter.WriteUserAction(uaf) serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } @@ -2287,21 +2290,21 @@ func (s *ModuleService) PatchPolicyModule(c *gin.Context) { uaf.ObjectDisplayName = name } utils.FromContext(c).WithError(err).Errorf("error binding JSON") - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesInvalidRequest, err, uaf) + response.Error(c, response.ErrModulesInvalidRequest, err) return } if encryptor = getDBEncryptor(c); encryptor == nil { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternalDBEncryptorNotFound, nil, uaf) + response.Error(c, response.ErrInternalDBEncryptorNotFound, nil) return } if err = iDB.Take(&policy, "hash = ?", hash).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding policy by hash") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchPolicyModulePolicyNotFound, err, uaf) + response.Error(c, response.ErrPatchPolicyModulePolicyNotFound, err) } else { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) } return } @@ -2309,12 +2312,12 @@ func (s *ModuleService) PatchPolicyModule(c *gin.Context) { if err = policy.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating policy data '%s'", policy.Hash) - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchPolicyModuleInvalidPolicyData, err, uaf) + response.Error(c, response.ErrPatchPolicyModuleInvalidPolicyData, err) return } if sv = getService(c); sv == nil { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternalServiceNotFound, err, uaf) + response.Error(c, response.ErrInternalServiceNotFound, err) return } @@ -2332,14 +2335,14 @@ func (s *ModuleService) PatchPolicyModule(c *gin.Context) { if err = s.db.Scopes(scope).Take(&moduleS).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding system module by name") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesSystemModuleNotFound, err, uaf) + response.Error(c, response.ErrModulesSystemModuleNotFound, err) } else { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) } return } else if err = moduleS.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating system module data '%s'", moduleS.Info.Name) - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesInvalidSystemModuleData, err, uaf) + response.Error(c, response.ErrModulesInvalidSystemModuleData, err) return } @@ -2348,13 +2351,13 @@ func (s *ModuleService) PatchPolicyModule(c *gin.Context) { moduleA.PolicyID = policy.ID } else if err = moduleA.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating module data '%s'", moduleA.Info.Name) - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesInvalidData, err, uaf) + response.Error(c, response.ErrModulesInvalidData, err) return } if moduleA.ID == 0 && form.Action != "activate" { utils.FromContext(c).WithError(nil).Errorf("error on %s module, policy module not found", form.Action) - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesInvalidSystemModuleData, err, uaf) + response.Error(c, response.ErrModulesInvalidSystemModuleData, err) return } @@ -2364,32 +2367,32 @@ func (s *ModuleService) PatchPolicyModule(c *gin.Context) { case "activate": if err = CheckModulesDuplicate(iDB, &moduleA); err != nil { utils.FromContext(c).WithError(err).Errorf("error checking duplicate modules") - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchPolicyModuleDuplicatedModule, err, uaf) + response.Error(c, response.ErrPatchPolicyModuleDuplicatedModule, err) return } if moduleA.ID == 0 { if err = CopyModuleAFilesToInstanceS3(&moduleA.Info, sv); err != nil { utils.FromContext(c).WithError(err).Errorf("error copying module files to S3") - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } if err = moduleA.ValidateEncryption(encryptor); err != nil { utils.FromContext(c).WithError(err).Errorf("module config not encrypted") - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesDataNotEncryptedOnDBInsert, nil, uaf) + response.Error(c, response.ErrModulesDataNotEncryptedOnDBInsert, nil) return } if err = iDB.Create(&moduleA).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error creating module") - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } if moduleS.State == "draft" { if err = updatePolicyModulesByModuleS(c, &moduleS, sv); err != nil { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } } @@ -2397,7 +2400,7 @@ func (s *ModuleService) PatchPolicyModule(c *gin.Context) { moduleA.Status = "joined" if err = iDB.Select("", incl...).Save(&moduleA).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error updating module") - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } } @@ -2406,28 +2409,28 @@ func (s *ModuleService) PatchPolicyModule(c *gin.Context) { moduleA.Status = "inactive" if err = iDB.Select("", incl...).Save(&moduleA).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error updating module") - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } case "store": if err = form.Module.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating module") - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchPolicyModuleNewModuleInvalid, err, uaf) + response.Error(c, response.ErrPatchPolicyModuleNewModuleInvalid, err) return } changes, err := compareModulesChanges(form.Module, moduleA, encryptor) if err != nil { utils.FromContext(c).WithError(err).Errorf("failed to compare modules changes") - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesFailedToCompareChanges, err, uaf) + response.Error(c, response.ErrModulesFailedToCompareChanges, err) return } for _, ch := range changes { if ch { utils.FromContext(c).WithError(nil).Errorf("error accepting module changes") - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchPolicyModuleAcceptFail, nil, uaf) + response.Error(c, response.ErrPatchPolicyModuleAcceptFail, nil) return } } @@ -2435,12 +2438,12 @@ func (s *ModuleService) PatchPolicyModule(c *gin.Context) { err = form.Module.EncryptSecureParameters(encryptor) if err != nil { utils.FromContext(c).WithError(err).Errorf("failed to encrypt module secure config") - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesFailedToEncryptSecureConfig, err, uaf) + response.Error(c, response.ErrModulesFailedToEncryptSecureConfig, err) return } if err = iDB.Omit(excl...).Save(&form.Module).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error saving module") - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } @@ -2448,55 +2451,55 @@ func (s *ModuleService) PatchPolicyModule(c *gin.Context) { moduleVersion := moduleA.Info.Version.String() if moduleVersion == moduleS.Info.Version.String() { utils.FromContext(c).WithError(nil).Errorf("error updating module to the same version: %s", moduleVersion) - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } moduleA, err = MergeModuleAConfigFromModuleS(&moduleA, &moduleS, encryptor) if err != nil { utils.FromContext(c).WithError(err).Errorf("invalid module state") - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) return } if err = moduleA.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("invalid module state") - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) return } err = moduleA.EncryptSecureParameters(encryptor) if err != nil { utils.FromContext(c).WithError(err).Errorf("failed to encrypt module secure config") - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesFailedToEncryptSecureConfig, err, uaf) + response.Error(c, response.ErrModulesFailedToEncryptSecureConfig, err) return } if err = CopyModuleAFilesToInstanceS3(&moduleA.Info, sv); err != nil { utils.FromContext(c).WithError(err).Errorf("error copying module files to S3") - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } if err = iDB.Omit(excl...).Save(&moduleA).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error updating module") - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } if err = removeUnusedModuleVersion(c, iDB, moduleName, moduleVersion, sv); err != nil { utils.FromContext(c).WithError(err).Errorf("error removing unused module data") - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } default: utils.FromContext(c).WithError(nil).Errorf("error making unknown action on module") - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchPolicyModuleActionNotFound, nil, uaf) + response.Error(c, response.ErrPatchPolicyModuleActionNotFound, nil) return } - utils.HTTPSuccessWithUAFields(c, http.StatusOK, struct{}{}, uaf) + response.Success(c, http.StatusOK, struct{}{}) } func compareModulesChanges(moduleIn, moduleDB models.ModuleA, encryptor crypto.IDBConfigEncryptor) ([]bool, error) { @@ -2556,75 +2559,71 @@ func (s *ModuleService) DeletePolicyModule(c *gin.Context) { policy models.Policy sv *models.Service ) - uaf := utils.UserActionFields{ - Domain: "policy", - ObjectType: "policy", - ActionCode: "editing", - ObjectId: hash, - ObjectDisplayName: utils.UnknownObjectDisplayName, - } + + uaf := useraction.NewFields(c, "policy", "policy", "editing", hash, useraction.UnknownObjectDisplayName) + defer s.userActionWriter.WriteUserAction(uaf) serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } if err = iDB.Take(&policy, "hash = ?", hash).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding policy by hash") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPErrorWithUAFields(c, srverrors.ErrDeletePolicyModulePolicyNotFound, err, uaf) + response.Error(c, response.ErrDeletePolicyModulePolicyNotFound, err) } else { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) } return } else if err = policy.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating policy data '%s'", policy.Hash) - utils.HTTPErrorWithUAFields(c, srverrors.ErrDeletePolicyModuleInvalidPolicyData, err, uaf) + response.Error(c, response.ErrDeletePolicyModuleInvalidPolicyData, err) return } uaf.ObjectDisplayName = policy.Info.Name.En if sv = getService(c); sv == nil { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternalServiceNotFound, nil, uaf) + response.Error(c, response.ErrInternalServiceNotFound, nil) return } if err = iDB.Take(&module, "policy_id = ? AND name = ?", policy.ID, moduleName).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding policy module by name") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesNotFound, err, uaf) + response.Error(c, response.ErrModulesNotFound, err) } else { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) } return } else if err = module.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating module data '%s'", module.Info.Name) - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesInvalidData, err, uaf) + response.Error(c, response.ErrModulesInvalidData, err) return } if err = iDB.Delete(&module).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error deleting policy module by name '%s'", moduleName) - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } moduleVersion := module.Info.Version.String() if err = removeUnusedModuleVersion(c, iDB, moduleName, moduleVersion, sv); err != nil { utils.FromContext(c).WithError(err).Errorf("error removing unused module data") - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } - utils.HTTPSuccessWithUAFields(c, http.StatusOK, struct{}{}, uaf) + response.Success(c, http.StatusOK, struct{}{}) } // SetPolicyModuleSecureConfigValue is a function to set secured parameter value in policy module @@ -2653,22 +2652,19 @@ func (s *ModuleService) SetPolicyModuleSecureConfigValue(c *gin.Context) { encryptor crypto.IDBConfigEncryptor paramName string ) - uaf := utils.UserActionFields{ - Domain: "policy", - ObjectType: "policy", - ActionCode: "setting value to module secure config", - ObjectId: hash, - } + + uaf := useraction.NewFields(c, "policy", "policy", "setting value to module secure config", hash, useraction.UnknownObjectDisplayName) + defer s.userActionWriter.WriteUserAction(uaf) err := c.ShouldBindJSON(&payload) switch { case err != nil: utils.FromContext(c).WithError(err).Errorf("error binding JSON") - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesInvalidRequest, err, uaf) + response.Error(c, response.ErrModulesInvalidRequest, err) return case len(payload) != 1: utils.FromContext(c).WithError(err).Errorf("only one key-value pair in body allowed") - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesInvalidRequest, err, uaf) + response.Error(c, response.ErrModulesInvalidRequest, err) return } @@ -2680,37 +2676,37 @@ func (s *ModuleService) SetPolicyModuleSecureConfigValue(c *gin.Context) { serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } if sv = getService(c); sv == nil { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternalServiceNotFound, err, uaf) + response.Error(c, response.ErrInternalServiceNotFound, err) return } if encryptor = getDBEncryptor(c); encryptor == nil { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternalDBEncryptorNotFound, nil, uaf) + response.Error(c, response.ErrInternalDBEncryptorNotFound, nil) return } if err = iDB.Take(&policy, "hash = ?", hash).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding policy by hash") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchPolicyModulePolicyNotFound, err, uaf) + response.Error(c, response.ErrPatchPolicyModulePolicyNotFound, err) } else { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) } return } else if err = policy.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating policy data '%s'", policy.Hash) - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchPolicyModuleInvalidPolicyData, err, uaf) + response.Error(c, response.ErrPatchPolicyModuleInvalidPolicyData, err) return } @@ -2723,14 +2719,14 @@ func (s *ModuleService) SetPolicyModuleSecureConfigValue(c *gin.Context) { if err = s.db.Scopes(scope).Take(&moduleS).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding system module by name") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesSystemModuleNotFound, err, uaf) + response.Error(c, response.ErrModulesSystemModuleNotFound, err) } else { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) } return } else if err = moduleS.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating system module data '%s'", moduleS.Info.Name) - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesInvalidSystemModuleData, err, uaf) + response.Error(c, response.ErrModulesInvalidSystemModuleData, err) return } uaf.ObjectDisplayName = moduleS.Locale.Module["en"].Title @@ -2740,21 +2736,21 @@ func (s *ModuleService) SetPolicyModuleSecureConfigValue(c *gin.Context) { moduleA.PolicyID = policy.ID } else if err = moduleA.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating module data '%s'", moduleA.Info.Name) - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesInvalidData, err, uaf) + response.Error(c, response.ErrModulesInvalidData, err) return } if err = moduleA.DecryptSecureParameters(encryptor); err != nil { utils.FromContext(c).WithError(err). Errorf("error decrypting module data '%s'", moduleA.Info.Name) - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesFailedToDecryptSecureConfig, err, uaf) + response.Error(c, response.ErrModulesFailedToDecryptSecureConfig, err) return } param, ok := moduleA.SecureCurrentConfig[paramName] if !ok { utils.FromContext(c).WithError(err).Errorf("module secure parameter not exists") - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesInvalidRequest, err, uaf) + response.Error(c, response.ErrModulesInvalidRequest, err) return } @@ -2764,23 +2760,23 @@ func (s *ModuleService) SetPolicyModuleSecureConfigValue(c *gin.Context) { } if err = moduleA.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error saving module") - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesInvalidParameterValue, err, uaf) + response.Error(c, response.ErrModulesInvalidParameterValue, err) return } err = moduleA.EncryptSecureParameters(encryptor) if err != nil { utils.FromContext(c).WithError(err).Errorf("failed to encrypt module secure config") - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesFailedToEncryptSecureConfig, err, uaf) + response.Error(c, response.ErrModulesFailedToEncryptSecureConfig, err) return } if err = iDB.Save(&moduleA).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error saving module") - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } - utils.HTTPSuccessWithUAFields(c, http.StatusOK, struct{}{}, uaf) + response.Success(c, http.StatusOK, struct{}{}) } // GetPolicyModuleSecureConfigValue is a function to get secured parameter value in policy module @@ -2806,47 +2802,45 @@ func (s *ModuleService) GetPolicyModuleSecureConfigValue(c *gin.Context) { paramName = c.Param("param_name") encryptor crypto.IDBConfigEncryptor ) - uaf := utils.UserActionFields{ - Domain: "policy", - ObjectType: "policy", - ActionCode: fmt.Sprintf("retrieving value in module secure config, key: %s", paramName), - ObjectId: hash, - } + + actionCode := fmt.Sprintf("retrieving value in module secure config, key: %s", paramName) + uaf := useraction.NewFields(c, "policy", "policy", actionCode, hash, useraction.UnknownObjectDisplayName) + defer s.userActionWriter.WriteUserAction(uaf) serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } if sv = getService(c); sv == nil { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternalServiceNotFound, err, uaf) + response.Error(c, response.ErrInternalServiceNotFound, err) return } if encryptor = getDBEncryptor(c); encryptor == nil { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternalDBEncryptorNotFound, nil, uaf) + response.Error(c, response.ErrInternalDBEncryptorNotFound, nil) return } if err = iDB.Take(&policy, "hash = ?", hash).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding policy by hash") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchPolicyModulePolicyNotFound, err, uaf) + response.Error(c, response.ErrPatchPolicyModulePolicyNotFound, err) } else { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) } return } else if err = policy.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating policy data '%s'", policy.Hash) - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchPolicyModuleInvalidPolicyData, err, uaf) + response.Error(c, response.ErrPatchPolicyModuleInvalidPolicyData, err) return } @@ -2859,14 +2853,14 @@ func (s *ModuleService) GetPolicyModuleSecureConfigValue(c *gin.Context) { if err = s.db.Scopes(scope).Take(&moduleS).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding system module by name") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesSystemModuleNotFound, err, uaf) + response.Error(c, response.ErrModulesSystemModuleNotFound, err) } else { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) } return } else if err = moduleS.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating system module data '%s'", moduleS.Info.Name) - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesInvalidSystemModuleData, err, uaf) + response.Error(c, response.ErrModulesInvalidSystemModuleData, err) return } uaf.ObjectDisplayName = moduleS.Locale.Module["en"].Title @@ -2876,27 +2870,27 @@ func (s *ModuleService) GetPolicyModuleSecureConfigValue(c *gin.Context) { moduleA.PolicyID = policy.ID } else if err = moduleA.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating module data '%s'", moduleA.Info.Name) - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesInvalidData, err, uaf) + response.Error(c, response.ErrModulesInvalidData, err) return } if err = moduleA.DecryptSecureParameters(encryptor); err != nil { utils.FromContext(c).WithError(err). Errorf("error decrypting module data '%s'", moduleA.Info.Name) - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesFailedToDecryptSecureConfig, err, uaf) + response.Error(c, response.ErrModulesFailedToDecryptSecureConfig, err) return } val, ok := moduleA.SecureCurrentConfig[paramName] if !ok { utils.FromContext(c).WithError(err).Errorf("module secure parameter not exists") - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesInvalidRequest, err, uaf) + response.Error(c, response.ErrModulesInvalidRequest, err) return } resp := make(models.ModuleConfig) resp[paramName] = val.Value - utils.HTTPSuccessWithUAFields(c, http.StatusOK, resp, uaf) + response.Success(c, http.StatusOK, resp) } // GetModules is a function to return system module list @@ -2920,17 +2914,17 @@ func (s *ModuleService) GetModules(c *gin.Context) { if err := c.ShouldBindQuery(&query); err != nil { utils.FromContext(c).WithError(err).Errorf("error binding query") - utils.HTTPError(c, srverrors.ErrModulesInvalidRequest, err) + response.Error(c, response.ErrModulesInvalidRequest, err) return } if sv = getService(c); sv == nil { - utils.HTTPError(c, srverrors.ErrInternalServiceNotFound, nil) + response.Error(c, response.ErrInternalServiceNotFound, nil) return } if encryptor = getDBEncryptor(c); encryptor == nil { - utils.HTTPError(c, srverrors.ErrInternalDBEncryptorNotFound, nil) + response.Error(c, response.ErrInternalDBEncryptorNotFound, nil) return } @@ -2968,7 +2962,7 @@ func (s *ModuleService) GetModules(c *gin.Context) { total, err := query.Query(s.db, &resp.Modules, funcs...) if err != nil { utils.FromContext(c).WithError(err).Errorf("error finding system modules") - utils.HTTPError(c, srverrors.ErrGetModulesInvalidModulesQuery, err) + response.Error(c, response.ErrGetModulesInvalidModulesQuery, err) return } resp.Total = total @@ -2977,19 +2971,19 @@ func (s *ModuleService) GetModules(c *gin.Context) { if err = module.Valid(); err != nil { utils.FromContext(c).WithError(err). Errorf("error validating system module data '%s'", module.Info.Name) - utils.HTTPError(c, srverrors.ErrModulesInvalidSystemModuleData, err) + response.Error(c, response.ErrModulesInvalidSystemModuleData, err) return } if err = module.DecryptSecureParameters(encryptor); err != nil { utils.FromContext(c).WithError(err). Errorf("error decrypting module data '%s'", module.Info.Name) - utils.HTTPError(c, srverrors.ErrModulesFailedToDecryptSecureConfig, err) + response.Error(c, response.ErrModulesFailedToDecryptSecureConfig, err) return } } - utils.HTTPSuccess(c, http.StatusOK, resp) + response.Success(c, http.StatusOK, resp) } // CreateModule is a function to create new system module @@ -3012,20 +3006,17 @@ func (s *ModuleService) CreateModule(c *gin.Context) { template Template encryptor crypto.IDBConfigEncryptor ) - uaf := utils.UserActionFields{ - Domain: "module", - ObjectType: "module", - ActionCode: "creation", - ObjectDisplayName: utils.UnknownObjectDisplayName, - } + + uaf := useraction.NewFields(c, "module", "module", "creation", "", useraction.UnknownObjectDisplayName) + defer s.userActionWriter.WriteUserAction(uaf) if sv = getService(c); sv == nil { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternalServiceNotFound, nil, uaf) + response.Error(c, response.ErrInternalServiceNotFound, nil) return } if encryptor = getDBEncryptor(c); encryptor == nil { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternalDBEncryptorNotFound, nil, uaf) + response.Error(c, response.ErrInternalDBEncryptorNotFound, nil) return } @@ -3036,10 +3027,10 @@ func (s *ModuleService) CreateModule(c *gin.Context) { err = info.Valid() } utils.FromContext(c).WithError(err).Errorf("error binding JSON") - utils.HTTPErrorWithUAFields(c, srverrors.ErrCreateModuleInvalidInfo, err, uaf) + response.Error(c, response.ErrCreateModuleInvalidInfo, err) return } - uaf.ObjectId = info.Name + uaf.ObjectID = info.Name scope := func(db *gorm.DB) *gorm.DB { return db.Where("name = ? AND tenant_id = ? AND service_type = ?", info.Name, tid, sv.Type) @@ -3047,11 +3038,11 @@ func (s *ModuleService) CreateModule(c *gin.Context) { if err := s.db.Scopes(scope).Model(&module).Count(&count).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding number of system module") - utils.HTTPErrorWithUAFields(c, srverrors.ErrCreateModuleGetCountFail, err, uaf) + response.Error(c, response.ErrCreateModuleGetCountFail, err) return } else if count >= 1 { utils.FromContext(c).WithError(nil).Errorf("error creating second system module") - utils.HTTPErrorWithUAFields(c, srverrors.ErrCreateModuleSecondSystemModule, err, uaf) + response.Error(c, response.ErrCreateModuleSecondSystemModule, err) return } @@ -3060,7 +3051,7 @@ func (s *ModuleService) CreateModule(c *gin.Context) { var err error if template, module, err = LoadModuleSTemplate(&info); err != nil { utils.FromContext(c).WithError(err).Errorf("error loading module") - utils.HTTPErrorWithUAFields(c, srverrors.ErrCreateModuleLoadFail, err, uaf) + response.Error(c, response.ErrCreateModuleLoadFail, err) return } uaf.ObjectDisplayName = module.Locale.Module["en"].Title @@ -3070,27 +3061,27 @@ func (s *ModuleService) CreateModule(c *gin.Context) { module.ServiceType = sv.Type if err = module.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating module") - utils.HTTPErrorWithUAFields(c, srverrors.ErrCreateModuleValidationFail, err, uaf) + response.Error(c, response.ErrCreateModuleValidationFail, err) return } if err = StoreModuleSToGlobalS3(&info, template); err != nil { utils.FromContext(c).WithError(err).Errorf("error storing module to S3") - utils.HTTPErrorWithUAFields(c, srverrors.ErrCreateModuleStoreS3Fail, err, uaf) + response.Error(c, response.ErrCreateModuleStoreS3Fail, err) return } if err = module.DecryptSecureParameters(encryptor); err != nil { - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesFailedToEncryptSecureConfig, nil, uaf) + response.Error(c, response.ErrModulesFailedToEncryptSecureConfig, nil) return } if err = s.db.Create(module).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error creating module") - utils.HTTPErrorWithUAFields(c, srverrors.ErrCreateModuleStoreDBFail, err, uaf) + response.Error(c, response.ErrCreateModuleStoreDBFail, err) return } - utils.HTTPSuccessWithUAFields(c, http.StatusCreated, module, uaf) + response.Success(c, http.StatusCreated, module) } // DeleteModule is a function to cascade delete system module @@ -3112,16 +3103,12 @@ func (s *ModuleService) DeleteModule(c *gin.Context) { sv *models.Service services []models.Service ) - uaf := utils.UserActionFields{ - Domain: "module", - ObjectType: "module", - ActionCode: "deletion", - ObjectId: moduleName, - ObjectDisplayName: utils.UnknownObjectDisplayName, - } + + uaf := useraction.NewFields(c, "module", "module", "deletion", moduleName, useraction.UnknownObjectDisplayName) + defer s.userActionWriter.WriteUserAction(uaf) if sv = getService(c); sv == nil { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternalServiceNotFound, nil, uaf) + response.Error(c, response.ErrInternalServiceNotFound, nil) return } @@ -3133,9 +3120,9 @@ func (s *ModuleService) DeleteModule(c *gin.Context) { if err = s.db.Scopes(scope).Find(&modules).Error; err != nil || len(modules) == 0 { utils.FromContext(c).WithError(err).Errorf("error finding system module by name") if err == nil && len(modules) == 0 { - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesNotFound, err, uaf) + response.Error(c, response.ErrModulesNotFound, err) } else { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) } return } @@ -3182,36 +3169,36 @@ func (s *ModuleService) DeleteModule(c *gin.Context) { if err = s.db.Find(&services, "tenant_id = ? AND type = ?", tid, sv.Type).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding services") - utils.HTTPErrorWithUAFields(c, srverrors.ErrDeleteModuleServiceNotFound, err, uaf) + response.Error(c, response.ErrDeleteModuleServiceNotFound, err) return } for _, s := range services { if err = deletePolicyModule(&s); err != nil { - utils.HTTPErrorWithUAFields(c, srverrors.ErrDeleteModuleDeleteFail, err, uaf) + response.Error(c, response.ErrDeleteModuleDeleteFail, err) return } } if err = s.db.Where("name = ?", moduleName).Delete(&modules).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error deleting system module by name '%s'", moduleName) - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } if s3, err = storage.NewS3(nil); err != nil { utils.FromContext(c).WithError(err).Errorf("error openning connection to S3") - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } if err = s3.RemoveDir(moduleName + "/"); err != nil && err.Error() != "not found" { utils.FromContext(c).WithError(err).Errorf("error removing system modules files") - utils.HTTPErrorWithUAFields(c, srverrors.ErrDeleteModuleDeleteFilesFail, err, uaf) + response.Error(c, response.ErrDeleteModuleDeleteFilesFail, err) return } - utils.HTTPSuccessWithUAFields(c, http.StatusOK, struct{}{}, uaf) + response.Success(c, http.StatusOK, struct{}{}) } // GetModuleVersions is a function to return all versions for system module @@ -3235,12 +3222,12 @@ func (s *ModuleService) GetModuleVersions(c *gin.Context) { if err := c.ShouldBindQuery(&query); err != nil { utils.FromContext(c).WithError(err).Errorf("error binding query") - utils.HTTPError(c, srverrors.ErrModulesInvalidRequest, err) + response.Error(c, response.ErrModulesInvalidRequest, err) return } if sv = getService(c); sv == nil { - utils.HTTPError(c, srverrors.ErrInternalServiceNotFound, nil) + response.Error(c, response.ErrInternalServiceNotFound, nil) return } @@ -3260,7 +3247,7 @@ func (s *ModuleService) GetModuleVersions(c *gin.Context) { total, err := query.Query(s.db, &resp.Modules) if err != nil { utils.FromContext(c).WithError(err).Errorf("error finding system modules") - utils.HTTPError(c, srverrors.ErrGetModuleVersionsInvalidModulesQuery, err) + response.Error(c, response.ErrGetModuleVersionsInvalidModulesQuery, err) return } resp.Total = total @@ -3269,12 +3256,12 @@ func (s *ModuleService) GetModuleVersions(c *gin.Context) { if err = resp.Modules[i].Valid(); err != nil { utils.FromContext(c).WithError(err). Errorf("error validating system module data '%s'", resp.Modules[i].Info.Name) - utils.HTTPError(c, srverrors.ErrModulesInvalidSystemModuleData, err) + response.Error(c, response.ErrModulesInvalidSystemModuleData, err) return } } - utils.HTTPSuccess(c, http.StatusOK, resp) + response.Success(c, http.StatusOK, resp) } // GetModuleVersion is a function to return system module by name and version @@ -3298,12 +3285,12 @@ func (s *ModuleService) GetModuleVersion(c *gin.Context) { ) if sv = getService(c); sv == nil { - utils.HTTPError(c, srverrors.ErrInternalServiceNotFound, nil) + response.Error(c, response.ErrInternalServiceNotFound, nil) return } if encryptor = getDBEncryptor(c); encryptor == nil { - utils.HTTPError(c, srverrors.ErrInternalDBEncryptorNotFound, nil) + response.Error(c, response.ErrInternalDBEncryptorNotFound, nil) return } @@ -3315,25 +3302,25 @@ func (s *ModuleService) GetModuleVersion(c *gin.Context) { if err := s.db.Scopes(FilterModulesByVersion(version), scope).Take(&module).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding system module by name") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPError(c, srverrors.ErrModulesNotFound, err) + response.Error(c, response.ErrModulesNotFound, err) } else { - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) } return } else if err = module.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating system module data '%s'", module.Info.Name) - utils.HTTPError(c, srverrors.ErrModulesInvalidSystemModuleData, err) + response.Error(c, response.ErrModulesInvalidSystemModuleData, err) return } if err := module.DecryptSecureParameters(encryptor); err != nil { utils.FromContext(c).WithError(err).Errorf("error decrypting module data") - utils.HTTPError(c, srverrors.ErrModulesFailedToDecryptSecureConfig, err) + response.Error(c, response.ErrModulesFailedToDecryptSecureConfig, err) return } - utils.HTTPSuccess(c, http.StatusOK, module) + response.Success(c, http.StatusOK, module) } // PatchModuleVersion is a function to update system module by name and version @@ -3361,13 +3348,9 @@ func (s *ModuleService) PatchModuleVersion(c *gin.Context) { version = c.Param("version") encryptor crypto.IDBConfigEncryptor ) - uaf := utils.UserActionFields{ - Domain: "module", - ObjectType: "module", - ObjectId: moduleName, - ActionCode: "undefined action", - ObjectDisplayName: utils.UnknownObjectDisplayName, - } + + uaf := useraction.NewFields(c, "module", "module", "undefined action", moduleName, useraction.UnknownObjectDisplayName) + defer s.userActionWriter.WriteUserAction(uaf) if err := c.ShouldBindJSON(&form); err != nil || form.Module.Valid() != nil { if err == nil { @@ -3378,7 +3361,7 @@ func (s *ModuleService) PatchModuleVersion(c *gin.Context) { uaf.ObjectDisplayName = name } utils.FromContext(c).WithError(err).Errorf("error binding JSON") - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesInvalidRequest, err, uaf) + response.Error(c, response.ErrModulesInvalidRequest, err) return } @@ -3390,12 +3373,12 @@ func (s *ModuleService) PatchModuleVersion(c *gin.Context) { uaf.ObjectDisplayName = form.Module.Locale.Module["en"].Title if sv = getService(c); sv == nil { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternalServiceNotFound, nil, uaf) + response.Error(c, response.ErrInternalServiceNotFound, nil) return } if encryptor = getDBEncryptor(c); encryptor == nil { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternalDBEncryptorNotFound, nil, uaf) + response.Error(c, response.ErrInternalDBEncryptorNotFound, nil) return } @@ -3407,20 +3390,20 @@ func (s *ModuleService) PatchModuleVersion(c *gin.Context) { if err := s.db.Scopes(FilterModulesByVersion(version), scope).Take(&module).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding system module by name") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesSystemModuleNotFound, err, uaf) + response.Error(c, response.ErrModulesSystemModuleNotFound, err) } else { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) } return } else if err = module.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating system module data '%s'", module.Info.Name) - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesInvalidSystemModuleData, err, uaf) + response.Error(c, response.ErrModulesInvalidSystemModuleData, err) return } if module.State == "release" { utils.FromContext(c).WithError(nil).Errorf("error changing released system module") - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchModuleVersionAcceptReleaseChangesFail, nil, uaf) + response.Error(c, response.ErrPatchModuleVersionAcceptReleaseChangesFail, nil) return } @@ -3436,7 +3419,7 @@ func (s *ModuleService) PatchModuleVersion(c *gin.Context) { for _, ch := range changes { if ch { utils.FromContext(c).WithError(nil).Errorf("error accepting system module changes") - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchModuleVersionAcceptSystemChangesFail, nil, uaf) + response.Error(c, response.ErrPatchModuleVersionAcceptSystemChangesFail, nil) return } } @@ -3444,24 +3427,24 @@ func (s *ModuleService) PatchModuleVersion(c *gin.Context) { err := form.Module.EncryptSecureParameters(encryptor) if err != nil { utils.FromContext(c).WithError(err).Errorf("failed to encrypt module secure config") - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesFailedToEncryptSecureConfig, err, uaf) + response.Error(c, response.ErrModulesFailedToEncryptSecureConfig, err) return } if sqlResult := s.db.Omit("last_update").Save(&form.Module); sqlResult.Error != nil { utils.FromContext(c).WithError(sqlResult.Error).Errorf("error saving system module") - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchModuleVersionUpdateFail, err, uaf) + response.Error(c, response.ErrPatchModuleVersionUpdateFail, err) return } else if sqlResult.RowsAffected != 0 { if cfiles, err = BuildModuleSConfig(&form.Module); err != nil { utils.FromContext(c).WithError(err).Errorf("error building system module files") - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchModuleVersionBuildFilesFail, err, uaf) + response.Error(c, response.ErrPatchModuleVersionBuildFilesFail, err) return } template["config"] = cfiles if err = StoreModuleSToGlobalS3(&form.Module.Info, template); err != nil { utils.FromContext(c).WithError(err).Errorf("error storing system module files to S3") - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchModuleVersionUpdateS3Fail, err, uaf) + response.Error(c, response.ErrPatchModuleVersionUpdateS3Fail, err) return } } @@ -3469,25 +3452,25 @@ func (s *ModuleService) PatchModuleVersion(c *gin.Context) { if module.State == "draft" && form.Module.State == "release" { if err = s.db.Find(&services, "tenant_id = ? AND type = ?", tid, sv.Type).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding services") - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchModuleVersionServiceNotFound, err, uaf) + response.Error(c, response.ErrPatchModuleVersionServiceNotFound, err) return } if err = s.db.Model(&form.Module).Take(&module).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding system module by id '%d'", form.Module.ID) - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } for _, s := range services { if err = updatePolicyModulesByModuleS(c, &module, &s); err != nil { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } } } - utils.HTTPSuccessWithUAFields(c, http.StatusOK, struct{}{}, uaf) + response.Success(c, http.StatusOK, struct{}{}) } // CreateModuleVersion is a function to create new system module version @@ -3516,21 +3499,17 @@ func (s *ModuleService) CreateModuleVersion(c *gin.Context) { version = c.Param("version") encryptor crypto.IDBConfigEncryptor ) - uaf := utils.UserActionFields{ - Domain: "module", - ObjectType: "module", - ActionCode: "creation of the draft", - ObjectId: moduleName, - ObjectDisplayName: utils.UnknownObjectDisplayName, - } + + uaf := useraction.NewFields(c, "module", "module", "creation of the draft", moduleName, useraction.UnknownObjectDisplayName) + defer s.userActionWriter.WriteUserAction(uaf) if sv = getService(c); sv == nil { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternalServiceNotFound, nil, uaf) + response.Error(c, response.ErrInternalServiceNotFound, nil) return } if encryptor = getDBEncryptor(c); encryptor == nil { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternalDBEncryptorNotFound, nil, uaf) + response.Error(c, response.ErrInternalDBEncryptorNotFound, nil) return } @@ -3543,7 +3522,7 @@ func (s *ModuleService) CreateModuleVersion(c *gin.Context) { uaf.ObjectDisplayName = name } utils.FromContext(c).WithError(err).Errorf("error binding JSON") - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesInvalidRequest, err, uaf) + response.Error(c, response.ErrModulesInvalidRequest, err) return } @@ -3555,9 +3534,9 @@ func (s *ModuleService) CreateModuleVersion(c *gin.Context) { if err := s.db.Scopes(FilterModulesByVersion("latest"), scope).Take(&module).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding system module by name") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesSystemModuleNotFound, err, uaf) + response.Error(c, response.ErrModulesSystemModuleNotFound, err) } else { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) } return } @@ -3566,7 +3545,7 @@ func (s *ModuleService) CreateModuleVersion(c *gin.Context) { if err := module.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating system module data '%s'", module.Info.Name) - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesInvalidSystemModuleData, err, uaf) + response.Error(c, response.ErrModulesInvalidSystemModuleData, err) return } @@ -3576,18 +3555,18 @@ func (s *ModuleService) CreateModuleVersion(c *gin.Context) { if err := s.db.Scopes(scope, draft).Model(&module).Count(&count).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding number of system module drafts") - utils.HTTPErrorWithUAFields(c, srverrors.ErrCreateModuleVersionGetDraftNumberFail, err, uaf) + response.Error(c, response.ErrCreateModuleVersionGetDraftNumberFail, err) return } else if count >= 1 { utils.FromContext(c).WithError(nil).Errorf("error creating system module second draft") - utils.HTTPErrorWithUAFields(c, srverrors.ErrCreateModuleVersionSecondSystemModuleDraft, err, uaf) + response.Error(c, response.ErrCreateModuleVersionSecondSystemModuleDraft, err) return } newModuleVersion, err := semver.NewVersion(version) if err != nil { utils.FromContext(c).WithError(err).Errorf("error parsing new version '%s'", version) - utils.HTTPErrorWithUAFields(c, srverrors.ErrCreateModuleVersionInvalidModuleVersionFormat, err, uaf) + response.Error(c, response.ErrCreateModuleVersionInvalidModuleVersionFormat, err) return } @@ -3596,13 +3575,13 @@ func (s *ModuleService) CreateModuleVersion(c *gin.Context) { default: utils.FromContext(c).WithError(nil).Errorf("error validating new version '%s' -> '%s'", module.Info.Version.String(), version) - utils.HTTPErrorWithUAFields(c, srverrors.ErrCreateModuleVersionInvalidModuleVersion, nil, uaf) + response.Error(c, response.ErrCreateModuleVersionInvalidModuleVersion, nil) return } if template, err = LoadModuleSFromGlobalS3(&module.Info); err != nil { utils.FromContext(c).WithError(err).Errorf("error building system module files") - utils.HTTPErrorWithUAFields(c, srverrors.ErrCreateModuleVersionBuildFilesFail, err, uaf) + response.Error(c, response.ErrCreateModuleVersionBuildFilesFail, err) return } @@ -3615,36 +3594,36 @@ func (s *ModuleService) CreateModuleVersion(c *gin.Context) { module.Changelog[module.Info.Version.String()] = clver if err = module.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating module") - utils.HTTPErrorWithUAFields(c, srverrors.ErrCreateModuleVersionValidationFail, err, uaf) + response.Error(c, response.ErrCreateModuleVersionValidationFail, err) return } if cfiles, err = BuildModuleSConfig(&module); err != nil { utils.FromContext(c).WithError(err).Errorf("error building system module files") - utils.HTTPErrorWithUAFields(c, srverrors.ErrCreateModuleVersionBuildFilesFail, err, uaf) + response.Error(c, response.ErrCreateModuleVersionBuildFilesFail, err) return } template["config"] = cfiles if err = StoreModuleSToGlobalS3(&module.Info, template); err != nil { utils.FromContext(c).WithError(err).Errorf("error storing module to S3") - utils.HTTPErrorWithUAFields(c, srverrors.ErrCreateModuleVersionStoreS3Fail, err, uaf) + response.Error(c, response.ErrCreateModuleVersionStoreS3Fail, err) return } err = module.EncryptSecureParameters(encryptor) if err != nil { utils.FromContext(c).WithError(err).Errorf("failed to encrypt module secure config") - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesFailedToEncryptSecureConfig, err, uaf) + response.Error(c, response.ErrModulesFailedToEncryptSecureConfig, err) return } if err = s.db.Create(&module).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error creating module") - utils.HTTPErrorWithUAFields(c, srverrors.ErrCreateModuleVersionStoreDBFail, err, uaf) + response.Error(c, response.ErrCreateModuleVersionStoreDBFail, err) return } - utils.HTTPSuccessWithUAFields(c, http.StatusCreated, module, uaf) + response.Success(c, http.StatusCreated, module) } // DeleteModuleVersion is a function to delete the version system module @@ -3666,16 +3645,12 @@ func (s *ModuleService) DeleteModuleVersion(c *gin.Context) { sv *models.Service version = c.Param("version") ) - uaf := utils.UserActionFields{ - Domain: "module", - ObjectType: "module", - ActionCode: "deletion of the version", - ObjectId: moduleName, - ObjectDisplayName: utils.UnknownObjectDisplayName, - } + + uaf := useraction.NewFields(c, "module", "module", "deletion of the version", moduleName, useraction.UnknownObjectDisplayName) + defer s.userActionWriter.WriteUserAction(uaf) if sv = getService(c); sv == nil { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternalServiceNotFound, nil, uaf) + response.Error(c, response.ErrInternalServiceNotFound, nil) return } @@ -3686,50 +3661,50 @@ func (s *ModuleService) DeleteModuleVersion(c *gin.Context) { if err := s.db.Scopes(scope).Model(&module).Count(&count).Error; err != nil || count == 0 { utils.FromContext(c).WithError(err).Errorf("error finding number of system module versions") - utils.HTTPErrorWithUAFields(c, srverrors.ErrDeleteModuleVersionGetVersionNumberFail, err, uaf) + response.Error(c, response.ErrDeleteModuleVersionGetVersionNumberFail, err) return } else if count == 1 { utils.FromContext(c).WithError(nil).Errorf("error deleting last system module version") - utils.HTTPErrorWithUAFields(c, srverrors.ErrDeleteModuleVersionDeleteLastVersionFail, nil, uaf) + response.Error(c, response.ErrDeleteModuleVersionDeleteLastVersionFail, nil) return } if err := s.db.Scopes(FilterModulesByVersion(version), scope).Take(&module).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding system module by name") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesSystemModuleNotFound, err, uaf) + response.Error(c, response.ErrModulesSystemModuleNotFound, err) } else { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) } return } else if err = module.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating system module data '%s'", module.Info.Name) - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesInvalidSystemModuleData, err, uaf) + response.Error(c, response.ErrModulesInvalidSystemModuleData, err) return } uaf.ObjectDisplayName = module.Locale.Module["en"].Title if err := s.db.Delete(&module).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error deleting system module by name '%s'", moduleName) - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } s3, err := storage.NewS3(nil) if err != nil { utils.FromContext(c).WithError(err).Errorf("error openning connection to S3") - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } path := moduleName + "/" + module.Info.Version.String() + "/" if err = s3.RemoveDir(path); err != nil && err.Error() != "not found" { utils.FromContext(c).WithError(err).Errorf("error removing system modules files") - utils.HTTPErrorWithUAFields(c, srverrors.ErrDeleteModuleVersionDeleteFilesFail, err, uaf) + response.Error(c, response.ErrDeleteModuleVersionDeleteFilesFail, err) return } - utils.HTTPSuccessWithUAFields(c, http.StatusOK, struct{}{}, uaf) + response.Success(c, http.StatusOK, struct{}{}) } // GetModuleVersionUpdates is a function to return policy modules list ready to update @@ -3757,18 +3732,18 @@ func (s *ModuleService) GetModuleVersionUpdates(c *gin.Context) { serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } if sv = getService(c); sv == nil { - utils.HTTPError(c, srverrors.ErrInternalServiceNotFound, nil) + response.Error(c, response.ErrInternalServiceNotFound, nil) return } @@ -3780,14 +3755,14 @@ func (s *ModuleService) GetModuleVersionUpdates(c *gin.Context) { if err = s.db.Scopes(FilterModulesByVersion(version), scope).Take(&module).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding system module by name") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPError(c, srverrors.ErrModulesSystemModuleNotFound, err) + response.Error(c, response.ErrModulesSystemModuleNotFound, err) } else { - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) } return } else if err = module.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating system module data '%s'", module.Info.Name) - utils.HTTPError(c, srverrors.ErrModulesInvalidSystemModuleData, err) + response.Error(c, response.ErrModulesInvalidSystemModuleData, err) return } @@ -3799,7 +3774,7 @@ func (s *ModuleService) GetModuleVersionUpdates(c *gin.Context) { utils.FromContext(c).WithError(err). Errorf("error finding policy modules by name and version '%s' '%s'", module.Info.Name, module.Info.Version.String()) - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) return } @@ -3809,19 +3784,19 @@ func (s *ModuleService) GetModuleVersionUpdates(c *gin.Context) { if err = iDB.Find(&resp.Policies, "id IN (?)", pids).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding policies by IDs") - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) return } else { for _, policy := range resp.Policies { if err = policy.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating policy data '%s'", policy.Hash) - utils.HTTPError(c, srverrors.ErrGetModuleVersionUpdatesInvalidPolicyData, err) + response.Error(c, response.ErrGetModuleVersionUpdatesInvalidPolicyData, err) return } } } - utils.HTTPSuccess(c, http.StatusOK, resp) + response.Success(c, http.StatusOK, resp) } // CreateModuleVersionUpdates is a function to run policy modules update @@ -3843,16 +3818,12 @@ func (s *ModuleService) CreateModuleVersionUpdates(c *gin.Context) { sv *models.Service version = c.Param("version") ) - uaf := utils.UserActionFields{ - Domain: "module", - ObjectType: "module", - ActionCode: "version update in policies", - ObjectId: moduleName, - ObjectDisplayName: utils.UnknownObjectDisplayName, - } + + uaf := useraction.NewFields(c, "module", "module", "version update in policies", moduleName, useraction.UnknownObjectDisplayName) + defer s.userActionWriter.WriteUserAction(uaf) if sv = getService(c); sv == nil { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternalServiceNotFound, nil, uaf) + response.Error(c, response.ErrInternalServiceNotFound, nil) return } @@ -3864,24 +3835,24 @@ func (s *ModuleService) CreateModuleVersionUpdates(c *gin.Context) { if err := s.db.Scopes(FilterModulesByVersion(version), scope).Take(&module).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding system module by name") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesSystemModuleNotFound, err, uaf) + response.Error(c, response.ErrModulesSystemModuleNotFound, err) } else { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) } return } else if err = module.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating system module data '%s'", module.Info.Name) - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesInvalidSystemModuleData, err, uaf) + response.Error(c, response.ErrModulesInvalidSystemModuleData, err) return } uaf.ObjectDisplayName = module.Locale.Module["en"].Title if err := updatePolicyModulesByModuleS(c, &module, sv); err != nil { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } - utils.HTTPSuccessWithUAFields(c, http.StatusCreated, struct{}{}, uaf) + response.Success(c, http.StatusCreated, struct{}{}) } // GetModuleVersionFiles is a function to return system module file list @@ -3905,7 +3876,7 @@ func (s *ModuleService) GetModuleVersionFiles(c *gin.Context) { ) if sv = getService(c); sv == nil { - utils.HTTPError(c, srverrors.ErrInternalServiceNotFound, nil) + response.Error(c, response.ErrInternalServiceNotFound, nil) return } @@ -3917,32 +3888,32 @@ func (s *ModuleService) GetModuleVersionFiles(c *gin.Context) { if err := s.db.Scopes(FilterModulesByVersion(version), scope).Take(&module).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding system module by name") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPError(c, srverrors.ErrModulesSystemModuleNotFound, err) + response.Error(c, response.ErrModulesSystemModuleNotFound, err) } else { - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) } return } else if err = module.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating system module data '%s'", module.Info.Name) - utils.HTTPError(c, srverrors.ErrModulesInvalidSystemModuleData, err) + response.Error(c, response.ErrModulesInvalidSystemModuleData, err) return } s3, err := storage.NewS3(nil) if err != nil { utils.FromContext(c).WithError(err).Errorf("error openning connection to S3") - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) return } path := moduleName + "/" + module.Info.Version.String() if files, err = readDir(s3, path); err != nil { utils.FromContext(c).WithError(err).Errorf("error listening module files from S3") - utils.HTTPError(c, srverrors.ErrGetModuleVersionFilesListenFail, err) + response.Error(c, response.ErrGetModuleVersionFilesListenFail, err) return } - utils.HTTPSuccess(c, http.StatusOK, files) + response.Success(c, http.StatusOK, files) } // GetModuleVersionFile is a function to return system module file content @@ -3969,7 +3940,7 @@ func (s *ModuleService) GetModuleVersionFile(c *gin.Context) { ) if sv = getService(c); sv == nil { - utils.HTTPError(c, srverrors.ErrInternalServiceNotFound, nil) + response.Error(c, response.ErrInternalServiceNotFound, nil) return } @@ -3981,39 +3952,39 @@ func (s *ModuleService) GetModuleVersionFile(c *gin.Context) { if err := s.db.Scopes(FilterModulesByVersion(version), scope).Take(&module).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding system module by name") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPError(c, srverrors.ErrModulesSystemModuleNotFound, err) + response.Error(c, response.ErrModulesSystemModuleNotFound, err) } else { - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) } return } else if err = module.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating system module data '%s'", module.Info.Name) - utils.HTTPError(c, srverrors.ErrModulesInvalidSystemModuleData, err) + response.Error(c, response.ErrModulesInvalidSystemModuleData, err) return } s3, err := storage.NewS3(nil) if err != nil { utils.FromContext(c).WithError(err).Errorf("error openning connection to S3") - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) return } prefix := moduleName + "/" + module.Info.Version.String() + "/" if !strings.HasPrefix(filePath, prefix) || strings.Contains(filePath, "..") { utils.FromContext(c).WithError(nil).Errorf("error parsing path to file: mismatch base prefix") - utils.HTTPError(c, srverrors.ErrGetModuleVersionFileParsePathFail, nil) + response.Error(c, response.ErrGetModuleVersionFileParsePathFail, nil) return } if fileData, err = s3.ReadFile(filePath); err != nil { utils.FromContext(c).WithError(err).Errorf("error reading module file '%s'", filePath) - utils.HTTPError(c, srverrors.ErrGetModuleVersionFileReadFail, err) + response.Error(c, response.ErrGetModuleVersionFileReadFail, err) return } data = base64.StdEncoding.EncodeToString(fileData) - utils.HTTPSuccess(c, http.StatusOK, systemModuleFile{Path: filePath, Data: data}) + response.Success(c, http.StatusOK, systemModuleFile{Path: filePath, Data: data}) } // PatchModuleVersionFile is a function to save, move, remove of system module file and its content @@ -4040,16 +4011,12 @@ func (s *ModuleService) PatchModuleVersionFile(c *gin.Context) { sv *models.Service version = c.Param("version") ) - uaf := utils.UserActionFields{ - Domain: "module", - ObjectType: "module", - ActionCode: "module editing", - ObjectId: moduleName, - ObjectDisplayName: utils.UnknownObjectDisplayName, - } + + uaf := useraction.NewFields(c, "module", "module", "module editing", moduleName, useraction.UnknownObjectDisplayName) + defer s.userActionWriter.WriteUserAction(uaf) if sv = getService(c); sv == nil { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternalServiceNotFound, nil, uaf) + response.Error(c, response.ErrInternalServiceNotFound, nil) return } @@ -4061,41 +4028,41 @@ func (s *ModuleService) PatchModuleVersionFile(c *gin.Context) { if err := s.db.Scopes(FilterModulesByVersion(version), scope).Take(&module).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding system module by name") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesSystemModuleNotFound, err, uaf) + response.Error(c, response.ErrModulesSystemModuleNotFound, err) } else { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) } return } else if err = module.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating system module data '%s'", module.Info.Name) - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesInvalidSystemModuleData, err, uaf) + response.Error(c, response.ErrModulesInvalidSystemModuleData, err) return } uaf.ObjectDisplayName = module.Locale.Module["en"].Title if module.State == "release" { utils.FromContext(c).WithError(nil).Errorf("error patching released module") - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchModuleVersionFileUpdateFail, nil, uaf) + response.Error(c, response.ErrPatchModuleVersionFileUpdateFail, nil) return } s3, err := storage.NewS3(nil) if err != nil { utils.FromContext(c).WithError(err).Errorf("error openning connection to S3") - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } if err = c.ShouldBindJSON(&form); err != nil { utils.FromContext(c).WithError(err).Errorf("error binding JSON") - utils.HTTPErrorWithUAFields(c, srverrors.ErrModulesInvalidRequest, err, uaf) + response.Error(c, response.ErrModulesInvalidRequest, err) return } prefix := moduleName + "/" + module.Info.Version.String() + "/" if !strings.HasPrefix(form.Path, prefix) || strings.Contains(form.Path, "..") { utils.FromContext(c).WithError(nil).Errorf("error parsing path to file: mismatch base prefix") - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchModuleVersionFileParsePathFail, nil, uaf) + response.Error(c, response.ErrPatchModuleVersionFileParsePathFail, nil) return } @@ -4103,33 +4070,33 @@ func (s *ModuleService) PatchModuleVersionFile(c *gin.Context) { case "save": if data, err = base64.StdEncoding.DecodeString(form.Data); err != nil { utils.FromContext(c).WithError(err).Errorf("error decoding file data") - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchModuleVersionFileParseModuleFileFail, err, uaf) + response.Error(c, response.ErrPatchModuleVersionFileParseModuleFileFail, err) return } if err = s3.WriteFile(form.Path, data); err != nil { utils.FromContext(c).WithError(err).Errorf("error writing file data to S3") - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchModuleVersionFileWriteModuleFileFail, err, uaf) + response.Error(c, response.ErrPatchModuleVersionFileWriteModuleFileFail, err) return } case "remove": if err = s3.Remove(form.Path); err != nil { utils.FromContext(c).WithError(err).Errorf("error removing file from S3") - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchModuleVersionFileWriteModuleObjectFail, err, uaf) + response.Error(c, response.ErrPatchModuleVersionFileWriteModuleObjectFail, err) return } case "move": if !strings.HasPrefix(form.NewPath, prefix) || strings.Contains(form.NewPath, "..") { utils.FromContext(c).WithError(nil).Errorf("error parsing path to file: mismatch base prefix") - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchModuleVersionFileParseNewpathFail, nil, uaf) + response.Error(c, response.ErrPatchModuleVersionFileParseNewpathFail, nil) return } if info, err = s3.GetInfo(form.Path); err != nil { utils.FromContext(c).WithError(err).Errorf("error getting file info from S3") - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchModuleVersionFileObjectNotFound, err, uaf) + response.Error(c, response.ErrPatchModuleVersionFileObjectNotFound, err) return } else if !info.IsDir() { if strings.HasSuffix(form.NewPath, "/") { @@ -4138,13 +4105,13 @@ func (s *ModuleService) PatchModuleVersionFile(c *gin.Context) { if form.Path == form.NewPath { utils.FromContext(c).WithError(nil).Errorf("error moving file in S3: newpath is identical to path") - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchModuleVersionFilePathIdentical, nil, uaf) + response.Error(c, response.ErrPatchModuleVersionFilePathIdentical, nil) return } if err = s3.Rename(form.Path, form.NewPath); err != nil { utils.FromContext(c).WithError(err).Errorf("error renaming file in S3") - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchModuleVersionFileObjectMoveFail, err, uaf) + response.Error(c, response.ErrPatchModuleVersionFileObjectMoveFail, err) return } } else { @@ -4157,13 +4124,13 @@ func (s *ModuleService) PatchModuleVersionFile(c *gin.Context) { if form.Path == form.NewPath { utils.FromContext(c).WithError(nil).Errorf("error moving file in S3: newpath is identical to path") - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchModuleVersionFilePathIdentical, nil, uaf) + response.Error(c, response.ErrPatchModuleVersionFilePathIdentical, nil) return } if files, err = s3.ListDirRec(form.Path); err != nil { utils.FromContext(c).WithError(err).Errorf("error getting files by path from S3") - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchModuleVersionFileGetFilesFail, err, uaf) + response.Error(c, response.ErrPatchModuleVersionFileGetFilesFail, err) return } @@ -4173,7 +4140,7 @@ func (s *ModuleService) PatchModuleVersionFile(c *gin.Context) { newfile := filepath.Join(form.NewPath, obj) if err = s3.Rename(curfile, newfile); err != nil { utils.FromContext(c).WithError(err).Errorf("error moving file in S3") - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchModuleVersionFileObjectMoveFail, err, uaf) + response.Error(c, response.ErrPatchModuleVersionFileObjectMoveFail, err) return } } @@ -4182,17 +4149,17 @@ func (s *ModuleService) PatchModuleVersionFile(c *gin.Context) { default: utils.FromContext(c).WithError(nil).Errorf("error making unknown action on module") - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchModuleVersionFileActionNotFound, nil, uaf) + response.Error(c, response.ErrPatchModuleVersionFileActionNotFound, nil) return } if err = s.db.Model(&module).UpdateColumn("last_update", gorm.Expr("NOW()")).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error updating system module") - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchModuleVersionFileSystemModuleUpdateFail, err, uaf) + response.Error(c, response.ErrPatchModuleVersionFileSystemModuleUpdateFail, err) return } - utils.HTTPSuccessWithUAFields(c, http.StatusOK, struct{}{}, uaf) + response.Success(c, http.StatusOK, struct{}{}) } // GetModuleVersionOption is a function to return option of system module rendered on server side @@ -4217,7 +4184,7 @@ func (s *ModuleService) GetModuleVersionOption(c *gin.Context) { ) if sv = getService(c); sv == nil { - utils.HTTPError(c, srverrors.ErrInternalServiceNotFound, nil) + response.Error(c, response.ErrInternalServiceNotFound, nil) return } @@ -4229,24 +4196,24 @@ func (s *ModuleService) GetModuleVersionOption(c *gin.Context) { if err := s.db.Scopes(FilterModulesByVersion(version), scope).Take(&module).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding system module by name") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPError(c, srverrors.ErrModulesSystemModuleNotFound, err) + response.Error(c, response.ErrModulesSystemModuleNotFound, err) } else { - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) } return } else if err = module.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating system module data '%s'", module.Info.Name) - utils.HTTPError(c, srverrors.ErrModulesInvalidSystemModuleData, err) + response.Error(c, response.ErrModulesInvalidSystemModuleData, err) return } if optionName == "event_config_schema_definitions" { - utils.HTTPSuccess(c, http.StatusOK, models.GetECSDefinitions(nil)) + response.Success(c, http.StatusOK, models.GetECSDefinitions(nil)) return } if optionName == "action_config_schema_definitions" { - utils.HTTPSuccess(c, http.StatusOK, models.GetACSDefinitions(nil)) + response.Success(c, http.StatusOK, models.GetACSDefinitions(nil)) return } @@ -4254,17 +4221,17 @@ func (s *ModuleService) GetModuleVersionOption(c *gin.Context) { data, err := json.Marshal(module) if err != nil { utils.FromContext(c).WithError(err).Errorf("error building system module JSON") - utils.HTTPError(c, srverrors.ErrGetModuleVersionOptionMakeJsonFail, err) + response.Error(c, response.ErrGetModuleVersionOptionMakeJsonFail, err) return } else if err = json.Unmarshal(data, &options); err != nil { utils.FromContext(c).WithError(err).Errorf("error parsing system module JSON") - utils.HTTPError(c, srverrors.ErrGetModuleVersionOptionParseJsonFail, err) + response.Error(c, response.ErrGetModuleVersionOptionParseJsonFail, err) return } else if _, ok := options[optionName]; !ok { utils.FromContext(c).WithError(err).Errorf("error finding system module option by name") - utils.HTTPError(c, srverrors.ErrGetModuleVersionOptionNotFound, err) + response.Error(c, response.ErrGetModuleVersionOptionNotFound, err) return } - utils.HTTPSuccess(c, http.StatusOK, options[optionName]) + response.Success(c, http.StatusOK, options[optionName]) } diff --git a/pkg/app/api/server/private/notifications.go b/pkg/app/api/server/private/notifications.go index a7a48de5..96c88fab 100644 --- a/pkg/app/api/server/private/notifications.go +++ b/pkg/app/api/server/private/notifications.go @@ -13,8 +13,7 @@ import ( "soldr/pkg/app/api/models" srvevents "soldr/pkg/app/api/server/events" - srverrors "soldr/pkg/app/api/server/response" - "soldr/pkg/app/api/utils" + "soldr/pkg/app/api/server/response" ) type PermissionsFilter func(*gin.Context, srvevents.EventChannelName) bool @@ -43,28 +42,28 @@ func SubscribeHandler(exchanger *srvevents.Exchanger, permsFilter PermissionsFil if len(subscribes) == 0 { logger.Errorf("subscribes empty list after filtering: %s", subscribeString) - utils.HTTPError(c, srverrors.ErrNotificationsSubscribesEmptyList, nil) + response.Error(c, response.ErrNotificationsSubscribesEmptyList, nil) return } conn, _, _, err := ws.UpgradeHTTP(r, w) if err != nil { logger.WithError(err).Errorf("failed to updgrade ws conn") - utils.HTTPError(c, srverrors.ErrNotificationsUpgradeWSConnFail, err) + response.Error(c, response.ErrNotificationsUpgradeWSConnFail, err) return } svc, exists := c.Get("SV") if !exists { logger.Errorf("service not found in session: %#v", c.Keys) - utils.HTTPError(c, srverrors.ErrNotificationsServiceNotFound, nil) + response.Error(c, response.ErrNotificationsServiceNotFound, nil) return } service, ok := svc.(*models.Service) if !ok { logger.Errorf("unexpected service value: %#v", svc) - utils.HTTPError(c, srverrors.ErrNotificationsInvalidServiceValue, nil) + response.Error(c, response.ErrNotificationsInvalidServiceValue, nil) return } diff --git a/pkg/app/api/server/private/options.go b/pkg/app/api/server/private/options.go index a819a5a3..73716d5c 100644 --- a/pkg/app/api/server/private/options.go +++ b/pkg/app/api/server/private/options.go @@ -10,7 +10,7 @@ import ( "soldr/pkg/app/api/models" srvcontext "soldr/pkg/app/api/server/context" - srverrors "soldr/pkg/app/api/server/response" + "soldr/pkg/app/api/server/response" "soldr/pkg/app/api/utils" ) @@ -162,7 +162,7 @@ func validOptions(c *gin.Context, value interface{}) bool { return true } -func getOption(c *gin.Context, db *gorm.DB, option string, value interface{}) (uint64, *srverrors.HttpError) { +func getOption(c *gin.Context, db *gorm.DB, option string, value interface{}) (uint64, *response.HttpError) { var ( err error query utils.TableQuery @@ -172,11 +172,11 @@ func getOption(c *gin.Context, db *gorm.DB, option string, value interface{}) (u if err = c.ShouldBindQuery(&query); err != nil { utils.FromContext(c).WithError(err).Errorf("error binding query") - return 0, srverrors.ErrOptionsInvalidRequestData + return 0, response.ErrOptionsInvalidRequestData } if sv = getService(c); sv == nil { - return 0, srverrors.ErrInternalServiceNotFound + return 0, response.ErrInternalServiceNotFound } tid, _ := srvcontext.GetUint64(c, "tid") @@ -209,11 +209,11 @@ func getOption(c *gin.Context, db *gorm.DB, option string, value interface{}) (u } if total, err = query.Query(db, value, funcs...); err != nil { utils.FromContext(c).WithError(err).Errorf("error finding global %s list", option) - return 0, srverrors.ErrOptionsInvalidQuery + return 0, response.ErrOptionsInvalidQuery } if !validOptions(c, value) { - return 0, srverrors.ErrOptionsInvalidData + return 0, response.ErrOptionsInvalidData } return total, nil @@ -241,11 +241,11 @@ func (s *OptionService) GetOptionsActions(c *gin.Context) { var resp optionsActions ext, err := getOption(c, s.db, "action", &resp.Actions) if err != nil { - utils.HTTPError(c, err, nil) + response.Error(c, err, nil) } resp.Total = ext - utils.HTTPSuccess(c, http.StatusOK, resp) + response.Success(c, http.StatusOK, resp) } // GetOptionsEvents is a function to return global event list @@ -262,11 +262,11 @@ func (s *OptionService) GetOptionsEvents(c *gin.Context) { var resp optionsEvents ext, err := getOption(c, s.db, "event", &resp.Events) if err != nil { - utils.HTTPError(c, err, nil) + response.Error(c, err, nil) } resp.Total = ext - utils.HTTPSuccess(c, http.StatusOK, resp) + response.Success(c, http.StatusOK, resp) } // GetOptionsFields is a function to return global field list @@ -283,11 +283,11 @@ func (s *OptionService) GetOptionsFields(c *gin.Context) { var resp optionsFields ext, err := getOption(c, s.db, "field", &resp.Fields) if err != nil { - utils.HTTPError(c, err, nil) + response.Error(c, err, nil) } resp.Total = ext - utils.HTTPSuccess(c, http.StatusOK, resp) + response.Success(c, http.StatusOK, resp) } // GetOptionsTags is a function to return global tag list @@ -304,11 +304,11 @@ func (s *OptionService) GetOptionsTags(c *gin.Context) { var resp optionsTags ext, err := getOption(c, s.db, "tag", &resp.Tags) if err != nil { - utils.HTTPError(c, err, nil) + response.Error(c, err, nil) } resp.Total = ext - utils.HTTPSuccess(c, http.StatusOK, resp) + response.Success(c, http.StatusOK, resp) } // GetOptionsVersions is a function to return global version list @@ -325,9 +325,9 @@ func (s *OptionService) GetOptionsVersions(c *gin.Context) { var resp optionsVersions ext, err := getOption(c, s.db, "version", &resp.Versions) if err != nil { - utils.HTTPError(c, err, nil) + response.Error(c, err, nil) } resp.Total = ext - utils.HTTPSuccess(c, http.StatusOK, resp) + response.Success(c, http.StatusOK, resp) } diff --git a/pkg/app/api/server/private/policies.go b/pkg/app/api/server/private/policies.go index 761ffe59..efcd0786 100644 --- a/pkg/app/api/server/private/policies.go +++ b/pkg/app/api/server/private/policies.go @@ -11,7 +11,8 @@ import ( "soldr/pkg/app/api/client" "soldr/pkg/app/api/models" srvcontext "soldr/pkg/app/api/server/context" - srverrors "soldr/pkg/app/api/server/response" + "soldr/pkg/app/api/server/response" + useraction "soldr/pkg/app/api/user_action" "soldr/pkg/app/api/utils" ) @@ -160,14 +161,20 @@ func getPolicyName(db *gorm.DB, hash string) (string, error) { } type PolicyService struct { - db *gorm.DB - serverConnector *client.AgentServerClient + db *gorm.DB + serverConnector *client.AgentServerClient + userActionWriter useraction.Writer } -func NewPolicyService(db *gorm.DB, serverConnector *client.AgentServerClient) *PolicyService { +func NewPolicyService( + db *gorm.DB, + serverConnector *client.AgentServerClient, + userActionWriter useraction.Writer, +) *PolicyService { return &PolicyService{ - db: db, - serverConnector: serverConnector, + db: db, + serverConnector: serverConnector, + userActionWriter: userActionWriter, } } @@ -200,25 +207,25 @@ func (s *PolicyService) GetPolicies(c *gin.Context) { if err := c.ShouldBindQuery(&query); err != nil { utils.FromContext(c).WithError(err).Errorf("error binding query") - utils.HTTPError(c, srverrors.ErrPoliciesInvalidRequest, err) + response.Error(c, response.ErrPoliciesInvalidRequest, err) return } serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } if sv = getService(c); sv == nil { - utils.HTTPError(c, srverrors.ErrInternalServiceNotFound, nil) + response.Error(c, response.ErrInternalServiceNotFound, nil) return } @@ -229,13 +236,13 @@ func (s *PolicyService) GetPolicies(c *gin.Context) { if err = s.db.Scopes(LatestModulesQuery, scope).Find(&modules).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error loading system modules latest version") - utils.HTTPError(c, srverrors.ErrGetPoliciesSystemModulesNotFound, err) + response.Error(c, response.ErrGetPoliciesSystemModulesNotFound, err) return } if err = query.Init("policies", policiesSQLMappers); err != nil { utils.FromContext(c).WithError(err).Errorf("error binding query") - utils.HTTPError(c, srverrors.ErrPoliciesInvalidRequest, err) + response.Error(c, response.ErrPoliciesInvalidRequest, err) return } @@ -286,16 +293,16 @@ func (s *PolicyService) GetPolicies(c *gin.Context) { if query.Group == "" { if resp.Total, err = query.Query(iDB, &resp.Policies, funcs...); err != nil { utils.FromContext(c).WithError(err).Errorf("error finding policies") - utils.HTTPError(c, srverrors.ErrPoliciesInvalidQuery, err) + response.Error(c, response.ErrPoliciesInvalidQuery, err) return } } else { if groupedResp.Total, err = query.QueryGrouped(iDB, &groupedResp.Grouped, funcs...); err != nil { utils.FromContext(c).WithError(err).Errorf("error finding grouped policies") - utils.HTTPError(c, srverrors.ErrPoliciesInvalidQuery, err) + response.Error(c, response.ErrPoliciesInvalidQuery, err) return } - utils.HTTPSuccess(c, http.StatusOK, groupedResp) + response.Success(c, http.StatusOK, groupedResp) return } @@ -303,7 +310,7 @@ func (s *PolicyService) GetPolicies(c *gin.Context) { pids = append(pids, resp.Policies[i].ID) if err = resp.Policies[i].Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating policy data '%s'", resp.Policies[i].Hash) - utils.HTTPError(c, srverrors.ErrPoliciesInvalidData, err) + response.Error(c, response.ErrPoliciesInvalidData, err) return } } @@ -311,13 +318,13 @@ func (s *PolicyService) GetPolicies(c *gin.Context) { sqlQuery := sqlPolicyDetails + ` WHERE p.id IN (?) AND p.deleted_at IS NULL` if err = iDB.Raw(sqlQuery, pids).Scan(&resp.Details).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error loading policies details") - utils.HTTPError(c, srverrors.ErrGetPoliciesDetailsNotFound, err) + response.Error(c, response.ErrGetPoliciesDetailsNotFound, err) return } if err = iDB.Find(&modulesa, "policy_id IN (?) AND status = 'joined'", pids).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding policy modules") - utils.HTTPError(c, srverrors.ErrGetPoliciesModulesNotFound, err) + response.Error(c, response.ErrGetPoliciesModulesNotFound, err) return } else { for i := 0; i < len(modulesa); i++ { @@ -325,7 +332,7 @@ func (s *PolicyService) GetPolicies(c *gin.Context) { name := modulesa[i].Info.Name if err = modulesa[i].Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating policy module data '%d' '%s'", id, name) - utils.HTTPError(c, srverrors.ErrGetPoliciesInvalidModuleData, err) + response.Error(c, response.ErrGetPoliciesInvalidModuleData, err) return } } @@ -333,7 +340,7 @@ func (s *PolicyService) GetPolicies(c *gin.Context) { if err = iDB.Find(&pgss, "policy_id IN (?)", pids).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding group to policies links") - utils.HTTPError(c, srverrors.ErrGroupPolicyPoliciesNotFound, err) + response.Error(c, response.ErrGroupPolicyPoliciesNotFound, err) return } @@ -343,7 +350,7 @@ func (s *PolicyService) GetPolicies(c *gin.Context) { Find(&groups, "gtp.policy_id IN (?)", pids).Error if err != nil { utils.FromContext(c).WithError(err).Errorf("error finding policy groups") - utils.HTTPError(c, srverrors.ErrGroupPolicyGroupsNotFound, err) + response.Error(c, response.ErrGroupPolicyGroupsNotFound, err) return } else { for i := 0; i < len(groups); i++ { @@ -351,7 +358,7 @@ func (s *PolicyService) GetPolicies(c *gin.Context) { name := groups[i].Info.Name if err = groups[i].Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating agent group data '%d' '%s'", id, name) - utils.HTTPError(c, srverrors.ErrGetPoliciesInvalidGroupData, err) + response.Error(c, response.ErrGetPoliciesInvalidGroupData, err) return } } @@ -396,7 +403,7 @@ func (s *PolicyService) GetPolicies(c *gin.Context) { } } - utils.HTTPSuccess(c, http.StatusOK, resp) + response.Success(c, http.StatusOK, resp) } // GetPolicy is a function to return policy info and details view @@ -420,18 +427,18 @@ func (s *PolicyService) GetPolicy(c *gin.Context) { serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } if sv = getService(c); sv == nil { - utils.HTTPError(c, srverrors.ErrInternalServiceNotFound, nil) + response.Error(c, response.ErrInternalServiceNotFound, nil) return } @@ -442,34 +449,34 @@ func (s *PolicyService) GetPolicy(c *gin.Context) { if err = s.db.Scopes(LatestModulesQuery, scope).Find(&modules).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error loading system modules latest version") - utils.HTTPError(c, srverrors.ErrGetPolicySystemModulesNotFound, err) + response.Error(c, response.ErrGetPolicySystemModulesNotFound, err) return } if err = iDB.Take(&resp.Policy, "hash = ?", hash).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding policy by hash") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPError(c, srverrors.ErrPoliciesNotFound, err) + response.Error(c, response.ErrPoliciesNotFound, err) } else { - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) } return } else if err = resp.Policy.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating policy data '%s'", resp.Policy.Hash) - utils.HTTPError(c, srverrors.ErrPoliciesInvalidData, err) + response.Error(c, response.ErrPoliciesInvalidData, err) return } sqlQuery := sqlPolicyDetails + ` WHERE p.hash = ? AND p.deleted_at IS NULL` if err = iDB.Raw(sqlQuery, hash).Scan(&resp.Details).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error loading details by policy hash '%s'", hash) - utils.HTTPError(c, srverrors.ErrGetPolicyDetailsNotFound, err) + response.Error(c, response.ErrGetPolicyDetailsNotFound, err) return } if err = iDB.Find(&resp.Details.Modules, "policy_id = ? AND status = 'joined'", resp.Policy.ID).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding policy modules by policy ID '%d'", resp.Policy.ID) - utils.HTTPError(c, srverrors.ErrGetPolicyModulesNotFound, err) + response.Error(c, response.ErrGetPolicyModulesNotFound, err) return } else { for i := 0; i < len(resp.Details.Modules); i++ { @@ -477,7 +484,7 @@ func (s *PolicyService) GetPolicy(c *gin.Context) { name := resp.Details.Modules[i].Info.Name if err = resp.Details.Modules[i].Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating policy module data '%d' '%s'", id, name) - utils.HTTPError(c, srverrors.ErrGetPolicyInvalidModuleData, err) + response.Error(c, response.ErrGetPolicyInvalidModuleData, err) return } for _, module := range modules { @@ -495,12 +502,12 @@ func (s *PolicyService) GetPolicy(c *gin.Context) { } if err = iDB.Model(pgs).Association("groups").Find(&pgs.Groups).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding policy groups by policy model") - utils.HTTPError(c, srverrors.ErrGetPolicyGroupsNotFound, err) + response.Error(c, response.ErrGetPolicyGroupsNotFound, err) return } resp.Details.Groups = pgs.Groups - utils.HTTPSuccess(c, http.StatusOK, resp) + response.Success(c, http.StatusOK, resp) } // PatchPolicy is a function to update policy public info only @@ -522,24 +529,25 @@ func (s *PolicyService) PatchPolicy(c *gin.Context) { hash = c.Param("hash") policy models.Policy ) - uaf := utils.UserActionFields{ + uaf := useraction.Fields{ Domain: "policy", ObjectType: "policy", ActionCode: "editing", - ObjectId: hash, - ObjectDisplayName: utils.UnknownObjectDisplayName, + ObjectID: hash, + ObjectDisplayName: useraction.UnknownObjectDisplayName, } + defer s.userActionWriter.WriteUserAction(uaf) serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } @@ -552,20 +560,20 @@ func (s *PolicyService) PatchPolicy(c *gin.Context) { uaf.ObjectDisplayName = name } utils.FromContext(c).WithError(err).Errorf("error binding JSON") - utils.HTTPErrorWithUAFields(c, srverrors.ErrPoliciesInvalidRequest, err, uaf) + response.Error(c, response.ErrPoliciesInvalidRequest, err) return } uaf.ObjectDisplayName = policy.Info.Name.En if hash != policy.Hash { utils.FromContext(c).WithError(nil).Errorf("mismatch policy hash to requested one") - utils.HTTPErrorWithUAFields(c, srverrors.ErrPoliciesInvalidRequest, err, uaf) + response.Error(c, response.ErrPoliciesInvalidRequest, err) return } if err = iDB.Model(&policy).Count(&count).Error; err != nil || count == 0 { utils.FromContext(c).WithError(nil).Errorf("error updating policy by hash '%s', group not found", hash) - utils.HTTPErrorWithUAFields(c, srverrors.ErrPoliciesNotFound, err, uaf) + response.Error(c, response.ErrPoliciesNotFound, err) return } @@ -574,15 +582,15 @@ func (s *PolicyService) PatchPolicy(c *gin.Context) { if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { utils.FromContext(c).WithError(nil).Errorf("error updating policy by hash '%s', policy not found", hash) - utils.HTTPErrorWithUAFields(c, srverrors.ErrPoliciesNotFound, err, uaf) + response.Error(c, response.ErrPoliciesNotFound, err) return } else if err != nil { utils.FromContext(c).WithError(err).Errorf("error updating policy by hash '%s'", hash) - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } - utils.HTTPSuccessWithUAFields(c, http.StatusOK, policy, uaf) + response.Success(c, http.StatusOK, policy) } // PatchPolicyGroup is a function to update policy group linking @@ -605,24 +613,25 @@ func (s *PolicyService) PatchPolicyGroup(c *gin.Context) { hash = c.Param("hash") policy models.Policy ) - uaf := utils.UserActionFields{ + uaf := useraction.Fields{ Domain: "policy", ObjectType: "policy", - ObjectId: hash, + ObjectID: hash, ActionCode: "undefined action", - ObjectDisplayName: utils.UnknownObjectDisplayName, + ObjectDisplayName: useraction.UnknownObjectDisplayName, } + defer s.userActionWriter.WriteUserAction(uaf) serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } @@ -632,7 +641,7 @@ func (s *PolicyService) PatchPolicyGroup(c *gin.Context) { uaf.ObjectDisplayName = name } utils.FromContext(c).WithError(err).Errorf("error binding JSON") - utils.HTTPErrorWithUAFields(c, srverrors.ErrPoliciesInvalidRequest, err, uaf) + response.Error(c, response.ErrPoliciesInvalidRequest, err) return } if form.Action == "activate" { @@ -644,39 +653,39 @@ func (s *PolicyService) PatchPolicyGroup(c *gin.Context) { if err = iDB.Take(&policy, "hash = ?", hash).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding policy by hash") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPErrorWithUAFields(c, srverrors.ErrPoliciesNotFound, err, uaf) + response.Error(c, response.ErrPoliciesNotFound, err) } else { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) } return } uaf.ObjectDisplayName = policy.Info.Name.En if err = policy.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating policy data '%s'", policy.Hash) - utils.HTTPErrorWithUAFields(c, srverrors.ErrPoliciesInvalidData, err, uaf) + response.Error(c, response.ErrPoliciesInvalidData, err) return } if err = iDB.Take(&group, "hash = ?", form.Group.Hash).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding group by hash") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPErrorWithUAFields(c, srverrors.ErrPoliciesNotFound, err, uaf) + response.Error(c, response.ErrPoliciesNotFound, err) } else { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) } return } else if err = group.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating group data '%s'", group.Hash) - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchPolicyGroupInvalidGroupData, err, uaf) + response.Error(c, response.ErrPatchPolicyGroupInvalidGroupData, err) return } httpErr, err := makeGroupPolicyAction(form.Action, iDB, group, policy) if httpErr != nil { utils.FromContext(c).WithError(err).Errorf("error patching group policy by action: %s", httpErr.Error()) - utils.HTTPErrorWithUAFields(c, httpErr, err, uaf) + response.Error(c, httpErr, err) } - utils.HTTPSuccessWithUAFields(c, http.StatusOK, struct{}{}, uaf) + response.Success(c, http.StatusOK, struct{}{}) } // CreatePolicy is a function to create new policy @@ -695,16 +704,17 @@ func (s *PolicyService) CreatePolicy(c *gin.Context) { info policyInfo policyFrom models.Policy ) - uaf := utils.UserActionFields{ + uaf := useraction.Fields{ Domain: "policy", ObjectType: "policy", ActionCode: "creation", - ObjectDisplayName: utils.UnknownObjectDisplayName, + ObjectDisplayName: useraction.UnknownObjectDisplayName, } + defer s.userActionWriter.WriteUserAction(uaf) if err := c.ShouldBindJSON(&info); err != nil { utils.FromContext(c).WithError(err).Errorf("error binding JSON") - utils.HTTPErrorWithUAFields(c, srverrors.ErrPoliciesInvalidRequest, err, uaf) + response.Error(c, response.ErrPoliciesInvalidRequest, err) return } uaf.ObjectDisplayName = info.Name @@ -712,13 +722,13 @@ func (s *PolicyService) CreatePolicy(c *gin.Context) { serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } @@ -733,16 +743,16 @@ func (s *PolicyService) CreatePolicy(c *gin.Context) { System: false, }, } - uaf.ObjectId = policy.Hash + uaf.ObjectID = policy.Hash if info.From != 0 { if err = iDB.Take(&policyFrom, "id = ?", info.From).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding source policy by ID") - utils.HTTPErrorWithUAFields(c, srverrors.ErrCreatePolicySourceNotFound, err, uaf) + response.Error(c, response.ErrCreatePolicySourceNotFound, err) return } else if err = policyFrom.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating policy data '%s'", policyFrom.Hash) - utils.HTTPErrorWithUAFields(c, srverrors.ErrPoliciesInvalidData, err, uaf) + response.Error(c, response.ErrPoliciesInvalidData, err) return } @@ -767,7 +777,7 @@ func (s *PolicyService) CreatePolicy(c *gin.Context) { if err = iDB.Create(&policy).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error creating policy") - utils.HTTPErrorWithUAFields(c, srverrors.ErrCreatePolicyCreateFail, err, uaf) + response.Error(c, response.ErrCreatePolicyCreateFail, err) return } @@ -776,7 +786,7 @@ func (s *PolicyService) CreatePolicy(c *gin.Context) { err = iDB.Where("policy_id = ? AND status = 'joined'", policyFrom.ID).Find(&modules).Error if err != nil { utils.FromContext(c).WithError(err).Errorf("error finding policy modules by policy ID '%d'", policyFrom.ID) - utils.HTTPErrorWithUAFields(c, srverrors.ErrCreatePolicyModulesNotFound, err, uaf) + response.Error(c, response.ErrCreatePolicyModulesNotFound, err) return } for _, module := range modules { @@ -784,13 +794,13 @@ func (s *PolicyService) CreatePolicy(c *gin.Context) { module.PolicyID = policy.ID if err = iDB.Create(&module).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error creating policy module") - utils.HTTPErrorWithUAFields(c, srverrors.ErrCreatePolicyCreateModulesFail, err, uaf) + response.Error(c, response.ErrCreatePolicyCreateModulesFail, err) return } } } - utils.HTTPSuccessWithUAFields(c, http.StatusCreated, policy, uaf) + response.Success(c, http.StatusCreated, policy) } // DeletePolicy is a function to cascade delete policy @@ -810,50 +820,51 @@ func (s *PolicyService) DeletePolicy(c *gin.Context) { policy models.Policy sv *models.Service ) - uaf := utils.UserActionFields{ + uaf := useraction.Fields{ Domain: "policy", ObjectType: "policy", ActionCode: "deletion", - ObjectId: hash, - ObjectDisplayName: utils.UnknownObjectDisplayName, + ObjectID: hash, + ObjectDisplayName: useraction.UnknownObjectDisplayName, } + defer s.userActionWriter.WriteUserAction(uaf) serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } if sv = getService(c); sv == nil { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternalServiceNotFound, nil, uaf) + response.Error(c, response.ErrInternalServiceNotFound, nil) return } if err = iDB.Take(&policy, "hash = ?", hash).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding policy by hash") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPErrorWithUAFields(c, srverrors.ErrPoliciesNotFound, err, uaf) + response.Error(c, response.ErrPoliciesNotFound, err) } else { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) } return } else if err = policy.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating policy data '%s'", policy.Hash) - utils.HTTPErrorWithUAFields(c, srverrors.ErrPoliciesInvalidData, err, uaf) + response.Error(c, response.ErrPoliciesInvalidData, err) return } uaf.ObjectDisplayName = policy.Info.Name.En if policy.Info.System { utils.FromContext(c).WithError(nil).Errorf("error removing system policy") - utils.HTTPErrorWithUAFields(c, srverrors.ErrDeletePolicySystemPolicy, err, uaf) + response.Error(c, response.ErrDeletePolicySystemPolicy, err) return } @@ -862,24 +873,24 @@ func (s *PolicyService) DeletePolicy(c *gin.Context) { } if err = iDB.Model(pgs).Association("groups").Find(&pgs.Groups).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding policy groups by policy model") - utils.HTTPErrorWithUAFields(c, srverrors.ErrDeletePolicyGroupsNotFound, err, uaf) + response.Error(c, response.ErrDeletePolicyGroupsNotFound, err) return } if len(pgs.Groups) != 0 { utils.FromContext(c).WithError(nil).Errorf("error removing policy which linked to groups") - utils.HTTPErrorWithUAFields(c, srverrors.ErrDeletePolicyPolicyLinkedToGroups, err, uaf) + response.Error(c, response.ErrDeletePolicyPolicyLinkedToGroups, err) return } if err = iDB.Find(&modules, "policy_id = ?", policy.ID).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding policy modules by policy ID '%d'", policy.ID) - utils.HTTPErrorWithUAFields(c, srverrors.ErrDeletePolicyModulesNotFound, err, uaf) + response.Error(c, response.ErrDeletePolicyModulesNotFound, err) return } if err = iDB.Delete(&policy).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error deleting policy by hash '%s'", hash) - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } @@ -888,12 +899,12 @@ func (s *PolicyService) DeletePolicy(c *gin.Context) { moduleVersion := module.Info.Version.String() if err = removeUnusedModuleVersion(c, iDB, moduleName, moduleVersion, sv); err != nil { utils.FromContext(c).WithError(err).Errorf("error removing unused module data") - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } } - utils.HTTPSuccessWithUAFields(c, http.StatusOK, struct{}{}, uaf) + response.Success(c, http.StatusOK, struct{}{}) } // GetPoliciesCount is a function to return groups of counted policies @@ -904,27 +915,24 @@ func (s *PolicyService) DeletePolicy(c *gin.Context) { // @Failure 500 {object} utils.errorResp "internal error" // @Router /policies/count [get] func (s *PolicyService) GetPoliciesCount(c *gin.Context) { - var ( - resp policyCount - ) - logger := utils.FromContext(c) - uaf := utils.UserActionFields{ + uaf := useraction.Fields{ Domain: "policy", ObjectType: "policy", ActionCode: "counting", - ObjectDisplayName: utils.UnknownObjectDisplayName, + ObjectDisplayName: useraction.UnknownObjectDisplayName, } + defer s.userActionWriter.WriteUserAction(uaf) serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } @@ -936,14 +944,15 @@ func (s *PolicyService) GetPoliciesCount(c *gin.Context) { WHERE gtp.group_id IS NULL AND deleted_at IS NULL) AS 'without_groups' FROM policies WHERE deleted_at IS NULL` + var resp policyCount err = iDB.Raw(q). Scan(&resp). Error if err != nil { - logger.WithError(err).Errorf("could not count policies") - utils.HTTPError(c, srverrors.ErrInternal, err) + utils.FromContext(c).WithError(err).Errorf("could not count policies") + response.Error(c, response.ErrInternal, err) return } - utils.HTTPSuccessWithUAFields(c, http.StatusOK, resp, uaf) + response.Success(c, http.StatusOK, resp) } diff --git a/pkg/app/api/server/private/porting.go b/pkg/app/api/server/private/porting.go index f561f6c2..23e0a20f 100644 --- a/pkg/app/api/server/private/porting.go +++ b/pkg/app/api/server/private/porting.go @@ -17,7 +17,8 @@ import ( "soldr/pkg/app/api/models" srvcontext "soldr/pkg/app/api/server/context" - srverrors "soldr/pkg/app/api/server/response" + "soldr/pkg/app/api/server/response" + useraction "soldr/pkg/app/api/user_action" "soldr/pkg/app/api/utils" ) @@ -90,12 +91,17 @@ func getModuleTemplates(zipArchive *multipart.FileHeader, moduleName, version st } type PortingService struct { - db *gorm.DB + db *gorm.DB + userActionWriter useraction.Writer } -func NewPortingService(db *gorm.DB) *PortingService { +func NewPortingService( + db *gorm.DB, + userActionWriter useraction.Writer, +) *PortingService { return &PortingService{ - db: db, + db: db, + userActionWriter: userActionWriter, } } @@ -118,16 +124,17 @@ func (s *PortingService) ExportModule(c *gin.Context) { sv *models.Service version = c.Param("version") ) - uaf := utils.UserActionFields{ + uaf := useraction.Fields{ Domain: "module", ObjectType: "module", ActionCode: "export", - ObjectId: moduleName, - ObjectDisplayName: utils.UnknownObjectDisplayName, + ObjectID: moduleName, + ObjectDisplayName: useraction.UnknownObjectDisplayName, } + defer s.userActionWriter.WriteUserAction(uaf) if sv = getService(c); sv == nil { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternalServiceNotFound, nil, uaf) + response.Error(c, response.ErrInternalServiceNotFound, nil) return } @@ -138,18 +145,18 @@ func (s *PortingService) ExportModule(c *gin.Context) { if err = s.db.Scopes(FilterModulesByVersion(version), scope).Find(&modules).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding system module by name") - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } else { if len(modules) == 0 { utils.FromContext(c).WithError(nil).Errorf("system module by name and version not found: %s : %s", moduleName, version) - utils.HTTPErrorWithUAFields(c, srverrors.ErrPortingModuleNotFound, nil, uaf) + response.Error(c, response.ErrPortingModuleNotFound, nil) return } for _, module := range modules { if err = module.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating system module data '%s'", module.Info.Name) - utils.HTTPErrorWithUAFields(c, srverrors.ErrExportInvalidModuleData, err, uaf) + response.Error(c, response.ErrExportInvalidModuleData, err) return } } @@ -165,13 +172,13 @@ func (s *PortingService) ExportModule(c *gin.Context) { template, err := LoadModuleSFromGlobalS3(&module.Info) if err != nil { utils.FromContext(c).WithError(err).Errorf("error loading system module files from S3") - utils.HTTPErrorWithUAFields(c, srverrors.ErrExportLoadFilesFail, err, uaf) + response.Error(c, response.ErrExportLoadFilesFail, err) return } config, err := BuildModuleSConfig(&module) if err != nil { utils.FromContext(c).WithError(err).Errorf("error building system module config") - utils.HTTPErrorWithUAFields(c, srverrors.ErrExportBuildConfigFail, err, uaf) + response.Error(c, response.ErrExportBuildConfigFail, err) return } template["config"] = config @@ -181,13 +188,13 @@ func (s *PortingService) ExportModule(c *gin.Context) { zipFile, err := zipWriter.Create(prefix + "/" + folderName + "/" + fileName) if err != nil { utils.FromContext(c).WithError(err).Errorf("error adding new system module file to zip") - utils.HTTPErrorWithUAFields(c, srverrors.ErrExportAddFileFail, err, uaf) + response.Error(c, response.ErrExportAddFileFail, err) return } if _, err = zipFile.Write(fileContent); err != nil { utils.FromContext(c).WithError(err).Errorf("error writing system module file to zip") - utils.HTTPErrorWithUAFields(c, srverrors.ErrExportWriteFileFail, err, uaf) + response.Error(c, response.ErrExportWriteFileFail, err) return } } @@ -195,12 +202,12 @@ func (s *PortingService) ExportModule(c *gin.Context) { } if err = zipWriter.Close(); err != nil { utils.FromContext(c).WithError(err).Errorf("error closing system module archive") - utils.HTTPErrorWithUAFields(c, srverrors.ErrExportCloseArchiveFail, err, uaf) + response.Error(c, response.ErrExportCloseArchiveFail, err) return } uaf.Success = true - c.Set("uaf", []utils.UserActionFields{uaf}) + c.Set("uaf", []useraction.Fields{uaf}) date := time.Now().Format("06.01.02") contentDisposition := fmt.Sprintf("attachment; filename=%s.v.%s.%s.zip", moduleName, version, date) c.Writer.Header().Add("Content-Disposition", contentDisposition) @@ -232,16 +239,18 @@ func (s *PortingService) ImportModule(c *gin.Context) { sv *models.Service version = c.Param("version") ) - uaf := utils.UserActionFields{ + + uaf := useraction.Fields{ Domain: "module", ObjectType: "module", ActionCode: "import", - ObjectId: moduleName, - ObjectDisplayName: utils.UnknownObjectDisplayName, + ObjectID: moduleName, + ObjectDisplayName: useraction.UnknownObjectDisplayName, } + defer s.userActionWriter.WriteUserAction(uaf) if sv = getService(c); sv == nil { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternalServiceNotFound, nil, uaf) + response.Error(c, response.ErrInternalServiceNotFound, nil) return } @@ -252,7 +261,7 @@ func (s *PortingService) ImportModule(c *gin.Context) { if err = s.db.Scopes(FilterModulesByVersion("all"), scope).Find(&modules).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding system module by name") - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } getModule := func(version models.SemVersion) *models.ModuleS { @@ -267,26 +276,26 @@ func (s *PortingService) ImportModule(c *gin.Context) { zipArchive, err := c.FormFile("archive") if err != nil { utils.FromContext(c).WithError(err).Errorf("error reading system module zip file") - utils.HTTPErrorWithUAFields(c, srverrors.ErrImportReadArchiveFail, err, uaf) + response.Error(c, response.ErrImportReadArchiveFail, err) return } templates, err := getModuleTemplates(zipArchive, moduleName, version) if err != nil { utils.FromContext(c).WithError(err).Errorf("error parsing system module zip file") - utils.HTTPErrorWithUAFields(c, srverrors.ErrImportParseArchiveFail, err, uaf) + response.Error(c, response.ErrImportParseArchiveFail, err) return } if len(templates) == 0 { utils.FromContext(c).WithError(nil).Errorf("system module by name and version not found: %s : %s", moduleName, version) - utils.HTTPErrorWithUAFields(c, srverrors.ErrPortingModuleNotFound, nil, uaf) + response.Error(c, response.ErrPortingModuleNotFound, nil) return } for _, template := range templates { module, err := LoadModuleSConfig(template["config"]) if err != nil { utils.FromContext(c).WithError(err).Errorf("error parsing system module config from zip file") - utils.HTTPErrorWithUAFields(c, srverrors.ErrImportParseConfigFail, err, uaf) + response.Error(c, response.ErrImportParseConfigFail, err) return } @@ -295,19 +304,19 @@ func (s *PortingService) ImportModule(c *gin.Context) { module.ServiceType = sv.Type if err = json.Unmarshal(template["config"]["info.json"], &module.Info); err != nil { utils.FromContext(c).WithError(err).Errorf("error parsing system module file info") - utils.HTTPErrorWithUAFields(c, srverrors.ErrImportParseFileFail, err, uaf) + response.Error(c, response.ErrImportParseFileFail, err) return } if err = module.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating system module data") - utils.HTTPErrorWithUAFields(c, srverrors.ErrImportValidateConfigFail, err, uaf) + response.Error(c, response.ErrImportValidateConfigFail, err) return } svModule := getModule(module.Info.Version) if svModule != nil && !rewrite { utils.FromContext(c).WithError(nil).Errorf("error overriding system module version: %s", module.Info.Version.String()) - utils.HTTPErrorWithUAFields(c, srverrors.ErrImportOverrideNotPermitted, err, uaf) + response.Error(c, response.ErrImportOverrideNotPermitted, err) return } nmodules = append(nmodules, module) @@ -319,7 +328,7 @@ func (s *PortingService) ImportModule(c *gin.Context) { svModule := getModule(module.Info.Version) if err = StoreCleanModuleSToGlobalS3(&module.Info, template); err != nil { utils.FromContext(c).WithError(err).Errorf("error storing system module to S3") - utils.HTTPErrorWithUAFields(c, srverrors.ErrImportStoreS3Fail, err, uaf) + response.Error(c, response.ErrImportStoreS3Fail, err) return } if svModule != nil { @@ -330,10 +339,10 @@ func (s *PortingService) ImportModule(c *gin.Context) { } if err != nil { utils.FromContext(c).WithError(err).Errorf("error storing system module to DB") - utils.HTTPErrorWithUAFields(c, srverrors.ErrImportStoreDBFail, err, uaf) + response.Error(c, response.ErrImportStoreDBFail, err) return } } - utils.HTTPSuccessWithUAFields(c, http.StatusOK, struct{}{}, uaf) + response.Success(c, http.StatusOK, struct{}{}) } diff --git a/pkg/app/api/server/private/proto.go b/pkg/app/api/server/private/proto.go index 77672006..3b9f6dbb 100644 --- a/pkg/app/api/server/private/proto.go +++ b/pkg/app/api/server/private/proto.go @@ -10,7 +10,7 @@ import ( "soldr/pkg/app/api/models" srvcontext "soldr/pkg/app/api/server/context" - srverrors "soldr/pkg/app/api/server/response" + "soldr/pkg/app/api/server/response" "soldr/pkg/app/api/utils" ) @@ -100,23 +100,23 @@ func CreateAuthToken(c *gin.Context) { var req models.ProtoAuthTokenRequest if err := c.ShouldBindJSON(&req); err != nil { utils.FromContext(c).WithError(err).Errorf("error binding JSON") - utils.HTTPError(c, srverrors.ErrProtoInvalidRequest, err) + response.Error(c, response.ErrProtoInvalidRequest, err) return } else if err := req.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating JSON") - utils.HTTPError(c, srverrors.ErrProtoInvalidRequest, err) + response.Error(c, response.ErrProtoInvalidRequest, err) return } token, err := MakeToken(c, &req) if err != nil { utils.FromContext(c).WithError(err).Errorf("error on making token") - utils.HTTPError(c, srverrors.ErrProtoCreateTokenFail, err) + response.Error(c, response.ErrProtoCreateTokenFail, err) return } if _, err := ValidateToken(token); err != nil { utils.FromContext(c).WithError(err).Errorf("error on validating token") - utils.HTTPError(c, srverrors.ErrProtoInvalidToken, err) + response.Error(c, response.ErrProtoInvalidToken, err) return } @@ -125,5 +125,5 @@ func CreateAuthToken(c *gin.Context) { TTL: req.TTL, CreatedDate: time.Now(), } - utils.HTTPSuccess(c, http.StatusCreated, pat) + response.Success(c, http.StatusCreated, pat) } diff --git a/pkg/app/api/server/private/roles.go b/pkg/app/api/server/private/roles.go index 7b7facea..5c5b520d 100644 --- a/pkg/app/api/server/private/roles.go +++ b/pkg/app/api/server/private/roles.go @@ -7,7 +7,7 @@ import ( "github.com/jinzhu/gorm" "soldr/pkg/app/api/models" - srverrors "soldr/pkg/app/api/server/response" + "soldr/pkg/app/api/server/response" "soldr/pkg/app/api/utils" ) @@ -51,7 +51,7 @@ func (s *RoleService) GetRoles(c *gin.Context) { if err = c.ShouldBindQuery(&query); err != nil { utils.FromContext(c).WithError(err).Errorf("error binding query") - utils.HTTPError(c, srverrors.ErrRolesInvalidRequest, err) + response.Error(c, response.ErrRolesInvalidRequest, err) return } @@ -59,17 +59,17 @@ func (s *RoleService) GetRoles(c *gin.Context) { if resp.Total, err = query.Query(s.db, &resp.Roles); err != nil { utils.FromContext(c).WithError(err).Errorf("error finding roles") - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) return } for i := 0; i < len(resp.Roles); i++ { if err = resp.Roles[i].Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating role data '%d'", resp.Roles[i].ID) - utils.HTTPError(c, srverrors.ErrRolesInvalidData, err) + response.Error(c, response.ErrRolesInvalidData, err) return } } - utils.HTTPSuccess(c, http.StatusOK, resp) + response.Success(c, http.StatusOK, resp) } diff --git a/pkg/app/api/server/private/services.go b/pkg/app/api/server/private/services.go index 24e7ae45..f8df9371 100644 --- a/pkg/app/api/server/private/services.go +++ b/pkg/app/api/server/private/services.go @@ -9,7 +9,7 @@ import ( "soldr/pkg/app/api/models" srvcontext "soldr/pkg/app/api/server/context" - srverrors "soldr/pkg/app/api/server/response" + "soldr/pkg/app/api/server/response" "soldr/pkg/app/api/utils" ) @@ -69,7 +69,7 @@ func (s *ServicesService) GetServices(c *gin.Context) { if err = c.ShouldBindQuery(&query); err != nil { utils.FromContext(c).WithError(err).Errorf("error binding query") - utils.HTTPError(c, srverrors.ErrServicesInvalidRequest, err) + response.Error(c, response.ErrServicesInvalidRequest, err) return } @@ -88,25 +88,25 @@ func (s *ServicesService) GetServices(c *gin.Context) { }) default: utils.FromContext(c).WithError(nil).Errorf("error filtering user role services: unexpected role") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } if resp.Total, err = query.Query(s.db, &resp.Services); err != nil { utils.FromContext(c).WithError(err).Errorf("error finding services") - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) return } for i := 0; i < len(resp.Services); i++ { if err = resp.Services[i].Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating service data '%s'", resp.Services[i].Hash) - utils.HTTPError(c, srverrors.ErrServicesInvalidData, err) + response.Error(c, response.ErrServicesInvalidData, err) return } } - utils.HTTPSuccess(c, http.StatusOK, resp) + response.Success(c, http.StatusOK, resp) } // GetService is a function to return service by hash @@ -143,18 +143,18 @@ func (s *ServicesService) GetService(c *gin.Context) { if err = s.db.Scopes(scope).Take(&resp).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding service by hash") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPError(c, srverrors.ErrServicesNotFound, err) + response.Error(c, response.ErrServicesNotFound, err) } else { - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) } return } else if err = resp.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating service data '%s'", resp.Hash) - utils.HTTPError(c, srverrors.ErrServicesInvalidData, err) + response.Error(c, response.ErrServicesInvalidData, err) return } - utils.HTTPSuccess(c, http.StatusOK, resp) + response.Success(c, http.StatusOK, resp) } // CreateService is a function to create new service @@ -176,7 +176,7 @@ func (s *ServicesService) CreateService(c *gin.Context) { if err = c.ShouldBindJSON(&service); err != nil { utils.FromContext(c).WithError(err).Errorf("error binding JSON") - utils.HTTPError(c, srverrors.ErrServicesInvalidRequest, err) + response.Error(c, response.ErrServicesInvalidRequest, err) return } @@ -189,7 +189,7 @@ func (s *ServicesService) CreateService(c *gin.Context) { service.TenantID = tid default: utils.FromContext(c).WithError(nil).Errorf("error filtering user role services: unexpected role") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } @@ -197,11 +197,11 @@ func (s *ServicesService) CreateService(c *gin.Context) { if err = s.db.Create(&service).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error creating service") - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) return } - utils.HTTPSuccess(c, http.StatusCreated, service) + response.Success(c, http.StatusCreated, service) } // PatchService is a function to update service by hash @@ -225,15 +225,15 @@ func (s *ServicesService) PatchService(c *gin.Context) { if err = c.ShouldBindJSON(&service); err != nil { utils.FromContext(c).WithError(err).Errorf("error binding JSON") - utils.HTTPError(c, srverrors.ErrServicesInvalidRequest, err) + response.Error(c, response.ErrServicesInvalidRequest, err) return } else if hash != service.Hash { utils.FromContext(c).WithError(nil).Errorf("mismatch service hash to requested one") - utils.HTTPError(c, srverrors.ErrServicesInvalidRequest, nil) + response.Error(c, response.ErrServicesInvalidRequest, nil) return } else if err = service.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating service JSON") - utils.HTTPError(c, srverrors.ErrServicesInvalidRequest, err) + response.Error(c, response.ErrServicesInvalidRequest, err) return } @@ -241,7 +241,7 @@ func (s *ServicesService) PatchService(c *gin.Context) { tid, _ := srvcontext.GetUint64(c, "tid") if rid == models.RoleExternal { utils.FromContext(c).WithError(nil).Errorf("error: no rights to patch service") - utils.HTTPError(c, srverrors.ErrNotPermitted, nil) + response.Error(c, response.ErrNotPermitted, nil) return } scope := func(db *gorm.DB) *gorm.DB { @@ -260,15 +260,15 @@ func (s *ServicesService) PatchService(c *gin.Context) { err = s.db.Scopes(scope).Select("", public_info...).Save(&service).Error if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { utils.FromContext(c).WithError(nil).Errorf("error updating service by hash '%s', service not found", hash) - utils.HTTPError(c, srverrors.ErrServicesNotFound, err) + response.Error(c, response.ErrServicesNotFound, err) return } else if err != nil { utils.FromContext(c).WithError(err).Errorf("error updating service by hash '%s'", hash) - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) return } - utils.HTTPSuccess(c, http.StatusOK, service) + response.Success(c, http.StatusOK, service) } // DeleteService is a function to delete service by hash @@ -292,7 +292,7 @@ func (s *ServicesService) DeleteService(c *gin.Context) { tid, _ := srvcontext.GetUint64(c, "tid") if rid == models.RoleExternal { utils.FromContext(c).WithError(nil).Errorf("error: no rights to delete service") - utils.HTTPError(c, srverrors.ErrNotPermitted, nil) + response.Error(c, response.ErrNotPermitted, nil) return } scope := func(db *gorm.DB) *gorm.DB { @@ -310,22 +310,22 @@ func (s *ServicesService) DeleteService(c *gin.Context) { if err = s.db.Scopes(scope).Take(&service).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding service by hash") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPError(c, srverrors.ErrServicesNotFound, err) + response.Error(c, response.ErrServicesNotFound, err) } else { - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) } return } else if err = service.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating service data '%s'", service.Hash) - utils.HTTPError(c, srverrors.ErrServicesInvalidData, err) + response.Error(c, response.ErrServicesInvalidData, err) return } if err = s.db.Delete(&service).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error deleting service by hash '%s'", hash) - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) return } - utils.HTTPSuccess(c, http.StatusOK, struct{}{}) + response.Success(c, http.StatusOK, struct{}{}) } diff --git a/pkg/app/api/server/private/tags.go b/pkg/app/api/server/private/tags.go index b0750a42..5b94fc92 100644 --- a/pkg/app/api/server/private/tags.go +++ b/pkg/app/api/server/private/tags.go @@ -10,7 +10,7 @@ import ( "soldr/pkg/app/api/client" srvcontext "soldr/pkg/app/api/server/context" - srverrors "soldr/pkg/app/api/server/response" + "soldr/pkg/app/api/server/response" "soldr/pkg/app/api/utils" ) @@ -176,27 +176,27 @@ func (s *TagService) GetTags(c *gin.Context) { if err := c.ShouldBindQuery(&query); err != nil { utils.FromContext(c).WithError(err).Errorf("error binding query") - utils.HTTPError(c, srverrors.ErrTagsInvalidRequest, err) + response.Error(c, response.ErrTagsInvalidRequest, err) return } serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } table, sqlMappers, err = getTagMappers(&query) if err != nil { utils.FromContext(c).WithError(err).Errorf("error getting tag mappers by query") - utils.HTTPError(c, srverrors.ErrTagsMappersNotFound, err) + response.Error(c, response.ErrTagsMappersNotFound, err) return } @@ -238,9 +238,9 @@ func (s *TagService) GetTags(c *gin.Context) { funcs = append(funcs, getTagJoinFuncs(table, useGroup, useModule, usePolicy)...) if resp.Total, err = query.Query(iDB, &resp.Tags, funcs...); err != nil { utils.FromContext(c).WithError(err).Errorf("error finding tags") - utils.HTTPError(c, srverrors.ErrTagsInvalidQuery, err) + response.Error(c, response.ErrTagsInvalidQuery, err) return } - utils.HTTPSuccess(c, http.StatusOK, resp) + response.Success(c, http.StatusOK, resp) } diff --git a/pkg/app/api/server/private/tenants.go b/pkg/app/api/server/private/tenants.go index 9a258090..0f7e2662 100644 --- a/pkg/app/api/server/private/tenants.go +++ b/pkg/app/api/server/private/tenants.go @@ -9,7 +9,7 @@ import ( "soldr/pkg/app/api/models" srvcontext "soldr/pkg/app/api/server/context" - srverrors "soldr/pkg/app/api/server/response" + "soldr/pkg/app/api/server/response" "soldr/pkg/app/api/utils" ) @@ -55,7 +55,7 @@ func (s *TenantService) GetTenants(c *gin.Context) { if err = c.ShouldBindQuery(&query); err != nil { utils.FromContext(c).WithError(err).Errorf("error binding query") - utils.HTTPError(c, srverrors.ErrTenantsInvalidRequest, err) + response.Error(c, response.ErrTenantsInvalidRequest, err) return } @@ -76,25 +76,25 @@ func (s *TenantService) GetTenants(c *gin.Context) { }) default: utils.FromContext(c).WithError(nil).Errorf("error filtering user role services: unexpected role") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } if resp.Total, err = query.Query(s.db, &resp.Tenants); err != nil { utils.FromContext(c).WithError(err).Errorf("error finding tenants") - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) return } for i := 0; i < len(resp.Tenants); i++ { if err = resp.Tenants[i].Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating tenant data '%s'", resp.Tenants[i].Hash) - utils.HTTPError(c, srverrors.ErrTenantsInvalidData, err) + response.Error(c, response.ErrTenantsInvalidData, err) return } } - utils.HTTPSuccess(c, http.StatusOK, resp) + response.Success(c, http.StatusOK, resp) } // GetTenant returns tenant by hash @@ -133,18 +133,18 @@ func (s *TenantService) GetTenant(c *gin.Context) { if err = s.db.Scopes(scope).Take(&resp).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding tenant by hash") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPError(c, srverrors.ErrTenantsNotFound, err) + response.Error(c, response.ErrTenantsNotFound, err) } else { - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) } return } else if err = resp.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating tenant data '%s'", resp.Hash) - utils.HTTPError(c, srverrors.ErrTenantsInvalidData, err) + response.Error(c, response.ErrTenantsInvalidData, err) return } - utils.HTTPSuccess(c, http.StatusOK, resp) + response.Success(c, http.StatusOK, resp) } // CreateTenant is a function to create new tenant @@ -166,7 +166,7 @@ func (s *TenantService) CreateTenant(c *gin.Context) { if err = c.ShouldBindJSON(&tenant); err != nil { utils.FromContext(c).WithError(err).Errorf("error binding JSON") - utils.HTTPError(c, srverrors.ErrTenantsInvalidRequest, err) + response.Error(c, response.ErrTenantsInvalidRequest, err) return } @@ -175,11 +175,11 @@ func (s *TenantService) CreateTenant(c *gin.Context) { if err = s.db.Create(&tenant).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error creating tenant") - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) return } - utils.HTTPSuccess(c, http.StatusCreated, tenant) + response.Success(c, http.StatusCreated, tenant) } // PatchTenant updates tenant by hash @@ -203,15 +203,15 @@ func (s *TenantService) PatchTenant(c *gin.Context) { if err = c.ShouldBindJSON(&tenant); err != nil { utils.FromContext(c).WithError(err).Errorf("error binding JSON") - utils.HTTPError(c, srverrors.ErrTenantsInvalidRequest, err) + response.Error(c, response.ErrTenantsInvalidRequest, err) return } else if hash != tenant.Hash { utils.FromContext(c).WithError(nil).Errorf("mismatch tenant hash to requested one") - utils.HTTPError(c, srverrors.ErrTenantsInvalidRequest, nil) + response.Error(c, response.ErrTenantsInvalidRequest, nil) return } else if err = tenant.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating tenant JSON") - utils.HTTPError(c, srverrors.ErrTenantsInvalidRequest, err) + response.Error(c, response.ErrTenantsInvalidRequest, err) return } @@ -235,15 +235,15 @@ func (s *TenantService) PatchTenant(c *gin.Context) { err = s.db.Scopes(scope).Select("", public_info...).Save(&tenant).Error if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { utils.FromContext(c).WithError(nil).Errorf("error updating tenant by hash '%s', tenant not found", hash) - utils.HTTPError(c, srverrors.ErrTenantsNotFound, err) + response.Error(c, response.ErrTenantsNotFound, err) return } else if err != nil { utils.FromContext(c).WithError(err).Errorf("error updating tenant by hash '%s'", hash) - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) return } - utils.HTTPSuccess(c, http.StatusOK, tenant) + response.Success(c, http.StatusOK, tenant) } // DeleteTenant is a function to delete tenant by hash @@ -282,22 +282,22 @@ func (s *TenantService) DeleteTenant(c *gin.Context) { if err = s.db.Scopes(scope).Take(&tenant).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding tenant by hash") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPError(c, srverrors.ErrTenantsNotFound, err) + response.Error(c, response.ErrTenantsNotFound, err) } else { - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) } return } else if err = tenant.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating tenant data '%s'", tenant.Hash) - utils.HTTPError(c, srverrors.ErrTenantsInvalidData, err) + response.Error(c, response.ErrTenantsInvalidData, err) return } if err = s.db.Delete(&tenant).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error deleting tenant by hash '%s'", hash) - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) return } - utils.HTTPSuccess(c, http.StatusOK, struct{}{}) + response.Success(c, http.StatusOK, struct{}{}) } diff --git a/pkg/app/api/server/private/upgrades.go b/pkg/app/api/server/private/upgrades.go index 97b10154..d602488b 100644 --- a/pkg/app/api/server/private/upgrades.go +++ b/pkg/app/api/server/private/upgrades.go @@ -6,6 +6,7 @@ import ( "encoding/hex" "errors" "net/http" + "time" "github.com/gin-gonic/gin" "github.com/jinzhu/gorm" @@ -13,7 +14,8 @@ import ( "soldr/pkg/app/api/client" "soldr/pkg/app/api/models" srvcontext "soldr/pkg/app/api/server/context" - srverrors "soldr/pkg/app/api/server/response" + "soldr/pkg/app/api/server/response" + useraction "soldr/pkg/app/api/user_action" "soldr/pkg/app/api/utils" "soldr/pkg/storage" ) @@ -52,14 +54,20 @@ var upgradesAgentsSQLMappers = map[string]interface{}{ } type UpgradeService struct { - db *gorm.DB - serverConnector *client.AgentServerClient + db *gorm.DB + serverConnector *client.AgentServerClient + userActionWriter useraction.Writer } -func NewUpgradeService(db *gorm.DB, serverConnector *client.AgentServerClient) *UpgradeService { +func NewUpgradeService( + db *gorm.DB, + serverConnector *client.AgentServerClient, + userActionWriter useraction.Writer, +) *UpgradeService { return &UpgradeService{ - db: db, - serverConnector: serverConnector, + db: db, + serverConnector: serverConnector, + userActionWriter: userActionWriter, } } @@ -81,20 +89,20 @@ func (s *UpgradeService) GetAgentsUpgrades(c *gin.Context) { if err := c.ShouldBindQuery(&query); err != nil { utils.FromContext(c).WithError(err).Errorf("error binding query") - utils.HTTPError(c, srverrors.ErrGetAgentsUpgradesInvalidRequest, err) + response.Error(c, response.ErrGetAgentsUpgradesInvalidRequest, err) return } serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } @@ -102,19 +110,19 @@ func (s *UpgradeService) GetAgentsUpgrades(c *gin.Context) { if resp.Total, err = query.Query(iDB, &resp.Tasks); err != nil { utils.FromContext(c).WithError(err).Errorf("error finding agents upgrades") - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) return } for i := 0; i < len(resp.Tasks); i++ { if err = resp.Tasks[i].Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating agents upgrades data '%d'", resp.Tasks[i].ID) - utils.HTTPError(c, srverrors.ErrGetAgentsUpgradesInvalidData, err) + response.Error(c, response.ErrGetAgentsUpgradesInvalidData, err) return } } - utils.HTTPSuccess(c, http.StatusOK, resp) + response.Success(c, http.StatusOK, resp) } // CreateUpgradesAgents is a function to request agents upgrades to a specific verison @@ -136,37 +144,39 @@ func (s *UpgradeService) CreateAgentsUpgrades(c *gin.Context) { query utils.TableQuery upgradeReq upgradesAgentsAction upgradeRes upgradesAgentsActionResult - uafArr = []utils.UserActionFields{ - { - Domain: "agent", - ObjectType: "agent", - ActionCode: "version update task creation", - ObjectDisplayName: utils.UnknownObjectDisplayName, - }, - } ) + tStart := time.Now() + + uaf := useraction.NewFields(c, "agent", "agent", "version update task creation", "", useraction.UnknownObjectDisplayName) + uafArr := []useraction.Fields{uaf} + defer func() { + for i := range uafArr { + s.userActionWriter.WriteUserAction(uafArr[i]) + } + }() + if err := c.ShouldBindJSON(&upgradeReq); err != nil { utils.FromContext(c).WithError(err).Errorf("error binding JSON") - utils.HTTPErrorWithUAFieldsSlice(c, srverrors.ErrCreateAgentsUpgradesInvalidRequest, err, uafArr) + response.Error(c, response.ErrCreateAgentsUpgradesInvalidRequest, err) return } serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } if sv = getService(c); sv == nil { - utils.HTTPErrorWithUAFieldsSlice(c, srverrors.ErrInternalServiceNotFound, nil, uafArr) + response.Error(c, response.ErrInternalServiceNotFound, nil) return } @@ -174,7 +184,7 @@ func (s *UpgradeService) CreateAgentsUpgrades(c *gin.Context) { batchRaw := make([]byte, 32) if _, err := rand.Read(batchRaw); err != nil { utils.FromContext(c).WithError(err).Errorf("failed to get random batch id") - utils.HTTPErrorWithUAFieldsSlice(c, srverrors.ErrInternal, err, uafArr) + response.Error(c, response.ErrInternal, err) return } batchHash := md5.Sum(batchRaw) @@ -191,11 +201,11 @@ func (s *UpgradeService) CreateAgentsUpgrades(c *gin.Context) { err = s.db.Scopes(scope).Model(&binary).Take(&binary).Error if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { utils.FromContext(c).WithError(nil).Errorf("error getting binary info by version '%s', record not found", upgradeReq.Version) - utils.HTTPErrorWithUAFieldsSlice(c, srverrors.ErrCreateAgentsUpgradesAgentNotFound, err, uafArr) + response.Error(c, response.ErrCreateAgentsUpgradesAgentNotFound, err) return } else if err != nil { utils.FromContext(c).WithError(err).Errorf("error getting binary info by version '%s'", upgradeReq.Version) - utils.HTTPErrorWithUAFieldsSlice(c, srverrors.ErrInternal, err, uafArr) + response.Error(c, response.ErrInternal, err) return } @@ -211,9 +221,10 @@ func (s *UpgradeService) CreateAgentsUpgrades(c *gin.Context) { SubQuery()).Find(&agents).Error if err != nil { utils.FromContext(c).WithError(err).Errorf("error collecting agents by filter") - utils.HTTPErrorWithUAFieldsSlice(c, srverrors.ErrPatchAgentsInvalidQuery, err, uafArr) + response.Error(c, response.ErrPatchAgentsInvalidQuery, err) } - uafArr = fillAgentUserActionFields(agents, "version update task creation") + + uafArr = fillAgentUserActionFields(c, agents, "version update task creation", tStart) sqlInsertResult := iDB.Exec("INSERT INTO upgrade_tasks(agent_id, version, batch) ?", iDB. Scopes(agentsScope). @@ -228,7 +239,7 @@ func (s *UpgradeService) CreateAgentsUpgrades(c *gin.Context) { if err = sqlInsertResult.Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error inserting new upgrade tasks into the table") - utils.HTTPErrorWithUAFieldsSlice(c, srverrors.ErrCreateAgentsUpgradesCreateTaskFail, err, uafArr) + response.Error(c, response.ErrCreateAgentsUpgradesCreateTaskFail, err) return } @@ -236,19 +247,19 @@ func (s *UpgradeService) CreateAgentsUpgrades(c *gin.Context) { s3, err := storage.NewS3(sv.Info.S3.ToS3ConnParams()) if err != nil { utils.FromContext(c).WithError(err).Errorf("error openning connection to S3") - utils.HTTPErrorWithUAFieldsSlice(c, srverrors.ErrInternal, err, uafArr) + response.Error(c, response.ErrInternal, err) return } if err = utils.UploadAgentBinariesToInstBucket(binary, s3); err != nil { utils.FromContext(c).WithError(err).Errorf("error uploading agent binaries to S3 instance bucket") - utils.HTTPErrorWithUAFieldsSlice(c, srverrors.ErrCreateAgentsUpgradesUpdateAgentBinariesFail, err, uafArr) + response.Error(c, response.ErrCreateAgentsUpgradesUpdateAgentBinariesFail, err) return } } upgradeRes.Total = sqlInsertResult.RowsAffected - utils.HTTPSuccessWithUAFieldsSlice(c, http.StatusCreated, upgradeRes, uafArr) + response.Success(c, http.StatusCreated, upgradeRes) } // GetLastUpgradeAgent is a function to return last agent upgrade information @@ -271,13 +282,13 @@ func (s *UpgradeService) GetLastAgentUpgrade(c *gin.Context) { serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } @@ -291,21 +302,21 @@ func (s *UpgradeService) GetLastAgentUpgrade(c *gin.Context) { if err = sqlQueryResult.Error; err != nil || sqlQueryResult.RowsAffected == 0 { utils.FromContext(c).WithError(err).Errorf("error finding last agent upgrade information") - utils.HTTPError(c, srverrors.ErrGetLastAgentUpgradeLastUpgradeNotFound, err) + response.Error(c, response.ErrGetLastAgentUpgradeLastUpgradeNotFound, err) return } else if err = resp.Task.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating last agent upgrade data '%d'", resp.Task.ID) - utils.HTTPError(c, srverrors.ErrGetLastAgentUpgradeInvalidLastData, err) + response.Error(c, response.ErrGetLastAgentUpgradeInvalidLastData, err) return } if err = iDB.Take(&resp.Details.Agent, "id = ?", resp.Task.AgentID).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding agent") - utils.HTTPError(c, srverrors.ErrGetLastAgentUpgradeAgentNotFound, err) + response.Error(c, response.ErrGetLastAgentUpgradeAgentNotFound, err) return } else if err = resp.Details.Agent.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating agent data '%s'", resp.Details.Agent.Hash) - utils.HTTPError(c, srverrors.ErrGetLastAgentUpgradeInvalidAgentData, err) + response.Error(c, response.ErrGetLastAgentUpgradeInvalidAgentData, err) return } @@ -313,16 +324,16 @@ func (s *UpgradeService) GetLastAgentUpgrade(c *gin.Context) { resp.Details.Group = &models.Group{} if err = iDB.Take(resp.Details.Group, "id = ?", resp.Details.Agent.GroupID).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding group") - utils.HTTPError(c, srverrors.ErrGetLastAgentUpgradeGroupNotFound, err) + response.Error(c, response.ErrGetLastAgentUpgradeGroupNotFound, err) return } else if err = resp.Details.Group.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating group data '%s'", resp.Details.Group.Hash) - utils.HTTPError(c, srverrors.ErrGetLastAgentUpgradeInvalidGroupData, err) + response.Error(c, response.ErrGetLastAgentUpgradeInvalidGroupData, err) return } } - utils.HTTPSuccess(c, http.StatusOK, resp) + response.Success(c, http.StatusOK, resp) } // PatchLastAgentUpgrade is a function to update last agent upgrade information @@ -346,24 +357,20 @@ func (s *UpgradeService) PatchLastAgentUpgrade(c *gin.Context) { sv *models.Service task models.AgentUpgradeTask ) - uaf := utils.UserActionFields{ - Domain: "agent", - ObjectType: "agent", - ActionCode: "undefined action", - ObjectId: hash, - ObjectDisplayName: utils.UnknownObjectDisplayName, - } + + uaf := useraction.NewFields(c, "agent", "agent", "undefined action", hash, useraction.UnknownObjectDisplayName) + defer s.userActionWriter.WriteUserAction(uaf) serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } @@ -376,7 +383,7 @@ func (s *UpgradeService) PatchLastAgentUpgrade(c *gin.Context) { uaf.ObjectDisplayName = name } utils.FromContext(c).WithError(err).Errorf("error binding JSON") - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchLastAgentUpgradeInvalidAgentUpgradeInfo, err, uaf) + response.Error(c, response.ErrPatchLastAgentUpgradeInvalidAgentUpgradeInfo, err) return } if task.Status == "failed" && task.Reason == "Canceled.By.User" { @@ -387,21 +394,21 @@ func (s *UpgradeService) PatchLastAgentUpgrade(c *gin.Context) { if err = iDB.Take(&agent, "id = ?", task.AgentID).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding agent") - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchLastAgentUpgradeAgentNotFound, err, uaf) + response.Error(c, response.ErrPatchLastAgentUpgradeAgentNotFound, err) return } else if err = agent.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating agent data '%s'", agent.Hash) - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchLastAgentUpgradeInvalidAgentData, err, uaf) + response.Error(c, response.ErrPatchLastAgentUpgradeInvalidAgentData, err) return } else if hash != agent.Hash { utils.FromContext(c).WithError(nil).Errorf("mismatch agent hash to requested one") - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchLastAgentUpgradeInvalidAgentUpgradeInfo, err, uaf) + response.Error(c, response.ErrPatchLastAgentUpgradeInvalidAgentUpgradeInfo, err) return } uaf.ObjectDisplayName = agent.Description if sv = getService(c); sv == nil { - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternalServiceNotFound, nil, uaf) + response.Error(c, response.ErrInternalServiceNotFound, nil) return } @@ -419,24 +426,24 @@ func (s *UpgradeService) PatchLastAgentUpgrade(c *gin.Context) { err = s.db.Scopes(scope).Model(&binary).Take(&binary).Error if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { utils.FromContext(c).WithError(nil).Errorf("error getting binary info by version '%s', record not found", task.Version) - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchLastAgentUpgradeAgentBinaryNotFound, err, uaf) + response.Error(c, response.ErrPatchLastAgentUpgradeAgentBinaryNotFound, err) return } else if err != nil { utils.FromContext(c).WithError(err).Errorf("error getting binary info by version '%s'", task.Version) - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } s3, err := storage.NewS3(sv.Info.S3.ToS3ConnParams()) if err != nil { utils.FromContext(c).WithError(err).Errorf("error openning connection to S3") - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } if err = utils.UploadAgentBinariesToInstBucket(binary, s3); err != nil { utils.FromContext(c).WithError(err).Errorf("error uploading agent binaries to S3 instance bucket") - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchLastAgentUpgradeUpdateAgentBinariesFail, err, uaf) + response.Error(c, response.ErrPatchLastAgentUpgradeUpdateAgentBinariesFail, err) return } } @@ -452,13 +459,13 @@ func (s *UpgradeService) PatchLastAgentUpgrade(c *gin.Context) { err = iDB.Model(&task).UpdateColumns(update_info).Error if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { utils.FromContext(c).WithError(nil).Errorf("error updating last agent upgrade information by id '%d', task not found", task.ID) - utils.HTTPErrorWithUAFields(c, srverrors.ErrPatchLastAgentUpgradeLastUpgradeInfoNotFound, err, uaf) + response.Error(c, response.ErrPatchLastAgentUpgradeLastUpgradeInfoNotFound, err) return } else if err != nil { utils.FromContext(c).WithError(err).Errorf("error updating last agent upgrade information by id '%d'", task.ID) - utils.HTTPErrorWithUAFields(c, srverrors.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } - utils.HTTPSuccessWithUAFields(c, http.StatusOK, task, uaf) + response.Success(c, http.StatusOK, task) } diff --git a/pkg/app/api/server/private/users.go b/pkg/app/api/server/private/users.go index 90ae719c..b758faed 100644 --- a/pkg/app/api/server/private/users.go +++ b/pkg/app/api/server/private/users.go @@ -10,7 +10,7 @@ import ( "soldr/pkg/app/api/models" srvcontext "soldr/pkg/app/api/server/context" - srverrors "soldr/pkg/app/api/server/response" + "soldr/pkg/app/api/server/response" "soldr/pkg/app/api/utils" ) @@ -66,18 +66,18 @@ func (s *UserService) GetCurrentUser(c *gin.Context) { if err != nil { utils.FromContext(c).WithError(err).Errorf("error finding current user") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPError(c, srverrors.ErrUsersNotFound, err) + response.Error(c, response.ErrUsersNotFound, err) } else { - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) } return } else if err = resp.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating user data '%s'", resp.Hash) - utils.HTTPError(c, srverrors.ErrUsersInvalidData, err) + response.Error(c, response.ErrUsersInvalidData, err) return } - utils.HTTPSuccess(c, http.StatusOK, resp) + response.Success(c, http.StatusOK, resp) } // ChangePasswordCurrentUser is a function to update account password @@ -105,7 +105,7 @@ func (s *UserService) ChangePasswordCurrentUser(c *gin.Context) { err = form.Valid() } utils.FromContext(c).WithError(err).Errorf("error binding JSON") - utils.HTTPError(c, srverrors.ErrChangePasswordCurrentUserInvalidPassword, err) + response.Error(c, response.ErrChangePasswordCurrentUserInvalidPassword, err) return } @@ -117,26 +117,26 @@ func (s *UserService) ChangePasswordCurrentUser(c *gin.Context) { if err = s.db.Scopes(scope).Take(&user).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding current user") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPError(c, srverrors.ErrUsersNotFound, err) + response.Error(c, response.ErrUsersNotFound, err) } else { - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) } return } else if err = user.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating user data '%s'", user.Hash) - utils.HTTPError(c, srverrors.ErrUsersInvalidData, err) + response.Error(c, response.ErrUsersInvalidData, err) return } if err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(form.CurrentPassword)); err != nil { utils.FromContext(c).WithError(err).Errorf("error checking password for current user") - utils.HTTPError(c, srverrors.ErrChangePasswordCurrentUserInvalidCurrentPassword, err) + response.Error(c, response.ErrChangePasswordCurrentUserInvalidCurrentPassword, err) return } if encPass, err = utils.EncryptPassword(form.Password); err != nil { utils.FromContext(c).WithError(err).Errorf("error making new password for current user") - utils.HTTPError(c, srverrors.ErrChangePasswordCurrentUserInvalidNewPassword, err) + response.Error(c, response.ErrChangePasswordCurrentUserInvalidNewPassword, err) return } user.Password = string(encPass) @@ -144,11 +144,11 @@ func (s *UserService) ChangePasswordCurrentUser(c *gin.Context) { if err = s.db.Scopes(scope).Select("password", "password_change_required").Save(&user).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error updating password for current user") - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) return } - utils.HTTPSuccess(c, http.StatusOK, struct{}{}) + response.Success(c, http.StatusOK, struct{}{}) } // GetUsers returns users list @@ -174,7 +174,7 @@ func (s *UserService) GetUsers(c *gin.Context) { if err = c.ShouldBindQuery(&query); err != nil { utils.FromContext(c).WithError(err).Errorf("error binding query") - utils.HTTPError(c, srverrors.ErrUsersInvalidRequest, err) + response.Error(c, response.ErrUsersInvalidRequest, err) return } @@ -200,13 +200,13 @@ func (s *UserService) GetUsers(c *gin.Context) { }) default: utils.FromContext(c).WithError(nil).Errorf("error filtering user role services: unexpected role") - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) return } if resp.Total, err = query.Query(s.db, &resp.Users); err != nil { utils.FromContext(c).WithError(err).Errorf("error finding users") - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) return } @@ -217,13 +217,13 @@ func (s *UserService) GetUsers(c *gin.Context) { if err = s.db.Find(&roles, "id IN (?)", rids).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding linked roles") - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) return } if err = s.db.Find(&tenans, "id IN (?)", tids).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding linked tenants") - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) return } @@ -248,12 +248,12 @@ func (s *UserService) GetUsers(c *gin.Context) { for i := 0; i < len(resp.Users); i++ { if err = resp.Users[i].Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating user data '%s'", resp.Users[i].Hash) - utils.HTTPError(c, srverrors.ErrUsersInvalidData, err) + response.Error(c, response.ErrUsersInvalidData, err) return } } - utils.HTTPSuccess(c, http.StatusOK, resp) + response.Success(c, http.StatusOK, resp) } // GetUser is a function to return user by hash @@ -293,28 +293,28 @@ func (s *UserService) GetUser(c *gin.Context) { if err = s.db.Scopes(scope).Take(&resp.User).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding user by hash") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPError(c, srverrors.ErrUsersNotFound, err) + response.Error(c, response.ErrUsersNotFound, err) } else { - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) } return } if err = s.db.Model(&resp.User).Related(&resp.Role).Related(&resp.Tenant).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding related models by user hash") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPError(c, srverrors.ErrGetUserModelsNotFound, err) + response.Error(c, response.ErrGetUserModelsNotFound, err) } else { - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) } return } if err = resp.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating user data '%s'", resp.Hash) - utils.HTTPError(c, srverrors.ErrUsersInvalidData, err) + response.Error(c, response.ErrUsersInvalidData, err) return } - utils.HTTPSuccess(c, http.StatusOK, resp) + response.Success(c, http.StatusOK, resp) } // CreateUser is a function to create new user @@ -338,7 +338,7 @@ func (s *UserService) CreateUser(c *gin.Context) { if err = c.ShouldBindJSON(&user); err != nil { utils.FromContext(c).WithError(err).Errorf("error binding JSON") - utils.HTTPError(c, srverrors.ErrUsersInvalidRequest, err) + response.Error(c, response.ErrUsersInvalidRequest, err) return } @@ -356,7 +356,7 @@ func (s *UserService) CreateUser(c *gin.Context) { user.TenantID = tid default: utils.FromContext(c).WithError(nil).Errorf("error filtering user role services: unexpected role") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } @@ -364,13 +364,13 @@ func (s *UserService) CreateUser(c *gin.Context) { user.Hash = utils.MakeUserHash(user.Name) if err = user.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating user") - utils.HTTPError(c, srverrors.ErrCreateUserInvalidUser, err) + response.Error(c, response.ErrCreateUserInvalidUser, err) return } if encPassword, err = utils.EncryptPassword(user.Password); err != nil { utils.FromContext(c).WithError(err).Errorf("error encoding password") - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) return } else { user.Password = string(encPassword) @@ -378,7 +378,7 @@ func (s *UserService) CreateUser(c *gin.Context) { if err = s.db.Create(&user).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error creating user") - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) return } @@ -387,15 +387,15 @@ func (s *UserService) CreateUser(c *gin.Context) { Related(&resp.Tenant).Error if err != nil { utils.FromContext(c).WithError(err).Errorf("error finding user by hash") - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) return } else if err = resp.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating user data '%s'", resp.Hash) - utils.HTTPError(c, srverrors.ErrUsersInvalidData, err) + response.Error(c, response.ErrUsersInvalidData, err) return } - utils.HTTPSuccess(c, http.StatusCreated, resp) + response.Success(c, http.StatusCreated, resp) } // PatchUser is a function to update user by hash @@ -420,19 +420,19 @@ func (s *UserService) PatchUser(c *gin.Context) { if err = c.ShouldBindJSON(&user); err != nil { utils.FromContext(c).WithError(err).Errorf("error binding JSON") - utils.HTTPError(c, srverrors.ErrUsersInvalidRequest, err) + response.Error(c, response.ErrUsersInvalidRequest, err) return } else if hash != user.Hash { utils.FromContext(c).WithError(nil).Errorf("mismatch user hash to requested one") - utils.HTTPError(c, srverrors.ErrUsersInvalidRequest, nil) + response.Error(c, response.ErrUsersInvalidRequest, nil) return } else if err = user.User.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating user JSON") - utils.HTTPError(c, srverrors.ErrUsersInvalidRequest, err) + response.Error(c, response.ErrUsersInvalidRequest, err) return } else if err = user.Valid(); user.Password != "" && err != nil { utils.FromContext(c).WithError(err).Errorf("error validating user password") - utils.HTTPError(c, srverrors.ErrUsersInvalidRequest, err) + response.Error(c, response.ErrUsersInvalidRequest, err) return } @@ -457,7 +457,7 @@ func (s *UserService) PatchUser(c *gin.Context) { if user.Password != "" { if encPassword, err := utils.EncryptPassword(user.Password); err != nil { utils.FromContext(c).WithError(err).Errorf("error encoding password") - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) return } else { user.Password = string(encPassword) @@ -470,39 +470,39 @@ func (s *UserService) PatchUser(c *gin.Context) { if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { utils.FromContext(c).WithError(nil).Errorf("error updating user by hash '%s', user not found", hash) - utils.HTTPError(c, srverrors.ErrUsersNotFound, err) + response.Error(c, response.ErrUsersNotFound, err) return } else if err != nil { utils.FromContext(c).WithError(err).Errorf("error updating user by hash '%s'", hash) - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) return } if err = s.db.Scopes(scope).Take(&resp.User).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding user by hash") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPError(c, srverrors.ErrUsersNotFound, err) + response.Error(c, response.ErrUsersNotFound, err) } else { - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) } return } if err = s.db.Model(&resp.User).Related(&resp.Role).Related(&resp.Tenant).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding related models by user hash") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPError(c, srverrors.ErrPatchUserModelsNotFound, err) + response.Error(c, response.ErrPatchUserModelsNotFound, err) } else { - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) } return } if err = resp.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating user data '%s'", resp.Hash) - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) return } - utils.HTTPSuccess(c, http.StatusOK, resp) + response.Success(c, http.StatusOK, resp) } // DeleteUser is a function to delete user by hash @@ -542,32 +542,32 @@ func (s *UserService) DeleteUser(c *gin.Context) { if err = s.db.Scopes(scope).Take(&user.User).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding user by hash") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPError(c, srverrors.ErrUsersNotFound, err) + response.Error(c, response.ErrUsersNotFound, err) } else { - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) } return } if err = s.db.Model(&user.User).Related(&user.Role).Related(&user.Tenant).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error finding related models by user hash") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPError(c, srverrors.ErrDeleteUserModelsNotFound, err) + response.Error(c, response.ErrDeleteUserModelsNotFound, err) } else { - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) } return } if err = user.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating user data '%s'", user.Hash) - utils.HTTPError(c, srverrors.ErrUsersInvalidData, err) + response.Error(c, response.ErrUsersInvalidData, err) return } if err = s.db.Delete(&user.User).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error deleting user by hash '%s'", hash) - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) return } - utils.HTTPSuccess(c, http.StatusOK, struct{}{}) + response.Success(c, http.StatusOK, struct{}{}) } diff --git a/pkg/app/api/server/private/versions.go b/pkg/app/api/server/private/versions.go index 7d4ed319..a4e21ccb 100644 --- a/pkg/app/api/server/private/versions.go +++ b/pkg/app/api/server/private/versions.go @@ -9,7 +9,7 @@ import ( "soldr/pkg/app/api/client" srvcontext "soldr/pkg/app/api/server/context" - srverrors "soldr/pkg/app/api/server/response" + "soldr/pkg/app/api/server/response" "soldr/pkg/app/api/utils" ) @@ -83,27 +83,27 @@ func (s *VersionService) GetVersions(c *gin.Context) { if err := c.ShouldBindQuery(&query); err != nil { utils.FromContext(c).WithError(err).Errorf("error binding query") - utils.HTTPError(c, srverrors.ErrVersionsInvalidRequest, err) + response.Error(c, response.ErrVersionsInvalidRequest, err) return } serviceHash, ok := srvcontext.GetString(c, "svc") if !ok { utils.FromContext(c).Errorf("could not get service hash") - utils.HTTPError(c, srverrors.ErrInternal, nil) + response.Error(c, response.ErrInternal, nil) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, err) + response.Error(c, response.ErrInternalDBNotFound, err) return } table, sqlMappers, err = getVersionMappers(&query) if err != nil { utils.FromContext(c).WithError(err).Errorf("error getting version mappers by query") - utils.HTTPError(c, srverrors.ErrVersionsMapperNotFound, err) + response.Error(c, response.ErrVersionsMapperNotFound, err) return } @@ -131,9 +131,9 @@ func (s *VersionService) GetVersions(c *gin.Context) { if resp.Total, err = query.Query(iDB, &resp.Versions, funcs...); err != nil { utils.FromContext(c).WithError(err).Errorf("error finding versions") - utils.HTTPError(c, srverrors.ErrVersionsInvalidQuery, err) + response.Error(c, response.ErrVersionsInvalidQuery, err) return } - utils.HTTPSuccess(c, http.StatusOK, resp) + response.Success(c, http.StatusOK, resp) } diff --git a/pkg/app/api/server/proto/proto.go b/pkg/app/api/server/proto/proto.go index 3aeffe33..803e41be 100644 --- a/pkg/app/api/server/proto/proto.go +++ b/pkg/app/api/server/proto/proto.go @@ -23,6 +23,7 @@ import ( srvcontext "soldr/pkg/app/api/server/context" "soldr/pkg/app/api/server/proto/vm" "soldr/pkg/app/api/server/response" + useraction "soldr/pkg/app/api/user_action" "soldr/pkg/app/api/utils" "soldr/pkg/hardening/luavm/certs" vxcommonVM "soldr/pkg/hardening/luavm/vm" @@ -207,9 +208,8 @@ func sendAuthResp(ctx context.Context, conn vxproto.IConnection, authRespMessage return nil } -func wsConnectToVXServer(c *gin.Context, connType vxproto.AgentType, sockID, sockType string, uaf utils.UserActionFields) { +func wsConnectToVXServer(c *gin.Context, connType vxproto.AgentType, sockID, sockType string, uaf useraction.Fields) { var ( - err error serverConn *socket sv *models.Service validate = models.GetValidator() @@ -222,37 +222,37 @@ func wsConnectToVXServer(c *gin.Context, connType vxproto.AgentType, sockID, soc }) if err := validate.Var(sockID, "len=32,hexadecimal,lowercase,required"); err != nil { - logger.WithError(err).Error("failed to validate sock ID (agent or group)") - utils.HTTPErrorWithUAFields(c, response.ErrProtoInvalidAgentID, err, uaf) + logger.WithError(err).Error("failed to validate agent ID") + response.Error(c, response.ErrProtoInvalidAgentID, err) return } if val, ok := c.Get("SV"); !ok { logger.Error("error getting vxservice instance from context") - utils.HTTPErrorWithUAFields(c, response.ErrProtoNoServiceInfo, nil, uaf) + response.Error(c, response.ErrProtoNoServiceInfo, nil) return } else if sv = val.(*models.Service); sv == nil { logger.Error("got nil value vxservice instance from context") - utils.HTTPErrorWithUAFields(c, response.ErrProtoNoServiceInfo, nil, uaf) + response.Error(c, response.ErrProtoNoServiceInfo, nil) return } agentInfo, err := system.GetAgentInfo(c) if err != nil { logger.WithError(err).Error("failed to get the agent info") - utils.HTTPErrorWithUAFields(c, response.ErrProtoNoServiceInfo, err, uaf) + response.Error(c, response.ErrProtoNoServiceInfo, err) return } logger.Debug("try prepareClientWSConn") clientConn, err := prepareClientWSConn(c.Writer, c.Request) if err != nil { logger.WithError(err).Error("failed to upgrade to websockets") - utils.HTTPErrorWithUAFields(c, response.ErrProtoUpgradeFail, err, uaf) + response.Error(c, response.ErrProtoUpgradeFail, err) return } defer clientConn.Close(c.Request.Context()) - defer func(uaFields *utils.UserActionFields) { - c.Set("uaf", []utils.UserActionFields{*uaFields}) + defer func(uaFields *useraction.Fields) { + c.Set("uaf", []useraction.Fields{*uaFields}) }(&uaf) logger.Debug("try recvAuthReq") @@ -345,37 +345,45 @@ func getServiceHash(c *gin.Context) (string, error) { } type ProtoService struct { - db *gorm.DB - serverConnector *client.AgentServerClient + db *gorm.DB + serverConnector *client.AgentServerClient + userActionWriter useraction.Writer } -func NewProtoService(db *gorm.DB, serverConnector *client.AgentServerClient) *ProtoService { +func NewProtoService( + db *gorm.DB, + serverConnector *client.AgentServerClient, + userActionWriter useraction.Writer, +) *ProtoService { return &ProtoService{ - db: db, - serverConnector: serverConnector, + db: db, + serverConnector: serverConnector, + userActionWriter: userActionWriter, } } func (s *ProtoService) AggregateWSConnect(c *gin.Context) { sockID := c.Param("group_id") - uaf := utils.UserActionFields{ + + uaf := useraction.Fields{ Domain: "agent", ObjectType: "agent", - ObjectId: sockID, + ObjectID: sockID, ActionCode: "interactive interaction", - ObjectDisplayName: utils.UnknownObjectDisplayName, + ObjectDisplayName: useraction.UnknownObjectDisplayName, } + defer s.userActionWriter.WriteUserAction(uaf) serviceHash, err := getServiceHash(c) if err != nil { utils.FromContext(c).WithError(err).Errorf("could not get service hash") - utils.HTTPErrorWithUAFields(c, response.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPErrorWithUAFields(c, response.ErrInternalDBNotFound, err, uaf) + response.Error(c, response.ErrInternalDBNotFound, err) return } @@ -385,17 +393,17 @@ func (s *ProtoService) AggregateWSConnect(c *gin.Context) { } else { utils.FromContext(c).WithError(err).Errorf("error finding group by hash") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPErrorWithUAFields(c, response.ErrAgentsNotFound, nil, uaf) - } else { - utils.HTTPErrorWithUAFields(c, response.ErrInternal, err, uaf) + response.Error(c, response.ErrAgentsNotFound, nil) + return } + response.Error(c, response.ErrInternal, err) return } sockType, ok := srvcontext.GetString(c, "cpt") if !ok || sockType != "aggregate" { utils.FromContext(c).WithError(nil).Errorf("mismatch socket type to incoming token type") - utils.HTTPErrorWithUAFields(c, response.ErrProtoSockMismatch, nil, uaf) + response.Error(c, response.ErrProtoSockMismatch, nil) return } @@ -404,24 +412,26 @@ func (s *ProtoService) AggregateWSConnect(c *gin.Context) { func (s *ProtoService) BrowserWSConnect(c *gin.Context) { sockID := c.Param("agent_id") - uaf := utils.UserActionFields{ + + uaf := useraction.Fields{ Domain: "agent", ObjectType: "agent", - ObjectId: sockID, + ObjectID: sockID, ActionCode: "interactive interaction", - ObjectDisplayName: utils.UnknownObjectDisplayName, + ObjectDisplayName: useraction.UnknownObjectDisplayName, } + defer s.userActionWriter.WriteUserAction(uaf) serviceHash, err := getServiceHash(c) if err != nil { utils.FromContext(c).WithError(err).Errorf("could not get service hash") - utils.HTTPErrorWithUAFields(c, response.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPErrorWithUAFields(c, response.ErrInternalDBNotFound, err, uaf) + response.Error(c, response.ErrInternalDBNotFound, err) return } @@ -431,17 +441,18 @@ func (s *ProtoService) BrowserWSConnect(c *gin.Context) { } else { utils.FromContext(c).WithError(err).Errorf("error finding agent by hash") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPErrorWithUAFields(c, response.ErrAgentsNotFound, nil, uaf) - } else { - utils.HTTPErrorWithUAFields(c, response.ErrInternal, err, uaf) + response.Error(c, response.ErrAgentsNotFound, nil) + return } + + response.Error(c, response.ErrInternal, err) return } sockType, ok := srvcontext.GetString(c, "cpt") if !ok || sockType != "browser" { utils.FromContext(c).WithError(nil).Errorf("mismatch socket type to incoming token type") - utils.HTTPErrorWithUAFields(c, response.ErrProtoSockMismatch, nil, uaf) + response.Error(c, response.ErrProtoSockMismatch, nil) return } @@ -450,24 +461,25 @@ func (s *ProtoService) BrowserWSConnect(c *gin.Context) { func (s *ProtoService) ExternalWSConnect(c *gin.Context) { sockID := c.Param("agent_id") - uaf := utils.UserActionFields{ + uaf := useraction.Fields{ Domain: "agent", ObjectType: "agent", - ObjectId: sockID, + ObjectID: sockID, ActionCode: "interactive interaction", - ObjectDisplayName: utils.UnknownObjectDisplayName, + ObjectDisplayName: useraction.UnknownObjectDisplayName, } + defer s.userActionWriter.WriteUserAction(uaf) serviceHash, err := getServiceHash(c) if err != nil { utils.FromContext(c).WithError(err).Errorf("could not get service hash") - utils.HTTPErrorWithUAFields(c, response.ErrInternal, err, uaf) + response.Error(c, response.ErrInternal, err) return } iDB, err := s.serverConnector.GetDB(c, serviceHash) if err != nil { utils.FromContext(c).WithError(err).Error() - utils.HTTPErrorWithUAFields(c, response.ErrInternalDBNotFound, err, uaf) + response.Error(c, response.ErrInternalDBNotFound, err) return } @@ -477,17 +489,17 @@ func (s *ProtoService) ExternalWSConnect(c *gin.Context) { } else { utils.FromContext(c).WithError(err).Errorf("error finding agent by hash") if errors.Is(err, gorm.ErrRecordNotFound) { - utils.HTTPErrorWithUAFields(c, response.ErrAgentsNotFound, nil, uaf) - } else { - utils.HTTPErrorWithUAFields(c, response.ErrInternal, err, uaf) + response.Error(c, response.ErrAgentsNotFound, nil) + return } + response.Error(c, response.ErrInternal, err) return } sockType, ok := srvcontext.GetString(c, "cpt") if !ok || sockType != "external" { utils.FromContext(c).WithError(nil).Errorf("mismatch socket type to incoming token type") - utils.HTTPErrorWithUAFields(c, response.ErrProtoSockMismatch, nil, uaf) + response.Error(c, response.ErrProtoSockMismatch, nil) return } diff --git a/pkg/app/api/server/public/auth.go b/pkg/app/api/server/public/auth.go index 2fdf2e54..a8bf118d 100644 --- a/pkg/app/api/server/public/auth.go +++ b/pkg/app/api/server/public/auth.go @@ -16,7 +16,7 @@ import ( "soldr/pkg/app/api/models" "soldr/pkg/app/api/server/context" - srverrors "soldr/pkg/app/api/server/response" + "soldr/pkg/app/api/server/response" "soldr/pkg/app/api/utils" ) @@ -47,61 +47,61 @@ func AuthLogin(c *gin.Context) { err = data.Valid() } utils.FromContext(c).WithError(err).Errorf("error validating request data") - utils.HTTPError(c, srverrors.ErrAuthInvalidLoginRequest, err) + response.Error(c, response.ErrAuthInvalidLoginRequest, err) return } if gDB = utils.GetGormDB(c, "gDB"); gDB == nil { - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, nil) + response.Error(c, response.ErrInternalDBNotFound, nil) return } if err = gDB.Take(&user, "(mail = ? OR name = ?) AND password IS NOT NULL", data.Mail, data.Mail).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error getting user by mail '%s'", data.Mail) - utils.HTTPError(c, srverrors.ErrAuthInvalidCredentials, err) + response.Error(c, response.ErrAuthInvalidCredentials, err) return } else if err = user.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating user data '%s'", user.Hash) - utils.HTTPError(c, srverrors.ErrAuthInvalidUserData, err) + response.Error(c, response.ErrAuthInvalidUserData, err) return } else if user.RoleID == 100 { utils.FromContext(c).WithError(err).Errorf("can't authorize external user '%s'", user.Hash) - utils.HTTPError(c, srverrors.ErrAuthInvalidUserData, fmt.Errorf("user is external")) + response.Error(c, response.ErrAuthInvalidUserData, fmt.Errorf("user is external")) return } if err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(data.Password)); err != nil { utils.FromContext(c).Errorf("error matching user input password") - utils.HTTPError(c, srverrors.ErrAuthInvalidCredentials, err) + response.Error(c, response.ErrAuthInvalidCredentials, err) return } if user.Status != "active" { utils.FromContext(c).Errorf("error checking active state for user '%s'", user.Status) - utils.HTTPError(c, srverrors.ErrAuthInactiveUser, fmt.Errorf("user is inactive")) + response.Error(c, response.ErrAuthInactiveUser, fmt.Errorf("user is inactive")) return } if service, err = getService(c, gDB, data.Service, &user.User); err != nil { utils.FromContext(c).WithError(err).Errorf("error loading service data by hash '%s'", data.Service) - utils.HTTPError(c, srverrors.ErrAuthInvalidServiceData, err) + response.Error(c, response.ErrAuthInvalidServiceData, err) return } else if err = service.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating service data '%s'", service.Hash) - utils.HTTPError(c, srverrors.ErrAuthInvalidServiceData, err) + response.Error(c, response.ErrAuthInvalidServiceData, err) return } if err = gDB.Table("privileges").Where("role_id = ?", user.RoleID).Pluck("name", &privs).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error getting user privileges list '%s'", user.Hash) - utils.HTTPError(c, srverrors.ErrAuthInvalidServiceData, err) + response.Error(c, response.ErrAuthInvalidServiceData, err) return } uuid, err := utils.MakeUuidStrFromHash(user.Hash) if err != nil { utils.FromContext(c).WithError(err).Errorf("error validating user data '%s'", user.Hash) - utils.HTTPError(c, srverrors.ErrAuthInvalidUserData, err) + response.Error(c, response.ErrAuthInvalidUserData, err) return } @@ -138,7 +138,7 @@ func AuthLogin(c *gin.Context) { }). Infof("user made successful local login for '%s'", data.Mail) - utils.HTTPSuccess(c, http.StatusOK, struct{}{}) + response.Success(c, http.StatusOK, struct{}{}) } // AuthLogout is function to logout current user @@ -195,12 +195,12 @@ func AuthSwitchService(c *gin.Context) { serviceHash := c.PostForm("service") if err := models.GetValidator().Var(serviceHash, "len=32,hexadecimal,lowercase,required"); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating input data") - utils.HTTPError(c, srverrors.ErrAuthInvalidSwitchServiceHash, err) + response.Error(c, response.ErrAuthInvalidSwitchServiceHash, err) return } if gDB = utils.GetGormDB(c, "gDB"); gDB == nil { - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, nil) + response.Error(c, response.ErrInternalDBNotFound, nil) return } @@ -210,21 +210,21 @@ func AuthSwitchService(c *gin.Context) { if err = gDB.Take(&tenant, "id = ?", tid).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error loading tenant data '%d'", tid) - utils.HTTPError(c, srverrors.ErrAuthInvalidTenantData, err) + response.Error(c, response.ErrAuthInvalidTenantData, err) return } else if err = tenant.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating tenant data '%d:%s'", tid, tenant.Hash) - utils.HTTPError(c, srverrors.ErrAuthInvalidTenantData, err) + response.Error(c, response.ErrAuthInvalidTenantData, err) return } if err = gDB.Take(&service, "hash LIKE ? AND status = 'active'", serviceHash).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error loading service data '%s'", serviceHash) - utils.HTTPError(c, srverrors.ErrAuthInvalidServiceData, err) + response.Error(c, response.ErrAuthInvalidServiceData, err) return } else if err = service.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating service data '%s'", serviceHash) - utils.HTTPError(c, srverrors.ErrAuthInvalidServiceData, err) + response.Error(c, response.ErrAuthInvalidServiceData, err) return } @@ -253,7 +253,7 @@ func AuthSwitchService(c *gin.Context) { Infof("session was refreshed and service was switched to '%s'", serviceHash) service.Info = nil - utils.HTTPSuccess(c, http.StatusOK, service) + response.Success(c, http.StatusOK, service) } func resetSession(c *gin.Context) { diff --git a/pkg/app/api/server/public/info.go b/pkg/app/api/server/public/info.go index 77f53983..0c6422e3 100644 --- a/pkg/app/api/server/public/info.go +++ b/pkg/app/api/server/public/info.go @@ -10,7 +10,7 @@ import ( "github.com/sirupsen/logrus" "soldr/pkg/app/api/models" - srverrors "soldr/pkg/app/api/server/response" + "soldr/pkg/app/api/server/response" "soldr/pkg/app/api/utils" "soldr/pkg/version" ) @@ -86,7 +86,7 @@ func Info(c *gin.Context) { ) if gDB = utils.GetGormDB(c, "gDB"); gDB == nil { - utils.HTTPError(c, srverrors.ErrInternalDBNotFound, nil) + response.Error(c, response.ErrInternalDBNotFound, nil) return } @@ -117,23 +117,23 @@ func Info(c *gin.Context) { err = gDB.Take(&resp.User, "id = ?", uid). Related(&resp.Role).Related(&resp.Tenant).Error if err != nil { - utils.HTTPError(c, srverrors.ErrInfoUserNotFound, err) + response.Error(c, response.ErrInfoUserNotFound, err) return } else if err = resp.User.Valid(); err != nil { utils.FromContext(c).WithError(err).Errorf("error validating user data '%s'", resp.User.Hash) - utils.HTTPError(c, srverrors.ErrInfoInvalidUserData, err) + response.Error(c, response.ErrInfoInvalidUserData, err) return } if err = gDB.Table("privileges").Where("role_id = ?", resp.User.RoleID).Pluck("name", &privs).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error getting user privileges list '%s'", resp.User.Hash) - utils.HTTPError(c, srverrors.ErrInfoInvalidUserData, err) + response.Error(c, response.ErrInfoInvalidUserData, err) return } if err = gDB.Find(&resp.Services, "tenant_id = ?", resp.User.TenantID).Error; err != nil { utils.FromContext(c).WithError(err).Errorf("error getting user services list '%s'", resp.User.Hash) - utils.HTTPError(c, srverrors.ErrInfoInvalidServiceData, err) + response.Error(c, response.ErrInfoInvalidServiceData, err) return } @@ -154,7 +154,7 @@ func Info(c *gin.Context) { utils.FromContext(c).WithError(err).Errorf("failed to refresh token") // raise error when there is elapsing last five minutes if nowt >= gtmt+int64(utils.DefaultSessionTimeout)-fiveMins { - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) return } } @@ -171,9 +171,9 @@ func Info(c *gin.Context) { "tid": resp.User.TenantID, }). Errorf("failed to get user privileges for '%s' '%s'", resp.User.Mail, resp.User.Name) - utils.HTTPError(c, srverrors.ErrInternal, err) + response.Error(c, response.ErrInternal, err) return } - utils.HTTPSuccess(c, http.StatusOK, resp) + response.Success(c, http.StatusOK, resp) } diff --git a/pkg/app/api/server/response/http.go b/pkg/app/api/server/response/http.go index 2b2de6fa..42439da0 100644 --- a/pkg/app/api/server/response/http.go +++ b/pkg/app/api/server/response/http.go @@ -1,6 +1,13 @@ package response -import "fmt" +import ( + "fmt" + + "github.com/gin-gonic/gin" + + obs "soldr/pkg/observability" + "soldr/pkg/version" +) type HttpError struct { message string @@ -27,3 +34,25 @@ func NewHttpError(httpCode int, code, message string) *HttpError { func (h *HttpError) Error() string { return fmt.Sprintf("%s: %s", h.code, h.message) } + +func Error(c *gin.Context, err *HttpError, original error) { + body := gin.H{"status": "error", "code": err.Code()} + + if version.IsDevelop == "true" { + body["msg"] = err.Msg() + if original != nil { + body["error"] = original.Error() + } + } + + traceID := obs.Observer.SpanContextFromContext(c.Request.Context()).TraceID() + if traceID.IsValid() { + body["trace_id"] = traceID.String() + } + + c.JSON(err.HttpCode(), body) +} + +func Success(c *gin.Context, code int, data interface{}) { + c.JSON(code, gin.H{"status": "success", "data": data}) +} diff --git a/pkg/app/api/server/router.go b/pkg/app/api/server/router.go index 976d16b2..80f9b767 100644 --- a/pkg/app/api/server/router.go +++ b/pkg/app/api/server/router.go @@ -29,6 +29,7 @@ import ( "soldr/pkg/app/api/server/proto" "soldr/pkg/app/api/server/public" "soldr/pkg/app/api/storage/mem" + useraction "soldr/pkg/app/api/user_action" "soldr/pkg/app/api/utils" ) @@ -50,6 +51,7 @@ import ( func NewRouter( db *gorm.DB, exchanger *srvevents.Exchanger, + userActionWriter useraction.Writer, dbConns *mem.DBConnectionStorage, s3Conns *mem.S3ConnectionStorage, @@ -149,17 +151,17 @@ func NewRouter( serverConnector := client.NewAgentServerClient(db, dbConns, s3Conns) // services - protoService := proto.NewProtoService(db, serverConnector) - agentService := private.NewAgentService(db, serverConnector) - binariesService := private.NewBinariesService(db) + protoService := proto.NewProtoService(db, serverConnector, userActionWriter) + agentService := private.NewAgentService(db, serverConnector, userActionWriter) + binariesService := private.NewBinariesService(db, userActionWriter) eventService := private.NewEventService(serverConnector) - groupService := private.NewGroupService(serverConnector) - moduleService := private.NewModuleService(db, serverConnector) + groupService := private.NewGroupService(serverConnector, userActionWriter) + moduleService := private.NewModuleService(db, serverConnector, userActionWriter) optionService := private.NewOptionService(db) - policyService := private.NewPolicyService(db, serverConnector) - portingService := private.NewPortingService(db) + policyService := private.NewPolicyService(db, serverConnector, userActionWriter) + portingService := private.NewPortingService(db, userActionWriter) roleService := private.NewRoleService(db) - upgradeService := private.NewUpgradeService(db, serverConnector) + upgradeService := private.NewUpgradeService(db, serverConnector, userActionWriter) tagService := private.NewTagService(db, serverConnector) versionService := private.NewVersionService(db, serverConnector) servicesService := private.NewServicesService(db) diff --git a/pkg/app/api/server/server_test.go b/pkg/app/api/server/server_test.go deleted file mode 100644 index 2ca52b51..00000000 --- a/pkg/app/api/server/server_test.go +++ /dev/null @@ -1,221 +0,0 @@ -package server - -import ( - "net/http" - "net/http/httptest" - "testing" - - "github.com/gin-contrib/sessions" - "github.com/gin-contrib/sessions/memstore" - "github.com/gin-gonic/gin" - _ "github.com/jinzhu/gorm/dialects/mysql" - "github.com/stretchr/testify/require" - - _ "soldr/pkg/app/api/docs" - useraction "soldr/pkg/app/api/user_action" - "soldr/pkg/app/api/utils" -) - -var testUserActionFields = utils.UserActionFields{ - Domain: "test objectDomain", - ObjectType: "test objectType", - ObjectId: "test objectId", - ObjectDisplayName: "test objectDisplayName", - ActionCode: "test actionCode", - Success: true, - FailReason: "", -} - -var testUserActionFieldsFailed = utils.UserActionFields{ - Domain: "test objectDomain", - ObjectType: "test objectType", - ObjectId: "test objectId2", - ObjectDisplayName: "test objectDisplayName2", - ActionCode: "test actionCode", - Success: false, - FailReason: "error", -} - -func compareBeginEventAndUafields(uaBeginEvent useraction.BeginEvent, uaFields utils.UserActionFields) bool { - if uaBeginEvent.ObjectDomain != uaFields.Domain || - uaBeginEvent.ObjectType != uaFields.ObjectType || - uaBeginEvent.ObjectID != uaFields.ObjectId || - uaBeginEvent.ObjectDisplayName != uaFields.ObjectDisplayName || - uaBeginEvent.ActionCode != uaFields.ActionCode { - return false - } - return true -} - -func compareSuccessEventAndUafields(uaSuccessEvent useraction.SuccessEvent, uaFields utils.UserActionFields) bool { - if uaSuccessEvent.ObjectID != uaFields.ObjectId || uaSuccessEvent.ObjectDisplayName != uaFields.ObjectDisplayName { - return false - } - return true -} - -func compareFailEventAndUafields(uaFailEvent useraction.FailEvent, uaFields utils.UserActionFields) bool { - return uaFailEvent.FailReason == uaFields.FailReason -} - -func Test_logUserActions(t *testing.T) { - t.Run("successful test", func(t *testing.T) { - uachan := make(chan useraction.Converter) - w := httptest.NewRecorder() - c, r := gin.CreateTestContext(w) - store := memstore.NewStore([]byte("secret")) - r.Use(sessions.Sessions("mysession", store)) - r.Use(func(c *gin.Context) { - session := sessions.Default(c) - session.Set("uuid", "test user id") - session.Set("uname", "test user name") - c.Set("uaf", []utils.UserActionFields{testUserActionFields, testUserActionFieldsFailed}) - }) - r.Use(useraction.LogUserActions(uachan)) - req, err := http.NewRequestWithContext(c, http.MethodGet, "/", nil) - require.NoError(t, err, "error in NewRequest") - go r.ServeHTTP(w, req) - - userAction := <-uachan - uaBeginEvent, ok := userAction.(useraction.BeginEvent) - require.True(t, ok, "wrong format of sent event") - require.True(t, compareBeginEventAndUafields(uaBeginEvent, testUserActionFields), "wrong fields in sent event, got %v want %v", uaBeginEvent, testUserActionFields) - userAction = <-uachan - uaSuccessEvent, ok := userAction.(useraction.SuccessEvent) - require.True(t, ok, "wrong format of sent event") - require.True(t, compareSuccessEventAndUafields(uaSuccessEvent, testUserActionFields), "wrong fields in sent event, got %v want %v", uaSuccessEvent, testUserActionFields) - userAction = <-uachan - uaBeginEvent, ok = userAction.(useraction.BeginEvent) - require.True(t, ok, "wrong format of sent event") - require.True(t, compareBeginEventAndUafields(uaBeginEvent, testUserActionFieldsFailed), "wrong fields in sent event, got %v want %v", uaBeginEvent, testUserActionFieldsFailed) - userAction = <-uachan - uaFailEvent, ok := userAction.(useraction.FailEvent) - require.True(t, ok, "wrong format of sent event") - require.True(t, compareFailEventAndUafields(uaFailEvent, testUserActionFieldsFailed), "wrong fields in sent event, got %v want %v", uaFailEvent, testUserActionFieldsFailed) - }) -} - -func Test_logUserActions_withAbortedContext(t *testing.T) { - t.Run("test with aborted context", func(t *testing.T) { - uachan := make(chan useraction.Converter) - w := httptest.NewRecorder() - c, r := gin.CreateTestContext(w) - store := memstore.NewStore([]byte("secret")) - r.Use(sessions.Sessions("mysession", store)) - r.Use(func(c *gin.Context) { - session := sessions.Default(c) - session.Set("uuid", "test user id") - session.Set("uname", "test user name") - c.Set("uaf", []utils.UserActionFields{testUserActionFields, testUserActionFieldsFailed}) - c.Abort() - }) - r.Use(useraction.LogUserActions(uachan)) - req, err := http.NewRequestWithContext(c, http.MethodGet, "/", nil) - require.NoError(t, err, "error in NewRequest") - r.ServeHTTP(w, req) - - }) -} - -func Test_logUserActions_withNoUaf(t *testing.T) { - t.Run("test with no uaf", func(t *testing.T) { - uachan := make(chan useraction.Converter) - w := httptest.NewRecorder() - c, r := gin.CreateTestContext(w) - store := memstore.NewStore([]byte("secret")) - r.Use(sessions.Sessions("mysession", store)) - r.Use(func(c *gin.Context) { - session := sessions.Default(c) - session.Set("uuid", "test user id") - session.Set("uname", "test user name") - }) - r.Use(useraction.LogUserActions(uachan)) - req, err := http.NewRequestWithContext(c, http.MethodGet, "/", nil) - require.NoError(t, err, "error in NewRequest") - r.ServeHTTP(w, req) - }) -} - -func Test_logUserActions_withIncorrectUaf(t *testing.T) { - t.Run("test with incorrect uaf", func(t *testing.T) { - uachan := make(chan useraction.Converter) - w := httptest.NewRecorder() - c, r := gin.CreateTestContext(w) - store := memstore.NewStore([]byte("secret")) - r.Use(sessions.Sessions("mysession", store)) - r.Use(func(c *gin.Context) { - session := sessions.Default(c) - session.Set("uuid", "test user id") - session.Set("uname", "test user name") - c.Set("uaf", "incorrect") - }) - r.Use(useraction.LogUserActions(uachan)) - req, err := http.NewRequestWithContext(c, http.MethodGet, "/", nil) - require.NoError(t, err, "error in NewRequest") - r.ServeHTTP(w, req) - }) -} - -func Test_logUserActions_withEmptyFieldInUaf(t *testing.T) { - t.Run("test with empty field in uaf", func(t *testing.T) { - uachan := make(chan useraction.Converter) - w := httptest.NewRecorder() - c, r := gin.CreateTestContext(w) - store := memstore.NewStore([]byte("secret")) - r.Use(sessions.Sessions("mysession", store)) - r.Use(func(c *gin.Context) { - session := sessions.Default(c) - session.Set("uuid", "test user id") - session.Set("uname", "test user name") - uafs := []utils.UserActionFields{testUserActionFields, testUserActionFieldsFailed} - uafs[0].Domain = "" - c.Set("uaf", uafs) - }) - r.Use(useraction.LogUserActions(uachan)) - req, err := http.NewRequestWithContext(c, http.MethodGet, "/", nil) - require.NoError(t, err, "error in NewRequest") - r.ServeHTTP(w, req) - }) -} - -func Test_logUserActions_withIncorrectUserId(t *testing.T) { - t.Run("test with incorrect user id", func(t *testing.T) { - uachan := make(chan useraction.Converter) - w := httptest.NewRecorder() - c, r := gin.CreateTestContext(w) - store := memstore.NewStore([]byte("secret")) - r.Use(sessions.Sessions("mysession", store)) - r.Use(func(c *gin.Context) { - session := sessions.Default(c) - session.Set("uuid", 7) - session.Set("uname", "test user name") - c.Set("uaf", []utils.UserActionFields{testUserActionFields, testUserActionFieldsFailed}) - }) - r.Use(useraction.LogUserActions(uachan)) - req, err := http.NewRequestWithContext(c, http.MethodGet, "/", nil) - require.NoError(t, err, "error in NewRequest") - r.ServeHTTP(w, req) - - }) -} - -func Test_logUserActions_withIncorrectUserName(t *testing.T) { - t.Run("test with incorrect user name", func(t *testing.T) { - uachan := make(chan useraction.Converter) - w := httptest.NewRecorder() - c, r := gin.CreateTestContext(w) - store := memstore.NewStore([]byte("secret")) - r.Use(sessions.Sessions("mysession", store)) - r.Use(func(c *gin.Context) { - session := sessions.Default(c) - session.Set("uuid", "test user id") - session.Set("uname", 7) - c.Set("uaf", []utils.UserActionFields{testUserActionFields, testUserActionFieldsFailed}) - }) - r.Use(useraction.LogUserActions(uachan)) - req, err := http.NewRequestWithContext(c, http.MethodGet, "/", nil) - require.NoError(t, err, "error in NewRequest") - r.ServeHTTP(w, req) - - }) -} diff --git a/pkg/app/api/user_action/log.go b/pkg/app/api/user_action/log.go new file mode 100644 index 00000000..e98650ef --- /dev/null +++ b/pkg/app/api/user_action/log.go @@ -0,0 +1,32 @@ +package useraction + +import ( + "github.com/sirupsen/logrus" + + "soldr/pkg/log" +) + +type LogWriter struct { + logger log.Logger +} + +func NewLogWriter(logger log.Logger) *LogWriter { + return &LogWriter{logger: logger} +} + +func (w *LogWriter) WriteUserAction(uaf Fields) error { + fields := logrus.Fields{ + "start_time": uaf.StartTime, + "user_name": uaf.UserName, + "user_uuid": uaf.UserUUID, + "domain": uaf.Domain, + "object_type": uaf.ObjectType, + "object_id": uaf.ObjectID, + "object_display_name": uaf.ObjectDisplayName, + "action_code": uaf.ActionCode, + "success": uaf.Success, + "fail_reason": uaf.FailReason, + } + w.logger.WithFields(fields).Info() + return nil +} diff --git a/pkg/app/api/user_action/user_action.go b/pkg/app/api/user_action/user_action.go index 56bdbf62..370cc961 100644 --- a/pkg/app/api/user_action/user_action.go +++ b/pkg/app/api/user_action/user_action.go @@ -1,182 +1,43 @@ package useraction import ( - "strings" "time" "github.com/gin-contrib/sessions" "github.com/gin-gonic/gin" - "github.com/google/uuid" - - "soldr/pkg/app/api/utils" ) -type Action struct { - Mtype string `json:"type"` - ID string `json:"id"` - Time int64 `json:"time"` - UtcOffset string `json:"utcOffset"` - UserID string `json:"userId,omitempty"` - UserDisplayName string `json:"userDisplayName,omitempty"` - ObjectDomain string `json:"objectDomain,omitempty"` - ObjectType string `json:"objectType,omitempty"` - ObjectID string `json:"objectId,omitempty"` - ObjectDisplayName string `json:"objectDisplayName,omitempty"` - ActionCode string `json:"actionCode,omitempty"` - FailReason string `json:"failReason,omitempty"` -} +const UnknownObjectDisplayName = "Undefined object" -type Converter interface { - ToUserAction() Action +type Writer interface { + WriteUserAction(uaf Fields) error } -type BeginEvent struct { - ID uuid.UUID - Time int64 - UTCOffset string - UserID string - UserDisplayName string - ObjectDomain string +type Fields struct { + StartTime time.Time + UserName string + UserUUID string + Domain string ObjectType string ObjectID string ObjectDisplayName string ActionCode string -} - -func (e BeginEvent) ToUserAction() Action { - return Action{ - Mtype: "UserActionBeginEvent", - ID: e.ID.String(), - Time: e.Time, - UtcOffset: e.UTCOffset, - UserID: e.UserID, - UserDisplayName: e.UserDisplayName, - ObjectDomain: e.ObjectDomain, - ObjectType: e.ObjectType, - ObjectID: e.ObjectID, - ObjectDisplayName: e.ObjectDisplayName, - ActionCode: e.ActionCode, - } -} - -type FailEvent struct { - ID uuid.UUID - Time int64 - UTCOffset string - FailReason string -} - -func (e FailEvent) ToUserAction() Action { - return Action{ - Mtype: "UserActionFailEvent", - ID: e.ID.String(), - Time: e.Time, - UtcOffset: e.UTCOffset, - FailReason: e.FailReason, - } -} - -type SuccessEvent struct { - ID uuid.UUID - Time int64 - UTCOffset string - ObjectID string - ObjectDisplayName string -} - -func (e SuccessEvent) ToUserAction() Action { - return Action{ - Mtype: "UserActionSuccessEvent", - ID: e.ID.String(), - Time: e.Time, - UtcOffset: e.UTCOffset, - ObjectID: e.ObjectID, - ObjectDisplayName: e.ObjectDisplayName, - } -} - -func LogUserActions(actionCh chan Converter) gin.HandlerFunc { - return func(c *gin.Context) { - if c.IsAborted() { - return - } - - tStart := time.Now() - - c.Next() - - fields, ok := c.Get("uaf") - if !ok { - // action doesn't need to be logged - return - } - - uafs, ok := fields.([]utils.UserActionFields) - if !ok { - utils.FromContext(c).Errorf("wrong fields format for action logging") - return - } - for _, uaf := range uafs { - if uaf.ActionCode == "" || uaf.Domain == "" || uaf.ObjectType == "" { - utils.FromContext(c).Errorf("empty required field or wrong action code for action logging") - return - } - } - - tFinish := time.Now() - tstrarr := strings.Fields(tFinish.Format("01/02 03:04:05PM '06 -07:00")) - - session := sessions.Default(c) - uid := session.Get("uuid") - uuidstr, ok := uid.(string) - if !ok { - utils.FromContext(c).Errorf("error getting user id from session") - return - } - - userName := session.Get("uname") - userNamestr, ok := userName.(string) - if !ok { - utils.FromContext(c).Errorf("error getting user name from session") - return - } - - for _, uaf := range uafs { - eventId := uuid.New() - - beginAction := BeginEvent{ - ID: eventId, - Time: tStart.Unix(), - UTCOffset: tstrarr[3], - UserID: uuidstr, - UserDisplayName: userNamestr, - ObjectDomain: uaf.Domain, - ObjectType: uaf.ObjectType, - ObjectID: uaf.ObjectId, - ObjectDisplayName: uaf.ObjectDisplayName, - ActionCode: uaf.ActionCode, - } - actionCh <- beginAction - - if uaf.Success { - successAction := SuccessEvent{ - ID: eventId, - Time: tFinish.Unix(), - UTCOffset: tstrarr[3], - ObjectID: uaf.ObjectId, - ObjectDisplayName: uaf.ObjectDisplayName, - } - actionCh <- successAction - - } else { - failAction := FailEvent{ - ID: eventId, - Time: tFinish.Unix(), - UTCOffset: tstrarr[3], - FailReason: uaf.FailReason, - } - actionCh <- failAction - } - } + Success bool + FailReason string +} + +func NewFields(c *gin.Context, domain, objectType, actionCode, objectID, objectDisplayName string) Fields { + session := sessions.Default(c) + uuid := (session.Get("uuid")).(string) + userName := (session.Get("uname")).(string) + return Fields{ + StartTime: time.Now(), + UserName: userName, + UserUUID: uuid, + Domain: domain, + ObjectType: objectType, + ObjectID: objectID, + ObjectDisplayName: objectDisplayName, + ActionCode: actionCode, } } diff --git a/pkg/app/api/utils/utils.go b/pkg/app/api/utils/utils.go index 6b0cc6f0..1f1e91ae 100644 --- a/pkg/app/api/utils/utils.go +++ b/pkg/app/api/utils/utils.go @@ -4,13 +4,11 @@ import ( "crypto/md5" "crypto/rand" "crypto/sha256" - "crypto/tls" "encoding/base64" "encoding/hex" "encoding/json" "fmt" "io" - "net/http" "os" "path/filepath" "regexp" @@ -25,7 +23,6 @@ import ( "github.com/sirupsen/logrus" "golang.org/x/crypto/bcrypt" - obs "soldr/pkg/observability" "soldr/pkg/storage" "soldr/pkg/system" "soldr/pkg/version" @@ -53,18 +50,6 @@ const ( PrefixPathAPI = "/api/v1" ) -type UserActionFields struct { - Domain string - ObjectType string - ObjectId string - ObjectDisplayName string - ActionCode string - Success bool - FailReason string -} - -const UnknownObjectDisplayName = "Undefined object" - func GetAgentName(db *gorm.DB, hash string) (string, error) { var agent models.Agent if err := db.Take(&agent, "hash = ?", hash).Error; err != nil { @@ -493,83 +478,6 @@ func CompareVersions(sourceVersion, targetVersion string) int { } } -func GetHttpClient() *http.Client { - return &http.Client{ - Timeout: 10 * time.Second, - Transport: &http.Transport{ - TLSClientConfig: &tls.Config{ - InsecureSkipVerify: true, - }, - }, - } -} - -// HTTPSuccess is function as a main part of public REST API (success response) -func HTTPSuccess(c *gin.Context, code int, data interface{}) { - HTTPSuccessWithUAFieldsSlice(c, code, data, nil) -} - -func HTTPSuccessWithUAFields(c *gin.Context, code int, data interface{}, uaFields UserActionFields) { - HTTPSuccessWithUAFieldsSlice(c, code, data, []UserActionFields{uaFields}) -} - -func HTTPSuccessWithUAFieldsSlice(c *gin.Context, code int, data interface{}, uaFields []UserActionFields) { - if !c.IsAborted() { - if uaFields != nil { - for i := range uaFields { - uaFields[i].Success = true - } - c.Set("uaf", uaFields) - } - c.JSON(code, gin.H{"status": "success", "data": data}) - c.Abort() - } -} - -type HttpError interface { - Code() string - HttpCode() int - Msg() string -} - -// HTTPError is function as a main part of public REST API (failed response) -func HTTPError(c *gin.Context, err HttpError, original error) { - HTTPErrorWithUAFieldsSlice(c, err, original, nil) -} - -func HTTPErrorWithUAFields(c *gin.Context, err HttpError, original error, uaFields UserActionFields) { - HTTPErrorWithUAFieldsSlice(c, err, original, []UserActionFields{uaFields}) -} - -func HTTPErrorWithUAFieldsSlice(c *gin.Context, err HttpError, original error, uaFields []UserActionFields) { - if !c.IsAborted() { - if uaFields != nil { - for i := range uaFields { - uaFields[i].Success = false - uaFields[i].FailReason = err.Msg() - - } - c.Set("uaf", uaFields) - } - body := gin.H{"status": "error", "code": err.Code()} - - if version.IsDevelop == "true" { - body["msg"] = err.Msg() - if original != nil { - body["error"] = original.Error() - } - } - - traceID := obs.Observer.SpanContextFromContext(c.Request.Context()).TraceID() - if traceID.IsValid() { - body["trace_id"] = traceID.String() - } - - c.JSON(err.HttpCode(), body) - c.Abort() - } -} - func ValidateBinaryFileByChksums(data []byte, chksums models.BinaryChksum) error { md5Hash := md5.Sum(data) if chksums.MD5 != "" && chksums.MD5 != hex.EncodeToString(md5Hash[:]) { diff --git a/pkg/app/api/utils/utils_test.go b/pkg/app/api/utils/utils_test.go deleted file mode 100644 index 5386d999..00000000 --- a/pkg/app/api/utils/utils_test.go +++ /dev/null @@ -1,183 +0,0 @@ -package utils - -import ( - "bytes" - "net/http" - "net/http/httptest" - "reflect" - "strings" - "testing" - - srverrors "soldr/pkg/app/api/server/response" - - "github.com/gin-gonic/gin" - "github.com/google/uuid" - "github.com/stretchr/testify/require" -) - -var testUserActionFields = UserActionFields{ - Domain: "test objectDomain", - ObjectType: "test objectType", - ObjectId: "test objectId", - ObjectDisplayName: "test objectDisplayName", - ActionCode: "test actionCode", - Success: true, - FailReason: "", -} - -var testUserActionFieldsSuccess = UserActionFields{ - Domain: "test objectDomain", - ObjectType: "test objectType", - ObjectId: "test objectId", - ObjectDisplayName: "test objectDisplayName", - ActionCode: "test actionCode", - Success: true, - FailReason: "", -} - -var testUserActionFieldsFail = UserActionFields{ - Domain: "test objectDomain", - ObjectType: "test objectType", - ObjectId: "test objectId", - ObjectDisplayName: "test objectDisplayName", - ActionCode: "test actionCode", - Success: false, - FailReason: "internal server error", -} - -func TestMakeUuidStrFromHash(t *testing.T) { - uid := strings.Replace(uuid.New().String(), "-", "", -1) - type args struct { - hash string - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "successful test", - args: args{ - hash: uid, - }, - wantErr: false, - }, - { - name: "test with error in decode", - args: args{ - hash: "a", - }, - wantErr: true, - }, - { - name: "test with error creating error", - args: args{ - hash: "123456789012345678901234567890", - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - _, err := MakeUuidStrFromHash(tt.args.hash) - if !tt.wantErr { - require.NoError(t, err, "MakeUuidStrFromHash() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - -func TestHTTPSuccessWithUAFieldsSlice(t *testing.T) { - - t.Run("successful test", func(t *testing.T) { - w := httptest.NewRecorder() - c, _ := gin.CreateTestContext(w) - testUafs := []UserActionFields{testUserActionFields, testUserActionFields} - HTTPSuccessWithUAFieldsSlice(c, http.StatusOK, "some data", testUafs) - - require.True(t, c.IsAborted(), "context is not aborted") - uafint, ok := c.Get("uaf") - require.True(t, ok, "user action fields value is not set") - uaf, ok := uafint.([]UserActionFields) - require.True(t, ok, "user action fields value in wrong format") - testSuccessUafs := []UserActionFields{testUserActionFieldsSuccess, testUserActionFieldsSuccess} - require.True(t, reflect.DeepEqual(uaf, testSuccessUafs), "wrong user action fields value, got %v, want %v", uaf, testUafs) - }) -} - -func TestHTTPSuccessWithUAFieldsSlice_withAbortedContext(t *testing.T) { - - t.Run("successful test with aborted context", func(t *testing.T) { - w := httptest.NewRecorder() - c, _ := gin.CreateTestContext(w) - c.Abort() - testUafs := []UserActionFields{testUserActionFields, testUserActionFields} - HTTPSuccessWithUAFieldsSlice(c, http.StatusOK, "some data", testUafs) - - _, ok := c.Get("uaf") - require.False(t, ok, "user action fields value is set") - }) -} - -func TestHTTPSuccessWithUAFieldsSlice_withEmptyUafields(t *testing.T) { - - t.Run("successful test with empty uafields", func(t *testing.T) { - w := httptest.NewRecorder() - c, _ := gin.CreateTestContext(w) - HTTPSuccessWithUAFieldsSlice(c, http.StatusOK, "some data", nil) - - require.True(t, c.IsAborted(), "context is not aborted") - _, ok := c.Get("uaf") - require.False(t, ok, "user action fields value is set") - }) -} - -func TestHTTPErrorWithUAFieldsSlice(t *testing.T) { - t.Run("successful test", func(t *testing.T) { - w := httptest.NewRecorder() - c, _ := gin.CreateTestContext(w) - var err error - c.Request, err = http.NewRequest(http.MethodPost, "/", bytes.NewBuffer([]byte("{}"))) - require.NoError(t, err, "error in NewRequest") - testUafs := []UserActionFields{testUserActionFields, testUserActionFields} - HTTPErrorWithUAFieldsSlice(c, srverrors.ErrInternal, nil, testUafs) - require.True(t, c.IsAborted(), "context is not aborted") - uafint, ok := c.Get("uaf") - require.True(t, ok, "user action fields value is not set") - uaf, ok := uafint.([]UserActionFields) - require.True(t, ok, "user action fields value in wrong format") - testSuccessUafs := []UserActionFields{testUserActionFieldsFail, testUserActionFieldsFail} - require.True(t, reflect.DeepEqual(uaf, testSuccessUafs), "wrong user action fields value, got %v, want %v", uaf, testUafs) - }) - -} - -func TestHTTPErrorWithUAFieldsSlice_withAbortedContext(t *testing.T) { - - t.Run("successful test with aborted context", func(t *testing.T) { - w := httptest.NewRecorder() - c, _ := gin.CreateTestContext(w) - c.Abort() - testUafs := []UserActionFields{testUserActionFields, testUserActionFields} - HTTPErrorWithUAFieldsSlice(c, srverrors.ErrInternal, nil, testUafs) - _, ok := c.Get("uaf") - require.False(t, ok, "user action fields value is set") - }) -} - -func TestHTTPErrorWithUAFieldsSlice_withEmptyUafields(t *testing.T) { - t.Run("successful test with empty uafields", func(t *testing.T) { - w := httptest.NewRecorder() - c, _ := gin.CreateTestContext(w) - var err error - c.Request, err = http.NewRequest(http.MethodPost, "/", bytes.NewBuffer([]byte("{}"))) - require.NoError(t, err, "error in NewRequest") - HTTPErrorWithUAFieldsSlice(c, srverrors.ErrInternal, nil, nil) - if !c.IsAborted() { - t.Errorf("context is not aborted") - } - _, ok := c.Get("uaf") - require.False(t, ok, "user action fields value is set") - }) - -}