From 8333ea88a8b132ef9cd242084ea68c6c8aa459c6 Mon Sep 17 00:00:00 2001 From: Jonas Plum Date: Sat, 8 Jan 2022 00:48:44 +0100 Subject: [PATCH] Change code generator (#4) * Change code generator * Remove gin --- auth.go | 345 +- backup.go | 16 +- bus/job.go | 14 +- bus/result.go | 6 +- busservice/busservice.go | 12 +- busservice/job.go | 10 +- busservice/result.go | 4 +- cmd/catalyst-dev/main.go | 23 +- cmd/catalyst/main.go | 3 +- cmd/cmd.go | 20 +- database/artifact.go | 12 +- database/automation.go | 28 +- database/busdb/busdb.go | 78 +- database/busdb/context.go | 20 +- database/busdb/log.go | 18 +- database/job.go | 38 +- database/migrations/migrations.go | 32 +- database/playbook.go | 38 +- database/playbookutils.go | 14 +- database/playbookutils_test.go | 18 +- database/settings.go | 25 +- database/settings_test.go | 21 +- database/statistics.go | 6 +- database/task.go | 21 +- database/template.go | 28 +- database/template_test.go | 22 +- database/ticket.go | 64 +- database/ticket_field.go | 26 +- database/ticket_task.go | 30 +- database/tickettype.go | 28 +- database/user.go | 49 +- definition/jobs.yaml | 2 +- definition/playbooks.yaml | 2 +- definition/tasks.yaml | 2 +- definition/tickets.yaml | 37 +- file.go | 50 +- generate.sh | 3 +- generated/api/api.go | 1094 ++ generated/api/test_api.go | 587 + generated/catalyst.json | 47 +- generated/catalyst.yml | 47 +- generated/community.json | 47 +- generated/community.yml | 47 +- .../{models/models.go => model/model.go} | 202 +- generated/restapi/api.go | 252 - generated/restapi/api/response.go | 6 - generated/restapi/embedded_spec.go | 14098 ---------------- .../create_automation_parameters.go | 90 - .../delete_automation_parameters.go | 87 - .../automations/get_automation_parameters.go | 87 - .../list_automations_parameters.go | 55 - .../update_automation_parameters.go | 111 - .../operations/jobs/get_job_parameters.go | 87 - .../operations/jobs/list_jobs_parameters.go | 55 - .../operations/jobs/run_job_parameters.go | 90 - .../operations/jobs/update_job_parameters.go | 111 - .../operations/logs/get_logs_parameters.go | 87 - .../playbooks/create_playbook_parameters.go | 90 - .../playbooks/delete_playbook_parameters.go | 87 - .../playbooks/get_playbook_parameters.go | 87 - .../playbooks/list_playbooks_parameters.go | 55 - .../playbooks/update_playbook_parameters.go | 111 - .../settings/get_settings_parameters.go | 55 - .../statistics/get_statistics_parameters.go | 55 - .../operations/tasks/list_tasks_parameters.go | 55 - .../templates/create_template_parameters.go | 90 - .../templates/delete_template_parameters.go | 87 - .../templates/get_template_parameters.go | 87 - .../templates/list_templates_parameters.go | 55 - .../templates/update_template_parameters.go | 111 - .../tickets/add_artifact_parameters.go | 116 - .../tickets/add_comment_parameters.go | 116 - .../tickets/add_ticket_playbook_parameters.go | 116 - .../tickets/complete_task_parameters.go | 157 - .../tickets/create_ticket_batch_parameters.go | 90 - .../tickets/create_ticket_parameters.go | 90 - .../tickets/delete_ticket_parameters.go | 92 - .../tickets/enrich_artifact_parameters.go | 137 - .../tickets/get_artifact_parameters.go | 113 - .../tickets/get_ticket_parameters.go | 92 - .../tickets/link_files_parameters.go | 116 - .../tickets/link_ticket_parameters.go | 115 - .../tickets/list_tickets_parameters.go | 269 - .../tickets/remove_artifact_parameters.go | 113 - .../tickets/remove_comment_parameters.go | 117 - .../remove_ticket_playbook_parameters.go | 113 - .../tickets/run_artifact_parameters.go | 134 - .../operations/tickets/run_task_parameters.go | 134 - .../tickets/set_artifact_parameters.go | 137 - .../tickets/set_references_parameters.go | 116 - .../tickets/set_schema_parameters.go | 106 - .../operations/tickets/set_task_parameters.go | 158 - .../tickets/unlink_ticket_parameters.go | 115 - .../tickets/update_ticket_parameters.go | 116 - .../create_ticket_type_parameters.go | 90 - .../delete_ticket_type_parameters.go | 87 - .../tickettypes/get_ticket_type_parameters.go | 87 - .../list_ticket_types_parameters.go | 55 - .../update_ticket_type_parameters.go | 111 - .../userdata/current_user_data_parameters.go | 55 - .../userdata/get_user_data_parameters.go | 87 - .../userdata/list_user_data_parameters.go | 55 - .../update_current_user_data_parameters.go | 90 - .../userdata/update_user_data_parameters.go | 111 - .../users/create_user_parameters.go | 90 - .../users/current_user_parameters.go | 55 - .../users/delete_user_parameters.go | 87 - .../operations/users/get_user_parameters.go | 87 - .../operations/users/list_users_parameters.go | 55 - .../users/update_user_parameters.go | 111 - generated/test/api_server_test.go | 638 - generator/generator.go | 342 - generator/swagger.go | 61 - generator/templates/api.gotmpl | 124 - generator/templates/api_server_test.gotmpl | 146 - generator/templates/parameter.gotmpl | 347 - generator/templates/response.gotmpl | 6 - generator/templates/simplemodel.gotmpl | 64 - go.mod | 27 +- go.sum | 377 +- hooks/hooks.go | 3 +- index/index.go | 4 +- index/index_test.go | 6 +- restore.go | 27 +- role/role.go | 6 +- server.go | 65 +- service/artifact.go | 38 - service/automation.go | 38 +- service/job.go | 39 +- service/log.go | 10 +- service/playbook.go | 61 +- service/service.go | 35 +- service/statistics.go | 7 +- service/task.go | 7 +- service/template.go | 42 +- service/ticket.go | 210 +- service/ticket_field.go | 88 - service/tickettype.go | 40 +- service/uisettings.go | 15 +- service/user.go | 56 +- service/userdata.go | 44 +- static.go | 12 +- test/data.go | 24 +- test/server_test.go | 132 +- test/test.go | 39 +- ui/src/client/api.ts | 90 +- ui/src/views/TaskList.vue | 4 +- websocket.go | 11 +- 148 files changed, 3077 insertions(+), 23976 deletions(-) create mode 100755 generated/api/api.go create mode 100755 generated/api/test_api.go rename generated/{models/models.go => model/model.go} (86%) delete mode 100644 generated/restapi/api.go delete mode 100644 generated/restapi/api/response.go delete mode 100644 generated/restapi/embedded_spec.go delete mode 100644 generated/restapi/operations/automations/create_automation_parameters.go delete mode 100644 generated/restapi/operations/automations/delete_automation_parameters.go delete mode 100644 generated/restapi/operations/automations/get_automation_parameters.go delete mode 100644 generated/restapi/operations/automations/list_automations_parameters.go delete mode 100644 generated/restapi/operations/automations/update_automation_parameters.go delete mode 100644 generated/restapi/operations/jobs/get_job_parameters.go delete mode 100644 generated/restapi/operations/jobs/list_jobs_parameters.go delete mode 100644 generated/restapi/operations/jobs/run_job_parameters.go delete mode 100644 generated/restapi/operations/jobs/update_job_parameters.go delete mode 100644 generated/restapi/operations/logs/get_logs_parameters.go delete mode 100644 generated/restapi/operations/playbooks/create_playbook_parameters.go delete mode 100644 generated/restapi/operations/playbooks/delete_playbook_parameters.go delete mode 100644 generated/restapi/operations/playbooks/get_playbook_parameters.go delete mode 100644 generated/restapi/operations/playbooks/list_playbooks_parameters.go delete mode 100644 generated/restapi/operations/playbooks/update_playbook_parameters.go delete mode 100644 generated/restapi/operations/settings/get_settings_parameters.go delete mode 100644 generated/restapi/operations/statistics/get_statistics_parameters.go delete mode 100644 generated/restapi/operations/tasks/list_tasks_parameters.go delete mode 100644 generated/restapi/operations/templates/create_template_parameters.go delete mode 100644 generated/restapi/operations/templates/delete_template_parameters.go delete mode 100644 generated/restapi/operations/templates/get_template_parameters.go delete mode 100644 generated/restapi/operations/templates/list_templates_parameters.go delete mode 100644 generated/restapi/operations/templates/update_template_parameters.go delete mode 100644 generated/restapi/operations/tickets/add_artifact_parameters.go delete mode 100644 generated/restapi/operations/tickets/add_comment_parameters.go delete mode 100644 generated/restapi/operations/tickets/add_ticket_playbook_parameters.go delete mode 100644 generated/restapi/operations/tickets/complete_task_parameters.go delete mode 100644 generated/restapi/operations/tickets/create_ticket_batch_parameters.go delete mode 100644 generated/restapi/operations/tickets/create_ticket_parameters.go delete mode 100644 generated/restapi/operations/tickets/delete_ticket_parameters.go delete mode 100644 generated/restapi/operations/tickets/enrich_artifact_parameters.go delete mode 100644 generated/restapi/operations/tickets/get_artifact_parameters.go delete mode 100644 generated/restapi/operations/tickets/get_ticket_parameters.go delete mode 100644 generated/restapi/operations/tickets/link_files_parameters.go delete mode 100644 generated/restapi/operations/tickets/link_ticket_parameters.go delete mode 100644 generated/restapi/operations/tickets/list_tickets_parameters.go delete mode 100644 generated/restapi/operations/tickets/remove_artifact_parameters.go delete mode 100644 generated/restapi/operations/tickets/remove_comment_parameters.go delete mode 100644 generated/restapi/operations/tickets/remove_ticket_playbook_parameters.go delete mode 100644 generated/restapi/operations/tickets/run_artifact_parameters.go delete mode 100644 generated/restapi/operations/tickets/run_task_parameters.go delete mode 100644 generated/restapi/operations/tickets/set_artifact_parameters.go delete mode 100644 generated/restapi/operations/tickets/set_references_parameters.go delete mode 100644 generated/restapi/operations/tickets/set_schema_parameters.go delete mode 100644 generated/restapi/operations/tickets/set_task_parameters.go delete mode 100644 generated/restapi/operations/tickets/unlink_ticket_parameters.go delete mode 100644 generated/restapi/operations/tickets/update_ticket_parameters.go delete mode 100644 generated/restapi/operations/tickettypes/create_ticket_type_parameters.go delete mode 100644 generated/restapi/operations/tickettypes/delete_ticket_type_parameters.go delete mode 100644 generated/restapi/operations/tickettypes/get_ticket_type_parameters.go delete mode 100644 generated/restapi/operations/tickettypes/list_ticket_types_parameters.go delete mode 100644 generated/restapi/operations/tickettypes/update_ticket_type_parameters.go delete mode 100644 generated/restapi/operations/userdata/current_user_data_parameters.go delete mode 100644 generated/restapi/operations/userdata/get_user_data_parameters.go delete mode 100644 generated/restapi/operations/userdata/list_user_data_parameters.go delete mode 100644 generated/restapi/operations/userdata/update_current_user_data_parameters.go delete mode 100644 generated/restapi/operations/userdata/update_user_data_parameters.go delete mode 100644 generated/restapi/operations/users/create_user_parameters.go delete mode 100644 generated/restapi/operations/users/current_user_parameters.go delete mode 100644 generated/restapi/operations/users/delete_user_parameters.go delete mode 100644 generated/restapi/operations/users/get_user_parameters.go delete mode 100644 generated/restapi/operations/users/list_users_parameters.go delete mode 100644 generated/restapi/operations/users/update_user_parameters.go delete mode 100644 generated/test/api_server_test.go delete mode 100644 generator/generator.go delete mode 100644 generator/swagger.go delete mode 100644 generator/templates/api.gotmpl delete mode 100644 generator/templates/api_server_test.gotmpl delete mode 100644 generator/templates/parameter.gotmpl delete mode 100644 generator/templates/response.gotmpl delete mode 100644 generator/templates/simplemodel.gotmpl delete mode 100644 service/artifact.go delete mode 100644 service/ticket_field.go diff --git a/auth.go b/auth.go index be32591..29bc743 100644 --- a/auth.go +++ b/auth.go @@ -4,21 +4,20 @@ import ( "context" "crypto/sha256" "encoding/base64" + "encoding/json" + "errors" "fmt" - "log" "math/rand" "net/http" "strings" - "time" "github.com/coreos/go-oidc/v3/oidc" - "github.com/gin-contrib/sessions" - "github.com/gin-gonic/gin" "golang.org/x/oauth2" "github.com/SecurityBrewery/catalyst/database" "github.com/SecurityBrewery/catalyst/database/busdb" - "github.com/SecurityBrewery/catalyst/generated/models" + "github.com/SecurityBrewery/catalyst/generated/api" + "github.com/SecurityBrewery/catalyst/generated/model" "github.com/SecurityBrewery/catalyst/hooks" "github.com/SecurityBrewery/catalyst/role" ) @@ -59,33 +58,31 @@ func (c *AuthConfig) Load(ctx context.Context) error { } const ( - SessionName = "catalyst-session" - stateSession = "state" - userSession = "user" + stateSessionCookie = "state" + userSessionCookie = "user" ) -func Authenticate(db *database.Database, config *AuthConfig) gin.HandlerFunc { - return func(ctx *gin.Context) { - iss := config.OIDCIssuer +func Authenticate(db *database.Database, config *AuthConfig) func(next http.Handler) http.Handler { + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + keyHeader := r.Header.Get("PRIVATE-TOKEN") + authHeader := r.Header.Get("User") - keyHeader := ctx.Request.Header.Get("PRIVATE-TOKEN") - if keyHeader != "" { - keyAuth(db, keyHeader)(ctx) - return - } - - authHeader := ctx.Request.Header.Get("User") - - if authHeader != "" { - bearerAuth(db, authHeader, iss, config)(ctx) - return - } - sessionAuth(db, config)(ctx) + switch { + case keyHeader != "": + keyAuth(db, keyHeader)(next).ServeHTTP(w, r) + case authHeader != "": + iss := config.OIDCIssuer + bearerAuth(db, authHeader, iss, config)(next).ServeHTTP(w, r) + default: + sessionAuth(db, config)(next).ServeHTTP(w, r) + } + }) } } -func oidcCtx(ctx *gin.Context) (context.Context, context.CancelFunc) { - /* +/* +func oidcCtx(w http.ResponseWriter, r *http.Request) (context.Context, context.CancelFunc) { if config.TLSCertFile != "" && config.TLSKeyFile != "" { cert, err := tls.LoadX509KeyPair(config.TLSCertFile, config.TLSKeyFile) if err != nil { @@ -109,137 +106,145 @@ func oidcCtx(ctx *gin.Context) (context.Context, context.CancelFunc) { }, }), nil } - */ cctx, cancel := context.WithTimeout(ctx, time.Minute) return cctx, cancel } +*/ -func bearerAuth(db *database.Database, authHeader string, iss string, config *AuthConfig) func(ctx *gin.Context) { - return func(ctx *gin.Context) { - if !strings.HasPrefix(authHeader, "Bearer ") { - ctx.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "no bearer token"}) - return - } +func bearerAuth(db *database.Database, authHeader string, iss string, config *AuthConfig) func(next http.Handler) http.Handler { + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if !strings.HasPrefix(authHeader, "Bearer ") { + api.JSONErrorStatus(w, http.StatusUnauthorized, errors.New("no bearer token")) + return + } - oidcCtx, cancel := oidcCtx(ctx) - defer cancel() + // oidcCtx, cancel := oidcCtx(ctx) + // defer cancel() - verifier, err := config.Verifier(oidcCtx) - if err != nil { - ctx.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "could not verify: " + err.Error()}) - return - } - authToken, err := verifier.Verify(oidcCtx, authHeader[7:]) - if err != nil { - ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("could not verify bearer token: %v", err)}) - return - } + verifier, err := config.Verifier(r.Context()) + if err != nil { + api.JSONErrorStatus(w, http.StatusUnauthorized, fmt.Errorf("could not verify: %w", err)) + return + } + authToken, err := verifier.Verify(r.Context(), authHeader[7:]) + if err != nil { + api.JSONErrorStatus(w, http.StatusInternalServerError, fmt.Errorf("could not verify bearer token: %w", err)) + return + } - var claims map[string]interface{} - if err := authToken.Claims(&claims); err != nil { - ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("failed to parse claims: %v", err)}) - return - } + var claims map[string]interface{} + if err := authToken.Claims(&claims); err != nil { + api.JSONErrorStatus(w, http.StatusInternalServerError, fmt.Errorf("failed to parse claims: %w", err)) + return + } - // if claims.Iss != iss { - // ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "wrong issuer"}) - // return - // } + // if claims.Iss != iss { + // return &api.HTTPError{Status: http.StatusInternalServerError, Internal: "wrong issuer"}) + // return + // } - session := sessions.Default(ctx) - session.Set(userSession, claims) - if err = session.Save(); err != nil { - ctx.AbortWithStatusJSON(http.StatusInternalServerError, fmt.Sprintf("could not set session: %v", err)) - return - } + b, _ := json.Marshal(claims) + http.SetCookie(w, &http.Cookie{Name: userSessionCookie, Value: base64.StdEncoding.EncodeToString(b)}) - if err = setContextClaims(ctx, db, claims, config); err != nil { - ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("could not load user: %s", err)}) - return - } - ctx.Next() + r, err = setContextClaims(r, db, claims, config) + if err != nil { + api.JSONErrorStatus(w, http.StatusInternalServerError, fmt.Errorf("could not load user: %w", err)) + return + } + + next.ServeHTTP(w, r) + }) } } -func keyAuth(db *database.Database, keyHeader string) func(ctx *gin.Context) { - return func(ctx *gin.Context) { - h := fmt.Sprintf("%x", sha256.Sum256([]byte(keyHeader))) +func keyAuth(db *database.Database, keyHeader string) func(next http.Handler) http.Handler { + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + h := fmt.Sprintf("%x", sha256.Sum256([]byte(keyHeader))) - key, err := db.UserByHash(ctx, h) - if err != nil { - ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("could not verify private token: %v", err)}) - return - } + key, err := db.UserByHash(r.Context(), h) + if err != nil { + api.JSONErrorStatus(w, http.StatusInternalServerError, fmt.Errorf("could not verify private token: %w", err)) + return + } - setContextUser(ctx, key, db.Hooks) + r = setContextUser(r, key, db.Hooks) - ctx.Next() + next.ServeHTTP(w, r) + }) } } -func sessionAuth(db *database.Database, config *AuthConfig) func(ctx *gin.Context) { - return func(ctx *gin.Context) { - session := sessions.Default(ctx) +func sessionAuth(db *database.Database, config *AuthConfig) func(next http.Handler) http.Handler { + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + userCookie, err := r.Cookie(userSessionCookie) + if err != nil { + redirectToLogin(w, r, config.OAuth2) - user := session.Get(userSession) - if user == nil { - redirectToLogin(ctx, session, config.OAuth2) + return + } - return - } + b, err := base64.StdEncoding.DecodeString(userCookie.Value) + if err != nil { + api.JSONErrorStatus(w, http.StatusInternalServerError, fmt.Errorf("could not decode cookie: %w", err)) + return + } - claims, ok := user.(map[string]interface{}) - if !ok { - ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "claims not in session"}) - return - } + var claims map[string]interface{} + if err := json.Unmarshal(b, &claims); err != nil { + api.JSONErrorStatus(w, http.StatusInternalServerError, errors.New("claims not in session")) + return + } - if err := setContextClaims(ctx, db, claims, config); err != nil { - ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("could not load user: %s", err)}) - return - } + r, err = setContextClaims(r, db, claims, config) + if err != nil { + api.JSONErrorStatus(w, http.StatusInternalServerError, fmt.Errorf("could not load user: %w", err)) + return + } - ctx.Next() + next.ServeHTTP(w, r) + }) } } -func setContextClaims(ctx *gin.Context, db *database.Database, claims map[string]interface{}, config *AuthConfig) error { +func setContextClaims(r *http.Request, db *database.Database, claims map[string]interface{}, config *AuthConfig) (*http.Request, error) { newUser, newSetting, err := mapUserAndSettings(claims, config) if err != nil { - return err + return nil, err } - if _, ok := busdb.UserFromContext(ctx); !ok { - busdb.SetContext(ctx, &models.UserResponse{ID: "auth", Roles: []string{role.Admin}, Apikey: false, Blocked: false}) + if _, ok := busdb.UserFromContext(r.Context()); !ok { + r = busdb.SetContext(r, &model.UserResponse{ID: "auth", Roles: []string{role.Admin}, Apikey: false, Blocked: false}) } - user, err := db.UserGetOrCreate(ctx, newUser) + user, err := db.UserGetOrCreate(r.Context(), newUser) if err != nil { - return err + return nil, err } - _, err = db.UserDataGetOrCreate(ctx, newUser.ID, newSetting) + _, err = db.UserDataGetOrCreate(r.Context(), newUser.ID, newSetting) if err != nil { - return err + return nil, err } - setContextUser(ctx, user, db.Hooks) - return nil + return setContextUser(r, user, db.Hooks), nil } -func setContextUser(ctx *gin.Context, user *models.UserResponse, hooks *hooks.Hooks) { - groups, err := hooks.GetGroups(ctx, user.ID) +func setContextUser(r *http.Request, user *model.UserResponse, hooks *hooks.Hooks) *http.Request { + groups, err := hooks.GetGroups(r.Context(), user.ID) if err == nil { - busdb.SetGroupContext(ctx, groups) + r = busdb.SetGroupContext(r, groups) } - busdb.SetContext(ctx, user) + return busdb.SetContext(r, user) } -func mapUserAndSettings(claims map[string]interface{}, config *AuthConfig) (*models.UserForm, *models.UserData, error) { +func mapUserAndSettings(claims map[string]interface{}, config *AuthConfig) (*model.UserForm, *model.UserData, error) { // handle Bearer tokens // if typ, ok := claims["typ"]; ok && typ == "Bearer" { - // return &models.User{ + // return &model.User{ // Username: "bot", // Blocked: false, // Email: pointer.String("bot@example.org"), @@ -262,11 +267,11 @@ func mapUserAndSettings(claims map[string]interface{}, config *AuthConfig) (*mod name = "" } - return &models.UserForm{ + return &model.UserForm{ ID: username, Blocked: config.AuthBlockNew, Roles: role.Strings(config.AuthDefaultRoles), - }, &models.UserData{ + }, &model.UserData{ Email: &email, Name: &name, }, nil @@ -283,114 +288,110 @@ func getString(m map[string]interface{}, key string) (string, error) { return "", fmt.Errorf("mapping of %s failed, missing value", key) } -func redirectToLogin(ctx *gin.Context, session sessions.Session, oauth2Config *oauth2.Config) { +func redirectToLogin(w http.ResponseWriter, r *http.Request, oauth2Config *oauth2.Config) { state, err := state() if err != nil { - ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "generating state failed"}) - return - } - session.Set(stateSession, state) - err = session.Save() - if err != nil { - log.Println(err) - } - - ctx.Redirect(http.StatusFound, oauth2Config.AuthCodeURL(state)) - log.Println("abort", ctx.Request.URL.String()) - ctx.Abort() -} - -func AuthorizeBlockedUser(ctx *gin.Context) { - user, ok := busdb.UserFromContext(ctx) - if !ok { - ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "no user in context"}) + api.JSONErrorStatus(w, http.StatusInternalServerError, errors.New("generating state failed")) return } - if user.Blocked { - ctx.AbortWithStatusJSON(http.StatusForbidden, gin.H{"error": "user is blocked"}) - return - } + http.SetCookie(w, &http.Cookie{Name: stateSessionCookie, Value: state}) - ctx.Next() + http.Redirect(w, r, oauth2Config.AuthCodeURL(state), http.StatusFound) + return } -func AuthorizeRole(roles []role.Role) gin.HandlerFunc { - return func(ctx *gin.Context) { - user, ok := busdb.UserFromContext(ctx) - if !ok { - ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "no user in context"}) - return - } +func AuthorizeBlockedUser() func(http.Handler) http.Handler { + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + user, ok := busdb.UserFromContext(r.Context()) + if !ok { + api.JSONErrorStatus(w, http.StatusInternalServerError, errors.New("no user in context")) + return + } - if !role.UserHasRoles(user, roles) { - ctx.AbortWithStatusJSON(http.StatusForbidden, gin.H{"error": fmt.Sprintf("missing role %s has %s", roles, user.Roles)}) - return - } + if user.Blocked { + api.JSONErrorStatus(w, http.StatusForbidden, errors.New("user is blocked")) + return + } - ctx.Next() + next.ServeHTTP(w, r) + }) } } -func callback(config *AuthConfig) gin.HandlerFunc { - return func(ctx *gin.Context) { - session := sessions.Default(ctx) +func AuthorizeRole(roles []string) func(http.Handler) http.Handler { + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + user, ok := busdb.UserFromContext(r.Context()) + if !ok { + api.JSONErrorStatus(w, http.StatusInternalServerError, errors.New("no user in context")) + return + } - state := session.Get(stateSession) - if state == "" { - ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "state missing"}) + if !role.UserHasRoles(user, role.FromStrings(roles)) { + api.JSONErrorStatus(w, http.StatusForbidden, fmt.Errorf("missing role %s has %s", roles, user.Roles)) + return + } + + next.ServeHTTP(w, r) + }) + } +} + +func callback(config *AuthConfig) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + stateCookie, err := r.Cookie(stateSessionCookie) + if err != nil || stateCookie.Value == "" { + api.JSONErrorStatus(w, http.StatusInternalServerError, errors.New("state missing")) return } - if state != ctx.Query("state") { - ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "state mismatch"}) + if stateCookie.Value != r.URL.Query().Get("state") { + api.JSONErrorStatus(w, http.StatusInternalServerError, errors.New("state mismatch")) return } - oauth2Token, err := config.OAuth2.Exchange(ctx, ctx.Query("code")) + oauth2Token, err := config.OAuth2.Exchange(r.Context(), r.URL.Query().Get("code")) if err != nil { - ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": gin.H{"error": fmt.Sprintf("oauth2 exchange failed: %s", err)}}) + api.JSONErrorStatus(w, http.StatusInternalServerError, fmt.Errorf("oauth2 exchange failed: %w", err)) return } // Extract the ID Token from OAuth2 token. rawIDToken, ok := oauth2Token.Extra("id_token").(string) if !ok { - ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "missing id token"}) + api.JSONErrorStatus(w, http.StatusInternalServerError, errors.New("missing id token")) return } - oidcCtx, cancel := oidcCtx(ctx) - defer cancel() + // oidcCtx, cancel := oidcCtx(ctx) + // defer cancel() - verifier, err := config.Verifier(oidcCtx) + verifier, err := config.Verifier(r.Context()) if err != nil { - ctx.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "could not verify: " + err.Error()}) + api.JSONErrorStatus(w, http.StatusUnauthorized, fmt.Errorf("could not verify: %w", err)) return } // Parse and verify ID Token payload. - idToken, err := verifier.Verify(oidcCtx, rawIDToken) + idToken, err := verifier.Verify(r.Context(), rawIDToken) if err != nil { - ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "token verification failed: " + err.Error()}) + api.JSONErrorStatus(w, http.StatusInternalServerError, fmt.Errorf("token verification failed: %w", err)) return } // Extract custom claims var claims map[string]interface{} if err := idToken.Claims(&claims); err != nil { - ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "claim extraction failed"}) + api.JSONErrorStatus(w, http.StatusInternalServerError, errors.New("claim extraction failed")) return } - session.Set(userSession, claims) - err = session.Save() - if err != nil { - ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("could not save session %s", err)}) - return - } + b, _ := json.Marshal(claims) + http.SetCookie(w, &http.Cookie{Name: userSessionCookie, Value: base64.StdEncoding.EncodeToString(b)}) - ctx.Redirect(http.StatusFound, "/") + http.Redirect(w, r, "/", http.StatusFound) } } diff --git a/backup.go b/backup.go index 317059b..0c5128f 100644 --- a/backup.go +++ b/backup.go @@ -5,7 +5,6 @@ import ( "bytes" "io" "io/fs" - "log" "net/http" "os" "os/exec" @@ -13,20 +12,19 @@ import ( "strings" "github.com/aws/aws-sdk-go/service/s3" - "github.com/gin-gonic/gin" "github.com/SecurityBrewery/catalyst/database" + "github.com/SecurityBrewery/catalyst/generated/api" "github.com/SecurityBrewery/catalyst/storage" ) -func BackupHandler(catalystStorage *storage.Storage, c *database.Config) gin.HandlerFunc { - return func(context *gin.Context) { - context.Header("Content-Disposition", "attachment; filename=backup.zip") - context.Header("Content-Type", "application/zip") - err := Backup(catalystStorage, c, context.Writer) +func BackupHandler(catalystStorage *storage.Storage, c *database.Config) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Disposition", "attachment; filename=backup.zip") + w.Header().Set("Content-Type", "application/zip") + err := Backup(catalystStorage, c, w) if err != nil { - log.Println(err) - context.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + api.JSONError(w, err) } } } diff --git a/bus/job.go b/bus/job.go index 169fee4..d522ff0 100644 --- a/bus/job.go +++ b/bus/job.go @@ -6,24 +6,24 @@ import ( emitter "github.com/emitter-io/go/v2" - "github.com/SecurityBrewery/catalyst/generated/models" + "github.com/SecurityBrewery/catalyst/generated/model" ) const channelJob = "job" type JobMsg struct { - ID string `json:"id"` - Automation string `json:"automation"` - Origin *models.Origin `json:"origin"` - Message *models.Message `json:"message"` + ID string `json:"id"` + Automation string `json:"automation"` + Origin *model.Origin `json:"origin"` + Message *model.Message `json:"message"` } -func (b *Bus) PublishJob(id, automation string, payload interface{}, context *models.Context, origin *models.Origin) error { +func (b *Bus) PublishJob(id, automation string, payload interface{}, context *model.Context, origin *model.Origin) error { return b.jsonPublish(&JobMsg{ ID: id, Automation: automation, Origin: origin, - Message: &models.Message{ + Message: &model.Message{ Context: context, Payload: payload, }, diff --git a/bus/result.go b/bus/result.go index c564881..a81c699 100644 --- a/bus/result.go +++ b/bus/result.go @@ -6,7 +6,7 @@ import ( emitter "github.com/emitter-io/go/v2" - "github.com/SecurityBrewery/catalyst/generated/models" + "github.com/SecurityBrewery/catalyst/generated/model" ) const channelResult = "result" @@ -14,10 +14,10 @@ const channelResult = "result" type ResultMsg struct { Automation string `json:"automation"` Data map[string]interface{} `json:"data,omitempty"` - Target *models.Origin `json:"target"` + Target *model.Origin `json:"target"` } -func (b *Bus) PublishResult(automation string, data map[string]interface{}, target *models.Origin) error { +func (b *Bus) PublishResult(automation string, data map[string]interface{}, target *model.Origin) error { return b.jsonPublish(&ResultMsg{Automation: automation, Data: data, Target: target}, channelResult, b.config.resultBusKey) } diff --git a/busservice/busservice.go b/busservice/busservice.go index 4ff1d34..6a99500 100644 --- a/busservice/busservice.go +++ b/busservice/busservice.go @@ -7,7 +7,7 @@ import ( "github.com/SecurityBrewery/catalyst/bus" "github.com/SecurityBrewery/catalyst/database" "github.com/SecurityBrewery/catalyst/database/busdb" - "github.com/SecurityBrewery/catalyst/generated/models" + "github.com/SecurityBrewery/catalyst/generated/model" "github.com/SecurityBrewery/catalyst/role" "github.com/SecurityBrewery/catalyst/time" ) @@ -19,9 +19,9 @@ type busService struct { catalystBus *bus.Bus } -func New(apiurl, apikey string, catalystBus *bus.Bus, db *database.Database) error { +func New(apiURL, apikey string, catalystBus *bus.Bus, db *database.Database) error { - h := &busService{db: db, apiURL: apiurl, apiKey: apikey, catalystBus: catalystBus} + h := &busService{db: db, apiURL: apiURL, apiKey: apikey, catalystBus: catalystBus} if err := catalystBus.SubscribeRequest(h.logRequest); err != nil { return err @@ -38,14 +38,14 @@ func New(apiurl, apikey string, catalystBus *bus.Bus, db *database.Database) err func busContext() context.Context { // TODO: change roles? - bot := &models.UserResponse{ID: "bot", Roles: []string{role.Admin}} + bot := &model.UserResponse{ID: "bot", Roles: []string{role.Admin}} return busdb.UserContext(context.Background(), bot) } func (h *busService) logRequest(msg *bus.RequestMsg) { - var logEntries []*models.LogEntry + var logEntries []*model.LogEntry for _, i := range msg.IDs { - logEntries = append(logEntries, &models.LogEntry{ + logEntries = append(logEntries, &model.LogEntry{ Type: bus.ChannelRequest, Reference: i.String(), Creator: msg.User, diff --git a/busservice/job.go b/busservice/job.go index c520053..0636de2 100644 --- a/busservice/job.go +++ b/busservice/job.go @@ -6,13 +6,13 @@ import ( "log" "github.com/SecurityBrewery/catalyst/bus" - "github.com/SecurityBrewery/catalyst/generated/models" + "github.com/SecurityBrewery/catalyst/generated/model" ) func (h *busService) handleJob(automationMsg *bus.JobMsg) { ctx := busContext() - job, err := h.db.JobCreate(ctx, automationMsg.ID, &models.JobForm{ + job, err := h.db.JobCreate(ctx, automationMsg.ID, &model.JobForm{ Automation: automationMsg.Automation, Payload: automationMsg.Message.Payload, Origin: automationMsg.Origin, @@ -47,7 +47,7 @@ func (h *busService) handleJob(automationMsg *bus.JobMsg) { return } - if _, err := h.db.JobUpdate(ctx, automationMsg.ID, &models.Job{ + if _, err := h.db.JobUpdate(ctx, automationMsg.ID, &model.Job{ Automation: job.Automation, Container: &containerID, Origin: job.Origin, @@ -85,7 +85,7 @@ func (h *busService) handleJob(automationMsg *bus.JobMsg) { } /* -func getAutomation(automationID string, config *Config) (*models.AutomationResponse, error) { +func getAutomation(automationID string, config *Config) (*model.AutomationResponse, error) { req, err := http.NewRequest(http.MethodGet, config.CatalystAPIUrl+"/automations/"+automationID, nil) if err != nil { return nil, err @@ -104,7 +104,7 @@ func getAutomation(automationID string, config *Config) (*models.AutomationRespo return nil, err } - var automation models.AutomationResponse + var automation model.AutomationResponse if err := json.Unmarshal(b, &automation); err != nil { return nil, err } diff --git a/busservice/result.go b/busservice/result.go index 322f8cb..c1357fe 100644 --- a/busservice/result.go +++ b/busservice/result.go @@ -4,7 +4,7 @@ import ( "log" "github.com/SecurityBrewery/catalyst/bus" - "github.com/SecurityBrewery/catalyst/generated/models" + "github.com/SecurityBrewery/catalyst/generated/model" ) func (h *busService) handleResult(resultMsg *bus.ResultMsg) { @@ -22,7 +22,7 @@ func (h *busService) handleResult(resultMsg *bus.ResultMsg) { log.Println(err) } case resultMsg.Target.ArtifactOrigin != nil: - enrichment := &models.EnrichmentForm{ + enrichment := &model.EnrichmentForm{ Data: resultMsg.Data, Name: resultMsg.Automation, } diff --git a/cmd/catalyst-dev/main.go b/cmd/catalyst-dev/main.go index a42f795..cd0f313 100644 --- a/cmd/catalyst-dev/main.go +++ b/cmd/catalyst-dev/main.go @@ -3,18 +3,16 @@ package main import ( "context" "log" + "net/http" "net/http/httputil" "net/url" "github.com/arangodb/go-driver" - "github.com/gin-contrib/sessions" - "github.com/gin-contrib/sessions/cookie" - "github.com/gin-gonic/gin" "github.com/SecurityBrewery/catalyst" "github.com/SecurityBrewery/catalyst/cmd" "github.com/SecurityBrewery/catalyst/database/busdb" - "github.com/SecurityBrewery/catalyst/generated/models" + "github.com/SecurityBrewery/catalyst/generated/model" "github.com/SecurityBrewery/catalyst/hooks" "github.com/SecurityBrewery/catalyst/role" "github.com/SecurityBrewery/catalyst/test" @@ -36,30 +34,25 @@ func main() { log.Fatal(err) } - demoUser := &models.UserResponse{ID: "demo", Roles: []string{role.Admin}} + demoUser := &model.UserResponse{ID: "demo", Roles: []string{role.Admin}} ctx := busdb.UserContext(context.Background(), demoUser) if err := test.SetupTestData(ctx, theCatalyst.DB); err != nil { log.Fatal(err) } // proxy static requests - theCatalyst.Server.NoRoute( - sessions.Sessions(catalyst.SessionName, cookie.NewStore(config.Secret)), - catalyst.Authenticate(theCatalyst.DB, config.Auth), - catalyst.AuthorizeBlockedUser, - proxy, - ) + theCatalyst.Server.With(catalyst.Authenticate(theCatalyst.DB, config.Auth), catalyst.AuthorizeBlockedUser()).NotFound(proxy) - if err = theCatalyst.Server.RunWithSigHandler(); err != nil { + if err := http.ListenAndServe(":8000", theCatalyst.Server); err != nil { log.Fatal(err) } } -func proxy(ctx *gin.Context) { +func proxy(w http.ResponseWriter, r *http.Request) { u, _ := url.Parse("http://localhost:8080") proxy := httputil.NewSingleHostReverseProxy(u) - ctx.Request.Host = ctx.Request.URL.Host + r.Host = r.URL.Host - proxy.ServeHTTP(ctx.Writer, ctx.Request) + proxy.ServeHTTP(w, r) } diff --git a/cmd/catalyst/main.go b/cmd/catalyst/main.go index e2f3f02..4bb1302 100644 --- a/cmd/catalyst/main.go +++ b/cmd/catalyst/main.go @@ -2,6 +2,7 @@ package main import ( "log" + "net/http" "github.com/SecurityBrewery/catalyst" "github.com/SecurityBrewery/catalyst/cmd" @@ -21,7 +22,7 @@ func main() { log.Fatal(err) } - if err = theCatalyst.Server.RunWithSigHandler(); err != nil { + if err := http.ListenAndServe(":8000", theCatalyst.Server); err != nil { log.Fatal(err) } } diff --git a/cmd/cmd.go b/cmd/cmd.go index a895be9..1b10ee4 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -11,7 +11,7 @@ import ( "github.com/SecurityBrewery/catalyst" "github.com/SecurityBrewery/catalyst/bus" "github.com/SecurityBrewery/catalyst/database" - "github.com/SecurityBrewery/catalyst/generated/models" + "github.com/SecurityBrewery/catalyst/generated/model" "github.com/SecurityBrewery/catalyst/pointer" "github.com/SecurityBrewery/catalyst/role" "github.com/SecurityBrewery/catalyst/storage" @@ -72,10 +72,10 @@ func MapConfig(cli CLI) (*catalyst.Config, error) { } if len(artifactStates) == 0 { - artifactStates = []*models.Type{ - {Icon: "mdi-help-circle-outline", ID: "unknown", Name: "Unknown", Color: pointer.String(models.TypeColorInfo)}, - {Icon: "mdi-skull", ID: "malicious", Name: "Malicious", Color: pointer.String(models.TypeColorError)}, - {Icon: "mdi-check", ID: "clean", Name: "Clean", Color: pointer.String(models.TypeColorSuccess)}, + artifactStates = []*model.Type{ + {Icon: "mdi-help-circle-outline", ID: "unknown", Name: "Unknown", Color: pointer.String(model.TypeColorInfo)}, + {Icon: "mdi-skull", ID: "malicious", Name: "Malicious", Color: pointer.String(model.TypeColorError)}, + {Icon: "mdi-check", ID: "clean", Name: "Clean", Color: pointer.String(model.TypeColorSuccess)}, } } @@ -96,21 +96,21 @@ func MapConfig(cli CLI) (*catalyst.Config, error) { AuthDefaultRoles: roles, }, Bus: &bus.Config{Host: cli.EmitterIOHost, Key: cli.EmitterIORKey, APIUrl: cli.CatalystAddress + "/api"}, - UISettings: &models.Settings{ + UISettings: &model.Settings{ ArtifactStates: artifactStates, Timeformat: cli.Timeformat, Version: catalyst.GetVersion(), - Tier: models.SettingsTierCommunity, + Tier: model.SettingsTierCommunity, }, InitialAPIKey: cli.InitialAPIKey, } return config, nil } -func toTypes(params []map[string]string) ([]*models.Type, error) { - var types []*models.Type +func toTypes(params []map[string]string) ([]*model.Type, error) { + var types []*model.Type for _, param := range params { - t := &models.Type{} + t := &model.Type{} icon, iconOK := param["icon"] if iconOK { diff --git a/database/artifact.go b/database/artifact.go index c34b634..acb8909 100644 --- a/database/artifact.go +++ b/database/artifact.go @@ -8,11 +8,11 @@ import ( "github.com/SecurityBrewery/catalyst/bus" "github.com/SecurityBrewery/catalyst/database/busdb" - "github.com/SecurityBrewery/catalyst/generated/models" + "github.com/SecurityBrewery/catalyst/generated/model" "github.com/SecurityBrewery/catalyst/time" ) -func (db *Database) ArtifactGet(ctx context.Context, id int64, name string) (*models.Artifact, error) { +func (db *Database) ArtifactGet(ctx context.Context, id int64, name string) (*model.Artifact, error) { ticketFilterQuery, ticketFilterVars, err := db.Hooks.TicketWriteFilter(ctx) if err != nil { return nil, err @@ -33,7 +33,7 @@ func (db *Database) ArtifactGet(ctx context.Context, id int64, name string) (*mo } defer cursor.Close() - var doc models.Artifact + var doc model.Artifact _, err = cursor.ReadDocument(ctx, &doc) if err != nil { return nil, err @@ -42,7 +42,7 @@ func (db *Database) ArtifactGet(ctx context.Context, id int64, name string) (*mo return &doc, nil } -func (db *Database) ArtifactUpdate(ctx context.Context, id int64, name string, artifact *models.Artifact) (*models.TicketWithTickets, error) { +func (db *Database) ArtifactUpdate(ctx context.Context, id int64, name string, artifact *model.Artifact) (*model.TicketWithTickets, error) { ticketFilterQuery, ticketFilterVars, err := db.Hooks.TicketWriteFilter(ctx) if err != nil { return nil, err @@ -68,8 +68,8 @@ func (db *Database) ArtifactUpdate(ctx context.Context, id int64, name string, a }) } -func (db *Database) EnrichArtifact(ctx context.Context, id int64, name string, enrichmentForm *models.EnrichmentForm) (*models.TicketWithTickets, error) { - enrichment := models.Enrichment{time.Now().UTC(), enrichmentForm.Data, enrichmentForm.Name} +func (db *Database) EnrichArtifact(ctx context.Context, id int64, name string, enrichmentForm *model.EnrichmentForm) (*model.TicketWithTickets, error) { + enrichment := model.Enrichment{time.Now().UTC(), enrichmentForm.Data, enrichmentForm.Name} ticketFilterQuery, ticketFilterVars, err := db.Hooks.TicketWriteFilter(ctx) if err != nil { diff --git a/database/automation.go b/database/automation.go index 287371a..9004b03 100644 --- a/database/automation.go +++ b/database/automation.go @@ -7,11 +7,11 @@ import ( "github.com/arangodb/go-driver" "github.com/SecurityBrewery/catalyst/database/busdb" - "github.com/SecurityBrewery/catalyst/generated/models" + "github.com/SecurityBrewery/catalyst/generated/model" ) -func toAutomation(doc *models.AutomationForm) interface{} { - return &models.Automation{ +func toAutomation(doc *model.AutomationForm) interface{} { + return &model.Automation{ Image: doc.Image, Script: doc.Script, Schema: doc.Schema, @@ -19,8 +19,8 @@ func toAutomation(doc *models.AutomationForm) interface{} { } } -func toAutomationResponse(id string, doc models.Automation) *models.AutomationResponse { - return &models.AutomationResponse{ +func toAutomationResponse(id string, doc model.Automation) *model.AutomationResponse { + return &model.AutomationResponse{ ID: id, Image: doc.Image, Script: doc.Script, @@ -29,7 +29,7 @@ func toAutomationResponse(id string, doc models.Automation) *models.AutomationRe } } -func (db *Database) AutomationCreate(ctx context.Context, automation *models.AutomationForm) (*models.AutomationResponse, error) { +func (db *Database) AutomationCreate(ctx context.Context, automation *model.AutomationForm) (*model.AutomationResponse, error) { if automation == nil { return nil, errors.New("requires automation") } @@ -37,7 +37,7 @@ func (db *Database) AutomationCreate(ctx context.Context, automation *models.Aut return nil, errors.New("requires automation ID") } - var doc models.Automation + var doc model.Automation newctx := driver.WithReturnNew(ctx, &doc) meta, err := db.automationCollection.CreateDocument(ctx, newctx, automation.ID, toAutomation(automation)) @@ -48,8 +48,8 @@ func (db *Database) AutomationCreate(ctx context.Context, automation *models.Aut return toAutomationResponse(meta.Key, doc), nil } -func (db *Database) AutomationGet(ctx context.Context, id string) (*models.AutomationResponse, error) { - var doc models.Automation +func (db *Database) AutomationGet(ctx context.Context, id string) (*model.AutomationResponse, error) { + var doc model.Automation meta, err := db.automationCollection.ReadDocument(ctx, id, &doc) if err != nil { return nil, err @@ -58,8 +58,8 @@ func (db *Database) AutomationGet(ctx context.Context, id string) (*models.Autom return toAutomationResponse(meta.Key, doc), nil } -func (db *Database) AutomationUpdate(ctx context.Context, id string, automation *models.AutomationForm) (*models.AutomationResponse, error) { - var doc models.Automation +func (db *Database) AutomationUpdate(ctx context.Context, id string, automation *model.AutomationForm) (*model.AutomationResponse, error) { + var doc model.Automation ctx = driver.WithReturnNew(ctx, &doc) meta, err := db.automationCollection.ReplaceDocument(ctx, id, toAutomation(automation)) @@ -75,16 +75,16 @@ func (db *Database) AutomationDelete(ctx context.Context, id string) error { return err } -func (db *Database) AutomationList(ctx context.Context) ([]*models.AutomationResponse, error) { +func (db *Database) AutomationList(ctx context.Context) ([]*model.AutomationResponse, error) { query := "FOR d IN @@collection SORT d._key ASC RETURN UNSET(d, 'script')" cursor, _, err := db.Query(ctx, query, map[string]interface{}{"@collection": AutomationCollectionName}, busdb.ReadOperation) if err != nil { return nil, err } defer cursor.Close() - var docs []*models.AutomationResponse + var docs []*model.AutomationResponse for { - var doc models.Automation + var doc model.Automation meta, err := cursor.ReadDocument(ctx, &doc) if driver.IsNoMoreDocuments(err) { break diff --git a/database/busdb/busdb.go b/database/busdb/busdb.go index 8d1074d..9b384f0 100644 --- a/database/busdb/busdb.go +++ b/database/busdb/busdb.go @@ -2,11 +2,13 @@ package busdb import ( "context" + "errors" "github.com/arangodb/go-driver" "github.com/SecurityBrewery/catalyst/bus" - "github.com/SecurityBrewery/catalyst/generated/models" + "github.com/SecurityBrewery/catalyst/generated/api" + "github.com/SecurityBrewery/catalyst/generated/model" ) // BusDatabase @@ -41,14 +43,14 @@ type Operation struct { var CreateOperation = &Operation{Type: bus.DatabaseEntryCreated} var ReadOperation = &Operation{Type: bus.DatabaseEntryRead} -func (db BusDatabase) Query(ctx context.Context, query string, vars map[string]interface{}, operation *Operation) (driver.Cursor, *models.LogEntry, error) { - cur, err := db.internal.Query(ctx, query, vars) +func (db BusDatabase) Query(ctx context.Context, query string, vars map[string]interface{}, operation *Operation) (cur driver.Cursor, logs *model.LogEntry, err error) { + defer func() { err = toHTTPErr(err) }() + + cur, err = db.internal.Query(ctx, query, vars) if err != nil { return nil, nil, err } - var logs *models.LogEntry - switch { case operation.Type == bus.DatabaseEntryCreated, operation.Type == bus.DatabaseEntryUpdated: if err := db.bus.PublishDatabaseUpdate(operation.Ids, operation.Type); err != nil { @@ -59,11 +61,15 @@ func (db BusDatabase) Query(ctx context.Context, query string, vars map[string]i return cur, logs, err } -func (db BusDatabase) Remove(ctx context.Context) error { +func (db BusDatabase) Remove(ctx context.Context) (err error) { + defer func() { err = toHTTPErr(err) }() + return db.internal.Remove(ctx) } -func (db BusDatabase) Collection(ctx context.Context, name string) (driver.Collection, error) { +func (db BusDatabase) Collection(ctx context.Context, name string) (col driver.Collection, err error) { + defer func() { err = toHTTPErr(err) }() + return db.internal.Collection(ctx, name) } @@ -76,8 +82,10 @@ func NewCollection(internal driver.Collection, db *BusDatabase) *Collection { return &Collection{internal: internal, db: db} } -func (c Collection) CreateDocument(ctx, newctx context.Context, key string, document interface{}) (driver.DocumentMeta, error) { - meta, err := c.internal.CreateDocument(newctx, &Keyed{Key: key, Doc: document}) +func (c Collection) CreateDocument(ctx, newctx context.Context, key string, document interface{}) (meta driver.DocumentMeta, err error) { + defer func() { err = toHTTPErr(err) }() + + meta, err = c.internal.CreateDocument(newctx, &Keyed{Key: key, Doc: document}) if err != nil { return meta, err } @@ -89,8 +97,10 @@ func (c Collection) CreateDocument(ctx, newctx context.Context, key string, docu return meta, nil } -func (c Collection) CreateEdge(ctx, newctx context.Context, edge *driver.EdgeDocument) (driver.DocumentMeta, error) { - meta, err := c.internal.CreateDocument(newctx, edge) +func (c Collection) CreateEdge(ctx, newctx context.Context, edge *driver.EdgeDocument) (meta driver.DocumentMeta, err error) { + defer func() { err = toHTTPErr(err) }() + + meta, err = c.internal.CreateDocument(newctx, edge) if err != nil { return meta, err } @@ -102,7 +112,9 @@ func (c Collection) CreateEdge(ctx, newctx context.Context, edge *driver.EdgeDoc return meta, nil } -func (c Collection) CreateEdges(ctx context.Context, edges []*driver.EdgeDocument) (driver.DocumentMetaSlice, error) { +func (c Collection) CreateEdges(ctx context.Context, edges []*driver.EdgeDocument) (meta driver.DocumentMetaSlice, err error) { + defer func() { err = toHTTPErr(err) }() + metas, errs, err := c.internal.CreateDocuments(ctx, edges) if err != nil { return nil, err @@ -124,16 +136,24 @@ func (c Collection) CreateEdges(ctx context.Context, edges []*driver.EdgeDocumen return metas, nil } -func (c Collection) DocumentExists(ctx context.Context, id string) (bool, error) { +func (c Collection) DocumentExists(ctx context.Context, id string) (exists bool, err error) { + defer func() { err = toHTTPErr(err) }() + return c.internal.DocumentExists(ctx, id) } -func (c Collection) ReadDocument(ctx context.Context, key string, result interface{}) (driver.DocumentMeta, error) { - return c.internal.ReadDocument(ctx, key, result) +func (c Collection) ReadDocument(ctx context.Context, key string, result interface{}) (meta driver.DocumentMeta, err error) { + defer func() { err = toHTTPErr(err) }() + + meta, err = c.internal.ReadDocument(ctx, key, result) + + return } -func (c Collection) UpdateDocument(ctx context.Context, key string, update interface{}) (driver.DocumentMeta, error) { - meta, err := c.internal.UpdateDocument(ctx, key, update) +func (c Collection) UpdateDocument(ctx context.Context, key string, update interface{}) (meta driver.DocumentMeta, err error) { + defer func() { err = toHTTPErr(err) }() + + meta, err = c.internal.UpdateDocument(ctx, key, update) if err != nil { return meta, err } @@ -141,8 +161,10 @@ func (c Collection) UpdateDocument(ctx context.Context, key string, update inter return meta, c.db.bus.PublishDatabaseUpdate([]driver.DocumentID{meta.ID}, bus.DatabaseEntryUpdated) } -func (c Collection) ReplaceDocument(ctx context.Context, key string, document interface{}) (driver.DocumentMeta, error) { - meta, err := c.internal.ReplaceDocument(ctx, key, document) +func (c Collection) ReplaceDocument(ctx context.Context, key string, document interface{}) (meta driver.DocumentMeta, err error) { + defer func() { err = toHTTPErr(err) }() + + meta, err = c.internal.ReplaceDocument(ctx, key, document) if err != nil { return meta, err } @@ -150,10 +172,24 @@ func (c Collection) ReplaceDocument(ctx context.Context, key string, document in return meta, c.db.bus.PublishDatabaseUpdate([]driver.DocumentID{meta.ID}, bus.DatabaseEntryUpdated) } -func (c Collection) RemoveDocument(ctx context.Context, formatInt string) (driver.DocumentMeta, error) { +func (c Collection) RemoveDocument(ctx context.Context, formatInt string) (meta driver.DocumentMeta, err error) { + defer func() { err = toHTTPErr(err) }() + return c.internal.RemoveDocument(ctx, formatInt) } -func (c Collection) Truncate(ctx context.Context) error { +func (c Collection) Truncate(ctx context.Context) (err error) { + defer func() { err = toHTTPErr(err) }() + return c.internal.Truncate(ctx) } + +func toHTTPErr(err error) error { + if err != nil { + ae := driver.ArangoError{} + if errors.As(err, &ae) { + return &api.HTTPError{Status: ae.Code, Internal: err} + } + } + return nil +} diff --git a/database/busdb/context.go b/database/busdb/context.go index 206487f..0edbc66 100644 --- a/database/busdb/context.go +++ b/database/busdb/context.go @@ -2,10 +2,9 @@ package busdb import ( "context" + "net/http" - "github.com/gin-gonic/gin" - - "github.com/SecurityBrewery/catalyst/generated/models" + "github.com/SecurityBrewery/catalyst/generated/model" "github.com/SecurityBrewery/catalyst/role" ) @@ -14,21 +13,22 @@ const ( groupContextKey = "groups" ) -func SetContext(ctx *gin.Context, user *models.UserResponse) { +func SetContext(r *http.Request, user *model.UserResponse) *http.Request { user.Roles = role.Strings(role.Explodes(user.Roles)) - ctx.Set(userContextKey, user) + + return r.WithContext(context.WithValue(r.Context(), userContextKey, user)) } -func SetGroupContext(ctx *gin.Context, groups []string) { - ctx.Set(groupContextKey, groups) +func SetGroupContext(r *http.Request, groups []string) *http.Request { + return r.WithContext(context.WithValue(r.Context(), groupContextKey, groups)) } -func UserContext(ctx context.Context, user *models.UserResponse) context.Context { +func UserContext(ctx context.Context, user *model.UserResponse) context.Context { user.Roles = role.Strings(role.Explodes(user.Roles)) return context.WithValue(ctx, userContextKey, user) } -func UserFromContext(ctx context.Context) (*models.UserResponse, bool) { - u, ok := ctx.Value(userContextKey).(*models.UserResponse) +func UserFromContext(ctx context.Context) (*model.UserResponse, bool) { + u, ok := ctx.Value(userContextKey).(*model.UserResponse) return u, ok } diff --git a/database/busdb/log.go b/database/busdb/log.go index c16de36..1b33036 100644 --- a/database/busdb/log.go +++ b/database/busdb/log.go @@ -3,24 +3,24 @@ package busdb import ( "context" "errors" - "github.com/SecurityBrewery/catalyst/bus" "strings" "github.com/arangodb/go-driver" - "github.com/SecurityBrewery/catalyst/generated/models" + "github.com/SecurityBrewery/catalyst/bus" + "github.com/SecurityBrewery/catalyst/generated/model" "github.com/SecurityBrewery/catalyst/time" ) const LogCollectionName = "logs" -func (db *BusDatabase) LogCreate(ctx context.Context, logType, reference, message string) (*models.LogEntry, error) { +func (db *BusDatabase) LogCreate(ctx context.Context, logType, reference, message string) (*model.LogEntry, error) { user, ok := UserFromContext(ctx) if !ok { return nil, errors.New("no user in context") } - logentry := &models.LogEntry{ + logentry := &model.LogEntry{ Type: logType, Reference: reference, Created: time.Now().UTC(), @@ -28,7 +28,7 @@ func (db *BusDatabase) LogCreate(ctx context.Context, logType, reference, messag Message: message, } - doc := models.LogEntry{} + doc := model.LogEntry{} _, err := db.logCollection.CreateDocument(driver.WithReturnNew(ctx, &doc), logentry) if err != nil { return nil, err @@ -37,7 +37,7 @@ func (db *BusDatabase) LogCreate(ctx context.Context, logType, reference, messag return &doc, nil } -func (db *BusDatabase) LogBatchCreate(ctx context.Context, logentries []*models.LogEntry) error { +func (db *BusDatabase) LogBatchCreate(ctx context.Context, logentries []*model.LogEntry) error { var ids []driver.DocumentID for _, entry := range logentries { if strings.HasPrefix(entry.Reference, "tickets/") { @@ -60,7 +60,7 @@ func (db *BusDatabase) LogBatchCreate(ctx context.Context, logentries []*models. return nil } -func (db *BusDatabase) LogList(ctx context.Context, reference string) ([]*models.LogEntry, error) { +func (db *BusDatabase) LogList(ctx context.Context, reference string) ([]*model.LogEntry, error) { query := "FOR d IN @@collection FILTER d.reference == @reference SORT d.created DESC RETURN d" cursor, err := db.internal.Query(ctx, query, map[string]interface{}{ "@collection": LogCollectionName, @@ -70,9 +70,9 @@ func (db *BusDatabase) LogList(ctx context.Context, reference string) ([]*models return nil, err } defer cursor.Close() - var docs []*models.LogEntry + var docs []*model.LogEntry for { - var doc models.LogEntry + var doc model.LogEntry _, err := cursor.ReadDocument(ctx, &doc) if driver.IsNoMoreDocuments(err) { break diff --git a/database/job.go b/database/job.go index f3cfbce..58dae9e 100644 --- a/database/job.go +++ b/database/job.go @@ -14,11 +14,11 @@ import ( "github.com/SecurityBrewery/catalyst/bus" "github.com/SecurityBrewery/catalyst/caql" "github.com/SecurityBrewery/catalyst/database/busdb" - "github.com/SecurityBrewery/catalyst/generated/models" + "github.com/SecurityBrewery/catalyst/generated/model" ) -func toJob(doc *models.JobForm) *models.Job { - return &models.Job{ +func toJob(doc *model.JobForm) *model.Job { + return &model.Job{ Automation: doc.Automation, Payload: doc.Payload, Origin: doc.Origin, @@ -27,7 +27,7 @@ func toJob(doc *models.JobForm) *models.Job { } } -func (db *Database) toJobResponse(ctx context.Context, key string, doc *models.Job, update bool) (*models.JobResponse, error) { +func (db *Database) toJobResponse(ctx context.Context, key string, doc *model.Job, update bool) (*model.JobResponse, error) { cli, err := client.NewClientWithOpts(client.FromEnv) if err != nil { return nil, err @@ -52,7 +52,7 @@ func (db *Database) toJobResponse(ctx context.Context, key string, doc *models.J } } - return &models.JobResponse{ + return &model.JobResponse{ Automation: doc.Automation, ID: key, Log: doc.Log, @@ -64,19 +64,19 @@ func (db *Database) toJobResponse(ctx context.Context, key string, doc *models.J }, nil } -func (db *Database) JobCreate(ctx context.Context, id string, job *models.JobForm) (*models.JobResponse, error) { +func (db *Database) JobCreate(ctx context.Context, id string, job *model.JobForm) (*model.JobResponse, error) { if job == nil { return nil, errors.New("requires job") } - var doc models.Job + var doc model.Job newctx := driver.WithReturnNew(ctx, &doc) /* Start validation */ j := toJob(job) b, _ := json.Marshal(j) - r, err := models.JobSchema.Validate(gojsonschema.NewBytesLoader(b)) + r, err := model.JobSchema.Validate(gojsonschema.NewBytesLoader(b)) if err != nil { return nil, err } @@ -98,8 +98,8 @@ func (db *Database) JobCreate(ctx context.Context, id string, job *models.JobFor return db.toJobResponse(ctx, meta.Key, &doc, true) } -func (db *Database) JobGet(ctx context.Context, id string) (*models.JobResponse, error) { - var doc models.Job +func (db *Database) JobGet(ctx context.Context, id string) (*model.JobResponse, error) { + var doc model.Job meta, err := db.jobCollection.ReadDocument(ctx, id, &doc) if err != nil { return nil, err @@ -108,14 +108,14 @@ func (db *Database) JobGet(ctx context.Context, id string) (*models.JobResponse, return db.toJobResponse(ctx, meta.Key, &doc, true) } -func (db *Database) JobUpdate(ctx context.Context, id string, job *models.Job) (*models.JobResponse, error) { - var doc models.Job +func (db *Database) JobUpdate(ctx context.Context, id string, job *model.Job) (*model.JobResponse, error) { + var doc model.Job ctx = driver.WithReturnNew(ctx, &doc) /* Start validation */ b, _ := json.Marshal(job) - r, err := models.JobSchema.Validate(gojsonschema.NewBytesLoader(b)) + r, err := model.JobSchema.Validate(gojsonschema.NewBytesLoader(b)) if err != nil { return nil, err } @@ -184,16 +184,16 @@ func (db *Database) JobDelete(ctx context.Context, id string) error { return err } -func (db *Database) JobList(ctx context.Context) ([]*models.JobResponse, error) { +func (db *Database) JobList(ctx context.Context) ([]*model.JobResponse, error) { query := "FOR d IN @@collection RETURN d" cursor, _, err := db.Query(ctx, query, map[string]interface{}{"@collection": JobCollectionName}, busdb.ReadOperation) if err != nil { return nil, err } defer cursor.Close() - var docs []*models.JobResponse + var docs []*model.JobResponse for { - var doc models.Job + var doc model.Job meta, err := cursor.ReadDocument(ctx, &doc) if driver.IsNoMoreDocuments(err) { break @@ -212,7 +212,7 @@ func (db *Database) JobList(ctx context.Context) ([]*models.JobResponse, error) return docs, err } -func publishJobMapping(id, automation string, contextStructs *models.Context, origin *models.Origin, payloadMapping map[string]string, db *Database) error { +func publishJobMapping(id, automation string, contextStructs *model.Context, origin *model.Origin, payloadMapping map[string]string, db *Database) error { msg, err := generatePayload(payloadMapping, contextStructs) if err != nil { return fmt.Errorf("message generation failed: %w", err) @@ -221,11 +221,11 @@ func publishJobMapping(id, automation string, contextStructs *models.Context, or return publishJob(id, automation, contextStructs, origin, msg, db) } -func publishJob(id, automation string, contextStructs *models.Context, origin *models.Origin, payload map[string]interface{}, db *Database) error { +func publishJob(id, automation string, contextStructs *model.Context, origin *model.Origin, payload map[string]interface{}, db *Database) error { return db.bus.PublishJob(id, automation, payload, contextStructs, origin) } -func generatePayload(msgMapping map[string]string, contextStructs *models.Context) (map[string]interface{}, error) { +func generatePayload(msgMapping map[string]string, contextStructs *model.Context) (map[string]interface{}, error) { contextJson, err := json.Marshal(contextStructs) if err != nil { return nil, err diff --git a/database/migrations/migrations.go b/database/migrations/migrations.go index 5329717..6d7bff2 100644 --- a/database/migrations/migrations.go +++ b/database/migrations/migrations.go @@ -7,7 +7,7 @@ import ( "github.com/arangodb/go-driver" "github.com/SecurityBrewery/catalyst/database/busdb" - "github.com/SecurityBrewery/catalyst/generated/models" + "github.com/SecurityBrewery/catalyst/generated/model" "github.com/SecurityBrewery/catalyst/pointer" ) @@ -32,23 +32,23 @@ func generateMigrations() ([]Migration, error) { &createGraph{ID: "create-ticket-graph", Name: "Graph", EdgeDefinitions: []driver.EdgeDefinition{{Collection: "related", From: []string{"tickets"}, To: []string{"tickets"}}}}, - &createDocument{ID: "create-template-default", Collection: "templates", Document: &busdb.Keyed{Key: "default", Doc: models.TicketTemplate{Schema: DefaultTemplateSchema, Name: "Default"}}}, - &createDocument{ID: "create-automation-vt.hash", Collection: "automations", Document: &busdb.Keyed{Key: "vt.hash", Doc: models.Automation{Image: "docker.io/python:3", Script: VTHashAutomation}}}, - &createDocument{ID: "create-automation-comment", Collection: "automations", Document: &busdb.Keyed{Key: "comment", Doc: models.Automation{Image: "docker.io/python:3", Script: CommentAutomation}}}, - &createDocument{ID: "create-automation-thehive", Collection: "automations", Document: &busdb.Keyed{Key: "thehive", Doc: models.Automation{Image: "docker.io/python:3", Script: TheHiveAutomation}}}, - &createDocument{ID: "create-automation-hash.sha1", Collection: "automations", Document: &busdb.Keyed{Key: "hash.sha1", Doc: models.Automation{Image: "docker.io/python:3", Script: SHA1HashAutomation}}}, - &createDocument{ID: "create-playbook-malware", Collection: "playbooks", Document: &busdb.Keyed{Key: "malware", Doc: models.PlaybookTemplate{Name: "Malware", Yaml: MalwarePlaybook}}}, - &createDocument{ID: "create-playbook-phishing", Collection: "playbooks", Document: &busdb.Keyed{Key: "phishing", Doc: models.PlaybookTemplate{Name: "Phishing", Yaml: PhishingPlaybook}}}, - &createDocument{ID: "create-tickettype-alert", Collection: "tickettypes", Document: &busdb.Keyed{Key: "alert", Doc: models.TicketType{Name: "Alerts", Icon: "mdi-alert", DefaultTemplate: "default", DefaultPlaybooks: []string{}, DefaultGroups: nil}}}, - &createDocument{ID: "create-tickettype-incident", Collection: "tickettypes", Document: &busdb.Keyed{Key: "incident", Doc: models.TicketType{Name: "Incidents", Icon: "mdi-radioactive", DefaultTemplate: "default", DefaultPlaybooks: []string{}, DefaultGroups: nil}}}, - &createDocument{ID: "create-tickettype-investigation", Collection: "tickettypes", Document: &busdb.Keyed{Key: "investigation", Doc: models.TicketType{Name: "Forensic Investigations", Icon: "mdi-fingerprint", DefaultTemplate: "default", DefaultPlaybooks: []string{}, DefaultGroups: nil}}}, - &createDocument{ID: "create-tickettype-hunt", Collection: "tickettypes", Document: &busdb.Keyed{Key: "hunt", Doc: models.TicketType{Name: "Threat Hunting", Icon: "mdi-target", DefaultTemplate: "default", DefaultPlaybooks: []string{}, DefaultGroups: nil}}}, + &createDocument{ID: "create-template-default", Collection: "templates", Document: &busdb.Keyed{Key: "default", Doc: model.TicketTemplate{Schema: DefaultTemplateSchema, Name: "Default"}}}, + &createDocument{ID: "create-automation-vt.hash", Collection: "automations", Document: &busdb.Keyed{Key: "vt.hash", Doc: model.Automation{Image: "docker.io/python:3", Script: VTHashAutomation}}}, + &createDocument{ID: "create-automation-comment", Collection: "automations", Document: &busdb.Keyed{Key: "comment", Doc: model.Automation{Image: "docker.io/python:3", Script: CommentAutomation}}}, + &createDocument{ID: "create-automation-thehive", Collection: "automations", Document: &busdb.Keyed{Key: "thehive", Doc: model.Automation{Image: "docker.io/python:3", Script: TheHiveAutomation}}}, + &createDocument{ID: "create-automation-hash.sha1", Collection: "automations", Document: &busdb.Keyed{Key: "hash.sha1", Doc: model.Automation{Image: "docker.io/python:3", Script: SHA1HashAutomation}}}, + &createDocument{ID: "create-playbook-malware", Collection: "playbooks", Document: &busdb.Keyed{Key: "malware", Doc: model.PlaybookTemplate{Name: "Malware", Yaml: MalwarePlaybook}}}, + &createDocument{ID: "create-playbook-phishing", Collection: "playbooks", Document: &busdb.Keyed{Key: "phishing", Doc: model.PlaybookTemplate{Name: "Phishing", Yaml: PhishingPlaybook}}}, + &createDocument{ID: "create-tickettype-alert", Collection: "tickettypes", Document: &busdb.Keyed{Key: "alert", Doc: model.TicketType{Name: "Alerts", Icon: "mdi-alert", DefaultTemplate: "default", DefaultPlaybooks: []string{}, DefaultGroups: nil}}}, + &createDocument{ID: "create-tickettype-incident", Collection: "tickettypes", Document: &busdb.Keyed{Key: "incident", Doc: model.TicketType{Name: "Incidents", Icon: "mdi-radioactive", DefaultTemplate: "default", DefaultPlaybooks: []string{}, DefaultGroups: nil}}}, + &createDocument{ID: "create-tickettype-investigation", Collection: "tickettypes", Document: &busdb.Keyed{Key: "investigation", Doc: model.TicketType{Name: "Forensic Investigations", Icon: "mdi-fingerprint", DefaultTemplate: "default", DefaultPlaybooks: []string{}, DefaultGroups: nil}}}, + &createDocument{ID: "create-tickettype-hunt", Collection: "tickettypes", Document: &busdb.Keyed{Key: "hunt", Doc: model.TicketType{Name: "Threat Hunting", Icon: "mdi-target", DefaultTemplate: "default", DefaultPlaybooks: []string{}, DefaultGroups: nil}}}, &updateSchema{ID: "update-automation-collection-1", Name: "automations", DataType: "automation", Schema: `{"properties":{"image":{"type":"string"},"script":{"type":"string"}},"required":["image","script"],"type":"object"}`}, - &updateDocument{ID: "update-automation-vt.hash-1", Collection: "automations", Key: "vt.hash", Document: models.Automation{Image: "docker.io/python:3", Script: VTHashAutomation, Schema: pointer.String(`{"title":"Input","type":"object","properties":{"default":{"type":"string","title":"Value"}},"required":["default"]}`), Type: []string{"global", "artifact", "playbook"}}}, - &updateDocument{ID: "update-automation-comment-1", Collection: "automations", Key: "comment", Document: models.Automation{Image: "docker.io/python:3", Script: CommentAutomation, Type: []string{"playbook"}}}, - &updateDocument{ID: "update-automation-thehive-1", Collection: "automations", Key: "thehive", Document: models.Automation{Image: "docker.io/python:3", Script: TheHiveAutomation, Schema: pointer.String(`{"title":"TheHive credentials","type":"object","properties":{"thehiveurl":{"type":"string","title":"TheHive URL (e.g. 'https://thehive.example.org')"},"thehivekey":{"type":"string","title":"TheHive API Key"},"skip_files":{"type":"boolean", "default": true, "title":"Skip Files (much faster)"},"keep_ids":{"type":"boolean", "default": true, "title":"Keep IDs and overwrite existing IDs"}},"required":["thehiveurl", "thehivekey", "skip_files", "keep_ids"]}`), Type: []string{"global"}}}, - &updateDocument{ID: "update-automation-hash.sha1-1", Collection: "automations", Key: "hash.sha1", Document: models.Automation{Image: "docker.io/python:3", Script: SHA1HashAutomation, Schema: pointer.String(`{"title":"Input","type":"object","properties":{"default":{"type":"string","title":"Value"}},"required":["default"]}`), Type: []string{"global", "artifact", "playbook"}}}, + &updateDocument{ID: "update-automation-vt.hash-1", Collection: "automations", Key: "vt.hash", Document: model.Automation{Image: "docker.io/python:3", Script: VTHashAutomation, Schema: pointer.String(`{"title":"Input","type":"object","properties":{"default":{"type":"string","title":"Value"}},"required":["default"]}`), Type: []string{"global", "artifact", "playbook"}}}, + &updateDocument{ID: "update-automation-comment-1", Collection: "automations", Key: "comment", Document: model.Automation{Image: "docker.io/python:3", Script: CommentAutomation, Type: []string{"playbook"}}}, + &updateDocument{ID: "update-automation-thehive-1", Collection: "automations", Key: "thehive", Document: model.Automation{Image: "docker.io/python:3", Script: TheHiveAutomation, Schema: pointer.String(`{"title":"TheHive credentials","type":"object","properties":{"thehiveurl":{"type":"string","title":"TheHive URL (e.g. 'https://thehive.example.org')"},"thehivekey":{"type":"string","title":"TheHive API Key"},"skip_files":{"type":"boolean", "default": true, "title":"Skip Files (much faster)"},"keep_ids":{"type":"boolean", "default": true, "title":"Keep IDs and overwrite existing IDs"}},"required":["thehiveurl", "thehivekey", "skip_files", "keep_ids"]}`), Type: []string{"global"}}}, + &updateDocument{ID: "update-automation-hash.sha1-1", Collection: "automations", Key: "hash.sha1", Document: model.Automation{Image: "docker.io/python:3", Script: SHA1HashAutomation, Schema: pointer.String(`{"title":"Input","type":"object","properties":{"default":{"type":"string","title":"Value"}},"required":["default"]}`), Type: []string{"global", "artifact", "playbook"}}}, &createCollection{ID: "create-job-collection", Name: "jobs", DataType: "job", Schema: `{"properties":{"automation":{"type":"string"},"log":{"type":"string"},"payload":{},"origin":{"properties":{"artifact_origin":{"properties":{"artifact":{"type":"string"},"ticket_id":{"format":"int64","type":"integer"}},"required":["artifact","ticket_id"],"type":"object"},"task_origin":{"properties":{"playbook_id":{"type":"string"},"task_id":{"type":"string"},"ticket_id":{"format":"int64","type":"integer"}},"required":["playbook_id","task_id","ticket_id"],"type":"object"}},"type":"object"},"output":{"properties":{},"type":"object"},"running":{"type":"boolean"},"status":{"type":"string"}},"required":["automation","running","status"],"type":"object"}`}, }, nil diff --git a/database/playbook.go b/database/playbook.go index b2d9a2d..ac08f79 100644 --- a/database/playbook.go +++ b/database/playbook.go @@ -10,7 +10,7 @@ import ( "gopkg.in/yaml.v3" "github.com/SecurityBrewery/catalyst/database/busdb" - "github.com/SecurityBrewery/catalyst/generated/models" + "github.com/SecurityBrewery/catalyst/generated/model" "github.com/SecurityBrewery/catalyst/time" ) @@ -29,8 +29,8 @@ type TaskYAML struct { Join bool `yaml:"join"` } -func toPlaybooks(docs []*models.PlaybookTemplateForm) (map[string]*models.Playbook, error) { - playbooks := map[string]*models.Playbook{} +func toPlaybooks(docs []*model.PlaybookTemplateForm) (map[string]*model.Playbook, error) { + playbooks := map[string]*model.Playbook{} for _, doc := range docs { playbook, err := toPlaybook(doc) if err != nil { @@ -45,15 +45,15 @@ func toPlaybooks(docs []*models.PlaybookTemplateForm) (map[string]*models.Playbo return playbooks, nil } -func toPlaybook(doc *models.PlaybookTemplateForm) (*models.Playbook, error) { - ticketPlaybook := &models.Playbook{} +func toPlaybook(doc *model.PlaybookTemplateForm) (*model.Playbook, error) { + ticketPlaybook := &model.Playbook{} err := yaml.Unmarshal([]byte(doc.Yaml), ticketPlaybook) if err != nil { return nil, err } for idx, task := range ticketPlaybook.Tasks { if task.Schema != nil { - task.Schema = dyno.ConvertMapI2MapS(task.Schema.(map[string]interface{})) + task.Schema = dyno.ConvertMapI2MapS(task.Schema).(map[string]interface{}) } task.Created = time.Now().UTC() ticketPlaybook.Tasks[idx] = task @@ -61,11 +61,11 @@ func toPlaybook(doc *models.PlaybookTemplateForm) (*models.Playbook, error) { return ticketPlaybook, nil } -func toPlaybookTemplateResponse(key string, doc *models.PlaybookTemplate) *models.PlaybookTemplateResponse { - return &models.PlaybookTemplateResponse{ID: key, Name: doc.Name, Yaml: doc.Yaml} +func toPlaybookTemplateResponse(key string, doc *model.PlaybookTemplate) *model.PlaybookTemplateResponse { + return &model.PlaybookTemplateResponse{ID: key, Name: doc.Name, Yaml: doc.Yaml} } -func (db *Database) PlaybookCreate(ctx context.Context, playbook *models.PlaybookTemplateForm) (*models.PlaybookTemplateResponse, error) { +func (db *Database) PlaybookCreate(ctx context.Context, playbook *model.PlaybookTemplateForm) (*model.PlaybookTemplateResponse, error) { if playbook == nil { return nil, errors.New("requires playbook") } @@ -79,9 +79,9 @@ func (db *Database) PlaybookCreate(ctx context.Context, playbook *models.Playboo if playbookYAML.Name == "" { return nil, errors.New("requires template name") } - p := models.PlaybookTemplate{Name: playbookYAML.Name, Yaml: playbook.Yaml} + p := model.PlaybookTemplate{Name: playbookYAML.Name, Yaml: playbook.Yaml} - var doc models.PlaybookTemplate + var doc model.PlaybookTemplate newctx := driver.WithReturnNew(ctx, &doc) meta, err := db.playbookCollection.CreateDocument(ctx, newctx, strcase.ToKebab(playbookYAML.Name), p) @@ -92,8 +92,8 @@ func (db *Database) PlaybookCreate(ctx context.Context, playbook *models.Playboo return toPlaybookTemplateResponse(meta.Key, &doc), nil } -func (db *Database) PlaybookGet(ctx context.Context, id string) (*models.PlaybookTemplateResponse, error) { - doc := models.PlaybookTemplate{} +func (db *Database) PlaybookGet(ctx context.Context, id string) (*model.PlaybookTemplateResponse, error) { + doc := model.PlaybookTemplate{} meta, err := db.playbookCollection.ReadDocument(ctx, id, &doc) if err != nil { return nil, err @@ -107,7 +107,7 @@ func (db *Database) PlaybookDelete(ctx context.Context, id string) error { return err } -func (db *Database) PlaybookUpdate(ctx context.Context, id string, playbook *models.PlaybookTemplateForm) (*models.PlaybookTemplateResponse, error) { +func (db *Database) PlaybookUpdate(ctx context.Context, id string, playbook *model.PlaybookTemplateForm) (*model.PlaybookTemplateResponse, error) { var pb PlaybookYAML err := yaml.Unmarshal([]byte(playbook.Yaml), &pb) if err != nil { @@ -118,10 +118,10 @@ func (db *Database) PlaybookUpdate(ctx context.Context, id string, playbook *mod return nil, errors.New("requires template name") } - var doc models.PlaybookTemplate + var doc model.PlaybookTemplate ctx = driver.WithReturnNew(ctx, &doc) - meta, err := db.playbookCollection.ReplaceDocument(ctx, id, models.PlaybookTemplate{Name: pb.Name, Yaml: playbook.Yaml}) + meta, err := db.playbookCollection.ReplaceDocument(ctx, id, model.PlaybookTemplate{Name: pb.Name, Yaml: playbook.Yaml}) if err != nil { return nil, err } @@ -129,16 +129,16 @@ func (db *Database) PlaybookUpdate(ctx context.Context, id string, playbook *mod return toPlaybookTemplateResponse(meta.Key, &doc), nil } -func (db *Database) PlaybookList(ctx context.Context) ([]*models.PlaybookTemplateResponse, error) { +func (db *Database) PlaybookList(ctx context.Context) ([]*model.PlaybookTemplateResponse, error) { query := "FOR d IN @@collection RETURN d" cursor, _, err := db.Query(ctx, query, map[string]interface{}{"@collection": PlaybookCollectionName}, busdb.ReadOperation) if err != nil { return nil, err } defer cursor.Close() - var docs []*models.PlaybookTemplateResponse + var docs []*model.PlaybookTemplateResponse for { - var doc models.PlaybookTemplate + var doc model.PlaybookTemplate meta, err := cursor.ReadDocument(ctx, &doc) if driver.IsNoMoreDocuments(err) { break diff --git a/database/playbookutils.go b/database/playbookutils.go index 2df7eef..df97d21 100644 --- a/database/playbookutils.go +++ b/database/playbookutils.go @@ -8,10 +8,10 @@ import ( "github.com/SecurityBrewery/catalyst/caql" "github.com/SecurityBrewery/catalyst/dag" - "github.com/SecurityBrewery/catalyst/generated/models" + "github.com/SecurityBrewery/catalyst/generated/model" ) -func playbookGraph(playbook *models.Playbook) (*dag.Graph, error) { +func playbookGraph(playbook *model.Playbook) (*dag.Graph, error) { d := dag.NewGraph() var taskIDs []string @@ -36,13 +36,13 @@ func playbookGraph(playbook *models.Playbook) (*dag.Graph, error) { return d, nil } -func toTaskResponse(playbook *models.Playbook, taskID string, order int, graph *dag.Graph) (*models.TaskResponse, error) { +func toTaskResponse(playbook *model.Playbook, taskID string, order int, graph *dag.Graph) (*model.TaskResponse, error) { task, ok := playbook.Tasks[taskID] if !ok { return nil, fmt.Errorf("task %s not found", taskID) } - tr := &models.TaskResponse{ + tr := &model.TaskResponse{ Automation: task.Automation, Closed: task.Closed, Created: task.Created, @@ -67,7 +67,7 @@ func toTaskResponse(playbook *models.Playbook, taskID string, order int, graph * return tr, nil } -func activePlaybook(playbook *models.Playbook, taskID string) (bool, error) { +func activePlaybook(playbook *model.Playbook, taskID string) (bool, error) { task, ok := playbook.Tasks[taskID] if !ok { return false, fmt.Errorf("playbook does not contain tasks %s", taskID) @@ -81,7 +81,7 @@ func activePlaybook(playbook *models.Playbook, taskID string) (bool, error) { return active(playbook, taskID, d, task) } -func active(playbook *models.Playbook, taskID string, d *dag.Graph, task *models.Task) (bool, error) { +func active(playbook *model.Playbook, taskID string, d *dag.Graph, task *model.Task) (bool, error) { if task.Done { return false, nil } @@ -165,7 +165,7 @@ func evalRequirement(aql string, data interface{}) (bool, error) { /* // "github.com/qri-io/jsonschema" -func valid(task *models.Task) (bool, error) { +func valid(task *model.Task) (bool, error) { schema, err := json.Marshal(task.Schema) if err != nil { return false, err diff --git a/database/playbookutils_test.go b/database/playbookutils_test.go index 25ed2bf..3208cfb 100644 --- a/database/playbookutils_test.go +++ b/database/playbookutils_test.go @@ -5,12 +5,12 @@ import ( "github.com/stretchr/testify/assert" - "github.com/SecurityBrewery/catalyst/generated/models" + "github.com/SecurityBrewery/catalyst/generated/model" ) -var playbook2 = &models.Playbook{ +var playbook2 = &model.Playbook{ Name: "Phishing", - Tasks: map[string]*models.Task{ + Tasks: map[string]*model.Task{ "board": {Next: map[string]string{ "escalate": "boardInvolved == true", "aquire-mail": "boardInvolved == false", @@ -30,9 +30,9 @@ var playbook2 = &models.Playbook{ }, } -var playbook3 = &models.Playbook{ +var playbook3 = &model.Playbook{ Name: "Phishing", - Tasks: map[string]*models.Task{ + Tasks: map[string]*model.Task{ "board": {Next: map[string]string{ "escalate": "boardInvolved == true", "aquire-mail": "boardInvolved == false", @@ -52,9 +52,9 @@ var playbook3 = &models.Playbook{ }, } -var playbook4 = &models.Playbook{ +var playbook4 = &model.Playbook{ Name: "Malware", - Tasks: map[string]*models.Task{ + Tasks: map[string]*model.Task{ "file-or-hash": {Next: map[string]string{ "enter-hash": "file == 'Hash'", "upload": "file == 'File'", @@ -72,7 +72,7 @@ var playbook4 = &models.Playbook{ func Test_canBeCompleted(t *testing.T) { type args struct { - playbook *models.Playbook + playbook *model.Playbook taskID string } tests := []struct { @@ -106,7 +106,7 @@ func Test_canBeCompleted(t *testing.T) { func Test_playbookOrder(t *testing.T) { type args struct { - playbook *models.Playbook + playbook *model.Playbook } tests := []struct { name string diff --git a/database/settings.go b/database/settings.go index 67136b7..ddfff22 100644 --- a/database/settings.go +++ b/database/settings.go @@ -5,14 +5,13 @@ import ( "errors" "github.com/arangodb/go-driver" - "github.com/gin-gonic/gin" "github.com/SecurityBrewery/catalyst/database/busdb" - "github.com/SecurityBrewery/catalyst/generated/models" + "github.com/SecurityBrewery/catalyst/generated/model" ) -func toUserDataResponse(key string, doc *models.UserData) *models.UserDataResponse { - return &models.UserDataResponse{ +func toUserDataResponse(key string, doc *model.UserData) *model.UserDataResponse { + return &model.UserDataResponse{ Email: doc.Email, ID: key, Image: doc.Image, @@ -21,7 +20,7 @@ func toUserDataResponse(key string, doc *models.UserData) *models.UserDataRespon } } -func (db *Database) UserDataCreate(ctx context.Context, id string, userdata *models.UserData) error { +func (db *Database) UserDataCreate(ctx context.Context, id string, userdata *model.UserData) error { if userdata == nil { return errors.New("requires setting") } @@ -33,7 +32,7 @@ func (db *Database) UserDataCreate(ctx context.Context, id string, userdata *mod return err } -func (db *Database) UserDataGetOrCreate(ctx *gin.Context, id string, newUserData *models.UserData) (*models.UserDataResponse, error) { +func (db *Database) UserDataGetOrCreate(ctx context.Context, id string, newUserData *model.UserData) (*model.UserDataResponse, error) { setting, err := db.UserDataGet(ctx, id) if err != nil { return toUserDataResponse(id, newUserData), db.UserDataCreate(ctx, id, newUserData) @@ -41,8 +40,8 @@ func (db *Database) UserDataGetOrCreate(ctx *gin.Context, id string, newUserData return setting, nil } -func (db *Database) UserDataGet(ctx context.Context, id string) (*models.UserDataResponse, error) { - var doc models.UserData +func (db *Database) UserDataGet(ctx context.Context, id string) (*model.UserDataResponse, error) { + var doc model.UserData meta, err := db.userdataCollection.ReadDocument(ctx, id, &doc) if err != nil { return nil, err @@ -51,16 +50,16 @@ func (db *Database) UserDataGet(ctx context.Context, id string) (*models.UserDat return toUserDataResponse(meta.Key, &doc), err } -func (db *Database) UserDataList(ctx context.Context) ([]*models.UserDataResponse, error) { +func (db *Database) UserDataList(ctx context.Context) ([]*model.UserDataResponse, error) { query := "FOR d IN @@collection SORT d.username ASC RETURN d" cursor, _, err := db.Query(ctx, query, map[string]interface{}{"@collection": UserDataCollectionName}, busdb.ReadOperation) if err != nil { return nil, err } defer cursor.Close() - var docs []*models.UserDataResponse + var docs []*model.UserDataResponse for { - var doc models.UserData + var doc model.UserData meta, err := cursor.ReadDocument(ctx, &doc) if driver.IsNoMoreDocuments(err) { break @@ -73,8 +72,8 @@ func (db *Database) UserDataList(ctx context.Context) ([]*models.UserDataRespons return docs, err } -func (db *Database) UserDataUpdate(ctx context.Context, id string, userdata *models.UserData) (*models.UserDataResponse, error) { - var doc models.UserData +func (db *Database) UserDataUpdate(ctx context.Context, id string, userdata *model.UserData) (*model.UserDataResponse, error) { + var doc model.UserData ctx = driver.WithReturnNew(ctx, &doc) meta, err := db.userdataCollection.ReplaceDocument(ctx, id, userdata) diff --git a/database/settings_test.go b/database/settings_test.go index 52adc05..f52ab68 100644 --- a/database/settings_test.go +++ b/database/settings_test.go @@ -3,24 +3,19 @@ package database_test import ( "testing" - "github.com/gin-gonic/gin" "github.com/stretchr/testify/assert" - "github.com/SecurityBrewery/catalyst/generated/models" + "github.com/SecurityBrewery/catalyst/generated/model" "github.com/SecurityBrewery/catalyst/pointer" "github.com/SecurityBrewery/catalyst/test" ) -func init() { - gin.SetMode(gin.TestMode) -} - -var bob = &models.UserData{ +var bob = &model.UserData{ Email: pointer.String("bob@example.org"), Name: pointer.String("Bob"), } -var bobResponse = &models.UserDataResponse{ +var bobResponse = &model.UserDataResponse{ ID: "bob", Email: pointer.String("bob@example.org"), Name: pointer.String("Bob"), @@ -29,7 +24,7 @@ var bobResponse = &models.UserDataResponse{ func TestDatabase_UserDataCreate(t *testing.T) { type args struct { id string - setting *models.UserData + setting *model.UserData } tests := []struct { name string @@ -63,7 +58,7 @@ func TestDatabase_UserDataGet(t *testing.T) { tests := []struct { name string args args - want *models.UserDataResponse + want *model.UserDataResponse wantErr bool }{ {name: "Normal get", args: args{id: "bob"}, want: bobResponse}, @@ -98,10 +93,10 @@ func TestDatabase_UserDataGet(t *testing.T) { func TestDatabase_UserDataList(t *testing.T) { tests := []struct { name string - want []*models.UserDataResponse + want []*model.UserDataResponse wantErr bool }{ - {name: "Normal list", want: []*models.UserDataResponse{bobResponse}}, + {name: "Normal list", want: []*model.UserDataResponse{bobResponse}}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -129,7 +124,7 @@ func TestDatabase_UserDataList(t *testing.T) { func TestDatabase_UserDataUpdate(t *testing.T) { type args struct { id string - setting *models.UserData + setting *model.UserData } tests := []struct { name string diff --git a/database/statistics.go b/database/statistics.go index 3073f94..55f5394 100644 --- a/database/statistics.go +++ b/database/statistics.go @@ -4,10 +4,10 @@ import ( "context" "github.com/SecurityBrewery/catalyst/database/busdb" - "github.com/SecurityBrewery/catalyst/generated/models" + "github.com/SecurityBrewery/catalyst/generated/model" ) -func (db *Database) Statistics(ctx context.Context) (*models.Statistics, error) { +func (db *Database) Statistics(ctx context.Context) (*model.Statistics, error) { query := `RETURN { tickets_per_type: MERGE(FOR d in tickets COLLECT type = d.type WITH COUNT INTO typecount @@ -34,7 +34,7 @@ func (db *Database) Statistics(ctx context.Context) (*models.Statistics, error) } defer cur.Close() - statistics := models.Statistics{} + statistics := model.Statistics{} if _, err := cur.ReadDocument(ctx, &statistics); err != nil { return nil, err } diff --git a/database/task.go b/database/task.go index b8b2d81..dc08b60 100644 --- a/database/task.go +++ b/database/task.go @@ -6,18 +6,18 @@ import ( "github.com/arangodb/go-driver" "github.com/SecurityBrewery/catalyst/database/busdb" - "github.com/SecurityBrewery/catalyst/generated/models" + "github.com/SecurityBrewery/catalyst/generated/model" ) type playbookResponse struct { - PlaybookId string `json:"playbook_id"` - PlaybookName string `json:"playbook_name"` - Playbook models.Playbook `json:"playbook"` - TicketId int64 `json:"ticket_id"` - TicketName string `json:"ticket_name"` + PlaybookId string `json:"playbook_id"` + PlaybookName string `json:"playbook_name"` + Playbook model.Playbook `json:"playbook"` + TicketId int64 `json:"ticket_id"` + TicketName string `json:"ticket_name"` } -func (db *Database) TaskList(ctx context.Context) ([]*models.TaskWithContext, error) { +func (db *Database) TaskList(ctx context.Context) ([]*model.TaskWithContext, error) { ticketFilterQuery, ticketFilterVars, err := db.Hooks.TicketWriteFilter(ctx) if err != nil { return nil, err @@ -35,7 +35,7 @@ func (db *Database) TaskList(ctx context.Context) ([]*models.TaskWithContext, er return nil, err } defer cursor.Close() - docs := []*models.TaskWithContext{} + var docs []*model.TaskWithContext for { var doc playbookResponse _, err := cursor.ReadDocument(ctx, &doc) @@ -45,7 +45,6 @@ func (db *Database) TaskList(ctx context.Context) ([]*models.TaskWithContext, er return nil, err } - playbook, err := toPlaybookResponse(&doc.Playbook) if err != nil { return nil, err @@ -53,10 +52,10 @@ func (db *Database) TaskList(ctx context.Context) ([]*models.TaskWithContext, er for _, task := range playbook.Tasks { if task.Active { - docs = append(docs, &models.TaskWithContext{ + docs = append(docs, &model.TaskWithContext{ PlaybookId: doc.PlaybookId, PlaybookName: doc.PlaybookName, - Task: *task, + Task: task, TicketId: doc.TicketId, TicketName: doc.TicketName, }) diff --git a/database/template.go b/database/template.go index 5e33996..5a41e06 100644 --- a/database/template.go +++ b/database/template.go @@ -8,18 +8,18 @@ import ( "github.com/iancoleman/strcase" "github.com/SecurityBrewery/catalyst/database/busdb" - "github.com/SecurityBrewery/catalyst/generated/models" + "github.com/SecurityBrewery/catalyst/generated/model" ) -func toTicketTemplate(doc *models.TicketTemplateForm) *models.TicketTemplate { - return &models.TicketTemplate{Name: doc.Name, Schema: doc.Schema} +func toTicketTemplate(doc *model.TicketTemplateForm) *model.TicketTemplate { + return &model.TicketTemplate{Name: doc.Name, Schema: doc.Schema} } -func toTicketTemplateResponse(key string, doc *models.TicketTemplate) *models.TicketTemplateResponse { - return &models.TicketTemplateResponse{ID: key, Name: doc.Name, Schema: doc.Schema} +func toTicketTemplateResponse(key string, doc *model.TicketTemplate) *model.TicketTemplateResponse { + return &model.TicketTemplateResponse{ID: key, Name: doc.Name, Schema: doc.Schema} } -func (db *Database) TemplateCreate(ctx context.Context, template *models.TicketTemplateForm) (*models.TicketTemplateResponse, error) { +func (db *Database) TemplateCreate(ctx context.Context, template *model.TicketTemplateForm) (*model.TicketTemplateResponse, error) { if template == nil { return nil, errors.New("requires template") } @@ -27,7 +27,7 @@ func (db *Database) TemplateCreate(ctx context.Context, template *models.TicketT return nil, errors.New("requires template name") } - var doc models.TicketTemplate + var doc model.TicketTemplate newctx := driver.WithReturnNew(ctx, &doc) meta, err := db.templateCollection.CreateDocument(ctx, newctx, strcase.ToKebab(template.Name), toTicketTemplate(template)) @@ -38,8 +38,8 @@ func (db *Database) TemplateCreate(ctx context.Context, template *models.TicketT return toTicketTemplateResponse(meta.Key, &doc), nil } -func (db *Database) TemplateGet(ctx context.Context, id string) (*models.TicketTemplateResponse, error) { - var doc models.TicketTemplate +func (db *Database) TemplateGet(ctx context.Context, id string) (*model.TicketTemplateResponse, error) { + var doc model.TicketTemplate meta, err := db.templateCollection.ReadDocument(ctx, id, &doc) if err != nil { return nil, err @@ -48,8 +48,8 @@ func (db *Database) TemplateGet(ctx context.Context, id string) (*models.TicketT return toTicketTemplateResponse(meta.Key, &doc), nil } -func (db *Database) TemplateUpdate(ctx context.Context, id string, template *models.TicketTemplateForm) (*models.TicketTemplateResponse, error) { - var doc models.TicketTemplate +func (db *Database) TemplateUpdate(ctx context.Context, id string, template *model.TicketTemplateForm) (*model.TicketTemplateResponse, error) { + var doc model.TicketTemplate ctx = driver.WithReturnNew(ctx, &doc) meta, err := db.templateCollection.ReplaceDocument(ctx, id, toTicketTemplate(template)) @@ -65,16 +65,16 @@ func (db *Database) TemplateDelete(ctx context.Context, id string) error { return err } -func (db *Database) TemplateList(ctx context.Context) ([]*models.TicketTemplateResponse, error) { +func (db *Database) TemplateList(ctx context.Context) ([]*model.TicketTemplateResponse, error) { query := "FOR d IN @@collection RETURN d" cursor, _, err := db.Query(ctx, query, map[string]interface{}{"@collection": TemplateCollectionName}, busdb.ReadOperation) if err != nil { return nil, err } defer cursor.Close() - var docs []*models.TicketTemplateResponse + var docs []*model.TicketTemplateResponse for { - var doc models.TicketTemplate + var doc model.TicketTemplate meta, err := cursor.ReadDocument(ctx, &doc) if driver.IsNoMoreDocuments(err) { break diff --git a/database/template_test.go b/database/template_test.go index 76fa1c6..00311d8 100644 --- a/database/template_test.go +++ b/database/template_test.go @@ -6,22 +6,22 @@ import ( "github.com/stretchr/testify/assert" "github.com/SecurityBrewery/catalyst/database/migrations" - "github.com/SecurityBrewery/catalyst/generated/models" + "github.com/SecurityBrewery/catalyst/generated/model" "github.com/SecurityBrewery/catalyst/test" ) -var template1 = &models.TicketTemplateForm{ +var template1 = &model.TicketTemplateForm{ Schema: migrations.DefaultTemplateSchema, Name: "Template 1", } -var default1 = &models.TicketTemplateForm{ +var default1 = &model.TicketTemplateForm{ Schema: migrations.DefaultTemplateSchema, Name: "Default", } func TestDatabase_TemplateCreate(t *testing.T) { type args struct { - template *models.TicketTemplateForm + template *model.TicketTemplateForm } tests := []struct { name string @@ -31,8 +31,8 @@ func TestDatabase_TemplateCreate(t *testing.T) { {name: "Normal", args: args{template: template1}}, {name: "Duplicate", args: args{template: default1}, wantErr: true}, {name: "Nil template", args: args{}, wantErr: true}, - {name: "Template without fields", args: args{template: &models.TicketTemplateForm{}}, wantErr: true}, - {name: "Only name", args: args{template: &models.TicketTemplateForm{Name: "name"}}, wantErr: false}, + {name: "Template without fields", args: args{template: &model.TicketTemplateForm{}}, wantErr: true}, + {name: "Only name", args: args{template: &model.TicketTemplateForm{Name: "name"}}, wantErr: false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -87,10 +87,10 @@ func TestDatabase_TemplateGet(t *testing.T) { tests := []struct { name string args args - want *models.TicketTemplateResponse + want *model.TicketTemplateResponse wantErr bool }{ - {name: "Normal", args: args{id: "default"}, want: &models.TicketTemplateResponse{ID: "default", Name: "Default", Schema: migrations.DefaultTemplateSchema}}, + {name: "Normal", args: args{id: "default"}, want: &model.TicketTemplateResponse{ID: "default", Name: "Default", Schema: migrations.DefaultTemplateSchema}}, {name: "Not existing", args: args{id: "foobar"}, wantErr: true}, } for _, tt := range tests { @@ -122,10 +122,10 @@ func TestDatabase_TemplateGet(t *testing.T) { func TestDatabase_TemplateList(t *testing.T) { tests := []struct { name string - want []*models.TicketTemplateResponse + want []*model.TicketTemplateResponse wantErr bool }{ - {name: "Normal", want: []*models.TicketTemplateResponse{{ID: "default", Name: "Default", Schema: migrations.DefaultTemplateSchema}, {ID: "template-1", Name: template1.Name, Schema: template1.Schema}}}, + {name: "Normal", want: []*model.TicketTemplateResponse{{ID: "default", Name: "Default", Schema: migrations.DefaultTemplateSchema}, {ID: "template-1", Name: template1.Name, Schema: template1.Schema}}}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -152,7 +152,7 @@ func TestDatabase_TemplateList(t *testing.T) { func TestDatabase_TemplateUpdate(t *testing.T) { type args struct { id string - template *models.TicketTemplateForm + template *model.TicketTemplateForm } tests := []struct { name string diff --git a/database/ticket.go b/database/ticket.go index 7aac399..39519d3 100644 --- a/database/ticket.go +++ b/database/ticket.go @@ -16,18 +16,18 @@ import ( "github.com/SecurityBrewery/catalyst/bus" "github.com/SecurityBrewery/catalyst/caql" "github.com/SecurityBrewery/catalyst/database/busdb" - "github.com/SecurityBrewery/catalyst/generated/models" + "github.com/SecurityBrewery/catalyst/generated/model" "github.com/SecurityBrewery/catalyst/index" "github.com/SecurityBrewery/catalyst/time" ) -func toTicket(ticketForm *models.TicketForm) (interface{}, error) { +func toTicket(ticketForm *model.TicketForm) (interface{}, error) { playbooks, err := toPlaybooks(ticketForm.Playbooks) if err != nil { return nil, err } - ticket := &models.Ticket{ + ticket := &model.Ticket{ Artifacts: ticketForm.Artifacts, Comments: ticketForm.Comments, Details: ticketForm.Details, @@ -70,8 +70,8 @@ func toTicket(ticketForm *models.TicketForm) (interface{}, error) { return ticket, nil } -func toTicketResponses(tickets []*models.TicketSimpleResponse) ([]*models.TicketResponse, error) { - var extendedTickets []*models.TicketResponse +func toTicketResponses(tickets []*model.TicketSimpleResponse) ([]*model.TicketResponse, error) { + var extendedTickets []*model.TicketResponse for _, simple := range tickets { tr, err := toTicketResponse(simple) if err != nil { @@ -82,13 +82,13 @@ func toTicketResponses(tickets []*models.TicketSimpleResponse) ([]*models.Ticket return extendedTickets, nil } -func toTicketResponse(ticket *models.TicketSimpleResponse) (*models.TicketResponse, error) { +func toTicketResponse(ticket *model.TicketSimpleResponse) (*model.TicketResponse, error) { playbooks, err := toPlaybookResponses(ticket.Playbooks) if err != nil { return nil, err } - return &models.TicketResponse{ + return &model.TicketResponse{ ID: ticket.ID, Artifacts: ticket.Artifacts, Comments: ticket.Comments, @@ -108,13 +108,13 @@ func toTicketResponse(ticket *models.TicketSimpleResponse) (*models.TicketRespon }, nil } -func toTicketSimpleResponse(key string, ticket *models.Ticket) (*models.TicketSimpleResponse, error) { +func toTicketSimpleResponse(key string, ticket *model.Ticket) (*model.TicketSimpleResponse, error) { id, err := strconv.ParseInt(key, 10, 64) if err != nil { return nil, err } - return &models.TicketSimpleResponse{ + return &model.TicketSimpleResponse{ Artifacts: ticket.Artifacts, Comments: ticket.Comments, Created: ticket.Created, @@ -134,8 +134,8 @@ func toTicketSimpleResponse(key string, ticket *models.Ticket) (*models.TicketSi }, nil } -func toTicketWithTickets(ticketResponse *models.TicketResponse, tickets []*models.TicketSimpleResponse, logs []*models.LogEntry) *models.TicketWithTickets { - return &models.TicketWithTickets{ +func toTicketWithTickets(ticketResponse *model.TicketResponse, tickets []*model.TicketSimpleResponse, logs []*model.LogEntry) *model.TicketWithTickets { + return &model.TicketWithTickets{ Artifacts: ticketResponse.Artifacts, Comments: ticketResponse.Comments, Created: ticketResponse.Created, @@ -158,8 +158,8 @@ func toTicketWithTickets(ticketResponse *models.TicketResponse, tickets []*model } } -func toPlaybookResponses(playbooks map[string]*models.Playbook) (map[string]*models.PlaybookResponse, error) { - pr := map[string]*models.PlaybookResponse{} +func toPlaybookResponses(playbooks map[string]*model.Playbook) (map[string]*model.PlaybookResponse, error) { + pr := map[string]*model.PlaybookResponse{} var err error for k, v := range playbooks { pr[k], err = toPlaybookResponse(v) @@ -170,15 +170,15 @@ func toPlaybookResponses(playbooks map[string]*models.Playbook) (map[string]*mod return pr, nil } -func toPlaybookResponse(playbook *models.Playbook) (*models.PlaybookResponse, error) { +func toPlaybookResponse(playbook *model.Playbook) (*model.PlaybookResponse, error) { graph, err := playbookGraph(playbook) if err != nil { return nil, err } - re := &models.PlaybookResponse{ + re := &model.PlaybookResponse{ Name: playbook.Name, - Tasks: map[string]*models.TaskResponse{}, + Tasks: map[string]*model.TaskResponse{}, } results, err := graph.Toposort() @@ -198,7 +198,7 @@ func toPlaybookResponse(playbook *models.Playbook) (*models.PlaybookResponse, er return re, nil } -func (db *Database) TicketBatchCreate(ctx context.Context, ticketForms []*models.TicketForm) ([]*models.TicketResponse, error) { +func (db *Database) TicketBatchCreate(ctx context.Context, ticketForms []*model.TicketForm) ([]*model.TicketResponse, error) { update, err := db.Hooks.IngestionFilter(ctx, db.Index) if err != nil { return nil, err @@ -211,7 +211,7 @@ func (db *Database) TicketBatchCreate(ctx context.Context, ticketForms []*models return nil, err } - if err := validate(ticket, models.TicketSchema); err != nil { + if err := validate(ticket, model.TicketSchema); err != nil { return nil, err } @@ -278,26 +278,26 @@ func (db *Database) IndexRebuild(ctx context.Context) error { return batchIndex(db.Index, tickets) } -func batchIndex(index *index.Index, tickets []*models.TicketSimpleResponse) error { +func batchIndex(index *index.Index, tickets []*model.TicketSimpleResponse) error { var wg sync.WaitGroup - var batch []*models.TicketSimpleResponse + var batch []*model.TicketSimpleResponse for _, ticket := range tickets { batch = append(batch, ticket) if len(batch) > 100 { wg.Add(1) - go func(docs []*models.TicketSimpleResponse) { + go func(docs []*model.TicketSimpleResponse) { index.Index(docs) wg.Done() }(batch) - batch = []*models.TicketSimpleResponse{} + batch = []*model.TicketSimpleResponse{} } } wg.Wait() return nil } -func (db *Database) TicketGet(ctx context.Context, ticketID int64) (*models.TicketWithTickets, error) { +func (db *Database) TicketGet(ctx context.Context, ticketID int64) (*model.TicketWithTickets, error) { ticketFilterQuery, ticketFilterVars, err := db.Hooks.TicketReadFilter(ctx) if err != nil { return nil, err @@ -306,7 +306,7 @@ func (db *Database) TicketGet(ctx context.Context, ticketID int64) (*models.Tick return db.ticketGetQuery(ctx, ticketID, `LET d = DOCUMENT(@@collection, @ID) `+ticketFilterQuery+` RETURN d`, ticketFilterVars, busdb.ReadOperation) } -func (db *Database) ticketGetQuery(ctx context.Context, ticketID int64, query string, bindVars map[string]interface{}, operation *busdb.Operation) (*models.TicketWithTickets, error) { +func (db *Database) ticketGetQuery(ctx context.Context, ticketID int64, query string, bindVars map[string]interface{}, operation *busdb.Operation) (*model.TicketWithTickets, error) { if bindVars == nil { bindVars = map[string]interface{}{} } @@ -321,7 +321,7 @@ func (db *Database) ticketGetQuery(ctx context.Context, ticketID int64, query st } defer cur.Close() - ticket := models.Ticket{} + ticket := model.Ticket{} meta, err := cur.ReadDocument(ctx, &ticket) if err != nil { return nil, err @@ -333,7 +333,7 @@ func (db *Database) ticketGetQuery(ctx context.Context, ticketID int64, query st } // index - go db.Index.Index([]*models.TicketSimpleResponse{ticketSimpleResponse}) + go db.Index.Index([]*model.TicketSimpleResponse{ticketSimpleResponse}) ticketFilterQuery, ticketFilterVars, err := db.Hooks.TicketReadFilter(ctx) if err != nil { @@ -414,7 +414,7 @@ func (db *Database) ticketGetQuery(ctx context.Context, ticketID int64, query st return toTicketWithTickets(ticketResponse, tickets, logs), nil } -func (db *Database) TicketUpdate(ctx context.Context, ticketID int64, ticket *models.Ticket) (*models.TicketWithTickets, error) { +func (db *Database) TicketUpdate(ctx context.Context, ticketID int64, ticket *model.Ticket) (*model.TicketWithTickets, error) { ticketFilterQuery, ticketFilterVars, err := db.Hooks.TicketWriteFilter(ctx) if err != nil { return nil, err @@ -446,7 +446,7 @@ func (db *Database) TicketDelete(ctx context.Context, ticketID int64) error { return nil } -func (db *Database) TicketList(ctx context.Context, ticketType string, query string, sorts []string, desc []bool, offset, count int64) (*models.TicketList, error) { +func (db *Database) TicketList(ctx context.Context, ticketType string, query string, sorts []string, desc []bool, offset, count int64) (*model.TicketList, error) { binVars := map[string]interface{}{} parser := &caql.Parser{Searcher: db.Index, Prefix: "d."} @@ -494,14 +494,14 @@ func (db *Database) TicketList(ctx context.Context, ticketType string, query str RETURN d` // RETURN KEEP(d, "_key", "id", "name", "type", "created")` ticketList, _, err := db.ticketListQuery(ctx, q, mergeMaps(binVars, ticketFilterVars), busdb.ReadOperation) - return &models.TicketList{ + return &model.TicketList{ Count: documentCount, Tickets: ticketList, }, err // return map[string]interface{}{"tickets": ticketList, "count": documentCount}, err } -func (db *Database) ticketListQuery(ctx context.Context, query string, bindVars map[string]interface{}, operation *busdb.Operation) ([]*models.TicketSimpleResponse, *models.LogEntry, error) { +func (db *Database) ticketListQuery(ctx context.Context, query string, bindVars map[string]interface{}, operation *busdb.Operation) ([]*model.TicketSimpleResponse, *model.LogEntry, error) { if bindVars == nil { bindVars = map[string]interface{}{} } @@ -513,9 +513,9 @@ func (db *Database) ticketListQuery(ctx context.Context, query string, bindVars } defer cursor.Close() - var docs []*models.TicketSimpleResponse + var docs []*model.TicketSimpleResponse for { - doc := models.Ticket{} + doc := model.Ticket{} meta, err := cursor.ReadDocument(ctx, &doc) if driver.IsNoMoreDocuments(err) { break diff --git a/database/ticket_field.go b/database/ticket_field.go index e7944ba..c0f46cb 100644 --- a/database/ticket_field.go +++ b/database/ticket_field.go @@ -11,12 +11,12 @@ import ( "github.com/SecurityBrewery/catalyst/bus" "github.com/SecurityBrewery/catalyst/database/busdb" - "github.com/SecurityBrewery/catalyst/generated/models" + "github.com/SecurityBrewery/catalyst/generated/model" "github.com/SecurityBrewery/catalyst/pointer" "github.com/SecurityBrewery/catalyst/time" ) -func (db *Database) AddArtifact(ctx context.Context, id int64, artifact *models.Artifact) (*models.TicketWithTickets, error) { +func (db *Database) AddArtifact(ctx context.Context, id int64, artifact *model.Artifact) (*model.TicketWithTickets, error) { ticketFilterQuery, ticketFilterVars, err := db.Hooks.TicketWriteFilter(ctx) if err != nil { return nil, err @@ -60,7 +60,7 @@ func inferType(name string) string { return "unknown" } -func (db *Database) RemoveArtifact(ctx context.Context, id int64, name string) (*models.TicketWithTickets, error) { +func (db *Database) RemoveArtifact(ctx context.Context, id int64, name string) (*model.TicketWithTickets, error) { ticketFilterQuery, ticketFilterVars, err := db.Hooks.TicketWriteFilter(ctx) if err != nil { return nil, err @@ -81,7 +81,7 @@ func (db *Database) RemoveArtifact(ctx context.Context, id int64, name string) ( }) } -func (db *Database) SetTemplate(ctx context.Context, id int64, schema string) (*models.TicketWithTickets, error) { +func (db *Database) SetTemplate(ctx context.Context, id int64, schema string) (*model.TicketWithTickets, error) { ticketFilterQuery, ticketFilterVars, err := db.Hooks.TicketWriteFilter(ctx) if err != nil { return nil, err @@ -99,7 +99,7 @@ func (db *Database) SetTemplate(ctx context.Context, id int64, schema string) (* }) } -func (db *Database) AddComment(ctx context.Context, id int64, comment *models.CommentForm) (*models.TicketWithTickets, error) { +func (db *Database) AddComment(ctx context.Context, id int64, comment *model.CommentForm) (*model.TicketWithTickets, error) { ticketFilterQuery, ticketFilterVars, err := db.Hooks.TicketWriteFilter(ctx) if err != nil { return nil, err @@ -130,7 +130,7 @@ func (db *Database) AddComment(ctx context.Context, id int64, comment *models.Co }) } -func (db *Database) RemoveComment(ctx context.Context, id int64, commentID int64) (*models.TicketWithTickets, error) { +func (db *Database) RemoveComment(ctx context.Context, id int64, commentID int64) (*model.TicketWithTickets, error) { ticketFilterQuery, ticketFilterVars, err := db.Hooks.TicketWriteFilter(ctx) if err != nil { return nil, err @@ -148,7 +148,7 @@ func (db *Database) RemoveComment(ctx context.Context, id int64, commentID int64 }) } -func (db *Database) SetReferences(ctx context.Context, id int64, references []*models.Reference) (*models.TicketWithTickets, error) { +func (db *Database) SetReferences(ctx context.Context, id int64, references []*model.Reference) (*model.TicketWithTickets, error) { ticketFilterQuery, ticketFilterVars, err := db.Hooks.TicketWriteFilter(ctx) if err != nil { return nil, err @@ -166,7 +166,7 @@ func (db *Database) SetReferences(ctx context.Context, id int64, references []*m }) } -func (db *Database) LinkFiles(ctx context.Context, id int64, files []*models.File) (*models.TicketWithTickets, error) { +func (db *Database) LinkFiles(ctx context.Context, id int64, files []*model.File) (*model.TicketWithTickets, error) { ticketFilterQuery, ticketFilterVars, err := db.Hooks.TicketWriteFilter(ctx) if err != nil { return nil, err @@ -184,7 +184,7 @@ func (db *Database) LinkFiles(ctx context.Context, id int64, files []*models.Fil }) } -func (db *Database) AddTicketPlaybook(ctx context.Context, id int64, playbookTemplate *models.PlaybookTemplateForm) (*models.TicketWithTickets, error) { +func (db *Database) AddTicketPlaybook(ctx context.Context, id int64, playbookTemplate *model.PlaybookTemplateForm) (*model.TicketWithTickets, error) { pb, err := toPlaybook(playbookTemplate) if err != nil { return nil, err @@ -234,7 +234,7 @@ func (db *Database) AddTicketPlaybook(ctx context.Context, id int64, playbookTem return ticket, nil } -func findName(playbooks map[string]*models.PlaybookResponse, name string) string { +func findName(playbooks map[string]*model.PlaybookResponse, name string) string { if _, ok := playbooks[name]; !ok { return name } @@ -247,10 +247,10 @@ func findName(playbooks map[string]*models.PlaybookResponse, name string) string } } -func runRootTask(ticket *models.TicketResponse, playbookID string, db *Database) error { +func runRootTask(ticket *model.TicketResponse, playbookID string, db *Database) error { playbook := ticket.Playbooks[playbookID] - var root *models.TaskResponse + var root *model.TaskResponse for _, task := range playbook.Tasks { if task.Order == 0 { root = task @@ -261,7 +261,7 @@ func runRootTask(ticket *models.TicketResponse, playbookID string, db *Database) return nil } -func (db *Database) RemoveTicketPlaybook(ctx context.Context, id int64, playbookID string) (*models.TicketWithTickets, error) { +func (db *Database) RemoveTicketPlaybook(ctx context.Context, id int64, playbookID string) (*model.TicketWithTickets, error) { ticketFilterQuery, ticketFilterVars, err := db.Hooks.TicketWriteFilter(ctx) if err != nil { return nil, err diff --git a/database/ticket_task.go b/database/ticket_task.go index af5cfe0..09863b4 100644 --- a/database/ticket_task.go +++ b/database/ticket_task.go @@ -11,11 +11,11 @@ import ( "github.com/SecurityBrewery/catalyst/bus" "github.com/SecurityBrewery/catalyst/database/busdb" - "github.com/SecurityBrewery/catalyst/generated/models" + "github.com/SecurityBrewery/catalyst/generated/model" "github.com/SecurityBrewery/catalyst/time" ) -func (db *Database) TaskGet(ctx context.Context, id int64, playbookID string, taskID string) (*models.TicketWithTickets, *models.PlaybookResponse, *models.TaskWithContext, error) { +func (db *Database) TaskGet(ctx context.Context, id int64, playbookID string, taskID string) (*model.TicketWithTickets, *model.PlaybookResponse, *model.TaskWithContext, error) { inc, err := db.TicketGet(ctx, id) if err != nil { return nil, nil, nil, err @@ -31,17 +31,17 @@ func (db *Database) TaskGet(ctx context.Context, id int64, playbookID string, ta return nil, nil, nil, errors.New("task does not exist") } - return inc, playbook, &models.TaskWithContext{ + return inc, playbook, &model.TaskWithContext{ PlaybookId: playbookID, PlaybookName: playbook.Name, TaskId: taskID, - Task: *task, + Task: task, TicketId: id, TicketName: inc.Name, }, nil } -func (db *Database) TaskComplete(ctx context.Context, id int64, playbookID string, taskID string, data interface{}) (*models.TicketWithTickets, error) { +func (db *Database) TaskComplete(ctx context.Context, id int64, playbookID string, taskID string, data interface{}) (*model.TicketWithTickets, error) { inc, err := db.TicketGet(ctx, id) if err != nil { return nil, err @@ -92,8 +92,8 @@ func (db *Database) TaskComplete(ctx context.Context, id int64, playbookID strin return ticket, nil } -func extractTicketResponse(ticket *models.TicketWithTickets) *models.TicketResponse { - return &models.TicketResponse{ +func extractTicketResponse(ticket *model.TicketWithTickets) *model.TicketResponse { + return &model.TicketResponse{ Artifacts: ticket.Artifacts, Comments: ticket.Comments, Created: ticket.Created, @@ -113,7 +113,7 @@ func extractTicketResponse(ticket *models.TicketWithTickets) *models.TicketRespo } } -func (db *Database) TaskUpdate(ctx context.Context, id int64, playbookID string, taskID string, task *models.Task) (*models.TicketWithTickets, error) { +func (db *Database) TaskUpdate(ctx context.Context, id int64, playbookID string, taskID string, task *model.Task) (*model.TicketWithTickets, error) { ticketFilterQuery, ticketFilterVars, err := db.Hooks.TicketWriteFilter(ctx) if err != nil { return nil, err @@ -154,8 +154,8 @@ func (db *Database) TaskRun(ctx context.Context, id int64, playbookID string, ta return err } - if task.Task.Type == models.TaskTypeAutomation { - if err := runTask(id, playbookID, taskID, &task.Task, extractTicketResponse(ticket), db); err != nil { + if task.Task.Type == model.TaskTypeAutomation { + if err := runTask(id, playbookID, taskID, task.Task, extractTicketResponse(ticket), db); err != nil { return err } } @@ -163,10 +163,10 @@ func (db *Database) TaskRun(ctx context.Context, id int64, playbookID string, ta return nil } -func runNextTasks(id int64, playbookID string, next map[string]string, data interface{}, ticket *models.TicketResponse, db *Database) { +func runNextTasks(id int64, playbookID string, next map[string]string, data interface{}, ticket *model.TicketResponse, db *Database) { for nextTaskID, requirement := range next { nextTask := ticket.Playbooks[playbookID].Tasks[nextTaskID] - if nextTask.Type == models.TaskTypeAutomation { + if nextTask.Type == model.TaskTypeAutomation { b, err := evalRequirement(requirement, data) if err != nil { continue @@ -180,10 +180,10 @@ func runNextTasks(id int64, playbookID string, next map[string]string, data inte } } -func runTask(ticketID int64, playbookID string, taskID string, task *models.TaskResponse, ticket *models.TicketResponse, db *Database) error { +func runTask(ticketID int64, playbookID string, taskID string, task *model.TaskResponse, ticket *model.TicketResponse, db *Database) error { playbook := ticket.Playbooks[playbookID] - msgContext := &models.Context{Playbook: playbook, Task: task, Ticket: ticket} - origin := &models.Origin{TaskOrigin: &models.TaskOrigin{TaskId: taskID, PlaybookId: playbookID, TicketId: ticketID}} + msgContext := &model.Context{Playbook: playbook, Task: task, Ticket: ticket} + origin := &model.Origin{TaskOrigin: &model.TaskOrigin{TaskId: taskID, PlaybookId: playbookID, TicketId: ticketID}} jobID := uuid.NewString() return publishJobMapping(jobID, *task.Automation, msgContext, origin, task.Payload, db) } diff --git a/database/tickettype.go b/database/tickettype.go index f4581bc..6289157 100644 --- a/database/tickettype.go +++ b/database/tickettype.go @@ -8,11 +8,11 @@ import ( "github.com/iancoleman/strcase" "github.com/SecurityBrewery/catalyst/database/busdb" - "github.com/SecurityBrewery/catalyst/generated/models" + "github.com/SecurityBrewery/catalyst/generated/model" ) -func toTicketType(doc *models.TicketTypeForm) *models.TicketType { - return &models.TicketType{ +func toTicketType(doc *model.TicketTypeForm) *model.TicketType { + return &model.TicketType{ Name: doc.Name, Icon: doc.Icon, DefaultPlaybooks: doc.DefaultPlaybooks, @@ -21,8 +21,8 @@ func toTicketType(doc *models.TicketTypeForm) *models.TicketType { } } -func toTicketTypeResponse(key string, doc *models.TicketType) *models.TicketTypeResponse { - return &models.TicketTypeResponse{ +func toTicketTypeResponse(key string, doc *model.TicketType) *model.TicketTypeResponse { + return &model.TicketTypeResponse{ ID: key, Name: doc.Name, Icon: doc.Icon, @@ -32,7 +32,7 @@ func toTicketTypeResponse(key string, doc *models.TicketType) *models.TicketType } } -func (db *Database) TicketTypeCreate(ctx context.Context, tickettype *models.TicketTypeForm) (*models.TicketTypeResponse, error) { +func (db *Database) TicketTypeCreate(ctx context.Context, tickettype *model.TicketTypeForm) (*model.TicketTypeResponse, error) { if tickettype == nil { return nil, errors.New("requires ticket type") } @@ -40,7 +40,7 @@ func (db *Database) TicketTypeCreate(ctx context.Context, tickettype *models.Tic return nil, errors.New("requires ticket type name") } - var doc models.TicketType + var doc model.TicketType newctx := driver.WithReturnNew(ctx, &doc) meta, err := db.tickettypeCollection.CreateDocument(ctx, newctx, strcase.ToKebab(tickettype.Name), toTicketType(tickettype)) @@ -51,8 +51,8 @@ func (db *Database) TicketTypeCreate(ctx context.Context, tickettype *models.Tic return toTicketTypeResponse(meta.Key, &doc), nil } -func (db *Database) TicketTypeGet(ctx context.Context, id string) (*models.TicketTypeResponse, error) { - var doc models.TicketType +func (db *Database) TicketTypeGet(ctx context.Context, id string) (*model.TicketTypeResponse, error) { + var doc model.TicketType meta, err := db.tickettypeCollection.ReadDocument(ctx, id, &doc) if err != nil { return nil, err @@ -61,8 +61,8 @@ func (db *Database) TicketTypeGet(ctx context.Context, id string) (*models.Ticke return toTicketTypeResponse(meta.Key, &doc), nil } -func (db *Database) TicketTypeUpdate(ctx context.Context, id string, tickettype *models.TicketTypeForm) (*models.TicketTypeResponse, error) { - var doc models.TicketType +func (db *Database) TicketTypeUpdate(ctx context.Context, id string, tickettype *model.TicketTypeForm) (*model.TicketTypeResponse, error) { + var doc model.TicketType ctx = driver.WithReturnNew(ctx, &doc) meta, err := db.tickettypeCollection.ReplaceDocument(ctx, id, toTicketType(tickettype)) @@ -78,16 +78,16 @@ func (db *Database) TicketTypeDelete(ctx context.Context, id string) error { return err } -func (db *Database) TicketTypeList(ctx context.Context) ([]*models.TicketTypeResponse, error) { +func (db *Database) TicketTypeList(ctx context.Context) ([]*model.TicketTypeResponse, error) { query := "FOR d IN @@collection RETURN d" cursor, _, err := db.Query(ctx, query, map[string]interface{}{"@collection": TicketTypeCollectionName}, busdb.ReadOperation) if err != nil { return nil, err } defer cursor.Close() - var docs []*models.TicketTypeResponse + var docs []*model.TicketTypeResponse for { - var doc models.TicketType + var doc model.TicketType meta, err := cursor.ReadDocument(ctx, &doc) if driver.IsNoMoreDocuments(err) { break diff --git a/database/user.go b/database/user.go index a2c8c7a..817d356 100644 --- a/database/user.go +++ b/database/user.go @@ -8,11 +8,10 @@ import ( "math/rand" "github.com/arangodb/go-driver" - "github.com/gin-gonic/gin" "github.com/iancoleman/strcase" "github.com/SecurityBrewery/catalyst/database/busdb" - "github.com/SecurityBrewery/catalyst/generated/models" + "github.com/SecurityBrewery/catalyst/generated/model" "github.com/SecurityBrewery/catalyst/pointer" "github.com/SecurityBrewery/catalyst/role" "github.com/SecurityBrewery/catalyst/time" @@ -32,10 +31,10 @@ func generateKey() string { return string(b) } -func toUser(user *models.UserForm, sha256 *string) *models.User { +func toUser(user *model.UserForm, sha256 *string) *model.User { roles := []string{} roles = append(roles, role.Strings(role.Explodes(user.Roles))...) - u := &models.User{ + u := &model.User{ Blocked: user.Blocked, Roles: roles, Sha256: sha256, @@ -45,7 +44,7 @@ func toUser(user *models.UserForm, sha256 *string) *models.User { // log.Println(u) // b, _ := json.Marshal(u) // loader := gojsonschema.NewBytesLoader(b) - // res, err := models.UserSchema.Validate(loader) + // res, err := model.UserSchema.Validate(loader) // if err != nil { // log.Println(err) // } @@ -54,8 +53,8 @@ func toUser(user *models.UserForm, sha256 *string) *models.User { return u } -func toUserResponse(key string, user *models.User) *models.UserResponse { - return &models.UserResponse{ +func toUserResponse(key string, user *model.User) *model.UserResponse { + return &model.UserResponse{ ID: key, Roles: user.Roles, Blocked: user.Blocked, @@ -63,8 +62,8 @@ func toUserResponse(key string, user *models.User) *models.UserResponse { } } -func toNewUserResponse(key string, user *models.User, secret *string) *models.NewUserResponse { - return &models.NewUserResponse{ +func toNewUserResponse(key string, user *model.User, secret *string) *model.NewUserResponse { + return &model.NewUserResponse{ ID: key, Roles: user.Roles, Secret: secret, @@ -72,19 +71,19 @@ func toNewUserResponse(key string, user *models.User, secret *string) *models.Ne } } -func (db *Database) UserGetOrCreate(ctx *gin.Context, newUser *models.UserForm) (*models.UserResponse, error) { +func (db *Database) UserGetOrCreate(ctx context.Context, newUser *model.UserForm) (*model.UserResponse, error) { user, err := db.UserGet(ctx, newUser.ID) if err != nil { newUser, err := db.UserCreate(ctx, newUser) if err != nil { return nil, err } - return &models.UserResponse{ID: newUser.ID, Roles: newUser.Roles, Blocked: newUser.Blocked}, nil + return &model.UserResponse{ID: newUser.ID, Roles: newUser.Roles, Blocked: newUser.Blocked}, nil } return user, nil } -func (db *Database) UserCreate(ctx context.Context, newUser *models.UserForm) (*models.NewUserResponse, error) { +func (db *Database) UserCreate(ctx context.Context, newUser *model.UserForm) (*model.NewUserResponse, error) { var key string var hash *string if newUser.Apikey { @@ -92,7 +91,7 @@ func (db *Database) UserCreate(ctx context.Context, newUser *models.UserForm) (* hash = pointer.String(fmt.Sprintf("%x", sha256.Sum256([]byte(key)))) } - var doc models.User + var doc model.User newctx := driver.WithReturnNew(ctx, &doc) meta, err := db.userCollection.CreateDocument(ctx, newctx, strcase.ToKebab(newUser.ID), toUser(newUser, hash)) if err != nil { @@ -102,8 +101,8 @@ func (db *Database) UserCreate(ctx context.Context, newUser *models.UserForm) (* return toNewUserResponse(meta.Key, &doc, pointer.String(key)), nil } -func (db *Database) UserCreateSetupAPIKey(ctx context.Context, key string) (*models.UserResponse, error) { - newUser := &models.UserForm{ +func (db *Database) UserCreateSetupAPIKey(ctx context.Context, key string) (*model.UserResponse, error) { + newUser := &model.UserForm{ ID: "setup", Roles: []string{role.Admin}, Apikey: true, @@ -111,7 +110,7 @@ func (db *Database) UserCreateSetupAPIKey(ctx context.Context, key string) (*mod } hash := pointer.String(fmt.Sprintf("%x", sha256.Sum256([]byte(key)))) - var doc models.User + var doc model.User newctx := driver.WithReturnNew(ctx, &doc) meta, err := db.userCollection.CreateDocument(ctx, newctx, strcase.ToKebab(newUser.ID), toUser(newUser, hash)) if err != nil { @@ -121,8 +120,8 @@ func (db *Database) UserCreateSetupAPIKey(ctx context.Context, key string) (*mod return toUserResponse(meta.Key, &doc), nil } -func (db *Database) UserGet(ctx context.Context, id string) (*models.UserResponse, error) { - var doc models.User +func (db *Database) UserGet(ctx context.Context, id string) (*model.UserResponse, error) { + var doc model.User meta, err := db.userCollection.ReadDocument(ctx, id, &doc) if err != nil { return nil, err @@ -136,16 +135,16 @@ func (db *Database) UserDelete(ctx context.Context, id string) error { return err } -func (db *Database) UserList(ctx context.Context) ([]*models.UserResponse, error) { +func (db *Database) UserList(ctx context.Context) ([]*model.UserResponse, error) { query := "FOR d IN @@collection RETURN d" cursor, _, err := db.Query(ctx, query, map[string]interface{}{"@collection": UserCollectionName}, busdb.ReadOperation) if err != nil { return nil, err } defer cursor.Close() - var docs []*models.UserResponse + var docs []*model.UserResponse for { - var doc models.User + var doc model.User meta, err := cursor.ReadDocument(ctx, &doc) if driver.IsNoMoreDocuments(err) { break @@ -159,7 +158,7 @@ func (db *Database) UserList(ctx context.Context) ([]*models.UserResponse, error return docs, err } -func (db *Database) UserByHash(ctx context.Context, sha256 string) (*models.UserResponse, error) { +func (db *Database) UserByHash(ctx context.Context, sha256 string) (*model.UserResponse, error) { query := `FOR d in @@collection FILTER d.sha256 == @sha256 RETURN d` @@ -170,7 +169,7 @@ func (db *Database) UserByHash(ctx context.Context, sha256 string) (*models.User } defer cursor.Close() - var doc models.User + var doc model.User meta, err := cursor.ReadDocument(ctx, &doc) if err != nil { return nil, err @@ -179,8 +178,8 @@ func (db *Database) UserByHash(ctx context.Context, sha256 string) (*models.User return toUserResponse(meta.Key, &doc), err } -func (db *Database) UserUpdate(ctx context.Context, id string, user *models.UserForm) (*models.UserResponse, error) { - var doc models.User +func (db *Database) UserUpdate(ctx context.Context, id string, user *model.UserForm) (*model.UserResponse, error) { + var doc model.User _, err := db.userCollection.ReadDocument(ctx, id, &doc) if err != nil { return nil, err diff --git a/definition/jobs.yaml b/definition/jobs.yaml index d9f9e43..eaa5441 100644 --- a/definition/jobs.yaml +++ b/definition/jobs.yaml @@ -62,7 +62,7 @@ definitions: Message: type: object properties: - payload: { type: object } + payload: { } secrets: { type: object, additionalProperties: { type: string } } context: { $ref: "#/definitions/Context" } diff --git a/definition/playbooks.yaml b/definition/playbooks.yaml index 0af18ef..eeb6b36 100644 --- a/definition/playbooks.yaml +++ b/definition/playbooks.yaml @@ -32,7 +32,7 @@ paths: responses: "200": description: "successful operation" - schema: { type: array, items: { $ref: "#/definitions/PlaybookTemplateResponse" } } + schema: { $ref: "#/definitions/PlaybookTemplateResponse" } examples: test: id: simple-2 diff --git a/definition/tasks.yaml b/definition/tasks.yaml index 7b5e15e..c48afdc 100644 --- a/definition/tasks.yaml +++ b/definition/tasks.yaml @@ -10,7 +10,7 @@ paths: responses: "200": description: "successful operation" - schema: { type: array, items: { $ref: "#/definitions/TaskResponse" } } + schema: { type: array, items: { $ref: "#/definitions/TaskWithContext" } } examples: test: [ ] security: [ { roles: [ "ticket:read" ] } ] diff --git a/definition/tickets.yaml b/definition/tickets.yaml index 6ae6c32..d79d937 100644 --- a/definition/tickets.yaml +++ b/definition/tickets.yaml @@ -95,7 +95,7 @@ paths: responses: "200": description: "successful operation" - schema: { $ref: "#/definitions/TicketResponse" } + schema: { $ref: "#/definitions/TicketWithTickets" } examples: test: id: 8125 @@ -126,7 +126,7 @@ paths: responses: "200": description: "successful operation" - schema: { $ref: "#/definitions/TicketResponse" } + schema: { $ref: "#/definitions/TicketWithTickets" } examples: test: id: 8125 @@ -168,7 +168,7 @@ paths: responses: "200": description: "successful operation" - schema: { $ref: "#/definitions/TicketResponse" } + schema: { $ref: "#/definitions/TicketWithTickets" } examples: test: id: 8126 @@ -234,7 +234,7 @@ paths: responses: "200": description: "successful operation" - schema: { $ref: "#/definitions/TicketResponse" } + schema: { $ref: "#/definitions/TicketWithTickets" } examples: test: id: 8126 @@ -262,7 +262,7 @@ paths: responses: "200": description: "successful operation" - schema: { $ref: "#/definitions/TicketResponse" } + schema: { $ref: "#/definitions/TicketWithTickets" } examples: test: id: 8125 @@ -297,7 +297,7 @@ paths: responses: "200": description: "successful operation" - schema: { $ref: "#/definitions/TicketResponse" } + schema: { $ref: "#/definitions/TicketWithTickets" } examples: test: id: 8123 @@ -340,7 +340,7 @@ paths: responses: "200": description: "successful operation" - schema: { $ref: "#/definitions/TicketResponse" } + schema: { $ref: "#/definitions/TicketWithTickets" } examples: test: id: 8125 @@ -363,11 +363,11 @@ paths: operationId: "setSchema" parameters: - { name: "id", in: "path", description: "Ticket ID", required: true, type: integer, format: "int64", x-example: 8125 } - - { name: "schema", in: "body", description: "New ticket schema", schema: { type: string }, x-example: "{}" } + - { name: "schema", in: "body", description: "New ticket schema", required: true, schema: { type: string }, x-example: "{}" } responses: "200": description: "successful operation" - schema: { $ref: "#/definitions/TicketResponse" } + schema: { $ref: "#/definitions/TicketWithTickets" } examples: test: id: 8125 @@ -398,7 +398,7 @@ paths: responses: "200": description: "successful operation" - schema: { $ref: "#/definitions/TicketResponse" } + schema: { $ref: "#/definitions/TicketWithTickets" } examples: test: id: 8125 @@ -430,7 +430,7 @@ paths: responses: "200": description: "successful operation" - schema: { $ref: "#/definitions/TicketResponse" } + schema: { $ref: "#/definitions/TicketWithTickets" } examples: test: id: 8125 @@ -489,6 +489,7 @@ paths: order: 2 name: Escalate to malware team type: task + security: [ { roles: [ "ticket:write" ] } ] /tickets/{id}/playbooks/{playbookID}: delete: @@ -501,7 +502,7 @@ paths: responses: "200": description: "successful operation" - schema: { $ref: "#/definitions/TicketResponse" } + schema: { $ref: "#/definitions/TicketWithTickets" } examples: test: id: 8123 @@ -625,7 +626,7 @@ paths: responses: "200": description: "successful operation" - schema: { $ref: "#/definitions/TicketResponse" } + schema: { $ref: "#/definitions/TicketWithTickets" } examples: test: id: 8123 @@ -670,7 +671,7 @@ paths: responses: "200": description: "successful operation" - schema: { $ref: "#/definitions/TicketResponse" } + schema: { $ref: "#/definitions/TicketWithTickets" } examples: test: id: 8123 @@ -726,7 +727,7 @@ paths: responses: "200": description: "successful operation" - schema: { $ref: "#/definitions/TicketResponse" } + schema: { $ref: "#/definitions/TicketWithTickets" } examples: test: id: 8123 @@ -785,7 +786,7 @@ paths: responses: "200": description: "successful operation" - schema: { $ref: "#/definitions/TicketResponse" } + schema: { $ref: "#/definitions/TicketWithTickets" } examples: test: id: 8123 @@ -826,7 +827,7 @@ paths: responses: "200": description: "successful operation" - schema: { $ref: "#/definitions/TicketResponse" } + schema: { $ref: "#/definitions/TicketWithTickets" } examples: test: id: 8123 @@ -882,7 +883,7 @@ paths: responses: "200": description: "successful operation" - schema: { $ref: "#/definitions/Artifact" } + schema: { $ref: "#/definitions/TicketWithTickets" } examples: test: id: 8123 diff --git a/file.go b/file.go index c480775..ad7d5cf 100644 --- a/file.go +++ b/file.go @@ -4,29 +4,29 @@ import ( "errors" "fmt" "io" - "log" "net/http" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/s3" "github.com/aws/aws-sdk-go/service/s3/s3manager" - "github.com/gin-gonic/gin" + "github.com/go-chi/chi" tusd "github.com/tus/tusd/pkg/handler" "github.com/tus/tusd/pkg/s3store" + "github.com/SecurityBrewery/catalyst/generated/api" "github.com/SecurityBrewery/catalyst/storage" ) -func upload(client *s3.S3, external string) gin.HandlerFunc { - return func(ctx *gin.Context) { - ticketID, exists := ctx.Params.Get("ticketID") - if !exists { - ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "ticketID not given"}) +func upload(client *s3.S3, external string) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + ticketID := chi.URLParam(r, "ticketID") + if ticketID == "" { + api.JSONErrorStatus(w, http.StatusBadRequest, errors.New("ticketID not given")) return } if err := storage.CreateBucket(client, ticketID); err != nil { - ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": fmt.Errorf("could not create bucket: %w", err)}) + api.JSONErrorStatus(w, http.StatusBadRequest, fmt.Errorf("could not create bucket: %w", err)) return } @@ -40,39 +40,38 @@ func upload(client *s3.S3, external string) gin.HandlerFunc { StoreComposer: composer, }) if err != nil { - ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": fmt.Errorf("could not create tusd handler: %w", err)}) + api.JSONErrorStatus(w, http.StatusBadRequest, fmt.Errorf("could not create tusd handler: %w", err)) return } - switch ctx.Request.Method { + switch r.Method { case http.MethodHead: - gin.WrapF(handler.HeadFile)(ctx) + handler.HeadFile(w, r) case http.MethodPost: - gin.WrapF(handler.PostFile)(ctx) + handler.PostFile(w, r) case http.MethodPatch: - gin.WrapF(handler.PatchFile)(ctx) + handler.PatchFile(w, r) default: - log.Println(errors.New("unknown method")) - ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "unknown method"}) + api.JSONErrorStatus(w, http.StatusInternalServerError, errors.New("unknown method")) } } } -func download(downloader *s3manager.Downloader) gin.HandlerFunc { - return func(ctx *gin.Context) { - ticketID, exists := ctx.Params.Get("ticketID") - if !exists { - ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "ticketID not given"}) +func download(downloader *s3manager.Downloader) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + ticketID := chi.URLParam(r, "ticketID") + if ticketID == "" { + api.JSONErrorStatus(w, http.StatusBadRequest, errors.New("ticketID not given")) return } - key, exists := ctx.Params.Get("key") - if !exists { - ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "key not given"}) + key := chi.URLParam(r, "key") + if key == "" { + api.JSONErrorStatus(w, http.StatusBadRequest, errors.New("key not given")) return } - buf := sequentialWriter{ctx.Writer} + buf := sequentialWriter{w} downloader.Concurrency = 1 _, err := downloader.Download(buf, &s3.GetObjectInput{ @@ -80,8 +79,7 @@ func download(downloader *s3manager.Downloader) gin.HandlerFunc { Key: aws.String(key), }) if err != nil { - ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": err}) - return + api.JSONErrorStatus(w, http.StatusInternalServerError, err) } } } diff --git a/generate.sh b/generate.sh index 51ac1ae..922088b 100644 --- a/generate.sh +++ b/generate.sh @@ -22,7 +22,8 @@ mv generated/openapi.json generated/catalyst.json # openapi-generator generate -i generated/community.yml -o generated/python -g python --package-name catalystpy --ignore-file-override .openapi-generator-ignore echo generate server and tests -go run ./generator/. ./generator +# go run ./generator/. ./generator +swachigo generated/community.yml generated echo generate typescript client openapi-generator generate -i generated/catalyst.yml -o ui/src/client -g typescript-axios --artifact-version 1.0.0-SNAPSHOT diff --git a/generated/api/api.go b/generated/api/api.go new file mode 100755 index 0000000..36f502a --- /dev/null +++ b/generated/api/api.go @@ -0,0 +1,1094 @@ +package api + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "net/http" + "strconv" + + "github.com/go-chi/chi" + + // "github.com/xeipuuv/gojsonschema" + "github.com/SecurityBrewery/catalyst/generated/model" +) + +type HTTPError struct { + Status int + Internal error +} + +func (e *HTTPError) Error() string { + return fmt.Sprintf("HTTPError(%d): %s", e.Status, e.Internal) +} + +func (e *HTTPError) Unwrap() error { + return e.Internal +} + +type Service interface { + ListAutomations(context.Context) ([]*model.AutomationResponse, error) + CreateAutomation(context.Context, *model.AutomationForm) (*model.AutomationResponse, error) + GetAutomation(context.Context, string) (*model.AutomationResponse, error) + UpdateAutomation(context.Context, string, *model.AutomationForm) (*model.AutomationResponse, error) + DeleteAutomation(context.Context, string) error + CurrentUser(context.Context) (*model.UserResponse, error) + CurrentUserData(context.Context) (*model.UserDataResponse, error) + UpdateCurrentUserData(context.Context, *model.UserData) (*model.UserDataResponse, error) + ListJobs(context.Context) ([]*model.JobResponse, error) + RunJob(context.Context, *model.JobForm) error + GetJob(context.Context, string) (*model.JobResponse, error) + UpdateJob(context.Context, string, *model.Job) (*model.JobResponse, error) + GetLogs(context.Context, string) ([]*model.LogEntry, error) + ListPlaybooks(context.Context) ([]*model.PlaybookTemplateResponse, error) + CreatePlaybook(context.Context, *model.PlaybookTemplateForm) (*model.PlaybookTemplateResponse, error) + GetPlaybook(context.Context, string) (*model.PlaybookTemplateResponse, error) + UpdatePlaybook(context.Context, string, *model.PlaybookTemplateForm) (*model.PlaybookTemplateResponse, error) + DeletePlaybook(context.Context, string) error + GetSettings(context.Context) (*model.Settings, error) + GetStatistics(context.Context) (*model.Statistics, error) + ListTasks(context.Context) ([]*model.TaskWithContext, error) + ListTemplates(context.Context) ([]*model.TicketTemplateResponse, error) + CreateTemplate(context.Context, *model.TicketTemplateForm) (*model.TicketTemplateResponse, error) + GetTemplate(context.Context, string) (*model.TicketTemplateResponse, error) + UpdateTemplate(context.Context, string, *model.TicketTemplateForm) (*model.TicketTemplateResponse, error) + DeleteTemplate(context.Context, string) error + ListTickets(context.Context, *string, *int, *int, []string, []bool, *string) (*model.TicketList, error) + CreateTicket(context.Context, *model.TicketForm) (*model.TicketResponse, error) + CreateTicketBatch(context.Context, []*model.TicketForm) error + GetTicket(context.Context, int64) (*model.TicketWithTickets, error) + UpdateTicket(context.Context, int64, *model.Ticket) (*model.TicketWithTickets, error) + DeleteTicket(context.Context, int64) error + AddArtifact(context.Context, int64, *model.Artifact) (*model.TicketWithTickets, error) + GetArtifact(context.Context, int64, string) (*model.Artifact, error) + SetArtifact(context.Context, int64, string, *model.Artifact) (*model.TicketWithTickets, error) + RemoveArtifact(context.Context, int64, string) (*model.TicketWithTickets, error) + EnrichArtifact(context.Context, int64, string, *model.EnrichmentForm) (*model.TicketWithTickets, error) + RunArtifact(context.Context, int64, string, string) error + AddComment(context.Context, int64, *model.CommentForm) (*model.TicketWithTickets, error) + RemoveComment(context.Context, int64, int) (*model.TicketWithTickets, error) + LinkFiles(context.Context, int64, []*model.File) (*model.TicketWithTickets, error) + AddTicketPlaybook(context.Context, int64, *model.PlaybookTemplateForm) (*model.TicketWithTickets, error) + RemoveTicketPlaybook(context.Context, int64, string) (*model.TicketWithTickets, error) + SetTask(context.Context, int64, string, string, *model.Task) (*model.TicketWithTickets, error) + CompleteTask(context.Context, int64, string, string, map[string]interface{}) (*model.TicketWithTickets, error) + RunTask(context.Context, int64, string, string) error + SetReferences(context.Context, int64, []*model.Reference) (*model.TicketWithTickets, error) + SetSchema(context.Context, int64, string) (*model.TicketWithTickets, error) + LinkTicket(context.Context, int64, int64) (*model.TicketWithTickets, error) + UnlinkTicket(context.Context, int64, int64) (*model.TicketWithTickets, error) + ListTicketTypes(context.Context) ([]*model.TicketTypeResponse, error) + CreateTicketType(context.Context, *model.TicketTypeForm) (*model.TicketTypeResponse, error) + GetTicketType(context.Context, string) (*model.TicketTypeResponse, error) + UpdateTicketType(context.Context, string, *model.TicketTypeForm) (*model.TicketTypeResponse, error) + DeleteTicketType(context.Context, string) error + ListUserData(context.Context) ([]*model.UserDataResponse, error) + GetUserData(context.Context, string) (*model.UserDataResponse, error) + UpdateUserData(context.Context, string, *model.UserData) (*model.UserDataResponse, error) + ListUsers(context.Context) ([]*model.UserResponse, error) + CreateUser(context.Context, *model.UserForm) (*model.NewUserResponse, error) + GetUser(context.Context, string) (*model.UserResponse, error) + UpdateUser(context.Context, string, *model.UserForm) (*model.UserResponse, error) + DeleteUser(context.Context, string) error +} + +func NewServer(service Service, roleAuth func([]string) func(http.Handler) http.Handler, middlewares ...func(http.Handler) http.Handler) chi.Router { + r := chi.NewRouter() + r.Use(middlewares...) + + s := &server{service} + + r.With(roleAuth([]string{"automation:read"})).Get("/automations", s.listAutomationsHandler) + r.With(roleAuth([]string{"automation:write"})).Post("/automations", s.createAutomationHandler) + r.With(roleAuth([]string{"automation:read"})).Get("/automations/{id}", s.getAutomationHandler) + r.With(roleAuth([]string{"automation:write"})).Put("/automations/{id}", s.updateAutomationHandler) + r.With(roleAuth([]string{"automation:write"})).Delete("/automations/{id}", s.deleteAutomationHandler) + r.With(roleAuth([]string{"currentuser:read"})).Get("/currentuser", s.currentUserHandler) + r.With(roleAuth([]string{"currentuserdata:read"})).Get("/currentuserdata", s.currentUserDataHandler) + r.With(roleAuth([]string{"currentuserdata:write"})).Put("/currentuserdata", s.updateCurrentUserDataHandler) + r.With(roleAuth([]string{"job:read"})).Get("/jobs", s.listJobsHandler) + r.With(roleAuth([]string{"job:write"})).Post("/jobs", s.runJobHandler) + r.With(roleAuth([]string{"job:read"})).Get("/jobs/{id}", s.getJobHandler) + r.With(roleAuth([]string{"job:write"})).Put("/jobs/{id}", s.updateJobHandler) + r.With(roleAuth([]string{"log:read"})).Get("/logs/{reference}", s.getLogsHandler) + r.With(roleAuth([]string{"playbook:read"})).Get("/playbooks", s.listPlaybooksHandler) + r.With(roleAuth([]string{"playbook:write"})).Post("/playbooks", s.createPlaybookHandler) + r.With(roleAuth([]string{"playbook:read"})).Get("/playbooks/{id}", s.getPlaybookHandler) + r.With(roleAuth([]string{"playbook:write"})).Put("/playbooks/{id}", s.updatePlaybookHandler) + r.With(roleAuth([]string{"playbook:write"})).Delete("/playbooks/{id}", s.deletePlaybookHandler) + r.With(roleAuth([]string{"settings:read"})).Get("/settings", s.getSettingsHandler) + r.With(roleAuth([]string{"ticket:read"})).Get("/statistics", s.getStatisticsHandler) + r.With(roleAuth([]string{"ticket:read"})).Get("/tasks", s.listTasksHandler) + r.With(roleAuth([]string{"template:read"})).Get("/templates", s.listTemplatesHandler) + r.With(roleAuth([]string{"template:write"})).Post("/templates", s.createTemplateHandler) + r.With(roleAuth([]string{"template:read"})).Get("/templates/{id}", s.getTemplateHandler) + r.With(roleAuth([]string{"template:write"})).Put("/templates/{id}", s.updateTemplateHandler) + r.With(roleAuth([]string{"template:write"})).Delete("/templates/{id}", s.deleteTemplateHandler) + r.With(roleAuth([]string{"ticket:read"})).Get("/tickets", s.listTicketsHandler) + r.With(roleAuth([]string{"ticket:write"})).Post("/tickets", s.createTicketHandler) + r.With(roleAuth([]string{"ticket:write"})).Post("/tickets/batch", s.createTicketBatchHandler) + r.With(roleAuth([]string{"ticket:read"})).Get("/tickets/{id}", s.getTicketHandler) + r.With(roleAuth([]string{"ticket:write"})).Put("/tickets/{id}", s.updateTicketHandler) + r.With(roleAuth([]string{"ticket:delete"})).Delete("/tickets/{id}", s.deleteTicketHandler) + r.With(roleAuth([]string{"ticket:write"})).Post("/tickets/{id}/artifacts", s.addArtifactHandler) + r.With(roleAuth([]string{"ticket:write"})).Get("/tickets/{id}/artifacts/{name}", s.getArtifactHandler) + r.With(roleAuth([]string{"ticket:write"})).Put("/tickets/{id}/artifacts/{name}", s.setArtifactHandler) + r.With(roleAuth([]string{"ticket:write"})).Delete("/tickets/{id}/artifacts/{name}", s.removeArtifactHandler) + r.With(roleAuth([]string{"ticket:write"})).Post("/tickets/{id}/artifacts/{name}/enrich", s.enrichArtifactHandler) + r.With(roleAuth([]string{"ticket:write"})).Post("/tickets/{id}/artifacts/{name}/run/{automation}", s.runArtifactHandler) + r.With(roleAuth([]string{"ticket:write"})).Post("/tickets/{id}/comments", s.addCommentHandler) + r.With(roleAuth([]string{"ticket:write"})).Delete("/tickets/{id}/comments/{commentID}", s.removeCommentHandler) + r.With(roleAuth([]string{"ticket:write"})).Put("/tickets/{id}/files", s.linkFilesHandler) + r.With(roleAuth([]string{"ticket:write"})).Post("/tickets/{id}/playbooks", s.addTicketPlaybookHandler) + r.With(roleAuth([]string{"ticket:write"})).Delete("/tickets/{id}/playbooks/{playbookID}", s.removeTicketPlaybookHandler) + r.With(roleAuth([]string{"ticket:write"})).Put("/tickets/{id}/playbooks/{playbookID}/task/{taskID}", s.setTaskHandler) + r.With(roleAuth([]string{"ticket:write"})).Put("/tickets/{id}/playbooks/{playbookID}/task/{taskID}/complete", s.completeTaskHandler) + r.With(roleAuth([]string{"ticket:write"})).Post("/tickets/{id}/playbooks/{playbookID}/task/{taskID}/run", s.runTaskHandler) + r.With(roleAuth([]string{"ticket:write"})).Put("/tickets/{id}/references", s.setReferencesHandler) + r.With(roleAuth([]string{"ticket:write"})).Put("/tickets/{id}/schema", s.setSchemaHandler) + r.With(roleAuth([]string{"ticket:write"})).Patch("/tickets/{id}/tickets", s.linkTicketHandler) + r.With(roleAuth([]string{"ticket:write"})).Delete("/tickets/{id}/tickets", s.unlinkTicketHandler) + r.With(roleAuth([]string{"tickettype:read"})).Get("/tickettypes", s.listTicketTypesHandler) + r.With(roleAuth([]string{"tickettype:write"})).Post("/tickettypes", s.createTicketTypeHandler) + r.With(roleAuth([]string{"tickettype:read"})).Get("/tickettypes/{id}", s.getTicketTypeHandler) + r.With(roleAuth([]string{"tickettype:write"})).Put("/tickettypes/{id}", s.updateTicketTypeHandler) + r.With(roleAuth([]string{"tickettype:write"})).Delete("/tickettypes/{id}", s.deleteTicketTypeHandler) + r.With(roleAuth([]string{"userdata:read"})).Get("/userdata", s.listUserDataHandler) + r.With(roleAuth([]string{"userdata:read"})).Get("/userdata/{id}", s.getUserDataHandler) + r.With(roleAuth([]string{"userdata:write"})).Put("/userdata/{id}", s.updateUserDataHandler) + r.With(roleAuth([]string{"user:read"})).Get("/users", s.listUsersHandler) + r.With(roleAuth([]string{"user:write"})).Post("/users", s.createUserHandler) + r.With(roleAuth([]string{"user:read"})).Get("/users/{id}", s.getUserHandler) + r.With(roleAuth([]string{"user:write"})).Put("/users/{id}", s.updateUserHandler) + r.With(roleAuth([]string{"user:write"})).Delete("/users/{id}", s.deleteUserHandler) + return r +} + +type server struct { + service Service +} + +func (s *server) listAutomationsHandler(w http.ResponseWriter, r *http.Request) { + result, err := s.service.ListAutomations(r.Context()) + response(w, result, err) +} + +func (s *server) createAutomationHandler(w http.ResponseWriter, r *http.Request) { + // jl, _ := gojsonschema.NewReaderLoader(r.Body) + // *model.AutomationFormSchema.Validate(jl) + + var automationP *model.AutomationForm + if err := parseBody(r, &automationP); err != nil { + JSONError(w, err) + return + } + + result, err := s.service.CreateAutomation(r.Context(), automationP) + response(w, result, err) +} + +func (s *server) getAutomationHandler(w http.ResponseWriter, r *http.Request) { + idP := chi.URLParam(r, "id") + + result, err := s.service.GetAutomation(r.Context(), idP) + response(w, result, err) +} + +func (s *server) updateAutomationHandler(w http.ResponseWriter, r *http.Request) { + idP := chi.URLParam(r, "id") + + // jl, _ := gojsonschema.NewReaderLoader(r.Body) + // *model.AutomationFormSchema.Validate(jl) + + var automationP *model.AutomationForm + if err := parseBody(r, &automationP); err != nil { + JSONError(w, err) + return + } + + result, err := s.service.UpdateAutomation(r.Context(), idP, automationP) + response(w, result, err) +} + +func (s *server) deleteAutomationHandler(w http.ResponseWriter, r *http.Request) { + idP := chi.URLParam(r, "id") + + response(w, nil, s.service.DeleteAutomation(r.Context(), idP)) +} + +func (s *server) currentUserHandler(w http.ResponseWriter, r *http.Request) { + result, err := s.service.CurrentUser(r.Context()) + response(w, result, err) +} + +func (s *server) currentUserDataHandler(w http.ResponseWriter, r *http.Request) { + result, err := s.service.CurrentUserData(r.Context()) + response(w, result, err) +} + +func (s *server) updateCurrentUserDataHandler(w http.ResponseWriter, r *http.Request) { + // jl, _ := gojsonschema.NewReaderLoader(r.Body) + // *model.UserDataSchema.Validate(jl) + + var userdataP *model.UserData + if err := parseBody(r, &userdataP); err != nil { + JSONError(w, err) + return + } + + result, err := s.service.UpdateCurrentUserData(r.Context(), userdataP) + response(w, result, err) +} + +func (s *server) listJobsHandler(w http.ResponseWriter, r *http.Request) { + result, err := s.service.ListJobs(r.Context()) + response(w, result, err) +} + +func (s *server) runJobHandler(w http.ResponseWriter, r *http.Request) { + // jl, _ := gojsonschema.NewReaderLoader(r.Body) + // *model.JobFormSchema.Validate(jl) + + var jobP *model.JobForm + if err := parseBody(r, &jobP); err != nil { + JSONError(w, err) + return + } + + response(w, nil, s.service.RunJob(r.Context(), jobP)) +} + +func (s *server) getJobHandler(w http.ResponseWriter, r *http.Request) { + idP := chi.URLParam(r, "id") + + result, err := s.service.GetJob(r.Context(), idP) + response(w, result, err) +} + +func (s *server) updateJobHandler(w http.ResponseWriter, r *http.Request) { + idP := chi.URLParam(r, "id") + + // jl, _ := gojsonschema.NewReaderLoader(r.Body) + // *model.JobSchema.Validate(jl) + + var jobP *model.Job + if err := parseBody(r, &jobP); err != nil { + JSONError(w, err) + return + } + + result, err := s.service.UpdateJob(r.Context(), idP, jobP) + response(w, result, err) +} + +func (s *server) getLogsHandler(w http.ResponseWriter, r *http.Request) { + referenceP := chi.URLParam(r, "reference") + + result, err := s.service.GetLogs(r.Context(), referenceP) + response(w, result, err) +} + +func (s *server) listPlaybooksHandler(w http.ResponseWriter, r *http.Request) { + result, err := s.service.ListPlaybooks(r.Context()) + response(w, result, err) +} + +func (s *server) createPlaybookHandler(w http.ResponseWriter, r *http.Request) { + // jl, _ := gojsonschema.NewReaderLoader(r.Body) + // *model.PlaybookTemplateFormSchema.Validate(jl) + + var playbookP *model.PlaybookTemplateForm + if err := parseBody(r, &playbookP); err != nil { + JSONError(w, err) + return + } + + result, err := s.service.CreatePlaybook(r.Context(), playbookP) + response(w, result, err) +} + +func (s *server) getPlaybookHandler(w http.ResponseWriter, r *http.Request) { + idP := chi.URLParam(r, "id") + + result, err := s.service.GetPlaybook(r.Context(), idP) + response(w, result, err) +} + +func (s *server) updatePlaybookHandler(w http.ResponseWriter, r *http.Request) { + idP := chi.URLParam(r, "id") + + // jl, _ := gojsonschema.NewReaderLoader(r.Body) + // *model.PlaybookTemplateFormSchema.Validate(jl) + + var playbookP *model.PlaybookTemplateForm + if err := parseBody(r, &playbookP); err != nil { + JSONError(w, err) + return + } + + result, err := s.service.UpdatePlaybook(r.Context(), idP, playbookP) + response(w, result, err) +} + +func (s *server) deletePlaybookHandler(w http.ResponseWriter, r *http.Request) { + idP := chi.URLParam(r, "id") + + response(w, nil, s.service.DeletePlaybook(r.Context(), idP)) +} + +func (s *server) getSettingsHandler(w http.ResponseWriter, r *http.Request) { + result, err := s.service.GetSettings(r.Context()) + response(w, result, err) +} + +func (s *server) getStatisticsHandler(w http.ResponseWriter, r *http.Request) { + result, err := s.service.GetStatistics(r.Context()) + response(w, result, err) +} + +func (s *server) listTasksHandler(w http.ResponseWriter, r *http.Request) { + result, err := s.service.ListTasks(r.Context()) + response(w, result, err) +} + +func (s *server) listTemplatesHandler(w http.ResponseWriter, r *http.Request) { + result, err := s.service.ListTemplates(r.Context()) + response(w, result, err) +} + +func (s *server) createTemplateHandler(w http.ResponseWriter, r *http.Request) { + // jl, _ := gojsonschema.NewReaderLoader(r.Body) + // *model.TicketTemplateFormSchema.Validate(jl) + + var templateP *model.TicketTemplateForm + if err := parseBody(r, &templateP); err != nil { + JSONError(w, err) + return + } + + result, err := s.service.CreateTemplate(r.Context(), templateP) + response(w, result, err) +} + +func (s *server) getTemplateHandler(w http.ResponseWriter, r *http.Request) { + idP := chi.URLParam(r, "id") + + result, err := s.service.GetTemplate(r.Context(), idP) + response(w, result, err) +} + +func (s *server) updateTemplateHandler(w http.ResponseWriter, r *http.Request) { + idP := chi.URLParam(r, "id") + + // jl, _ := gojsonschema.NewReaderLoader(r.Body) + // *model.TicketTemplateFormSchema.Validate(jl) + + var templateP *model.TicketTemplateForm + if err := parseBody(r, &templateP); err != nil { + JSONError(w, err) + return + } + + result, err := s.service.UpdateTemplate(r.Context(), idP, templateP) + response(w, result, err) +} + +func (s *server) deleteTemplateHandler(w http.ResponseWriter, r *http.Request) { + idP := chi.URLParam(r, "id") + + response(w, nil, s.service.DeleteTemplate(r.Context(), idP)) +} + +func (s *server) listTicketsHandler(w http.ResponseWriter, r *http.Request) { + typeP := r.URL.Query().Get("type") + + offsetP, err := parseQueryOptionalInt(r, "offset") + if err != nil { + JSONError(w, err) + return + } + + countP, err := parseQueryOptionalInt(r, "count") + if err != nil { + JSONError(w, err) + return + } + + sortP, err := parseQueryOptionalStringArray(r, "sort") + if err != nil { + JSONError(w, err) + return + } + + descP, err := parseQueryOptionalBoolArray(r, "desc") + if err != nil { + JSONError(w, err) + return + } + + queryP := r.URL.Query().Get("query") + + result, err := s.service.ListTickets(r.Context(), &typeP, offsetP, countP, sortP, descP, &queryP) + response(w, result, err) +} + +func (s *server) createTicketHandler(w http.ResponseWriter, r *http.Request) { + // jl, _ := gojsonschema.NewReaderLoader(r.Body) + // *model.TicketFormSchema.Validate(jl) + + var ticketP *model.TicketForm + if err := parseBody(r, &ticketP); err != nil { + JSONError(w, err) + return + } + + result, err := s.service.CreateTicket(r.Context(), ticketP) + response(w, result, err) +} + +func (s *server) createTicketBatchHandler(w http.ResponseWriter, r *http.Request) { + // jl, _ := gojsonschema.NewReaderLoader(r.Body) + // []*model.TicketFormSchema.Validate(jl) + + var ticketP []*model.TicketForm + if err := parseBody(r, &ticketP); err != nil { + JSONError(w, err) + return + } + + response(w, nil, s.service.CreateTicketBatch(r.Context(), ticketP)) +} + +func (s *server) getTicketHandler(w http.ResponseWriter, r *http.Request) { + idP, err := parseURLInt64(r, "id") + if err != nil { + JSONError(w, err) + return + } + + result, err := s.service.GetTicket(r.Context(), idP) + response(w, result, err) +} + +func (s *server) updateTicketHandler(w http.ResponseWriter, r *http.Request) { + idP, err := parseURLInt64(r, "id") + if err != nil { + JSONError(w, err) + return + } + + // jl, _ := gojsonschema.NewReaderLoader(r.Body) + // *model.TicketSchema.Validate(jl) + + var ticketP *model.Ticket + if err := parseBody(r, &ticketP); err != nil { + JSONError(w, err) + return + } + + result, err := s.service.UpdateTicket(r.Context(), idP, ticketP) + response(w, result, err) +} + +func (s *server) deleteTicketHandler(w http.ResponseWriter, r *http.Request) { + idP, err := parseURLInt64(r, "id") + if err != nil { + JSONError(w, err) + return + } + + response(w, nil, s.service.DeleteTicket(r.Context(), idP)) +} + +func (s *server) addArtifactHandler(w http.ResponseWriter, r *http.Request) { + idP, err := parseURLInt64(r, "id") + if err != nil { + JSONError(w, err) + return + } + + // jl, _ := gojsonschema.NewReaderLoader(r.Body) + // *model.ArtifactSchema.Validate(jl) + + var artifactP *model.Artifact + if err := parseBody(r, &artifactP); err != nil { + JSONError(w, err) + return + } + + result, err := s.service.AddArtifact(r.Context(), idP, artifactP) + response(w, result, err) +} + +func (s *server) getArtifactHandler(w http.ResponseWriter, r *http.Request) { + idP, err := parseURLInt64(r, "id") + if err != nil { + JSONError(w, err) + return + } + + nameP := chi.URLParam(r, "name") + + result, err := s.service.GetArtifact(r.Context(), idP, nameP) + response(w, result, err) +} + +func (s *server) setArtifactHandler(w http.ResponseWriter, r *http.Request) { + idP, err := parseURLInt64(r, "id") + if err != nil { + JSONError(w, err) + return + } + + nameP := chi.URLParam(r, "name") + + // jl, _ := gojsonschema.NewReaderLoader(r.Body) + // *model.ArtifactSchema.Validate(jl) + + var artifactP *model.Artifact + if err := parseBody(r, &artifactP); err != nil { + JSONError(w, err) + return + } + + result, err := s.service.SetArtifact(r.Context(), idP, nameP, artifactP) + response(w, result, err) +} + +func (s *server) removeArtifactHandler(w http.ResponseWriter, r *http.Request) { + idP, err := parseURLInt64(r, "id") + if err != nil { + JSONError(w, err) + return + } + + nameP := chi.URLParam(r, "name") + + result, err := s.service.RemoveArtifact(r.Context(), idP, nameP) + response(w, result, err) +} + +func (s *server) enrichArtifactHandler(w http.ResponseWriter, r *http.Request) { + idP, err := parseURLInt64(r, "id") + if err != nil { + JSONError(w, err) + return + } + + nameP := chi.URLParam(r, "name") + + // jl, _ := gojsonschema.NewReaderLoader(r.Body) + // *model.EnrichmentFormSchema.Validate(jl) + + var dataP *model.EnrichmentForm + if err := parseBody(r, &dataP); err != nil { + JSONError(w, err) + return + } + + result, err := s.service.EnrichArtifact(r.Context(), idP, nameP, dataP) + response(w, result, err) +} + +func (s *server) runArtifactHandler(w http.ResponseWriter, r *http.Request) { + idP, err := parseURLInt64(r, "id") + if err != nil { + JSONError(w, err) + return + } + + nameP := chi.URLParam(r, "name") + + automationP := chi.URLParam(r, "automation") + + response(w, nil, s.service.RunArtifact(r.Context(), idP, nameP, automationP)) +} + +func (s *server) addCommentHandler(w http.ResponseWriter, r *http.Request) { + idP, err := parseURLInt64(r, "id") + if err != nil { + JSONError(w, err) + return + } + + // jl, _ := gojsonschema.NewReaderLoader(r.Body) + // *model.CommentFormSchema.Validate(jl) + + var commentP *model.CommentForm + if err := parseBody(r, &commentP); err != nil { + JSONError(w, err) + return + } + + result, err := s.service.AddComment(r.Context(), idP, commentP) + response(w, result, err) +} + +func (s *server) removeCommentHandler(w http.ResponseWriter, r *http.Request) { + idP, err := parseURLInt64(r, "id") + if err != nil { + JSONError(w, err) + return + } + + commentIDP, err := parseURLInt(r, "commentID") + if err != nil { + JSONError(w, err) + return + } + + result, err := s.service.RemoveComment(r.Context(), idP, commentIDP) + response(w, result, err) +} + +func (s *server) linkFilesHandler(w http.ResponseWriter, r *http.Request) { + idP, err := parseURLInt64(r, "id") + if err != nil { + JSONError(w, err) + return + } + + // jl, _ := gojsonschema.NewReaderLoader(r.Body) + // []*model.FileSchema.Validate(jl) + + var filesP []*model.File + if err := parseBody(r, &filesP); err != nil { + JSONError(w, err) + return + } + + result, err := s.service.LinkFiles(r.Context(), idP, filesP) + response(w, result, err) +} + +func (s *server) addTicketPlaybookHandler(w http.ResponseWriter, r *http.Request) { + idP, err := parseURLInt64(r, "id") + if err != nil { + JSONError(w, err) + return + } + + // jl, _ := gojsonschema.NewReaderLoader(r.Body) + // *model.PlaybookTemplateFormSchema.Validate(jl) + + var playbookP *model.PlaybookTemplateForm + if err := parseBody(r, &playbookP); err != nil { + JSONError(w, err) + return + } + + result, err := s.service.AddTicketPlaybook(r.Context(), idP, playbookP) + response(w, result, err) +} + +func (s *server) removeTicketPlaybookHandler(w http.ResponseWriter, r *http.Request) { + idP, err := parseURLInt64(r, "id") + if err != nil { + JSONError(w, err) + return + } + + playbookIDP := chi.URLParam(r, "playbookID") + + result, err := s.service.RemoveTicketPlaybook(r.Context(), idP, playbookIDP) + response(w, result, err) +} + +func (s *server) setTaskHandler(w http.ResponseWriter, r *http.Request) { + idP, err := parseURLInt64(r, "id") + if err != nil { + JSONError(w, err) + return + } + + playbookIDP := chi.URLParam(r, "playbookID") + + taskIDP := chi.URLParam(r, "taskID") + + // jl, _ := gojsonschema.NewReaderLoader(r.Body) + // *model.TaskSchema.Validate(jl) + + var taskP *model.Task + if err := parseBody(r, &taskP); err != nil { + JSONError(w, err) + return + } + + result, err := s.service.SetTask(r.Context(), idP, playbookIDP, taskIDP, taskP) + response(w, result, err) +} + +func (s *server) completeTaskHandler(w http.ResponseWriter, r *http.Request) { + idP, err := parseURLInt64(r, "id") + if err != nil { + JSONError(w, err) + return + } + + playbookIDP := chi.URLParam(r, "playbookID") + + taskIDP := chi.URLParam(r, "taskID") + + // jl, _ := gojsonschema.NewReaderLoader(r.Body) + // map[string]interface{}Schema.Validate(jl) + + var dataP map[string]interface{} + if err := parseBody(r, &dataP); err != nil { + JSONError(w, err) + return + } + + result, err := s.service.CompleteTask(r.Context(), idP, playbookIDP, taskIDP, dataP) + response(w, result, err) +} + +func (s *server) runTaskHandler(w http.ResponseWriter, r *http.Request) { + idP, err := parseURLInt64(r, "id") + if err != nil { + JSONError(w, err) + return + } + + playbookIDP := chi.URLParam(r, "playbookID") + + taskIDP := chi.URLParam(r, "taskID") + + response(w, nil, s.service.RunTask(r.Context(), idP, playbookIDP, taskIDP)) +} + +func (s *server) setReferencesHandler(w http.ResponseWriter, r *http.Request) { + idP, err := parseURLInt64(r, "id") + if err != nil { + JSONError(w, err) + return + } + + // jl, _ := gojsonschema.NewReaderLoader(r.Body) + // []*model.ReferenceSchema.Validate(jl) + + var referencesP []*model.Reference + if err := parseBody(r, &referencesP); err != nil { + JSONError(w, err) + return + } + + result, err := s.service.SetReferences(r.Context(), idP, referencesP) + response(w, result, err) +} + +func (s *server) setSchemaHandler(w http.ResponseWriter, r *http.Request) { + idP, err := parseURLInt64(r, "id") + if err != nil { + JSONError(w, err) + return + } + + // jl, _ := gojsonschema.NewReaderLoader(r.Body) + // stringSchema.Validate(jl) + + var schemaP string + if err := parseBody(r, &schemaP); err != nil { + JSONError(w, err) + return + } + + result, err := s.service.SetSchema(r.Context(), idP, schemaP) + response(w, result, err) +} + +func (s *server) linkTicketHandler(w http.ResponseWriter, r *http.Request) { + idP, err := parseURLInt64(r, "id") + if err != nil { + JSONError(w, err) + return + } + + // jl, _ := gojsonschema.NewReaderLoader(r.Body) + // int64Schema.Validate(jl) + + var linkedIDP int64 + if err := parseBody(r, &linkedIDP); err != nil { + JSONError(w, err) + return + } + + result, err := s.service.LinkTicket(r.Context(), idP, linkedIDP) + response(w, result, err) +} + +func (s *server) unlinkTicketHandler(w http.ResponseWriter, r *http.Request) { + idP, err := parseURLInt64(r, "id") + if err != nil { + JSONError(w, err) + return + } + + // jl, _ := gojsonschema.NewReaderLoader(r.Body) + // int64Schema.Validate(jl) + + var linkedIDP int64 + if err := parseBody(r, &linkedIDP); err != nil { + JSONError(w, err) + return + } + + result, err := s.service.UnlinkTicket(r.Context(), idP, linkedIDP) + response(w, result, err) +} + +func (s *server) listTicketTypesHandler(w http.ResponseWriter, r *http.Request) { + result, err := s.service.ListTicketTypes(r.Context()) + response(w, result, err) +} + +func (s *server) createTicketTypeHandler(w http.ResponseWriter, r *http.Request) { + // jl, _ := gojsonschema.NewReaderLoader(r.Body) + // *model.TicketTypeFormSchema.Validate(jl) + + var tickettypeP *model.TicketTypeForm + if err := parseBody(r, &tickettypeP); err != nil { + JSONError(w, err) + return + } + + result, err := s.service.CreateTicketType(r.Context(), tickettypeP) + response(w, result, err) +} + +func (s *server) getTicketTypeHandler(w http.ResponseWriter, r *http.Request) { + idP := chi.URLParam(r, "id") + + result, err := s.service.GetTicketType(r.Context(), idP) + response(w, result, err) +} + +func (s *server) updateTicketTypeHandler(w http.ResponseWriter, r *http.Request) { + idP := chi.URLParam(r, "id") + + // jl, _ := gojsonschema.NewReaderLoader(r.Body) + // *model.TicketTypeFormSchema.Validate(jl) + + var tickettypeP *model.TicketTypeForm + if err := parseBody(r, &tickettypeP); err != nil { + JSONError(w, err) + return + } + + result, err := s.service.UpdateTicketType(r.Context(), idP, tickettypeP) + response(w, result, err) +} + +func (s *server) deleteTicketTypeHandler(w http.ResponseWriter, r *http.Request) { + idP := chi.URLParam(r, "id") + + response(w, nil, s.service.DeleteTicketType(r.Context(), idP)) +} + +func (s *server) listUserDataHandler(w http.ResponseWriter, r *http.Request) { + result, err := s.service.ListUserData(r.Context()) + response(w, result, err) +} + +func (s *server) getUserDataHandler(w http.ResponseWriter, r *http.Request) { + idP := chi.URLParam(r, "id") + + result, err := s.service.GetUserData(r.Context(), idP) + response(w, result, err) +} + +func (s *server) updateUserDataHandler(w http.ResponseWriter, r *http.Request) { + idP := chi.URLParam(r, "id") + + // jl, _ := gojsonschema.NewReaderLoader(r.Body) + // *model.UserDataSchema.Validate(jl) + + var userdataP *model.UserData + if err := parseBody(r, &userdataP); err != nil { + JSONError(w, err) + return + } + + result, err := s.service.UpdateUserData(r.Context(), idP, userdataP) + response(w, result, err) +} + +func (s *server) listUsersHandler(w http.ResponseWriter, r *http.Request) { + result, err := s.service.ListUsers(r.Context()) + response(w, result, err) +} + +func (s *server) createUserHandler(w http.ResponseWriter, r *http.Request) { + // jl, _ := gojsonschema.NewReaderLoader(r.Body) + // *model.UserFormSchema.Validate(jl) + + var userP *model.UserForm + if err := parseBody(r, &userP); err != nil { + JSONError(w, err) + return + } + + result, err := s.service.CreateUser(r.Context(), userP) + response(w, result, err) +} + +func (s *server) getUserHandler(w http.ResponseWriter, r *http.Request) { + idP := chi.URLParam(r, "id") + + result, err := s.service.GetUser(r.Context(), idP) + response(w, result, err) +} + +func (s *server) updateUserHandler(w http.ResponseWriter, r *http.Request) { + idP := chi.URLParam(r, "id") + + // jl, _ := gojsonschema.NewReaderLoader(r.Body) + // *model.UserFormSchema.Validate(jl) + + var userP *model.UserForm + if err := parseBody(r, &userP); err != nil { + JSONError(w, err) + return + } + + result, err := s.service.UpdateUser(r.Context(), idP, userP) + response(w, result, err) +} + +func (s *server) deleteUserHandler(w http.ResponseWriter, r *http.Request) { + idP := chi.URLParam(r, "id") + + response(w, nil, s.service.DeleteUser(r.Context(), idP)) +} + +func parseURLInt64(r *http.Request, s string) (int64, error) { + i, err := strconv.ParseInt(chi.URLParam(r, s), 10, 64) + if err != nil { + return 0, fmt.Errorf("%w", &HTTPError{http.StatusUnprocessableEntity, err}) + } + return i, nil +} + +func parseURLInt(r *http.Request, s string) (int, error) { + i, err := strconv.Atoi(chi.URLParam(r, s)) + if err != nil { + return 0, fmt.Errorf("%w", &HTTPError{http.StatusUnprocessableEntity, err}) + } + return i, nil +} + +func parseQueryInt(r *http.Request, s string) (int, error) { + i, err := strconv.Atoi(r.URL.Query().Get(s)) + if err != nil { + return 0, fmt.Errorf("%w", &HTTPError{http.StatusUnprocessableEntity, err}) + } + return i, nil +} + +func parseQueryBool(r *http.Request, s string) (bool, error) { + b, err := strconv.ParseBool(r.URL.Query().Get(s)) + if err != nil { + return false, fmt.Errorf("%w", &HTTPError{http.StatusUnprocessableEntity, err}) + } + return b, nil +} + +func parseQueryStringArray(r *http.Request, key string) ([]string, error) { + stringArray, ok := r.URL.Query()[key] + if !ok { + return nil, nil + } + return removeEmpty(stringArray), nil +} + +func removeEmpty(l []string) []string { + var stringArray []string + for _, s := range l { + if s == "" { + continue + } + stringArray = append(stringArray, s) + } + + return stringArray +} + +func parseQueryBoolArray(r *http.Request, key string) ([]bool, error) { + stringArray, ok := r.URL.Query()[key] + if !ok { + return nil, nil + } + var boolArray []bool + for _, s := range stringArray { + if s == "" { + continue + } + b, err := strconv.ParseBool(s) + if err != nil { + return nil, fmt.Errorf("%w", &HTTPError{http.StatusUnprocessableEntity, err}) + } + boolArray = append(boolArray, b) + } + + return boolArray, nil +} + +func parseQueryOptionalInt(r *http.Request, key string) (*int, error) { + s := r.URL.Query().Get(key) + if s == "" { + return nil, nil + } + + i, err := strconv.Atoi(s) + if err != nil { + return nil, fmt.Errorf("%w", &HTTPError{http.StatusUnprocessableEntity, err}) + } + return &i, nil +} + +func parseQueryOptionalStringArray(r *http.Request, key string) ([]string, error) { + return parseQueryStringArray(r, key) +} + +func parseQueryOptionalBoolArray(r *http.Request, key string) ([]bool, error) { + return parseQueryBoolArray(r, key) +} + +func parseBody(r *http.Request, i interface{}) error { + dec := json.NewDecoder(r.Body) + err := dec.Decode(i) + if err != nil { + return fmt.Errorf("%w", &HTTPError{http.StatusUnprocessableEntity, err}) + } + return nil +} + +func JSONError(w http.ResponseWriter, err error) { + JSONErrorStatus(w, http.StatusInternalServerError, err) +} + +func JSONErrorStatus(w http.ResponseWriter, status int, err error) { + w.WriteHeader(status) + b, _ := json.Marshal(map[string]string{"error": err.Error()}) + w.Write(b) +} + +func response(w http.ResponseWriter, v interface{}, err error) { + if err != nil { + var httpError *HTTPError + if errors.As(err, &httpError) { + JSONErrorStatus(w, httpError.Status, httpError.Internal) + return + } + JSONError(w, err) + return + } + + if v == nil { + w.WriteHeader(http.StatusNoContent) + return + } + w.WriteHeader(http.StatusOK) + b, _ := json.Marshal(v) + w.Write(b) +} diff --git a/generated/api/test_api.go b/generated/api/test_api.go new file mode 100755 index 0000000..f650bed --- /dev/null +++ b/generated/api/test_api.go @@ -0,0 +1,587 @@ +package api + +import "time" + +type Args struct { + Method string + URL string + Data interface{} +} +type Want struct { + Status int + Body interface{} +} + +var Tests = []struct { + Name string + Args Args + Want Want +}{ + + { + Name: "ListAutomations", + Args: Args{Method: "Get", URL: "/automations"}, + Want: Want{ + Status: 200, + Body: []interface{}{map[string]interface{}{"id": "comment", "image": "docker.io/python:3", "script": "", "type": []interface{}{"playbook"}}, map[string]interface{}{"id": "hash.sha1", "image": "docker.io/python:3", "schema": "{\"title\":\"Input\",\"type\":\"object\",\"properties\":{\"default\":{\"type\":\"string\",\"title\":\"Value\"}},\"required\":[\"default\"]}", "script": "", "type": []interface{}{"global", "artifact", "playbook"}}, map[string]interface{}{"id": "thehive", "image": "docker.io/python:3", "schema": "{\"title\":\"TheHive credentials\",\"type\":\"object\",\"properties\":{\"thehiveurl\":{\"type\":\"string\",\"title\":\"TheHive URL (e.g. 'https://thehive.example.org')\"},\"thehivekey\":{\"type\":\"string\",\"title\":\"TheHive API Key\"},\"skip_files\":{\"type\":\"boolean\", \"default\": true, \"title\":\"Skip Files (much faster)\"},\"keep_ids\":{\"type\":\"boolean\", \"default\": true, \"title\":\"Keep IDs and overwrite existing IDs\"}},\"required\":[\"thehiveurl\", \"thehivekey\", \"skip_files\", \"keep_ids\"]}", "script": "", "type": []interface{}{"global"}}, map[string]interface{}{"id": "vt.hash", "image": "docker.io/python:3", "schema": "{\"title\":\"Input\",\"type\":\"object\",\"properties\":{\"default\":{\"type\":\"string\",\"title\":\"Value\"}},\"required\":[\"default\"]}", "script": "", "type": []interface{}{"global", "artifact", "playbook"}}}, + }, + }, + + { + Name: "CreateAutomation", + Args: Args{Method: "Post", URL: "/automations", Data: map[string]interface{}{"id": "hash-sha-256", "image": "docker.io/python:3", "script": "import sys\nimport json\nimport hashlib\n\n\ndef run(msg):\n sha256 = hashlib.sha256(msg['payload']['default'].encode('utf-8'))\n return {'hash': sha256.hexdigest()}\n\n\nprint(json.dumps(run(json.loads(sys.argv[1]))))\n", "type": []interface{}{"global"}}}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"id": "hash-sha-256", "image": "docker.io/python:3", "script": "import sys\nimport json\nimport hashlib\n\n\ndef run(msg):\n sha256 = hashlib.sha256(msg['payload']['default'].encode('utf-8'))\n return {'hash': sha256.hexdigest()}\n\n\nprint(json.dumps(run(json.loads(sys.argv[1]))))\n", "type": []interface{}{"global"}}, + }, + }, + + { + Name: "GetAutomation", + Args: Args{Method: "Get", URL: "/automations/hash.sha1"}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"id": "hash.sha1", "image": "docker.io/python:3", "schema": "{\"title\":\"Input\",\"type\":\"object\",\"properties\":{\"default\":{\"type\":\"string\",\"title\":\"Value\"}},\"required\":[\"default\"]}", "script": "#!/usr/bin/env python\n\nimport sys\nimport json\nimport hashlib\n\n\ndef run(msg):\n sha1 = hashlib.sha1(msg['payload']['default'].encode('utf-8'))\n return {\"hash\": sha1.hexdigest()}\n\n\nprint(json.dumps(run(json.loads(sys.argv[1]))))\n", "type": []interface{}{"global", "artifact", "playbook"}}, + }, + }, + + { + Name: "UpdateAutomation", + Args: Args{Method: "Put", URL: "/automations/hash.sha1", Data: map[string]interface{}{"id": "hash.sha1", "image": "docker.io/python:3", "script": "import sys\nimport json\nimport hashlib\n\n\ndef run(msg):\n sha1 = hashlib.sha1(msg['payload'].encode('utf-8'))\n return {'hash': sha1.hexdigest()}\n\n\nprint(json.dumps(run(json.loads(sys.argv[1]))))\n", "type": []interface{}{"global", "artifact", "playbook"}}}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"id": "hash.sha1", "image": "docker.io/python:3", "script": "import sys\nimport json\nimport hashlib\n\n\ndef run(msg):\n sha1 = hashlib.sha1(msg['payload'].encode('utf-8'))\n return {'hash': sha1.hexdigest()}\n\n\nprint(json.dumps(run(json.loads(sys.argv[1]))))\n", "type": []interface{}{"global", "artifact", "playbook"}}, + }, + }, + + { + Name: "DeleteAutomation", + Args: Args{Method: "Delete", URL: "/automations/hash.sha1"}, + Want: Want{ + Status: 204, + Body: nil, + }, + }, + + { + Name: "CurrentUser", + Args: Args{Method: "Get", URL: "/currentuser"}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"apikey": false, "blocked": false, "id": "bob", "roles": []interface{}{"admin:backup:read", "admin:backup:restore", "admin:group:write", "admin:job:read", "admin:job:write", "admin:log:read", "admin:ticket:delete", "admin:user:write", "admin:userdata:read", "admin:userdata:write", "analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write"}}, + }, + }, + + { + Name: "CurrentUserData", + Args: Args{Method: "Get", URL: "/currentuserdata"}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"email": "bob@example.org", "id": "bob", "name": "Bob Bad"}, + }, + }, + + { + Name: "UpdateCurrentUserData", + Args: Args{Method: "Put", URL: "/currentuserdata", Data: map[string]interface{}{"email": "bob@example.org", "name": "Bob Bad"}}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"email": "bob@example.org", "id": "bob", "name": "Bob Bad"}, + }, + }, + + { + Name: "ListJobs", + Args: Args{Method: "Get", URL: "/jobs"}, + Want: Want{ + Status: 200, + Body: []interface{}{map[string]interface{}{"automation": "hash.sha1", "id": "99cd67131b48", "payload": "test", "status": "created"}}, + }, + }, + + { + Name: "RunJob", + Args: Args{Method: "Post", URL: "/jobs", Data: map[string]interface{}{"automation": "hash.sha1", "message": map[string]interface{}{"payload": "test"}}}, + Want: Want{ + Status: 204, + Body: nil, + }, + }, + + { + Name: "GetJob", + Args: Args{Method: "Get", URL: "/jobs/99cd67131b48"}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"automation": "hash.sha1", "id": "99cd67131b48", "payload": "test", "status": "created"}, + }, + }, + + { + Name: "UpdateJob", + Args: Args{Method: "Put", URL: "/jobs/99cd67131b48", Data: map[string]interface{}{"automation": "hash.sha1", "id": "99cd67131b48", "payload": "test", "status": "failed"}}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"automation": "hash.sha1", "id": "99cd67131b48", "payload": "test", "status": "failed"}, + }, + }, + + { + Name: "GetLogs", + Args: Args{Method: "Get", URL: "/logs/tickets%252F294511"}, + Want: Want{ + Status: 200, + Body: []interface{}{map[string]interface{}{"created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "creator": "bob", "message": "Fail run account resist lend solve incident centre priority temperature. Cause change distribution examine location technique shape partner milk customer. Rail tea plate soil report cook railway interpretation breath action. Exercise dream accept park conclusion addition shoot assistance may answer. Gold writer link stop combine hear power name commitment operation. Determine lifespan support grow degree henry exclude detail set religion. Direct library policy convention chain retain discover ride walk student. Gather proposal select march aspect play noise avoid encourage employ. Assessment preserve transport combine wish influence income guess run stand. Charge limit crime ignore statement foundation study issue stop claim.", "reference": "tickets/294511", "type": "manual"}}, + }, + }, + + { + Name: "ListPlaybooks", + Args: Args{Method: "Get", URL: "/playbooks"}, + Want: Want{ + Status: 200, + Body: []interface{}{map[string]interface{}{"id": "malware", "name": "Malware", "yaml": "name: Malware\ntasks:\n file-or-hash:\n name: Do you have the file or the hash?\n type: input\n schema:\n title: Malware\n type: object\n properties:\n file:\n type: string\n title: \"I have the\"\n enum: [ \"File\", \"Hash\" ]\n next:\n enter-hash: \"file == 'Hash'\"\n upload: \"file == 'File'\"\n\n enter-hash:\n name: Please enter the hash\n type: input\n schema:\n title: Malware\n type: object\n properties:\n hash:\n type: string\n title: Please enter the hash value\n minlength: 32\n next:\n virustotal: \"hash != ''\"\n\n upload:\n name: Upload the malware\n type: input\n schema:\n title: Malware\n type: object\n properties:\n malware:\n type: object\n x-display: file\n title: Please upload the malware\n next:\n hash: \"malware\"\n\n hash:\n name: Hash the malware\n type: automation\n automation: hash.sha1\n payload:\n default: \"playbook.tasks['upload'].data['malware']\"\n next:\n virustotal:\n\n virustotal:\n name: Send hash to VirusTotal\n type: automation\n automation: vt.hash\n args:\n hash: \"playbook.tasks['enter-hash'].data['hash'] || playbook.tasks['hash'].data['hash']\"\n # next:\n # known-malware: \"score > 5\"\n # sandbox: \"score < 6\" # unknown-malware\n"}, map[string]interface{}{"id": "phishing", "name": "Phishing", "yaml": "name: Phishing\ntasks:\n board:\n name: Board Involvement?\n description: Is a board member involved?\n type: input\n schema:\n properties:\n boardInvolved:\n default: false\n title: A board member is involved.\n type: boolean\n required:\n - boardInvolved\n title: Board Involvement?\n type: object\n next:\n escalate: \"boardInvolved == true\"\n mail-available: \"boardInvolved == false\"\n\n escalate:\n name: Escalate to CISO\n description: Please escalate the task to the CISO\n type: task\n\n mail-available:\n name: Mail available\n type: input\n schema:\n oneOf:\n - properties:\n mail:\n title: Mail\n type: string\n x-display: textarea\n schemaKey:\n const: 'yes'\n type: string\n required:\n - mail\n title: 'Yes'\n - properties:\n schemaKey:\n const: 'no'\n type: string\n title: 'No'\n title: Mail available\n type: object\n next:\n block-sender: \"schemaKey == 'yes'\"\n extract-iocs: \"schemaKey == 'yes'\"\n search-email-gateway: \"schemaKey == 'no'\"\n\n search-email-gateway:\n name: Search email gateway\n description: Please search email-gateway for the phishing mail.\n type: task\n next:\n extract-iocs:\n\n block-sender:\n name: Block sender\n type: task\n next:\n extract-iocs:\n\n extract-iocs:\n name: Extract IOCs\n description: Please insert the IOCs\n type: input\n schema:\n properties:\n iocs:\n items:\n type: string\n title: IOCs\n type: array\n title: Extract IOCs\n type: object\n next:\n block-iocs:\n\n block-iocs:\n name: Block IOCs\n type: task\n"}, map[string]interface{}{"id": "simple", "name": "Simple", "yaml": "name: Simple\ntasks:\n input:\n name: Enter something to hash\n type: input\n schema:\n title: Something\n type: object\n properties:\n something:\n type: string\n title: Something\n default: \"\"\n next:\n hash: \"something != ''\"\n\n hash:\n name: Hash the something\n type: automation\n automation: hash.sha1\n payload:\n default: \"playbook.tasks['input'].data['something']\"\n next:\n comment: \"hash != ''\"\n\n comment:\n name: Comment the hash\n type: automation\n automation: comment\n payload:\n default: \"playbook.tasks['hash'].data['hash']\"\n next:\n done: \"done\"\n\n done:\n name: You can close this case now\n type: task\n"}}, + }, + }, + + { + Name: "CreatePlaybook", + Args: Args{Method: "Post", URL: "/playbooks", Data: map[string]interface{}{"yaml": "name: Simple2\ntasks:\n input:\n name: Upload malware if possible\n type: input\n schema:\n title: Malware\n type: object\n properties:\n malware:\n type: string\n title: Select malware\n default: \"\"\n next:\n hash: \"malware != ''\"\n\n hash:\n name: Hash the malware\n type: automation\n automation: hash.sha1\n payload:\n default: \"playbook.tasks['input'].data['malware']\"\n next:\n escalate:\n\n escalate:\n name: Escalate to malware team\n type: task\n"}}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"id": "simple-2", "name": "Simple2", "yaml": "name: Simple2\ntasks:\n input:\n name: Upload malware if possible\n type: input\n schema:\n title: Malware\n type: object\n properties:\n malware:\n type: string\n title: Select malware\n default: \"\"\n next:\n hash: \"malware != ''\"\n\n hash:\n name: Hash the malware\n type: automation\n automation: hash.sha1\n payload:\n default: \"playbook.tasks['input'].data['malware']\"\n next:\n escalate:\n\n escalate:\n name: Escalate to malware team\n type: task\n"}, + }, + }, + + { + Name: "GetPlaybook", + Args: Args{Method: "Get", URL: "/playbooks/simple"}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"id": "simple", "name": "Simple", "yaml": "name: Simple\ntasks:\n input:\n name: Enter something to hash\n type: input\n schema:\n title: Something\n type: object\n properties:\n something:\n type: string\n title: Something\n default: \"\"\n next:\n hash: \"something != ''\"\n\n hash:\n name: Hash the something\n type: automation\n automation: hash.sha1\n payload:\n default: \"playbook.tasks['input'].data['something']\"\n next:\n comment: \"hash != ''\"\n\n comment:\n name: Comment the hash\n type: automation\n automation: comment\n payload:\n default: \"playbook.tasks['hash'].data['hash']\"\n next:\n done: \"done\"\n\n done:\n name: You can close this case now\n type: task\n"}, + }, + }, + + { + Name: "UpdatePlaybook", + Args: Args{Method: "Put", URL: "/playbooks/simple", Data: map[string]interface{}{"yaml": "name: Simple\ntasks:\n input:\n name: Upload malware if possible\n type: input\n schema:\n title: Malware\n type: object\n properties:\n malware:\n type: string\n title: Select malware\n default: \"\"\n next:\n hash: \"malware != ''\"\n\n hash:\n name: Hash the malware\n type: automation\n automation: hash.sha1\n payload:\n default: \"playbook.tasks['input'].data['malware']\"\n next:\n escalate:\n\n escalate:\n name: Escalate to malware team\n type: task\n"}}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"id": "simple", "name": "Simple", "yaml": "name: Simple\ntasks:\n input:\n name: Upload malware if possible\n type: input\n schema:\n title: Malware\n type: object\n properties:\n malware:\n type: string\n title: Select malware\n default: \"\"\n next:\n hash: \"malware != ''\"\n\n hash:\n name: Hash the malware\n type: automation\n automation: hash.sha1\n payload:\n default: \"playbook.tasks['input'].data['malware']\"\n next:\n escalate:\n\n escalate:\n name: Escalate to malware team\n type: task\n"}, + }, + }, + + { + Name: "DeletePlaybook", + Args: Args{Method: "Delete", URL: "/playbooks/simple"}, + Want: Want{ + Status: 204, + Body: nil, + }, + }, + + { + Name: "GetSettings", + Args: Args{Method: "Get", URL: "/settings"}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"artifactStates": []interface{}{map[string]interface{}{"color": "info", "icon": "mdi-help-circle-outline", "id": "unknown", "name": "Unknown"}, map[string]interface{}{"color": "error", "icon": "mdi-skull", "id": "malicious", "name": "Malicious"}, map[string]interface{}{"color": "success", "icon": "mdi-check", "id": "clean", "name": "Clean"}}, "roles": []interface{}{"admin:backup:read", "admin:backup:restore", "admin:group:write", "admin:job:read", "admin:job:write", "admin:log:read", "admin:ticket:delete", "admin:user:write", "admin:userdata:read", "admin:userdata:write", "analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write"}, "ticketTypes": []interface{}{map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-alert", "id": "alert", "name": "Alerts"}, map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-radioactive", "id": "incident", "name": "Incidents"}, map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-fingerprint", "id": "investigation", "name": "Forensic Investigations"}, map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-target", "id": "hunt", "name": "Threat Hunting"}}, "tier": "community", "timeformat": "YYYY-MM-DDThh:mm:ss", "version": "0.0.0-test"}, + }, + }, + + { + Name: "GetStatistics", + Args: Args{Method: "Get", URL: "/statistics"}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"open_tickets_per_user": map[string]interface{}{}, "tickets_per_type": map[string]interface{}{"alert": 2, "incident": 1}, "tickets_per_week": map[string]interface{}{"2021-39": 3}, "unassigned": 0}, + }, + }, + + { + Name: "ListTasks", + Args: Args{Method: "Get", URL: "/tasks"}, + Want: Want{ + Status: 200, + Body: nil, + }, + }, + + { + Name: "ListTemplates", + Args: Args{Method: "Get", URL: "/templates"}, + Want: Want{ + Status: 200, + Body: []interface{}{map[string]interface{}{"id": "default", "name": "Default", "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Default\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n"}}, + }, + }, + + { + Name: "CreateTemplate", + Args: Args{Method: "Post", URL: "/templates", Data: map[string]interface{}{"name": "My Template", "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n"}}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"id": "my-template", "name": "My Template", "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n"}, + }, + }, + + { + Name: "GetTemplate", + Args: Args{Method: "Get", URL: "/templates/default"}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"id": "default", "name": "Default", "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Default\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n"}, + }, + }, + + { + Name: "UpdateTemplate", + Args: Args{Method: "Put", URL: "/templates/default", Data: map[string]interface{}{"name": "My Template", "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n"}}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"id": "default", "name": "My Template", "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n"}, + }, + }, + + { + Name: "DeleteTemplate", + Args: Args{Method: "Delete", URL: "/templates/default"}, + Want: Want{ + Status: 204, + Body: nil, + }, + }, + + { + Name: "ListTickets", + Args: Args{Method: "Get", URL: "/tickets"}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"count": 3, "tickets": []interface{}{map[string]interface{}{"artifacts": []interface{}{map[string]interface{}{"name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", "status": "unknown"}, map[string]interface{}{"name": "http://www.customerviral.io/scalable/vertical/killer", "status": "clean"}, map[string]interface{}{"name": "leadreintermediate.io", "status": "malicious"}}, "created": time.Date(2021, time.October, 2, 16, 4, 59, 78206000, time.UTC), "id": 8123, "modified": time.Date(2021, time.October, 2, 16, 4, 59, 78206000, time.UTC), "name": "live zebra", "owner": "demo", "playbooks": map[string]interface{}{"phishing": map[string]interface{}{"name": "Phishing", "tasks": map[string]interface{}{"block-iocs": map[string]interface{}{"created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Block IOCs", "type": "task"}, "block-sender": map[string]interface{}{"created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Block sender", "next": map[string]interface{}{"extract-iocs": ""}, "type": "task"}, "board": map[string]interface{}{"created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Board Involvement?", "next": map[string]interface{}{"escalate": "boardInvolved == true", "mail-available": "boardInvolved == false"}, "schema": map[string]interface{}{"properties": map[string]interface{}{"boardInvolved": map[string]interface{}{"default": false, "title": "A board member is involved.", "type": "boolean"}}, "required": []interface{}{"boardInvolved"}, "title": "Board Involvement?", "type": "object"}, "type": "input"}, "escalate": map[string]interface{}{"created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Escalate to CISO", "type": "task"}, "extract-iocs": map[string]interface{}{"created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Extract IOCs", "next": map[string]interface{}{"block-iocs": ""}, "schema": map[string]interface{}{"properties": map[string]interface{}{"iocs": map[string]interface{}{"items": map[string]interface{}{"type": "string"}, "title": "IOCs", "type": "array"}}, "title": "Extract IOCs", "type": "object"}, "type": "input"}, "mail-available": map[string]interface{}{"created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Mail available", "next": map[string]interface{}{"block-sender": "schemaKey == 'yes'", "extract-iocs": "schemaKey == 'yes'", "search-email-gateway": "schemaKey == 'no'"}, "schema": map[string]interface{}{"oneOf": []interface{}{map[string]interface{}{"properties": map[string]interface{}{"mail": map[string]interface{}{"title": "Mail", "type": "string", "x-display": "textarea"}, "schemaKey": map[string]interface{}{"const": "yes", "type": "string"}}, "required": []interface{}{"mail"}, "title": "Yes"}, map[string]interface{}{"properties": map[string]interface{}{"schemaKey": map[string]interface{}{"const": "no", "type": "string"}}, "title": "No"}}, "title": "Mail available", "type": "object"}, "type": "input"}, "search-email-gateway": map[string]interface{}{"created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Search email gateway", "next": map[string]interface{}{"extract-iocs": ""}, "type": "task"}}}}, "references": []interface{}{map[string]interface{}{"href": "https://www.leadmaximize.net/e-services/back-end", "name": "performance"}, map[string]interface{}{"href": "http://www.corporateinteractive.name/rich", "name": "autumn"}, map[string]interface{}{"href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", "name": "suggest"}}, "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", "status": "closed", "type": "incident"}, map[string]interface{}{"created": time.Date(2021, time.October, 2, 16, 4, 59, 78186000, time.UTC), "id": 8125, "modified": time.Date(2021, time.October, 2, 16, 4, 59, 78186000, time.UTC), "name": "phishing from selenafadel@von.com detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "https://www.seniorleading-edge.name/users/efficient", "name": "recovery"}, map[string]interface{}{"href": "http://www.dynamicseamless.com/clicks-and-mortar", "name": "force"}, map[string]interface{}{"href": "http://www.leadscalable.biz/envisioneer", "name": "fund"}}, "schema": "{}", "status": "closed", "type": "alert"}, map[string]interface{}{"created": time.Date(2021, time.October, 2, 16, 4, 59, 78186000, time.UTC), "id": 8126, "modified": time.Date(2021, time.October, 2, 16, 4, 59, 78186000, time.UTC), "name": "Surfaceintroduce virus detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "http://www.centralworld-class.io/synthesize", "name": "university"}, map[string]interface{}{"href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", "name": "goal"}, map[string]interface{}{"href": "http://www.chiefsyndicate.io/action-items", "name": "unemployment"}}, "schema": "{}", "status": "closed", "type": "alert"}}}, + }, + }, + + { + Name: "CreateTicket", + Args: Args{Method: "Post", URL: "/tickets", Data: map[string]interface{}{"id": 123, "name": "Wannacry infection", "owner": "bob", "status": "open", "type": "incident"}}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "id": 123, "modified": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "name": "Wannacry infection", "owner": "bob", "schema": "{}", "status": "open", "type": "incident"}, + }, + }, + + { + Name: "CreateTicketBatch", + Args: Args{Method: "Post", URL: "/tickets/batch", Data: []interface{}{map[string]interface{}{"id": 123, "name": "Wannacry infection", "owner": "bob", "status": "open", "type": "incident"}}}, + Want: Want{ + Status: 204, + Body: nil, + }, + }, + + { + Name: "GetTicket", + Args: Args{Method: "Get", URL: "/tickets/8125"}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"created": time.Date(2021, time.October, 2, 16, 4, 59, 78186000, time.UTC), "id": 8125, "modified": time.Date(2021, time.October, 2, 16, 4, 59, 78186000, time.UTC), "name": "phishing from selenafadel@von.com detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "https://www.seniorleading-edge.name/users/efficient", "name": "recovery"}, map[string]interface{}{"href": "http://www.dynamicseamless.com/clicks-and-mortar", "name": "force"}, map[string]interface{}{"href": "http://www.leadscalable.biz/envisioneer", "name": "fund"}}, "schema": "{}", "status": "closed", "tickets": []interface{}{map[string]interface{}{"created": time.Date(2021, time.October, 2, 16, 4, 59, 78186000, time.UTC), "id": 8126, "modified": time.Date(2021, time.October, 2, 16, 4, 59, 78186000, time.UTC), "name": "Surfaceintroduce virus detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "http://www.centralworld-class.io/synthesize", "name": "university"}, map[string]interface{}{"href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", "name": "goal"}, map[string]interface{}{"href": "http://www.chiefsyndicate.io/action-items", "name": "unemployment"}}, "schema": "{}", "status": "closed", "type": "alert"}}, "type": "alert"}, + }, + }, + + { + Name: "UpdateTicket", + Args: Args{Method: "Put", URL: "/tickets/8125", Data: map[string]interface{}{"created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "modified": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "name": "phishing from selenafadel@von.org detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "https://www.seniorleading-edge.name/users/efficient", "name": "recovery"}, map[string]interface{}{"href": "http://www.dynamicseamless.com/clicks-and-mortar", "name": "force"}, map[string]interface{}{"href": "http://www.leadscalable.biz/envisioneer", "name": "fund"}}, "schema": "{}", "status": "closed", "type": "alert"}}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "id": 8125, "modified": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "name": "phishing from selenafadel@von.org detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "https://www.seniorleading-edge.name/users/efficient", "name": "recovery"}, map[string]interface{}{"href": "http://www.dynamicseamless.com/clicks-and-mortar", "name": "force"}, map[string]interface{}{"href": "http://www.leadscalable.biz/envisioneer", "name": "fund"}}, "schema": "{}", "status": "closed", "tickets": []interface{}{map[string]interface{}{"created": time.Date(2021, time.October, 2, 16, 4, 59, 78186000, time.UTC), "id": 8126, "modified": time.Date(2021, time.October, 2, 16, 4, 59, 78186000, time.UTC), "name": "Surfaceintroduce virus detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "http://www.centralworld-class.io/synthesize", "name": "university"}, map[string]interface{}{"href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", "name": "goal"}, map[string]interface{}{"href": "http://www.chiefsyndicate.io/action-items", "name": "unemployment"}}, "schema": "{}", "status": "closed", "type": "alert"}}, "type": "alert"}, + }, + }, + + { + Name: "DeleteTicket", + Args: Args{Method: "Delete", URL: "/tickets/8125"}, + Want: Want{ + Status: 204, + Body: nil, + }, + }, + + { + Name: "AddArtifact", + Args: Args{Method: "Post", URL: "/tickets/8123/artifacts", Data: map[string]interface{}{"name": "2.2.2.2"}}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"artifacts": []interface{}{map[string]interface{}{"name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", "status": "unknown"}, map[string]interface{}{"name": "http://www.customerviral.io/scalable/vertical/killer", "status": "clean"}, map[string]interface{}{"name": "leadreintermediate.io", "status": "malicious"}, map[string]interface{}{"name": "2.2.2.2", "status": "unknown", "type": "ip"}}, "created": time.Date(2021, time.October, 2, 16, 4, 59, 78206000, time.UTC), "id": 8123, "modified": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "name": "live zebra", "owner": "demo", "playbooks": map[string]interface{}{"phishing": map[string]interface{}{"name": "Phishing", "tasks": map[string]interface{}{"block-iocs": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Block IOCs", "order": 6, "type": "task"}, "block-sender": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Block sender", "next": map[string]interface{}{"extract-iocs": ""}, "order": 3, "type": "task"}, "board": map[string]interface{}{"active": true, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Board Involvement?", "next": map[string]interface{}{"escalate": "boardInvolved == true", "mail-available": "boardInvolved == false"}, "order": 0, "schema": map[string]interface{}{"properties": map[string]interface{}{"boardInvolved": map[string]interface{}{"default": false, "title": "A board member is involved.", "type": "boolean"}}, "required": []interface{}{"boardInvolved"}, "title": "Board Involvement?", "type": "object"}, "type": "input"}, "escalate": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Escalate to CISO", "order": 1, "type": "task"}, "extract-iocs": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Extract IOCs", "next": map[string]interface{}{"block-iocs": ""}, "order": 5, "schema": map[string]interface{}{"properties": map[string]interface{}{"iocs": map[string]interface{}{"items": map[string]interface{}{"type": "string"}, "title": "IOCs", "type": "array"}}, "title": "Extract IOCs", "type": "object"}, "type": "input"}, "mail-available": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Mail available", "next": map[string]interface{}{"block-sender": "schemaKey == 'yes'", "extract-iocs": "schemaKey == 'yes'", "search-email-gateway": "schemaKey == 'no'"}, "order": 2, "schema": map[string]interface{}{"oneOf": []interface{}{map[string]interface{}{"properties": map[string]interface{}{"mail": map[string]interface{}{"title": "Mail", "type": "string", "x-display": "textarea"}, "schemaKey": map[string]interface{}{"const": "yes", "type": "string"}}, "required": []interface{}{"mail"}, "title": "Yes"}, map[string]interface{}{"properties": map[string]interface{}{"schemaKey": map[string]interface{}{"const": "no", "type": "string"}}, "title": "No"}}, "title": "Mail available", "type": "object"}, "type": "input"}, "search-email-gateway": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Search email gateway", "next": map[string]interface{}{"extract-iocs": ""}, "order": 4, "type": "task"}}}}, "references": []interface{}{map[string]interface{}{"href": "https://www.leadmaximize.net/e-services/back-end", "name": "performance"}, map[string]interface{}{"href": "http://www.corporateinteractive.name/rich", "name": "autumn"}, map[string]interface{}{"href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", "name": "suggest"}}, "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", "status": "closed", "type": "incident"}, + }, + }, + + { + Name: "GetArtifact", + Args: Args{Method: "Get", URL: "/tickets/8123/artifacts/leadreintermediate.io"}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"name": "leadreintermediate.io", "status": "malicious"}, + }, + }, + + { + Name: "SetArtifact", + Args: Args{Method: "Put", URL: "/tickets/8123/artifacts/leadreintermediate.io", Data: map[string]interface{}{"name": "leadreintermediate.io", "status": "clean"}}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"artifacts": []interface{}{map[string]interface{}{"name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", "status": "unknown"}, map[string]interface{}{"name": "http://www.customerviral.io/scalable/vertical/killer", "status": "clean"}, map[string]interface{}{"name": "leadreintermediate.io", "status": "clean"}}, "created": time.Date(2021, time.October, 2, 16, 4, 59, 78206000, time.UTC), "id": 8123, "modified": time.Date(2021, time.October, 2, 16, 4, 59, 78206000, time.UTC), "name": "live zebra", "owner": "demo", "playbooks": map[string]interface{}{"phishing": map[string]interface{}{"name": "Phishing", "tasks": map[string]interface{}{"block-iocs": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Block IOCs", "order": 6, "type": "task"}, "block-sender": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Block sender", "next": map[string]interface{}{"extract-iocs": ""}, "order": 3, "type": "task"}, "board": map[string]interface{}{"active": true, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Board Involvement?", "next": map[string]interface{}{"escalate": "boardInvolved == true", "mail-available": "boardInvolved == false"}, "order": 0, "schema": map[string]interface{}{"properties": map[string]interface{}{"boardInvolved": map[string]interface{}{"default": false, "title": "A board member is involved.", "type": "boolean"}}, "required": []interface{}{"boardInvolved"}, "title": "Board Involvement?", "type": "object"}, "type": "input"}, "escalate": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Escalate to CISO", "order": 1, "type": "task"}, "extract-iocs": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Extract IOCs", "next": map[string]interface{}{"block-iocs": ""}, "order": 5, "schema": map[string]interface{}{"properties": map[string]interface{}{"iocs": map[string]interface{}{"items": map[string]interface{}{"type": "string"}, "title": "IOCs", "type": "array"}}, "title": "Extract IOCs", "type": "object"}, "type": "input"}, "mail-available": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Mail available", "next": map[string]interface{}{"block-sender": "schemaKey == 'yes'", "extract-iocs": "schemaKey == 'yes'", "search-email-gateway": "schemaKey == 'no'"}, "order": 2, "schema": map[string]interface{}{"oneOf": []interface{}{map[string]interface{}{"properties": map[string]interface{}{"mail": map[string]interface{}{"title": "Mail", "type": "string", "x-display": "textarea"}, "schemaKey": map[string]interface{}{"const": "yes", "type": "string"}}, "required": []interface{}{"mail"}, "title": "Yes"}, map[string]interface{}{"properties": map[string]interface{}{"schemaKey": map[string]interface{}{"const": "no", "type": "string"}}, "title": "No"}}, "title": "Mail available", "type": "object"}, "type": "input"}, "search-email-gateway": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Search email gateway", "next": map[string]interface{}{"extract-iocs": ""}, "order": 4, "type": "task"}}}}, "references": []interface{}{map[string]interface{}{"href": "https://www.leadmaximize.net/e-services/back-end", "name": "performance"}, map[string]interface{}{"href": "http://www.corporateinteractive.name/rich", "name": "autumn"}, map[string]interface{}{"href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", "name": "suggest"}}, "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", "status": "closed", "type": "incident"}, + }, + }, + + { + Name: "RemoveArtifact", + Args: Args{Method: "Delete", URL: "/tickets/8123/artifacts/leadreintermediate.io"}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"artifacts": []interface{}{map[string]interface{}{"name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", "status": "unknown"}, map[string]interface{}{"name": "http://www.customerviral.io/scalable/vertical/killer", "status": "clean"}}, "created": time.Date(2021, time.October, 2, 16, 4, 59, 78206000, time.UTC), "id": 8123, "modified": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "name": "live zebra", "owner": "demo", "playbooks": map[string]interface{}{"phishing": map[string]interface{}{"name": "Phishing", "tasks": map[string]interface{}{"block-iocs": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Block IOCs", "order": 6, "type": "task"}, "block-sender": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Block sender", "next": map[string]interface{}{"extract-iocs": ""}, "order": 3, "type": "task"}, "board": map[string]interface{}{"active": true, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Board Involvement?", "next": map[string]interface{}{"escalate": "boardInvolved == true", "mail-available": "boardInvolved == false"}, "order": 0, "schema": map[string]interface{}{"properties": map[string]interface{}{"boardInvolved": map[string]interface{}{"default": false, "title": "A board member is involved.", "type": "boolean"}}, "required": []interface{}{"boardInvolved"}, "title": "Board Involvement?", "type": "object"}, "type": "input"}, "escalate": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Escalate to CISO", "order": 1, "type": "task"}, "extract-iocs": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Extract IOCs", "next": map[string]interface{}{"block-iocs": ""}, "order": 5, "schema": map[string]interface{}{"properties": map[string]interface{}{"iocs": map[string]interface{}{"items": map[string]interface{}{"type": "string"}, "title": "IOCs", "type": "array"}}, "title": "Extract IOCs", "type": "object"}, "type": "input"}, "mail-available": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Mail available", "next": map[string]interface{}{"block-sender": "schemaKey == 'yes'", "extract-iocs": "schemaKey == 'yes'", "search-email-gateway": "schemaKey == 'no'"}, "order": 2, "schema": map[string]interface{}{"oneOf": []interface{}{map[string]interface{}{"properties": map[string]interface{}{"mail": map[string]interface{}{"title": "Mail", "type": "string", "x-display": "textarea"}, "schemaKey": map[string]interface{}{"const": "yes", "type": "string"}}, "required": []interface{}{"mail"}, "title": "Yes"}, map[string]interface{}{"properties": map[string]interface{}{"schemaKey": map[string]interface{}{"const": "no", "type": "string"}}, "title": "No"}}, "title": "Mail available", "type": "object"}, "type": "input"}, "search-email-gateway": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Search email gateway", "next": map[string]interface{}{"extract-iocs": ""}, "order": 4, "type": "task"}}}}, "references": []interface{}{map[string]interface{}{"href": "https://www.leadmaximize.net/e-services/back-end", "name": "performance"}, map[string]interface{}{"href": "http://www.corporateinteractive.name/rich", "name": "autumn"}, map[string]interface{}{"href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", "name": "suggest"}}, "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", "status": "closed", "type": "incident"}, + }, + }, + + { + Name: "EnrichArtifact", + Args: Args{Method: "Post", URL: "/tickets/8123/artifacts/leadreintermediate.io/enrich", Data: map[string]interface{}{"data": map[string]interface{}{"hash": "b7a067a742c20d07a7456646de89bc2d408a1153"}, "name": "hash.sha1"}}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"artifacts": []interface{}{map[string]interface{}{"name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", "status": "unknown"}, map[string]interface{}{"name": "http://www.customerviral.io/scalable/vertical/killer", "status": "clean"}, map[string]interface{}{"enrichments": map[string]interface{}{"hash.sha1": map[string]interface{}{"created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "data": map[string]interface{}{"hash": "b7a067a742c20d07a7456646de89bc2d408a1153"}, "name": "hash.sha1"}}, "name": "leadreintermediate.io", "status": "malicious"}}, "created": time.Date(2021, time.October, 2, 16, 4, 59, 78206000, time.UTC), "id": 8123, "modified": time.Date(2021, time.October, 2, 16, 4, 59, 78206000, time.UTC), "name": "live zebra", "owner": "demo", "playbooks": map[string]interface{}{"phishing": map[string]interface{}{"name": "Phishing", "tasks": map[string]interface{}{"block-iocs": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Block IOCs", "order": 6, "type": "task"}, "block-sender": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Block sender", "next": map[string]interface{}{"extract-iocs": ""}, "order": 3, "type": "task"}, "board": map[string]interface{}{"active": true, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Board Involvement?", "next": map[string]interface{}{"escalate": "boardInvolved == true", "mail-available": "boardInvolved == false"}, "order": 0, "schema": map[string]interface{}{"properties": map[string]interface{}{"boardInvolved": map[string]interface{}{"default": false, "title": "A board member is involved.", "type": "boolean"}}, "required": []interface{}{"boardInvolved"}, "title": "Board Involvement?", "type": "object"}, "type": "input"}, "escalate": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Escalate to CISO", "order": 1, "type": "task"}, "extract-iocs": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Extract IOCs", "next": map[string]interface{}{"block-iocs": ""}, "order": 5, "schema": map[string]interface{}{"properties": map[string]interface{}{"iocs": map[string]interface{}{"items": map[string]interface{}{"type": "string"}, "title": "IOCs", "type": "array"}}, "title": "Extract IOCs", "type": "object"}, "type": "input"}, "mail-available": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Mail available", "next": map[string]interface{}{"block-sender": "schemaKey == 'yes'", "extract-iocs": "schemaKey == 'yes'", "search-email-gateway": "schemaKey == 'no'"}, "order": 2, "schema": map[string]interface{}{"oneOf": []interface{}{map[string]interface{}{"properties": map[string]interface{}{"mail": map[string]interface{}{"title": "Mail", "type": "string", "x-display": "textarea"}, "schemaKey": map[string]interface{}{"const": "yes", "type": "string"}}, "required": []interface{}{"mail"}, "title": "Yes"}, map[string]interface{}{"properties": map[string]interface{}{"schemaKey": map[string]interface{}{"const": "no", "type": "string"}}, "title": "No"}}, "title": "Mail available", "type": "object"}, "type": "input"}, "search-email-gateway": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Search email gateway", "next": map[string]interface{}{"extract-iocs": ""}, "order": 4, "type": "task"}}}}, "references": []interface{}{map[string]interface{}{"href": "https://www.leadmaximize.net/e-services/back-end", "name": "performance"}, map[string]interface{}{"href": "http://www.corporateinteractive.name/rich", "name": "autumn"}, map[string]interface{}{"href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", "name": "suggest"}}, "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", "status": "closed", "type": "incident"}, + }, + }, + + { + Name: "RunArtifact", + Args: Args{Method: "Post", URL: "/tickets/8123/artifacts/leadreintermediate.io/run/hash.sha1"}, + Want: Want{ + Status: 204, + Body: nil, + }, + }, + + { + Name: "AddComment", + Args: Args{Method: "Post", URL: "/tickets/8125/comments", Data: map[string]interface{}{"message": "My first comment"}}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"comments": []interface{}{map[string]interface{}{"created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "creator": "bob", "message": "My first comment"}}, "created": time.Date(2021, time.October, 2, 16, 4, 59, 78186000, time.UTC), "id": 8125, "modified": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "name": "phishing from selenafadel@von.com detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "https://www.seniorleading-edge.name/users/efficient", "name": "recovery"}, map[string]interface{}{"href": "http://www.dynamicseamless.com/clicks-and-mortar", "name": "force"}, map[string]interface{}{"href": "http://www.leadscalable.biz/envisioneer", "name": "fund"}}, "schema": "{}", "status": "closed", "tickets": []interface{}{map[string]interface{}{"created": time.Date(2021, time.October, 2, 16, 4, 59, 78186000, time.UTC), "id": 8126, "modified": time.Date(2021, time.October, 2, 16, 4, 59, 78186000, time.UTC), "name": "Surfaceintroduce virus detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "http://www.centralworld-class.io/synthesize", "name": "university"}, map[string]interface{}{"href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", "name": "goal"}, map[string]interface{}{"href": "http://www.chiefsyndicate.io/action-items", "name": "unemployment"}}, "schema": "{}", "status": "closed", "type": "alert"}}, "type": "alert"}, + }, + }, + + { + Name: "RemoveComment", + Args: Args{Method: "Delete", URL: "/tickets/8123/comments/0"}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"artifacts": []interface{}{map[string]interface{}{"name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", "status": "unknown"}, map[string]interface{}{"name": "http://www.customerviral.io/scalable/vertical/killer", "status": "clean"}, map[string]interface{}{"name": "leadreintermediate.io", "status": "malicious"}}, "created": time.Date(2021, time.October, 2, 16, 4, 59, 78206000, time.UTC), "id": 8123, "modified": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "name": "live zebra", "owner": "demo", "playbooks": map[string]interface{}{"phishing": map[string]interface{}{"name": "Phishing", "tasks": map[string]interface{}{"block-iocs": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Block IOCs", "order": 6, "type": "task"}, "block-sender": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Block sender", "next": map[string]interface{}{"extract-iocs": ""}, "order": 3, "type": "task"}, "board": map[string]interface{}{"active": true, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Board Involvement?", "next": map[string]interface{}{"escalate": "boardInvolved == true", "mail-available": "boardInvolved == false"}, "order": 0, "schema": map[string]interface{}{"properties": map[string]interface{}{"boardInvolved": map[string]interface{}{"default": false, "title": "A board member is involved.", "type": "boolean"}}, "required": []interface{}{"boardInvolved"}, "title": "Board Involvement?", "type": "object"}, "type": "input"}, "escalate": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Escalate to CISO", "order": 1, "type": "task"}, "extract-iocs": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Extract IOCs", "next": map[string]interface{}{"block-iocs": ""}, "order": 5, "schema": map[string]interface{}{"properties": map[string]interface{}{"iocs": map[string]interface{}{"items": map[string]interface{}{"type": "string"}, "title": "IOCs", "type": "array"}}, "title": "Extract IOCs", "type": "object"}, "type": "input"}, "mail-available": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Mail available", "next": map[string]interface{}{"block-sender": "schemaKey == 'yes'", "extract-iocs": "schemaKey == 'yes'", "search-email-gateway": "schemaKey == 'no'"}, "order": 2, "schema": map[string]interface{}{"oneOf": []interface{}{map[string]interface{}{"properties": map[string]interface{}{"mail": map[string]interface{}{"title": "Mail", "type": "string", "x-display": "textarea"}, "schemaKey": map[string]interface{}{"const": "yes", "type": "string"}}, "required": []interface{}{"mail"}, "title": "Yes"}, map[string]interface{}{"properties": map[string]interface{}{"schemaKey": map[string]interface{}{"const": "no", "type": "string"}}, "title": "No"}}, "title": "Mail available", "type": "object"}, "type": "input"}, "search-email-gateway": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Search email gateway", "next": map[string]interface{}{"extract-iocs": ""}, "order": 4, "type": "task"}}}}, "references": []interface{}{map[string]interface{}{"href": "https://www.leadmaximize.net/e-services/back-end", "name": "performance"}, map[string]interface{}{"href": "http://www.corporateinteractive.name/rich", "name": "autumn"}, map[string]interface{}{"href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", "name": "suggest"}}, "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", "status": "closed", "type": "incident"}, + }, + }, + + { + Name: "LinkFiles", + Args: Args{Method: "Put", URL: "/tickets/8125/files", Data: []interface{}{map[string]interface{}{"key": "myfile", "name": "document.doc"}}}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"created": time.Date(2021, time.October, 2, 16, 4, 59, 78186000, time.UTC), "files": []interface{}{map[string]interface{}{"key": "myfile", "name": "document.doc"}}, "id": 8125, "modified": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "name": "phishing from selenafadel@von.com detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "https://www.seniorleading-edge.name/users/efficient", "name": "recovery"}, map[string]interface{}{"href": "http://www.dynamicseamless.com/clicks-and-mortar", "name": "force"}, map[string]interface{}{"href": "http://www.leadscalable.biz/envisioneer", "name": "fund"}}, "schema": "{}", "status": "closed", "tickets": []interface{}{map[string]interface{}{"created": time.Date(2021, time.October, 2, 16, 4, 59, 78186000, time.UTC), "id": 8126, "modified": time.Date(2021, time.October, 2, 16, 4, 59, 78186000, time.UTC), "name": "Surfaceintroduce virus detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "http://www.centralworld-class.io/synthesize", "name": "university"}, map[string]interface{}{"href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", "name": "goal"}, map[string]interface{}{"href": "http://www.chiefsyndicate.io/action-items", "name": "unemployment"}}, "schema": "{}", "status": "closed", "type": "alert"}}, "type": "alert"}, + }, + }, + + { + Name: "AddTicketPlaybook", + Args: Args{Method: "Post", URL: "/tickets/8125/playbooks", Data: map[string]interface{}{"yaml": "name: Simple\ntasks:\n input:\n name: Upload malware if possible\n type: input\n schema:\n title: Malware\n type: object\n properties:\n malware:\n type: string\n title: Select malware\n default: \"\"\n next:\n hash: \"malware != ''\"\n\n hash:\n name: Hash the malware\n type: automation\n automation: hash.sha1\n payload:\n default: \"playbook.tasks['input'].data['malware']\"\n next:\n escalate:\n\n escalate:\n name: Escalate to malware team\n type: task\n"}}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"created": time.Date(2021, time.October, 2, 16, 4, 59, 78186000, time.UTC), "id": 8125, "modified": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "name": "phishing from selenafadel@von.com detected", "owner": "demo", "playbooks": map[string]interface{}{"simple": map[string]interface{}{"name": "Simple", "tasks": map[string]interface{}{"escalate": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Escalate to malware team", "order": 2, "type": "task"}, "hash": map[string]interface{}{"active": false, "automation": "hash.sha1", "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Hash the malware", "next": map[string]interface{}{"escalate": ""}, "order": 1, "payload": map[string]interface{}{"default": "playbook.tasks['input'].data['malware']"}, "type": "automation"}, "input": map[string]interface{}{"active": true, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Upload malware if possible", "next": map[string]interface{}{"hash": "malware != ''"}, "order": 0, "schema": map[string]interface{}{"properties": map[string]interface{}{"malware": map[string]interface{}{"default": "", "title": "Select malware", "type": "string"}}, "title": "Malware", "type": "object"}, "type": "input"}}}}, "references": []interface{}{map[string]interface{}{"href": "https://www.seniorleading-edge.name/users/efficient", "name": "recovery"}, map[string]interface{}{"href": "http://www.dynamicseamless.com/clicks-and-mortar", "name": "force"}, map[string]interface{}{"href": "http://www.leadscalable.biz/envisioneer", "name": "fund"}}, "schema": "{}", "status": "closed", "tickets": []interface{}{map[string]interface{}{"created": time.Date(2021, time.October, 2, 16, 4, 59, 78186000, time.UTC), "id": 8126, "modified": time.Date(2021, time.October, 2, 16, 4, 59, 78186000, time.UTC), "name": "Surfaceintroduce virus detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "http://www.centralworld-class.io/synthesize", "name": "university"}, map[string]interface{}{"href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", "name": "goal"}, map[string]interface{}{"href": "http://www.chiefsyndicate.io/action-items", "name": "unemployment"}}, "schema": "{}", "status": "closed", "type": "alert"}}, "type": "alert"}, + }, + }, + + { + Name: "RemoveTicketPlaybook", + Args: Args{Method: "Delete", URL: "/tickets/8123/playbooks/phishing"}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"artifacts": []interface{}{map[string]interface{}{"name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", "status": "unknown"}, map[string]interface{}{"name": "http://www.customerviral.io/scalable/vertical/killer", "status": "clean"}, map[string]interface{}{"name": "leadreintermediate.io", "status": "malicious"}}, "created": time.Date(2021, time.October, 2, 16, 4, 59, 78206000, time.UTC), "id": 8123, "modified": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "name": "live zebra", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "https://www.leadmaximize.net/e-services/back-end", "name": "performance"}, map[string]interface{}{"href": "http://www.corporateinteractive.name/rich", "name": "autumn"}, map[string]interface{}{"href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", "name": "suggest"}}, "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", "status": "closed", "type": "incident"}, + }, + }, + + { + Name: "SetTask", + Args: Args{Method: "Put", URL: "/tickets/8123/playbooks/phishing/task/board", Data: map[string]interface{}{"active": true, "data": map[string]interface{}{"boardInvolved": true}, "done": false, "name": "Board Involvement?", "next": map[string]interface{}{"escalate": "boardInvolved == true", "mail-available": "boardInvolved == false"}, "order": 0, "schema": map[string]interface{}{"properties": map[string]interface{}{"boardInvolved": map[string]interface{}{"default": false, "title": "A board member is involved.", "type": "boolean"}}, "required": []interface{}{"boardInvolved"}, "title": "Board Involvement?", "type": "object"}, "type": "input"}}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"artifacts": []interface{}{map[string]interface{}{"name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", "status": "unknown"}, map[string]interface{}{"name": "http://www.customerviral.io/scalable/vertical/killer", "status": "clean"}, map[string]interface{}{"name": "leadreintermediate.io", "status": "malicious"}}, "created": time.Date(2021, time.October, 2, 16, 4, 59, 78206000, time.UTC), "id": 8123, "modified": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "name": "live zebra", "owner": "demo", "playbooks": map[string]interface{}{"phishing": map[string]interface{}{"name": "Phishing", "tasks": map[string]interface{}{"block-iocs": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Block IOCs", "order": 6, "type": "task"}, "block-sender": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Block sender", "next": map[string]interface{}{"extract-iocs": ""}, "order": 3, "type": "task"}, "board": map[string]interface{}{"active": true, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "data": map[string]interface{}{"boardInvolved": true}, "done": false, "name": "Board Involvement?", "next": map[string]interface{}{"escalate": "boardInvolved == true", "mail-available": "boardInvolved == false"}, "order": 0, "schema": map[string]interface{}{"properties": map[string]interface{}{"boardInvolved": map[string]interface{}{"default": false, "title": "A board member is involved.", "type": "boolean"}}, "required": []interface{}{"boardInvolved"}, "title": "Board Involvement?", "type": "object"}, "type": "input"}, "escalate": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Escalate to CISO", "order": 1, "type": "task"}, "extract-iocs": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Extract IOCs", "next": map[string]interface{}{"block-iocs": ""}, "order": 5, "schema": map[string]interface{}{"properties": map[string]interface{}{"iocs": map[string]interface{}{"items": map[string]interface{}{"type": "string"}, "title": "IOCs", "type": "array"}}, "title": "Extract IOCs", "type": "object"}, "type": "input"}, "mail-available": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Mail available", "next": map[string]interface{}{"block-sender": "schemaKey == 'yes'", "extract-iocs": "schemaKey == 'yes'", "search-email-gateway": "schemaKey == 'no'"}, "order": 2, "schema": map[string]interface{}{"oneOf": []interface{}{map[string]interface{}{"properties": map[string]interface{}{"mail": map[string]interface{}{"title": "Mail", "type": "string", "x-display": "textarea"}, "schemaKey": map[string]interface{}{"const": "yes", "type": "string"}}, "required": []interface{}{"mail"}, "title": "Yes"}, map[string]interface{}{"properties": map[string]interface{}{"schemaKey": map[string]interface{}{"const": "no", "type": "string"}}, "title": "No"}}, "title": "Mail available", "type": "object"}, "type": "input"}, "search-email-gateway": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Search email gateway", "next": map[string]interface{}{"extract-iocs": ""}, "order": 4, "type": "task"}}}}, "references": []interface{}{map[string]interface{}{"href": "https://www.leadmaximize.net/e-services/back-end", "name": "performance"}, map[string]interface{}{"href": "http://www.corporateinteractive.name/rich", "name": "autumn"}, map[string]interface{}{"href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", "name": "suggest"}}, "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", "status": "closed", "type": "incident"}, + }, + }, + + { + Name: "CompleteTask", + Args: Args{Method: "Put", URL: "/tickets/8123/playbooks/phishing/task/board/complete", Data: map[string]interface{}{"boardInvolved": true}}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"artifacts": []interface{}{map[string]interface{}{"name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", "status": "unknown"}, map[string]interface{}{"name": "http://www.customerviral.io/scalable/vertical/killer", "status": "clean"}, map[string]interface{}{"name": "leadreintermediate.io", "status": "malicious"}}, "created": time.Date(2021, time.October, 2, 16, 4, 59, 78206000, time.UTC), "id": 8123, "modified": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "name": "live zebra", "owner": "demo", "playbooks": map[string]interface{}{"phishing": map[string]interface{}{"name": "Phishing", "tasks": map[string]interface{}{"block-iocs": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Block IOCs", "order": 6, "type": "task"}, "block-sender": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Block sender", "next": map[string]interface{}{"extract-iocs": ""}, "order": 3, "type": "task"}, "board": map[string]interface{}{"active": false, "closed": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "data": map[string]interface{}{"boardInvolved": true}, "done": true, "name": "Board Involvement?", "next": map[string]interface{}{"escalate": "boardInvolved == true", "mail-available": "boardInvolved == false"}, "order": 0, "schema": map[string]interface{}{"properties": map[string]interface{}{"boardInvolved": map[string]interface{}{"default": false, "title": "A board member is involved.", "type": "boolean"}}, "required": []interface{}{"boardInvolved"}, "title": "Board Involvement?", "type": "object"}, "type": "input"}, "escalate": map[string]interface{}{"active": true, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Escalate to CISO", "order": 1, "type": "task"}, "extract-iocs": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Extract IOCs", "next": map[string]interface{}{"block-iocs": ""}, "order": 5, "schema": map[string]interface{}{"properties": map[string]interface{}{"iocs": map[string]interface{}{"items": map[string]interface{}{"type": "string"}, "title": "IOCs", "type": "array"}}, "title": "Extract IOCs", "type": "object"}, "type": "input"}, "mail-available": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Mail available", "next": map[string]interface{}{"block-sender": "schemaKey == 'yes'", "extract-iocs": "schemaKey == 'yes'", "search-email-gateway": "schemaKey == 'no'"}, "order": 2, "schema": map[string]interface{}{"oneOf": []interface{}{map[string]interface{}{"properties": map[string]interface{}{"mail": map[string]interface{}{"title": "Mail", "type": "string", "x-display": "textarea"}, "schemaKey": map[string]interface{}{"const": "yes", "type": "string"}}, "required": []interface{}{"mail"}, "title": "Yes"}, map[string]interface{}{"properties": map[string]interface{}{"schemaKey": map[string]interface{}{"const": "no", "type": "string"}}, "title": "No"}}, "title": "Mail available", "type": "object"}, "type": "input"}, "search-email-gateway": map[string]interface{}{"active": false, "created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Search email gateway", "next": map[string]interface{}{"extract-iocs": ""}, "order": 4, "type": "task"}}}}, "references": []interface{}{map[string]interface{}{"href": "https://www.leadmaximize.net/e-services/back-end", "name": "performance"}, map[string]interface{}{"href": "http://www.corporateinteractive.name/rich", "name": "autumn"}, map[string]interface{}{"href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", "name": "suggest"}}, "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", "status": "closed", "type": "incident"}, + }, + }, + + { + Name: "RunTask", + Args: Args{Method: "Post", URL: "/tickets/8123/playbooks/phishing/task/board/run"}, + Want: Want{ + Status: 204, + Body: nil, + }, + }, + + { + Name: "SetReferences", + Args: Args{Method: "Put", URL: "/tickets/8125/references", Data: []interface{}{map[string]interface{}{"href": "http://www.leadscalable.biz/envisioneer", "name": "fund"}}}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"created": time.Date(2021, time.October, 2, 16, 4, 59, 78186000, time.UTC), "id": 8125, "modified": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "name": "phishing from selenafadel@von.com detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "http://www.leadscalable.biz/envisioneer", "name": "fund"}}, "schema": "{}", "status": "closed", "tickets": []interface{}{map[string]interface{}{"created": time.Date(2021, time.October, 2, 16, 4, 59, 78186000, time.UTC), "id": 8126, "modified": time.Date(2021, time.October, 2, 16, 4, 59, 78186000, time.UTC), "name": "Surfaceintroduce virus detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "http://www.centralworld-class.io/synthesize", "name": "university"}, map[string]interface{}{"href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", "name": "goal"}, map[string]interface{}{"href": "http://www.chiefsyndicate.io/action-items", "name": "unemployment"}}, "schema": "{}", "status": "closed", "type": "alert"}}, "type": "alert"}, + }, + }, + + { + Name: "SetSchema", + Args: Args{Method: "Put", URL: "/tickets/8125/schema", Data: "{}"}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"created": time.Date(2021, time.October, 2, 16, 4, 59, 78186000, time.UTC), "id": 8125, "modified": time.Date(2021, time.October, 2, 16, 4, 59, 78186000, time.UTC), "name": "phishing from selenafadel@von.com detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "https://www.seniorleading-edge.name/users/efficient", "name": "recovery"}, map[string]interface{}{"href": "http://www.dynamicseamless.com/clicks-and-mortar", "name": "force"}, map[string]interface{}{"href": "http://www.leadscalable.biz/envisioneer", "name": "fund"}}, "schema": "{}", "status": "closed", "tickets": []interface{}{map[string]interface{}{"created": time.Date(2021, time.October, 2, 16, 4, 59, 78186000, time.UTC), "id": 8126, "modified": time.Date(2021, time.October, 2, 16, 4, 59, 78186000, time.UTC), "name": "Surfaceintroduce virus detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "http://www.centralworld-class.io/synthesize", "name": "university"}, map[string]interface{}{"href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", "name": "goal"}, map[string]interface{}{"href": "http://www.chiefsyndicate.io/action-items", "name": "unemployment"}}, "schema": "{}", "status": "closed", "type": "alert"}}, "type": "alert"}, + }, + }, + + { + Name: "LinkTicket", + Args: Args{Method: "Patch", URL: "/tickets/8126/tickets", Data: 8123}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"created": time.Date(2021, time.October, 2, 16, 4, 59, 78186000, time.UTC), "id": 8126, "modified": time.Date(2021, time.October, 2, 16, 4, 59, 78186000, time.UTC), "name": "Surfaceintroduce virus detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "http://www.centralworld-class.io/synthesize", "name": "university"}, map[string]interface{}{"href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", "name": "goal"}, map[string]interface{}{"href": "http://www.chiefsyndicate.io/action-items", "name": "unemployment"}}, "schema": "{}", "status": "closed", "tickets": []interface{}{map[string]interface{}{"artifacts": []interface{}{map[string]interface{}{"name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", "status": "unknown"}, map[string]interface{}{"name": "http://www.customerviral.io/scalable/vertical/killer", "status": "clean"}, map[string]interface{}{"name": "leadreintermediate.io", "status": "malicious"}}, "created": time.Date(2021, time.October, 2, 16, 4, 59, 78206000, time.UTC), "id": 8123, "modified": time.Date(2021, time.October, 2, 16, 4, 59, 78206000, time.UTC), "name": "live zebra", "owner": "demo", "playbooks": map[string]interface{}{"phishing": map[string]interface{}{"name": "Phishing", "tasks": map[string]interface{}{"block-iocs": map[string]interface{}{"created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Block IOCs", "type": "task"}, "block-sender": map[string]interface{}{"created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Block sender", "next": map[string]interface{}{"extract-iocs": ""}, "type": "task"}, "board": map[string]interface{}{"created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Board Involvement?", "next": map[string]interface{}{"escalate": "boardInvolved == true", "mail-available": "boardInvolved == false"}, "schema": map[string]interface{}{"properties": map[string]interface{}{"boardInvolved": map[string]interface{}{"default": false, "title": "A board member is involved.", "type": "boolean"}}, "required": []interface{}{"boardInvolved"}, "title": "Board Involvement?", "type": "object"}, "type": "input"}, "escalate": map[string]interface{}{"created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Escalate to CISO", "type": "task"}, "extract-iocs": map[string]interface{}{"created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Extract IOCs", "next": map[string]interface{}{"block-iocs": ""}, "schema": map[string]interface{}{"properties": map[string]interface{}{"iocs": map[string]interface{}{"items": map[string]interface{}{"type": "string"}, "title": "IOCs", "type": "array"}}, "title": "Extract IOCs", "type": "object"}, "type": "input"}, "mail-available": map[string]interface{}{"created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Mail available", "next": map[string]interface{}{"block-sender": "schemaKey == 'yes'", "extract-iocs": "schemaKey == 'yes'", "search-email-gateway": "schemaKey == 'no'"}, "schema": map[string]interface{}{"oneOf": []interface{}{map[string]interface{}{"properties": map[string]interface{}{"mail": map[string]interface{}{"title": "Mail", "type": "string", "x-display": "textarea"}, "schemaKey": map[string]interface{}{"const": "yes", "type": "string"}}, "required": []interface{}{"mail"}, "title": "Yes"}, map[string]interface{}{"properties": map[string]interface{}{"schemaKey": map[string]interface{}{"const": "no", "type": "string"}}, "title": "No"}}, "title": "Mail available", "type": "object"}, "type": "input"}, "search-email-gateway": map[string]interface{}{"created": time.Date(2021, time.December, 12, 12, 12, 12, 12, time.UTC), "done": false, "name": "Search email gateway", "next": map[string]interface{}{"extract-iocs": ""}, "type": "task"}}}}, "references": []interface{}{map[string]interface{}{"href": "https://www.leadmaximize.net/e-services/back-end", "name": "performance"}, map[string]interface{}{"href": "http://www.corporateinteractive.name/rich", "name": "autumn"}, map[string]interface{}{"href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", "name": "suggest"}}, "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", "status": "closed", "type": "incident"}, map[string]interface{}{"created": time.Date(2021, time.October, 2, 16, 4, 59, 78186000, time.UTC), "id": 8125, "modified": time.Date(2021, time.October, 2, 16, 4, 59, 78186000, time.UTC), "name": "phishing from selenafadel@von.com detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "https://www.seniorleading-edge.name/users/efficient", "name": "recovery"}, map[string]interface{}{"href": "http://www.dynamicseamless.com/clicks-and-mortar", "name": "force"}, map[string]interface{}{"href": "http://www.leadscalable.biz/envisioneer", "name": "fund"}}, "schema": "{}", "status": "closed", "type": "alert"}}, "type": "alert"}, + }, + }, + + { + Name: "UnlinkTicket", + Args: Args{Method: "Delete", URL: "/tickets/8126/tickets", Data: 8125}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"created": time.Date(2021, time.October, 2, 16, 4, 59, 78186000, time.UTC), "id": 8126, "modified": time.Date(2021, time.October, 2, 16, 4, 59, 78186000, time.UTC), "name": "Surfaceintroduce virus detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "http://www.centralworld-class.io/synthesize", "name": "university"}, map[string]interface{}{"href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", "name": "goal"}, map[string]interface{}{"href": "http://www.chiefsyndicate.io/action-items", "name": "unemployment"}}, "schema": "{}", "status": "closed", "type": "alert"}, + }, + }, + + { + Name: "ListTicketTypes", + Args: Args{Method: "Get", URL: "/tickettypes"}, + Want: Want{ + Status: 200, + Body: []interface{}{map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-alert", "id": "alert", "name": "Alerts"}, map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-radioactive", "id": "incident", "name": "Incidents"}, map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-fingerprint", "id": "investigation", "name": "Forensic Investigations"}, map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-target", "id": "hunt", "name": "Threat Hunting"}}, + }, + }, + + { + Name: "CreateTicketType", + Args: Args{Method: "Post", URL: "/tickettypes", Data: map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-newspaper-variant-outline", "name": "TI Tickets"}}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-newspaper-variant-outline", "id": "ti-tickets", "name": "TI Tickets"}, + }, + }, + + { + Name: "GetTicketType", + Args: Args{Method: "Get", URL: "/tickettypes/alert"}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-alert", "id": "alert", "name": "Alerts"}, + }, + }, + + { + Name: "UpdateTicketType", + Args: Args{Method: "Put", URL: "/tickettypes/alert", Data: map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-bell", "id": "alert", "name": "Alerts"}}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-bell", "id": "alert", "name": "Alerts"}, + }, + }, + + { + Name: "DeleteTicketType", + Args: Args{Method: "Delete", URL: "/tickettypes/alert"}, + Want: Want{ + Status: 204, + Body: nil, + }, + }, + + { + Name: "ListUserData", + Args: Args{Method: "Get", URL: "/userdata"}, + Want: Want{ + Status: 200, + Body: []interface{}{map[string]interface{}{"email": "bob@example.org", "id": "bob", "name": "Bob Bad"}}, + }, + }, + + { + Name: "GetUserData", + Args: Args{Method: "Get", URL: "/userdata/bob"}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"email": "bob@example.org", "id": "bob", "name": "Bob Bad"}, + }, + }, + + { + Name: "UpdateUserData", + Args: Args{Method: "Put", URL: "/userdata/bob", Data: map[string]interface{}{"blocked": false, "email": "bob@example.org", "name": "Bob Bad"}}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"email": "bob@example.org", "id": "bob", "name": "Bob Bad"}, + }, + }, + + { + Name: "ListUsers", + Args: Args{Method: "Get", URL: "/users"}, + Want: Want{ + Status: 200, + Body: []interface{}{map[string]interface{}{"apikey": false, "blocked": false, "id": "bob", "roles": []interface{}{"admin:backup:read", "admin:backup:restore", "admin:group:write", "admin:job:read", "admin:job:write", "admin:log:read", "admin:ticket:delete", "admin:user:write", "admin:userdata:read", "admin:userdata:write", "analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write"}}, map[string]interface{}{"apikey": true, "blocked": false, "id": "script", "roles": []interface{}{"analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write"}}}, + }, + }, + + { + Name: "CreateUser", + Args: Args{Method: "Post", URL: "/users", Data: map[string]interface{}{"id": "syncscript", "roles": []interface{}{"analyst"}}}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"blocked": false, "id": "syncscript", "roles": []interface{}{"analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read"}, "secret": "v39bOuobnlEljfWzjAgoKzhmnh1xSMxH"}, + }, + }, + + { + Name: "GetUser", + Args: Args{Method: "Get", URL: "/users/script"}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"apikey": true, "blocked": false, "id": "script", "roles": []interface{}{"analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write"}}, + }, + }, + + { + Name: "UpdateUser", + Args: Args{Method: "Put", URL: "/users/bob", Data: map[string]interface{}{"roles": []interface{}{"analyst", "admin"}}}, + Want: Want{ + Status: 200, + Body: map[string]interface{}{"apikey": false, "blocked": false, "id": "bob", "roles": []interface{}{"admin:backup:read", "admin:backup:restore", "admin:group:write", "admin:job:read", "admin:job:write", "admin:log:read", "admin:ticket:delete", "admin:user:write", "admin:userdata:read", "admin:userdata:write", "analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write"}}, + }, + }, + + { + Name: "DeleteUser", + Args: Args{Method: "Delete", URL: "/users/script"}, + Want: Want{ + Status: 204, + Body: nil, + }, + }, +} diff --git a/generated/catalyst.json b/generated/catalyst.json index 7699c7e..6f94a40 100644 --- a/generated/catalyst.json +++ b/generated/catalyst.json @@ -795,10 +795,7 @@ "content" : { "application/json" : { "schema" : { - "items" : { - "$ref" : "#/components/schemas/PlaybookTemplateResponse" - }, - "type" : "array" + "$ref" : "#/components/schemas/PlaybookTemplateResponse" } }, "test" : { @@ -1245,7 +1242,7 @@ "application/json" : { "schema" : { "items" : { - "$ref" : "#/components/schemas/TaskResponse" + "$ref" : "#/components/schemas/TaskWithContext" }, "type" : "array" } @@ -1805,7 +1802,7 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/TicketResponse" + "$ref" : "#/components/schemas/TicketWithTickets" } }, "test" : { @@ -1889,7 +1886,7 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/TicketResponse" + "$ref" : "#/components/schemas/TicketWithTickets" } }, "test" : { @@ -1976,7 +1973,7 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/TicketResponse" + "$ref" : "#/components/schemas/TicketWithTickets" } }, "test" : { @@ -2187,7 +2184,7 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/TicketResponse" + "$ref" : "#/components/schemas/TicketWithTickets" } }, "test" : { @@ -2443,7 +2440,7 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/TicketResponse" + "$ref" : "#/components/schemas/TicketWithTickets" } }, "test" : { @@ -2660,7 +2657,7 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/Artifact" + "$ref" : "#/components/schemas/TicketWithTickets" } }, "test" : { @@ -2922,7 +2919,7 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/TicketResponse" + "$ref" : "#/components/schemas/TicketWithTickets" } }, "test" : { @@ -3013,7 +3010,7 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/TicketResponse" + "$ref" : "#/components/schemas/TicketWithTickets" } }, "test" : { @@ -3226,7 +3223,7 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/TicketResponse" + "$ref" : "#/components/schemas/TicketWithTickets" } }, "test" : { @@ -3317,7 +3314,7 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/TicketResponse" + "$ref" : "#/components/schemas/TicketWithTickets" } }, "test" : { @@ -3418,6 +3415,9 @@ "description" : "successful operation" } }, + "security" : [ { + "roles" : [ "ticket:write" ] + } ], "summary" : "Add a new ticket playbook", "tags" : [ "tickets" ], "x-codegen-request-body-name" : "playbook" @@ -3451,7 +3451,7 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/TicketResponse" + "$ref" : "#/components/schemas/TicketWithTickets" } }, "test" : { @@ -3545,7 +3545,7 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/TicketResponse" + "$ref" : "#/components/schemas/TicketWithTickets" } }, "test" : { @@ -3776,7 +3776,7 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/TicketResponse" + "$ref" : "#/components/schemas/TicketWithTickets" } }, "test" : { @@ -4038,7 +4038,7 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/TicketResponse" + "$ref" : "#/components/schemas/TicketWithTickets" } }, "test" : { @@ -4112,14 +4112,14 @@ } }, "description" : "New ticket schema", - "required" : false + "required" : true }, "responses" : { "200" : { "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/TicketResponse" + "$ref" : "#/components/schemas/TicketWithTickets" } }, "test" : { @@ -4207,7 +4207,7 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/TicketResponse" + "$ref" : "#/components/schemas/TicketWithTickets" } }, "test" : { @@ -4273,7 +4273,7 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/TicketResponse" + "$ref" : "#/components/schemas/TicketWithTickets" } }, "test" : { @@ -5433,7 +5433,6 @@ "$ref" : "#/components/schemas/Context" }, "payload" : { - "properties" : { }, "type" : "object" }, "secrets" : { diff --git a/generated/catalyst.yml b/generated/catalyst.yml index 4d65698..9b07934 100644 --- a/generated/catalyst.yml +++ b/generated/catalyst.yml @@ -325,8 +325,7 @@ definitions: properties: context: $ref: '#/definitions/Context' - payload: - type: object + payload: {} secrets: additionalProperties: type: string @@ -2251,9 +2250,7 @@ paths: name: Escalate to malware team type: task schema: - items: - $ref: '#/definitions/PlaybookTemplateResponse' - type: array + $ref: '#/definitions/PlaybookTemplateResponse' security: - roles: - playbook:write @@ -2687,7 +2684,7 @@ paths: test: [] schema: items: - $ref: '#/definitions/TaskResponse' + $ref: '#/definitions/TaskWithContext' type: array security: - roles: @@ -3726,7 +3723,7 @@ paths: type: alert type: alert schema: - $ref: '#/definitions/TicketResponse' + $ref: '#/definitions/TicketWithTickets' security: - roles: - ticket:read @@ -3801,7 +3798,7 @@ paths: type: alert type: alert schema: - $ref: '#/definitions/TicketResponse' + $ref: '#/definitions/TicketWithTickets' security: - roles: - ticket:write @@ -4053,7 +4050,7 @@ paths: status: closed type: incident schema: - $ref: '#/definitions/TicketResponse' + $ref: '#/definitions/TicketWithTickets' security: - roles: - ticket:write @@ -4297,7 +4294,7 @@ paths: status: closed type: incident schema: - $ref: '#/definitions/TicketResponse' + $ref: '#/definitions/TicketWithTickets' security: - roles: - ticket:write @@ -4580,7 +4577,7 @@ paths: status: closed type: incident schema: - $ref: '#/definitions/TicketResponse' + $ref: '#/definitions/TicketWithTickets' security: - roles: - ticket:write @@ -4841,7 +4838,7 @@ paths: status: closed type: incident schema: - $ref: '#/definitions/Artifact' + $ref: '#/definitions/TicketWithTickets' security: - roles: - ticket:write @@ -4938,7 +4935,7 @@ paths: type: alert type: alert schema: - $ref: '#/definitions/TicketResponse' + $ref: '#/definitions/TicketWithTickets' security: - roles: - ticket:write @@ -5186,7 +5183,7 @@ paths: status: closed type: incident schema: - $ref: '#/definitions/TicketResponse' + $ref: '#/definitions/TicketWithTickets' security: - roles: - ticket:write @@ -5257,7 +5254,7 @@ paths: type: alert type: alert schema: - $ref: '#/definitions/TicketResponse' + $ref: '#/definitions/TicketWithTickets' security: - roles: - ticket:write @@ -5388,7 +5385,10 @@ paths: type: alert type: alert schema: - $ref: '#/definitions/TicketResponse' + $ref: '#/definitions/TicketWithTickets' + security: + - roles: + - ticket:write summary: Add a new ticket playbook tags: - tickets @@ -5527,7 +5527,7 @@ paths: status: closed type: incident schema: - $ref: '#/definitions/TicketResponse' + $ref: '#/definitions/TicketWithTickets' security: - roles: - ticket:write @@ -5809,7 +5809,7 @@ paths: status: closed type: incident schema: - $ref: '#/definitions/TicketResponse' + $ref: '#/definitions/TicketWithTickets' security: - roles: - ticket:write @@ -6073,7 +6073,7 @@ paths: status: closed type: incident schema: - $ref: '#/definitions/TicketResponse' + $ref: '#/definitions/TicketWithTickets' security: - roles: - ticket:write @@ -6167,7 +6167,7 @@ paths: type: alert type: alert schema: - $ref: '#/definitions/TicketResponse' + $ref: '#/definitions/TicketWithTickets' security: - roles: - ticket:write @@ -6188,6 +6188,7 @@ paths: - description: New ticket schema in: body name: schema + required: true schema: type: string x-example: '{}' @@ -6228,7 +6229,7 @@ paths: type: alert type: alert schema: - $ref: '#/definitions/TicketResponse' + $ref: '#/definitions/TicketWithTickets' security: - roles: - ticket:write @@ -6275,7 +6276,7 @@ paths: status: closed type: alert schema: - $ref: '#/definitions/TicketResponse' + $ref: '#/definitions/TicketWithTickets' security: - roles: - ticket:write @@ -6540,7 +6541,7 @@ paths: type: alert type: alert schema: - $ref: '#/definitions/TicketResponse' + $ref: '#/definitions/TicketWithTickets' security: - roles: - ticket:write diff --git a/generated/community.json b/generated/community.json index 3ff0129..f39ce70 100644 --- a/generated/community.json +++ b/generated/community.json @@ -563,10 +563,7 @@ "content" : { "application/json" : { "schema" : { - "items" : { - "$ref" : "#/components/schemas/PlaybookTemplateResponse" - }, - "type" : "array" + "$ref" : "#/components/schemas/PlaybookTemplateResponse" } }, "test" : { @@ -815,7 +812,7 @@ "application/json" : { "schema" : { "items" : { - "$ref" : "#/components/schemas/TaskResponse" + "$ref" : "#/components/schemas/TaskWithContext" }, "type" : "array" } @@ -1375,7 +1372,7 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/TicketResponse" + "$ref" : "#/components/schemas/TicketWithTickets" } }, "test" : { @@ -1459,7 +1456,7 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/TicketResponse" + "$ref" : "#/components/schemas/TicketWithTickets" } }, "test" : { @@ -1546,7 +1543,7 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/TicketResponse" + "$ref" : "#/components/schemas/TicketWithTickets" } }, "test" : { @@ -1757,7 +1754,7 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/TicketResponse" + "$ref" : "#/components/schemas/TicketWithTickets" } }, "test" : { @@ -2013,7 +2010,7 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/TicketResponse" + "$ref" : "#/components/schemas/TicketWithTickets" } }, "test" : { @@ -2230,7 +2227,7 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/Artifact" + "$ref" : "#/components/schemas/TicketWithTickets" } }, "test" : { @@ -2492,7 +2489,7 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/TicketResponse" + "$ref" : "#/components/schemas/TicketWithTickets" } }, "test" : { @@ -2583,7 +2580,7 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/TicketResponse" + "$ref" : "#/components/schemas/TicketWithTickets" } }, "test" : { @@ -2796,7 +2793,7 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/TicketResponse" + "$ref" : "#/components/schemas/TicketWithTickets" } }, "test" : { @@ -2887,7 +2884,7 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/TicketResponse" + "$ref" : "#/components/schemas/TicketWithTickets" } }, "test" : { @@ -2988,6 +2985,9 @@ "description" : "successful operation" } }, + "security" : [ { + "roles" : [ "ticket:write" ] + } ], "summary" : "Add a new ticket playbook", "tags" : [ "tickets" ], "x-codegen-request-body-name" : "playbook" @@ -3021,7 +3021,7 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/TicketResponse" + "$ref" : "#/components/schemas/TicketWithTickets" } }, "test" : { @@ -3115,7 +3115,7 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/TicketResponse" + "$ref" : "#/components/schemas/TicketWithTickets" } }, "test" : { @@ -3346,7 +3346,7 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/TicketResponse" + "$ref" : "#/components/schemas/TicketWithTickets" } }, "test" : { @@ -3608,7 +3608,7 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/TicketResponse" + "$ref" : "#/components/schemas/TicketWithTickets" } }, "test" : { @@ -3682,14 +3682,14 @@ } }, "description" : "New ticket schema", - "required" : false + "required" : true }, "responses" : { "200" : { "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/TicketResponse" + "$ref" : "#/components/schemas/TicketWithTickets" } }, "test" : { @@ -3777,7 +3777,7 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/TicketResponse" + "$ref" : "#/components/schemas/TicketWithTickets" } }, "test" : { @@ -3843,7 +3843,7 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/TicketResponse" + "$ref" : "#/components/schemas/TicketWithTickets" } }, "test" : { @@ -4920,7 +4920,6 @@ "$ref" : "#/components/schemas/Context" }, "payload" : { - "properties" : { }, "type" : "object" }, "secrets" : { diff --git a/generated/community.yml b/generated/community.yml index 091956b..1835681 100644 --- a/generated/community.yml +++ b/generated/community.yml @@ -260,8 +260,7 @@ definitions: properties: context: $ref: '#/definitions/Context' - payload: - type: object + payload: {} secrets: additionalProperties: type: string @@ -1980,9 +1979,7 @@ paths: name: Escalate to malware team type: task schema: - items: - $ref: '#/definitions/PlaybookTemplateResponse' - type: array + $ref: '#/definitions/PlaybookTemplateResponse' security: - roles: - playbook:write @@ -2275,7 +2272,7 @@ paths: test: [] schema: items: - $ref: '#/definitions/TaskResponse' + $ref: '#/definitions/TaskWithContext' type: array security: - roles: @@ -3314,7 +3311,7 @@ paths: type: alert type: alert schema: - $ref: '#/definitions/TicketResponse' + $ref: '#/definitions/TicketWithTickets' security: - roles: - ticket:read @@ -3389,7 +3386,7 @@ paths: type: alert type: alert schema: - $ref: '#/definitions/TicketResponse' + $ref: '#/definitions/TicketWithTickets' security: - roles: - ticket:write @@ -3641,7 +3638,7 @@ paths: status: closed type: incident schema: - $ref: '#/definitions/TicketResponse' + $ref: '#/definitions/TicketWithTickets' security: - roles: - ticket:write @@ -3885,7 +3882,7 @@ paths: status: closed type: incident schema: - $ref: '#/definitions/TicketResponse' + $ref: '#/definitions/TicketWithTickets' security: - roles: - ticket:write @@ -4168,7 +4165,7 @@ paths: status: closed type: incident schema: - $ref: '#/definitions/TicketResponse' + $ref: '#/definitions/TicketWithTickets' security: - roles: - ticket:write @@ -4429,7 +4426,7 @@ paths: status: closed type: incident schema: - $ref: '#/definitions/Artifact' + $ref: '#/definitions/TicketWithTickets' security: - roles: - ticket:write @@ -4526,7 +4523,7 @@ paths: type: alert type: alert schema: - $ref: '#/definitions/TicketResponse' + $ref: '#/definitions/TicketWithTickets' security: - roles: - ticket:write @@ -4774,7 +4771,7 @@ paths: status: closed type: incident schema: - $ref: '#/definitions/TicketResponse' + $ref: '#/definitions/TicketWithTickets' security: - roles: - ticket:write @@ -4845,7 +4842,7 @@ paths: type: alert type: alert schema: - $ref: '#/definitions/TicketResponse' + $ref: '#/definitions/TicketWithTickets' security: - roles: - ticket:write @@ -4976,7 +4973,10 @@ paths: type: alert type: alert schema: - $ref: '#/definitions/TicketResponse' + $ref: '#/definitions/TicketWithTickets' + security: + - roles: + - ticket:write summary: Add a new ticket playbook tags: - tickets @@ -5115,7 +5115,7 @@ paths: status: closed type: incident schema: - $ref: '#/definitions/TicketResponse' + $ref: '#/definitions/TicketWithTickets' security: - roles: - ticket:write @@ -5397,7 +5397,7 @@ paths: status: closed type: incident schema: - $ref: '#/definitions/TicketResponse' + $ref: '#/definitions/TicketWithTickets' security: - roles: - ticket:write @@ -5661,7 +5661,7 @@ paths: status: closed type: incident schema: - $ref: '#/definitions/TicketResponse' + $ref: '#/definitions/TicketWithTickets' security: - roles: - ticket:write @@ -5755,7 +5755,7 @@ paths: type: alert type: alert schema: - $ref: '#/definitions/TicketResponse' + $ref: '#/definitions/TicketWithTickets' security: - roles: - ticket:write @@ -5776,6 +5776,7 @@ paths: - description: New ticket schema in: body name: schema + required: true schema: type: string x-example: '{}' @@ -5816,7 +5817,7 @@ paths: type: alert type: alert schema: - $ref: '#/definitions/TicketResponse' + $ref: '#/definitions/TicketWithTickets' security: - roles: - ticket:write @@ -5863,7 +5864,7 @@ paths: status: closed type: alert schema: - $ref: '#/definitions/TicketResponse' + $ref: '#/definitions/TicketWithTickets' security: - roles: - ticket:write @@ -6128,7 +6129,7 @@ paths: type: alert type: alert schema: - $ref: '#/definitions/TicketResponse' + $ref: '#/definitions/TicketWithTickets' security: - roles: - ticket:write diff --git a/generated/models/models.go b/generated/model/model.go similarity index 86% rename from generated/models/models.go rename to generated/model/model.go index a24788f..c875652 100755 --- a/generated/models/models.go +++ b/generated/model/model.go @@ -1,4 +1,4 @@ -package models +package model import ( "fmt" @@ -78,7 +78,7 @@ func init() { gojsonschema.NewStringLoader(`{"type":"object","required":["automation"],"x-embed":"","properties":{"automation":{"type":"string"},"origin":{"$ref":"#/definitions/Origin"},"payload":{}},"$id":"#/definitions/JobForm"}`), gojsonschema.NewStringLoader(`{"type":"object","required":["id","automation","status"],"x-embed":"","properties":{"automation":{"type":"string"},"container":{"type":"string"},"id":{"type":"string"},"log":{"type":"string"},"origin":{"$ref":"#/definitions/Origin"},"output":{"type":"object"},"payload":{},"status":{"type":"string"}},"$id":"#/definitions/JobResponse"}`), gojsonschema.NewStringLoader(`{"type":"object","required":["type","reference","creator","created","message"],"x-embed":"","properties":{"created":{"format":"date-time","type":"string"},"creator":{"type":"string"},"message":{"type":"string"},"reference":{"type":"string"},"type":{"type":"string"}},"$id":"#/definitions/LogEntry"}`), - gojsonschema.NewStringLoader(`{"type":"object","x-embed":"","properties":{"context":{"$ref":"#/definitions/Context"},"payload":{"type":"object"},"secrets":{"type":"object","additionalProperties":{"type":"string"}}},"$id":"#/definitions/Message"}`), + gojsonschema.NewStringLoader(`{"type":"object","x-embed":"","properties":{"context":{"$ref":"#/definitions/Context"},"payload":{},"secrets":{"type":"object","additionalProperties":{"type":"string"}}},"$id":"#/definitions/Message"}`), gojsonschema.NewStringLoader(`{"type":"object","required":["id","blocked","roles"],"x-embed":"","properties":{"blocked":{"type":"boolean"},"id":{"type":"string"},"roles":{"items":{"type":"string"},"type":"array"},"secret":{"type":"string"}},"$id":"#/definitions/NewUserResponse"}`), gojsonschema.NewStringLoader(`{"type":"object","x-embed":"","properties":{"artifact_origin":{"$ref":"#/definitions/ArtifactOrigin"},"task_origin":{"$ref":"#/definitions/TaskOrigin"}},"$id":"#/definitions/Origin"}`), gojsonschema.NewStringLoader(`{"type":"object","required":["name","tasks"],"x-embed":"","properties":{"name":{"type":"string"},"tasks":{"type":"object","additionalProperties":{"$ref":"#/definitions/Task"}}},"$id":"#/definitions/Playbook"}`), @@ -223,14 +223,14 @@ type Context struct { } type Enrichment struct { - Created time.Time `json:"created"` - Data interface{} `json:"data"` - Name string `json:"name"` + Created time.Time `json:"created"` + Data map[string]interface{} `json:"data"` + Name string `json:"name"` } type EnrichmentForm struct { - Data interface{} `json:"data"` - Name string `json:"name"` + Data map[string]interface{} `json:"data"` + Name string `json:"name"` } type File struct { @@ -239,14 +239,14 @@ type File struct { } type Job struct { - Automation string `json:"automation"` - Container *string `json:"container,omitempty"` - Log *string `json:"log,omitempty"` - Origin *Origin `json:"origin,omitempty"` - Output interface{} `json:"output,omitempty"` - Payload interface{} `json:"payload,omitempty"` - Running bool `json:"running"` - Status string `json:"status"` + Automation string `json:"automation"` + Container *string `json:"container,omitempty"` + Log *string `json:"log,omitempty"` + Origin *Origin `json:"origin,omitempty"` + Output map[string]interface{} `json:"output,omitempty"` + Payload interface{} `json:"payload,omitempty"` + Running bool `json:"running"` + Status string `json:"status"` } type JobForm struct { @@ -256,14 +256,14 @@ type JobForm struct { } type JobResponse struct { - Automation string `json:"automation"` - Container *string `json:"container,omitempty"` - ID string `json:"id"` - Log *string `json:"log,omitempty"` - Origin *Origin `json:"origin,omitempty"` - Output interface{} `json:"output,omitempty"` - Payload interface{} `json:"payload,omitempty"` - Status string `json:"status"` + Automation string `json:"automation"` + Container *string `json:"container,omitempty"` + ID string `json:"id"` + Log *string `json:"log,omitempty"` + Origin *Origin `json:"origin,omitempty"` + Output map[string]interface{} `json:"output,omitempty"` + Payload interface{} `json:"payload,omitempty"` + Status string `json:"status"` } type LogEntry struct { @@ -340,33 +340,33 @@ type Statistics struct { } type Task struct { - Automation *string `json:"automation,omitempty"` - Closed *time.Time `json:"closed,omitempty"` - Created time.Time `json:"created"` - Data interface{} `json:"data,omitempty"` - Done bool `json:"done"` - Join *bool `json:"join,omitempty"` - Name string `json:"name"` - Next map[string]string `json:"next,omitempty"` - Owner *string `json:"owner,omitempty"` - Payload map[string]string `json:"payload,omitempty"` - Schema interface{} `json:"schema,omitempty"` - Type string `json:"type"` + Automation *string `json:"automation,omitempty"` + Closed *time.Time `json:"closed,omitempty"` + Created time.Time `json:"created"` + Data map[string]interface{} `json:"data,omitempty"` + Done bool `json:"done"` + Join *bool `json:"join,omitempty"` + Name string `json:"name"` + Next map[string]string `json:"next,omitempty"` + Owner *string `json:"owner,omitempty"` + Payload map[string]string `json:"payload,omitempty"` + Schema map[string]interface{} `json:"schema,omitempty"` + Type string `json:"type"` } type TaskForm struct { - Automation *string `json:"automation,omitempty"` - Closed *time.Time `json:"closed,omitempty"` - Created *time.Time `json:"created,omitempty"` - Data interface{} `json:"data,omitempty"` - Done *bool `json:"done,omitempty"` - Join *bool `json:"join,omitempty"` - Name string `json:"name"` - Next map[string]string `json:"next,omitempty"` - Owner *string `json:"owner,omitempty"` - Payload map[string]string `json:"payload,omitempty"` - Schema interface{} `json:"schema,omitempty"` - Type string `json:"type"` + Automation *string `json:"automation,omitempty"` + Closed *time.Time `json:"closed,omitempty"` + Created *time.Time `json:"created,omitempty"` + Data map[string]interface{} `json:"data,omitempty"` + Done *bool `json:"done,omitempty"` + Join *bool `json:"join,omitempty"` + Name string `json:"name"` + Next map[string]string `json:"next,omitempty"` + Owner *string `json:"owner,omitempty"` + Payload map[string]string `json:"payload,omitempty"` + Schema map[string]interface{} `json:"schema,omitempty"` + Type string `json:"type"` } type TaskOrigin struct { @@ -376,54 +376,54 @@ type TaskOrigin struct { } type TaskResponse struct { - Active bool `json:"active"` - Automation *string `json:"automation,omitempty"` - Closed *time.Time `json:"closed,omitempty"` - Created time.Time `json:"created"` - Data interface{} `json:"data,omitempty"` - Done bool `json:"done"` - Join *bool `json:"join,omitempty"` - Name string `json:"name"` - Next map[string]string `json:"next,omitempty"` - Order int64 `json:"order"` - Owner *string `json:"owner,omitempty"` - Payload map[string]string `json:"payload,omitempty"` - Schema interface{} `json:"schema,omitempty"` - Type string `json:"type"` + Active bool `json:"active"` + Automation *string `json:"automation,omitempty"` + Closed *time.Time `json:"closed,omitempty"` + Created time.Time `json:"created"` + Data map[string]interface{} `json:"data,omitempty"` + Done bool `json:"done"` + Join *bool `json:"join,omitempty"` + Name string `json:"name"` + Next map[string]string `json:"next,omitempty"` + Order int64 `json:"order"` + Owner *string `json:"owner,omitempty"` + Payload map[string]string `json:"payload,omitempty"` + Schema map[string]interface{} `json:"schema,omitempty"` + Type string `json:"type"` } type TaskWithContext struct { - PlaybookId string `json:"playbook_id"` - PlaybookName string `json:"playbook_name"` - Task TaskResponse `json:"task"` - TaskId string `json:"task_id"` - TicketId int64 `json:"ticket_id"` - TicketName string `json:"ticket_name"` + PlaybookId string `json:"playbook_id"` + PlaybookName string `json:"playbook_name"` + Task *TaskResponse `json:"task"` + TaskId string `json:"task_id"` + TicketId int64 `json:"ticket_id"` + TicketName string `json:"ticket_name"` } type Ticket struct { - Artifacts []*Artifact `json:"artifacts,omitempty"` - Comments []*Comment `json:"comments,omitempty"` - Created time.Time `json:"created"` - Details interface{} `json:"details,omitempty"` - Files []*File `json:"files,omitempty"` - Modified time.Time `json:"modified"` - Name string `json:"name"` - Owner *string `json:"owner,omitempty"` - Playbooks map[string]*Playbook `json:"playbooks,omitempty"` - Read []string `json:"read,omitempty"` - References []*Reference `json:"references,omitempty"` - Schema string `json:"schema"` - Status string `json:"status"` - Type string `json:"type"` - Write []string `json:"write,omitempty"` + Artifacts []*Artifact `json:"artifacts,omitempty"` + Comments []*Comment `json:"comments,omitempty"` + Created time.Time `json:"created"` + Details map[string]interface{} `json:"details,omitempty"` + Files []*File `json:"files,omitempty"` + Modified time.Time `json:"modified"` + Name string `json:"name"` + Owner *string `json:"owner,omitempty"` + Playbooks map[string]*Playbook `json:"playbooks,omitempty"` + Read []string `json:"read,omitempty"` + References []*Reference `json:"references,omitempty"` + Schema string `json:"schema"` + Status string `json:"status"` + Type string `json:"type"` + Write []string `json:"write,omitempty"` } type TicketForm struct { Artifacts []*Artifact `json:"artifacts,omitempty"` Comments []*Comment `json:"comments,omitempty"` Created *time.Time `json:"created,omitempty"` - Details interface{} `json:"details,omitempty"` + Details map[string]interface{} `json:"details,omitempty"` Files []*File `json:"files,omitempty"` ID *int64 `json:"id,omitempty"` Modified *time.Time `json:"modified,omitempty"` @@ -447,7 +447,7 @@ type TicketResponse struct { Artifacts []*Artifact `json:"artifacts,omitempty"` Comments []*Comment `json:"comments,omitempty"` Created time.Time `json:"created"` - Details interface{} `json:"details,omitempty"` + Details map[string]interface{} `json:"details,omitempty"` Files []*File `json:"files,omitempty"` ID int64 `json:"id"` Modified time.Time `json:"modified"` @@ -463,22 +463,22 @@ type TicketResponse struct { } type TicketSimpleResponse struct { - Artifacts []*Artifact `json:"artifacts,omitempty"` - Comments []*Comment `json:"comments,omitempty"` - Created time.Time `json:"created"` - Details interface{} `json:"details,omitempty"` - Files []*File `json:"files,omitempty"` - ID int64 `json:"id"` - Modified time.Time `json:"modified"` - Name string `json:"name"` - Owner *string `json:"owner,omitempty"` - Playbooks map[string]*Playbook `json:"playbooks,omitempty"` - Read []string `json:"read,omitempty"` - References []*Reference `json:"references,omitempty"` - Schema string `json:"schema"` - Status string `json:"status"` - Type string `json:"type"` - Write []string `json:"write,omitempty"` + Artifacts []*Artifact `json:"artifacts,omitempty"` + Comments []*Comment `json:"comments,omitempty"` + Created time.Time `json:"created"` + Details map[string]interface{} `json:"details,omitempty"` + Files []*File `json:"files,omitempty"` + ID int64 `json:"id"` + Modified time.Time `json:"modified"` + Name string `json:"name"` + Owner *string `json:"owner,omitempty"` + Playbooks map[string]*Playbook `json:"playbooks,omitempty"` + Read []string `json:"read,omitempty"` + References []*Reference `json:"references,omitempty"` + Schema string `json:"schema"` + Status string `json:"status"` + Type string `json:"type"` + Write []string `json:"write,omitempty"` } type TicketTemplate struct { @@ -528,7 +528,7 @@ type TicketWithTickets struct { Artifacts []*Artifact `json:"artifacts,omitempty"` Comments []*Comment `json:"comments,omitempty"` Created time.Time `json:"created"` - Details interface{} `json:"details,omitempty"` + Details map[string]interface{} `json:"details,omitempty"` Files []*File `json:"files,omitempty"` ID int64 `json:"id"` Logs []*LogEntry `json:"logs,omitempty"` diff --git a/generated/restapi/api.go b/generated/restapi/api.go deleted file mode 100644 index b56ed31..0000000 --- a/generated/restapi/api.go +++ /dev/null @@ -1,252 +0,0 @@ -package restapi - -import ( - "context" - "log" - "net/http" - "os" - "os/signal" - "syscall" - "time" - - "github.com/gin-gonic/gin" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" - "github.com/SecurityBrewery/catalyst/generated/restapi/operations/automations" - "github.com/SecurityBrewery/catalyst/generated/restapi/operations/jobs" - "github.com/SecurityBrewery/catalyst/generated/restapi/operations/logs" - "github.com/SecurityBrewery/catalyst/generated/restapi/operations/playbooks" - "github.com/SecurityBrewery/catalyst/generated/restapi/operations/settings" - "github.com/SecurityBrewery/catalyst/generated/restapi/operations/statistics" - "github.com/SecurityBrewery/catalyst/generated/restapi/operations/tasks" - "github.com/SecurityBrewery/catalyst/generated/restapi/operations/templates" - "github.com/SecurityBrewery/catalyst/generated/restapi/operations/tickets" - "github.com/SecurityBrewery/catalyst/generated/restapi/operations/tickettypes" - "github.com/SecurityBrewery/catalyst/generated/restapi/operations/userdata" - "github.com/SecurityBrewery/catalyst/generated/restapi/operations/users" - "github.com/SecurityBrewery/catalyst/role" -) - -// Service is the interface that must be implemented in order to provide -// business logic for the Server service. -type Service interface { - AddArtifact(ctx context.Context, params *tickets.AddArtifactParams) *api.Response - AddComment(ctx context.Context, params *tickets.AddCommentParams) *api.Response - AddTicketPlaybook(ctx context.Context, params *tickets.AddTicketPlaybookParams) *api.Response - CompleteTask(ctx context.Context, params *tickets.CompleteTaskParams) *api.Response - CreateAutomation(ctx context.Context, params *automations.CreateAutomationParams) *api.Response - CreatePlaybook(ctx context.Context, params *playbooks.CreatePlaybookParams) *api.Response - CreateTemplate(ctx context.Context, params *templates.CreateTemplateParams) *api.Response - CreateTicket(ctx context.Context, params *tickets.CreateTicketParams) *api.Response - CreateTicketBatch(ctx context.Context, params *tickets.CreateTicketBatchParams) *api.Response - CreateTicketType(ctx context.Context, params *tickettypes.CreateTicketTypeParams) *api.Response - CreateUser(ctx context.Context, params *users.CreateUserParams) *api.Response - CurrentUser(ctx context.Context) *api.Response - CurrentUserData(ctx context.Context) *api.Response - DeleteAutomation(ctx context.Context, params *automations.DeleteAutomationParams) *api.Response - DeletePlaybook(ctx context.Context, params *playbooks.DeletePlaybookParams) *api.Response - DeleteTemplate(ctx context.Context, params *templates.DeleteTemplateParams) *api.Response - DeleteTicket(ctx context.Context, params *tickets.DeleteTicketParams) *api.Response - DeleteTicketType(ctx context.Context, params *tickettypes.DeleteTicketTypeParams) *api.Response - DeleteUser(ctx context.Context, params *users.DeleteUserParams) *api.Response - EnrichArtifact(ctx context.Context, params *tickets.EnrichArtifactParams) *api.Response - GetArtifact(ctx context.Context, params *tickets.GetArtifactParams) *api.Response - GetAutomation(ctx context.Context, params *automations.GetAutomationParams) *api.Response - GetJob(ctx context.Context, params *jobs.GetJobParams) *api.Response - GetLogs(ctx context.Context, params *logs.GetLogsParams) *api.Response - GetPlaybook(ctx context.Context, params *playbooks.GetPlaybookParams) *api.Response - GetSettings(ctx context.Context) *api.Response - GetStatistics(ctx context.Context) *api.Response - GetTemplate(ctx context.Context, params *templates.GetTemplateParams) *api.Response - GetTicket(ctx context.Context, params *tickets.GetTicketParams) *api.Response - GetTicketType(ctx context.Context, params *tickettypes.GetTicketTypeParams) *api.Response - GetUser(ctx context.Context, params *users.GetUserParams) *api.Response - GetUserData(ctx context.Context, params *userdata.GetUserDataParams) *api.Response - LinkFiles(ctx context.Context, params *tickets.LinkFilesParams) *api.Response - LinkTicket(ctx context.Context, params *tickets.LinkTicketParams) *api.Response - ListAutomations(ctx context.Context) *api.Response - ListJobs(ctx context.Context) *api.Response - ListPlaybooks(ctx context.Context) *api.Response - ListTasks(ctx context.Context) *api.Response - ListTemplates(ctx context.Context) *api.Response - ListTicketTypes(ctx context.Context) *api.Response - ListTickets(ctx context.Context, params *tickets.ListTicketsParams) *api.Response - ListUserData(ctx context.Context) *api.Response - ListUsers(ctx context.Context) *api.Response - RemoveArtifact(ctx context.Context, params *tickets.RemoveArtifactParams) *api.Response - RemoveComment(ctx context.Context, params *tickets.RemoveCommentParams) *api.Response - RemoveTicketPlaybook(ctx context.Context, params *tickets.RemoveTicketPlaybookParams) *api.Response - RunArtifact(ctx context.Context, params *tickets.RunArtifactParams) *api.Response - RunJob(ctx context.Context, params *jobs.RunJobParams) *api.Response - RunTask(ctx context.Context, params *tickets.RunTaskParams) *api.Response - SetArtifact(ctx context.Context, params *tickets.SetArtifactParams) *api.Response - SetReferences(ctx context.Context, params *tickets.SetReferencesParams) *api.Response - SetSchema(ctx context.Context, params *tickets.SetSchemaParams) *api.Response - SetTask(ctx context.Context, params *tickets.SetTaskParams) *api.Response - UnlinkTicket(ctx context.Context, params *tickets.UnlinkTicketParams) *api.Response - UpdateAutomation(ctx context.Context, params *automations.UpdateAutomationParams) *api.Response - UpdateCurrentUserData(ctx context.Context, params *userdata.UpdateCurrentUserDataParams) *api.Response - UpdateJob(ctx context.Context, params *jobs.UpdateJobParams) *api.Response - UpdatePlaybook(ctx context.Context, params *playbooks.UpdatePlaybookParams) *api.Response - UpdateTemplate(ctx context.Context, params *templates.UpdateTemplateParams) *api.Response - UpdateTicket(ctx context.Context, params *tickets.UpdateTicketParams) *api.Response - UpdateTicketType(ctx context.Context, params *tickettypes.UpdateTicketTypeParams) *api.Response - UpdateUser(ctx context.Context, params *users.UpdateUserParams) *api.Response - UpdateUserData(ctx context.Context, params *userdata.UpdateUserDataParams) *api.Response -} - -// Config defines the config options for the API server. -type Config struct { - Address string - InsecureHTTP bool - TLSCertFile string - TLSKeyFile string -} - -// Server defines the Server service. -type Server struct { - *gin.Engine - config *Config - server *http.Server - service Service - - ApiGroup *gin.RouterGroup - - RoleAuth func([]role.Role) gin.HandlerFunc -} - -// New initializes a new Server service. -func New(svc Service, config *Config) *Server { - engine := gin.New() - engine.Use(gin.Recovery()) - - return &Server{ - Engine: engine, - service: svc, - config: config, - server: &http.Server{ - Addr: config.Address, - Handler: engine, - ReadTimeout: 10 * time.Second, - WriteTimeout: 10 * time.Second, - }, - - ApiGroup: engine.Group("/api"), - - RoleAuth: func(i []role.Role) gin.HandlerFunc { return func(c *gin.Context) { c.Next() } }, - } -} - -// ConfigureRoutes configures the routes for the Server service. -// Configuring of routes includes setting up Auth if it is enabled. -func (s *Server) ConfigureRoutes() { - s.ApiGroup.POST("/tickets/:id/artifacts", s.RoleAuth([]role.Role{role.TicketWrite}), tickets.AddArtifactEndpoint(s.service.AddArtifact)) - s.ApiGroup.POST("/tickets/:id/comments", s.RoleAuth([]role.Role{role.TicketWrite}), tickets.AddCommentEndpoint(s.service.AddComment)) - s.ApiGroup.POST("/tickets/:id/playbooks", s.RoleAuth([]role.Role{}), tickets.AddTicketPlaybookEndpoint(s.service.AddTicketPlaybook)) - s.ApiGroup.PUT("/tickets/:id/playbooks/:playbookID/task/:taskID/complete", s.RoleAuth([]role.Role{role.TicketWrite}), tickets.CompleteTaskEndpoint(s.service.CompleteTask)) - s.ApiGroup.POST("/automations", s.RoleAuth([]role.Role{role.AutomationWrite}), automations.CreateAutomationEndpoint(s.service.CreateAutomation)) - s.ApiGroup.POST("/playbooks", s.RoleAuth([]role.Role{role.PlaybookWrite}), playbooks.CreatePlaybookEndpoint(s.service.CreatePlaybook)) - s.ApiGroup.POST("/templates", s.RoleAuth([]role.Role{role.TemplateWrite}), templates.CreateTemplateEndpoint(s.service.CreateTemplate)) - s.ApiGroup.POST("/tickets", s.RoleAuth([]role.Role{role.TicketWrite}), tickets.CreateTicketEndpoint(s.service.CreateTicket)) - s.ApiGroup.POST("/tickets/batch", s.RoleAuth([]role.Role{role.TicketWrite}), tickets.CreateTicketBatchEndpoint(s.service.CreateTicketBatch)) - s.ApiGroup.POST("/tickettypes", s.RoleAuth([]role.Role{role.TickettypeWrite}), tickettypes.CreateTicketTypeEndpoint(s.service.CreateTicketType)) - s.ApiGroup.POST("/users", s.RoleAuth([]role.Role{role.UserWrite}), users.CreateUserEndpoint(s.service.CreateUser)) - s.ApiGroup.GET("/currentuser", s.RoleAuth([]role.Role{role.CurrentuserRead}), users.CurrentUserEndpoint(s.service.CurrentUser)) - s.ApiGroup.GET("/currentuserdata", s.RoleAuth([]role.Role{role.CurrentuserdataRead}), userdata.CurrentUserDataEndpoint(s.service.CurrentUserData)) - s.ApiGroup.DELETE("/automations/:id", s.RoleAuth([]role.Role{role.AutomationWrite}), automations.DeleteAutomationEndpoint(s.service.DeleteAutomation)) - s.ApiGroup.DELETE("/playbooks/:id", s.RoleAuth([]role.Role{role.PlaybookWrite}), playbooks.DeletePlaybookEndpoint(s.service.DeletePlaybook)) - s.ApiGroup.DELETE("/templates/:id", s.RoleAuth([]role.Role{role.TemplateWrite}), templates.DeleteTemplateEndpoint(s.service.DeleteTemplate)) - s.ApiGroup.DELETE("/tickets/:id", s.RoleAuth([]role.Role{role.TicketDelete}), tickets.DeleteTicketEndpoint(s.service.DeleteTicket)) - s.ApiGroup.DELETE("/tickettypes/:id", s.RoleAuth([]role.Role{role.TickettypeWrite}), tickettypes.DeleteTicketTypeEndpoint(s.service.DeleteTicketType)) - s.ApiGroup.DELETE("/users/:id", s.RoleAuth([]role.Role{role.UserWrite}), users.DeleteUserEndpoint(s.service.DeleteUser)) - s.ApiGroup.POST("/tickets/:id/artifacts/:name/enrich", s.RoleAuth([]role.Role{role.TicketWrite}), tickets.EnrichArtifactEndpoint(s.service.EnrichArtifact)) - s.ApiGroup.GET("/tickets/:id/artifacts/:name", s.RoleAuth([]role.Role{role.TicketWrite}), tickets.GetArtifactEndpoint(s.service.GetArtifact)) - s.ApiGroup.GET("/automations/:id", s.RoleAuth([]role.Role{role.AutomationRead}), automations.GetAutomationEndpoint(s.service.GetAutomation)) - s.ApiGroup.GET("/jobs/:id", s.RoleAuth([]role.Role{role.JobRead}), jobs.GetJobEndpoint(s.service.GetJob)) - s.ApiGroup.GET("/logs/:reference", s.RoleAuth([]role.Role{role.LogRead}), logs.GetLogsEndpoint(s.service.GetLogs)) - s.ApiGroup.GET("/playbooks/:id", s.RoleAuth([]role.Role{role.PlaybookRead}), playbooks.GetPlaybookEndpoint(s.service.GetPlaybook)) - s.ApiGroup.GET("/settings", s.RoleAuth([]role.Role{role.SettingsRead}), settings.GetSettingsEndpoint(s.service.GetSettings)) - s.ApiGroup.GET("/statistics", s.RoleAuth([]role.Role{role.TicketRead}), statistics.GetStatisticsEndpoint(s.service.GetStatistics)) - s.ApiGroup.GET("/templates/:id", s.RoleAuth([]role.Role{role.TemplateRead}), templates.GetTemplateEndpoint(s.service.GetTemplate)) - s.ApiGroup.GET("/tickets/:id", s.RoleAuth([]role.Role{role.TicketRead}), tickets.GetTicketEndpoint(s.service.GetTicket)) - s.ApiGroup.GET("/tickettypes/:id", s.RoleAuth([]role.Role{role.TickettypeRead}), tickettypes.GetTicketTypeEndpoint(s.service.GetTicketType)) - s.ApiGroup.GET("/users/:id", s.RoleAuth([]role.Role{role.UserRead}), users.GetUserEndpoint(s.service.GetUser)) - s.ApiGroup.GET("/userdata/:id", s.RoleAuth([]role.Role{role.UserdataRead}), userdata.GetUserDataEndpoint(s.service.GetUserData)) - s.ApiGroup.PUT("/tickets/:id/files", s.RoleAuth([]role.Role{role.TicketWrite}), tickets.LinkFilesEndpoint(s.service.LinkFiles)) - s.ApiGroup.PATCH("/tickets/:id/tickets", s.RoleAuth([]role.Role{role.TicketWrite}), tickets.LinkTicketEndpoint(s.service.LinkTicket)) - s.ApiGroup.GET("/automations", s.RoleAuth([]role.Role{role.AutomationRead}), automations.ListAutomationsEndpoint(s.service.ListAutomations)) - s.ApiGroup.GET("/jobs", s.RoleAuth([]role.Role{role.JobRead}), jobs.ListJobsEndpoint(s.service.ListJobs)) - s.ApiGroup.GET("/playbooks", s.RoleAuth([]role.Role{role.PlaybookRead}), playbooks.ListPlaybooksEndpoint(s.service.ListPlaybooks)) - s.ApiGroup.GET("/tasks", s.RoleAuth([]role.Role{role.TicketRead}), tasks.ListTasksEndpoint(s.service.ListTasks)) - s.ApiGroup.GET("/templates", s.RoleAuth([]role.Role{role.TemplateRead}), templates.ListTemplatesEndpoint(s.service.ListTemplates)) - s.ApiGroup.GET("/tickettypes", s.RoleAuth([]role.Role{role.TickettypeRead}), tickettypes.ListTicketTypesEndpoint(s.service.ListTicketTypes)) - s.ApiGroup.GET("/tickets", s.RoleAuth([]role.Role{role.TicketRead}), tickets.ListTicketsEndpoint(s.service.ListTickets)) - s.ApiGroup.GET("/userdata", s.RoleAuth([]role.Role{role.UserdataRead}), userdata.ListUserDataEndpoint(s.service.ListUserData)) - s.ApiGroup.GET("/users", s.RoleAuth([]role.Role{role.UserRead}), users.ListUsersEndpoint(s.service.ListUsers)) - s.ApiGroup.DELETE("/tickets/:id/artifacts/:name", s.RoleAuth([]role.Role{role.TicketWrite}), tickets.RemoveArtifactEndpoint(s.service.RemoveArtifact)) - s.ApiGroup.DELETE("/tickets/:id/comments/:commentID", s.RoleAuth([]role.Role{role.TicketWrite}), tickets.RemoveCommentEndpoint(s.service.RemoveComment)) - s.ApiGroup.DELETE("/tickets/:id/playbooks/:playbookID", s.RoleAuth([]role.Role{role.TicketWrite}), tickets.RemoveTicketPlaybookEndpoint(s.service.RemoveTicketPlaybook)) - s.ApiGroup.POST("/tickets/:id/artifacts/:name/run/:automation", s.RoleAuth([]role.Role{role.TicketWrite}), tickets.RunArtifactEndpoint(s.service.RunArtifact)) - s.ApiGroup.POST("/jobs", s.RoleAuth([]role.Role{role.JobWrite}), jobs.RunJobEndpoint(s.service.RunJob)) - s.ApiGroup.POST("/tickets/:id/playbooks/:playbookID/task/:taskID/run", s.RoleAuth([]role.Role{role.TicketWrite}), tickets.RunTaskEndpoint(s.service.RunTask)) - s.ApiGroup.PUT("/tickets/:id/artifacts/:name", s.RoleAuth([]role.Role{role.TicketWrite}), tickets.SetArtifactEndpoint(s.service.SetArtifact)) - s.ApiGroup.PUT("/tickets/:id/references", s.RoleAuth([]role.Role{role.TicketWrite}), tickets.SetReferencesEndpoint(s.service.SetReferences)) - s.ApiGroup.PUT("/tickets/:id/schema", s.RoleAuth([]role.Role{role.TicketWrite}), tickets.SetSchemaEndpoint(s.service.SetSchema)) - s.ApiGroup.PUT("/tickets/:id/playbooks/:playbookID/task/:taskID", s.RoleAuth([]role.Role{role.TicketWrite}), tickets.SetTaskEndpoint(s.service.SetTask)) - s.ApiGroup.DELETE("/tickets/:id/tickets", s.RoleAuth([]role.Role{role.TicketWrite}), tickets.UnlinkTicketEndpoint(s.service.UnlinkTicket)) - s.ApiGroup.PUT("/automations/:id", s.RoleAuth([]role.Role{role.AutomationWrite}), automations.UpdateAutomationEndpoint(s.service.UpdateAutomation)) - s.ApiGroup.PUT("/currentuserdata", s.RoleAuth([]role.Role{role.CurrentuserdataWrite}), userdata.UpdateCurrentUserDataEndpoint(s.service.UpdateCurrentUserData)) - s.ApiGroup.PUT("/jobs/:id", s.RoleAuth([]role.Role{role.JobWrite}), jobs.UpdateJobEndpoint(s.service.UpdateJob)) - s.ApiGroup.PUT("/playbooks/:id", s.RoleAuth([]role.Role{role.PlaybookWrite}), playbooks.UpdatePlaybookEndpoint(s.service.UpdatePlaybook)) - s.ApiGroup.PUT("/templates/:id", s.RoleAuth([]role.Role{role.TemplateWrite}), templates.UpdateTemplateEndpoint(s.service.UpdateTemplate)) - s.ApiGroup.PUT("/tickets/:id", s.RoleAuth([]role.Role{role.TicketWrite}), tickets.UpdateTicketEndpoint(s.service.UpdateTicket)) - s.ApiGroup.PUT("/tickettypes/:id", s.RoleAuth([]role.Role{role.TickettypeWrite}), tickettypes.UpdateTicketTypeEndpoint(s.service.UpdateTicketType)) - s.ApiGroup.PUT("/users/:id", s.RoleAuth([]role.Role{role.UserWrite}), users.UpdateUserEndpoint(s.service.UpdateUser)) - s.ApiGroup.PUT("/userdata/:id", s.RoleAuth([]role.Role{role.UserdataWrite}), userdata.UpdateUserDataEndpoint(s.service.UpdateUserData)) -} - -// run the Server. It will listen on either HTTP or HTTPS depending on the -// config passed to NewServer. -func (s *Server) run() error { - log.Printf("Serving on address %s\n", s.server.Addr) - if s.config.InsecureHTTP { - return s.server.ListenAndServe() - } - return s.server.ListenAndServeTLS(s.config.TLSCertFile, s.config.TLSKeyFile) -} - -// Shutdown will gracefully shutdown the Server. -func (s *Server) Shutdown() error { - return s.server.Shutdown(context.Background()) -} - -// RunWithSigHandler runs the Server with SIGTERM handling automatically -// enabled. The server will listen for a SIGTERM signal and gracefully shutdown -// the web server. -// It's possible to optionally pass any number shutdown functions which will -// execute one by one after the webserver has been shutdown successfully. -func (s *Server) RunWithSigHandler(shutdown ...func() error) error { - sigCh := make(chan os.Signal, 1) - signal.Notify(sigCh, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM) - - go func() { - <-sigCh - s.Shutdown() - }() - - err := s.run() - if err != nil { - if err != http.ErrServerClosed { - return err - } - } - - for _, fn := range shutdown { - err := fn() - if err != nil { - return err - } - } - - return nil -} diff --git a/generated/restapi/api/response.go b/generated/restapi/api/response.go deleted file mode 100644 index a11347a..0000000 --- a/generated/restapi/api/response.go +++ /dev/null @@ -1,6 +0,0 @@ -package api - -type Response struct { - Code int - Body interface{} -} diff --git a/generated/restapi/embedded_spec.go b/generated/restapi/embedded_spec.go deleted file mode 100644 index be92fc3..0000000 --- a/generated/restapi/embedded_spec.go +++ /dev/null @@ -1,14098 +0,0 @@ -// Code generated by go-swagger; DO NOT EDIT. - -package restapi - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "encoding/json" -) - -var ( - // SwaggerJSON embedded version of the swagger document used at generation time - SwaggerJSON json.RawMessage - // FlatSwaggerJSON embedded flattened version of the swagger document used at generation time - FlatSwaggerJSON json.RawMessage -) - -func init() { - SwaggerJSON = json.RawMessage([]byte(`{ - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "schemes": [ - "http" - ], - "swagger": "2.0", - "info": { - "description": "API for the catalyst incident response platform." - }, - "host": ".", - "basePath": "/api", - "paths": { - "/automations": { - "get": { - "security": [ - { - "roles": [ - "automation:read" - ] - } - ], - "tags": [ - "automations" - ], - "summary": "List automations", - "operationId": "listAutomations", - "responses": { - "200": { - "description": "successful operation", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/AutomationResponse" - } - }, - "examples": { - "test": [ - { - "id": "comment", - "image": "docker.io/python:3", - "script": "", - "type": [ - "playbook" - ] - }, - { - "id": "hash.sha1", - "image": "docker.io/python:3", - "schema": "{\"title\":\"Input\",\"type\":\"object\",\"properties\":{\"default\":{\"type\":\"string\",\"title\":\"Value\"}},\"required\":[\"default\"]}", - "script": "", - "type": [ - "global", - "artifact", - "playbook" - ] - }, - { - "id": "thehive", - "image": "docker.io/python:3", - "schema": "{\"title\":\"TheHive credentials\",\"type\":\"object\",\"properties\":{\"thehiveurl\":{\"type\":\"string\",\"title\":\"TheHive URL (e.g. 'https://thehive.example.org')\"},\"thehivekey\":{\"type\":\"string\",\"title\":\"TheHive API Key\"},\"skip_files\":{\"type\":\"boolean\", \"default\": true, \"title\":\"Skip Files (much faster)\"},\"keep_ids\":{\"type\":\"boolean\", \"default\": true, \"title\":\"Keep IDs and overwrite existing IDs\"}},\"required\":[\"thehiveurl\", \"thehivekey\", \"skip_files\", \"keep_ids\"]}", - "script": "", - "type": [ - "global" - ] - }, - { - "id": "vt.hash", - "image": "docker.io/python:3", - "schema": "{\"title\":\"Input\",\"type\":\"object\",\"properties\":{\"default\":{\"type\":\"string\",\"title\":\"Value\"}},\"required\":[\"default\"]}", - "script": "", - "type": [ - "global", - "artifact", - "playbook" - ] - } - ] - } - } - } - }, - "post": { - "security": [ - { - "roles": [ - "automation:write" - ] - } - ], - "tags": [ - "automations" - ], - "summary": "Create a new automation", - "operationId": "createAutomation", - "parameters": [ - { - "x-example": { - "id": "hash-sha-256", - "image": "docker.io/python:3", - "script": "import sys\nimport json\nimport hashlib\n\n\ndef run(msg):\n sha256 = hashlib.sha256(msg['payload']['default'].encode('utf-8'))\n return {'hash': sha256.hexdigest()}\n\n\nprint(json.dumps(run(json.loads(sys.argv[1]))))\n", - "type": [ - "global" - ] - }, - "description": "New automation", - "name": "automation", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/AutomationForm" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/AutomationResponse" - }, - "examples": { - "test": { - "id": "hash-sha-256", - "image": "docker.io/python:3", - "script": "import sys\nimport json\nimport hashlib\n\n\ndef run(msg):\n sha256 = hashlib.sha256(msg['payload']['default'].encode('utf-8'))\n return {'hash': sha256.hexdigest()}\n\n\nprint(json.dumps(run(json.loads(sys.argv[1]))))\n", - "type": [ - "global" - ] - } - } - } - } - } - }, - "/automations/{id}": { - "get": { - "security": [ - { - "roles": [ - "automation:read" - ] - } - ], - "tags": [ - "automations" - ], - "summary": "Get a single automation", - "operationId": "getAutomation", - "parameters": [ - { - "type": "string", - "x-example": "hash.sha1", - "description": "Automation ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/AutomationResponse" - }, - "examples": { - "test": { - "id": "hash.sha1", - "image": "docker.io/python:3", - "schema": "{\"title\":\"Input\",\"type\":\"object\",\"properties\":{\"default\":{\"type\":\"string\",\"title\":\"Value\"}},\"required\":[\"default\"]}", - "script": "#!/usr/bin/env python\n\nimport sys\nimport json\nimport hashlib\n\n\ndef run(msg):\n sha1 = hashlib.sha1(msg['payload']['default'].encode('utf-8'))\n return {\"hash\": sha1.hexdigest()}\n\n\nprint(json.dumps(run(json.loads(sys.argv[1]))))\n", - "type": [ - "global", - "artifact", - "playbook" - ] - } - } - } - } - }, - "put": { - "security": [ - { - "roles": [ - "automation:write" - ] - } - ], - "tags": [ - "automations" - ], - "summary": "Update an existing automation", - "operationId": "updateAutomation", - "parameters": [ - { - "type": "string", - "x-example": "hash.sha1", - "description": "Automation ID", - "name": "id", - "in": "path", - "required": true - }, - { - "x-example": { - "id": "hash.sha1", - "image": "docker.io/python:3", - "script": "import sys\nimport json\nimport hashlib\n\n\ndef run(msg):\n sha1 = hashlib.sha1(msg['payload'].encode('utf-8'))\n return {'hash': sha1.hexdigest()}\n\n\nprint(json.dumps(run(json.loads(sys.argv[1]))))\n", - "type": [ - "global", - "artifact", - "playbook" - ] - }, - "description": "Automation object that needs to be added", - "name": "automation", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/AutomationForm" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/AutomationResponse" - }, - "examples": { - "test": { - "id": "hash.sha1", - "image": "docker.io/python:3", - "script": "import sys\nimport json\nimport hashlib\n\n\ndef run(msg):\n sha1 = hashlib.sha1(msg['payload'].encode('utf-8'))\n return {'hash': sha1.hexdigest()}\n\n\nprint(json.dumps(run(json.loads(sys.argv[1]))))\n", - "type": [ - "global", - "artifact", - "playbook" - ] - } - } - } - } - }, - "delete": { - "security": [ - { - "roles": [ - "automation:write" - ] - } - ], - "tags": [ - "automations" - ], - "summary": "Delete a automation", - "operationId": "deleteAutomation", - "parameters": [ - { - "type": "string", - "x-example": "hash.sha1", - "description": "Automation ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "204": { - "description": "successful operation" - } - } - } - }, - "/currentuser": { - "get": { - "security": [ - { - "roles": [ - "currentuser:read" - ] - } - ], - "tags": [ - "users" - ], - "summary": "Get current user", - "operationId": "currentUser", - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/UserResponse" - }, - "examples": { - "test": { - "apikey": false, - "blocked": false, - "id": "bob", - "roles": [ - "admin:backup:read", - "admin:backup:restore", - "admin:group:write", - "admin:job:read", - "admin:job:write", - "admin:log:read", - "admin:ticket:delete", - "admin:user:write", - "admin:userdata:read", - "admin:userdata:write", - "analyst:automation:read", - "analyst:currentsettings:write", - "analyst:currentuser:read", - "analyst:currentuserdata:read", - "analyst:file", - "analyst:group:read", - "analyst:playbook:read", - "analyst:rule:read", - "analyst:settings:read", - "analyst:template:read", - "analyst:ticket:read", - "analyst:ticket:write", - "analyst:tickettype:read", - "analyst:user:read", - "engineer:automation:write", - "engineer:playbook:write", - "engineer:rule:write", - "engineer:template:write", - "engineer:tickettype:write" - ] - } - } - } - } - } - }, - "/currentuserdata": { - "get": { - "security": [ - { - "roles": [ - "currentuserdata:read" - ] - } - ], - "tags": [ - "userdata" - ], - "summary": "Get current user data", - "operationId": "currentUserData", - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/UserDataResponse" - }, - "examples": { - "test": { - "email": "bob@example.org", - "id": "bob", - "name": "Bob Bad" - } - } - } - } - }, - "put": { - "security": [ - { - "roles": [ - "currentuserdata:write" - ] - } - ], - "tags": [ - "userdata" - ], - "summary": "Update current user data", - "operationId": "updateCurrentUserData", - "parameters": [ - { - "x-example": { - "email": "bob@example.org", - "name": "Bob Bad" - }, - "description": "User data object that needs to be added", - "name": "userdata", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/UserData" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/UserDataResponse" - }, - "examples": { - "test": { - "email": "bob@example.org", - "id": "bob", - "name": "Bob Bad" - } - } - } - } - } - }, - "/jobs": { - "get": { - "security": [ - { - "roles": [ - "job:read" - ] - } - ], - "tags": [ - "jobs" - ], - "summary": "List jobs", - "operationId": "listJobs", - "responses": { - "200": { - "description": "successful operation", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/JobResponse" - } - }, - "examples": { - "test": [ - { - "automation": "hash.sha1", - "id": "99cd67131b48", - "payload": "test", - "status": "created" - } - ] - } - } - } - }, - "post": { - "security": [ - { - "roles": [ - "job:write" - ] - } - ], - "tags": [ - "jobs" - ], - "summary": "Start a new job", - "operationId": "runJob", - "parameters": [ - { - "x-example": { - "automation": "hash.sha1", - "message": { - "payload": "test" - } - }, - "description": "New job", - "name": "job", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/JobForm" - } - } - ], - "responses": { - "204": { - "description": "successful operation" - } - } - } - }, - "/jobs/{id}": { - "get": { - "security": [ - { - "roles": [ - "job:read" - ] - } - ], - "tags": [ - "jobs" - ], - "summary": "Get a single job", - "operationId": "getJob", - "parameters": [ - { - "type": "string", - "x-example": "99cd67131b48", - "description": "Job ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/JobResponse" - }, - "examples": { - "test": { - "automation": "hash.sha1", - "id": "99cd67131b48", - "payload": "test", - "status": "created" - } - } - } - } - }, - "put": { - "security": [ - { - "roles": [ - "job:write" - ] - } - ], - "tags": [ - "jobs" - ], - "summary": "Update an existing job", - "operationId": "updateJob", - "parameters": [ - { - "type": "string", - "x-example": "99cd67131b48", - "description": "Job ID", - "name": "id", - "in": "path", - "required": true - }, - { - "x-example": { - "automation": "hash.sha1", - "id": "99cd67131b48", - "payload": "test", - "status": "failed" - }, - "description": "Job object that needs to be added", - "name": "job", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/Job" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/JobResponse" - }, - "examples": { - "test": { - "automation": "hash.sha1", - "id": "99cd67131b48", - "payload": "test", - "status": "failed" - } - } - } - } - } - }, - "/logs/{reference}": { - "get": { - "security": [ - { - "roles": [ - "log:read" - ] - } - ], - "tags": [ - "logs" - ], - "summary": "Get log entries", - "operationId": "getLogs", - "parameters": [ - { - "type": "string", - "x-example": "tickets%2F294511", - "description": "Reference", - "name": "reference", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/LogEntry" - } - }, - "examples": { - "test": [ - { - "created": "2021-12-12T12:12:12.000000012Z", - "creator": "bob", - "message": "Fail run account resist lend solve incident centre priority temperature. Cause change distribution examine location technique shape partner milk customer. Rail tea plate soil report cook railway interpretation breath action. Exercise dream accept park conclusion addition shoot assistance may answer. Gold writer link stop combine hear power name commitment operation. Determine lifespan support grow degree henry exclude detail set religion. Direct library policy convention chain retain discover ride walk student. Gather proposal select march aspect play noise avoid encourage employ. Assessment preserve transport combine wish influence income guess run stand. Charge limit crime ignore statement foundation study issue stop claim.", - "reference": "tickets/294511", - "type": "manual" - } - ] - } - } - } - } - }, - "/playbooks": { - "get": { - "security": [ - { - "roles": [ - "playbook:read" - ] - } - ], - "tags": [ - "playbooks" - ], - "summary": "List playbooks", - "operationId": "listPlaybooks", - "responses": { - "200": { - "description": "successful operation", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/PlaybookTemplateResponse" - } - }, - "examples": { - "test": [ - { - "id": "malware", - "name": "Malware", - "yaml": "name: Malware\ntasks:\n file-or-hash:\n name: Do you have the file or the hash?\n type: input\n schema:\n title: Malware\n type: object\n properties:\n file:\n type: string\n title: \"I have the\"\n enum: [ \"File\", \"Hash\" ]\n next:\n enter-hash: \"file == 'Hash'\"\n upload: \"file == 'File'\"\n\n enter-hash:\n name: Please enter the hash\n type: input\n schema:\n title: Malware\n type: object\n properties:\n hash:\n type: string\n title: Please enter the hash value\n minlength: 32\n next:\n virustotal: \"hash != ''\"\n\n upload:\n name: Upload the malware\n type: input\n schema:\n title: Malware\n type: object\n properties:\n malware:\n type: object\n x-display: file\n title: Please upload the malware\n next:\n hash: \"malware\"\n\n hash:\n name: Hash the malware\n type: automation\n automation: hash.sha1\n payload:\n default: \"playbook.tasks['upload'].data['malware']\"\n next:\n virustotal:\n\n virustotal:\n name: Send hash to VirusTotal\n type: automation\n automation: vt.hash\n args:\n hash: \"playbook.tasks['enter-hash'].data['hash'] || playbook.tasks['hash'].data['hash']\"\n # next:\n # known-malware: \"score \u003e 5\"\n # sandbox: \"score \u003c 6\" # unknown-malware\n" - }, - { - "id": "phishing", - "name": "Phishing", - "yaml": "name: Phishing\ntasks:\n board:\n name: Board Involvement?\n description: Is a board member involved?\n type: input\n schema:\n properties:\n boardInvolved:\n default: false\n title: A board member is involved.\n type: boolean\n required:\n - boardInvolved\n title: Board Involvement?\n type: object\n next:\n escalate: \"boardInvolved == true\"\n mail-available: \"boardInvolved == false\"\n\n escalate:\n name: Escalate to CISO\n description: Please escalate the task to the CISO\n type: task\n\n mail-available:\n name: Mail available\n type: input\n schema:\n oneOf:\n - properties:\n mail:\n title: Mail\n type: string\n x-display: textarea\n schemaKey:\n const: 'yes'\n type: string\n required:\n - mail\n title: 'Yes'\n - properties:\n schemaKey:\n const: 'no'\n type: string\n title: 'No'\n title: Mail available\n type: object\n next:\n block-sender: \"schemaKey == 'yes'\"\n extract-iocs: \"schemaKey == 'yes'\"\n search-email-gateway: \"schemaKey == 'no'\"\n\n search-email-gateway:\n name: Search email gateway\n description: Please search email-gateway for the phishing mail.\n type: task\n next:\n extract-iocs:\n\n block-sender:\n name: Block sender\n type: task\n next:\n extract-iocs:\n\n extract-iocs:\n name: Extract IOCs\n description: Please insert the IOCs\n type: input\n schema:\n properties:\n iocs:\n items:\n type: string\n title: IOCs\n type: array\n title: Extract IOCs\n type: object\n next:\n block-iocs:\n\n block-iocs:\n name: Block IOCs\n type: task\n" - }, - { - "id": "simple", - "name": "Simple", - "yaml": "name: Simple\ntasks:\n input:\n name: Enter something to hash\n type: input\n schema:\n title: Something\n type: object\n properties:\n something:\n type: string\n title: Something\n default: \"\"\n next:\n hash: \"something != ''\"\n\n hash:\n name: Hash the something\n type: automation\n automation: hash.sha1\n payload:\n default: \"playbook.tasks['input'].data['something']\"\n next:\n comment: \"hash != ''\"\n\n comment:\n name: Comment the hash\n type: automation\n automation: comment\n payload:\n default: \"playbook.tasks['hash'].data['hash']\"\n next:\n done: \"done\"\n\n done:\n name: You can close this case now\n type: task\n" - } - ] - } - } - } - }, - "post": { - "security": [ - { - "roles": [ - "playbook:write" - ] - } - ], - "tags": [ - "playbooks" - ], - "summary": "Create a playbook", - "operationId": "createPlaybook", - "parameters": [ - { - "x-example": { - "yaml": "name: Simple2\ntasks:\n input:\n name: Upload malware if possible\n type: input\n schema:\n title: Malware\n type: object\n properties:\n malware:\n type: string\n title: Select malware\n default: \"\"\n next:\n hash: \"malware != ''\"\n\n hash:\n name: Hash the malware\n type: automation\n automation: hash.sha1\n payload:\n default: \"playbook.tasks['input'].data['malware']\"\n next:\n escalate:\n\n escalate:\n name: Escalate to malware team\n type: task\n" - }, - "description": "New playbook", - "name": "playbook", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/PlaybookTemplateForm" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/PlaybookTemplateResponse" - } - }, - "examples": { - "test": { - "id": "simple-2", - "name": "Simple2", - "yaml": "name: Simple2\ntasks:\n input:\n name: Upload malware if possible\n type: input\n schema:\n title: Malware\n type: object\n properties:\n malware:\n type: string\n title: Select malware\n default: \"\"\n next:\n hash: \"malware != ''\"\n\n hash:\n name: Hash the malware\n type: automation\n automation: hash.sha1\n payload:\n default: \"playbook.tasks['input'].data['malware']\"\n next:\n escalate:\n\n escalate:\n name: Escalate to malware team\n type: task\n" - } - } - } - } - } - }, - "/playbooks/{id}": { - "get": { - "security": [ - { - "roles": [ - "playbook:read" - ] - } - ], - "tags": [ - "playbooks" - ], - "summary": "Get a single playbook", - "operationId": "getPlaybook", - "parameters": [ - { - "type": "string", - "x-example": "simple", - "description": "Playbook name", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/PlaybookTemplateResponse" - }, - "examples": { - "test": { - "id": "simple", - "name": "Simple", - "yaml": "name: Simple\ntasks:\n input:\n name: Enter something to hash\n type: input\n schema:\n title: Something\n type: object\n properties:\n something:\n type: string\n title: Something\n default: \"\"\n next:\n hash: \"something != ''\"\n\n hash:\n name: Hash the something\n type: automation\n automation: hash.sha1\n payload:\n default: \"playbook.tasks['input'].data['something']\"\n next:\n comment: \"hash != ''\"\n\n comment:\n name: Comment the hash\n type: automation\n automation: comment\n payload:\n default: \"playbook.tasks['hash'].data['hash']\"\n next:\n done: \"done\"\n\n done:\n name: You can close this case now\n type: task\n" - } - } - } - } - }, - "put": { - "security": [ - { - "roles": [ - "playbook:write" - ] - } - ], - "tags": [ - "playbooks" - ], - "summary": "Update an existing ticket playbook", - "operationId": "updatePlaybook", - "parameters": [ - { - "type": "string", - "x-example": "simple", - "description": "Playbook ID", - "name": "id", - "in": "path", - "required": true - }, - { - "x-example": { - "yaml": "name: Simple\ntasks:\n input:\n name: Upload malware if possible\n type: input\n schema:\n title: Malware\n type: object\n properties:\n malware:\n type: string\n title: Select malware\n default: \"\"\n next:\n hash: \"malware != ''\"\n\n hash:\n name: Hash the malware\n type: automation\n automation: hash.sha1\n payload:\n default: \"playbook.tasks['input'].data['malware']\"\n next:\n escalate:\n\n escalate:\n name: Escalate to malware team\n type: task\n" - }, - "description": "Updated playbook", - "name": "playbook", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/PlaybookTemplateForm" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/PlaybookTemplateResponse" - }, - "examples": { - "test": { - "id": "simple", - "name": "Simple", - "yaml": "name: Simple\ntasks:\n input:\n name: Upload malware if possible\n type: input\n schema:\n title: Malware\n type: object\n properties:\n malware:\n type: string\n title: Select malware\n default: \"\"\n next:\n hash: \"malware != ''\"\n\n hash:\n name: Hash the malware\n type: automation\n automation: hash.sha1\n payload:\n default: \"playbook.tasks['input'].data['malware']\"\n next:\n escalate:\n\n escalate:\n name: Escalate to malware team\n type: task\n" - } - } - } - } - }, - "delete": { - "security": [ - { - "roles": [ - "playbook:write" - ] - } - ], - "tags": [ - "playbooks" - ], - "summary": "Delete a playbook", - "operationId": "deletePlaybook", - "parameters": [ - { - "type": "string", - "x-example": "simple", - "description": "Playbook name", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "204": { - "description": "successful operation" - } - } - } - }, - "/settings": { - "get": { - "security": [ - { - "roles": [ - "settings:read" - ] - } - ], - "tags": [ - "settings" - ], - "summary": "Get settings", - "operationId": "getSettings", - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/Settings" - }, - "examples": { - "test": { - "artifactStates": [ - { - "color": "info", - "icon": "mdi-help-circle-outline", - "id": "unknown", - "name": "Unknown" - }, - { - "color": "error", - "icon": "mdi-skull", - "id": "malicious", - "name": "Malicious" - }, - { - "color": "success", - "icon": "mdi-check", - "id": "clean", - "name": "Clean" - } - ], - "roles": [ - "admin:backup:read", - "admin:backup:restore", - "admin:group:write", - "admin:job:read", - "admin:job:write", - "admin:log:read", - "admin:ticket:delete", - "admin:user:write", - "admin:userdata:read", - "admin:userdata:write", - "analyst:automation:read", - "analyst:currentsettings:write", - "analyst:currentuser:read", - "analyst:currentuserdata:read", - "analyst:file", - "analyst:group:read", - "analyst:playbook:read", - "analyst:rule:read", - "analyst:settings:read", - "analyst:template:read", - "analyst:ticket:read", - "analyst:ticket:write", - "analyst:tickettype:read", - "analyst:user:read", - "engineer:automation:write", - "engineer:playbook:write", - "engineer:rule:write", - "engineer:template:write", - "engineer:tickettype:write" - ], - "ticketTypes": [ - { - "default_playbooks": null, - "default_template": "default", - "icon": "mdi-alert", - "id": "alert", - "name": "Alerts" - }, - { - "default_playbooks": null, - "default_template": "default", - "icon": "mdi-radioactive", - "id": "incident", - "name": "Incidents" - }, - { - "default_playbooks": null, - "default_template": "default", - "icon": "mdi-fingerprint", - "id": "investigation", - "name": "Forensic Investigations" - }, - { - "default_playbooks": null, - "default_template": "default", - "icon": "mdi-target", - "id": "hunt", - "name": "Threat Hunting" - } - ], - "tier": "community", - "timeformat": "YYYY-MM-DDThh:mm:ss", - "version": "0.0.0-test" - } - } - } - } - } - }, - "/statistics": { - "get": { - "security": [ - { - "roles": [ - "ticket:read" - ] - } - ], - "tags": [ - "statistics" - ], - "summary": "Get statistics", - "operationId": "getStatistics", - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/Statistics" - }, - "examples": { - "test": { - "open_tickets_per_user": {}, - "tickets_per_type": { - "alert": 2, - "incident": 1 - }, - "tickets_per_week": { - "2021-39": 3 - }, - "unassigned": 0 - } - } - } - } - } - }, - "/tasks": { - "get": { - "security": [ - { - "roles": [ - "ticket:read" - ] - } - ], - "tags": [ - "tasks" - ], - "summary": "List tasks", - "operationId": "listTasks", - "responses": { - "200": { - "description": "successful operation", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/TaskResponse" - } - }, - "examples": { - "test": null - } - } - } - } - }, - "/templates": { - "get": { - "security": [ - { - "roles": [ - "template:read" - ] - } - ], - "tags": [ - "templates" - ], - "summary": "List templates", - "operationId": "listTemplates", - "responses": { - "200": { - "description": "successful operation", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/TicketTemplateResponse" - } - }, - "examples": { - "test": [ - { - "id": "default", - "name": "Default", - "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Default\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n" - } - ] - } - } - } - }, - "post": { - "security": [ - { - "roles": [ - "template:write" - ] - } - ], - "tags": [ - "templates" - ], - "summary": "Create a new template", - "operationId": "createTemplate", - "parameters": [ - { - "x-example": { - "name": "My Template", - "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n" - }, - "description": "New template", - "name": "template", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/TicketTemplateForm" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketTemplateResponse" - }, - "examples": { - "test": { - "id": "my-template", - "name": "My Template", - "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n" - } - } - } - } - } - }, - "/templates/{id}": { - "get": { - "security": [ - { - "roles": [ - "template:read" - ] - } - ], - "tags": [ - "templates" - ], - "summary": "Get a single template", - "operationId": "getTemplate", - "parameters": [ - { - "type": "string", - "x-example": "default", - "description": "Template ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketTemplateResponse" - }, - "examples": { - "test": { - "id": "default", - "name": "Default", - "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Default\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n" - } - } - } - } - }, - "put": { - "security": [ - { - "roles": [ - "template:write" - ] - } - ], - "tags": [ - "templates" - ], - "summary": "Update an existing template", - "operationId": "updateTemplate", - "parameters": [ - { - "type": "string", - "x-example": "default", - "description": "Template ID", - "name": "id", - "in": "path", - "required": true - }, - { - "x-example": { - "name": "My Template", - "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n" - }, - "description": "Template object that needs to be added", - "name": "template", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/TicketTemplateForm" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketTemplateResponse" - }, - "examples": { - "test": { - "id": "default", - "name": "My Template", - "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n" - } - } - } - } - }, - "delete": { - "security": [ - { - "roles": [ - "template:write" - ] - } - ], - "tags": [ - "templates" - ], - "summary": "Delete a template", - "operationId": "deleteTemplate", - "parameters": [ - { - "type": "string", - "x-example": "default", - "description": "Template ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "204": { - "description": "successful operation" - } - } - } - }, - "/tickets": { - "get": { - "security": [ - { - "roles": [ - "ticket:read" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "List tickets", - "operationId": "listTickets", - "parameters": [ - { - "type": "string", - "description": "Ticket Type", - "name": "type", - "in": "query" - }, - { - "type": "integer", - "default": 0, - "description": "Offset of the list", - "name": "offset", - "in": "query" - }, - { - "maximum": 100, - "type": "integer", - "default": 25, - "description": "Number of tickets", - "name": "count", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "description": "Sort columns", - "name": "sort", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "boolean" - }, - "description": "Sort descending", - "name": "desc", - "in": "query" - }, - { - "type": "string", - "description": "Search query", - "name": "query", - "in": "query" - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketList" - }, - "examples": { - "test": { - "count": 3, - "tickets": [ - { - "artifacts": [ - { - "name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", - "status": "unknown" - }, - { - "name": "http://www.customerviral.io/scalable/vertical/killer", - "status": "clean" - }, - { - "name": "leadreintermediate.io", - "status": "malicious" - } - ], - "created": "2021-10-02T16:04:59.078206Z", - "id": 8123, - "modified": "2021-10-02T16:04:59.078206Z", - "name": "live zebra", - "owner": "demo", - "playbooks": { - "phishing": { - "name": "Phishing", - "tasks": { - "block-iocs": { - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Block IOCs", - "type": "task" - }, - "block-sender": { - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Block sender", - "next": { - "extract-iocs": "" - }, - "type": "task" - }, - "board": { - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Board Involvement?", - "next": { - "escalate": "boardInvolved == true", - "mail-available": "boardInvolved == false" - }, - "schema": { - "properties": { - "boardInvolved": { - "default": false, - "title": "A board member is involved.", - "type": "boolean" - } - }, - "required": [ - "boardInvolved" - ], - "title": "Board Involvement?", - "type": "object" - }, - "type": "input" - }, - "escalate": { - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Escalate to CISO", - "type": "task" - }, - "extract-iocs": { - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Extract IOCs", - "next": { - "block-iocs": "" - }, - "schema": { - "properties": { - "iocs": { - "items": { - "type": "string" - }, - "title": "IOCs", - "type": "array" - } - }, - "title": "Extract IOCs", - "type": "object" - }, - "type": "input" - }, - "mail-available": { - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Mail available", - "next": { - "block-sender": "schemaKey == 'yes'", - "extract-iocs": "schemaKey == 'yes'", - "search-email-gateway": "schemaKey == 'no'" - }, - "schema": { - "oneOf": [ - { - "properties": { - "mail": { - "title": "Mail", - "type": "string", - "x-display": "textarea" - }, - "schemaKey": { - "const": "yes", - "type": "string" - } - }, - "required": [ - "mail" - ], - "title": "Yes" - }, - { - "properties": { - "schemaKey": { - "const": "no", - "type": "string" - } - }, - "title": "No" - } - ], - "title": "Mail available", - "type": "object" - }, - "type": "input" - }, - "search-email-gateway": { - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Search email gateway", - "next": { - "extract-iocs": "" - }, - "type": "task" - } - } - } - }, - "references": [ - { - "href": "https://www.leadmaximize.net/e-services/back-end", - "name": "performance" - }, - { - "href": "http://www.corporateinteractive.name/rich", - "name": "autumn" - }, - { - "href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", - "name": "suggest" - } - ], - "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", - "status": "closed", - "type": "incident" - }, - { - "created": "2021-10-02T16:04:59.078186Z", - "id": 8125, - "modified": "2021-10-02T16:04:59.078186Z", - "name": "phishing from selenafadel@von.com detected", - "owner": "demo", - "references": [ - { - "href": "https://www.seniorleading-edge.name/users/efficient", - "name": "recovery" - }, - { - "href": "http://www.dynamicseamless.com/clicks-and-mortar", - "name": "force" - }, - { - "href": "http://www.leadscalable.biz/envisioneer", - "name": "fund" - } - ], - "schema": "{}", - "status": "closed", - "type": "alert" - }, - { - "created": "2021-10-02T16:04:59.078186Z", - "id": 8126, - "modified": "2021-10-02T16:04:59.078186Z", - "name": "Surfaceintroduce virus detected", - "owner": "demo", - "references": [ - { - "href": "http://www.centralworld-class.io/synthesize", - "name": "university" - }, - { - "href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", - "name": "goal" - }, - { - "href": "http://www.chiefsyndicate.io/action-items", - "name": "unemployment" - } - ], - "schema": "{}", - "status": "closed", - "type": "alert" - } - ] - } - } - } - } - }, - "post": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Create a new ticket", - "operationId": "createTicket", - "parameters": [ - { - "x-example": { - "id": 123, - "name": "Wannacry infection", - "owner": "bob", - "status": "open", - "type": "incident" - }, - "description": "New ticket", - "name": "ticket", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/TicketForm" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketResponse" - }, - "examples": { - "test": { - "created": "2021-12-12T12:12:12.000000012Z", - "id": 123, - "modified": "2021-12-12T12:12:12.000000012Z", - "name": "Wannacry infection", - "owner": "bob", - "schema": "{}", - "status": "open", - "type": "incident" - } - } - } - } - } - }, - "/tickets/batch": { - "post": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Create a new tickets in batch", - "operationId": "createTicketBatch", - "parameters": [ - { - "x-example": [ - { - "id": 123, - "name": "Wannacry infection", - "owner": "bob", - "status": "open", - "type": "incident" - } - ], - "description": "New ticket", - "name": "ticket", - "in": "body", - "required": true, - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/TicketForm" - } - } - } - ], - "responses": { - "204": { - "description": "successful operation" - } - } - } - }, - "/tickets/{id}": { - "get": { - "security": [ - { - "roles": [ - "ticket:read" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Get a single ticket", - "operationId": "getTicket", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8125, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketResponse" - }, - "examples": { - "test": { - "created": "2021-10-02T16:04:59.078186Z", - "id": 8125, - "modified": "2021-10-02T16:04:59.078186Z", - "name": "phishing from selenafadel@von.com detected", - "owner": "demo", - "references": [ - { - "href": "https://www.seniorleading-edge.name/users/efficient", - "name": "recovery" - }, - { - "href": "http://www.dynamicseamless.com/clicks-and-mortar", - "name": "force" - }, - { - "href": "http://www.leadscalable.biz/envisioneer", - "name": "fund" - } - ], - "schema": "{}", - "status": "closed", - "tickets": [ - { - "created": "2021-10-02T16:04:59.078186Z", - "id": 8126, - "modified": "2021-10-02T16:04:59.078186Z", - "name": "Surfaceintroduce virus detected", - "owner": "demo", - "references": [ - { - "href": "http://www.centralworld-class.io/synthesize", - "name": "university" - }, - { - "href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", - "name": "goal" - }, - { - "href": "http://www.chiefsyndicate.io/action-items", - "name": "unemployment" - } - ], - "schema": "{}", - "status": "closed", - "type": "alert" - } - ], - "type": "alert" - } - } - } - } - }, - "put": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Update an existing ticket", - "operationId": "updateTicket", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8125, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "x-example": { - "created": "2021-12-12T12:12:12.000000012Z", - "modified": "2021-12-12T12:12:12.000000012Z", - "name": "phishing from selenafadel@von.org detected", - "owner": "demo", - "references": [ - { - "href": "https://www.seniorleading-edge.name/users/efficient", - "name": "recovery" - }, - { - "href": "http://www.dynamicseamless.com/clicks-and-mortar", - "name": "force" - }, - { - "href": "http://www.leadscalable.biz/envisioneer", - "name": "fund" - } - ], - "schema": "{}", - "status": "closed", - "type": "alert" - }, - "description": "Updated ticket", - "name": "ticket", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/Ticket" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketResponse" - }, - "examples": { - "test": { - "created": "2021-12-12T12:12:12.000000012Z", - "id": 8125, - "modified": "2021-12-12T12:12:12.000000012Z", - "name": "phishing from selenafadel@von.org detected", - "owner": "demo", - "references": [ - { - "href": "https://www.seniorleading-edge.name/users/efficient", - "name": "recovery" - }, - { - "href": "http://www.dynamicseamless.com/clicks-and-mortar", - "name": "force" - }, - { - "href": "http://www.leadscalable.biz/envisioneer", - "name": "fund" - } - ], - "schema": "{}", - "status": "closed", - "tickets": [ - { - "created": "2021-10-02T16:04:59.078186Z", - "id": 8126, - "modified": "2021-10-02T16:04:59.078186Z", - "name": "Surfaceintroduce virus detected", - "owner": "demo", - "references": [ - { - "href": "http://www.centralworld-class.io/synthesize", - "name": "university" - }, - { - "href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", - "name": "goal" - }, - { - "href": "http://www.chiefsyndicate.io/action-items", - "name": "unemployment" - } - ], - "schema": "{}", - "status": "closed", - "type": "alert" - } - ], - "type": "alert" - } - } - } - } - }, - "delete": { - "security": [ - { - "roles": [ - "ticket:delete" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Delete an ticket", - "operationId": "deleteTicket", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8125, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "204": { - "description": "successful operation" - } - } - } - }, - "/tickets/{id}/artifacts": { - "post": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Add a single artifact", - "operationId": "addArtifact", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8123, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "x-example": { - "name": "2.2.2.2" - }, - "description": "Artifact object that needs to be added", - "name": "artifact", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/Artifact" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketResponse" - }, - "examples": { - "test": { - "artifacts": [ - { - "name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", - "status": "unknown" - }, - { - "name": "http://www.customerviral.io/scalable/vertical/killer", - "status": "clean" - }, - { - "name": "leadreintermediate.io", - "status": "malicious" - }, - { - "name": "2.2.2.2", - "status": "unknown", - "type": "ip" - } - ], - "created": "2021-10-02T16:04:59.078206Z", - "id": 8123, - "modified": "2021-12-12T12:12:12.000000012Z", - "name": "live zebra", - "owner": "demo", - "playbooks": { - "phishing": { - "name": "Phishing", - "tasks": { - "block-iocs": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Block IOCs", - "order": 6, - "type": "task" - }, - "block-sender": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Block sender", - "next": { - "extract-iocs": "" - }, - "order": 3, - "type": "task" - }, - "board": { - "active": true, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Board Involvement?", - "next": { - "escalate": "boardInvolved == true", - "mail-available": "boardInvolved == false" - }, - "order": 0, - "schema": { - "properties": { - "boardInvolved": { - "default": false, - "title": "A board member is involved.", - "type": "boolean" - } - }, - "required": [ - "boardInvolved" - ], - "title": "Board Involvement?", - "type": "object" - }, - "type": "input" - }, - "escalate": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Escalate to CISO", - "order": 1, - "type": "task" - }, - "extract-iocs": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Extract IOCs", - "next": { - "block-iocs": "" - }, - "order": 5, - "schema": { - "properties": { - "iocs": { - "items": { - "type": "string" - }, - "title": "IOCs", - "type": "array" - } - }, - "title": "Extract IOCs", - "type": "object" - }, - "type": "input" - }, - "mail-available": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Mail available", - "next": { - "block-sender": "schemaKey == 'yes'", - "extract-iocs": "schemaKey == 'yes'", - "search-email-gateway": "schemaKey == 'no'" - }, - "order": 2, - "schema": { - "oneOf": [ - { - "properties": { - "mail": { - "title": "Mail", - "type": "string", - "x-display": "textarea" - }, - "schemaKey": { - "const": "yes", - "type": "string" - } - }, - "required": [ - "mail" - ], - "title": "Yes" - }, - { - "properties": { - "schemaKey": { - "const": "no", - "type": "string" - } - }, - "title": "No" - } - ], - "title": "Mail available", - "type": "object" - }, - "type": "input" - }, - "search-email-gateway": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Search email gateway", - "next": { - "extract-iocs": "" - }, - "order": 4, - "type": "task" - } - } - } - }, - "references": [ - { - "href": "https://www.leadmaximize.net/e-services/back-end", - "name": "performance" - }, - { - "href": "http://www.corporateinteractive.name/rich", - "name": "autumn" - }, - { - "href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", - "name": "suggest" - } - ], - "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", - "status": "closed", - "type": "incident" - } - } - } - } - } - }, - "/tickets/{id}/artifacts/{name}": { - "get": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Get a single artifact", - "operationId": "getArtifact", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8123, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "string", - "x-example": "leadreintermediate.io", - "name": "name", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/Artifact" - }, - "examples": { - "test": { - "name": "leadreintermediate.io", - "status": "malicious" - } - } - } - } - }, - "put": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Set a single artifact", - "operationId": "setArtifact", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8123, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "string", - "x-example": "leadreintermediate.io", - "name": "name", - "in": "path", - "required": true - }, - { - "x-example": { - "name": "leadreintermediate.io", - "status": "clean" - }, - "name": "artifact", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/Artifact" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketResponse" - }, - "examples": { - "test": { - "artifacts": [ - { - "name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", - "status": "unknown" - }, - { - "name": "http://www.customerviral.io/scalable/vertical/killer", - "status": "clean" - }, - { - "name": "leadreintermediate.io", - "status": "clean" - } - ], - "created": "2021-10-02T16:04:59.078206Z", - "id": 8123, - "modified": "2021-10-02T16:04:59.078206Z", - "name": "live zebra", - "owner": "demo", - "playbooks": { - "phishing": { - "name": "Phishing", - "tasks": { - "block-iocs": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Block IOCs", - "order": 6, - "type": "task" - }, - "block-sender": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Block sender", - "next": { - "extract-iocs": "" - }, - "order": 3, - "type": "task" - }, - "board": { - "active": true, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Board Involvement?", - "next": { - "escalate": "boardInvolved == true", - "mail-available": "boardInvolved == false" - }, - "order": 0, - "schema": { - "properties": { - "boardInvolved": { - "default": false, - "title": "A board member is involved.", - "type": "boolean" - } - }, - "required": [ - "boardInvolved" - ], - "title": "Board Involvement?", - "type": "object" - }, - "type": "input" - }, - "escalate": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Escalate to CISO", - "order": 1, - "type": "task" - }, - "extract-iocs": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Extract IOCs", - "next": { - "block-iocs": "" - }, - "order": 5, - "schema": { - "properties": { - "iocs": { - "items": { - "type": "string" - }, - "title": "IOCs", - "type": "array" - } - }, - "title": "Extract IOCs", - "type": "object" - }, - "type": "input" - }, - "mail-available": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Mail available", - "next": { - "block-sender": "schemaKey == 'yes'", - "extract-iocs": "schemaKey == 'yes'", - "search-email-gateway": "schemaKey == 'no'" - }, - "order": 2, - "schema": { - "oneOf": [ - { - "properties": { - "mail": { - "title": "Mail", - "type": "string", - "x-display": "textarea" - }, - "schemaKey": { - "const": "yes", - "type": "string" - } - }, - "required": [ - "mail" - ], - "title": "Yes" - }, - { - "properties": { - "schemaKey": { - "const": "no", - "type": "string" - } - }, - "title": "No" - } - ], - "title": "Mail available", - "type": "object" - }, - "type": "input" - }, - "search-email-gateway": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Search email gateway", - "next": { - "extract-iocs": "" - }, - "order": 4, - "type": "task" - } - } - } - }, - "references": [ - { - "href": "https://www.leadmaximize.net/e-services/back-end", - "name": "performance" - }, - { - "href": "http://www.corporateinteractive.name/rich", - "name": "autumn" - }, - { - "href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", - "name": "suggest" - } - ], - "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", - "status": "closed", - "type": "incident" - } - } - } - } - }, - "delete": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Remove an artifact", - "operationId": "removeArtifact", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8123, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "string", - "x-example": "leadreintermediate.io", - "name": "name", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketResponse" - }, - "examples": { - "test": { - "artifacts": [ - { - "name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", - "status": "unknown" - }, - { - "name": "http://www.customerviral.io/scalable/vertical/killer", - "status": "clean" - } - ], - "created": "2021-10-02T16:04:59.078206Z", - "id": 8123, - "modified": "2021-12-12T12:12:12.000000012Z", - "name": "live zebra", - "owner": "demo", - "playbooks": { - "phishing": { - "name": "Phishing", - "tasks": { - "block-iocs": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Block IOCs", - "order": 6, - "type": "task" - }, - "block-sender": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Block sender", - "next": { - "extract-iocs": "" - }, - "order": 3, - "type": "task" - }, - "board": { - "active": true, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Board Involvement?", - "next": { - "escalate": "boardInvolved == true", - "mail-available": "boardInvolved == false" - }, - "order": 0, - "schema": { - "properties": { - "boardInvolved": { - "default": false, - "title": "A board member is involved.", - "type": "boolean" - } - }, - "required": [ - "boardInvolved" - ], - "title": "Board Involvement?", - "type": "object" - }, - "type": "input" - }, - "escalate": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Escalate to CISO", - "order": 1, - "type": "task" - }, - "extract-iocs": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Extract IOCs", - "next": { - "block-iocs": "" - }, - "order": 5, - "schema": { - "properties": { - "iocs": { - "items": { - "type": "string" - }, - "title": "IOCs", - "type": "array" - } - }, - "title": "Extract IOCs", - "type": "object" - }, - "type": "input" - }, - "mail-available": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Mail available", - "next": { - "block-sender": "schemaKey == 'yes'", - "extract-iocs": "schemaKey == 'yes'", - "search-email-gateway": "schemaKey == 'no'" - }, - "order": 2, - "schema": { - "oneOf": [ - { - "properties": { - "mail": { - "title": "Mail", - "type": "string", - "x-display": "textarea" - }, - "schemaKey": { - "const": "yes", - "type": "string" - } - }, - "required": [ - "mail" - ], - "title": "Yes" - }, - { - "properties": { - "schemaKey": { - "const": "no", - "type": "string" - } - }, - "title": "No" - } - ], - "title": "Mail available", - "type": "object" - }, - "type": "input" - }, - "search-email-gateway": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Search email gateway", - "next": { - "extract-iocs": "" - }, - "order": 4, - "type": "task" - } - } - } - }, - "references": [ - { - "href": "https://www.leadmaximize.net/e-services/back-end", - "name": "performance" - }, - { - "href": "http://www.corporateinteractive.name/rich", - "name": "autumn" - }, - { - "href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", - "name": "suggest" - } - ], - "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", - "status": "closed", - "type": "incident" - } - } - } - } - } - }, - "/tickets/{id}/artifacts/{name}/enrich": { - "post": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Enrich a single artifact", - "operationId": "enrichArtifact", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8123, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "string", - "x-example": "leadreintermediate.io", - "name": "name", - "in": "path", - "required": true - }, - { - "x-example": { - "data": { - "hash": "b7a067a742c20d07a7456646de89bc2d408a1153" - }, - "name": "hash.sha1" - }, - "name": "data", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/EnrichmentForm" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/Artifact" - }, - "examples": { - "test": { - "artifacts": [ - { - "name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", - "status": "unknown" - }, - { - "name": "http://www.customerviral.io/scalable/vertical/killer", - "status": "clean" - }, - { - "enrichments": { - "hash.sha1": { - "created": "2021-12-12T12:12:12.000000012Z", - "data": { - "hash": "b7a067a742c20d07a7456646de89bc2d408a1153" - }, - "name": "hash.sha1" - } - }, - "name": "leadreintermediate.io", - "status": "malicious" - } - ], - "created": "2021-10-02T16:04:59.078206Z", - "id": 8123, - "modified": "2021-10-02T16:04:59.078206Z", - "name": "live zebra", - "owner": "demo", - "playbooks": { - "phishing": { - "name": "Phishing", - "tasks": { - "block-iocs": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Block IOCs", - "order": 6, - "type": "task" - }, - "block-sender": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Block sender", - "next": { - "extract-iocs": "" - }, - "order": 3, - "type": "task" - }, - "board": { - "active": true, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Board Involvement?", - "next": { - "escalate": "boardInvolved == true", - "mail-available": "boardInvolved == false" - }, - "order": 0, - "schema": { - "properties": { - "boardInvolved": { - "default": false, - "title": "A board member is involved.", - "type": "boolean" - } - }, - "required": [ - "boardInvolved" - ], - "title": "Board Involvement?", - "type": "object" - }, - "type": "input" - }, - "escalate": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Escalate to CISO", - "order": 1, - "type": "task" - }, - "extract-iocs": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Extract IOCs", - "next": { - "block-iocs": "" - }, - "order": 5, - "schema": { - "properties": { - "iocs": { - "items": { - "type": "string" - }, - "title": "IOCs", - "type": "array" - } - }, - "title": "Extract IOCs", - "type": "object" - }, - "type": "input" - }, - "mail-available": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Mail available", - "next": { - "block-sender": "schemaKey == 'yes'", - "extract-iocs": "schemaKey == 'yes'", - "search-email-gateway": "schemaKey == 'no'" - }, - "order": 2, - "schema": { - "oneOf": [ - { - "properties": { - "mail": { - "title": "Mail", - "type": "string", - "x-display": "textarea" - }, - "schemaKey": { - "const": "yes", - "type": "string" - } - }, - "required": [ - "mail" - ], - "title": "Yes" - }, - { - "properties": { - "schemaKey": { - "const": "no", - "type": "string" - } - }, - "title": "No" - } - ], - "title": "Mail available", - "type": "object" - }, - "type": "input" - }, - "search-email-gateway": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Search email gateway", - "next": { - "extract-iocs": "" - }, - "order": 4, - "type": "task" - } - } - } - }, - "references": [ - { - "href": "https://www.leadmaximize.net/e-services/back-end", - "name": "performance" - }, - { - "href": "http://www.corporateinteractive.name/rich", - "name": "autumn" - }, - { - "href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", - "name": "suggest" - } - ], - "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", - "status": "closed", - "type": "incident" - } - } - } - } - } - }, - "/tickets/{id}/artifacts/{name}/run/{automation}": { - "post": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Run automation on a single artifact", - "operationId": "runArtifact", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8123, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "string", - "x-example": "leadreintermediate.io", - "name": "name", - "in": "path", - "required": true - }, - { - "type": "string", - "x-example": "hash.sha1", - "name": "automation", - "in": "path", - "required": true - } - ], - "responses": { - "204": { - "description": "successful operation" - } - } - } - }, - "/tickets/{id}/comments": { - "post": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Add ticket comment", - "operationId": "addComment", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8125, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "x-example": { - "message": "My first comment" - }, - "description": "Ticket comment", - "name": "comment", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/CommentForm" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketResponse" - }, - "examples": { - "test": { - "comments": [ - { - "created": "2021-12-12T12:12:12.000000012Z", - "creator": "bob", - "message": "My first comment" - } - ], - "created": "2021-10-02T16:04:59.078186Z", - "id": 8125, - "modified": "2021-12-12T12:12:12.000000012Z", - "name": "phishing from selenafadel@von.com detected", - "owner": "demo", - "references": [ - { - "href": "https://www.seniorleading-edge.name/users/efficient", - "name": "recovery" - }, - { - "href": "http://www.dynamicseamless.com/clicks-and-mortar", - "name": "force" - }, - { - "href": "http://www.leadscalable.biz/envisioneer", - "name": "fund" - } - ], - "schema": "{}", - "status": "closed", - "tickets": [ - { - "created": "2021-10-02T16:04:59.078186Z", - "id": 8126, - "modified": "2021-10-02T16:04:59.078186Z", - "name": "Surfaceintroduce virus detected", - "owner": "demo", - "references": [ - { - "href": "http://www.centralworld-class.io/synthesize", - "name": "university" - }, - { - "href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", - "name": "goal" - }, - { - "href": "http://www.chiefsyndicate.io/action-items", - "name": "unemployment" - } - ], - "schema": "{}", - "status": "closed", - "type": "alert" - } - ], - "type": "alert" - } - } - } - } - } - }, - "/tickets/{id}/comments/{commentID}": { - "delete": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "description": "Comment will be removed from the ticket.", - "tags": [ - "tickets" - ], - "summary": "Remove an comment from an ticket", - "operationId": "removeComment", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8123, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "integer", - "x-example": 0, - "description": "Comment ID to remove", - "name": "commentID", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketResponse" - }, - "examples": { - "test": { - "artifacts": [ - { - "name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", - "status": "unknown" - }, - { - "name": "http://www.customerviral.io/scalable/vertical/killer", - "status": "clean" - }, - { - "name": "leadreintermediate.io", - "status": "malicious" - } - ], - "created": "2021-10-02T16:04:59.078206Z", - "id": 8123, - "modified": "2021-12-12T12:12:12.000000012Z", - "name": "live zebra", - "owner": "demo", - "playbooks": { - "phishing": { - "name": "Phishing", - "tasks": { - "block-iocs": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Block IOCs", - "order": 6, - "type": "task" - }, - "block-sender": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Block sender", - "next": { - "extract-iocs": "" - }, - "order": 3, - "type": "task" - }, - "board": { - "active": true, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Board Involvement?", - "next": { - "escalate": "boardInvolved == true", - "mail-available": "boardInvolved == false" - }, - "order": 0, - "schema": { - "properties": { - "boardInvolved": { - "default": false, - "title": "A board member is involved.", - "type": "boolean" - } - }, - "required": [ - "boardInvolved" - ], - "title": "Board Involvement?", - "type": "object" - }, - "type": "input" - }, - "escalate": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Escalate to CISO", - "order": 1, - "type": "task" - }, - "extract-iocs": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Extract IOCs", - "next": { - "block-iocs": "" - }, - "order": 5, - "schema": { - "properties": { - "iocs": { - "items": { - "type": "string" - }, - "title": "IOCs", - "type": "array" - } - }, - "title": "Extract IOCs", - "type": "object" - }, - "type": "input" - }, - "mail-available": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Mail available", - "next": { - "block-sender": "schemaKey == 'yes'", - "extract-iocs": "schemaKey == 'yes'", - "search-email-gateway": "schemaKey == 'no'" - }, - "order": 2, - "schema": { - "oneOf": [ - { - "properties": { - "mail": { - "title": "Mail", - "type": "string", - "x-display": "textarea" - }, - "schemaKey": { - "const": "yes", - "type": "string" - } - }, - "required": [ - "mail" - ], - "title": "Yes" - }, - { - "properties": { - "schemaKey": { - "const": "no", - "type": "string" - } - }, - "title": "No" - } - ], - "title": "Mail available", - "type": "object" - }, - "type": "input" - }, - "search-email-gateway": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Search email gateway", - "next": { - "extract-iocs": "" - }, - "order": 4, - "type": "task" - } - } - } - }, - "references": [ - { - "href": "https://www.leadmaximize.net/e-services/back-end", - "name": "performance" - }, - { - "href": "http://www.corporateinteractive.name/rich", - "name": "autumn" - }, - { - "href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", - "name": "suggest" - } - ], - "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", - "status": "closed", - "type": "incident" - } - } - } - } - } - }, - "/tickets/{id}/files": { - "put": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "description": "Link files to an ticket. The files themself will be stored in object storage.", - "tags": [ - "tickets" - ], - "summary": "Link files to an ticket", - "operationId": "linkFiles", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8125, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "x-example": [ - { - "key": "myfile", - "name": "document.doc" - } - ], - "description": "Added files", - "name": "files", - "in": "body", - "required": true, - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/File" - } - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketResponse" - }, - "examples": { - "test": { - "created": "2021-10-02T16:04:59.078186Z", - "files": [ - { - "key": "myfile", - "name": "document.doc" - } - ], - "id": 8125, - "modified": "2021-12-12T12:12:12.000000012Z", - "name": "phishing from selenafadel@von.com detected", - "owner": "demo", - "references": [ - { - "href": "https://www.seniorleading-edge.name/users/efficient", - "name": "recovery" - }, - { - "href": "http://www.dynamicseamless.com/clicks-and-mortar", - "name": "force" - }, - { - "href": "http://www.leadscalable.biz/envisioneer", - "name": "fund" - } - ], - "schema": "{}", - "status": "closed", - "tickets": [ - { - "created": "2021-10-02T16:04:59.078186Z", - "id": 8126, - "modified": "2021-10-02T16:04:59.078186Z", - "name": "Surfaceintroduce virus detected", - "owner": "demo", - "references": [ - { - "href": "http://www.centralworld-class.io/synthesize", - "name": "university" - }, - { - "href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", - "name": "goal" - }, - { - "href": "http://www.chiefsyndicate.io/action-items", - "name": "unemployment" - } - ], - "schema": "{}", - "status": "closed", - "type": "alert" - } - ], - "type": "alert" - } - } - } - } - } - }, - "/tickets/{id}/playbooks": { - "post": { - "tags": [ - "tickets" - ], - "summary": "Add a new ticket playbook", - "operationId": "addTicketPlaybook", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8125, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "x-example": { - "yaml": "name: Simple\ntasks:\n input:\n name: Upload malware if possible\n type: input\n schema:\n title: Malware\n type: object\n properties:\n malware:\n type: string\n title: Select malware\n default: \"\"\n next:\n hash: \"malware != ''\"\n\n hash:\n name: Hash the malware\n type: automation\n automation: hash.sha1\n payload:\n default: \"playbook.tasks['input'].data['malware']\"\n next:\n escalate:\n\n escalate:\n name: Escalate to malware team\n type: task\n" - }, - "description": "Ticket playbook object that needs to be added", - "name": "playbook", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/PlaybookTemplateForm" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketResponse" - }, - "examples": { - "test": { - "created": "2021-10-02T16:04:59.078186Z", - "id": 8125, - "modified": "2021-12-12T12:12:12.000000012Z", - "name": "phishing from selenafadel@von.com detected", - "owner": "demo", - "playbooks": { - "simple": { - "name": "Simple", - "tasks": { - "escalate": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Escalate to malware team", - "order": 2, - "type": "task" - }, - "hash": { - "active": false, - "automation": "hash.sha1", - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Hash the malware", - "next": { - "escalate": "" - }, - "order": 1, - "payload": { - "default": "playbook.tasks['input'].data['malware']" - }, - "type": "automation" - }, - "input": { - "active": true, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Upload malware if possible", - "next": { - "hash": "malware != ''" - }, - "order": 0, - "schema": { - "properties": { - "malware": { - "default": "", - "title": "Select malware", - "type": "string" - } - }, - "title": "Malware", - "type": "object" - }, - "type": "input" - } - } - } - }, - "references": [ - { - "href": "https://www.seniorleading-edge.name/users/efficient", - "name": "recovery" - }, - { - "href": "http://www.dynamicseamless.com/clicks-and-mortar", - "name": "force" - }, - { - "href": "http://www.leadscalable.biz/envisioneer", - "name": "fund" - } - ], - "schema": "{}", - "status": "closed", - "tickets": [ - { - "created": "2021-10-02T16:04:59.078186Z", - "id": 8126, - "modified": "2021-10-02T16:04:59.078186Z", - "name": "Surfaceintroduce virus detected", - "owner": "demo", - "references": [ - { - "href": "http://www.centralworld-class.io/synthesize", - "name": "university" - }, - { - "href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", - "name": "goal" - }, - { - "href": "http://www.chiefsyndicate.io/action-items", - "name": "unemployment" - } - ], - "schema": "{}", - "status": "closed", - "type": "alert" - } - ], - "type": "alert" - } - } - } - } - } - }, - "/tickets/{id}/playbooks/{playbookID}": { - "delete": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Remove an ticket playbook", - "operationId": "removeTicketPlaybook", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8123, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "string", - "x-example": "phishing", - "description": "Playbook ID", - "name": "playbookID", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketResponse" - }, - "examples": { - "test": { - "artifacts": [ - { - "name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", - "status": "unknown" - }, - { - "name": "http://www.customerviral.io/scalable/vertical/killer", - "status": "clean" - }, - { - "name": "leadreintermediate.io", - "status": "malicious" - } - ], - "created": "2021-10-02T16:04:59.078206Z", - "id": 8123, - "modified": "2021-12-12T12:12:12.000000012Z", - "name": "live zebra", - "owner": "demo", - "references": [ - { - "href": "https://www.leadmaximize.net/e-services/back-end", - "name": "performance" - }, - { - "href": "http://www.corporateinteractive.name/rich", - "name": "autumn" - }, - { - "href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", - "name": "suggest" - } - ], - "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", - "status": "closed", - "type": "incident" - } - } - } - } - } - }, - "/tickets/{id}/playbooks/{playbookID}/task/{taskID}": { - "put": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Set a ticket playbook task", - "operationId": "setTask", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8123, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "string", - "x-example": "phishing", - "description": "Playbook ID", - "name": "playbookID", - "in": "path", - "required": true - }, - { - "type": "string", - "x-example": "board", - "description": "Task ID", - "name": "taskID", - "in": "path", - "required": true - }, - { - "x-example": { - "active": true, - "data": { - "boardInvolved": true - }, - "done": false, - "name": "Board Involvement?", - "next": { - "escalate": "boardInvolved == true", - "mail-available": "boardInvolved == false" - }, - "order": 0, - "schema": { - "properties": { - "boardInvolved": { - "default": false, - "title": "A board member is involved.", - "type": "boolean" - } - }, - "required": [ - "boardInvolved" - ], - "title": "Board Involvement?", - "type": "object" - }, - "type": "input" - }, - "description": "Task", - "name": "task", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/Task" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketResponse" - }, - "examples": { - "test": { - "artifacts": [ - { - "name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", - "status": "unknown" - }, - { - "name": "http://www.customerviral.io/scalable/vertical/killer", - "status": "clean" - }, - { - "name": "leadreintermediate.io", - "status": "malicious" - } - ], - "created": "2021-10-02T16:04:59.078206Z", - "id": 8123, - "modified": "2021-12-12T12:12:12.000000012Z", - "name": "live zebra", - "owner": "demo", - "playbooks": { - "phishing": { - "name": "Phishing", - "tasks": { - "block-iocs": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Block IOCs", - "order": 6, - "type": "task" - }, - "block-sender": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Block sender", - "next": { - "extract-iocs": "" - }, - "order": 3, - "type": "task" - }, - "board": { - "active": true, - "created": "2021-12-12T12:12:12.000000012Z", - "data": { - "boardInvolved": true - }, - "done": false, - "name": "Board Involvement?", - "next": { - "escalate": "boardInvolved == true", - "mail-available": "boardInvolved == false" - }, - "order": 0, - "schema": { - "properties": { - "boardInvolved": { - "default": false, - "title": "A board member is involved.", - "type": "boolean" - } - }, - "required": [ - "boardInvolved" - ], - "title": "Board Involvement?", - "type": "object" - }, - "type": "input" - }, - "escalate": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Escalate to CISO", - "order": 1, - "type": "task" - }, - "extract-iocs": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Extract IOCs", - "next": { - "block-iocs": "" - }, - "order": 5, - "schema": { - "properties": { - "iocs": { - "items": { - "type": "string" - }, - "title": "IOCs", - "type": "array" - } - }, - "title": "Extract IOCs", - "type": "object" - }, - "type": "input" - }, - "mail-available": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Mail available", - "next": { - "block-sender": "schemaKey == 'yes'", - "extract-iocs": "schemaKey == 'yes'", - "search-email-gateway": "schemaKey == 'no'" - }, - "order": 2, - "schema": { - "oneOf": [ - { - "properties": { - "mail": { - "title": "Mail", - "type": "string", - "x-display": "textarea" - }, - "schemaKey": { - "const": "yes", - "type": "string" - } - }, - "required": [ - "mail" - ], - "title": "Yes" - }, - { - "properties": { - "schemaKey": { - "const": "no", - "type": "string" - } - }, - "title": "No" - } - ], - "title": "Mail available", - "type": "object" - }, - "type": "input" - }, - "search-email-gateway": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Search email gateway", - "next": { - "extract-iocs": "" - }, - "order": 4, - "type": "task" - } - } - } - }, - "references": [ - { - "href": "https://www.leadmaximize.net/e-services/back-end", - "name": "performance" - }, - { - "href": "http://www.corporateinteractive.name/rich", - "name": "autumn" - }, - { - "href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", - "name": "suggest" - } - ], - "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", - "status": "closed", - "type": "incident" - } - } - } - } - } - }, - "/tickets/{id}/playbooks/{playbookID}/task/{taskID}/complete": { - "put": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Complete ticket playbook task", - "operationId": "completeTask", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8123, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "string", - "x-example": "phishing", - "description": "Playbook ID", - "name": "playbookID", - "in": "path", - "required": true - }, - { - "type": "string", - "x-example": "board", - "description": "Task ID", - "name": "taskID", - "in": "path", - "required": true - }, - { - "x-example": { - "boardInvolved": true - }, - "description": "Ticket playbook object that needs to be added", - "name": "data", - "in": "body", - "required": true, - "schema": { - "type": "object" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketResponse" - }, - "examples": { - "test": { - "artifacts": [ - { - "name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", - "status": "unknown" - }, - { - "name": "http://www.customerviral.io/scalable/vertical/killer", - "status": "clean" - }, - { - "name": "leadreintermediate.io", - "status": "malicious" - } - ], - "created": "2021-10-02T16:04:59.078206Z", - "id": 8123, - "modified": "2021-12-12T12:12:12.000000012Z", - "name": "live zebra", - "owner": "demo", - "playbooks": { - "phishing": { - "name": "Phishing", - "tasks": { - "block-iocs": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Block IOCs", - "order": 6, - "type": "task" - }, - "block-sender": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Block sender", - "next": { - "extract-iocs": "" - }, - "order": 3, - "type": "task" - }, - "board": { - "active": false, - "closed": "2021-12-12T12:12:12.000000012Z", - "created": "2021-12-12T12:12:12.000000012Z", - "data": { - "boardInvolved": true - }, - "done": true, - "name": "Board Involvement?", - "next": { - "escalate": "boardInvolved == true", - "mail-available": "boardInvolved == false" - }, - "order": 0, - "schema": { - "properties": { - "boardInvolved": { - "default": false, - "title": "A board member is involved.", - "type": "boolean" - } - }, - "required": [ - "boardInvolved" - ], - "title": "Board Involvement?", - "type": "object" - }, - "type": "input" - }, - "escalate": { - "active": true, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Escalate to CISO", - "order": 1, - "type": "task" - }, - "extract-iocs": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Extract IOCs", - "next": { - "block-iocs": "" - }, - "order": 5, - "schema": { - "properties": { - "iocs": { - "items": { - "type": "string" - }, - "title": "IOCs", - "type": "array" - } - }, - "title": "Extract IOCs", - "type": "object" - }, - "type": "input" - }, - "mail-available": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Mail available", - "next": { - "block-sender": "schemaKey == 'yes'", - "extract-iocs": "schemaKey == 'yes'", - "search-email-gateway": "schemaKey == 'no'" - }, - "order": 2, - "schema": { - "oneOf": [ - { - "properties": { - "mail": { - "title": "Mail", - "type": "string", - "x-display": "textarea" - }, - "schemaKey": { - "const": "yes", - "type": "string" - } - }, - "required": [ - "mail" - ], - "title": "Yes" - }, - { - "properties": { - "schemaKey": { - "const": "no", - "type": "string" - } - }, - "title": "No" - } - ], - "title": "Mail available", - "type": "object" - }, - "type": "input" - }, - "search-email-gateway": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Search email gateway", - "next": { - "extract-iocs": "" - }, - "order": 4, - "type": "task" - } - } - } - }, - "references": [ - { - "href": "https://www.leadmaximize.net/e-services/back-end", - "name": "performance" - }, - { - "href": "http://www.corporateinteractive.name/rich", - "name": "autumn" - }, - { - "href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", - "name": "suggest" - } - ], - "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", - "status": "closed", - "type": "incident" - } - } - } - } - } - }, - "/tickets/{id}/playbooks/{playbookID}/task/{taskID}/run": { - "post": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Run ticket playbook task", - "operationId": "runTask", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8123, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "string", - "x-example": "phishing", - "description": "Playbook ID", - "name": "playbookID", - "in": "path", - "required": true - }, - { - "type": "string", - "x-example": "board", - "description": "Task ID", - "name": "taskID", - "in": "path", - "required": true - } - ], - "responses": { - "204": { - "description": "successful operation" - } - } - } - }, - "/tickets/{id}/references": { - "put": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Set ticket references", - "operationId": "setReferences", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8125, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "x-example": [ - { - "href": "http://www.leadscalable.biz/envisioneer", - "name": "fund" - } - ], - "description": "All ticket references", - "name": "references", - "in": "body", - "required": true, - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/Reference" - } - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketResponse" - }, - "examples": { - "test": { - "created": "2021-10-02T16:04:59.078186Z", - "id": 8125, - "modified": "2021-12-12T12:12:12.000000012Z", - "name": "phishing from selenafadel@von.com detected", - "owner": "demo", - "references": [ - { - "href": "http://www.leadscalable.biz/envisioneer", - "name": "fund" - } - ], - "schema": "{}", - "status": "closed", - "tickets": [ - { - "created": "2021-10-02T16:04:59.078186Z", - "id": 8126, - "modified": "2021-10-02T16:04:59.078186Z", - "name": "Surfaceintroduce virus detected", - "owner": "demo", - "references": [ - { - "href": "http://www.centralworld-class.io/synthesize", - "name": "university" - }, - { - "href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", - "name": "goal" - }, - { - "href": "http://www.chiefsyndicate.io/action-items", - "name": "unemployment" - } - ], - "schema": "{}", - "status": "closed", - "type": "alert" - } - ], - "type": "alert" - } - } - } - } - } - }, - "/tickets/{id}/schema": { - "put": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Set ticket schema", - "operationId": "setSchema", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8125, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "x-example": "{}", - "description": "New ticket schema", - "name": "schema", - "in": "body", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketResponse" - }, - "examples": { - "test": { - "created": "2021-10-02T16:04:59.078186Z", - "id": 8125, - "modified": "2021-10-02T16:04:59.078186Z", - "name": "phishing from selenafadel@von.com detected", - "owner": "demo", - "references": [ - { - "href": "https://www.seniorleading-edge.name/users/efficient", - "name": "recovery" - }, - { - "href": "http://www.dynamicseamless.com/clicks-and-mortar", - "name": "force" - }, - { - "href": "http://www.leadscalable.biz/envisioneer", - "name": "fund" - } - ], - "schema": "{}", - "status": "closed", - "tickets": [ - { - "created": "2021-10-02T16:04:59.078186Z", - "id": 8126, - "modified": "2021-10-02T16:04:59.078186Z", - "name": "Surfaceintroduce virus detected", - "owner": "demo", - "references": [ - { - "href": "http://www.centralworld-class.io/synthesize", - "name": "university" - }, - { - "href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", - "name": "goal" - }, - { - "href": "http://www.chiefsyndicate.io/action-items", - "name": "unemployment" - } - ], - "schema": "{}", - "status": "closed", - "type": "alert" - } - ], - "type": "alert" - } - } - } - } - } - }, - "/tickets/{id}/tickets": { - "delete": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Unlink an ticket to an ticket", - "operationId": "unlinkTicket", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8126, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "x-example": 8125, - "description": "Added ticket ID", - "name": "linkedID", - "in": "body", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketResponse" - }, - "examples": { - "test": { - "created": "2021-10-02T16:04:59.078186Z", - "id": 8126, - "modified": "2021-10-02T16:04:59.078186Z", - "name": "Surfaceintroduce virus detected", - "owner": "demo", - "references": [ - { - "href": "http://www.centralworld-class.io/synthesize", - "name": "university" - }, - { - "href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", - "name": "goal" - }, - { - "href": "http://www.chiefsyndicate.io/action-items", - "name": "unemployment" - } - ], - "schema": "{}", - "status": "closed", - "type": "alert" - } - } - } - } - }, - "patch": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Link an ticket to an ticket", - "operationId": "linkTicket", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8126, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "x-example": 8123, - "description": "Added ticket ID", - "name": "linkedID", - "in": "body", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketResponse" - }, - "examples": { - "test": { - "created": "2021-10-02T16:04:59.078186Z", - "id": 8126, - "modified": "2021-10-02T16:04:59.078186Z", - "name": "Surfaceintroduce virus detected", - "owner": "demo", - "references": [ - { - "href": "http://www.centralworld-class.io/synthesize", - "name": "university" - }, - { - "href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", - "name": "goal" - }, - { - "href": "http://www.chiefsyndicate.io/action-items", - "name": "unemployment" - } - ], - "schema": "{}", - "status": "closed", - "tickets": [ - { - "artifacts": [ - { - "name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", - "status": "unknown" - }, - { - "name": "http://www.customerviral.io/scalable/vertical/killer", - "status": "clean" - }, - { - "name": "leadreintermediate.io", - "status": "malicious" - } - ], - "created": "2021-10-02T16:04:59.078206Z", - "id": 8123, - "modified": "2021-10-02T16:04:59.078206Z", - "name": "live zebra", - "owner": "demo", - "playbooks": { - "phishing": { - "name": "Phishing", - "tasks": { - "block-iocs": { - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Block IOCs", - "type": "task" - }, - "block-sender": { - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Block sender", - "next": { - "extract-iocs": "" - }, - "type": "task" - }, - "board": { - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Board Involvement?", - "next": { - "escalate": "boardInvolved == true", - "mail-available": "boardInvolved == false" - }, - "schema": { - "properties": { - "boardInvolved": { - "default": false, - "title": "A board member is involved.", - "type": "boolean" - } - }, - "required": [ - "boardInvolved" - ], - "title": "Board Involvement?", - "type": "object" - }, - "type": "input" - }, - "escalate": { - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Escalate to CISO", - "type": "task" - }, - "extract-iocs": { - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Extract IOCs", - "next": { - "block-iocs": "" - }, - "schema": { - "properties": { - "iocs": { - "items": { - "type": "string" - }, - "title": "IOCs", - "type": "array" - } - }, - "title": "Extract IOCs", - "type": "object" - }, - "type": "input" - }, - "mail-available": { - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Mail available", - "next": { - "block-sender": "schemaKey == 'yes'", - "extract-iocs": "schemaKey == 'yes'", - "search-email-gateway": "schemaKey == 'no'" - }, - "schema": { - "oneOf": [ - { - "properties": { - "mail": { - "title": "Mail", - "type": "string", - "x-display": "textarea" - }, - "schemaKey": { - "const": "yes", - "type": "string" - } - }, - "required": [ - "mail" - ], - "title": "Yes" - }, - { - "properties": { - "schemaKey": { - "const": "no", - "type": "string" - } - }, - "title": "No" - } - ], - "title": "Mail available", - "type": "object" - }, - "type": "input" - }, - "search-email-gateway": { - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Search email gateway", - "next": { - "extract-iocs": "" - }, - "type": "task" - } - } - } - }, - "references": [ - { - "href": "https://www.leadmaximize.net/e-services/back-end", - "name": "performance" - }, - { - "href": "http://www.corporateinteractive.name/rich", - "name": "autumn" - }, - { - "href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", - "name": "suggest" - } - ], - "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", - "status": "closed", - "type": "incident" - }, - { - "created": "2021-10-02T16:04:59.078186Z", - "id": 8125, - "modified": "2021-10-02T16:04:59.078186Z", - "name": "phishing from selenafadel@von.com detected", - "owner": "demo", - "references": [ - { - "href": "https://www.seniorleading-edge.name/users/efficient", - "name": "recovery" - }, - { - "href": "http://www.dynamicseamless.com/clicks-and-mortar", - "name": "force" - }, - { - "href": "http://www.leadscalable.biz/envisioneer", - "name": "fund" - } - ], - "schema": "{}", - "status": "closed", - "type": "alert" - } - ], - "type": "alert" - } - } - } - } - } - }, - "/tickettypes": { - "get": { - "security": [ - { - "roles": [ - "tickettype:read" - ] - } - ], - "tags": [ - "tickettypes" - ], - "summary": "List tickettypes", - "operationId": "listTicketTypes", - "responses": { - "200": { - "description": "successful operation", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/TicketTypeResponse" - } - }, - "examples": { - "test": [ - { - "default_playbooks": null, - "default_template": "default", - "icon": "mdi-alert", - "id": "alert", - "name": "Alerts" - }, - { - "default_playbooks": null, - "default_template": "default", - "icon": "mdi-radioactive", - "id": "incident", - "name": "Incidents" - }, - { - "default_playbooks": null, - "default_template": "default", - "icon": "mdi-fingerprint", - "id": "investigation", - "name": "Forensic Investigations" - }, - { - "default_playbooks": null, - "default_template": "default", - "icon": "mdi-target", - "id": "hunt", - "name": "Threat Hunting" - } - ] - } - } - } - }, - "post": { - "security": [ - { - "roles": [ - "tickettype:write" - ] - } - ], - "tags": [ - "tickettypes" - ], - "summary": "Create a new tickettype", - "operationId": "createTicketType", - "parameters": [ - { - "x-example": { - "default_playbooks": null, - "default_template": "default", - "icon": "mdi-newspaper-variant-outline", - "name": "TI Tickets" - }, - "description": "New tickettype", - "name": "tickettype", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/TicketTypeForm" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketTypeResponse" - }, - "examples": { - "test": { - "default_playbooks": null, - "default_template": "default", - "icon": "mdi-newspaper-variant-outline", - "id": "ti-tickets", - "name": "TI Tickets" - } - } - } - } - } - }, - "/tickettypes/{id}": { - "get": { - "security": [ - { - "roles": [ - "tickettype:read" - ] - } - ], - "tags": [ - "tickettypes" - ], - "summary": "Get a single tickettype", - "operationId": "getTicketType", - "parameters": [ - { - "type": "string", - "x-example": "alert", - "description": "TicketType ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketTypeResponse" - }, - "examples": { - "test": { - "default_playbooks": null, - "default_template": "default", - "icon": "mdi-alert", - "id": "alert", - "name": "Alerts" - } - } - } - } - }, - "put": { - "security": [ - { - "roles": [ - "tickettype:write" - ] - } - ], - "tags": [ - "tickettypes" - ], - "summary": "Update an existing tickettype", - "operationId": "updateTicketType", - "parameters": [ - { - "type": "string", - "x-example": "alert", - "description": "TicketType ID", - "name": "id", - "in": "path", - "required": true - }, - { - "x-example": { - "default_playbooks": null, - "default_template": "default", - "icon": "mdi-bell", - "id": "alert", - "name": "Alerts" - }, - "description": "TicketType object that needs to be added", - "name": "tickettype", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/TicketTypeForm" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketTypeResponse" - }, - "examples": { - "test": { - "default_playbooks": null, - "default_template": "default", - "icon": "mdi-bell", - "id": "alert", - "name": "Alerts" - } - } - } - } - }, - "delete": { - "security": [ - { - "roles": [ - "tickettype:write" - ] - } - ], - "tags": [ - "tickettypes" - ], - "summary": "Delete a tickettype", - "operationId": "deleteTicketType", - "parameters": [ - { - "type": "string", - "x-example": "alert", - "description": "TicketType ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "204": { - "description": "successful operation" - } - } - } - }, - "/userdata": { - "get": { - "security": [ - { - "roles": [ - "userdata:read" - ] - } - ], - "tags": [ - "userdata" - ], - "summary": "List userdata", - "operationId": "listUserData", - "responses": { - "200": { - "description": "successful operation", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/UserDataResponse" - } - }, - "examples": { - "test": [ - { - "email": "bob@example.org", - "id": "bob", - "name": "Bob Bad" - } - ] - } - } - } - } - }, - "/userdata/{id}": { - "get": { - "security": [ - { - "roles": [ - "userdata:read" - ] - } - ], - "tags": [ - "userdata" - ], - "summary": "Get a single user data", - "operationId": "getUserData", - "parameters": [ - { - "type": "string", - "x-example": "bob", - "description": "User Data ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/UserDataResponse" - }, - "examples": { - "test": { - "email": "bob@example.org", - "id": "bob", - "name": "Bob Bad" - } - } - } - } - }, - "put": { - "security": [ - { - "roles": [ - "userdata:write" - ] - } - ], - "tags": [ - "userdata" - ], - "summary": "Update an existing user data", - "operationId": "updateUserData", - "parameters": [ - { - "type": "string", - "x-example": "bob", - "description": "User Data ID", - "name": "id", - "in": "path", - "required": true - }, - { - "x-example": { - "blocked": false, - "email": "bob@example.org", - "name": "Bob Bad" - }, - "description": "User data object that needs to be added", - "name": "userdata", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/UserData" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/UserDataResponse" - }, - "examples": { - "test": { - "email": "bob@example.org", - "id": "bob", - "name": "Bob Bad" - } - } - } - } - } - }, - "/users": { - "get": { - "security": [ - { - "roles": [ - "user:read" - ] - } - ], - "tags": [ - "users" - ], - "summary": "List users", - "operationId": "listUsers", - "responses": { - "200": { - "description": "successful operation", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/UserResponse" - } - }, - "examples": { - "test": [ - { - "apikey": false, - "blocked": false, - "id": "bob", - "roles": [ - "admin:backup:read", - "admin:backup:restore", - "admin:group:write", - "admin:job:read", - "admin:job:write", - "admin:log:read", - "admin:ticket:delete", - "admin:user:write", - "admin:userdata:read", - "admin:userdata:write", - "analyst:automation:read", - "analyst:currentsettings:write", - "analyst:currentuser:read", - "analyst:currentuserdata:read", - "analyst:file", - "analyst:group:read", - "analyst:playbook:read", - "analyst:rule:read", - "analyst:settings:read", - "analyst:template:read", - "analyst:ticket:read", - "analyst:ticket:write", - "analyst:tickettype:read", - "analyst:user:read", - "engineer:automation:write", - "engineer:playbook:write", - "engineer:rule:write", - "engineer:template:write", - "engineer:tickettype:write" - ] - }, - { - "apikey": true, - "blocked": false, - "id": "script", - "roles": [ - "analyst:automation:read", - "analyst:currentsettings:write", - "analyst:currentuser:read", - "analyst:currentuserdata:read", - "analyst:file", - "analyst:group:read", - "analyst:playbook:read", - "analyst:rule:read", - "analyst:settings:read", - "analyst:template:read", - "analyst:ticket:read", - "analyst:ticket:write", - "analyst:tickettype:read", - "analyst:user:read", - "engineer:automation:write", - "engineer:playbook:write", - "engineer:rule:write", - "engineer:template:write", - "engineer:tickettype:write" - ] - } - ] - } - } - } - }, - "post": { - "security": [ - { - "roles": [ - "user:write" - ] - } - ], - "tags": [ - "users" - ], - "summary": "Create user", - "operationId": "createUser", - "parameters": [ - { - "x-example": { - "id": "syncscript", - "roles": [ - "analyst" - ] - }, - "description": "user object that needs to be added", - "name": "user", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/UserForm" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/NewUserResponse" - }, - "examples": { - "test": { - "blocked": false, - "id": "syncscript", - "roles": [ - "analyst:automation:read", - "analyst:currentsettings:write", - "analyst:currentuser:read", - "analyst:currentuserdata:read", - "analyst:file", - "analyst:group:read", - "analyst:playbook:read", - "analyst:rule:read", - "analyst:settings:read", - "analyst:template:read", - "analyst:ticket:read", - "analyst:ticket:write", - "analyst:tickettype:read", - "analyst:user:read" - ], - "secret": "v39bOuobnlEljfWzjAgoKzhmnh1xSMxH" - } - } - } - } - } - }, - "/users/{id}": { - "get": { - "security": [ - { - "roles": [ - "user:read" - ] - } - ], - "tags": [ - "users" - ], - "summary": "Get a single user", - "operationId": "getUser", - "parameters": [ - { - "type": "string", - "x-example": "script", - "description": "user ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/UserResponse" - }, - "examples": { - "test": { - "apikey": true, - "blocked": false, - "id": "script", - "roles": [ - "analyst:automation:read", - "analyst:currentsettings:write", - "analyst:currentuser:read", - "analyst:currentuserdata:read", - "analyst:file", - "analyst:group:read", - "analyst:playbook:read", - "analyst:rule:read", - "analyst:settings:read", - "analyst:template:read", - "analyst:ticket:read", - "analyst:ticket:write", - "analyst:tickettype:read", - "analyst:user:read", - "engineer:automation:write", - "engineer:playbook:write", - "engineer:rule:write", - "engineer:template:write", - "engineer:tickettype:write" - ] - } - } - } - } - }, - "put": { - "security": [ - { - "roles": [ - "user:write" - ] - } - ], - "tags": [ - "users" - ], - "summary": "Update user", - "operationId": "updateUser", - "parameters": [ - { - "type": "string", - "x-example": "bob", - "description": "Template ID", - "name": "id", - "in": "path", - "required": true - }, - { - "x-example": { - "roles": [ - "analyst", - "admin" - ] - }, - "description": "user object that needs to be added", - "name": "user", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/UserForm" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/UserResponse" - }, - "examples": { - "test": { - "apikey": false, - "blocked": false, - "id": "bob", - "roles": [ - "admin:backup:read", - "admin:backup:restore", - "admin:group:write", - "admin:job:read", - "admin:job:write", - "admin:log:read", - "admin:ticket:delete", - "admin:user:write", - "admin:userdata:read", - "admin:userdata:write", - "analyst:automation:read", - "analyst:currentsettings:write", - "analyst:currentuser:read", - "analyst:currentuserdata:read", - "analyst:file", - "analyst:group:read", - "analyst:playbook:read", - "analyst:rule:read", - "analyst:settings:read", - "analyst:template:read", - "analyst:ticket:read", - "analyst:ticket:write", - "analyst:tickettype:read", - "analyst:user:read", - "engineer:automation:write", - "engineer:playbook:write", - "engineer:rule:write", - "engineer:template:write", - "engineer:tickettype:write" - ] - } - } - } - } - }, - "delete": { - "security": [ - { - "roles": [ - "user:write" - ] - } - ], - "tags": [ - "users" - ], - "summary": "Delete user", - "operationId": "deleteUser", - "parameters": [ - { - "type": "string", - "x-example": "script", - "description": "user ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "204": { - "description": "successful operation" - } - } - } - } - }, - "definitions": { - "Artifact": { - "type": "object", - "required": [ - "name" - ], - "properties": { - "enrichments": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/Enrichment" - } - }, - "name": { - "type": "string", - "example": "2.2.2.2" - }, - "status": { - "type": "string", - "example": "Unknown" - }, - "type": { - "type": "string" - } - } - }, - "ArtifactOrigin": { - "type": "object", - "required": [ - "ticket_id", - "artifact" - ], - "properties": { - "artifact": { - "type": "string" - }, - "ticket_id": { - "type": "integer", - "format": "int64" - } - } - }, - "Automation": { - "type": "object", - "required": [ - "image", - "script", - "type" - ], - "properties": { - "image": { - "type": "string" - }, - "schema": { - "type": "string", - "example": "{}" - }, - "script": { - "type": "string" - }, - "type": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "artifact", - "playbook", - "global" - ] - } - } - } - }, - "AutomationForm": { - "type": "object", - "required": [ - "id", - "image", - "script", - "type" - ], - "properties": { - "id": { - "type": "string" - }, - "image": { - "type": "string" - }, - "schema": { - "type": "string", - "example": "{}" - }, - "script": { - "type": "string" - }, - "type": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "artifact", - "playbook", - "global" - ] - } - } - } - }, - "AutomationResponse": { - "type": "object", - "required": [ - "id", - "image", - "script", - "type" - ], - "properties": { - "id": { - "type": "string" - }, - "image": { - "type": "string" - }, - "schema": { - "type": "string", - "example": "{}" - }, - "script": { - "type": "string" - }, - "type": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "artifact", - "playbook", - "global" - ] - } - } - } - }, - "Comment": { - "type": "object", - "required": [ - "creator", - "created", - "message" - ], - "properties": { - "created": { - "type": "string", - "format": "date-time" - }, - "creator": { - "type": "string" - }, - "message": { - "type": "string" - } - } - }, - "CommentForm": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "created": { - "type": "string", - "format": "date-time" - }, - "creator": { - "type": "string" - }, - "message": { - "type": "string" - } - } - }, - "Context": { - "type": "object", - "properties": { - "artifact": { - "$ref": "#/definitions/Artifact" - }, - "playbook": { - "$ref": "#/definitions/PlaybookResponse" - }, - "task": { - "$ref": "#/definitions/TaskResponse" - }, - "ticket": { - "$ref": "#/definitions/TicketResponse" - } - } - }, - "Enrichment": { - "type": "object", - "required": [ - "name", - "data", - "created" - ], - "properties": { - "created": { - "type": "string", - "format": "date-time", - "example": "1985-04-12T23:20:50.52Z" - }, - "data": { - "type": "object", - "example": { - "hash": "b7a067a742c20d07a7456646de89bc2d408a1153" - } - }, - "name": { - "type": "string", - "example": "hash.sha1" - } - } - }, - "EnrichmentForm": { - "type": "object", - "required": [ - "name", - "data" - ], - "properties": { - "data": { - "type": "object", - "example": { - "hash": "b7a067a742c20d07a7456646de89bc2d408a1153" - } - }, - "name": { - "type": "string", - "example": "hash.sha1" - } - } - }, - "File": { - "type": "object", - "required": [ - "key", - "name" - ], - "properties": { - "key": { - "type": "string", - "example": "myfile" - }, - "name": { - "type": "string", - "example": "notes.docx" - } - } - }, - "Job": { - "type": "object", - "required": [ - "automation", - "running", - "status" - ], - "properties": { - "automation": { - "type": "string" - }, - "container": { - "type": "string" - }, - "log": { - "type": "string" - }, - "origin": { - "$ref": "#/definitions/Origin" - }, - "output": { - "type": "object" - }, - "payload": {}, - "running": { - "type": "boolean" - }, - "status": { - "type": "string" - } - } - }, - "JobForm": { - "type": "object", - "required": [ - "automation" - ], - "properties": { - "automation": { - "type": "string" - }, - "origin": { - "$ref": "#/definitions/Origin" - }, - "payload": {} - } - }, - "JobResponse": { - "type": "object", - "required": [ - "id", - "automation", - "status" - ], - "properties": { - "automation": { - "type": "string" - }, - "container": { - "type": "string" - }, - "id": { - "type": "string" - }, - "log": { - "type": "string" - }, - "origin": { - "$ref": "#/definitions/Origin" - }, - "output": { - "type": "object" - }, - "payload": {}, - "status": { - "type": "string" - } - } - }, - "LogEntry": { - "type": "object", - "required": [ - "type", - "reference", - "creator", - "created", - "message" - ], - "properties": { - "created": { - "type": "string", - "format": "date-time" - }, - "creator": { - "type": "string" - }, - "message": { - "type": "string" - }, - "reference": { - "type": "string" - }, - "type": { - "type": "string" - } - } - }, - "Message": { - "type": "object", - "properties": { - "context": { - "$ref": "#/definitions/Context" - }, - "payload": { - "type": "object" - }, - "secrets": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - } - }, - "NewUserResponse": { - "type": "object", - "required": [ - "id", - "blocked", - "roles" - ], - "properties": { - "blocked": { - "type": "boolean" - }, - "id": { - "type": "string" - }, - "roles": { - "type": "array", - "items": { - "type": "string" - } - }, - "secret": { - "type": "string" - } - } - }, - "Origin": { - "type": "object", - "properties": { - "artifact_origin": { - "$ref": "#/definitions/ArtifactOrigin" - }, - "task_origin": { - "$ref": "#/definitions/TaskOrigin" - } - } - }, - "Playbook": { - "type": "object", - "required": [ - "name", - "tasks" - ], - "properties": { - "name": { - "type": "string", - "example": "Phishing" - }, - "tasks": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/Task" - } - } - } - }, - "PlaybookResponse": { - "type": "object", - "required": [ - "name", - "tasks" - ], - "properties": { - "name": { - "type": "string", - "example": "Phishing" - }, - "tasks": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/TaskResponse" - } - } - } - }, - "PlaybookTemplate": { - "type": "object", - "required": [ - "name", - "yaml" - ], - "properties": { - "name": { - "type": "string" - }, - "yaml": { - "type": "string" - } - } - }, - "PlaybookTemplateForm": { - "type": "object", - "required": [ - "yaml" - ], - "properties": { - "id": { - "type": "string" - }, - "yaml": { - "type": "string" - } - } - }, - "PlaybookTemplateResponse": { - "type": "object", - "required": [ - "id", - "name", - "yaml" - ], - "properties": { - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "yaml": { - "type": "string" - } - } - }, - "Reference": { - "type": "object", - "required": [ - "name", - "href" - ], - "properties": { - "href": { - "type": "string", - "example": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=cve-2017-0144" - }, - "name": { - "type": "string", - "example": "CVE-2017-0144" - } - } - }, - "Settings": { - "type": "object", - "required": [ - "version", - "tier", - "timeformat", - "ticketTypes", - "artifactStates" - ], - "properties": { - "artifactStates": { - "type": "array", - "title": "Artifact States", - "items": { - "$ref": "#/definitions/Type" - } - }, - "roles": { - "type": "array", - "title": "Roles", - "items": { - "type": "string" - } - }, - "ticketTypes": { - "type": "array", - "title": "Ticket Types", - "items": { - "$ref": "#/definitions/TicketTypeResponse" - } - }, - "tier": { - "type": "string", - "title": "Tier", - "enum": [ - "community", - "enterprise" - ] - }, - "timeformat": { - "type": "string", - "title": "Time Format" - }, - "version": { - "type": "string", - "title": "Version" - } - } - }, - "Statistics": { - "type": "object", - "required": [ - "unassigned", - "open_tickets_per_user", - "tickets_per_week", - "tickets_per_type" - ], - "properties": { - "open_tickets_per_user": { - "type": "object", - "additionalProperties": { - "type": "integer" - } - }, - "tickets_per_type": { - "type": "object", - "additionalProperties": { - "type": "integer" - } - }, - "tickets_per_week": { - "type": "object", - "additionalProperties": { - "type": "integer" - } - }, - "unassigned": { - "type": "integer" - } - } - }, - "Task": { - "type": "object", - "required": [ - "name", - "type", - "done", - "created" - ], - "properties": { - "automation": { - "type": "string" - }, - "closed": { - "type": "string", - "format": "date-time", - "example": "1985-04-12T23:20:50.52Z" - }, - "created": { - "type": "string", - "format": "date-time", - "example": "1985-04-12T23:20:50.52Z" - }, - "data": { - "type": "object" - }, - "done": { - "type": "boolean" - }, - "join": { - "type": "boolean", - "example": false - }, - "name": { - "type": "string", - "example": "Inform user" - }, - "next": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "owner": { - "type": "string" - }, - "payload": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "schema": { - "type": "object" - }, - "type": { - "type": "string", - "enum": [ - "task", - "input", - "automation" - ], - "example": "task" - } - } - }, - "TaskForm": { - "type": "object", - "required": [ - "name", - "type" - ], - "properties": { - "automation": { - "type": "string" - }, - "closed": { - "type": "string", - "format": "date-time", - "example": "1985-04-12T23:20:50.52Z" - }, - "created": { - "type": "string", - "format": "date-time", - "example": "1985-04-12T23:20:50.52Z" - }, - "data": { - "type": "object" - }, - "done": { - "type": "boolean" - }, - "join": { - "type": "boolean", - "example": false - }, - "name": { - "type": "string", - "example": "Inform user" - }, - "next": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "owner": { - "type": "string" - }, - "payload": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "schema": { - "type": "object" - }, - "type": { - "type": "string", - "enum": [ - "task", - "input", - "automation" - ], - "example": "task" - } - } - }, - "TaskOrigin": { - "type": "object", - "required": [ - "ticket_id", - "playbook_id", - "task_id" - ], - "properties": { - "playbook_id": { - "type": "string" - }, - "task_id": { - "type": "string" - }, - "ticket_id": { - "type": "integer", - "format": "int64" - } - } - }, - "TaskResponse": { - "type": "object", - "required": [ - "name", - "type", - "done", - "created", - "order", - "active" - ], - "properties": { - "active": { - "type": "boolean", - "example": false - }, - "automation": { - "type": "string" - }, - "closed": { - "type": "string", - "format": "date-time", - "example": "1985-04-12T23:20:50.52Z" - }, - "created": { - "type": "string", - "format": "date-time", - "example": "1985-04-12T23:20:50.52Z" - }, - "data": { - "type": "object" - }, - "done": { - "type": "boolean" - }, - "join": { - "type": "boolean", - "example": false - }, - "name": { - "type": "string", - "example": "Inform user" - }, - "next": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "order": { - "type": "number", - "format": "int64", - "example": 2 - }, - "owner": { - "type": "string" - }, - "payload": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "schema": { - "type": "object" - }, - "type": { - "type": "string", - "enum": [ - "task", - "input", - "automation" - ], - "example": "task" - } - } - }, - "TaskWithContext": { - "type": "object", - "required": [ - "ticket_id", - "ticket_name", - "playbook_id", - "playbook_name", - "task_id", - "task" - ], - "properties": { - "playbook_id": { - "type": "string" - }, - "playbook_name": { - "type": "string" - }, - "task": { - "$ref": "#/definitions/TaskResponse" - }, - "task_id": { - "type": "string" - }, - "ticket_id": { - "type": "number", - "format": "int64" - }, - "ticket_name": { - "type": "string" - } - } - }, - "Ticket": { - "type": "object", - "required": [ - "name", - "type", - "status", - "created", - "modified", - "schema" - ], - "properties": { - "artifacts": { - "type": "array", - "items": { - "$ref": "#/definitions/Artifact" - } - }, - "comments": { - "type": "array", - "items": { - "$ref": "#/definitions/Comment" - } - }, - "created": { - "type": "string", - "format": "date-time", - "example": "1985-04-12T23:20:50.52Z" - }, - "details": { - "type": "object", - "example": { - "description": "my little incident" - } - }, - "files": { - "type": "array", - "items": { - "$ref": "#/definitions/File" - } - }, - "modified": { - "type": "string", - "format": "date-time", - "example": "1985-04-12T23:20:50.52Z" - }, - "name": { - "type": "string", - "example": "WannyCry" - }, - "owner": { - "type": "string", - "example": "bob" - }, - "playbooks": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/Playbook" - } - }, - "read": { - "type": "array", - "items": { - "type": "string" - }, - "example": [ - "bob" - ] - }, - "references": { - "type": "array", - "items": { - "$ref": "#/definitions/Reference" - } - }, - "schema": { - "type": "string", - "example": "{}" - }, - "status": { - "type": "string", - "example": "open" - }, - "type": { - "type": "string", - "example": "incident" - }, - "write": { - "type": "array", - "items": { - "type": "string" - }, - "example": [ - "alice" - ] - } - } - }, - "TicketForm": { - "type": "object", - "required": [ - "name", - "type", - "status" - ], - "properties": { - "artifacts": { - "type": "array", - "items": { - "$ref": "#/definitions/Artifact" - } - }, - "comments": { - "type": "array", - "items": { - "$ref": "#/definitions/Comment" - } - }, - "created": { - "type": "string", - "format": "date-time", - "example": "1985-04-12T23:20:50.52Z" - }, - "details": { - "type": "object", - "example": { - "description": "my little incident" - } - }, - "files": { - "type": "array", - "items": { - "$ref": "#/definitions/File" - } - }, - "id": { - "type": "integer", - "format": "int64", - "example": 123 - }, - "modified": { - "type": "string", - "format": "date-time", - "example": "1985-04-12T23:20:50.52Z" - }, - "name": { - "type": "string", - "example": "WannyCry" - }, - "owner": { - "type": "string", - "example": "bob" - }, - "playbooks": { - "type": "array", - "items": { - "$ref": "#/definitions/PlaybookTemplateForm" - } - }, - "read": { - "type": "array", - "items": { - "type": "string" - }, - "example": [ - "bob" - ] - }, - "references": { - "type": "array", - "items": { - "$ref": "#/definitions/Reference" - } - }, - "schema": { - "type": "string", - "example": "{}" - }, - "status": { - "type": "string", - "example": "open" - }, - "type": { - "type": "string", - "example": "incident" - }, - "write": { - "type": "array", - "items": { - "type": "string" - }, - "example": [ - "alice" - ] - } - } - }, - "TicketList": { - "type": "object", - "required": [ - "tickets", - "count" - ], - "properties": { - "count": { - "type": "number", - "example": 3 - }, - "tickets": { - "type": "array", - "items": { - "$ref": "#/definitions/TicketSimpleResponse" - } - } - } - }, - "TicketResponse": { - "type": "object", - "required": [ - "id", - "name", - "type", - "status", - "created", - "modified", - "schema" - ], - "properties": { - "artifacts": { - "type": "array", - "items": { - "$ref": "#/definitions/Artifact" - } - }, - "comments": { - "type": "array", - "items": { - "$ref": "#/definitions/Comment" - } - }, - "created": { - "type": "string", - "format": "date-time", - "example": "1985-04-12T23:20:50.52Z" - }, - "details": { - "type": "object", - "example": { - "description": "my little incident" - } - }, - "files": { - "type": "array", - "items": { - "$ref": "#/definitions/File" - } - }, - "id": { - "type": "integer", - "format": "int64", - "example": 123 - }, - "modified": { - "type": "string", - "format": "date-time", - "example": "1985-04-12T23:20:50.52Z" - }, - "name": { - "type": "string", - "example": "WannyCry" - }, - "owner": { - "type": "string", - "example": "bob" - }, - "playbooks": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/PlaybookResponse" - } - }, - "read": { - "type": "array", - "items": { - "type": "string" - }, - "example": [ - "bob" - ] - }, - "references": { - "type": "array", - "items": { - "$ref": "#/definitions/Reference" - } - }, - "schema": { - "type": "string", - "example": "{}" - }, - "status": { - "type": "string", - "example": "open" - }, - "type": { - "type": "string", - "example": "incident" - }, - "write": { - "type": "array", - "items": { - "type": "string" - }, - "example": [ - "alice" - ] - } - } - }, - "TicketSimpleResponse": { - "type": "object", - "required": [ - "id", - "name", - "type", - "status", - "created", - "modified", - "schema" - ], - "properties": { - "artifacts": { - "type": "array", - "items": { - "$ref": "#/definitions/Artifact" - } - }, - "comments": { - "type": "array", - "items": { - "$ref": "#/definitions/Comment" - } - }, - "created": { - "type": "string", - "format": "date-time", - "example": "1985-04-12T23:20:50.52Z" - }, - "details": { - "type": "object", - "example": { - "description": "my little incident" - } - }, - "files": { - "type": "array", - "items": { - "$ref": "#/definitions/File" - } - }, - "id": { - "type": "integer", - "format": "int64", - "example": 123 - }, - "modified": { - "type": "string", - "format": "date-time", - "example": "1985-04-12T23:20:50.52Z" - }, - "name": { - "type": "string", - "example": "WannyCry" - }, - "owner": { - "type": "string", - "example": "bob" - }, - "playbooks": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/Playbook" - } - }, - "read": { - "type": "array", - "items": { - "type": "string" - }, - "example": [ - "bob" - ] - }, - "references": { - "type": "array", - "items": { - "$ref": "#/definitions/Reference" - } - }, - "schema": { - "type": "string", - "example": "{}" - }, - "status": { - "type": "string", - "example": "open" - }, - "type": { - "type": "string", - "example": "incident" - }, - "write": { - "type": "array", - "items": { - "type": "string" - }, - "example": [ - "alice" - ] - } - } - }, - "TicketTemplate": { - "type": "object", - "required": [ - "name", - "schema" - ], - "properties": { - "name": { - "type": "string" - }, - "schema": { - "type": "string" - } - } - }, - "TicketTemplateForm": { - "type": "object", - "required": [ - "name", - "schema" - ], - "properties": { - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "schema": { - "type": "string" - } - } - }, - "TicketTemplateResponse": { - "type": "object", - "required": [ - "id", - "name", - "schema" - ], - "properties": { - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "schema": { - "type": "string" - } - } - }, - "TicketType": { - "type": "object", - "required": [ - "name", - "icon", - "default_template", - "default_playbooks" - ], - "properties": { - "default_groups": { - "type": "array", - "items": { - "type": "string" - } - }, - "default_playbooks": { - "type": "array", - "items": { - "type": "string" - } - }, - "default_template": { - "type": "string" - }, - "icon": { - "type": "string" - }, - "name": { - "type": "string" - } - } - }, - "TicketTypeForm": { - "type": "object", - "required": [ - "name", - "icon", - "default_template", - "default_playbooks" - ], - "properties": { - "default_groups": { - "type": "array", - "items": { - "type": "string" - } - }, - "default_playbooks": { - "type": "array", - "items": { - "type": "string" - } - }, - "default_template": { - "type": "string" - }, - "icon": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - } - } - }, - "TicketTypeResponse": { - "type": "object", - "required": [ - "id", - "name", - "icon", - "default_template", - "default_playbooks" - ], - "properties": { - "default_groups": { - "type": "array", - "items": { - "type": "string" - } - }, - "default_playbooks": { - "type": "array", - "items": { - "type": "string" - } - }, - "default_template": { - "type": "string" - }, - "icon": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - } - } - }, - "TicketWithTickets": { - "type": "object", - "required": [ - "id", - "name", - "type", - "status", - "created", - "modified", - "schema" - ], - "properties": { - "artifacts": { - "type": "array", - "items": { - "$ref": "#/definitions/Artifact" - } - }, - "comments": { - "type": "array", - "items": { - "$ref": "#/definitions/Comment" - } - }, - "created": { - "type": "string", - "format": "date-time", - "example": "1985-04-12T23:20:50.52Z" - }, - "details": { - "type": "object", - "example": { - "description": "my little incident" - } - }, - "files": { - "type": "array", - "items": { - "$ref": "#/definitions/File" - } - }, - "id": { - "type": "integer", - "format": "int64", - "example": 123 - }, - "logs": { - "type": "array", - "items": { - "$ref": "#/definitions/LogEntry" - } - }, - "modified": { - "type": "string", - "format": "date-time", - "example": "1985-04-12T23:20:50.52Z" - }, - "name": { - "type": "string", - "example": "WannyCry" - }, - "owner": { - "type": "string", - "example": "bob" - }, - "playbooks": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/PlaybookResponse" - } - }, - "read": { - "type": "array", - "items": { - "type": "string" - }, - "example": [ - "bob" - ] - }, - "references": { - "type": "array", - "items": { - "$ref": "#/definitions/Reference" - } - }, - "schema": { - "type": "string", - "example": "{}" - }, - "status": { - "type": "string", - "example": "open" - }, - "tickets": { - "type": "array", - "items": { - "$ref": "#/definitions/TicketSimpleResponse" - } - }, - "type": { - "type": "string", - "example": "incident" - }, - "write": { - "type": "array", - "items": { - "type": "string" - }, - "example": [ - "alice" - ] - } - } - }, - "Type": { - "type": "object", - "required": [ - "id", - "name", - "icon" - ], - "properties": { - "color": { - "type": "string", - "title": "Color", - "enum": [ - "error", - "info", - "success", - "warning" - ], - "x-cols": 3 - }, - "icon": { - "type": "string", - "title": "Icon (https://materialdesignicons.com)", - "x-class": "pr-2", - "x-cols": 3 - }, - "id": { - "type": "string", - "title": "ID", - "x-class": "pr-2", - "x-cols": 3 - }, - "name": { - "type": "string", - "title": "Name", - "x-class": "pr-2", - "x-cols": 3 - } - } - }, - "User": { - "type": "object", - "required": [ - "blocked", - "apikey", - "roles" - ], - "properties": { - "apikey": { - "type": "boolean" - }, - "blocked": { - "type": "boolean" - }, - "roles": { - "type": "array", - "items": { - "type": "string" - } - }, - "sha256": { - "type": "string" - } - } - }, - "UserData": { - "type": "object", - "properties": { - "email": { - "type": "string", - "x-example": "bob@example.org" - }, - "image": { - "type": "string", - "x-display": "custom-avatar" - }, - "name": { - "type": "string", - "x-example": "Robert Smith" - }, - "timeformat": { - "type": "string", - "title": "Time Format (https://moment.github.io/luxon/docs/manual/formatting.html#table-of-tokens)" - } - } - }, - "UserDataResponse": { - "type": "object", - "required": [ - "id" - ], - "properties": { - "email": { - "type": "string", - "x-example": "bob@example.org" - }, - "id": { - "type": "string" - }, - "image": { - "type": "string", - "x-display": "custom-avatar" - }, - "name": { - "type": "string", - "x-example": "Robert Smith" - }, - "timeformat": { - "type": "string", - "title": "Time Format (https://moment.github.io/luxon/docs/manual/formatting.html#table-of-tokens)" - } - } - }, - "UserForm": { - "type": "object", - "required": [ - "id", - "blocked", - "roles", - "apikey" - ], - "properties": { - "apikey": { - "type": "boolean" - }, - "blocked": { - "type": "boolean" - }, - "id": { - "type": "string" - }, - "roles": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "UserResponse": { - "type": "object", - "required": [ - "id", - "blocked", - "roles", - "apikey" - ], - "properties": { - "apikey": { - "type": "boolean" - }, - "blocked": { - "type": "boolean" - }, - "id": { - "type": "string" - }, - "roles": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - } -}`)) - FlatSwaggerJSON = json.RawMessage([]byte(`{ - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "schemes": [ - "http" - ], - "swagger": "2.0", - "info": { - "description": "API for the catalyst incident response platform." - }, - "host": ".", - "basePath": "/api", - "paths": { - "/automations": { - "get": { - "security": [ - { - "roles": [ - "automation:read" - ] - } - ], - "tags": [ - "automations" - ], - "summary": "List automations", - "operationId": "listAutomations", - "responses": { - "200": { - "description": "successful operation", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/AutomationResponse" - } - }, - "examples": { - "test": [ - { - "id": "comment", - "image": "docker.io/python:3", - "script": "", - "type": [ - "playbook" - ] - }, - { - "id": "hash.sha1", - "image": "docker.io/python:3", - "schema": "{\"title\":\"Input\",\"type\":\"object\",\"properties\":{\"default\":{\"type\":\"string\",\"title\":\"Value\"}},\"required\":[\"default\"]}", - "script": "", - "type": [ - "global", - "artifact", - "playbook" - ] - }, - { - "id": "thehive", - "image": "docker.io/python:3", - "schema": "{\"title\":\"TheHive credentials\",\"type\":\"object\",\"properties\":{\"thehiveurl\":{\"type\":\"string\",\"title\":\"TheHive URL (e.g. 'https://thehive.example.org')\"},\"thehivekey\":{\"type\":\"string\",\"title\":\"TheHive API Key\"},\"skip_files\":{\"type\":\"boolean\", \"default\": true, \"title\":\"Skip Files (much faster)\"},\"keep_ids\":{\"type\":\"boolean\", \"default\": true, \"title\":\"Keep IDs and overwrite existing IDs\"}},\"required\":[\"thehiveurl\", \"thehivekey\", \"skip_files\", \"keep_ids\"]}", - "script": "", - "type": [ - "global" - ] - }, - { - "id": "vt.hash", - "image": "docker.io/python:3", - "schema": "{\"title\":\"Input\",\"type\":\"object\",\"properties\":{\"default\":{\"type\":\"string\",\"title\":\"Value\"}},\"required\":[\"default\"]}", - "script": "", - "type": [ - "global", - "artifact", - "playbook" - ] - } - ] - } - } - } - }, - "post": { - "security": [ - { - "roles": [ - "automation:write" - ] - } - ], - "tags": [ - "automations" - ], - "summary": "Create a new automation", - "operationId": "createAutomation", - "parameters": [ - { - "x-example": { - "id": "hash-sha-256", - "image": "docker.io/python:3", - "script": "import sys\nimport json\nimport hashlib\n\n\ndef run(msg):\n sha256 = hashlib.sha256(msg['payload']['default'].encode('utf-8'))\n return {'hash': sha256.hexdigest()}\n\n\nprint(json.dumps(run(json.loads(sys.argv[1]))))\n", - "type": [ - "global" - ] - }, - "description": "New automation", - "name": "automation", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/AutomationForm" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/AutomationResponse" - }, - "examples": { - "test": { - "id": "hash-sha-256", - "image": "docker.io/python:3", - "script": "import sys\nimport json\nimport hashlib\n\n\ndef run(msg):\n sha256 = hashlib.sha256(msg['payload']['default'].encode('utf-8'))\n return {'hash': sha256.hexdigest()}\n\n\nprint(json.dumps(run(json.loads(sys.argv[1]))))\n", - "type": [ - "global" - ] - } - } - } - } - } - }, - "/automations/{id}": { - "get": { - "security": [ - { - "roles": [ - "automation:read" - ] - } - ], - "tags": [ - "automations" - ], - "summary": "Get a single automation", - "operationId": "getAutomation", - "parameters": [ - { - "type": "string", - "x-example": "hash.sha1", - "description": "Automation ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/AutomationResponse" - }, - "examples": { - "test": { - "id": "hash.sha1", - "image": "docker.io/python:3", - "schema": "{\"title\":\"Input\",\"type\":\"object\",\"properties\":{\"default\":{\"type\":\"string\",\"title\":\"Value\"}},\"required\":[\"default\"]}", - "script": "#!/usr/bin/env python\n\nimport sys\nimport json\nimport hashlib\n\n\ndef run(msg):\n sha1 = hashlib.sha1(msg['payload']['default'].encode('utf-8'))\n return {\"hash\": sha1.hexdigest()}\n\n\nprint(json.dumps(run(json.loads(sys.argv[1]))))\n", - "type": [ - "global", - "artifact", - "playbook" - ] - } - } - } - } - }, - "put": { - "security": [ - { - "roles": [ - "automation:write" - ] - } - ], - "tags": [ - "automations" - ], - "summary": "Update an existing automation", - "operationId": "updateAutomation", - "parameters": [ - { - "type": "string", - "x-example": "hash.sha1", - "description": "Automation ID", - "name": "id", - "in": "path", - "required": true - }, - { - "x-example": { - "id": "hash.sha1", - "image": "docker.io/python:3", - "script": "import sys\nimport json\nimport hashlib\n\n\ndef run(msg):\n sha1 = hashlib.sha1(msg['payload'].encode('utf-8'))\n return {'hash': sha1.hexdigest()}\n\n\nprint(json.dumps(run(json.loads(sys.argv[1]))))\n", - "type": [ - "global", - "artifact", - "playbook" - ] - }, - "description": "Automation object that needs to be added", - "name": "automation", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/AutomationForm" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/AutomationResponse" - }, - "examples": { - "test": { - "id": "hash.sha1", - "image": "docker.io/python:3", - "script": "import sys\nimport json\nimport hashlib\n\n\ndef run(msg):\n sha1 = hashlib.sha1(msg['payload'].encode('utf-8'))\n return {'hash': sha1.hexdigest()}\n\n\nprint(json.dumps(run(json.loads(sys.argv[1]))))\n", - "type": [ - "global", - "artifact", - "playbook" - ] - } - } - } - } - }, - "delete": { - "security": [ - { - "roles": [ - "automation:write" - ] - } - ], - "tags": [ - "automations" - ], - "summary": "Delete a automation", - "operationId": "deleteAutomation", - "parameters": [ - { - "type": "string", - "x-example": "hash.sha1", - "description": "Automation ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "204": { - "description": "successful operation" - } - } - } - }, - "/currentuser": { - "get": { - "security": [ - { - "roles": [ - "currentuser:read" - ] - } - ], - "tags": [ - "users" - ], - "summary": "Get current user", - "operationId": "currentUser", - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/UserResponse" - }, - "examples": { - "test": { - "apikey": false, - "blocked": false, - "id": "bob", - "roles": [ - "admin:backup:read", - "admin:backup:restore", - "admin:group:write", - "admin:job:read", - "admin:job:write", - "admin:log:read", - "admin:ticket:delete", - "admin:user:write", - "admin:userdata:read", - "admin:userdata:write", - "analyst:automation:read", - "analyst:currentsettings:write", - "analyst:currentuser:read", - "analyst:currentuserdata:read", - "analyst:file", - "analyst:group:read", - "analyst:playbook:read", - "analyst:rule:read", - "analyst:settings:read", - "analyst:template:read", - "analyst:ticket:read", - "analyst:ticket:write", - "analyst:tickettype:read", - "analyst:user:read", - "engineer:automation:write", - "engineer:playbook:write", - "engineer:rule:write", - "engineer:template:write", - "engineer:tickettype:write" - ] - } - } - } - } - } - }, - "/currentuserdata": { - "get": { - "security": [ - { - "roles": [ - "currentuserdata:read" - ] - } - ], - "tags": [ - "userdata" - ], - "summary": "Get current user data", - "operationId": "currentUserData", - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/UserDataResponse" - }, - "examples": { - "test": { - "email": "bob@example.org", - "id": "bob", - "name": "Bob Bad" - } - } - } - } - }, - "put": { - "security": [ - { - "roles": [ - "currentuserdata:write" - ] - } - ], - "tags": [ - "userdata" - ], - "summary": "Update current user data", - "operationId": "updateCurrentUserData", - "parameters": [ - { - "x-example": { - "email": "bob@example.org", - "name": "Bob Bad" - }, - "description": "User data object that needs to be added", - "name": "userdata", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/UserData" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/UserDataResponse" - }, - "examples": { - "test": { - "email": "bob@example.org", - "id": "bob", - "name": "Bob Bad" - } - } - } - } - } - }, - "/jobs": { - "get": { - "security": [ - { - "roles": [ - "job:read" - ] - } - ], - "tags": [ - "jobs" - ], - "summary": "List jobs", - "operationId": "listJobs", - "responses": { - "200": { - "description": "successful operation", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/JobResponse" - } - }, - "examples": { - "test": [ - { - "automation": "hash.sha1", - "id": "99cd67131b48", - "payload": "test", - "status": "created" - } - ] - } - } - } - }, - "post": { - "security": [ - { - "roles": [ - "job:write" - ] - } - ], - "tags": [ - "jobs" - ], - "summary": "Start a new job", - "operationId": "runJob", - "parameters": [ - { - "x-example": { - "automation": "hash.sha1", - "message": { - "payload": "test" - } - }, - "description": "New job", - "name": "job", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/JobForm" - } - } - ], - "responses": { - "204": { - "description": "successful operation" - } - } - } - }, - "/jobs/{id}": { - "get": { - "security": [ - { - "roles": [ - "job:read" - ] - } - ], - "tags": [ - "jobs" - ], - "summary": "Get a single job", - "operationId": "getJob", - "parameters": [ - { - "type": "string", - "x-example": "99cd67131b48", - "description": "Job ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/JobResponse" - }, - "examples": { - "test": { - "automation": "hash.sha1", - "id": "99cd67131b48", - "payload": "test", - "status": "created" - } - } - } - } - }, - "put": { - "security": [ - { - "roles": [ - "job:write" - ] - } - ], - "tags": [ - "jobs" - ], - "summary": "Update an existing job", - "operationId": "updateJob", - "parameters": [ - { - "type": "string", - "x-example": "99cd67131b48", - "description": "Job ID", - "name": "id", - "in": "path", - "required": true - }, - { - "x-example": { - "automation": "hash.sha1", - "id": "99cd67131b48", - "payload": "test", - "status": "failed" - }, - "description": "Job object that needs to be added", - "name": "job", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/Job" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/JobResponse" - }, - "examples": { - "test": { - "automation": "hash.sha1", - "id": "99cd67131b48", - "payload": "test", - "status": "failed" - } - } - } - } - } - }, - "/logs/{reference}": { - "get": { - "security": [ - { - "roles": [ - "log:read" - ] - } - ], - "tags": [ - "logs" - ], - "summary": "Get log entries", - "operationId": "getLogs", - "parameters": [ - { - "type": "string", - "x-example": "tickets%2F294511", - "description": "Reference", - "name": "reference", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/LogEntry" - } - }, - "examples": { - "test": [ - { - "created": "2021-12-12T12:12:12.000000012Z", - "creator": "bob", - "message": "Fail run account resist lend solve incident centre priority temperature. Cause change distribution examine location technique shape partner milk customer. Rail tea plate soil report cook railway interpretation breath action. Exercise dream accept park conclusion addition shoot assistance may answer. Gold writer link stop combine hear power name commitment operation. Determine lifespan support grow degree henry exclude detail set religion. Direct library policy convention chain retain discover ride walk student. Gather proposal select march aspect play noise avoid encourage employ. Assessment preserve transport combine wish influence income guess run stand. Charge limit crime ignore statement foundation study issue stop claim.", - "reference": "tickets/294511", - "type": "manual" - } - ] - } - } - } - } - }, - "/playbooks": { - "get": { - "security": [ - { - "roles": [ - "playbook:read" - ] - } - ], - "tags": [ - "playbooks" - ], - "summary": "List playbooks", - "operationId": "listPlaybooks", - "responses": { - "200": { - "description": "successful operation", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/PlaybookTemplateResponse" - } - }, - "examples": { - "test": [ - { - "id": "malware", - "name": "Malware", - "yaml": "name: Malware\ntasks:\n file-or-hash:\n name: Do you have the file or the hash?\n type: input\n schema:\n title: Malware\n type: object\n properties:\n file:\n type: string\n title: \"I have the\"\n enum: [ \"File\", \"Hash\" ]\n next:\n enter-hash: \"file == 'Hash'\"\n upload: \"file == 'File'\"\n\n enter-hash:\n name: Please enter the hash\n type: input\n schema:\n title: Malware\n type: object\n properties:\n hash:\n type: string\n title: Please enter the hash value\n minlength: 32\n next:\n virustotal: \"hash != ''\"\n\n upload:\n name: Upload the malware\n type: input\n schema:\n title: Malware\n type: object\n properties:\n malware:\n type: object\n x-display: file\n title: Please upload the malware\n next:\n hash: \"malware\"\n\n hash:\n name: Hash the malware\n type: automation\n automation: hash.sha1\n payload:\n default: \"playbook.tasks['upload'].data['malware']\"\n next:\n virustotal:\n\n virustotal:\n name: Send hash to VirusTotal\n type: automation\n automation: vt.hash\n args:\n hash: \"playbook.tasks['enter-hash'].data['hash'] || playbook.tasks['hash'].data['hash']\"\n # next:\n # known-malware: \"score \u003e 5\"\n # sandbox: \"score \u003c 6\" # unknown-malware\n" - }, - { - "id": "phishing", - "name": "Phishing", - "yaml": "name: Phishing\ntasks:\n board:\n name: Board Involvement?\n description: Is a board member involved?\n type: input\n schema:\n properties:\n boardInvolved:\n default: false\n title: A board member is involved.\n type: boolean\n required:\n - boardInvolved\n title: Board Involvement?\n type: object\n next:\n escalate: \"boardInvolved == true\"\n mail-available: \"boardInvolved == false\"\n\n escalate:\n name: Escalate to CISO\n description: Please escalate the task to the CISO\n type: task\n\n mail-available:\n name: Mail available\n type: input\n schema:\n oneOf:\n - properties:\n mail:\n title: Mail\n type: string\n x-display: textarea\n schemaKey:\n const: 'yes'\n type: string\n required:\n - mail\n title: 'Yes'\n - properties:\n schemaKey:\n const: 'no'\n type: string\n title: 'No'\n title: Mail available\n type: object\n next:\n block-sender: \"schemaKey == 'yes'\"\n extract-iocs: \"schemaKey == 'yes'\"\n search-email-gateway: \"schemaKey == 'no'\"\n\n search-email-gateway:\n name: Search email gateway\n description: Please search email-gateway for the phishing mail.\n type: task\n next:\n extract-iocs:\n\n block-sender:\n name: Block sender\n type: task\n next:\n extract-iocs:\n\n extract-iocs:\n name: Extract IOCs\n description: Please insert the IOCs\n type: input\n schema:\n properties:\n iocs:\n items:\n type: string\n title: IOCs\n type: array\n title: Extract IOCs\n type: object\n next:\n block-iocs:\n\n block-iocs:\n name: Block IOCs\n type: task\n" - }, - { - "id": "simple", - "name": "Simple", - "yaml": "name: Simple\ntasks:\n input:\n name: Enter something to hash\n type: input\n schema:\n title: Something\n type: object\n properties:\n something:\n type: string\n title: Something\n default: \"\"\n next:\n hash: \"something != ''\"\n\n hash:\n name: Hash the something\n type: automation\n automation: hash.sha1\n payload:\n default: \"playbook.tasks['input'].data['something']\"\n next:\n comment: \"hash != ''\"\n\n comment:\n name: Comment the hash\n type: automation\n automation: comment\n payload:\n default: \"playbook.tasks['hash'].data['hash']\"\n next:\n done: \"done\"\n\n done:\n name: You can close this case now\n type: task\n" - } - ] - } - } - } - }, - "post": { - "security": [ - { - "roles": [ - "playbook:write" - ] - } - ], - "tags": [ - "playbooks" - ], - "summary": "Create a playbook", - "operationId": "createPlaybook", - "parameters": [ - { - "x-example": { - "yaml": "name: Simple2\ntasks:\n input:\n name: Upload malware if possible\n type: input\n schema:\n title: Malware\n type: object\n properties:\n malware:\n type: string\n title: Select malware\n default: \"\"\n next:\n hash: \"malware != ''\"\n\n hash:\n name: Hash the malware\n type: automation\n automation: hash.sha1\n payload:\n default: \"playbook.tasks['input'].data['malware']\"\n next:\n escalate:\n\n escalate:\n name: Escalate to malware team\n type: task\n" - }, - "description": "New playbook", - "name": "playbook", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/PlaybookTemplateForm" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/PlaybookTemplateResponse" - } - }, - "examples": { - "test": { - "id": "simple-2", - "name": "Simple2", - "yaml": "name: Simple2\ntasks:\n input:\n name: Upload malware if possible\n type: input\n schema:\n title: Malware\n type: object\n properties:\n malware:\n type: string\n title: Select malware\n default: \"\"\n next:\n hash: \"malware != ''\"\n\n hash:\n name: Hash the malware\n type: automation\n automation: hash.sha1\n payload:\n default: \"playbook.tasks['input'].data['malware']\"\n next:\n escalate:\n\n escalate:\n name: Escalate to malware team\n type: task\n" - } - } - } - } - } - }, - "/playbooks/{id}": { - "get": { - "security": [ - { - "roles": [ - "playbook:read" - ] - } - ], - "tags": [ - "playbooks" - ], - "summary": "Get a single playbook", - "operationId": "getPlaybook", - "parameters": [ - { - "type": "string", - "x-example": "simple", - "description": "Playbook name", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/PlaybookTemplateResponse" - }, - "examples": { - "test": { - "id": "simple", - "name": "Simple", - "yaml": "name: Simple\ntasks:\n input:\n name: Enter something to hash\n type: input\n schema:\n title: Something\n type: object\n properties:\n something:\n type: string\n title: Something\n default: \"\"\n next:\n hash: \"something != ''\"\n\n hash:\n name: Hash the something\n type: automation\n automation: hash.sha1\n payload:\n default: \"playbook.tasks['input'].data['something']\"\n next:\n comment: \"hash != ''\"\n\n comment:\n name: Comment the hash\n type: automation\n automation: comment\n payload:\n default: \"playbook.tasks['hash'].data['hash']\"\n next:\n done: \"done\"\n\n done:\n name: You can close this case now\n type: task\n" - } - } - } - } - }, - "put": { - "security": [ - { - "roles": [ - "playbook:write" - ] - } - ], - "tags": [ - "playbooks" - ], - "summary": "Update an existing ticket playbook", - "operationId": "updatePlaybook", - "parameters": [ - { - "type": "string", - "x-example": "simple", - "description": "Playbook ID", - "name": "id", - "in": "path", - "required": true - }, - { - "x-example": { - "yaml": "name: Simple\ntasks:\n input:\n name: Upload malware if possible\n type: input\n schema:\n title: Malware\n type: object\n properties:\n malware:\n type: string\n title: Select malware\n default: \"\"\n next:\n hash: \"malware != ''\"\n\n hash:\n name: Hash the malware\n type: automation\n automation: hash.sha1\n payload:\n default: \"playbook.tasks['input'].data['malware']\"\n next:\n escalate:\n\n escalate:\n name: Escalate to malware team\n type: task\n" - }, - "description": "Updated playbook", - "name": "playbook", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/PlaybookTemplateForm" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/PlaybookTemplateResponse" - }, - "examples": { - "test": { - "id": "simple", - "name": "Simple", - "yaml": "name: Simple\ntasks:\n input:\n name: Upload malware if possible\n type: input\n schema:\n title: Malware\n type: object\n properties:\n malware:\n type: string\n title: Select malware\n default: \"\"\n next:\n hash: \"malware != ''\"\n\n hash:\n name: Hash the malware\n type: automation\n automation: hash.sha1\n payload:\n default: \"playbook.tasks['input'].data['malware']\"\n next:\n escalate:\n\n escalate:\n name: Escalate to malware team\n type: task\n" - } - } - } - } - }, - "delete": { - "security": [ - { - "roles": [ - "playbook:write" - ] - } - ], - "tags": [ - "playbooks" - ], - "summary": "Delete a playbook", - "operationId": "deletePlaybook", - "parameters": [ - { - "type": "string", - "x-example": "simple", - "description": "Playbook name", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "204": { - "description": "successful operation" - } - } - } - }, - "/settings": { - "get": { - "security": [ - { - "roles": [ - "settings:read" - ] - } - ], - "tags": [ - "settings" - ], - "summary": "Get settings", - "operationId": "getSettings", - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/Settings" - }, - "examples": { - "test": { - "artifactStates": [ - { - "color": "info", - "icon": "mdi-help-circle-outline", - "id": "unknown", - "name": "Unknown" - }, - { - "color": "error", - "icon": "mdi-skull", - "id": "malicious", - "name": "Malicious" - }, - { - "color": "success", - "icon": "mdi-check", - "id": "clean", - "name": "Clean" - } - ], - "roles": [ - "admin:backup:read", - "admin:backup:restore", - "admin:group:write", - "admin:job:read", - "admin:job:write", - "admin:log:read", - "admin:ticket:delete", - "admin:user:write", - "admin:userdata:read", - "admin:userdata:write", - "analyst:automation:read", - "analyst:currentsettings:write", - "analyst:currentuser:read", - "analyst:currentuserdata:read", - "analyst:file", - "analyst:group:read", - "analyst:playbook:read", - "analyst:rule:read", - "analyst:settings:read", - "analyst:template:read", - "analyst:ticket:read", - "analyst:ticket:write", - "analyst:tickettype:read", - "analyst:user:read", - "engineer:automation:write", - "engineer:playbook:write", - "engineer:rule:write", - "engineer:template:write", - "engineer:tickettype:write" - ], - "ticketTypes": [ - { - "default_playbooks": [], - "default_template": "default", - "icon": "mdi-alert", - "id": "alert", - "name": "Alerts" - }, - { - "default_playbooks": [], - "default_template": "default", - "icon": "mdi-radioactive", - "id": "incident", - "name": "Incidents" - }, - { - "default_playbooks": [], - "default_template": "default", - "icon": "mdi-fingerprint", - "id": "investigation", - "name": "Forensic Investigations" - }, - { - "default_playbooks": [], - "default_template": "default", - "icon": "mdi-target", - "id": "hunt", - "name": "Threat Hunting" - } - ], - "tier": "community", - "timeformat": "YYYY-MM-DDThh:mm:ss", - "version": "0.0.0-test" - } - } - } - } - } - }, - "/statistics": { - "get": { - "security": [ - { - "roles": [ - "ticket:read" - ] - } - ], - "tags": [ - "statistics" - ], - "summary": "Get statistics", - "operationId": "getStatistics", - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/Statistics" - }, - "examples": { - "test": { - "open_tickets_per_user": {}, - "tickets_per_type": { - "alert": 2, - "incident": 1 - }, - "tickets_per_week": { - "2021-39": 3 - }, - "unassigned": 0 - } - } - } - } - } - }, - "/tasks": { - "get": { - "security": [ - { - "roles": [ - "ticket:read" - ] - } - ], - "tags": [ - "tasks" - ], - "summary": "List tasks", - "operationId": "listTasks", - "responses": { - "200": { - "description": "successful operation", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/TaskResponse" - } - }, - "examples": { - "test": [] - } - } - } - } - }, - "/templates": { - "get": { - "security": [ - { - "roles": [ - "template:read" - ] - } - ], - "tags": [ - "templates" - ], - "summary": "List templates", - "operationId": "listTemplates", - "responses": { - "200": { - "description": "successful operation", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/TicketTemplateResponse" - } - }, - "examples": { - "test": [ - { - "id": "default", - "name": "Default", - "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Default\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n" - } - ] - } - } - } - }, - "post": { - "security": [ - { - "roles": [ - "template:write" - ] - } - ], - "tags": [ - "templates" - ], - "summary": "Create a new template", - "operationId": "createTemplate", - "parameters": [ - { - "x-example": { - "name": "My Template", - "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n" - }, - "description": "New template", - "name": "template", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/TicketTemplateForm" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketTemplateResponse" - }, - "examples": { - "test": { - "id": "my-template", - "name": "My Template", - "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n" - } - } - } - } - } - }, - "/templates/{id}": { - "get": { - "security": [ - { - "roles": [ - "template:read" - ] - } - ], - "tags": [ - "templates" - ], - "summary": "Get a single template", - "operationId": "getTemplate", - "parameters": [ - { - "type": "string", - "x-example": "default", - "description": "Template ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketTemplateResponse" - }, - "examples": { - "test": { - "id": "default", - "name": "Default", - "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Default\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n" - } - } - } - } - }, - "put": { - "security": [ - { - "roles": [ - "template:write" - ] - } - ], - "tags": [ - "templates" - ], - "summary": "Update an existing template", - "operationId": "updateTemplate", - "parameters": [ - { - "type": "string", - "x-example": "default", - "description": "Template ID", - "name": "id", - "in": "path", - "required": true - }, - { - "x-example": { - "name": "My Template", - "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n" - }, - "description": "Template object that needs to be added", - "name": "template", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/TicketTemplateForm" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketTemplateResponse" - }, - "examples": { - "test": { - "id": "default", - "name": "My Template", - "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n" - } - } - } - } - }, - "delete": { - "security": [ - { - "roles": [ - "template:write" - ] - } - ], - "tags": [ - "templates" - ], - "summary": "Delete a template", - "operationId": "deleteTemplate", - "parameters": [ - { - "type": "string", - "x-example": "default", - "description": "Template ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "204": { - "description": "successful operation" - } - } - } - }, - "/tickets": { - "get": { - "security": [ - { - "roles": [ - "ticket:read" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "List tickets", - "operationId": "listTickets", - "parameters": [ - { - "type": "string", - "description": "Ticket Type", - "name": "type", - "in": "query" - }, - { - "type": "integer", - "default": 0, - "description": "Offset of the list", - "name": "offset", - "in": "query" - }, - { - "maximum": 100, - "type": "integer", - "default": 25, - "description": "Number of tickets", - "name": "count", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "description": "Sort columns", - "name": "sort", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "boolean" - }, - "description": "Sort descending", - "name": "desc", - "in": "query" - }, - { - "type": "string", - "description": "Search query", - "name": "query", - "in": "query" - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketList" - }, - "examples": { - "test": { - "count": 3, - "tickets": [ - { - "artifacts": [ - { - "name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", - "status": "unknown" - }, - { - "name": "http://www.customerviral.io/scalable/vertical/killer", - "status": "clean" - }, - { - "name": "leadreintermediate.io", - "status": "malicious" - } - ], - "created": "2021-10-02T16:04:59.078206Z", - "id": 8123, - "modified": "2021-10-02T16:04:59.078206Z", - "name": "live zebra", - "owner": "demo", - "playbooks": { - "phishing": { - "name": "Phishing", - "tasks": { - "block-iocs": { - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Block IOCs", - "type": "task" - }, - "block-sender": { - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Block sender", - "next": { - "extract-iocs": "" - }, - "type": "task" - }, - "board": { - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Board Involvement?", - "next": { - "escalate": "boardInvolved == true", - "mail-available": "boardInvolved == false" - }, - "schema": { - "properties": { - "boardInvolved": { - "default": false, - "title": "A board member is involved.", - "type": "boolean" - } - }, - "required": [ - "boardInvolved" - ], - "title": "Board Involvement?", - "type": "object" - }, - "type": "input" - }, - "escalate": { - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Escalate to CISO", - "type": "task" - }, - "extract-iocs": { - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Extract IOCs", - "next": { - "block-iocs": "" - }, - "schema": { - "properties": { - "iocs": { - "items": { - "type": "string" - }, - "title": "IOCs", - "type": "array" - } - }, - "title": "Extract IOCs", - "type": "object" - }, - "type": "input" - }, - "mail-available": { - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Mail available", - "next": { - "block-sender": "schemaKey == 'yes'", - "extract-iocs": "schemaKey == 'yes'", - "search-email-gateway": "schemaKey == 'no'" - }, - "schema": { - "oneOf": [ - { - "properties": { - "mail": { - "title": "Mail", - "type": "string", - "x-display": "textarea" - }, - "schemaKey": { - "const": "yes", - "type": "string" - } - }, - "required": [ - "mail" - ], - "title": "Yes" - }, - { - "properties": { - "schemaKey": { - "const": "no", - "type": "string" - } - }, - "title": "No" - } - ], - "title": "Mail available", - "type": "object" - }, - "type": "input" - }, - "search-email-gateway": { - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Search email gateway", - "next": { - "extract-iocs": "" - }, - "type": "task" - } - } - } - }, - "references": [ - { - "href": "https://www.leadmaximize.net/e-services/back-end", - "name": "performance" - }, - { - "href": "http://www.corporateinteractive.name/rich", - "name": "autumn" - }, - { - "href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", - "name": "suggest" - } - ], - "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", - "status": "closed", - "type": "incident" - }, - { - "created": "2021-10-02T16:04:59.078186Z", - "id": 8125, - "modified": "2021-10-02T16:04:59.078186Z", - "name": "phishing from selenafadel@von.com detected", - "owner": "demo", - "references": [ - { - "href": "https://www.seniorleading-edge.name/users/efficient", - "name": "recovery" - }, - { - "href": "http://www.dynamicseamless.com/clicks-and-mortar", - "name": "force" - }, - { - "href": "http://www.leadscalable.biz/envisioneer", - "name": "fund" - } - ], - "schema": "{}", - "status": "closed", - "type": "alert" - }, - { - "created": "2021-10-02T16:04:59.078186Z", - "id": 8126, - "modified": "2021-10-02T16:04:59.078186Z", - "name": "Surfaceintroduce virus detected", - "owner": "demo", - "references": [ - { - "href": "http://www.centralworld-class.io/synthesize", - "name": "university" - }, - { - "href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", - "name": "goal" - }, - { - "href": "http://www.chiefsyndicate.io/action-items", - "name": "unemployment" - } - ], - "schema": "{}", - "status": "closed", - "type": "alert" - } - ] - } - } - } - } - }, - "post": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Create a new ticket", - "operationId": "createTicket", - "parameters": [ - { - "x-example": { - "id": 123, - "name": "Wannacry infection", - "owner": "bob", - "status": "open", - "type": "incident" - }, - "description": "New ticket", - "name": "ticket", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/TicketForm" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketResponse" - }, - "examples": { - "test": { - "created": "2021-12-12T12:12:12.000000012Z", - "id": 123, - "modified": "2021-12-12T12:12:12.000000012Z", - "name": "Wannacry infection", - "owner": "bob", - "schema": "{}", - "status": "open", - "type": "incident" - } - } - } - } - } - }, - "/tickets/batch": { - "post": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Create a new tickets in batch", - "operationId": "createTicketBatch", - "parameters": [ - { - "x-example": [ - { - "id": 123, - "name": "Wannacry infection", - "owner": "bob", - "status": "open", - "type": "incident" - } - ], - "description": "New ticket", - "name": "ticket", - "in": "body", - "required": true, - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/TicketForm" - } - } - } - ], - "responses": { - "204": { - "description": "successful operation" - } - } - } - }, - "/tickets/{id}": { - "get": { - "security": [ - { - "roles": [ - "ticket:read" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Get a single ticket", - "operationId": "getTicket", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8125, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketResponse" - }, - "examples": { - "test": { - "created": "2021-10-02T16:04:59.078186Z", - "id": 8125, - "modified": "2021-10-02T16:04:59.078186Z", - "name": "phishing from selenafadel@von.com detected", - "owner": "demo", - "references": [ - { - "href": "https://www.seniorleading-edge.name/users/efficient", - "name": "recovery" - }, - { - "href": "http://www.dynamicseamless.com/clicks-and-mortar", - "name": "force" - }, - { - "href": "http://www.leadscalable.biz/envisioneer", - "name": "fund" - } - ], - "schema": "{}", - "status": "closed", - "tickets": [ - { - "created": "2021-10-02T16:04:59.078186Z", - "id": 8126, - "modified": "2021-10-02T16:04:59.078186Z", - "name": "Surfaceintroduce virus detected", - "owner": "demo", - "references": [ - { - "href": "http://www.centralworld-class.io/synthesize", - "name": "university" - }, - { - "href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", - "name": "goal" - }, - { - "href": "http://www.chiefsyndicate.io/action-items", - "name": "unemployment" - } - ], - "schema": "{}", - "status": "closed", - "type": "alert" - } - ], - "type": "alert" - } - } - } - } - }, - "put": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Update an existing ticket", - "operationId": "updateTicket", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8125, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "x-example": { - "created": "2021-12-12T12:12:12.000000012Z", - "modified": "2021-12-12T12:12:12.000000012Z", - "name": "phishing from selenafadel@von.org detected", - "owner": "demo", - "references": [ - { - "href": "https://www.seniorleading-edge.name/users/efficient", - "name": "recovery" - }, - { - "href": "http://www.dynamicseamless.com/clicks-and-mortar", - "name": "force" - }, - { - "href": "http://www.leadscalable.biz/envisioneer", - "name": "fund" - } - ], - "schema": "{}", - "status": "closed", - "type": "alert" - }, - "description": "Updated ticket", - "name": "ticket", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/Ticket" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketResponse" - }, - "examples": { - "test": { - "created": "2021-12-12T12:12:12.000000012Z", - "id": 8125, - "modified": "2021-12-12T12:12:12.000000012Z", - "name": "phishing from selenafadel@von.org detected", - "owner": "demo", - "references": [ - { - "href": "https://www.seniorleading-edge.name/users/efficient", - "name": "recovery" - }, - { - "href": "http://www.dynamicseamless.com/clicks-and-mortar", - "name": "force" - }, - { - "href": "http://www.leadscalable.biz/envisioneer", - "name": "fund" - } - ], - "schema": "{}", - "status": "closed", - "tickets": [ - { - "created": "2021-10-02T16:04:59.078186Z", - "id": 8126, - "modified": "2021-10-02T16:04:59.078186Z", - "name": "Surfaceintroduce virus detected", - "owner": "demo", - "references": [ - { - "href": "http://www.centralworld-class.io/synthesize", - "name": "university" - }, - { - "href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", - "name": "goal" - }, - { - "href": "http://www.chiefsyndicate.io/action-items", - "name": "unemployment" - } - ], - "schema": "{}", - "status": "closed", - "type": "alert" - } - ], - "type": "alert" - } - } - } - } - }, - "delete": { - "security": [ - { - "roles": [ - "ticket:delete" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Delete an ticket", - "operationId": "deleteTicket", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8125, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "204": { - "description": "successful operation" - } - } - } - }, - "/tickets/{id}/artifacts": { - "post": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Add a single artifact", - "operationId": "addArtifact", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8123, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "x-example": { - "name": "2.2.2.2" - }, - "description": "Artifact object that needs to be added", - "name": "artifact", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/Artifact" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketResponse" - }, - "examples": { - "test": { - "artifacts": [ - { - "name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", - "status": "unknown" - }, - { - "name": "http://www.customerviral.io/scalable/vertical/killer", - "status": "clean" - }, - { - "name": "leadreintermediate.io", - "status": "malicious" - }, - { - "name": "2.2.2.2", - "status": "unknown", - "type": "ip" - } - ], - "created": "2021-10-02T16:04:59.078206Z", - "id": 8123, - "modified": "2021-12-12T12:12:12.000000012Z", - "name": "live zebra", - "owner": "demo", - "playbooks": { - "phishing": { - "name": "Phishing", - "tasks": { - "block-iocs": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Block IOCs", - "order": 6, - "type": "task" - }, - "block-sender": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Block sender", - "next": { - "extract-iocs": "" - }, - "order": 3, - "type": "task" - }, - "board": { - "active": true, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Board Involvement?", - "next": { - "escalate": "boardInvolved == true", - "mail-available": "boardInvolved == false" - }, - "order": 0, - "schema": { - "properties": { - "boardInvolved": { - "default": false, - "title": "A board member is involved.", - "type": "boolean" - } - }, - "required": [ - "boardInvolved" - ], - "title": "Board Involvement?", - "type": "object" - }, - "type": "input" - }, - "escalate": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Escalate to CISO", - "order": 1, - "type": "task" - }, - "extract-iocs": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Extract IOCs", - "next": { - "block-iocs": "" - }, - "order": 5, - "schema": { - "properties": { - "iocs": { - "items": { - "type": "string" - }, - "title": "IOCs", - "type": "array" - } - }, - "title": "Extract IOCs", - "type": "object" - }, - "type": "input" - }, - "mail-available": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Mail available", - "next": { - "block-sender": "schemaKey == 'yes'", - "extract-iocs": "schemaKey == 'yes'", - "search-email-gateway": "schemaKey == 'no'" - }, - "order": 2, - "schema": { - "oneOf": [ - { - "properties": { - "mail": { - "title": "Mail", - "type": "string", - "x-display": "textarea" - }, - "schemaKey": { - "const": "yes", - "type": "string" - } - }, - "required": [ - "mail" - ], - "title": "Yes" - }, - { - "properties": { - "schemaKey": { - "const": "no", - "type": "string" - } - }, - "title": "No" - } - ], - "title": "Mail available", - "type": "object" - }, - "type": "input" - }, - "search-email-gateway": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Search email gateway", - "next": { - "extract-iocs": "" - }, - "order": 4, - "type": "task" - } - } - } - }, - "references": [ - { - "href": "https://www.leadmaximize.net/e-services/back-end", - "name": "performance" - }, - { - "href": "http://www.corporateinteractive.name/rich", - "name": "autumn" - }, - { - "href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", - "name": "suggest" - } - ], - "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", - "status": "closed", - "type": "incident" - } - } - } - } - } - }, - "/tickets/{id}/artifacts/{name}": { - "get": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Get a single artifact", - "operationId": "getArtifact", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8123, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "string", - "x-example": "leadreintermediate.io", - "name": "name", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/Artifact" - }, - "examples": { - "test": { - "name": "leadreintermediate.io", - "status": "malicious" - } - } - } - } - }, - "put": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Set a single artifact", - "operationId": "setArtifact", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8123, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "string", - "x-example": "leadreintermediate.io", - "name": "name", - "in": "path", - "required": true - }, - { - "x-example": { - "name": "leadreintermediate.io", - "status": "clean" - }, - "name": "artifact", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/Artifact" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketResponse" - }, - "examples": { - "test": { - "artifacts": [ - { - "name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", - "status": "unknown" - }, - { - "name": "http://www.customerviral.io/scalable/vertical/killer", - "status": "clean" - }, - { - "name": "leadreintermediate.io", - "status": "clean" - } - ], - "created": "2021-10-02T16:04:59.078206Z", - "id": 8123, - "modified": "2021-10-02T16:04:59.078206Z", - "name": "live zebra", - "owner": "demo", - "playbooks": { - "phishing": { - "name": "Phishing", - "tasks": { - "block-iocs": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Block IOCs", - "order": 6, - "type": "task" - }, - "block-sender": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Block sender", - "next": { - "extract-iocs": "" - }, - "order": 3, - "type": "task" - }, - "board": { - "active": true, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Board Involvement?", - "next": { - "escalate": "boardInvolved == true", - "mail-available": "boardInvolved == false" - }, - "order": 0, - "schema": { - "properties": { - "boardInvolved": { - "default": false, - "title": "A board member is involved.", - "type": "boolean" - } - }, - "required": [ - "boardInvolved" - ], - "title": "Board Involvement?", - "type": "object" - }, - "type": "input" - }, - "escalate": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Escalate to CISO", - "order": 1, - "type": "task" - }, - "extract-iocs": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Extract IOCs", - "next": { - "block-iocs": "" - }, - "order": 5, - "schema": { - "properties": { - "iocs": { - "items": { - "type": "string" - }, - "title": "IOCs", - "type": "array" - } - }, - "title": "Extract IOCs", - "type": "object" - }, - "type": "input" - }, - "mail-available": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Mail available", - "next": { - "block-sender": "schemaKey == 'yes'", - "extract-iocs": "schemaKey == 'yes'", - "search-email-gateway": "schemaKey == 'no'" - }, - "order": 2, - "schema": { - "oneOf": [ - { - "properties": { - "mail": { - "title": "Mail", - "type": "string", - "x-display": "textarea" - }, - "schemaKey": { - "const": "yes", - "type": "string" - } - }, - "required": [ - "mail" - ], - "title": "Yes" - }, - { - "properties": { - "schemaKey": { - "const": "no", - "type": "string" - } - }, - "title": "No" - } - ], - "title": "Mail available", - "type": "object" - }, - "type": "input" - }, - "search-email-gateway": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Search email gateway", - "next": { - "extract-iocs": "" - }, - "order": 4, - "type": "task" - } - } - } - }, - "references": [ - { - "href": "https://www.leadmaximize.net/e-services/back-end", - "name": "performance" - }, - { - "href": "http://www.corporateinteractive.name/rich", - "name": "autumn" - }, - { - "href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", - "name": "suggest" - } - ], - "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", - "status": "closed", - "type": "incident" - } - } - } - } - }, - "delete": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Remove an artifact", - "operationId": "removeArtifact", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8123, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "string", - "x-example": "leadreintermediate.io", - "name": "name", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketResponse" - }, - "examples": { - "test": { - "artifacts": [ - { - "name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", - "status": "unknown" - }, - { - "name": "http://www.customerviral.io/scalable/vertical/killer", - "status": "clean" - } - ], - "created": "2021-10-02T16:04:59.078206Z", - "id": 8123, - "modified": "2021-12-12T12:12:12.000000012Z", - "name": "live zebra", - "owner": "demo", - "playbooks": { - "phishing": { - "name": "Phishing", - "tasks": { - "block-iocs": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Block IOCs", - "order": 6, - "type": "task" - }, - "block-sender": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Block sender", - "next": { - "extract-iocs": "" - }, - "order": 3, - "type": "task" - }, - "board": { - "active": true, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Board Involvement?", - "next": { - "escalate": "boardInvolved == true", - "mail-available": "boardInvolved == false" - }, - "order": 0, - "schema": { - "properties": { - "boardInvolved": { - "default": false, - "title": "A board member is involved.", - "type": "boolean" - } - }, - "required": [ - "boardInvolved" - ], - "title": "Board Involvement?", - "type": "object" - }, - "type": "input" - }, - "escalate": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Escalate to CISO", - "order": 1, - "type": "task" - }, - "extract-iocs": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Extract IOCs", - "next": { - "block-iocs": "" - }, - "order": 5, - "schema": { - "properties": { - "iocs": { - "items": { - "type": "string" - }, - "title": "IOCs", - "type": "array" - } - }, - "title": "Extract IOCs", - "type": "object" - }, - "type": "input" - }, - "mail-available": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Mail available", - "next": { - "block-sender": "schemaKey == 'yes'", - "extract-iocs": "schemaKey == 'yes'", - "search-email-gateway": "schemaKey == 'no'" - }, - "order": 2, - "schema": { - "oneOf": [ - { - "properties": { - "mail": { - "title": "Mail", - "type": "string", - "x-display": "textarea" - }, - "schemaKey": { - "const": "yes", - "type": "string" - } - }, - "required": [ - "mail" - ], - "title": "Yes" - }, - { - "properties": { - "schemaKey": { - "const": "no", - "type": "string" - } - }, - "title": "No" - } - ], - "title": "Mail available", - "type": "object" - }, - "type": "input" - }, - "search-email-gateway": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Search email gateway", - "next": { - "extract-iocs": "" - }, - "order": 4, - "type": "task" - } - } - } - }, - "references": [ - { - "href": "https://www.leadmaximize.net/e-services/back-end", - "name": "performance" - }, - { - "href": "http://www.corporateinteractive.name/rich", - "name": "autumn" - }, - { - "href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", - "name": "suggest" - } - ], - "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", - "status": "closed", - "type": "incident" - } - } - } - } - } - }, - "/tickets/{id}/artifacts/{name}/enrich": { - "post": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Enrich a single artifact", - "operationId": "enrichArtifact", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8123, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "string", - "x-example": "leadreintermediate.io", - "name": "name", - "in": "path", - "required": true - }, - { - "x-example": { - "data": { - "hash": "b7a067a742c20d07a7456646de89bc2d408a1153" - }, - "name": "hash.sha1" - }, - "name": "data", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/EnrichmentForm" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/Artifact" - }, - "examples": { - "test": { - "artifacts": [ - { - "name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", - "status": "unknown" - }, - { - "name": "http://www.customerviral.io/scalable/vertical/killer", - "status": "clean" - }, - { - "enrichments": { - "hash.sha1": { - "created": "2021-12-12T12:12:12.000000012Z", - "data": { - "hash": "b7a067a742c20d07a7456646de89bc2d408a1153" - }, - "name": "hash.sha1" - } - }, - "name": "leadreintermediate.io", - "status": "malicious" - } - ], - "created": "2021-10-02T16:04:59.078206Z", - "id": 8123, - "modified": "2021-10-02T16:04:59.078206Z", - "name": "live zebra", - "owner": "demo", - "playbooks": { - "phishing": { - "name": "Phishing", - "tasks": { - "block-iocs": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Block IOCs", - "order": 6, - "type": "task" - }, - "block-sender": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Block sender", - "next": { - "extract-iocs": "" - }, - "order": 3, - "type": "task" - }, - "board": { - "active": true, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Board Involvement?", - "next": { - "escalate": "boardInvolved == true", - "mail-available": "boardInvolved == false" - }, - "order": 0, - "schema": { - "properties": { - "boardInvolved": { - "default": false, - "title": "A board member is involved.", - "type": "boolean" - } - }, - "required": [ - "boardInvolved" - ], - "title": "Board Involvement?", - "type": "object" - }, - "type": "input" - }, - "escalate": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Escalate to CISO", - "order": 1, - "type": "task" - }, - "extract-iocs": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Extract IOCs", - "next": { - "block-iocs": "" - }, - "order": 5, - "schema": { - "properties": { - "iocs": { - "items": { - "type": "string" - }, - "title": "IOCs", - "type": "array" - } - }, - "title": "Extract IOCs", - "type": "object" - }, - "type": "input" - }, - "mail-available": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Mail available", - "next": { - "block-sender": "schemaKey == 'yes'", - "extract-iocs": "schemaKey == 'yes'", - "search-email-gateway": "schemaKey == 'no'" - }, - "order": 2, - "schema": { - "oneOf": [ - { - "properties": { - "mail": { - "title": "Mail", - "type": "string", - "x-display": "textarea" - }, - "schemaKey": { - "const": "yes", - "type": "string" - } - }, - "required": [ - "mail" - ], - "title": "Yes" - }, - { - "properties": { - "schemaKey": { - "const": "no", - "type": "string" - } - }, - "title": "No" - } - ], - "title": "Mail available", - "type": "object" - }, - "type": "input" - }, - "search-email-gateway": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Search email gateway", - "next": { - "extract-iocs": "" - }, - "order": 4, - "type": "task" - } - } - } - }, - "references": [ - { - "href": "https://www.leadmaximize.net/e-services/back-end", - "name": "performance" - }, - { - "href": "http://www.corporateinteractive.name/rich", - "name": "autumn" - }, - { - "href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", - "name": "suggest" - } - ], - "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", - "status": "closed", - "type": "incident" - } - } - } - } - } - }, - "/tickets/{id}/artifacts/{name}/run/{automation}": { - "post": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Run automation on a single artifact", - "operationId": "runArtifact", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8123, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "string", - "x-example": "leadreintermediate.io", - "name": "name", - "in": "path", - "required": true - }, - { - "type": "string", - "x-example": "hash.sha1", - "name": "automation", - "in": "path", - "required": true - } - ], - "responses": { - "204": { - "description": "successful operation" - } - } - } - }, - "/tickets/{id}/comments": { - "post": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Add ticket comment", - "operationId": "addComment", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8125, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "x-example": { - "message": "My first comment" - }, - "description": "Ticket comment", - "name": "comment", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/CommentForm" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketResponse" - }, - "examples": { - "test": { - "comments": [ - { - "created": "2021-12-12T12:12:12.000000012Z", - "creator": "bob", - "message": "My first comment" - } - ], - "created": "2021-10-02T16:04:59.078186Z", - "id": 8125, - "modified": "2021-12-12T12:12:12.000000012Z", - "name": "phishing from selenafadel@von.com detected", - "owner": "demo", - "references": [ - { - "href": "https://www.seniorleading-edge.name/users/efficient", - "name": "recovery" - }, - { - "href": "http://www.dynamicseamless.com/clicks-and-mortar", - "name": "force" - }, - { - "href": "http://www.leadscalable.biz/envisioneer", - "name": "fund" - } - ], - "schema": "{}", - "status": "closed", - "tickets": [ - { - "created": "2021-10-02T16:04:59.078186Z", - "id": 8126, - "modified": "2021-10-02T16:04:59.078186Z", - "name": "Surfaceintroduce virus detected", - "owner": "demo", - "references": [ - { - "href": "http://www.centralworld-class.io/synthesize", - "name": "university" - }, - { - "href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", - "name": "goal" - }, - { - "href": "http://www.chiefsyndicate.io/action-items", - "name": "unemployment" - } - ], - "schema": "{}", - "status": "closed", - "type": "alert" - } - ], - "type": "alert" - } - } - } - } - } - }, - "/tickets/{id}/comments/{commentID}": { - "delete": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "description": "Comment will be removed from the ticket.", - "tags": [ - "tickets" - ], - "summary": "Remove an comment from an ticket", - "operationId": "removeComment", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8123, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "integer", - "x-example": 0, - "description": "Comment ID to remove", - "name": "commentID", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketResponse" - }, - "examples": { - "test": { - "artifacts": [ - { - "name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", - "status": "unknown" - }, - { - "name": "http://www.customerviral.io/scalable/vertical/killer", - "status": "clean" - }, - { - "name": "leadreintermediate.io", - "status": "malicious" - } - ], - "created": "2021-10-02T16:04:59.078206Z", - "id": 8123, - "modified": "2021-12-12T12:12:12.000000012Z", - "name": "live zebra", - "owner": "demo", - "playbooks": { - "phishing": { - "name": "Phishing", - "tasks": { - "block-iocs": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Block IOCs", - "order": 6, - "type": "task" - }, - "block-sender": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Block sender", - "next": { - "extract-iocs": "" - }, - "order": 3, - "type": "task" - }, - "board": { - "active": true, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Board Involvement?", - "next": { - "escalate": "boardInvolved == true", - "mail-available": "boardInvolved == false" - }, - "order": 0, - "schema": { - "properties": { - "boardInvolved": { - "default": false, - "title": "A board member is involved.", - "type": "boolean" - } - }, - "required": [ - "boardInvolved" - ], - "title": "Board Involvement?", - "type": "object" - }, - "type": "input" - }, - "escalate": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Escalate to CISO", - "order": 1, - "type": "task" - }, - "extract-iocs": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Extract IOCs", - "next": { - "block-iocs": "" - }, - "order": 5, - "schema": { - "properties": { - "iocs": { - "items": { - "type": "string" - }, - "title": "IOCs", - "type": "array" - } - }, - "title": "Extract IOCs", - "type": "object" - }, - "type": "input" - }, - "mail-available": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Mail available", - "next": { - "block-sender": "schemaKey == 'yes'", - "extract-iocs": "schemaKey == 'yes'", - "search-email-gateway": "schemaKey == 'no'" - }, - "order": 2, - "schema": { - "oneOf": [ - { - "properties": { - "mail": { - "title": "Mail", - "type": "string", - "x-display": "textarea" - }, - "schemaKey": { - "const": "yes", - "type": "string" - } - }, - "required": [ - "mail" - ], - "title": "Yes" - }, - { - "properties": { - "schemaKey": { - "const": "no", - "type": "string" - } - }, - "title": "No" - } - ], - "title": "Mail available", - "type": "object" - }, - "type": "input" - }, - "search-email-gateway": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Search email gateway", - "next": { - "extract-iocs": "" - }, - "order": 4, - "type": "task" - } - } - } - }, - "references": [ - { - "href": "https://www.leadmaximize.net/e-services/back-end", - "name": "performance" - }, - { - "href": "http://www.corporateinteractive.name/rich", - "name": "autumn" - }, - { - "href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", - "name": "suggest" - } - ], - "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", - "status": "closed", - "type": "incident" - } - } - } - } - } - }, - "/tickets/{id}/files": { - "put": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "description": "Link files to an ticket. The files themself will be stored in object storage.", - "tags": [ - "tickets" - ], - "summary": "Link files to an ticket", - "operationId": "linkFiles", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8125, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "x-example": [ - { - "key": "myfile", - "name": "document.doc" - } - ], - "description": "Added files", - "name": "files", - "in": "body", - "required": true, - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/File" - } - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketResponse" - }, - "examples": { - "test": { - "created": "2021-10-02T16:04:59.078186Z", - "files": [ - { - "key": "myfile", - "name": "document.doc" - } - ], - "id": 8125, - "modified": "2021-12-12T12:12:12.000000012Z", - "name": "phishing from selenafadel@von.com detected", - "owner": "demo", - "references": [ - { - "href": "https://www.seniorleading-edge.name/users/efficient", - "name": "recovery" - }, - { - "href": "http://www.dynamicseamless.com/clicks-and-mortar", - "name": "force" - }, - { - "href": "http://www.leadscalable.biz/envisioneer", - "name": "fund" - } - ], - "schema": "{}", - "status": "closed", - "tickets": [ - { - "created": "2021-10-02T16:04:59.078186Z", - "id": 8126, - "modified": "2021-10-02T16:04:59.078186Z", - "name": "Surfaceintroduce virus detected", - "owner": "demo", - "references": [ - { - "href": "http://www.centralworld-class.io/synthesize", - "name": "university" - }, - { - "href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", - "name": "goal" - }, - { - "href": "http://www.chiefsyndicate.io/action-items", - "name": "unemployment" - } - ], - "schema": "{}", - "status": "closed", - "type": "alert" - } - ], - "type": "alert" - } - } - } - } - } - }, - "/tickets/{id}/playbooks": { - "post": { - "tags": [ - "tickets" - ], - "summary": "Add a new ticket playbook", - "operationId": "addTicketPlaybook", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8125, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "x-example": { - "yaml": "name: Simple\ntasks:\n input:\n name: Upload malware if possible\n type: input\n schema:\n title: Malware\n type: object\n properties:\n malware:\n type: string\n title: Select malware\n default: \"\"\n next:\n hash: \"malware != ''\"\n\n hash:\n name: Hash the malware\n type: automation\n automation: hash.sha1\n payload:\n default: \"playbook.tasks['input'].data['malware']\"\n next:\n escalate:\n\n escalate:\n name: Escalate to malware team\n type: task\n" - }, - "description": "Ticket playbook object that needs to be added", - "name": "playbook", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/PlaybookTemplateForm" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketResponse" - }, - "examples": { - "test": { - "created": "2021-10-02T16:04:59.078186Z", - "id": 8125, - "modified": "2021-12-12T12:12:12.000000012Z", - "name": "phishing from selenafadel@von.com detected", - "owner": "demo", - "playbooks": { - "simple": { - "name": "Simple", - "tasks": { - "escalate": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Escalate to malware team", - "order": 2, - "type": "task" - }, - "hash": { - "active": false, - "automation": "hash.sha1", - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Hash the malware", - "next": { - "escalate": "" - }, - "order": 1, - "payload": { - "default": "playbook.tasks['input'].data['malware']" - }, - "type": "automation" - }, - "input": { - "active": true, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Upload malware if possible", - "next": { - "hash": "malware != ''" - }, - "order": 0, - "schema": { - "properties": { - "malware": { - "default": "", - "title": "Select malware", - "type": "string" - } - }, - "title": "Malware", - "type": "object" - }, - "type": "input" - } - } - } - }, - "references": [ - { - "href": "https://www.seniorleading-edge.name/users/efficient", - "name": "recovery" - }, - { - "href": "http://www.dynamicseamless.com/clicks-and-mortar", - "name": "force" - }, - { - "href": "http://www.leadscalable.biz/envisioneer", - "name": "fund" - } - ], - "schema": "{}", - "status": "closed", - "tickets": [ - { - "created": "2021-10-02T16:04:59.078186Z", - "id": 8126, - "modified": "2021-10-02T16:04:59.078186Z", - "name": "Surfaceintroduce virus detected", - "owner": "demo", - "references": [ - { - "href": "http://www.centralworld-class.io/synthesize", - "name": "university" - }, - { - "href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", - "name": "goal" - }, - { - "href": "http://www.chiefsyndicate.io/action-items", - "name": "unemployment" - } - ], - "schema": "{}", - "status": "closed", - "type": "alert" - } - ], - "type": "alert" - } - } - } - } - } - }, - "/tickets/{id}/playbooks/{playbookID}": { - "delete": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Remove an ticket playbook", - "operationId": "removeTicketPlaybook", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8123, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "string", - "x-example": "phishing", - "description": "Playbook ID", - "name": "playbookID", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketResponse" - }, - "examples": { - "test": { - "artifacts": [ - { - "name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", - "status": "unknown" - }, - { - "name": "http://www.customerviral.io/scalable/vertical/killer", - "status": "clean" - }, - { - "name": "leadreintermediate.io", - "status": "malicious" - } - ], - "created": "2021-10-02T16:04:59.078206Z", - "id": 8123, - "modified": "2021-12-12T12:12:12.000000012Z", - "name": "live zebra", - "owner": "demo", - "references": [ - { - "href": "https://www.leadmaximize.net/e-services/back-end", - "name": "performance" - }, - { - "href": "http://www.corporateinteractive.name/rich", - "name": "autumn" - }, - { - "href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", - "name": "suggest" - } - ], - "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", - "status": "closed", - "type": "incident" - } - } - } - } - } - }, - "/tickets/{id}/playbooks/{playbookID}/task/{taskID}": { - "put": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Set a ticket playbook task", - "operationId": "setTask", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8123, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "string", - "x-example": "phishing", - "description": "Playbook ID", - "name": "playbookID", - "in": "path", - "required": true - }, - { - "type": "string", - "x-example": "board", - "description": "Task ID", - "name": "taskID", - "in": "path", - "required": true - }, - { - "x-example": { - "active": true, - "data": { - "boardInvolved": true - }, - "done": false, - "name": "Board Involvement?", - "next": { - "escalate": "boardInvolved == true", - "mail-available": "boardInvolved == false" - }, - "order": 0, - "schema": { - "properties": { - "boardInvolved": { - "default": false, - "title": "A board member is involved.", - "type": "boolean" - } - }, - "required": [ - "boardInvolved" - ], - "title": "Board Involvement?", - "type": "object" - }, - "type": "input" - }, - "description": "Task", - "name": "task", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/Task" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketResponse" - }, - "examples": { - "test": { - "artifacts": [ - { - "name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", - "status": "unknown" - }, - { - "name": "http://www.customerviral.io/scalable/vertical/killer", - "status": "clean" - }, - { - "name": "leadreintermediate.io", - "status": "malicious" - } - ], - "created": "2021-10-02T16:04:59.078206Z", - "id": 8123, - "modified": "2021-12-12T12:12:12.000000012Z", - "name": "live zebra", - "owner": "demo", - "playbooks": { - "phishing": { - "name": "Phishing", - "tasks": { - "block-iocs": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Block IOCs", - "order": 6, - "type": "task" - }, - "block-sender": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Block sender", - "next": { - "extract-iocs": "" - }, - "order": 3, - "type": "task" - }, - "board": { - "active": true, - "created": "2021-12-12T12:12:12.000000012Z", - "data": { - "boardInvolved": true - }, - "done": false, - "name": "Board Involvement?", - "next": { - "escalate": "boardInvolved == true", - "mail-available": "boardInvolved == false" - }, - "order": 0, - "schema": { - "properties": { - "boardInvolved": { - "default": false, - "title": "A board member is involved.", - "type": "boolean" - } - }, - "required": [ - "boardInvolved" - ], - "title": "Board Involvement?", - "type": "object" - }, - "type": "input" - }, - "escalate": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Escalate to CISO", - "order": 1, - "type": "task" - }, - "extract-iocs": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Extract IOCs", - "next": { - "block-iocs": "" - }, - "order": 5, - "schema": { - "properties": { - "iocs": { - "items": { - "type": "string" - }, - "title": "IOCs", - "type": "array" - } - }, - "title": "Extract IOCs", - "type": "object" - }, - "type": "input" - }, - "mail-available": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Mail available", - "next": { - "block-sender": "schemaKey == 'yes'", - "extract-iocs": "schemaKey == 'yes'", - "search-email-gateway": "schemaKey == 'no'" - }, - "order": 2, - "schema": { - "oneOf": [ - { - "properties": { - "mail": { - "title": "Mail", - "type": "string", - "x-display": "textarea" - }, - "schemaKey": { - "const": "yes", - "type": "string" - } - }, - "required": [ - "mail" - ], - "title": "Yes" - }, - { - "properties": { - "schemaKey": { - "const": "no", - "type": "string" - } - }, - "title": "No" - } - ], - "title": "Mail available", - "type": "object" - }, - "type": "input" - }, - "search-email-gateway": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Search email gateway", - "next": { - "extract-iocs": "" - }, - "order": 4, - "type": "task" - } - } - } - }, - "references": [ - { - "href": "https://www.leadmaximize.net/e-services/back-end", - "name": "performance" - }, - { - "href": "http://www.corporateinteractive.name/rich", - "name": "autumn" - }, - { - "href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", - "name": "suggest" - } - ], - "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", - "status": "closed", - "type": "incident" - } - } - } - } - } - }, - "/tickets/{id}/playbooks/{playbookID}/task/{taskID}/complete": { - "put": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Complete ticket playbook task", - "operationId": "completeTask", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8123, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "string", - "x-example": "phishing", - "description": "Playbook ID", - "name": "playbookID", - "in": "path", - "required": true - }, - { - "type": "string", - "x-example": "board", - "description": "Task ID", - "name": "taskID", - "in": "path", - "required": true - }, - { - "x-example": { - "boardInvolved": true - }, - "description": "Ticket playbook object that needs to be added", - "name": "data", - "in": "body", - "required": true, - "schema": { - "type": "object" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketResponse" - }, - "examples": { - "test": { - "artifacts": [ - { - "name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", - "status": "unknown" - }, - { - "name": "http://www.customerviral.io/scalable/vertical/killer", - "status": "clean" - }, - { - "name": "leadreintermediate.io", - "status": "malicious" - } - ], - "created": "2021-10-02T16:04:59.078206Z", - "id": 8123, - "modified": "2021-12-12T12:12:12.000000012Z", - "name": "live zebra", - "owner": "demo", - "playbooks": { - "phishing": { - "name": "Phishing", - "tasks": { - "block-iocs": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Block IOCs", - "order": 6, - "type": "task" - }, - "block-sender": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Block sender", - "next": { - "extract-iocs": "" - }, - "order": 3, - "type": "task" - }, - "board": { - "active": false, - "closed": "2021-12-12T12:12:12.000000012Z", - "created": "2021-12-12T12:12:12.000000012Z", - "data": { - "boardInvolved": true - }, - "done": true, - "name": "Board Involvement?", - "next": { - "escalate": "boardInvolved == true", - "mail-available": "boardInvolved == false" - }, - "order": 0, - "schema": { - "properties": { - "boardInvolved": { - "default": false, - "title": "A board member is involved.", - "type": "boolean" - } - }, - "required": [ - "boardInvolved" - ], - "title": "Board Involvement?", - "type": "object" - }, - "type": "input" - }, - "escalate": { - "active": true, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Escalate to CISO", - "order": 1, - "type": "task" - }, - "extract-iocs": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Extract IOCs", - "next": { - "block-iocs": "" - }, - "order": 5, - "schema": { - "properties": { - "iocs": { - "items": { - "type": "string" - }, - "title": "IOCs", - "type": "array" - } - }, - "title": "Extract IOCs", - "type": "object" - }, - "type": "input" - }, - "mail-available": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Mail available", - "next": { - "block-sender": "schemaKey == 'yes'", - "extract-iocs": "schemaKey == 'yes'", - "search-email-gateway": "schemaKey == 'no'" - }, - "order": 2, - "schema": { - "oneOf": [ - { - "properties": { - "mail": { - "title": "Mail", - "type": "string", - "x-display": "textarea" - }, - "schemaKey": { - "const": "yes", - "type": "string" - } - }, - "required": [ - "mail" - ], - "title": "Yes" - }, - { - "properties": { - "schemaKey": { - "const": "no", - "type": "string" - } - }, - "title": "No" - } - ], - "title": "Mail available", - "type": "object" - }, - "type": "input" - }, - "search-email-gateway": { - "active": false, - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Search email gateway", - "next": { - "extract-iocs": "" - }, - "order": 4, - "type": "task" - } - } - } - }, - "references": [ - { - "href": "https://www.leadmaximize.net/e-services/back-end", - "name": "performance" - }, - { - "href": "http://www.corporateinteractive.name/rich", - "name": "autumn" - }, - { - "href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", - "name": "suggest" - } - ], - "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", - "status": "closed", - "type": "incident" - } - } - } - } - } - }, - "/tickets/{id}/playbooks/{playbookID}/task/{taskID}/run": { - "post": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Run ticket playbook task", - "operationId": "runTask", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8123, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "string", - "x-example": "phishing", - "description": "Playbook ID", - "name": "playbookID", - "in": "path", - "required": true - }, - { - "type": "string", - "x-example": "board", - "description": "Task ID", - "name": "taskID", - "in": "path", - "required": true - } - ], - "responses": { - "204": { - "description": "successful operation" - } - } - } - }, - "/tickets/{id}/references": { - "put": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Set ticket references", - "operationId": "setReferences", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8125, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "x-example": [ - { - "href": "http://www.leadscalable.biz/envisioneer", - "name": "fund" - } - ], - "description": "All ticket references", - "name": "references", - "in": "body", - "required": true, - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/Reference" - } - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketResponse" - }, - "examples": { - "test": { - "created": "2021-10-02T16:04:59.078186Z", - "id": 8125, - "modified": "2021-12-12T12:12:12.000000012Z", - "name": "phishing from selenafadel@von.com detected", - "owner": "demo", - "references": [ - { - "href": "http://www.leadscalable.biz/envisioneer", - "name": "fund" - } - ], - "schema": "{}", - "status": "closed", - "tickets": [ - { - "created": "2021-10-02T16:04:59.078186Z", - "id": 8126, - "modified": "2021-10-02T16:04:59.078186Z", - "name": "Surfaceintroduce virus detected", - "owner": "demo", - "references": [ - { - "href": "http://www.centralworld-class.io/synthesize", - "name": "university" - }, - { - "href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", - "name": "goal" - }, - { - "href": "http://www.chiefsyndicate.io/action-items", - "name": "unemployment" - } - ], - "schema": "{}", - "status": "closed", - "type": "alert" - } - ], - "type": "alert" - } - } - } - } - } - }, - "/tickets/{id}/schema": { - "put": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Set ticket schema", - "operationId": "setSchema", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8125, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "x-example": "{}", - "description": "New ticket schema", - "name": "schema", - "in": "body", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketResponse" - }, - "examples": { - "test": { - "created": "2021-10-02T16:04:59.078186Z", - "id": 8125, - "modified": "2021-10-02T16:04:59.078186Z", - "name": "phishing from selenafadel@von.com detected", - "owner": "demo", - "references": [ - { - "href": "https://www.seniorleading-edge.name/users/efficient", - "name": "recovery" - }, - { - "href": "http://www.dynamicseamless.com/clicks-and-mortar", - "name": "force" - }, - { - "href": "http://www.leadscalable.biz/envisioneer", - "name": "fund" - } - ], - "schema": "{}", - "status": "closed", - "tickets": [ - { - "created": "2021-10-02T16:04:59.078186Z", - "id": 8126, - "modified": "2021-10-02T16:04:59.078186Z", - "name": "Surfaceintroduce virus detected", - "owner": "demo", - "references": [ - { - "href": "http://www.centralworld-class.io/synthesize", - "name": "university" - }, - { - "href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", - "name": "goal" - }, - { - "href": "http://www.chiefsyndicate.io/action-items", - "name": "unemployment" - } - ], - "schema": "{}", - "status": "closed", - "type": "alert" - } - ], - "type": "alert" - } - } - } - } - } - }, - "/tickets/{id}/tickets": { - "delete": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Unlink an ticket to an ticket", - "operationId": "unlinkTicket", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8126, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "x-example": 8125, - "description": "Added ticket ID", - "name": "linkedID", - "in": "body", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketResponse" - }, - "examples": { - "test": { - "created": "2021-10-02T16:04:59.078186Z", - "id": 8126, - "modified": "2021-10-02T16:04:59.078186Z", - "name": "Surfaceintroduce virus detected", - "owner": "demo", - "references": [ - { - "href": "http://www.centralworld-class.io/synthesize", - "name": "university" - }, - { - "href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", - "name": "goal" - }, - { - "href": "http://www.chiefsyndicate.io/action-items", - "name": "unemployment" - } - ], - "schema": "{}", - "status": "closed", - "type": "alert" - } - } - } - } - }, - "patch": { - "security": [ - { - "roles": [ - "ticket:write" - ] - } - ], - "tags": [ - "tickets" - ], - "summary": "Link an ticket to an ticket", - "operationId": "linkTicket", - "parameters": [ - { - "type": "integer", - "format": "int64", - "x-example": 8126, - "description": "Ticket ID", - "name": "id", - "in": "path", - "required": true - }, - { - "x-example": 8123, - "description": "Added ticket ID", - "name": "linkedID", - "in": "body", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketResponse" - }, - "examples": { - "test": { - "created": "2021-10-02T16:04:59.078186Z", - "id": 8126, - "modified": "2021-10-02T16:04:59.078186Z", - "name": "Surfaceintroduce virus detected", - "owner": "demo", - "references": [ - { - "href": "http://www.centralworld-class.io/synthesize", - "name": "university" - }, - { - "href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", - "name": "goal" - }, - { - "href": "http://www.chiefsyndicate.io/action-items", - "name": "unemployment" - } - ], - "schema": "{}", - "status": "closed", - "tickets": [ - { - "artifacts": [ - { - "name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", - "status": "unknown" - }, - { - "name": "http://www.customerviral.io/scalable/vertical/killer", - "status": "clean" - }, - { - "name": "leadreintermediate.io", - "status": "malicious" - } - ], - "created": "2021-10-02T16:04:59.078206Z", - "id": 8123, - "modified": "2021-10-02T16:04:59.078206Z", - "name": "live zebra", - "owner": "demo", - "playbooks": { - "phishing": { - "name": "Phishing", - "tasks": { - "block-iocs": { - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Block IOCs", - "type": "task" - }, - "block-sender": { - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Block sender", - "next": { - "extract-iocs": "" - }, - "type": "task" - }, - "board": { - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Board Involvement?", - "next": { - "escalate": "boardInvolved == true", - "mail-available": "boardInvolved == false" - }, - "schema": { - "properties": { - "boardInvolved": { - "default": false, - "title": "A board member is involved.", - "type": "boolean" - } - }, - "required": [ - "boardInvolved" - ], - "title": "Board Involvement?", - "type": "object" - }, - "type": "input" - }, - "escalate": { - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Escalate to CISO", - "type": "task" - }, - "extract-iocs": { - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Extract IOCs", - "next": { - "block-iocs": "" - }, - "schema": { - "properties": { - "iocs": { - "items": { - "type": "string" - }, - "title": "IOCs", - "type": "array" - } - }, - "title": "Extract IOCs", - "type": "object" - }, - "type": "input" - }, - "mail-available": { - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Mail available", - "next": { - "block-sender": "schemaKey == 'yes'", - "extract-iocs": "schemaKey == 'yes'", - "search-email-gateway": "schemaKey == 'no'" - }, - "schema": { - "oneOf": [ - { - "properties": { - "mail": { - "title": "Mail", - "type": "string", - "x-display": "textarea" - }, - "schemaKey": { - "const": "yes", - "type": "string" - } - }, - "required": [ - "mail" - ], - "title": "Yes" - }, - { - "properties": { - "schemaKey": { - "const": "no", - "type": "string" - } - }, - "title": "No" - } - ], - "title": "Mail available", - "type": "object" - }, - "type": "input" - }, - "search-email-gateway": { - "created": "2021-12-12T12:12:12.000000012Z", - "done": false, - "name": "Search email gateway", - "next": { - "extract-iocs": "" - }, - "type": "task" - } - } - } - }, - "references": [ - { - "href": "https://www.leadmaximize.net/e-services/back-end", - "name": "performance" - }, - { - "href": "http://www.corporateinteractive.name/rich", - "name": "autumn" - }, - { - "href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", - "name": "suggest" - } - ], - "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", - "status": "closed", - "type": "incident" - }, - { - "created": "2021-10-02T16:04:59.078186Z", - "id": 8125, - "modified": "2021-10-02T16:04:59.078186Z", - "name": "phishing from selenafadel@von.com detected", - "owner": "demo", - "references": [ - { - "href": "https://www.seniorleading-edge.name/users/efficient", - "name": "recovery" - }, - { - "href": "http://www.dynamicseamless.com/clicks-and-mortar", - "name": "force" - }, - { - "href": "http://www.leadscalable.biz/envisioneer", - "name": "fund" - } - ], - "schema": "{}", - "status": "closed", - "type": "alert" - } - ], - "type": "alert" - } - } - } - } - } - }, - "/tickettypes": { - "get": { - "security": [ - { - "roles": [ - "tickettype:read" - ] - } - ], - "tags": [ - "tickettypes" - ], - "summary": "List tickettypes", - "operationId": "listTicketTypes", - "responses": { - "200": { - "description": "successful operation", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/TicketTypeResponse" - } - }, - "examples": { - "test": [ - { - "default_playbooks": [], - "default_template": "default", - "icon": "mdi-alert", - "id": "alert", - "name": "Alerts" - }, - { - "default_playbooks": [], - "default_template": "default", - "icon": "mdi-radioactive", - "id": "incident", - "name": "Incidents" - }, - { - "default_playbooks": [], - "default_template": "default", - "icon": "mdi-fingerprint", - "id": "investigation", - "name": "Forensic Investigations" - }, - { - "default_playbooks": [], - "default_template": "default", - "icon": "mdi-target", - "id": "hunt", - "name": "Threat Hunting" - } - ] - } - } - } - }, - "post": { - "security": [ - { - "roles": [ - "tickettype:write" - ] - } - ], - "tags": [ - "tickettypes" - ], - "summary": "Create a new tickettype", - "operationId": "createTicketType", - "parameters": [ - { - "x-example": { - "default_playbooks": [], - "default_template": "default", - "icon": "mdi-newspaper-variant-outline", - "name": "TI Tickets" - }, - "description": "New tickettype", - "name": "tickettype", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/TicketTypeForm" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketTypeResponse" - }, - "examples": { - "test": { - "default_playbooks": [], - "default_template": "default", - "icon": "mdi-newspaper-variant-outline", - "id": "ti-tickets", - "name": "TI Tickets" - } - } - } - } - } - }, - "/tickettypes/{id}": { - "get": { - "security": [ - { - "roles": [ - "tickettype:read" - ] - } - ], - "tags": [ - "tickettypes" - ], - "summary": "Get a single tickettype", - "operationId": "getTicketType", - "parameters": [ - { - "type": "string", - "x-example": "alert", - "description": "TicketType ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketTypeResponse" - }, - "examples": { - "test": { - "default_playbooks": [], - "default_template": "default", - "icon": "mdi-alert", - "id": "alert", - "name": "Alerts" - } - } - } - } - }, - "put": { - "security": [ - { - "roles": [ - "tickettype:write" - ] - } - ], - "tags": [ - "tickettypes" - ], - "summary": "Update an existing tickettype", - "operationId": "updateTicketType", - "parameters": [ - { - "type": "string", - "x-example": "alert", - "description": "TicketType ID", - "name": "id", - "in": "path", - "required": true - }, - { - "x-example": { - "default_playbooks": [], - "default_template": "default", - "icon": "mdi-bell", - "id": "alert", - "name": "Alerts" - }, - "description": "TicketType object that needs to be added", - "name": "tickettype", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/TicketTypeForm" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/TicketTypeResponse" - }, - "examples": { - "test": { - "default_playbooks": [], - "default_template": "default", - "icon": "mdi-bell", - "id": "alert", - "name": "Alerts" - } - } - } - } - }, - "delete": { - "security": [ - { - "roles": [ - "tickettype:write" - ] - } - ], - "tags": [ - "tickettypes" - ], - "summary": "Delete a tickettype", - "operationId": "deleteTicketType", - "parameters": [ - { - "type": "string", - "x-example": "alert", - "description": "TicketType ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "204": { - "description": "successful operation" - } - } - } - }, - "/userdata": { - "get": { - "security": [ - { - "roles": [ - "userdata:read" - ] - } - ], - "tags": [ - "userdata" - ], - "summary": "List userdata", - "operationId": "listUserData", - "responses": { - "200": { - "description": "successful operation", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/UserDataResponse" - } - }, - "examples": { - "test": [ - { - "email": "bob@example.org", - "id": "bob", - "name": "Bob Bad" - } - ] - } - } - } - } - }, - "/userdata/{id}": { - "get": { - "security": [ - { - "roles": [ - "userdata:read" - ] - } - ], - "tags": [ - "userdata" - ], - "summary": "Get a single user data", - "operationId": "getUserData", - "parameters": [ - { - "type": "string", - "x-example": "bob", - "description": "User Data ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/UserDataResponse" - }, - "examples": { - "test": { - "email": "bob@example.org", - "id": "bob", - "name": "Bob Bad" - } - } - } - } - }, - "put": { - "security": [ - { - "roles": [ - "userdata:write" - ] - } - ], - "tags": [ - "userdata" - ], - "summary": "Update an existing user data", - "operationId": "updateUserData", - "parameters": [ - { - "type": "string", - "x-example": "bob", - "description": "User Data ID", - "name": "id", - "in": "path", - "required": true - }, - { - "x-example": { - "blocked": false, - "email": "bob@example.org", - "name": "Bob Bad" - }, - "description": "User data object that needs to be added", - "name": "userdata", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/UserData" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/UserDataResponse" - }, - "examples": { - "test": { - "email": "bob@example.org", - "id": "bob", - "name": "Bob Bad" - } - } - } - } - } - }, - "/users": { - "get": { - "security": [ - { - "roles": [ - "user:read" - ] - } - ], - "tags": [ - "users" - ], - "summary": "List users", - "operationId": "listUsers", - "responses": { - "200": { - "description": "successful operation", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/UserResponse" - } - }, - "examples": { - "test": [ - { - "apikey": false, - "blocked": false, - "id": "bob", - "roles": [ - "admin:backup:read", - "admin:backup:restore", - "admin:group:write", - "admin:job:read", - "admin:job:write", - "admin:log:read", - "admin:ticket:delete", - "admin:user:write", - "admin:userdata:read", - "admin:userdata:write", - "analyst:automation:read", - "analyst:currentsettings:write", - "analyst:currentuser:read", - "analyst:currentuserdata:read", - "analyst:file", - "analyst:group:read", - "analyst:playbook:read", - "analyst:rule:read", - "analyst:settings:read", - "analyst:template:read", - "analyst:ticket:read", - "analyst:ticket:write", - "analyst:tickettype:read", - "analyst:user:read", - "engineer:automation:write", - "engineer:playbook:write", - "engineer:rule:write", - "engineer:template:write", - "engineer:tickettype:write" - ] - }, - { - "apikey": true, - "blocked": false, - "id": "script", - "roles": [ - "analyst:automation:read", - "analyst:currentsettings:write", - "analyst:currentuser:read", - "analyst:currentuserdata:read", - "analyst:file", - "analyst:group:read", - "analyst:playbook:read", - "analyst:rule:read", - "analyst:settings:read", - "analyst:template:read", - "analyst:ticket:read", - "analyst:ticket:write", - "analyst:tickettype:read", - "analyst:user:read", - "engineer:automation:write", - "engineer:playbook:write", - "engineer:rule:write", - "engineer:template:write", - "engineer:tickettype:write" - ] - } - ] - } - } - } - }, - "post": { - "security": [ - { - "roles": [ - "user:write" - ] - } - ], - "tags": [ - "users" - ], - "summary": "Create user", - "operationId": "createUser", - "parameters": [ - { - "x-example": { - "id": "syncscript", - "roles": [ - "analyst" - ] - }, - "description": "user object that needs to be added", - "name": "user", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/UserForm" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/NewUserResponse" - }, - "examples": { - "test": { - "blocked": false, - "id": "syncscript", - "roles": [ - "analyst:automation:read", - "analyst:currentsettings:write", - "analyst:currentuser:read", - "analyst:currentuserdata:read", - "analyst:file", - "analyst:group:read", - "analyst:playbook:read", - "analyst:rule:read", - "analyst:settings:read", - "analyst:template:read", - "analyst:ticket:read", - "analyst:ticket:write", - "analyst:tickettype:read", - "analyst:user:read" - ], - "secret": "v39bOuobnlEljfWzjAgoKzhmnh1xSMxH" - } - } - } - } - } - }, - "/users/{id}": { - "get": { - "security": [ - { - "roles": [ - "user:read" - ] - } - ], - "tags": [ - "users" - ], - "summary": "Get a single user", - "operationId": "getUser", - "parameters": [ - { - "type": "string", - "x-example": "script", - "description": "user ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/UserResponse" - }, - "examples": { - "test": { - "apikey": true, - "blocked": false, - "id": "script", - "roles": [ - "analyst:automation:read", - "analyst:currentsettings:write", - "analyst:currentuser:read", - "analyst:currentuserdata:read", - "analyst:file", - "analyst:group:read", - "analyst:playbook:read", - "analyst:rule:read", - "analyst:settings:read", - "analyst:template:read", - "analyst:ticket:read", - "analyst:ticket:write", - "analyst:tickettype:read", - "analyst:user:read", - "engineer:automation:write", - "engineer:playbook:write", - "engineer:rule:write", - "engineer:template:write", - "engineer:tickettype:write" - ] - } - } - } - } - }, - "put": { - "security": [ - { - "roles": [ - "user:write" - ] - } - ], - "tags": [ - "users" - ], - "summary": "Update user", - "operationId": "updateUser", - "parameters": [ - { - "type": "string", - "x-example": "bob", - "description": "Template ID", - "name": "id", - "in": "path", - "required": true - }, - { - "x-example": { - "roles": [ - "analyst", - "admin" - ] - }, - "description": "user object that needs to be added", - "name": "user", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/UserForm" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/UserResponse" - }, - "examples": { - "test": { - "apikey": false, - "blocked": false, - "id": "bob", - "roles": [ - "admin:backup:read", - "admin:backup:restore", - "admin:group:write", - "admin:job:read", - "admin:job:write", - "admin:log:read", - "admin:ticket:delete", - "admin:user:write", - "admin:userdata:read", - "admin:userdata:write", - "analyst:automation:read", - "analyst:currentsettings:write", - "analyst:currentuser:read", - "analyst:currentuserdata:read", - "analyst:file", - "analyst:group:read", - "analyst:playbook:read", - "analyst:rule:read", - "analyst:settings:read", - "analyst:template:read", - "analyst:ticket:read", - "analyst:ticket:write", - "analyst:tickettype:read", - "analyst:user:read", - "engineer:automation:write", - "engineer:playbook:write", - "engineer:rule:write", - "engineer:template:write", - "engineer:tickettype:write" - ] - } - } - } - } - }, - "delete": { - "security": [ - { - "roles": [ - "user:write" - ] - } - ], - "tags": [ - "users" - ], - "summary": "Delete user", - "operationId": "deleteUser", - "parameters": [ - { - "type": "string", - "x-example": "script", - "description": "user ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "204": { - "description": "successful operation" - } - } - } - } - }, - "definitions": { - "Artifact": { - "type": "object", - "required": [ - "name" - ], - "properties": { - "enrichments": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/Enrichment" - } - }, - "name": { - "type": "string", - "example": "2.2.2.2" - }, - "status": { - "type": "string", - "example": "Unknown" - }, - "type": { - "type": "string" - } - } - }, - "ArtifactOrigin": { - "type": "object", - "required": [ - "ticket_id", - "artifact" - ], - "properties": { - "artifact": { - "type": "string" - }, - "ticket_id": { - "type": "integer", - "format": "int64" - } - } - }, - "Automation": { - "type": "object", - "required": [ - "image", - "script", - "type" - ], - "properties": { - "image": { - "type": "string" - }, - "schema": { - "type": "string", - "example": "{}" - }, - "script": { - "type": "string" - }, - "type": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "artifact", - "playbook", - "global" - ] - } - } - } - }, - "AutomationForm": { - "type": "object", - "required": [ - "id", - "image", - "script", - "type" - ], - "properties": { - "id": { - "type": "string" - }, - "image": { - "type": "string" - }, - "schema": { - "type": "string", - "example": "{}" - }, - "script": { - "type": "string" - }, - "type": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "artifact", - "playbook", - "global" - ] - } - } - } - }, - "AutomationResponse": { - "type": "object", - "required": [ - "id", - "image", - "script", - "type" - ], - "properties": { - "id": { - "type": "string" - }, - "image": { - "type": "string" - }, - "schema": { - "type": "string", - "example": "{}" - }, - "script": { - "type": "string" - }, - "type": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "artifact", - "playbook", - "global" - ] - } - } - } - }, - "Comment": { - "type": "object", - "required": [ - "creator", - "created", - "message" - ], - "properties": { - "created": { - "type": "string", - "format": "date-time" - }, - "creator": { - "type": "string" - }, - "message": { - "type": "string" - } - } - }, - "CommentForm": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "created": { - "type": "string", - "format": "date-time" - }, - "creator": { - "type": "string" - }, - "message": { - "type": "string" - } - } - }, - "Context": { - "type": "object", - "properties": { - "artifact": { - "$ref": "#/definitions/Artifact" - }, - "playbook": { - "$ref": "#/definitions/PlaybookResponse" - }, - "task": { - "$ref": "#/definitions/TaskResponse" - }, - "ticket": { - "$ref": "#/definitions/TicketResponse" - } - } - }, - "Enrichment": { - "type": "object", - "required": [ - "name", - "data", - "created" - ], - "properties": { - "created": { - "type": "string", - "format": "date-time", - "example": "1985-04-12T23:20:50.52Z" - }, - "data": { - "type": "object", - "example": { - "hash": "b7a067a742c20d07a7456646de89bc2d408a1153" - } - }, - "name": { - "type": "string", - "example": "hash.sha1" - } - } - }, - "EnrichmentForm": { - "type": "object", - "required": [ - "name", - "data" - ], - "properties": { - "data": { - "type": "object", - "example": { - "hash": "b7a067a742c20d07a7456646de89bc2d408a1153" - } - }, - "name": { - "type": "string", - "example": "hash.sha1" - } - } - }, - "File": { - "type": "object", - "required": [ - "key", - "name" - ], - "properties": { - "key": { - "type": "string", - "example": "myfile" - }, - "name": { - "type": "string", - "example": "notes.docx" - } - } - }, - "Job": { - "type": "object", - "required": [ - "automation", - "running", - "status" - ], - "properties": { - "automation": { - "type": "string" - }, - "container": { - "type": "string" - }, - "log": { - "type": "string" - }, - "origin": { - "$ref": "#/definitions/Origin" - }, - "output": { - "type": "object" - }, - "payload": {}, - "running": { - "type": "boolean" - }, - "status": { - "type": "string" - } - } - }, - "JobForm": { - "type": "object", - "required": [ - "automation" - ], - "properties": { - "automation": { - "type": "string" - }, - "origin": { - "$ref": "#/definitions/Origin" - }, - "payload": {} - } - }, - "JobResponse": { - "type": "object", - "required": [ - "id", - "automation", - "status" - ], - "properties": { - "automation": { - "type": "string" - }, - "container": { - "type": "string" - }, - "id": { - "type": "string" - }, - "log": { - "type": "string" - }, - "origin": { - "$ref": "#/definitions/Origin" - }, - "output": { - "type": "object" - }, - "payload": {}, - "status": { - "type": "string" - } - } - }, - "LogEntry": { - "type": "object", - "required": [ - "type", - "reference", - "creator", - "created", - "message" - ], - "properties": { - "created": { - "type": "string", - "format": "date-time" - }, - "creator": { - "type": "string" - }, - "message": { - "type": "string" - }, - "reference": { - "type": "string" - }, - "type": { - "type": "string" - } - } - }, - "Message": { - "type": "object", - "properties": { - "context": { - "$ref": "#/definitions/Context" - }, - "payload": { - "type": "object" - }, - "secrets": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - } - }, - "NewUserResponse": { - "type": "object", - "required": [ - "id", - "blocked", - "roles" - ], - "properties": { - "blocked": { - "type": "boolean" - }, - "id": { - "type": "string" - }, - "roles": { - "type": "array", - "items": { - "type": "string" - } - }, - "secret": { - "type": "string" - } - } - }, - "Origin": { - "type": "object", - "properties": { - "artifact_origin": { - "$ref": "#/definitions/ArtifactOrigin" - }, - "task_origin": { - "$ref": "#/definitions/TaskOrigin" - } - } - }, - "Playbook": { - "type": "object", - "required": [ - "name", - "tasks" - ], - "properties": { - "name": { - "type": "string", - "example": "Phishing" - }, - "tasks": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/Task" - } - } - } - }, - "PlaybookResponse": { - "type": "object", - "required": [ - "name", - "tasks" - ], - "properties": { - "name": { - "type": "string", - "example": "Phishing" - }, - "tasks": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/TaskResponse" - } - } - } - }, - "PlaybookTemplate": { - "type": "object", - "required": [ - "name", - "yaml" - ], - "properties": { - "name": { - "type": "string" - }, - "yaml": { - "type": "string" - } - } - }, - "PlaybookTemplateForm": { - "type": "object", - "required": [ - "yaml" - ], - "properties": { - "id": { - "type": "string" - }, - "yaml": { - "type": "string" - } - } - }, - "PlaybookTemplateResponse": { - "type": "object", - "required": [ - "id", - "name", - "yaml" - ], - "properties": { - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "yaml": { - "type": "string" - } - } - }, - "Reference": { - "type": "object", - "required": [ - "name", - "href" - ], - "properties": { - "href": { - "type": "string", - "example": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=cve-2017-0144" - }, - "name": { - "type": "string", - "example": "CVE-2017-0144" - } - } - }, - "Settings": { - "type": "object", - "required": [ - "version", - "tier", - "timeformat", - "ticketTypes", - "artifactStates" - ], - "properties": { - "artifactStates": { - "type": "array", - "title": "Artifact States", - "items": { - "$ref": "#/definitions/Type" - } - }, - "roles": { - "type": "array", - "title": "Roles", - "items": { - "type": "string" - } - }, - "ticketTypes": { - "type": "array", - "title": "Ticket Types", - "items": { - "$ref": "#/definitions/TicketTypeResponse" - } - }, - "tier": { - "type": "string", - "title": "Tier", - "enum": [ - "community", - "enterprise" - ] - }, - "timeformat": { - "type": "string", - "title": "Time Format" - }, - "version": { - "type": "string", - "title": "Version" - } - } - }, - "Statistics": { - "type": "object", - "required": [ - "unassigned", - "open_tickets_per_user", - "tickets_per_week", - "tickets_per_type" - ], - "properties": { - "open_tickets_per_user": { - "type": "object", - "additionalProperties": { - "type": "integer" - } - }, - "tickets_per_type": { - "type": "object", - "additionalProperties": { - "type": "integer" - } - }, - "tickets_per_week": { - "type": "object", - "additionalProperties": { - "type": "integer" - } - }, - "unassigned": { - "type": "integer" - } - } - }, - "Task": { - "type": "object", - "required": [ - "name", - "type", - "done", - "created" - ], - "properties": { - "automation": { - "type": "string" - }, - "closed": { - "type": "string", - "format": "date-time", - "example": "1985-04-12T23:20:50.52Z" - }, - "created": { - "type": "string", - "format": "date-time", - "example": "1985-04-12T23:20:50.52Z" - }, - "data": { - "type": "object" - }, - "done": { - "type": "boolean" - }, - "join": { - "type": "boolean", - "example": false - }, - "name": { - "type": "string", - "example": "Inform user" - }, - "next": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "owner": { - "type": "string" - }, - "payload": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "schema": { - "type": "object" - }, - "type": { - "type": "string", - "enum": [ - "task", - "input", - "automation" - ], - "example": "task" - } - } - }, - "TaskForm": { - "type": "object", - "required": [ - "name", - "type" - ], - "properties": { - "automation": { - "type": "string" - }, - "closed": { - "type": "string", - "format": "date-time", - "example": "1985-04-12T23:20:50.52Z" - }, - "created": { - "type": "string", - "format": "date-time", - "example": "1985-04-12T23:20:50.52Z" - }, - "data": { - "type": "object" - }, - "done": { - "type": "boolean" - }, - "join": { - "type": "boolean", - "example": false - }, - "name": { - "type": "string", - "example": "Inform user" - }, - "next": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "owner": { - "type": "string" - }, - "payload": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "schema": { - "type": "object" - }, - "type": { - "type": "string", - "enum": [ - "task", - "input", - "automation" - ], - "example": "task" - } - } - }, - "TaskOrigin": { - "type": "object", - "required": [ - "ticket_id", - "playbook_id", - "task_id" - ], - "properties": { - "playbook_id": { - "type": "string" - }, - "task_id": { - "type": "string" - }, - "ticket_id": { - "type": "integer", - "format": "int64" - } - } - }, - "TaskResponse": { - "type": "object", - "required": [ - "name", - "type", - "done", - "created", - "order", - "active" - ], - "properties": { - "active": { - "type": "boolean", - "example": false - }, - "automation": { - "type": "string" - }, - "closed": { - "type": "string", - "format": "date-time", - "example": "1985-04-12T23:20:50.52Z" - }, - "created": { - "type": "string", - "format": "date-time", - "example": "1985-04-12T23:20:50.52Z" - }, - "data": { - "type": "object" - }, - "done": { - "type": "boolean" - }, - "join": { - "type": "boolean", - "example": false - }, - "name": { - "type": "string", - "example": "Inform user" - }, - "next": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "order": { - "type": "number", - "format": "int64", - "example": 2 - }, - "owner": { - "type": "string" - }, - "payload": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "schema": { - "type": "object" - }, - "type": { - "type": "string", - "enum": [ - "task", - "input", - "automation" - ], - "example": "task" - } - } - }, - "TaskWithContext": { - "type": "object", - "required": [ - "ticket_id", - "ticket_name", - "playbook_id", - "playbook_name", - "task_id", - "task" - ], - "properties": { - "playbook_id": { - "type": "string" - }, - "playbook_name": { - "type": "string" - }, - "task": { - "$ref": "#/definitions/TaskResponse" - }, - "task_id": { - "type": "string" - }, - "ticket_id": { - "type": "number", - "format": "int64" - }, - "ticket_name": { - "type": "string" - } - } - }, - "Ticket": { - "type": "object", - "required": [ - "name", - "type", - "status", - "created", - "modified", - "schema" - ], - "properties": { - "artifacts": { - "type": "array", - "items": { - "$ref": "#/definitions/Artifact" - } - }, - "comments": { - "type": "array", - "items": { - "$ref": "#/definitions/Comment" - } - }, - "created": { - "type": "string", - "format": "date-time", - "example": "1985-04-12T23:20:50.52Z" - }, - "details": { - "type": "object", - "example": { - "description": "my little incident" - } - }, - "files": { - "type": "array", - "items": { - "$ref": "#/definitions/File" - } - }, - "modified": { - "type": "string", - "format": "date-time", - "example": "1985-04-12T23:20:50.52Z" - }, - "name": { - "type": "string", - "example": "WannyCry" - }, - "owner": { - "type": "string", - "example": "bob" - }, - "playbooks": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/Playbook" - } - }, - "read": { - "type": "array", - "items": { - "type": "string" - }, - "example": [ - "bob" - ] - }, - "references": { - "type": "array", - "items": { - "$ref": "#/definitions/Reference" - } - }, - "schema": { - "type": "string", - "example": "{}" - }, - "status": { - "type": "string", - "example": "open" - }, - "type": { - "type": "string", - "example": "incident" - }, - "write": { - "type": "array", - "items": { - "type": "string" - }, - "example": [ - "alice" - ] - } - } - }, - "TicketForm": { - "type": "object", - "required": [ - "name", - "type", - "status" - ], - "properties": { - "artifacts": { - "type": "array", - "items": { - "$ref": "#/definitions/Artifact" - } - }, - "comments": { - "type": "array", - "items": { - "$ref": "#/definitions/Comment" - } - }, - "created": { - "type": "string", - "format": "date-time", - "example": "1985-04-12T23:20:50.52Z" - }, - "details": { - "type": "object", - "example": { - "description": "my little incident" - } - }, - "files": { - "type": "array", - "items": { - "$ref": "#/definitions/File" - } - }, - "id": { - "type": "integer", - "format": "int64", - "example": 123 - }, - "modified": { - "type": "string", - "format": "date-time", - "example": "1985-04-12T23:20:50.52Z" - }, - "name": { - "type": "string", - "example": "WannyCry" - }, - "owner": { - "type": "string", - "example": "bob" - }, - "playbooks": { - "type": "array", - "items": { - "$ref": "#/definitions/PlaybookTemplateForm" - } - }, - "read": { - "type": "array", - "items": { - "type": "string" - }, - "example": [ - "bob" - ] - }, - "references": { - "type": "array", - "items": { - "$ref": "#/definitions/Reference" - } - }, - "schema": { - "type": "string", - "example": "{}" - }, - "status": { - "type": "string", - "example": "open" - }, - "type": { - "type": "string", - "example": "incident" - }, - "write": { - "type": "array", - "items": { - "type": "string" - }, - "example": [ - "alice" - ] - } - } - }, - "TicketList": { - "type": "object", - "required": [ - "tickets", - "count" - ], - "properties": { - "count": { - "type": "number", - "example": 3 - }, - "tickets": { - "type": "array", - "items": { - "$ref": "#/definitions/TicketSimpleResponse" - } - } - } - }, - "TicketResponse": { - "type": "object", - "required": [ - "id", - "name", - "type", - "status", - "created", - "modified", - "schema" - ], - "properties": { - "artifacts": { - "type": "array", - "items": { - "$ref": "#/definitions/Artifact" - } - }, - "comments": { - "type": "array", - "items": { - "$ref": "#/definitions/Comment" - } - }, - "created": { - "type": "string", - "format": "date-time", - "example": "1985-04-12T23:20:50.52Z" - }, - "details": { - "type": "object", - "example": { - "description": "my little incident" - } - }, - "files": { - "type": "array", - "items": { - "$ref": "#/definitions/File" - } - }, - "id": { - "type": "integer", - "format": "int64", - "example": 123 - }, - "modified": { - "type": "string", - "format": "date-time", - "example": "1985-04-12T23:20:50.52Z" - }, - "name": { - "type": "string", - "example": "WannyCry" - }, - "owner": { - "type": "string", - "example": "bob" - }, - "playbooks": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/PlaybookResponse" - } - }, - "read": { - "type": "array", - "items": { - "type": "string" - }, - "example": [ - "bob" - ] - }, - "references": { - "type": "array", - "items": { - "$ref": "#/definitions/Reference" - } - }, - "schema": { - "type": "string", - "example": "{}" - }, - "status": { - "type": "string", - "example": "open" - }, - "type": { - "type": "string", - "example": "incident" - }, - "write": { - "type": "array", - "items": { - "type": "string" - }, - "example": [ - "alice" - ] - } - } - }, - "TicketSimpleResponse": { - "type": "object", - "required": [ - "id", - "name", - "type", - "status", - "created", - "modified", - "schema" - ], - "properties": { - "artifacts": { - "type": "array", - "items": { - "$ref": "#/definitions/Artifact" - } - }, - "comments": { - "type": "array", - "items": { - "$ref": "#/definitions/Comment" - } - }, - "created": { - "type": "string", - "format": "date-time", - "example": "1985-04-12T23:20:50.52Z" - }, - "details": { - "type": "object", - "example": { - "description": "my little incident" - } - }, - "files": { - "type": "array", - "items": { - "$ref": "#/definitions/File" - } - }, - "id": { - "type": "integer", - "format": "int64", - "example": 123 - }, - "modified": { - "type": "string", - "format": "date-time", - "example": "1985-04-12T23:20:50.52Z" - }, - "name": { - "type": "string", - "example": "WannyCry" - }, - "owner": { - "type": "string", - "example": "bob" - }, - "playbooks": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/Playbook" - } - }, - "read": { - "type": "array", - "items": { - "type": "string" - }, - "example": [ - "bob" - ] - }, - "references": { - "type": "array", - "items": { - "$ref": "#/definitions/Reference" - } - }, - "schema": { - "type": "string", - "example": "{}" - }, - "status": { - "type": "string", - "example": "open" - }, - "type": { - "type": "string", - "example": "incident" - }, - "write": { - "type": "array", - "items": { - "type": "string" - }, - "example": [ - "alice" - ] - } - } - }, - "TicketTemplate": { - "type": "object", - "required": [ - "name", - "schema" - ], - "properties": { - "name": { - "type": "string" - }, - "schema": { - "type": "string" - } - } - }, - "TicketTemplateForm": { - "type": "object", - "required": [ - "name", - "schema" - ], - "properties": { - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "schema": { - "type": "string" - } - } - }, - "TicketTemplateResponse": { - "type": "object", - "required": [ - "id", - "name", - "schema" - ], - "properties": { - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "schema": { - "type": "string" - } - } - }, - "TicketType": { - "type": "object", - "required": [ - "name", - "icon", - "default_template", - "default_playbooks" - ], - "properties": { - "default_groups": { - "type": "array", - "items": { - "type": "string" - } - }, - "default_playbooks": { - "type": "array", - "items": { - "type": "string" - } - }, - "default_template": { - "type": "string" - }, - "icon": { - "type": "string" - }, - "name": { - "type": "string" - } - } - }, - "TicketTypeForm": { - "type": "object", - "required": [ - "name", - "icon", - "default_template", - "default_playbooks" - ], - "properties": { - "default_groups": { - "type": "array", - "items": { - "type": "string" - } - }, - "default_playbooks": { - "type": "array", - "items": { - "type": "string" - } - }, - "default_template": { - "type": "string" - }, - "icon": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - } - } - }, - "TicketTypeResponse": { - "type": "object", - "required": [ - "id", - "name", - "icon", - "default_template", - "default_playbooks" - ], - "properties": { - "default_groups": { - "type": "array", - "items": { - "type": "string" - } - }, - "default_playbooks": { - "type": "array", - "items": { - "type": "string" - } - }, - "default_template": { - "type": "string" - }, - "icon": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - } - } - }, - "TicketWithTickets": { - "type": "object", - "required": [ - "id", - "name", - "type", - "status", - "created", - "modified", - "schema" - ], - "properties": { - "artifacts": { - "type": "array", - "items": { - "$ref": "#/definitions/Artifact" - } - }, - "comments": { - "type": "array", - "items": { - "$ref": "#/definitions/Comment" - } - }, - "created": { - "type": "string", - "format": "date-time", - "example": "1985-04-12T23:20:50.52Z" - }, - "details": { - "type": "object", - "example": { - "description": "my little incident" - } - }, - "files": { - "type": "array", - "items": { - "$ref": "#/definitions/File" - } - }, - "id": { - "type": "integer", - "format": "int64", - "example": 123 - }, - "logs": { - "type": "array", - "items": { - "$ref": "#/definitions/LogEntry" - } - }, - "modified": { - "type": "string", - "format": "date-time", - "example": "1985-04-12T23:20:50.52Z" - }, - "name": { - "type": "string", - "example": "WannyCry" - }, - "owner": { - "type": "string", - "example": "bob" - }, - "playbooks": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/PlaybookResponse" - } - }, - "read": { - "type": "array", - "items": { - "type": "string" - }, - "example": [ - "bob" - ] - }, - "references": { - "type": "array", - "items": { - "$ref": "#/definitions/Reference" - } - }, - "schema": { - "type": "string", - "example": "{}" - }, - "status": { - "type": "string", - "example": "open" - }, - "tickets": { - "type": "array", - "items": { - "$ref": "#/definitions/TicketSimpleResponse" - } - }, - "type": { - "type": "string", - "example": "incident" - }, - "write": { - "type": "array", - "items": { - "type": "string" - }, - "example": [ - "alice" - ] - } - } - }, - "Type": { - "type": "object", - "required": [ - "id", - "name", - "icon" - ], - "properties": { - "color": { - "type": "string", - "title": "Color", - "enum": [ - "error", - "info", - "success", - "warning" - ], - "x-cols": 3 - }, - "icon": { - "type": "string", - "title": "Icon (https://materialdesignicons.com)", - "x-class": "pr-2", - "x-cols": 3 - }, - "id": { - "type": "string", - "title": "ID", - "x-class": "pr-2", - "x-cols": 3 - }, - "name": { - "type": "string", - "title": "Name", - "x-class": "pr-2", - "x-cols": 3 - } - } - }, - "User": { - "type": "object", - "required": [ - "blocked", - "apikey", - "roles" - ], - "properties": { - "apikey": { - "type": "boolean" - }, - "blocked": { - "type": "boolean" - }, - "roles": { - "type": "array", - "items": { - "type": "string" - } - }, - "sha256": { - "type": "string" - } - } - }, - "UserData": { - "type": "object", - "properties": { - "email": { - "type": "string", - "x-example": "bob@example.org" - }, - "image": { - "type": "string", - "x-display": "custom-avatar" - }, - "name": { - "type": "string", - "x-example": "Robert Smith" - }, - "timeformat": { - "type": "string", - "title": "Time Format (https://moment.github.io/luxon/docs/manual/formatting.html#table-of-tokens)" - } - } - }, - "UserDataResponse": { - "type": "object", - "required": [ - "id" - ], - "properties": { - "email": { - "type": "string", - "x-example": "bob@example.org" - }, - "id": { - "type": "string" - }, - "image": { - "type": "string", - "x-display": "custom-avatar" - }, - "name": { - "type": "string", - "x-example": "Robert Smith" - }, - "timeformat": { - "type": "string", - "title": "Time Format (https://moment.github.io/luxon/docs/manual/formatting.html#table-of-tokens)" - } - } - }, - "UserForm": { - "type": "object", - "required": [ - "id", - "blocked", - "roles", - "apikey" - ], - "properties": { - "apikey": { - "type": "boolean" - }, - "blocked": { - "type": "boolean" - }, - "id": { - "type": "string" - }, - "roles": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "UserResponse": { - "type": "object", - "required": [ - "id", - "blocked", - "roles", - "apikey" - ], - "properties": { - "apikey": { - "type": "boolean" - }, - "blocked": { - "type": "boolean" - }, - "id": { - "type": "string" - }, - "roles": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - } -}`)) -} diff --git a/generated/restapi/operations/automations/create_automation_parameters.go b/generated/restapi/operations/automations/create_automation_parameters.go deleted file mode 100644 index 2fb2634..0000000 --- a/generated/restapi/operations/automations/create_automation_parameters.go +++ /dev/null @@ -1,90 +0,0 @@ -package automations - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "io" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime" - - "github.com/SecurityBrewery/catalyst/generated/models" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// CreateAutomationEndpoint executes the core logic of the related -// route endpoint. -func CreateAutomationEndpoint(handler func(ctx context.Context, params *CreateAutomationParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewCreateAutomationParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewCreateAutomationParams creates a new CreateAutomationParams object -// with the default values initialized. -func NewCreateAutomationParams() *CreateAutomationParams { - var () - return &CreateAutomationParams{} -} - -// CreateAutomationParams contains all the bound params for the create automation operation -// typically these are obtained from a http.Request -// -// swagger:parameters createAutomation -type CreateAutomationParams struct { - - /*New automation - Required: true - In: body - */ - Automation *models.AutomationForm -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *CreateAutomationParams) ReadRequest(ctx *gin.Context) error { - var res []error - - if runtime.HasBody(ctx.Request) { - var body models.AutomationForm - if err := ctx.BindJSON(&body); err != nil { - if err == io.EOF { - res = append(res, errors.Required("automation", "body", "")) - } else { - res = append(res, errors.NewParseError("automation", "body", "", err)) - } - - } else { - o.Automation = &body - } - } else { - res = append(res, errors.Required("automation", "body", "")) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} diff --git a/generated/restapi/operations/automations/delete_automation_parameters.go b/generated/restapi/operations/automations/delete_automation_parameters.go deleted file mode 100644 index 8aef194..0000000 --- a/generated/restapi/operations/automations/delete_automation_parameters.go +++ /dev/null @@ -1,87 +0,0 @@ -package automations - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// DeleteAutomationEndpoint executes the core logic of the related -// route endpoint. -func DeleteAutomationEndpoint(handler func(ctx context.Context, params *DeleteAutomationParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewDeleteAutomationParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewDeleteAutomationParams creates a new DeleteAutomationParams object -// with the default values initialized. -func NewDeleteAutomationParams() *DeleteAutomationParams { - var () - return &DeleteAutomationParams{} -} - -// DeleteAutomationParams contains all the bound params for the delete automation operation -// typically these are obtained from a http.Request -// -// swagger:parameters deleteAutomation -type DeleteAutomationParams struct { - - /*Automation ID - Required: true - In: path - */ - ID string -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *DeleteAutomationParams) ReadRequest(ctx *gin.Context) error { - var res []error - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *DeleteAutomationParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - o.ID = raw - - return nil -} diff --git a/generated/restapi/operations/automations/get_automation_parameters.go b/generated/restapi/operations/automations/get_automation_parameters.go deleted file mode 100644 index ff5907c..0000000 --- a/generated/restapi/operations/automations/get_automation_parameters.go +++ /dev/null @@ -1,87 +0,0 @@ -package automations - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// GetAutomationEndpoint executes the core logic of the related -// route endpoint. -func GetAutomationEndpoint(handler func(ctx context.Context, params *GetAutomationParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewGetAutomationParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewGetAutomationParams creates a new GetAutomationParams object -// with the default values initialized. -func NewGetAutomationParams() *GetAutomationParams { - var () - return &GetAutomationParams{} -} - -// GetAutomationParams contains all the bound params for the get automation operation -// typically these are obtained from a http.Request -// -// swagger:parameters getAutomation -type GetAutomationParams struct { - - /*Automation ID - Required: true - In: path - */ - ID string -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *GetAutomationParams) ReadRequest(ctx *gin.Context) error { - var res []error - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *GetAutomationParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - o.ID = raw - - return nil -} diff --git a/generated/restapi/operations/automations/list_automations_parameters.go b/generated/restapi/operations/automations/list_automations_parameters.go deleted file mode 100644 index 68673db..0000000 --- a/generated/restapi/operations/automations/list_automations_parameters.go +++ /dev/null @@ -1,55 +0,0 @@ -package automations - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// ListAutomationsEndpoint executes the core logic of the related -// route endpoint. -func ListAutomationsEndpoint(handler func(ctx context.Context) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - resp := handler(ctx) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewListAutomationsParams creates a new ListAutomationsParams object -// with the default values initialized. -func NewListAutomationsParams() *ListAutomationsParams { - var () - return &ListAutomationsParams{} -} - -// ListAutomationsParams contains all the bound params for the list automations operation -// typically these are obtained from a http.Request -// -// swagger:parameters listAutomations -type ListAutomationsParams struct { -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *ListAutomationsParams) ReadRequest(ctx *gin.Context) error { - var res []error - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} diff --git a/generated/restapi/operations/automations/update_automation_parameters.go b/generated/restapi/operations/automations/update_automation_parameters.go deleted file mode 100644 index 785fe06..0000000 --- a/generated/restapi/operations/automations/update_automation_parameters.go +++ /dev/null @@ -1,111 +0,0 @@ -package automations - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "io" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime" - - "github.com/SecurityBrewery/catalyst/generated/models" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// UpdateAutomationEndpoint executes the core logic of the related -// route endpoint. -func UpdateAutomationEndpoint(handler func(ctx context.Context, params *UpdateAutomationParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewUpdateAutomationParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewUpdateAutomationParams creates a new UpdateAutomationParams object -// with the default values initialized. -func NewUpdateAutomationParams() *UpdateAutomationParams { - var () - return &UpdateAutomationParams{} -} - -// UpdateAutomationParams contains all the bound params for the update automation operation -// typically these are obtained from a http.Request -// -// swagger:parameters updateAutomation -type UpdateAutomationParams struct { - - /*Automation object that needs to be added - Required: true - In: body - */ - Automation *models.AutomationForm - /*Automation ID - Required: true - In: path - */ - ID string -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *UpdateAutomationParams) ReadRequest(ctx *gin.Context) error { - var res []error - - if runtime.HasBody(ctx.Request) { - var body models.AutomationForm - if err := ctx.BindJSON(&body); err != nil { - if err == io.EOF { - res = append(res, errors.Required("automation", "body", "")) - } else { - res = append(res, errors.NewParseError("automation", "body", "", err)) - } - - } else { - o.Automation = &body - } - } else { - res = append(res, errors.Required("automation", "body", "")) - } - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *UpdateAutomationParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - o.ID = raw - - return nil -} diff --git a/generated/restapi/operations/jobs/get_job_parameters.go b/generated/restapi/operations/jobs/get_job_parameters.go deleted file mode 100644 index d51044c..0000000 --- a/generated/restapi/operations/jobs/get_job_parameters.go +++ /dev/null @@ -1,87 +0,0 @@ -package jobs - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// GetJobEndpoint executes the core logic of the related -// route endpoint. -func GetJobEndpoint(handler func(ctx context.Context, params *GetJobParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewGetJobParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewGetJobParams creates a new GetJobParams object -// with the default values initialized. -func NewGetJobParams() *GetJobParams { - var () - return &GetJobParams{} -} - -// GetJobParams contains all the bound params for the get job operation -// typically these are obtained from a http.Request -// -// swagger:parameters getJob -type GetJobParams struct { - - /*Job ID - Required: true - In: path - */ - ID string -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *GetJobParams) ReadRequest(ctx *gin.Context) error { - var res []error - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *GetJobParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - o.ID = raw - - return nil -} diff --git a/generated/restapi/operations/jobs/list_jobs_parameters.go b/generated/restapi/operations/jobs/list_jobs_parameters.go deleted file mode 100644 index ab90ddb..0000000 --- a/generated/restapi/operations/jobs/list_jobs_parameters.go +++ /dev/null @@ -1,55 +0,0 @@ -package jobs - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// ListJobsEndpoint executes the core logic of the related -// route endpoint. -func ListJobsEndpoint(handler func(ctx context.Context) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - resp := handler(ctx) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewListJobsParams creates a new ListJobsParams object -// with the default values initialized. -func NewListJobsParams() *ListJobsParams { - var () - return &ListJobsParams{} -} - -// ListJobsParams contains all the bound params for the list jobs operation -// typically these are obtained from a http.Request -// -// swagger:parameters listJobs -type ListJobsParams struct { -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *ListJobsParams) ReadRequest(ctx *gin.Context) error { - var res []error - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} diff --git a/generated/restapi/operations/jobs/run_job_parameters.go b/generated/restapi/operations/jobs/run_job_parameters.go deleted file mode 100644 index 5480d1d..0000000 --- a/generated/restapi/operations/jobs/run_job_parameters.go +++ /dev/null @@ -1,90 +0,0 @@ -package jobs - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "io" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime" - - "github.com/SecurityBrewery/catalyst/generated/models" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// RunJobEndpoint executes the core logic of the related -// route endpoint. -func RunJobEndpoint(handler func(ctx context.Context, params *RunJobParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewRunJobParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewRunJobParams creates a new RunJobParams object -// with the default values initialized. -func NewRunJobParams() *RunJobParams { - var () - return &RunJobParams{} -} - -// RunJobParams contains all the bound params for the run job operation -// typically these are obtained from a http.Request -// -// swagger:parameters runJob -type RunJobParams struct { - - /*New job - Required: true - In: body - */ - Job *models.JobForm -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *RunJobParams) ReadRequest(ctx *gin.Context) error { - var res []error - - if runtime.HasBody(ctx.Request) { - var body models.JobForm - if err := ctx.BindJSON(&body); err != nil { - if err == io.EOF { - res = append(res, errors.Required("job", "body", "")) - } else { - res = append(res, errors.NewParseError("job", "body", "", err)) - } - - } else { - o.Job = &body - } - } else { - res = append(res, errors.Required("job", "body", "")) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} diff --git a/generated/restapi/operations/jobs/update_job_parameters.go b/generated/restapi/operations/jobs/update_job_parameters.go deleted file mode 100644 index caeab53..0000000 --- a/generated/restapi/operations/jobs/update_job_parameters.go +++ /dev/null @@ -1,111 +0,0 @@ -package jobs - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "io" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime" - - "github.com/SecurityBrewery/catalyst/generated/models" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// UpdateJobEndpoint executes the core logic of the related -// route endpoint. -func UpdateJobEndpoint(handler func(ctx context.Context, params *UpdateJobParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewUpdateJobParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewUpdateJobParams creates a new UpdateJobParams object -// with the default values initialized. -func NewUpdateJobParams() *UpdateJobParams { - var () - return &UpdateJobParams{} -} - -// UpdateJobParams contains all the bound params for the update job operation -// typically these are obtained from a http.Request -// -// swagger:parameters updateJob -type UpdateJobParams struct { - - /*Job ID - Required: true - In: path - */ - ID string - /*Job object that needs to be added - Required: true - In: body - */ - Job *models.Job -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *UpdateJobParams) ReadRequest(ctx *gin.Context) error { - var res []error - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - if runtime.HasBody(ctx.Request) { - var body models.Job - if err := ctx.BindJSON(&body); err != nil { - if err == io.EOF { - res = append(res, errors.Required("job", "body", "")) - } else { - res = append(res, errors.NewParseError("job", "body", "", err)) - } - - } else { - o.Job = &body - } - } else { - res = append(res, errors.Required("job", "body", "")) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *UpdateJobParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - o.ID = raw - - return nil -} diff --git a/generated/restapi/operations/logs/get_logs_parameters.go b/generated/restapi/operations/logs/get_logs_parameters.go deleted file mode 100644 index 29236d5..0000000 --- a/generated/restapi/operations/logs/get_logs_parameters.go +++ /dev/null @@ -1,87 +0,0 @@ -package logs - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// GetLogsEndpoint executes the core logic of the related -// route endpoint. -func GetLogsEndpoint(handler func(ctx context.Context, params *GetLogsParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewGetLogsParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewGetLogsParams creates a new GetLogsParams object -// with the default values initialized. -func NewGetLogsParams() *GetLogsParams { - var () - return &GetLogsParams{} -} - -// GetLogsParams contains all the bound params for the get logs operation -// typically these are obtained from a http.Request -// -// swagger:parameters getLogs -type GetLogsParams struct { - - /*Reference - Required: true - In: path - */ - Reference string -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *GetLogsParams) ReadRequest(ctx *gin.Context) error { - var res []error - - rReference := []string{ctx.Param("reference")} - if err := o.bindReference(rReference, true); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *GetLogsParams) bindReference(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - o.Reference = raw - - return nil -} diff --git a/generated/restapi/operations/playbooks/create_playbook_parameters.go b/generated/restapi/operations/playbooks/create_playbook_parameters.go deleted file mode 100644 index 1f80305..0000000 --- a/generated/restapi/operations/playbooks/create_playbook_parameters.go +++ /dev/null @@ -1,90 +0,0 @@ -package playbooks - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "io" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime" - - "github.com/SecurityBrewery/catalyst/generated/models" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// CreatePlaybookEndpoint executes the core logic of the related -// route endpoint. -func CreatePlaybookEndpoint(handler func(ctx context.Context, params *CreatePlaybookParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewCreatePlaybookParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewCreatePlaybookParams creates a new CreatePlaybookParams object -// with the default values initialized. -func NewCreatePlaybookParams() *CreatePlaybookParams { - var () - return &CreatePlaybookParams{} -} - -// CreatePlaybookParams contains all the bound params for the create playbook operation -// typically these are obtained from a http.Request -// -// swagger:parameters createPlaybook -type CreatePlaybookParams struct { - - /*New playbook - Required: true - In: body - */ - Playbook *models.PlaybookTemplateForm -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *CreatePlaybookParams) ReadRequest(ctx *gin.Context) error { - var res []error - - if runtime.HasBody(ctx.Request) { - var body models.PlaybookTemplateForm - if err := ctx.BindJSON(&body); err != nil { - if err == io.EOF { - res = append(res, errors.Required("playbook", "body", "")) - } else { - res = append(res, errors.NewParseError("playbook", "body", "", err)) - } - - } else { - o.Playbook = &body - } - } else { - res = append(res, errors.Required("playbook", "body", "")) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} diff --git a/generated/restapi/operations/playbooks/delete_playbook_parameters.go b/generated/restapi/operations/playbooks/delete_playbook_parameters.go deleted file mode 100644 index ba16dd7..0000000 --- a/generated/restapi/operations/playbooks/delete_playbook_parameters.go +++ /dev/null @@ -1,87 +0,0 @@ -package playbooks - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// DeletePlaybookEndpoint executes the core logic of the related -// route endpoint. -func DeletePlaybookEndpoint(handler func(ctx context.Context, params *DeletePlaybookParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewDeletePlaybookParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewDeletePlaybookParams creates a new DeletePlaybookParams object -// with the default values initialized. -func NewDeletePlaybookParams() *DeletePlaybookParams { - var () - return &DeletePlaybookParams{} -} - -// DeletePlaybookParams contains all the bound params for the delete playbook operation -// typically these are obtained from a http.Request -// -// swagger:parameters deletePlaybook -type DeletePlaybookParams struct { - - /*Playbook name - Required: true - In: path - */ - ID string -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *DeletePlaybookParams) ReadRequest(ctx *gin.Context) error { - var res []error - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *DeletePlaybookParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - o.ID = raw - - return nil -} diff --git a/generated/restapi/operations/playbooks/get_playbook_parameters.go b/generated/restapi/operations/playbooks/get_playbook_parameters.go deleted file mode 100644 index 8aed8d2..0000000 --- a/generated/restapi/operations/playbooks/get_playbook_parameters.go +++ /dev/null @@ -1,87 +0,0 @@ -package playbooks - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// GetPlaybookEndpoint executes the core logic of the related -// route endpoint. -func GetPlaybookEndpoint(handler func(ctx context.Context, params *GetPlaybookParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewGetPlaybookParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewGetPlaybookParams creates a new GetPlaybookParams object -// with the default values initialized. -func NewGetPlaybookParams() *GetPlaybookParams { - var () - return &GetPlaybookParams{} -} - -// GetPlaybookParams contains all the bound params for the get playbook operation -// typically these are obtained from a http.Request -// -// swagger:parameters getPlaybook -type GetPlaybookParams struct { - - /*Playbook name - Required: true - In: path - */ - ID string -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *GetPlaybookParams) ReadRequest(ctx *gin.Context) error { - var res []error - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *GetPlaybookParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - o.ID = raw - - return nil -} diff --git a/generated/restapi/operations/playbooks/list_playbooks_parameters.go b/generated/restapi/operations/playbooks/list_playbooks_parameters.go deleted file mode 100644 index d63dc77..0000000 --- a/generated/restapi/operations/playbooks/list_playbooks_parameters.go +++ /dev/null @@ -1,55 +0,0 @@ -package playbooks - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// ListPlaybooksEndpoint executes the core logic of the related -// route endpoint. -func ListPlaybooksEndpoint(handler func(ctx context.Context) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - resp := handler(ctx) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewListPlaybooksParams creates a new ListPlaybooksParams object -// with the default values initialized. -func NewListPlaybooksParams() *ListPlaybooksParams { - var () - return &ListPlaybooksParams{} -} - -// ListPlaybooksParams contains all the bound params for the list playbooks operation -// typically these are obtained from a http.Request -// -// swagger:parameters listPlaybooks -type ListPlaybooksParams struct { -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *ListPlaybooksParams) ReadRequest(ctx *gin.Context) error { - var res []error - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} diff --git a/generated/restapi/operations/playbooks/update_playbook_parameters.go b/generated/restapi/operations/playbooks/update_playbook_parameters.go deleted file mode 100644 index ae3d524..0000000 --- a/generated/restapi/operations/playbooks/update_playbook_parameters.go +++ /dev/null @@ -1,111 +0,0 @@ -package playbooks - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "io" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime" - - "github.com/SecurityBrewery/catalyst/generated/models" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// UpdatePlaybookEndpoint executes the core logic of the related -// route endpoint. -func UpdatePlaybookEndpoint(handler func(ctx context.Context, params *UpdatePlaybookParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewUpdatePlaybookParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewUpdatePlaybookParams creates a new UpdatePlaybookParams object -// with the default values initialized. -func NewUpdatePlaybookParams() *UpdatePlaybookParams { - var () - return &UpdatePlaybookParams{} -} - -// UpdatePlaybookParams contains all the bound params for the update playbook operation -// typically these are obtained from a http.Request -// -// swagger:parameters updatePlaybook -type UpdatePlaybookParams struct { - - /*Playbook ID - Required: true - In: path - */ - ID string - /*Updated playbook - Required: true - In: body - */ - Playbook *models.PlaybookTemplateForm -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *UpdatePlaybookParams) ReadRequest(ctx *gin.Context) error { - var res []error - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - if runtime.HasBody(ctx.Request) { - var body models.PlaybookTemplateForm - if err := ctx.BindJSON(&body); err != nil { - if err == io.EOF { - res = append(res, errors.Required("playbook", "body", "")) - } else { - res = append(res, errors.NewParseError("playbook", "body", "", err)) - } - - } else { - o.Playbook = &body - } - } else { - res = append(res, errors.Required("playbook", "body", "")) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *UpdatePlaybookParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - o.ID = raw - - return nil -} diff --git a/generated/restapi/operations/settings/get_settings_parameters.go b/generated/restapi/operations/settings/get_settings_parameters.go deleted file mode 100644 index a6f9a19..0000000 --- a/generated/restapi/operations/settings/get_settings_parameters.go +++ /dev/null @@ -1,55 +0,0 @@ -package settings - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// GetSettingsEndpoint executes the core logic of the related -// route endpoint. -func GetSettingsEndpoint(handler func(ctx context.Context) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - resp := handler(ctx) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewGetSettingsParams creates a new GetSettingsParams object -// with the default values initialized. -func NewGetSettingsParams() *GetSettingsParams { - var () - return &GetSettingsParams{} -} - -// GetSettingsParams contains all the bound params for the get settings operation -// typically these are obtained from a http.Request -// -// swagger:parameters getSettings -type GetSettingsParams struct { -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *GetSettingsParams) ReadRequest(ctx *gin.Context) error { - var res []error - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} diff --git a/generated/restapi/operations/statistics/get_statistics_parameters.go b/generated/restapi/operations/statistics/get_statistics_parameters.go deleted file mode 100644 index ae3626e..0000000 --- a/generated/restapi/operations/statistics/get_statistics_parameters.go +++ /dev/null @@ -1,55 +0,0 @@ -package statistics - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// GetStatisticsEndpoint executes the core logic of the related -// route endpoint. -func GetStatisticsEndpoint(handler func(ctx context.Context) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - resp := handler(ctx) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewGetStatisticsParams creates a new GetStatisticsParams object -// with the default values initialized. -func NewGetStatisticsParams() *GetStatisticsParams { - var () - return &GetStatisticsParams{} -} - -// GetStatisticsParams contains all the bound params for the get statistics operation -// typically these are obtained from a http.Request -// -// swagger:parameters getStatistics -type GetStatisticsParams struct { -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *GetStatisticsParams) ReadRequest(ctx *gin.Context) error { - var res []error - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} diff --git a/generated/restapi/operations/tasks/list_tasks_parameters.go b/generated/restapi/operations/tasks/list_tasks_parameters.go deleted file mode 100644 index 4fd738b..0000000 --- a/generated/restapi/operations/tasks/list_tasks_parameters.go +++ /dev/null @@ -1,55 +0,0 @@ -package tasks - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// ListTasksEndpoint executes the core logic of the related -// route endpoint. -func ListTasksEndpoint(handler func(ctx context.Context) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - resp := handler(ctx) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewListTasksParams creates a new ListTasksParams object -// with the default values initialized. -func NewListTasksParams() *ListTasksParams { - var () - return &ListTasksParams{} -} - -// ListTasksParams contains all the bound params for the list tasks operation -// typically these are obtained from a http.Request -// -// swagger:parameters listTasks -type ListTasksParams struct { -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *ListTasksParams) ReadRequest(ctx *gin.Context) error { - var res []error - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} diff --git a/generated/restapi/operations/templates/create_template_parameters.go b/generated/restapi/operations/templates/create_template_parameters.go deleted file mode 100644 index 4ba64e0..0000000 --- a/generated/restapi/operations/templates/create_template_parameters.go +++ /dev/null @@ -1,90 +0,0 @@ -package templates - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "io" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime" - - "github.com/SecurityBrewery/catalyst/generated/models" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// CreateTemplateEndpoint executes the core logic of the related -// route endpoint. -func CreateTemplateEndpoint(handler func(ctx context.Context, params *CreateTemplateParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewCreateTemplateParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewCreateTemplateParams creates a new CreateTemplateParams object -// with the default values initialized. -func NewCreateTemplateParams() *CreateTemplateParams { - var () - return &CreateTemplateParams{} -} - -// CreateTemplateParams contains all the bound params for the create template operation -// typically these are obtained from a http.Request -// -// swagger:parameters createTemplate -type CreateTemplateParams struct { - - /*New template - Required: true - In: body - */ - Template *models.TicketTemplateForm -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *CreateTemplateParams) ReadRequest(ctx *gin.Context) error { - var res []error - - if runtime.HasBody(ctx.Request) { - var body models.TicketTemplateForm - if err := ctx.BindJSON(&body); err != nil { - if err == io.EOF { - res = append(res, errors.Required("template", "body", "")) - } else { - res = append(res, errors.NewParseError("template", "body", "", err)) - } - - } else { - o.Template = &body - } - } else { - res = append(res, errors.Required("template", "body", "")) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} diff --git a/generated/restapi/operations/templates/delete_template_parameters.go b/generated/restapi/operations/templates/delete_template_parameters.go deleted file mode 100644 index 951de04..0000000 --- a/generated/restapi/operations/templates/delete_template_parameters.go +++ /dev/null @@ -1,87 +0,0 @@ -package templates - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// DeleteTemplateEndpoint executes the core logic of the related -// route endpoint. -func DeleteTemplateEndpoint(handler func(ctx context.Context, params *DeleteTemplateParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewDeleteTemplateParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewDeleteTemplateParams creates a new DeleteTemplateParams object -// with the default values initialized. -func NewDeleteTemplateParams() *DeleteTemplateParams { - var () - return &DeleteTemplateParams{} -} - -// DeleteTemplateParams contains all the bound params for the delete template operation -// typically these are obtained from a http.Request -// -// swagger:parameters deleteTemplate -type DeleteTemplateParams struct { - - /*Template ID - Required: true - In: path - */ - ID string -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *DeleteTemplateParams) ReadRequest(ctx *gin.Context) error { - var res []error - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *DeleteTemplateParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - o.ID = raw - - return nil -} diff --git a/generated/restapi/operations/templates/get_template_parameters.go b/generated/restapi/operations/templates/get_template_parameters.go deleted file mode 100644 index 44e7020..0000000 --- a/generated/restapi/operations/templates/get_template_parameters.go +++ /dev/null @@ -1,87 +0,0 @@ -package templates - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// GetTemplateEndpoint executes the core logic of the related -// route endpoint. -func GetTemplateEndpoint(handler func(ctx context.Context, params *GetTemplateParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewGetTemplateParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewGetTemplateParams creates a new GetTemplateParams object -// with the default values initialized. -func NewGetTemplateParams() *GetTemplateParams { - var () - return &GetTemplateParams{} -} - -// GetTemplateParams contains all the bound params for the get template operation -// typically these are obtained from a http.Request -// -// swagger:parameters getTemplate -type GetTemplateParams struct { - - /*Template ID - Required: true - In: path - */ - ID string -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *GetTemplateParams) ReadRequest(ctx *gin.Context) error { - var res []error - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *GetTemplateParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - o.ID = raw - - return nil -} diff --git a/generated/restapi/operations/templates/list_templates_parameters.go b/generated/restapi/operations/templates/list_templates_parameters.go deleted file mode 100644 index 2f2e255..0000000 --- a/generated/restapi/operations/templates/list_templates_parameters.go +++ /dev/null @@ -1,55 +0,0 @@ -package templates - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// ListTemplatesEndpoint executes the core logic of the related -// route endpoint. -func ListTemplatesEndpoint(handler func(ctx context.Context) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - resp := handler(ctx) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewListTemplatesParams creates a new ListTemplatesParams object -// with the default values initialized. -func NewListTemplatesParams() *ListTemplatesParams { - var () - return &ListTemplatesParams{} -} - -// ListTemplatesParams contains all the bound params for the list templates operation -// typically these are obtained from a http.Request -// -// swagger:parameters listTemplates -type ListTemplatesParams struct { -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *ListTemplatesParams) ReadRequest(ctx *gin.Context) error { - var res []error - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} diff --git a/generated/restapi/operations/templates/update_template_parameters.go b/generated/restapi/operations/templates/update_template_parameters.go deleted file mode 100644 index 66fd60e..0000000 --- a/generated/restapi/operations/templates/update_template_parameters.go +++ /dev/null @@ -1,111 +0,0 @@ -package templates - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "io" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime" - - "github.com/SecurityBrewery/catalyst/generated/models" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// UpdateTemplateEndpoint executes the core logic of the related -// route endpoint. -func UpdateTemplateEndpoint(handler func(ctx context.Context, params *UpdateTemplateParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewUpdateTemplateParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewUpdateTemplateParams creates a new UpdateTemplateParams object -// with the default values initialized. -func NewUpdateTemplateParams() *UpdateTemplateParams { - var () - return &UpdateTemplateParams{} -} - -// UpdateTemplateParams contains all the bound params for the update template operation -// typically these are obtained from a http.Request -// -// swagger:parameters updateTemplate -type UpdateTemplateParams struct { - - /*Template ID - Required: true - In: path - */ - ID string - /*Template object that needs to be added - Required: true - In: body - */ - Template *models.TicketTemplateForm -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *UpdateTemplateParams) ReadRequest(ctx *gin.Context) error { - var res []error - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - if runtime.HasBody(ctx.Request) { - var body models.TicketTemplateForm - if err := ctx.BindJSON(&body); err != nil { - if err == io.EOF { - res = append(res, errors.Required("template", "body", "")) - } else { - res = append(res, errors.NewParseError("template", "body", "", err)) - } - - } else { - o.Template = &body - } - } else { - res = append(res, errors.Required("template", "body", "")) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *UpdateTemplateParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - o.ID = raw - - return nil -} diff --git a/generated/restapi/operations/tickets/add_artifact_parameters.go b/generated/restapi/operations/tickets/add_artifact_parameters.go deleted file mode 100644 index 60cbf17..0000000 --- a/generated/restapi/operations/tickets/add_artifact_parameters.go +++ /dev/null @@ -1,116 +0,0 @@ -package tickets - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "io" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime" - "github.com/go-openapi/swag" - - "github.com/SecurityBrewery/catalyst/generated/models" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// AddArtifactEndpoint executes the core logic of the related -// route endpoint. -func AddArtifactEndpoint(handler func(ctx context.Context, params *AddArtifactParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewAddArtifactParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewAddArtifactParams creates a new AddArtifactParams object -// with the default values initialized. -func NewAddArtifactParams() *AddArtifactParams { - var () - return &AddArtifactParams{} -} - -// AddArtifactParams contains all the bound params for the add artifact operation -// typically these are obtained from a http.Request -// -// swagger:parameters addArtifact -type AddArtifactParams struct { - - /*Artifact object that needs to be added - Required: true - In: body - */ - Artifact *models.Artifact - /*Ticket ID - Required: true - In: path - */ - ID int64 -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *AddArtifactParams) ReadRequest(ctx *gin.Context) error { - var res []error - - if runtime.HasBody(ctx.Request) { - var body models.Artifact - if err := ctx.BindJSON(&body); err != nil { - if err == io.EOF { - res = append(res, errors.Required("artifact", "body", "")) - } else { - res = append(res, errors.NewParseError("artifact", "body", "", err)) - } - - } else { - o.Artifact = &body - } - } else { - res = append(res, errors.Required("artifact", "body", "")) - } - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *AddArtifactParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - value, err := swag.ConvertInt64(raw) - if err != nil { - return errors.InvalidType("id", "path", "int64", raw) - } - o.ID = value - - return nil -} diff --git a/generated/restapi/operations/tickets/add_comment_parameters.go b/generated/restapi/operations/tickets/add_comment_parameters.go deleted file mode 100644 index 52608e2..0000000 --- a/generated/restapi/operations/tickets/add_comment_parameters.go +++ /dev/null @@ -1,116 +0,0 @@ -package tickets - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "io" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime" - "github.com/go-openapi/swag" - - "github.com/SecurityBrewery/catalyst/generated/models" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// AddCommentEndpoint executes the core logic of the related -// route endpoint. -func AddCommentEndpoint(handler func(ctx context.Context, params *AddCommentParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewAddCommentParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewAddCommentParams creates a new AddCommentParams object -// with the default values initialized. -func NewAddCommentParams() *AddCommentParams { - var () - return &AddCommentParams{} -} - -// AddCommentParams contains all the bound params for the add comment operation -// typically these are obtained from a http.Request -// -// swagger:parameters addComment -type AddCommentParams struct { - - /*Ticket comment - Required: true - In: body - */ - Comment *models.CommentForm - /*Ticket ID - Required: true - In: path - */ - ID int64 -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *AddCommentParams) ReadRequest(ctx *gin.Context) error { - var res []error - - if runtime.HasBody(ctx.Request) { - var body models.CommentForm - if err := ctx.BindJSON(&body); err != nil { - if err == io.EOF { - res = append(res, errors.Required("comment", "body", "")) - } else { - res = append(res, errors.NewParseError("comment", "body", "", err)) - } - - } else { - o.Comment = &body - } - } else { - res = append(res, errors.Required("comment", "body", "")) - } - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *AddCommentParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - value, err := swag.ConvertInt64(raw) - if err != nil { - return errors.InvalidType("id", "path", "int64", raw) - } - o.ID = value - - return nil -} diff --git a/generated/restapi/operations/tickets/add_ticket_playbook_parameters.go b/generated/restapi/operations/tickets/add_ticket_playbook_parameters.go deleted file mode 100644 index 261ea32..0000000 --- a/generated/restapi/operations/tickets/add_ticket_playbook_parameters.go +++ /dev/null @@ -1,116 +0,0 @@ -package tickets - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "io" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime" - "github.com/go-openapi/swag" - - "github.com/SecurityBrewery/catalyst/generated/models" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// AddTicketPlaybookEndpoint executes the core logic of the related -// route endpoint. -func AddTicketPlaybookEndpoint(handler func(ctx context.Context, params *AddTicketPlaybookParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewAddTicketPlaybookParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewAddTicketPlaybookParams creates a new AddTicketPlaybookParams object -// with the default values initialized. -func NewAddTicketPlaybookParams() *AddTicketPlaybookParams { - var () - return &AddTicketPlaybookParams{} -} - -// AddTicketPlaybookParams contains all the bound params for the add ticket playbook operation -// typically these are obtained from a http.Request -// -// swagger:parameters addTicketPlaybook -type AddTicketPlaybookParams struct { - - /*Ticket ID - Required: true - In: path - */ - ID int64 - /*Ticket playbook object that needs to be added - Required: true - In: body - */ - Playbook *models.PlaybookTemplateForm -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *AddTicketPlaybookParams) ReadRequest(ctx *gin.Context) error { - var res []error - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - if runtime.HasBody(ctx.Request) { - var body models.PlaybookTemplateForm - if err := ctx.BindJSON(&body); err != nil { - if err == io.EOF { - res = append(res, errors.Required("playbook", "body", "")) - } else { - res = append(res, errors.NewParseError("playbook", "body", "", err)) - } - - } else { - o.Playbook = &body - } - } else { - res = append(res, errors.Required("playbook", "body", "")) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *AddTicketPlaybookParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - value, err := swag.ConvertInt64(raw) - if err != nil { - return errors.InvalidType("id", "path", "int64", raw) - } - o.ID = value - - return nil -} diff --git a/generated/restapi/operations/tickets/complete_task_parameters.go b/generated/restapi/operations/tickets/complete_task_parameters.go deleted file mode 100644 index f53bb27..0000000 --- a/generated/restapi/operations/tickets/complete_task_parameters.go +++ /dev/null @@ -1,157 +0,0 @@ -package tickets - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "io" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime" - "github.com/go-openapi/swag" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// CompleteTaskEndpoint executes the core logic of the related -// route endpoint. -func CompleteTaskEndpoint(handler func(ctx context.Context, params *CompleteTaskParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewCompleteTaskParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewCompleteTaskParams creates a new CompleteTaskParams object -// with the default values initialized. -func NewCompleteTaskParams() *CompleteTaskParams { - var () - return &CompleteTaskParams{} -} - -// CompleteTaskParams contains all the bound params for the complete task operation -// typically these are obtained from a http.Request -// -// swagger:parameters completeTask -type CompleteTaskParams struct { - - /*Ticket playbook object that needs to be added - Required: true - In: body - */ - Data interface{} - /*Ticket ID - Required: true - In: path - */ - ID int64 - /*Playbook ID - Required: true - In: path - */ - PlaybookID string - /*Task ID - Required: true - In: path - */ - TaskID string -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *CompleteTaskParams) ReadRequest(ctx *gin.Context) error { - var res []error - - if runtime.HasBody(ctx.Request) { - var body interface{} - if err := ctx.BindJSON(&body); err != nil { - if err == io.EOF { - res = append(res, errors.Required("data", "body", "")) - } else { - res = append(res, errors.NewParseError("data", "body", "", err)) - } - - } else { - o.Data = body - } - } else { - res = append(res, errors.Required("data", "body", "")) - } - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - rPlaybookID := []string{ctx.Param("playbookID")} - if err := o.bindPlaybookID(rPlaybookID, true); err != nil { - res = append(res, err) - } - - rTaskID := []string{ctx.Param("taskID")} - if err := o.bindTaskID(rTaskID, true); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *CompleteTaskParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - value, err := swag.ConvertInt64(raw) - if err != nil { - return errors.InvalidType("id", "path", "int64", raw) - } - o.ID = value - - return nil -} - -func (o *CompleteTaskParams) bindPlaybookID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - o.PlaybookID = raw - - return nil -} - -func (o *CompleteTaskParams) bindTaskID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - o.TaskID = raw - - return nil -} diff --git a/generated/restapi/operations/tickets/create_ticket_batch_parameters.go b/generated/restapi/operations/tickets/create_ticket_batch_parameters.go deleted file mode 100644 index 56abf52..0000000 --- a/generated/restapi/operations/tickets/create_ticket_batch_parameters.go +++ /dev/null @@ -1,90 +0,0 @@ -package tickets - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "io" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime" - - "github.com/SecurityBrewery/catalyst/generated/models" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// CreateTicketBatchEndpoint executes the core logic of the related -// route endpoint. -func CreateTicketBatchEndpoint(handler func(ctx context.Context, params *CreateTicketBatchParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewCreateTicketBatchParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewCreateTicketBatchParams creates a new CreateTicketBatchParams object -// with the default values initialized. -func NewCreateTicketBatchParams() *CreateTicketBatchParams { - var () - return &CreateTicketBatchParams{} -} - -// CreateTicketBatchParams contains all the bound params for the create ticket batch operation -// typically these are obtained from a http.Request -// -// swagger:parameters createTicketBatch -type CreateTicketBatchParams struct { - - /*New ticket - Required: true - In: body - */ - Ticket []*models.TicketForm -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *CreateTicketBatchParams) ReadRequest(ctx *gin.Context) error { - var res []error - - if runtime.HasBody(ctx.Request) { - var body []*models.TicketForm - if err := ctx.BindJSON(&body); err != nil { - if err == io.EOF { - res = append(res, errors.Required("ticket", "body", "")) - } else { - res = append(res, errors.NewParseError("ticket", "body", "", err)) - } - - } else { - o.Ticket = body - } - } else { - res = append(res, errors.Required("ticket", "body", "")) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} diff --git a/generated/restapi/operations/tickets/create_ticket_parameters.go b/generated/restapi/operations/tickets/create_ticket_parameters.go deleted file mode 100644 index e5ec2fc..0000000 --- a/generated/restapi/operations/tickets/create_ticket_parameters.go +++ /dev/null @@ -1,90 +0,0 @@ -package tickets - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "io" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime" - - "github.com/SecurityBrewery/catalyst/generated/models" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// CreateTicketEndpoint executes the core logic of the related -// route endpoint. -func CreateTicketEndpoint(handler func(ctx context.Context, params *CreateTicketParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewCreateTicketParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewCreateTicketParams creates a new CreateTicketParams object -// with the default values initialized. -func NewCreateTicketParams() *CreateTicketParams { - var () - return &CreateTicketParams{} -} - -// CreateTicketParams contains all the bound params for the create ticket operation -// typically these are obtained from a http.Request -// -// swagger:parameters createTicket -type CreateTicketParams struct { - - /*New ticket - Required: true - In: body - */ - Ticket *models.TicketForm -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *CreateTicketParams) ReadRequest(ctx *gin.Context) error { - var res []error - - if runtime.HasBody(ctx.Request) { - var body models.TicketForm - if err := ctx.BindJSON(&body); err != nil { - if err == io.EOF { - res = append(res, errors.Required("ticket", "body", "")) - } else { - res = append(res, errors.NewParseError("ticket", "body", "", err)) - } - - } else { - o.Ticket = &body - } - } else { - res = append(res, errors.Required("ticket", "body", "")) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} diff --git a/generated/restapi/operations/tickets/delete_ticket_parameters.go b/generated/restapi/operations/tickets/delete_ticket_parameters.go deleted file mode 100644 index 77352e0..0000000 --- a/generated/restapi/operations/tickets/delete_ticket_parameters.go +++ /dev/null @@ -1,92 +0,0 @@ -package tickets - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/swag" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// DeleteTicketEndpoint executes the core logic of the related -// route endpoint. -func DeleteTicketEndpoint(handler func(ctx context.Context, params *DeleteTicketParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewDeleteTicketParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewDeleteTicketParams creates a new DeleteTicketParams object -// with the default values initialized. -func NewDeleteTicketParams() *DeleteTicketParams { - var () - return &DeleteTicketParams{} -} - -// DeleteTicketParams contains all the bound params for the delete ticket operation -// typically these are obtained from a http.Request -// -// swagger:parameters deleteTicket -type DeleteTicketParams struct { - - /*Ticket ID - Required: true - In: path - */ - ID int64 -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *DeleteTicketParams) ReadRequest(ctx *gin.Context) error { - var res []error - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *DeleteTicketParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - value, err := swag.ConvertInt64(raw) - if err != nil { - return errors.InvalidType("id", "path", "int64", raw) - } - o.ID = value - - return nil -} diff --git a/generated/restapi/operations/tickets/enrich_artifact_parameters.go b/generated/restapi/operations/tickets/enrich_artifact_parameters.go deleted file mode 100644 index e94aaef..0000000 --- a/generated/restapi/operations/tickets/enrich_artifact_parameters.go +++ /dev/null @@ -1,137 +0,0 @@ -package tickets - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "io" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime" - "github.com/go-openapi/swag" - - "github.com/SecurityBrewery/catalyst/generated/models" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// EnrichArtifactEndpoint executes the core logic of the related -// route endpoint. -func EnrichArtifactEndpoint(handler func(ctx context.Context, params *EnrichArtifactParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewEnrichArtifactParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewEnrichArtifactParams creates a new EnrichArtifactParams object -// with the default values initialized. -func NewEnrichArtifactParams() *EnrichArtifactParams { - var () - return &EnrichArtifactParams{} -} - -// EnrichArtifactParams contains all the bound params for the enrich artifact operation -// typically these are obtained from a http.Request -// -// swagger:parameters enrichArtifact -type EnrichArtifactParams struct { - - /* - Required: true - In: body - */ - Data *models.EnrichmentForm - /*Ticket ID - Required: true - In: path - */ - ID int64 - /* - Required: true - In: path - */ - Name string -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *EnrichArtifactParams) ReadRequest(ctx *gin.Context) error { - var res []error - - if runtime.HasBody(ctx.Request) { - var body models.EnrichmentForm - if err := ctx.BindJSON(&body); err != nil { - if err == io.EOF { - res = append(res, errors.Required("data", "body", "")) - } else { - res = append(res, errors.NewParseError("data", "body", "", err)) - } - - } else { - o.Data = &body - } - } else { - res = append(res, errors.Required("data", "body", "")) - } - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - rName := []string{ctx.Param("name")} - if err := o.bindName(rName, true); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *EnrichArtifactParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - value, err := swag.ConvertInt64(raw) - if err != nil { - return errors.InvalidType("id", "path", "int64", raw) - } - o.ID = value - - return nil -} - -func (o *EnrichArtifactParams) bindName(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - o.Name = raw - - return nil -} diff --git a/generated/restapi/operations/tickets/get_artifact_parameters.go b/generated/restapi/operations/tickets/get_artifact_parameters.go deleted file mode 100644 index 3329a11..0000000 --- a/generated/restapi/operations/tickets/get_artifact_parameters.go +++ /dev/null @@ -1,113 +0,0 @@ -package tickets - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/swag" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// GetArtifactEndpoint executes the core logic of the related -// route endpoint. -func GetArtifactEndpoint(handler func(ctx context.Context, params *GetArtifactParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewGetArtifactParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewGetArtifactParams creates a new GetArtifactParams object -// with the default values initialized. -func NewGetArtifactParams() *GetArtifactParams { - var () - return &GetArtifactParams{} -} - -// GetArtifactParams contains all the bound params for the get artifact operation -// typically these are obtained from a http.Request -// -// swagger:parameters getArtifact -type GetArtifactParams struct { - - /*Ticket ID - Required: true - In: path - */ - ID int64 - /* - Required: true - In: path - */ - Name string -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *GetArtifactParams) ReadRequest(ctx *gin.Context) error { - var res []error - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - rName := []string{ctx.Param("name")} - if err := o.bindName(rName, true); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *GetArtifactParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - value, err := swag.ConvertInt64(raw) - if err != nil { - return errors.InvalidType("id", "path", "int64", raw) - } - o.ID = value - - return nil -} - -func (o *GetArtifactParams) bindName(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - o.Name = raw - - return nil -} diff --git a/generated/restapi/operations/tickets/get_ticket_parameters.go b/generated/restapi/operations/tickets/get_ticket_parameters.go deleted file mode 100644 index 1616efc..0000000 --- a/generated/restapi/operations/tickets/get_ticket_parameters.go +++ /dev/null @@ -1,92 +0,0 @@ -package tickets - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/swag" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// GetTicketEndpoint executes the core logic of the related -// route endpoint. -func GetTicketEndpoint(handler func(ctx context.Context, params *GetTicketParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewGetTicketParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewGetTicketParams creates a new GetTicketParams object -// with the default values initialized. -func NewGetTicketParams() *GetTicketParams { - var () - return &GetTicketParams{} -} - -// GetTicketParams contains all the bound params for the get ticket operation -// typically these are obtained from a http.Request -// -// swagger:parameters getTicket -type GetTicketParams struct { - - /*Ticket ID - Required: true - In: path - */ - ID int64 -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *GetTicketParams) ReadRequest(ctx *gin.Context) error { - var res []error - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *GetTicketParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - value, err := swag.ConvertInt64(raw) - if err != nil { - return errors.InvalidType("id", "path", "int64", raw) - } - o.ID = value - - return nil -} diff --git a/generated/restapi/operations/tickets/link_files_parameters.go b/generated/restapi/operations/tickets/link_files_parameters.go deleted file mode 100644 index 23eab37..0000000 --- a/generated/restapi/operations/tickets/link_files_parameters.go +++ /dev/null @@ -1,116 +0,0 @@ -package tickets - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "io" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime" - "github.com/go-openapi/swag" - - "github.com/SecurityBrewery/catalyst/generated/models" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// LinkFilesEndpoint executes the core logic of the related -// route endpoint. -func LinkFilesEndpoint(handler func(ctx context.Context, params *LinkFilesParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewLinkFilesParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewLinkFilesParams creates a new LinkFilesParams object -// with the default values initialized. -func NewLinkFilesParams() *LinkFilesParams { - var () - return &LinkFilesParams{} -} - -// LinkFilesParams contains all the bound params for the link files operation -// typically these are obtained from a http.Request -// -// swagger:parameters linkFiles -type LinkFilesParams struct { - - /*Added files - Required: true - In: body - */ - Files []*models.File - /*Ticket ID - Required: true - In: path - */ - ID int64 -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *LinkFilesParams) ReadRequest(ctx *gin.Context) error { - var res []error - - if runtime.HasBody(ctx.Request) { - var body []*models.File - if err := ctx.BindJSON(&body); err != nil { - if err == io.EOF { - res = append(res, errors.Required("files", "body", "")) - } else { - res = append(res, errors.NewParseError("files", "body", "", err)) - } - - } else { - o.Files = body - } - } else { - res = append(res, errors.Required("files", "body", "")) - } - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *LinkFilesParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - value, err := swag.ConvertInt64(raw) - if err != nil { - return errors.InvalidType("id", "path", "int64", raw) - } - o.ID = value - - return nil -} diff --git a/generated/restapi/operations/tickets/link_ticket_parameters.go b/generated/restapi/operations/tickets/link_ticket_parameters.go deleted file mode 100644 index c86d899..0000000 --- a/generated/restapi/operations/tickets/link_ticket_parameters.go +++ /dev/null @@ -1,115 +0,0 @@ -package tickets - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "io" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime" - "github.com/go-openapi/swag" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// LinkTicketEndpoint executes the core logic of the related -// route endpoint. -func LinkTicketEndpoint(handler func(ctx context.Context, params *LinkTicketParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewLinkTicketParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewLinkTicketParams creates a new LinkTicketParams object -// with the default values initialized. -func NewLinkTicketParams() *LinkTicketParams { - var () - return &LinkTicketParams{} -} - -// LinkTicketParams contains all the bound params for the link ticket operation -// typically these are obtained from a http.Request -// -// swagger:parameters linkTicket -type LinkTicketParams struct { - - /*Ticket ID - Required: true - In: path - */ - ID int64 - /*Added ticket ID - Required: true - In: body - */ - LinkedID int64 -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *LinkTicketParams) ReadRequest(ctx *gin.Context) error { - var res []error - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - if runtime.HasBody(ctx.Request) { - var body int64 - if err := ctx.BindJSON(&body); err != nil { - if err == io.EOF { - res = append(res, errors.Required("linkedId", "body", "")) - } else { - res = append(res, errors.NewParseError("linkedId", "body", "", err)) - } - - } else { - o.LinkedID = body - } - } else { - res = append(res, errors.Required("linkedId", "body", "")) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *LinkTicketParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - value, err := swag.ConvertInt64(raw) - if err != nil { - return errors.InvalidType("id", "path", "int64", raw) - } - o.ID = value - - return nil -} diff --git a/generated/restapi/operations/tickets/list_tickets_parameters.go b/generated/restapi/operations/tickets/list_tickets_parameters.go deleted file mode 100644 index 4c230f7..0000000 --- a/generated/restapi/operations/tickets/list_tickets_parameters.go +++ /dev/null @@ -1,269 +0,0 @@ -package tickets - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "fmt" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime" - "github.com/go-openapi/swag" - "github.com/go-openapi/validate" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// ListTicketsEndpoint executes the core logic of the related -// route endpoint. -func ListTicketsEndpoint(handler func(ctx context.Context, params *ListTicketsParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewListTicketsParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewListTicketsParams creates a new ListTicketsParams object -// with the default values initialized. -func NewListTicketsParams() *ListTicketsParams { - var ( - countDefault = int64(25) - offsetDefault = int64(0) - ) - return &ListTicketsParams{ - Count: &countDefault, - - Offset: &offsetDefault, - } -} - -// ListTicketsParams contains all the bound params for the list tickets operation -// typically these are obtained from a http.Request -// -// swagger:parameters listTickets -type ListTicketsParams struct { - - /*Number of tickets - Maximum: 100 - In: query - Default: 25 - */ - Count *int64 - /*Sort descending - In: query - */ - Desc []bool - /*Offset of the list - In: query - Default: 0 - */ - Offset *int64 - /*Search query - In: query - */ - Query *string - /*Sort columns - In: query - */ - Sort []string - /*Ticket Type - In: query - */ - Type *string -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *ListTicketsParams) ReadRequest(ctx *gin.Context) error { - var res []error - qs := runtime.Values(ctx.Request.URL.Query()) - - qCount, qhkCount, _ := qs.GetOK("count") - if err := o.bindCount(qCount, qhkCount); err != nil { - res = append(res, err) - } - - qDesc, qhkDesc, _ := qs.GetOK("desc") - if err := o.bindDesc(qDesc, qhkDesc); err != nil { - res = append(res, err) - } - - qOffset, qhkOffset, _ := qs.GetOK("offset") - if err := o.bindOffset(qOffset, qhkOffset); err != nil { - res = append(res, err) - } - - qQuery, qhkQuery, _ := qs.GetOK("query") - if err := o.bindQuery(qQuery, qhkQuery); err != nil { - res = append(res, err) - } - - qSort, qhkSort, _ := qs.GetOK("sort") - if err := o.bindSort(qSort, qhkSort); err != nil { - res = append(res, err) - } - - qType, qhkType, _ := qs.GetOK("type") - if err := o.bindType(qType, qhkType); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *ListTicketsParams) bindCount(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - if raw == "" { // empty values pass all other validations - var countDefault int64 = int64(25) - o.Count = &countDefault - return nil - } - - value, err := swag.ConvertInt64(raw) - if err != nil { - return errors.InvalidType("count", "query", "int64", raw) - } - o.Count = &value - - if err := o.validateCount(); err != nil { - return err - } - - return nil -} - -func (o *ListTicketsParams) validateCount() error { - - if err := validate.MaximumInt("count", "query", int64(*o.Count), 100, false); err != nil { - return err - } - - return nil -} - -func (o *ListTicketsParams) bindDesc(rawData []string, hasKey bool) error { - - var qvDesc string - if len(rawData) > 0 { - qvDesc = rawData[len(rawData)-1] - } - - descIC := swag.SplitByFormat(qvDesc, "") - - if len(descIC) == 0 { - return nil - } - - var descIR []bool - for i, descIV := range descIC { - descI, err := swag.ConvertBool(descIV) - if err != nil { - return errors.InvalidType(fmt.Sprintf("%s.%v", "desc", i), "query", "bool", descI) - } - - descIR = append(descIR, descI) - } - - o.Desc = descIR - - return nil -} - -func (o *ListTicketsParams) bindOffset(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - if raw == "" { // empty values pass all other validations - var offsetDefault int64 = int64(0) - o.Offset = &offsetDefault - return nil - } - - value, err := swag.ConvertInt64(raw) - if err != nil { - return errors.InvalidType("offset", "query", "int64", raw) - } - o.Offset = &value - - return nil -} - -func (o *ListTicketsParams) bindQuery(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - if raw == "" { // empty values pass all other validations - return nil - } - - o.Query = &raw - - return nil -} - -func (o *ListTicketsParams) bindSort(rawData []string, hasKey bool) error { - - var qvSort string - if len(rawData) > 0 { - qvSort = rawData[len(rawData)-1] - } - - sortIC := swag.SplitByFormat(qvSort, "") - - if len(sortIC) == 0 { - return nil - } - - var sortIR []string - for _, sortIV := range sortIC { - sortI := sortIV - - sortIR = append(sortIR, sortI) - } - - o.Sort = sortIR - - return nil -} - -func (o *ListTicketsParams) bindType(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - if raw == "" { // empty values pass all other validations - return nil - } - - o.Type = &raw - - return nil -} diff --git a/generated/restapi/operations/tickets/remove_artifact_parameters.go b/generated/restapi/operations/tickets/remove_artifact_parameters.go deleted file mode 100644 index 4003d41..0000000 --- a/generated/restapi/operations/tickets/remove_artifact_parameters.go +++ /dev/null @@ -1,113 +0,0 @@ -package tickets - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/swag" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// RemoveArtifactEndpoint executes the core logic of the related -// route endpoint. -func RemoveArtifactEndpoint(handler func(ctx context.Context, params *RemoveArtifactParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewRemoveArtifactParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewRemoveArtifactParams creates a new RemoveArtifactParams object -// with the default values initialized. -func NewRemoveArtifactParams() *RemoveArtifactParams { - var () - return &RemoveArtifactParams{} -} - -// RemoveArtifactParams contains all the bound params for the remove artifact operation -// typically these are obtained from a http.Request -// -// swagger:parameters removeArtifact -type RemoveArtifactParams struct { - - /*Ticket ID - Required: true - In: path - */ - ID int64 - /* - Required: true - In: path - */ - Name string -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *RemoveArtifactParams) ReadRequest(ctx *gin.Context) error { - var res []error - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - rName := []string{ctx.Param("name")} - if err := o.bindName(rName, true); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *RemoveArtifactParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - value, err := swag.ConvertInt64(raw) - if err != nil { - return errors.InvalidType("id", "path", "int64", raw) - } - o.ID = value - - return nil -} - -func (o *RemoveArtifactParams) bindName(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - o.Name = raw - - return nil -} diff --git a/generated/restapi/operations/tickets/remove_comment_parameters.go b/generated/restapi/operations/tickets/remove_comment_parameters.go deleted file mode 100644 index 4ff85d2..0000000 --- a/generated/restapi/operations/tickets/remove_comment_parameters.go +++ /dev/null @@ -1,117 +0,0 @@ -package tickets - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/swag" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// RemoveCommentEndpoint executes the core logic of the related -// route endpoint. -func RemoveCommentEndpoint(handler func(ctx context.Context, params *RemoveCommentParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewRemoveCommentParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewRemoveCommentParams creates a new RemoveCommentParams object -// with the default values initialized. -func NewRemoveCommentParams() *RemoveCommentParams { - var () - return &RemoveCommentParams{} -} - -// RemoveCommentParams contains all the bound params for the remove comment operation -// typically these are obtained from a http.Request -// -// swagger:parameters removeComment -type RemoveCommentParams struct { - - /*Comment ID to remove - Required: true - In: path - */ - CommentID int64 - /*Ticket ID - Required: true - In: path - */ - ID int64 -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *RemoveCommentParams) ReadRequest(ctx *gin.Context) error { - var res []error - - rCommentID := []string{ctx.Param("commentID")} - if err := o.bindCommentID(rCommentID, true); err != nil { - res = append(res, err) - } - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *RemoveCommentParams) bindCommentID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - value, err := swag.ConvertInt64(raw) - if err != nil { - return errors.InvalidType("commentID", "path", "int64", raw) - } - o.CommentID = value - - return nil -} - -func (o *RemoveCommentParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - value, err := swag.ConvertInt64(raw) - if err != nil { - return errors.InvalidType("id", "path", "int64", raw) - } - o.ID = value - - return nil -} diff --git a/generated/restapi/operations/tickets/remove_ticket_playbook_parameters.go b/generated/restapi/operations/tickets/remove_ticket_playbook_parameters.go deleted file mode 100644 index a7fe504..0000000 --- a/generated/restapi/operations/tickets/remove_ticket_playbook_parameters.go +++ /dev/null @@ -1,113 +0,0 @@ -package tickets - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/swag" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// RemoveTicketPlaybookEndpoint executes the core logic of the related -// route endpoint. -func RemoveTicketPlaybookEndpoint(handler func(ctx context.Context, params *RemoveTicketPlaybookParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewRemoveTicketPlaybookParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewRemoveTicketPlaybookParams creates a new RemoveTicketPlaybookParams object -// with the default values initialized. -func NewRemoveTicketPlaybookParams() *RemoveTicketPlaybookParams { - var () - return &RemoveTicketPlaybookParams{} -} - -// RemoveTicketPlaybookParams contains all the bound params for the remove ticket playbook operation -// typically these are obtained from a http.Request -// -// swagger:parameters removeTicketPlaybook -type RemoveTicketPlaybookParams struct { - - /*Ticket ID - Required: true - In: path - */ - ID int64 - /*Playbook ID - Required: true - In: path - */ - PlaybookID string -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *RemoveTicketPlaybookParams) ReadRequest(ctx *gin.Context) error { - var res []error - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - rPlaybookID := []string{ctx.Param("playbookID")} - if err := o.bindPlaybookID(rPlaybookID, true); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *RemoveTicketPlaybookParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - value, err := swag.ConvertInt64(raw) - if err != nil { - return errors.InvalidType("id", "path", "int64", raw) - } - o.ID = value - - return nil -} - -func (o *RemoveTicketPlaybookParams) bindPlaybookID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - o.PlaybookID = raw - - return nil -} diff --git a/generated/restapi/operations/tickets/run_artifact_parameters.go b/generated/restapi/operations/tickets/run_artifact_parameters.go deleted file mode 100644 index 6a4cee4..0000000 --- a/generated/restapi/operations/tickets/run_artifact_parameters.go +++ /dev/null @@ -1,134 +0,0 @@ -package tickets - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/swag" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// RunArtifactEndpoint executes the core logic of the related -// route endpoint. -func RunArtifactEndpoint(handler func(ctx context.Context, params *RunArtifactParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewRunArtifactParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewRunArtifactParams creates a new RunArtifactParams object -// with the default values initialized. -func NewRunArtifactParams() *RunArtifactParams { - var () - return &RunArtifactParams{} -} - -// RunArtifactParams contains all the bound params for the run artifact operation -// typically these are obtained from a http.Request -// -// swagger:parameters runArtifact -type RunArtifactParams struct { - - /* - Required: true - In: path - */ - Automation string - /*Ticket ID - Required: true - In: path - */ - ID int64 - /* - Required: true - In: path - */ - Name string -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *RunArtifactParams) ReadRequest(ctx *gin.Context) error { - var res []error - - rAutomation := []string{ctx.Param("automation")} - if err := o.bindAutomation(rAutomation, true); err != nil { - res = append(res, err) - } - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - rName := []string{ctx.Param("name")} - if err := o.bindName(rName, true); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *RunArtifactParams) bindAutomation(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - o.Automation = raw - - return nil -} - -func (o *RunArtifactParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - value, err := swag.ConvertInt64(raw) - if err != nil { - return errors.InvalidType("id", "path", "int64", raw) - } - o.ID = value - - return nil -} - -func (o *RunArtifactParams) bindName(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - o.Name = raw - - return nil -} diff --git a/generated/restapi/operations/tickets/run_task_parameters.go b/generated/restapi/operations/tickets/run_task_parameters.go deleted file mode 100644 index f16a10b..0000000 --- a/generated/restapi/operations/tickets/run_task_parameters.go +++ /dev/null @@ -1,134 +0,0 @@ -package tickets - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/swag" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// RunTaskEndpoint executes the core logic of the related -// route endpoint. -func RunTaskEndpoint(handler func(ctx context.Context, params *RunTaskParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewRunTaskParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewRunTaskParams creates a new RunTaskParams object -// with the default values initialized. -func NewRunTaskParams() *RunTaskParams { - var () - return &RunTaskParams{} -} - -// RunTaskParams contains all the bound params for the run task operation -// typically these are obtained from a http.Request -// -// swagger:parameters runTask -type RunTaskParams struct { - - /*Ticket ID - Required: true - In: path - */ - ID int64 - /*Playbook ID - Required: true - In: path - */ - PlaybookID string - /*Task ID - Required: true - In: path - */ - TaskID string -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *RunTaskParams) ReadRequest(ctx *gin.Context) error { - var res []error - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - rPlaybookID := []string{ctx.Param("playbookID")} - if err := o.bindPlaybookID(rPlaybookID, true); err != nil { - res = append(res, err) - } - - rTaskID := []string{ctx.Param("taskID")} - if err := o.bindTaskID(rTaskID, true); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *RunTaskParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - value, err := swag.ConvertInt64(raw) - if err != nil { - return errors.InvalidType("id", "path", "int64", raw) - } - o.ID = value - - return nil -} - -func (o *RunTaskParams) bindPlaybookID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - o.PlaybookID = raw - - return nil -} - -func (o *RunTaskParams) bindTaskID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - o.TaskID = raw - - return nil -} diff --git a/generated/restapi/operations/tickets/set_artifact_parameters.go b/generated/restapi/operations/tickets/set_artifact_parameters.go deleted file mode 100644 index 50c573f..0000000 --- a/generated/restapi/operations/tickets/set_artifact_parameters.go +++ /dev/null @@ -1,137 +0,0 @@ -package tickets - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "io" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime" - "github.com/go-openapi/swag" - - "github.com/SecurityBrewery/catalyst/generated/models" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// SetArtifactEndpoint executes the core logic of the related -// route endpoint. -func SetArtifactEndpoint(handler func(ctx context.Context, params *SetArtifactParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewSetArtifactParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewSetArtifactParams creates a new SetArtifactParams object -// with the default values initialized. -func NewSetArtifactParams() *SetArtifactParams { - var () - return &SetArtifactParams{} -} - -// SetArtifactParams contains all the bound params for the set artifact operation -// typically these are obtained from a http.Request -// -// swagger:parameters setArtifact -type SetArtifactParams struct { - - /* - Required: true - In: body - */ - Artifact *models.Artifact - /*Ticket ID - Required: true - In: path - */ - ID int64 - /* - Required: true - In: path - */ - Name string -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *SetArtifactParams) ReadRequest(ctx *gin.Context) error { - var res []error - - if runtime.HasBody(ctx.Request) { - var body models.Artifact - if err := ctx.BindJSON(&body); err != nil { - if err == io.EOF { - res = append(res, errors.Required("artifact", "body", "")) - } else { - res = append(res, errors.NewParseError("artifact", "body", "", err)) - } - - } else { - o.Artifact = &body - } - } else { - res = append(res, errors.Required("artifact", "body", "")) - } - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - rName := []string{ctx.Param("name")} - if err := o.bindName(rName, true); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *SetArtifactParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - value, err := swag.ConvertInt64(raw) - if err != nil { - return errors.InvalidType("id", "path", "int64", raw) - } - o.ID = value - - return nil -} - -func (o *SetArtifactParams) bindName(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - o.Name = raw - - return nil -} diff --git a/generated/restapi/operations/tickets/set_references_parameters.go b/generated/restapi/operations/tickets/set_references_parameters.go deleted file mode 100644 index 99d1206..0000000 --- a/generated/restapi/operations/tickets/set_references_parameters.go +++ /dev/null @@ -1,116 +0,0 @@ -package tickets - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "io" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime" - "github.com/go-openapi/swag" - - "github.com/SecurityBrewery/catalyst/generated/models" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// SetReferencesEndpoint executes the core logic of the related -// route endpoint. -func SetReferencesEndpoint(handler func(ctx context.Context, params *SetReferencesParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewSetReferencesParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewSetReferencesParams creates a new SetReferencesParams object -// with the default values initialized. -func NewSetReferencesParams() *SetReferencesParams { - var () - return &SetReferencesParams{} -} - -// SetReferencesParams contains all the bound params for the set references operation -// typically these are obtained from a http.Request -// -// swagger:parameters setReferences -type SetReferencesParams struct { - - /*Ticket ID - Required: true - In: path - */ - ID int64 - /*All ticket references - Required: true - In: body - */ - References []*models.Reference -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *SetReferencesParams) ReadRequest(ctx *gin.Context) error { - var res []error - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - if runtime.HasBody(ctx.Request) { - var body []*models.Reference - if err := ctx.BindJSON(&body); err != nil { - if err == io.EOF { - res = append(res, errors.Required("references", "body", "")) - } else { - res = append(res, errors.NewParseError("references", "body", "", err)) - } - - } else { - o.References = body - } - } else { - res = append(res, errors.Required("references", "body", "")) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *SetReferencesParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - value, err := swag.ConvertInt64(raw) - if err != nil { - return errors.InvalidType("id", "path", "int64", raw) - } - o.ID = value - - return nil -} diff --git a/generated/restapi/operations/tickets/set_schema_parameters.go b/generated/restapi/operations/tickets/set_schema_parameters.go deleted file mode 100644 index f93406d..0000000 --- a/generated/restapi/operations/tickets/set_schema_parameters.go +++ /dev/null @@ -1,106 +0,0 @@ -package tickets - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime" - "github.com/go-openapi/swag" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// SetSchemaEndpoint executes the core logic of the related -// route endpoint. -func SetSchemaEndpoint(handler func(ctx context.Context, params *SetSchemaParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewSetSchemaParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewSetSchemaParams creates a new SetSchemaParams object -// with the default values initialized. -func NewSetSchemaParams() *SetSchemaParams { - var () - return &SetSchemaParams{} -} - -// SetSchemaParams contains all the bound params for the set schema operation -// typically these are obtained from a http.Request -// -// swagger:parameters setSchema -type SetSchemaParams struct { - - /*Ticket ID - Required: true - In: path - */ - ID int64 - /*New ticket schema - In: body - */ - Schema string -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *SetSchemaParams) ReadRequest(ctx *gin.Context) error { - var res []error - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - if runtime.HasBody(ctx.Request) { - var body string - if err := ctx.BindJSON(&body); err != nil { - res = append(res, errors.NewParseError("schema", "body", "", err)) - } else { - o.Schema = body - } - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *SetSchemaParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - value, err := swag.ConvertInt64(raw) - if err != nil { - return errors.InvalidType("id", "path", "int64", raw) - } - o.ID = value - - return nil -} diff --git a/generated/restapi/operations/tickets/set_task_parameters.go b/generated/restapi/operations/tickets/set_task_parameters.go deleted file mode 100644 index 3fd05ca..0000000 --- a/generated/restapi/operations/tickets/set_task_parameters.go +++ /dev/null @@ -1,158 +0,0 @@ -package tickets - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "io" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime" - "github.com/go-openapi/swag" - - "github.com/SecurityBrewery/catalyst/generated/models" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// SetTaskEndpoint executes the core logic of the related -// route endpoint. -func SetTaskEndpoint(handler func(ctx context.Context, params *SetTaskParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewSetTaskParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewSetTaskParams creates a new SetTaskParams object -// with the default values initialized. -func NewSetTaskParams() *SetTaskParams { - var () - return &SetTaskParams{} -} - -// SetTaskParams contains all the bound params for the set task operation -// typically these are obtained from a http.Request -// -// swagger:parameters setTask -type SetTaskParams struct { - - /*Ticket ID - Required: true - In: path - */ - ID int64 - /*Playbook ID - Required: true - In: path - */ - PlaybookID string - /*Task - Required: true - In: body - */ - Task *models.Task - /*Task ID - Required: true - In: path - */ - TaskID string -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *SetTaskParams) ReadRequest(ctx *gin.Context) error { - var res []error - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - rPlaybookID := []string{ctx.Param("playbookID")} - if err := o.bindPlaybookID(rPlaybookID, true); err != nil { - res = append(res, err) - } - - if runtime.HasBody(ctx.Request) { - var body models.Task - if err := ctx.BindJSON(&body); err != nil { - if err == io.EOF { - res = append(res, errors.Required("task", "body", "")) - } else { - res = append(res, errors.NewParseError("task", "body", "", err)) - } - - } else { - o.Task = &body - } - } else { - res = append(res, errors.Required("task", "body", "")) - } - - rTaskID := []string{ctx.Param("taskID")} - if err := o.bindTaskID(rTaskID, true); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *SetTaskParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - value, err := swag.ConvertInt64(raw) - if err != nil { - return errors.InvalidType("id", "path", "int64", raw) - } - o.ID = value - - return nil -} - -func (o *SetTaskParams) bindPlaybookID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - o.PlaybookID = raw - - return nil -} - -func (o *SetTaskParams) bindTaskID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - o.TaskID = raw - - return nil -} diff --git a/generated/restapi/operations/tickets/unlink_ticket_parameters.go b/generated/restapi/operations/tickets/unlink_ticket_parameters.go deleted file mode 100644 index fc3ff3a..0000000 --- a/generated/restapi/operations/tickets/unlink_ticket_parameters.go +++ /dev/null @@ -1,115 +0,0 @@ -package tickets - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "io" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime" - "github.com/go-openapi/swag" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// UnlinkTicketEndpoint executes the core logic of the related -// route endpoint. -func UnlinkTicketEndpoint(handler func(ctx context.Context, params *UnlinkTicketParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewUnlinkTicketParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewUnlinkTicketParams creates a new UnlinkTicketParams object -// with the default values initialized. -func NewUnlinkTicketParams() *UnlinkTicketParams { - var () - return &UnlinkTicketParams{} -} - -// UnlinkTicketParams contains all the bound params for the unlink ticket operation -// typically these are obtained from a http.Request -// -// swagger:parameters unlinkTicket -type UnlinkTicketParams struct { - - /*Ticket ID - Required: true - In: path - */ - ID int64 - /*Added ticket ID - Required: true - In: body - */ - LinkedID int64 -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *UnlinkTicketParams) ReadRequest(ctx *gin.Context) error { - var res []error - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - if runtime.HasBody(ctx.Request) { - var body int64 - if err := ctx.BindJSON(&body); err != nil { - if err == io.EOF { - res = append(res, errors.Required("linkedId", "body", "")) - } else { - res = append(res, errors.NewParseError("linkedId", "body", "", err)) - } - - } else { - o.LinkedID = body - } - } else { - res = append(res, errors.Required("linkedId", "body", "")) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *UnlinkTicketParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - value, err := swag.ConvertInt64(raw) - if err != nil { - return errors.InvalidType("id", "path", "int64", raw) - } - o.ID = value - - return nil -} diff --git a/generated/restapi/operations/tickets/update_ticket_parameters.go b/generated/restapi/operations/tickets/update_ticket_parameters.go deleted file mode 100644 index ebd673f..0000000 --- a/generated/restapi/operations/tickets/update_ticket_parameters.go +++ /dev/null @@ -1,116 +0,0 @@ -package tickets - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "io" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime" - "github.com/go-openapi/swag" - - "github.com/SecurityBrewery/catalyst/generated/models" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// UpdateTicketEndpoint executes the core logic of the related -// route endpoint. -func UpdateTicketEndpoint(handler func(ctx context.Context, params *UpdateTicketParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewUpdateTicketParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewUpdateTicketParams creates a new UpdateTicketParams object -// with the default values initialized. -func NewUpdateTicketParams() *UpdateTicketParams { - var () - return &UpdateTicketParams{} -} - -// UpdateTicketParams contains all the bound params for the update ticket operation -// typically these are obtained from a http.Request -// -// swagger:parameters updateTicket -type UpdateTicketParams struct { - - /*Ticket ID - Required: true - In: path - */ - ID int64 - /*Updated ticket - Required: true - In: body - */ - Ticket *models.Ticket -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *UpdateTicketParams) ReadRequest(ctx *gin.Context) error { - var res []error - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - if runtime.HasBody(ctx.Request) { - var body models.Ticket - if err := ctx.BindJSON(&body); err != nil { - if err == io.EOF { - res = append(res, errors.Required("ticket", "body", "")) - } else { - res = append(res, errors.NewParseError("ticket", "body", "", err)) - } - - } else { - o.Ticket = &body - } - } else { - res = append(res, errors.Required("ticket", "body", "")) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *UpdateTicketParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - value, err := swag.ConvertInt64(raw) - if err != nil { - return errors.InvalidType("id", "path", "int64", raw) - } - o.ID = value - - return nil -} diff --git a/generated/restapi/operations/tickettypes/create_ticket_type_parameters.go b/generated/restapi/operations/tickettypes/create_ticket_type_parameters.go deleted file mode 100644 index 034d5ed..0000000 --- a/generated/restapi/operations/tickettypes/create_ticket_type_parameters.go +++ /dev/null @@ -1,90 +0,0 @@ -package tickettypes - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "io" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime" - - "github.com/SecurityBrewery/catalyst/generated/models" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// CreateTicketTypeEndpoint executes the core logic of the related -// route endpoint. -func CreateTicketTypeEndpoint(handler func(ctx context.Context, params *CreateTicketTypeParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewCreateTicketTypeParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewCreateTicketTypeParams creates a new CreateTicketTypeParams object -// with the default values initialized. -func NewCreateTicketTypeParams() *CreateTicketTypeParams { - var () - return &CreateTicketTypeParams{} -} - -// CreateTicketTypeParams contains all the bound params for the create ticket type operation -// typically these are obtained from a http.Request -// -// swagger:parameters createTicketType -type CreateTicketTypeParams struct { - - /*New tickettype - Required: true - In: body - */ - Tickettype *models.TicketTypeForm -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *CreateTicketTypeParams) ReadRequest(ctx *gin.Context) error { - var res []error - - if runtime.HasBody(ctx.Request) { - var body models.TicketTypeForm - if err := ctx.BindJSON(&body); err != nil { - if err == io.EOF { - res = append(res, errors.Required("tickettype", "body", "")) - } else { - res = append(res, errors.NewParseError("tickettype", "body", "", err)) - } - - } else { - o.Tickettype = &body - } - } else { - res = append(res, errors.Required("tickettype", "body", "")) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} diff --git a/generated/restapi/operations/tickettypes/delete_ticket_type_parameters.go b/generated/restapi/operations/tickettypes/delete_ticket_type_parameters.go deleted file mode 100644 index 98e677d..0000000 --- a/generated/restapi/operations/tickettypes/delete_ticket_type_parameters.go +++ /dev/null @@ -1,87 +0,0 @@ -package tickettypes - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// DeleteTicketTypeEndpoint executes the core logic of the related -// route endpoint. -func DeleteTicketTypeEndpoint(handler func(ctx context.Context, params *DeleteTicketTypeParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewDeleteTicketTypeParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewDeleteTicketTypeParams creates a new DeleteTicketTypeParams object -// with the default values initialized. -func NewDeleteTicketTypeParams() *DeleteTicketTypeParams { - var () - return &DeleteTicketTypeParams{} -} - -// DeleteTicketTypeParams contains all the bound params for the delete ticket type operation -// typically these are obtained from a http.Request -// -// swagger:parameters deleteTicketType -type DeleteTicketTypeParams struct { - - /*TicketType ID - Required: true - In: path - */ - ID string -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *DeleteTicketTypeParams) ReadRequest(ctx *gin.Context) error { - var res []error - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *DeleteTicketTypeParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - o.ID = raw - - return nil -} diff --git a/generated/restapi/operations/tickettypes/get_ticket_type_parameters.go b/generated/restapi/operations/tickettypes/get_ticket_type_parameters.go deleted file mode 100644 index 70ad526..0000000 --- a/generated/restapi/operations/tickettypes/get_ticket_type_parameters.go +++ /dev/null @@ -1,87 +0,0 @@ -package tickettypes - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// GetTicketTypeEndpoint executes the core logic of the related -// route endpoint. -func GetTicketTypeEndpoint(handler func(ctx context.Context, params *GetTicketTypeParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewGetTicketTypeParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewGetTicketTypeParams creates a new GetTicketTypeParams object -// with the default values initialized. -func NewGetTicketTypeParams() *GetTicketTypeParams { - var () - return &GetTicketTypeParams{} -} - -// GetTicketTypeParams contains all the bound params for the get ticket type operation -// typically these are obtained from a http.Request -// -// swagger:parameters getTicketType -type GetTicketTypeParams struct { - - /*TicketType ID - Required: true - In: path - */ - ID string -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *GetTicketTypeParams) ReadRequest(ctx *gin.Context) error { - var res []error - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *GetTicketTypeParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - o.ID = raw - - return nil -} diff --git a/generated/restapi/operations/tickettypes/list_ticket_types_parameters.go b/generated/restapi/operations/tickettypes/list_ticket_types_parameters.go deleted file mode 100644 index 607dcc3..0000000 --- a/generated/restapi/operations/tickettypes/list_ticket_types_parameters.go +++ /dev/null @@ -1,55 +0,0 @@ -package tickettypes - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// ListTicketTypesEndpoint executes the core logic of the related -// route endpoint. -func ListTicketTypesEndpoint(handler func(ctx context.Context) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - resp := handler(ctx) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewListTicketTypesParams creates a new ListTicketTypesParams object -// with the default values initialized. -func NewListTicketTypesParams() *ListTicketTypesParams { - var () - return &ListTicketTypesParams{} -} - -// ListTicketTypesParams contains all the bound params for the list ticket types operation -// typically these are obtained from a http.Request -// -// swagger:parameters listTicketTypes -type ListTicketTypesParams struct { -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *ListTicketTypesParams) ReadRequest(ctx *gin.Context) error { - var res []error - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} diff --git a/generated/restapi/operations/tickettypes/update_ticket_type_parameters.go b/generated/restapi/operations/tickettypes/update_ticket_type_parameters.go deleted file mode 100644 index 9c7b323..0000000 --- a/generated/restapi/operations/tickettypes/update_ticket_type_parameters.go +++ /dev/null @@ -1,111 +0,0 @@ -package tickettypes - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "io" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime" - - "github.com/SecurityBrewery/catalyst/generated/models" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// UpdateTicketTypeEndpoint executes the core logic of the related -// route endpoint. -func UpdateTicketTypeEndpoint(handler func(ctx context.Context, params *UpdateTicketTypeParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewUpdateTicketTypeParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewUpdateTicketTypeParams creates a new UpdateTicketTypeParams object -// with the default values initialized. -func NewUpdateTicketTypeParams() *UpdateTicketTypeParams { - var () - return &UpdateTicketTypeParams{} -} - -// UpdateTicketTypeParams contains all the bound params for the update ticket type operation -// typically these are obtained from a http.Request -// -// swagger:parameters updateTicketType -type UpdateTicketTypeParams struct { - - /*TicketType ID - Required: true - In: path - */ - ID string - /*TicketType object that needs to be added - Required: true - In: body - */ - Tickettype *models.TicketTypeForm -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *UpdateTicketTypeParams) ReadRequest(ctx *gin.Context) error { - var res []error - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - if runtime.HasBody(ctx.Request) { - var body models.TicketTypeForm - if err := ctx.BindJSON(&body); err != nil { - if err == io.EOF { - res = append(res, errors.Required("tickettype", "body", "")) - } else { - res = append(res, errors.NewParseError("tickettype", "body", "", err)) - } - - } else { - o.Tickettype = &body - } - } else { - res = append(res, errors.Required("tickettype", "body", "")) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *UpdateTicketTypeParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - o.ID = raw - - return nil -} diff --git a/generated/restapi/operations/userdata/current_user_data_parameters.go b/generated/restapi/operations/userdata/current_user_data_parameters.go deleted file mode 100644 index 800485a..0000000 --- a/generated/restapi/operations/userdata/current_user_data_parameters.go +++ /dev/null @@ -1,55 +0,0 @@ -package userdata - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// CurrentUserDataEndpoint executes the core logic of the related -// route endpoint. -func CurrentUserDataEndpoint(handler func(ctx context.Context) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - resp := handler(ctx) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewCurrentUserDataParams creates a new CurrentUserDataParams object -// with the default values initialized. -func NewCurrentUserDataParams() *CurrentUserDataParams { - var () - return &CurrentUserDataParams{} -} - -// CurrentUserDataParams contains all the bound params for the current user data operation -// typically these are obtained from a http.Request -// -// swagger:parameters currentUserData -type CurrentUserDataParams struct { -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *CurrentUserDataParams) ReadRequest(ctx *gin.Context) error { - var res []error - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} diff --git a/generated/restapi/operations/userdata/get_user_data_parameters.go b/generated/restapi/operations/userdata/get_user_data_parameters.go deleted file mode 100644 index c255598..0000000 --- a/generated/restapi/operations/userdata/get_user_data_parameters.go +++ /dev/null @@ -1,87 +0,0 @@ -package userdata - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// GetUserDataEndpoint executes the core logic of the related -// route endpoint. -func GetUserDataEndpoint(handler func(ctx context.Context, params *GetUserDataParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewGetUserDataParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewGetUserDataParams creates a new GetUserDataParams object -// with the default values initialized. -func NewGetUserDataParams() *GetUserDataParams { - var () - return &GetUserDataParams{} -} - -// GetUserDataParams contains all the bound params for the get user data operation -// typically these are obtained from a http.Request -// -// swagger:parameters getUserData -type GetUserDataParams struct { - - /*User Data ID - Required: true - In: path - */ - ID string -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *GetUserDataParams) ReadRequest(ctx *gin.Context) error { - var res []error - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *GetUserDataParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - o.ID = raw - - return nil -} diff --git a/generated/restapi/operations/userdata/list_user_data_parameters.go b/generated/restapi/operations/userdata/list_user_data_parameters.go deleted file mode 100644 index fff2a0d..0000000 --- a/generated/restapi/operations/userdata/list_user_data_parameters.go +++ /dev/null @@ -1,55 +0,0 @@ -package userdata - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// ListUserDataEndpoint executes the core logic of the related -// route endpoint. -func ListUserDataEndpoint(handler func(ctx context.Context) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - resp := handler(ctx) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewListUserDataParams creates a new ListUserDataParams object -// with the default values initialized. -func NewListUserDataParams() *ListUserDataParams { - var () - return &ListUserDataParams{} -} - -// ListUserDataParams contains all the bound params for the list user data operation -// typically these are obtained from a http.Request -// -// swagger:parameters listUserData -type ListUserDataParams struct { -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *ListUserDataParams) ReadRequest(ctx *gin.Context) error { - var res []error - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} diff --git a/generated/restapi/operations/userdata/update_current_user_data_parameters.go b/generated/restapi/operations/userdata/update_current_user_data_parameters.go deleted file mode 100644 index 2b926ba..0000000 --- a/generated/restapi/operations/userdata/update_current_user_data_parameters.go +++ /dev/null @@ -1,90 +0,0 @@ -package userdata - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "io" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime" - - "github.com/SecurityBrewery/catalyst/generated/models" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// UpdateCurrentUserDataEndpoint executes the core logic of the related -// route endpoint. -func UpdateCurrentUserDataEndpoint(handler func(ctx context.Context, params *UpdateCurrentUserDataParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewUpdateCurrentUserDataParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewUpdateCurrentUserDataParams creates a new UpdateCurrentUserDataParams object -// with the default values initialized. -func NewUpdateCurrentUserDataParams() *UpdateCurrentUserDataParams { - var () - return &UpdateCurrentUserDataParams{} -} - -// UpdateCurrentUserDataParams contains all the bound params for the update current user data operation -// typically these are obtained from a http.Request -// -// swagger:parameters updateCurrentUserData -type UpdateCurrentUserDataParams struct { - - /*User data object that needs to be added - Required: true - In: body - */ - Userdata *models.UserData -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *UpdateCurrentUserDataParams) ReadRequest(ctx *gin.Context) error { - var res []error - - if runtime.HasBody(ctx.Request) { - var body models.UserData - if err := ctx.BindJSON(&body); err != nil { - if err == io.EOF { - res = append(res, errors.Required("userdata", "body", "")) - } else { - res = append(res, errors.NewParseError("userdata", "body", "", err)) - } - - } else { - o.Userdata = &body - } - } else { - res = append(res, errors.Required("userdata", "body", "")) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} diff --git a/generated/restapi/operations/userdata/update_user_data_parameters.go b/generated/restapi/operations/userdata/update_user_data_parameters.go deleted file mode 100644 index 4212316..0000000 --- a/generated/restapi/operations/userdata/update_user_data_parameters.go +++ /dev/null @@ -1,111 +0,0 @@ -package userdata - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "io" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime" - - "github.com/SecurityBrewery/catalyst/generated/models" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// UpdateUserDataEndpoint executes the core logic of the related -// route endpoint. -func UpdateUserDataEndpoint(handler func(ctx context.Context, params *UpdateUserDataParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewUpdateUserDataParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewUpdateUserDataParams creates a new UpdateUserDataParams object -// with the default values initialized. -func NewUpdateUserDataParams() *UpdateUserDataParams { - var () - return &UpdateUserDataParams{} -} - -// UpdateUserDataParams contains all the bound params for the update user data operation -// typically these are obtained from a http.Request -// -// swagger:parameters updateUserData -type UpdateUserDataParams struct { - - /*User Data ID - Required: true - In: path - */ - ID string - /*User data object that needs to be added - Required: true - In: body - */ - Userdata *models.UserData -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *UpdateUserDataParams) ReadRequest(ctx *gin.Context) error { - var res []error - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - if runtime.HasBody(ctx.Request) { - var body models.UserData - if err := ctx.BindJSON(&body); err != nil { - if err == io.EOF { - res = append(res, errors.Required("userdata", "body", "")) - } else { - res = append(res, errors.NewParseError("userdata", "body", "", err)) - } - - } else { - o.Userdata = &body - } - } else { - res = append(res, errors.Required("userdata", "body", "")) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *UpdateUserDataParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - o.ID = raw - - return nil -} diff --git a/generated/restapi/operations/users/create_user_parameters.go b/generated/restapi/operations/users/create_user_parameters.go deleted file mode 100644 index d345bae..0000000 --- a/generated/restapi/operations/users/create_user_parameters.go +++ /dev/null @@ -1,90 +0,0 @@ -package users - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "io" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime" - - "github.com/SecurityBrewery/catalyst/generated/models" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// CreateUserEndpoint executes the core logic of the related -// route endpoint. -func CreateUserEndpoint(handler func(ctx context.Context, params *CreateUserParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewCreateUserParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewCreateUserParams creates a new CreateUserParams object -// with the default values initialized. -func NewCreateUserParams() *CreateUserParams { - var () - return &CreateUserParams{} -} - -// CreateUserParams contains all the bound params for the create user operation -// typically these are obtained from a http.Request -// -// swagger:parameters createUser -type CreateUserParams struct { - - /*user object that needs to be added - Required: true - In: body - */ - User *models.UserForm -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *CreateUserParams) ReadRequest(ctx *gin.Context) error { - var res []error - - if runtime.HasBody(ctx.Request) { - var body models.UserForm - if err := ctx.BindJSON(&body); err != nil { - if err == io.EOF { - res = append(res, errors.Required("user", "body", "")) - } else { - res = append(res, errors.NewParseError("user", "body", "", err)) - } - - } else { - o.User = &body - } - } else { - res = append(res, errors.Required("user", "body", "")) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} diff --git a/generated/restapi/operations/users/current_user_parameters.go b/generated/restapi/operations/users/current_user_parameters.go deleted file mode 100644 index 28420e0..0000000 --- a/generated/restapi/operations/users/current_user_parameters.go +++ /dev/null @@ -1,55 +0,0 @@ -package users - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// CurrentUserEndpoint executes the core logic of the related -// route endpoint. -func CurrentUserEndpoint(handler func(ctx context.Context) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - resp := handler(ctx) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewCurrentUserParams creates a new CurrentUserParams object -// with the default values initialized. -func NewCurrentUserParams() *CurrentUserParams { - var () - return &CurrentUserParams{} -} - -// CurrentUserParams contains all the bound params for the current user operation -// typically these are obtained from a http.Request -// -// swagger:parameters currentUser -type CurrentUserParams struct { -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *CurrentUserParams) ReadRequest(ctx *gin.Context) error { - var res []error - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} diff --git a/generated/restapi/operations/users/delete_user_parameters.go b/generated/restapi/operations/users/delete_user_parameters.go deleted file mode 100644 index 3c7ccea..0000000 --- a/generated/restapi/operations/users/delete_user_parameters.go +++ /dev/null @@ -1,87 +0,0 @@ -package users - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// DeleteUserEndpoint executes the core logic of the related -// route endpoint. -func DeleteUserEndpoint(handler func(ctx context.Context, params *DeleteUserParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewDeleteUserParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewDeleteUserParams creates a new DeleteUserParams object -// with the default values initialized. -func NewDeleteUserParams() *DeleteUserParams { - var () - return &DeleteUserParams{} -} - -// DeleteUserParams contains all the bound params for the delete user operation -// typically these are obtained from a http.Request -// -// swagger:parameters deleteUser -type DeleteUserParams struct { - - /*user ID - Required: true - In: path - */ - ID string -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *DeleteUserParams) ReadRequest(ctx *gin.Context) error { - var res []error - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *DeleteUserParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - o.ID = raw - - return nil -} diff --git a/generated/restapi/operations/users/get_user_parameters.go b/generated/restapi/operations/users/get_user_parameters.go deleted file mode 100644 index 2f3230e..0000000 --- a/generated/restapi/operations/users/get_user_parameters.go +++ /dev/null @@ -1,87 +0,0 @@ -package users - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// GetUserEndpoint executes the core logic of the related -// route endpoint. -func GetUserEndpoint(handler func(ctx context.Context, params *GetUserParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewGetUserParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewGetUserParams creates a new GetUserParams object -// with the default values initialized. -func NewGetUserParams() *GetUserParams { - var () - return &GetUserParams{} -} - -// GetUserParams contains all the bound params for the get user operation -// typically these are obtained from a http.Request -// -// swagger:parameters getUser -type GetUserParams struct { - - /*user ID - Required: true - In: path - */ - ID string -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *GetUserParams) ReadRequest(ctx *gin.Context) error { - var res []error - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *GetUserParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - o.ID = raw - - return nil -} diff --git a/generated/restapi/operations/users/list_users_parameters.go b/generated/restapi/operations/users/list_users_parameters.go deleted file mode 100644 index b6c664b..0000000 --- a/generated/restapi/operations/users/list_users_parameters.go +++ /dev/null @@ -1,55 +0,0 @@ -package users - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// ListUsersEndpoint executes the core logic of the related -// route endpoint. -func ListUsersEndpoint(handler func(ctx context.Context) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - resp := handler(ctx) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewListUsersParams creates a new ListUsersParams object -// with the default values initialized. -func NewListUsersParams() *ListUsersParams { - var () - return &ListUsersParams{} -} - -// ListUsersParams contains all the bound params for the list users operation -// typically these are obtained from a http.Request -// -// swagger:parameters listUsers -type ListUsersParams struct { -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *ListUsersParams) ReadRequest(ctx *gin.Context) error { - var res []error - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} diff --git a/generated/restapi/operations/users/update_user_parameters.go b/generated/restapi/operations/users/update_user_parameters.go deleted file mode 100644 index 9ad2352..0000000 --- a/generated/restapi/operations/users/update_user_parameters.go +++ /dev/null @@ -1,111 +0,0 @@ -package users - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "io" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime" - - "github.com/SecurityBrewery/catalyst/generated/models" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// UpdateUserEndpoint executes the core logic of the related -// route endpoint. -func UpdateUserEndpoint(handler func(ctx context.Context, params *UpdateUserParams) *api.Response) gin.HandlerFunc { - return func(ctx *gin.Context) { - - // generate params from request - params := NewUpdateUserParams() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - - resp := handler(ctx, params) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// NewUpdateUserParams creates a new UpdateUserParams object -// with the default values initialized. -func NewUpdateUserParams() *UpdateUserParams { - var () - return &UpdateUserParams{} -} - -// UpdateUserParams contains all the bound params for the update user operation -// typically these are obtained from a http.Request -// -// swagger:parameters updateUser -type UpdateUserParams struct { - - /*Template ID - Required: true - In: path - */ - ID string - /*user object that needs to be added - Required: true - In: body - */ - User *models.UserForm -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func (o *UpdateUserParams) ReadRequest(ctx *gin.Context) error { - var res []error - - rID := []string{ctx.Param("id")} - if err := o.bindID(rID, true); err != nil { - res = append(res, err) - } - - if runtime.HasBody(ctx.Request) { - var body models.UserForm - if err := ctx.BindJSON(&body); err != nil { - if err == io.EOF { - res = append(res, errors.Required("user", "body", "")) - } else { - res = append(res, errors.NewParseError("user", "body", "", err)) - } - - } else { - o.User = &body - } - } else { - res = append(res, errors.Required("user", "body", "")) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (o *UpdateUserParams) bindID(rawData []string, hasKey bool) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - o.ID = raw - - return nil -} diff --git a/generated/test/api_server_test.go b/generated/test/api_server_test.go deleted file mode 100644 index 670b349..0000000 --- a/generated/test/api_server_test.go +++ /dev/null @@ -1,638 +0,0 @@ -package test - -import ( - "bytes" - "encoding/json" - "io" - "net/http" - "net/http/httptest" - "testing" - "time" - - "github.com/gin-gonic/gin" - "github.com/stretchr/testify/assert" - "github.com/tidwall/gjson" - "github.com/tidwall/sjson" - - "github.com/SecurityBrewery/catalyst/database/busdb" - "github.com/SecurityBrewery/catalyst/test" - ctime "github.com/SecurityBrewery/catalyst/time" -) - -type testClock struct{} - -func (testClock) Now() time.Time { - return time.Date(2021, 12, 12, 12, 12, 12, 12, time.UTC) -} - -func TestService(t *testing.T) { - gin.SetMode(gin.TestMode) - ctime.DefaultClock = testClock{} - - type args struct { - method string - url string - data interface{} - } - type want struct { - status int - body interface{} - } - tests := []struct { - name string - args args - want want - }{ - - { - name: "AddArtifact", - args: args{method: "POST", url: "/api/tickets/8123/artifacts", data: map[string]interface{}{"name": "2.2.2.2"}}, - want: want{ - status: 200, - body: map[string]interface{}{"artifacts": []interface{}{map[string]interface{}{"name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", "status": "unknown"}, map[string]interface{}{"name": "http://www.customerviral.io/scalable/vertical/killer", "status": "clean"}, map[string]interface{}{"name": "leadreintermediate.io", "status": "malicious"}, map[string]interface{}{"name": "2.2.2.2", "status": "unknown", "type": "ip"}}, "created": "2021-10-02T16:04:59.078206Z", "id": 8123, "modified": "2021-12-12T12:12:12.000000012Z", "name": "live zebra", "owner": "demo", "playbooks": map[string]interface{}{"phishing": map[string]interface{}{"name": "Phishing", "tasks": map[string]interface{}{"block-iocs": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Block IOCs", "order": 6, "type": "task"}, "block-sender": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Block sender", "next": map[string]interface{}{"extract-iocs": ""}, "order": 3, "type": "task"}, "board": map[string]interface{}{"active": true, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Board Involvement?", "next": map[string]interface{}{"escalate": "boardInvolved == true", "mail-available": "boardInvolved == false"}, "order": 0, "schema": map[string]interface{}{"properties": map[string]interface{}{"boardInvolved": map[string]interface{}{"default": false, "title": "A board member is involved.", "type": "boolean"}}, "required": []interface{}{"boardInvolved"}, "title": "Board Involvement?", "type": "object"}, "type": "input"}, "escalate": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Escalate to CISO", "order": 1, "type": "task"}, "extract-iocs": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Extract IOCs", "next": map[string]interface{}{"block-iocs": ""}, "order": 5, "schema": map[string]interface{}{"properties": map[string]interface{}{"iocs": map[string]interface{}{"items": map[string]interface{}{"type": "string"}, "title": "IOCs", "type": "array"}}, "title": "Extract IOCs", "type": "object"}, "type": "input"}, "mail-available": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Mail available", "next": map[string]interface{}{"block-sender": "schemaKey == 'yes'", "extract-iocs": "schemaKey == 'yes'", "search-email-gateway": "schemaKey == 'no'"}, "order": 2, "schema": map[string]interface{}{"oneOf": []interface{}{map[string]interface{}{"properties": map[string]interface{}{"mail": map[string]interface{}{"title": "Mail", "type": "string", "x-display": "textarea"}, "schemaKey": map[string]interface{}{"const": "yes", "type": "string"}}, "required": []interface{}{"mail"}, "title": "Yes"}, map[string]interface{}{"properties": map[string]interface{}{"schemaKey": map[string]interface{}{"const": "no", "type": "string"}}, "title": "No"}}, "title": "Mail available", "type": "object"}, "type": "input"}, "search-email-gateway": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Search email gateway", "next": map[string]interface{}{"extract-iocs": ""}, "order": 4, "type": "task"}}}}, "references": []interface{}{map[string]interface{}{"href": "https://www.leadmaximize.net/e-services/back-end", "name": "performance"}, map[string]interface{}{"href": "http://www.corporateinteractive.name/rich", "name": "autumn"}, map[string]interface{}{"href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", "name": "suggest"}}, "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", "status": "closed", "type": "incident"}, - }, - }, - { - name: "AddComment", - args: args{method: "POST", url: "/api/tickets/8125/comments", data: map[string]interface{}{"message": "My first comment"}}, - want: want{ - status: 200, - body: map[string]interface{}{"comments": []interface{}{map[string]interface{}{"created": "2021-12-12T12:12:12.000000012Z", "creator": "bob", "message": "My first comment"}}, "created": "2021-10-02T16:04:59.078186Z", "id": 8125, "modified": "2021-12-12T12:12:12.000000012Z", "name": "phishing from selenafadel@von.com detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "https://www.seniorleading-edge.name/users/efficient", "name": "recovery"}, map[string]interface{}{"href": "http://www.dynamicseamless.com/clicks-and-mortar", "name": "force"}, map[string]interface{}{"href": "http://www.leadscalable.biz/envisioneer", "name": "fund"}}, "schema": "{}", "status": "closed", "tickets": []interface{}{map[string]interface{}{"created": "2021-10-02T16:04:59.078186Z", "id": 8126, "modified": "2021-10-02T16:04:59.078186Z", "name": "Surfaceintroduce virus detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "http://www.centralworld-class.io/synthesize", "name": "university"}, map[string]interface{}{"href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", "name": "goal"}, map[string]interface{}{"href": "http://www.chiefsyndicate.io/action-items", "name": "unemployment"}}, "schema": "{}", "status": "closed", "type": "alert"}}, "type": "alert"}, - }, - }, - { - name: "AddTicketPlaybook", - args: args{method: "POST", url: "/api/tickets/8125/playbooks", data: map[string]interface{}{"yaml": "name: Simple\ntasks:\n input:\n name: Upload malware if possible\n type: input\n schema:\n title: Malware\n type: object\n properties:\n malware:\n type: string\n title: Select malware\n default: \"\"\n next:\n hash: \"malware != ''\"\n\n hash:\n name: Hash the malware\n type: automation\n automation: hash.sha1\n payload:\n default: \"playbook.tasks['input'].data['malware']\"\n next:\n escalate:\n\n escalate:\n name: Escalate to malware team\n type: task\n"}}, - want: want{ - status: 200, - body: map[string]interface{}{"created": "2021-10-02T16:04:59.078186Z", "id": 8125, "modified": "2021-12-12T12:12:12.000000012Z", "name": "phishing from selenafadel@von.com detected", "owner": "demo", "playbooks": map[string]interface{}{"simple": map[string]interface{}{"name": "Simple", "tasks": map[string]interface{}{"escalate": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Escalate to malware team", "order": 2, "type": "task"}, "hash": map[string]interface{}{"active": false, "automation": "hash.sha1", "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Hash the malware", "next": map[string]interface{}{"escalate": ""}, "order": 1, "payload": map[string]interface{}{"default": "playbook.tasks['input'].data['malware']"}, "type": "automation"}, "input": map[string]interface{}{"active": true, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Upload malware if possible", "next": map[string]interface{}{"hash": "malware != ''"}, "order": 0, "schema": map[string]interface{}{"properties": map[string]interface{}{"malware": map[string]interface{}{"default": "", "title": "Select malware", "type": "string"}}, "title": "Malware", "type": "object"}, "type": "input"}}}}, "references": []interface{}{map[string]interface{}{"href": "https://www.seniorleading-edge.name/users/efficient", "name": "recovery"}, map[string]interface{}{"href": "http://www.dynamicseamless.com/clicks-and-mortar", "name": "force"}, map[string]interface{}{"href": "http://www.leadscalable.biz/envisioneer", "name": "fund"}}, "schema": "{}", "status": "closed", "tickets": []interface{}{map[string]interface{}{"created": "2021-10-02T16:04:59.078186Z", "id": 8126, "modified": "2021-10-02T16:04:59.078186Z", "name": "Surfaceintroduce virus detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "http://www.centralworld-class.io/synthesize", "name": "university"}, map[string]interface{}{"href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", "name": "goal"}, map[string]interface{}{"href": "http://www.chiefsyndicate.io/action-items", "name": "unemployment"}}, "schema": "{}", "status": "closed", "type": "alert"}}, "type": "alert"}, - }, - }, - { - name: "CompleteTask", - args: args{method: "PUT", url: "/api/tickets/8123/playbooks/phishing/task/board/complete", data: map[string]interface{}{"boardInvolved": true}}, - want: want{ - status: 200, - body: map[string]interface{}{"artifacts": []interface{}{map[string]interface{}{"name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", "status": "unknown"}, map[string]interface{}{"name": "http://www.customerviral.io/scalable/vertical/killer", "status": "clean"}, map[string]interface{}{"name": "leadreintermediate.io", "status": "malicious"}}, "created": "2021-10-02T16:04:59.078206Z", "id": 8123, "modified": "2021-12-12T12:12:12.000000012Z", "name": "live zebra", "owner": "demo", "playbooks": map[string]interface{}{"phishing": map[string]interface{}{"name": "Phishing", "tasks": map[string]interface{}{"block-iocs": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Block IOCs", "order": 6, "type": "task"}, "block-sender": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Block sender", "next": map[string]interface{}{"extract-iocs": ""}, "order": 3, "type": "task"}, "board": map[string]interface{}{"active": false, "closed": "2021-12-12T12:12:12.000000012Z", "created": "2021-12-12T12:12:12.000000012Z", "data": map[string]interface{}{"boardInvolved": true}, "done": true, "name": "Board Involvement?", "next": map[string]interface{}{"escalate": "boardInvolved == true", "mail-available": "boardInvolved == false"}, "order": 0, "schema": map[string]interface{}{"properties": map[string]interface{}{"boardInvolved": map[string]interface{}{"default": false, "title": "A board member is involved.", "type": "boolean"}}, "required": []interface{}{"boardInvolved"}, "title": "Board Involvement?", "type": "object"}, "type": "input"}, "escalate": map[string]interface{}{"active": true, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Escalate to CISO", "order": 1, "type": "task"}, "extract-iocs": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Extract IOCs", "next": map[string]interface{}{"block-iocs": ""}, "order": 5, "schema": map[string]interface{}{"properties": map[string]interface{}{"iocs": map[string]interface{}{"items": map[string]interface{}{"type": "string"}, "title": "IOCs", "type": "array"}}, "title": "Extract IOCs", "type": "object"}, "type": "input"}, "mail-available": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Mail available", "next": map[string]interface{}{"block-sender": "schemaKey == 'yes'", "extract-iocs": "schemaKey == 'yes'", "search-email-gateway": "schemaKey == 'no'"}, "order": 2, "schema": map[string]interface{}{"oneOf": []interface{}{map[string]interface{}{"properties": map[string]interface{}{"mail": map[string]interface{}{"title": "Mail", "type": "string", "x-display": "textarea"}, "schemaKey": map[string]interface{}{"const": "yes", "type": "string"}}, "required": []interface{}{"mail"}, "title": "Yes"}, map[string]interface{}{"properties": map[string]interface{}{"schemaKey": map[string]interface{}{"const": "no", "type": "string"}}, "title": "No"}}, "title": "Mail available", "type": "object"}, "type": "input"}, "search-email-gateway": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Search email gateway", "next": map[string]interface{}{"extract-iocs": ""}, "order": 4, "type": "task"}}}}, "references": []interface{}{map[string]interface{}{"href": "https://www.leadmaximize.net/e-services/back-end", "name": "performance"}, map[string]interface{}{"href": "http://www.corporateinteractive.name/rich", "name": "autumn"}, map[string]interface{}{"href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", "name": "suggest"}}, "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", "status": "closed", "type": "incident"}, - }, - }, - { - name: "CreateAutomation", - args: args{method: "POST", url: "/api/automations", data: map[string]interface{}{"id": "hash-sha-256", "image": "docker.io/python:3", "script": "import sys\nimport json\nimport hashlib\n\n\ndef run(msg):\n sha256 = hashlib.sha256(msg['payload']['default'].encode('utf-8'))\n return {'hash': sha256.hexdigest()}\n\n\nprint(json.dumps(run(json.loads(sys.argv[1]))))\n", "type": []interface{}{"global"}}}, - want: want{ - status: 200, - body: map[string]interface{}{"id": "hash-sha-256", "image": "docker.io/python:3", "script": "import sys\nimport json\nimport hashlib\n\n\ndef run(msg):\n sha256 = hashlib.sha256(msg['payload']['default'].encode('utf-8'))\n return {'hash': sha256.hexdigest()}\n\n\nprint(json.dumps(run(json.loads(sys.argv[1]))))\n", "type": []interface{}{"global"}}, - }, - }, - { - name: "CreatePlaybook", - args: args{method: "POST", url: "/api/playbooks", data: map[string]interface{}{"yaml": "name: Simple2\ntasks:\n input:\n name: Upload malware if possible\n type: input\n schema:\n title: Malware\n type: object\n properties:\n malware:\n type: string\n title: Select malware\n default: \"\"\n next:\n hash: \"malware != ''\"\n\n hash:\n name: Hash the malware\n type: automation\n automation: hash.sha1\n payload:\n default: \"playbook.tasks['input'].data['malware']\"\n next:\n escalate:\n\n escalate:\n name: Escalate to malware team\n type: task\n"}}, - want: want{ - status: 200, - body: map[string]interface{}{"id": "simple-2", "name": "Simple2", "yaml": "name: Simple2\ntasks:\n input:\n name: Upload malware if possible\n type: input\n schema:\n title: Malware\n type: object\n properties:\n malware:\n type: string\n title: Select malware\n default: \"\"\n next:\n hash: \"malware != ''\"\n\n hash:\n name: Hash the malware\n type: automation\n automation: hash.sha1\n payload:\n default: \"playbook.tasks['input'].data['malware']\"\n next:\n escalate:\n\n escalate:\n name: Escalate to malware team\n type: task\n"}, - }, - }, - { - name: "CreateTemplate", - args: args{method: "POST", url: "/api/templates", data: map[string]interface{}{"name": "My Template", "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n"}}, - want: want{ - status: 200, - body: map[string]interface{}{"id": "my-template", "name": "My Template", "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n"}, - }, - }, - { - name: "CreateTicket", - args: args{method: "POST", url: "/api/tickets", data: map[string]interface{}{"id": 123, "name": "Wannacry infection", "owner": "bob", "status": "open", "type": "incident"}}, - want: want{ - status: 200, - body: map[string]interface{}{"created": "2021-12-12T12:12:12.000000012Z", "id": 123, "modified": "2021-12-12T12:12:12.000000012Z", "name": "Wannacry infection", "owner": "bob", "schema": "{}", "status": "open", "type": "incident"}, - }, - }, - { - name: "CreateTicketBatch", - args: args{method: "POST", url: "/api/tickets/batch", data: []interface{}{map[string]interface{}{"id": 123, "name": "Wannacry infection", "owner": "bob", "status": "open", "type": "incident"}}}, - want: want{ - status: 204, - body: nil, - }, - }, - { - name: "CreateTicketType", - args: args{method: "POST", url: "/api/tickettypes", data: map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-newspaper-variant-outline", "name": "TI Tickets"}}, - want: want{ - status: 200, - body: map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-newspaper-variant-outline", "id": "ti-tickets", "name": "TI Tickets"}, - }, - }, - { - name: "CreateUser", - args: args{method: "POST", url: "/api/users", data: map[string]interface{}{"id": "syncscript", "roles": []interface{}{"analyst"}}}, - want: want{ - status: 200, - body: map[string]interface{}{"blocked": false, "id": "syncscript", "roles": []interface{}{"analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read"}, "secret": "v39bOuobnlEljfWzjAgoKzhmnh1xSMxH"}, - }, - }, - { - name: "CurrentUser", - args: args{method: "GET", url: "/api/currentuser"}, - want: want{ - status: 200, - body: map[string]interface{}{"apikey": false, "blocked": false, "id": "bob", "roles": []interface{}{"admin:backup:read", "admin:backup:restore", "admin:group:write", "admin:job:read", "admin:job:write", "admin:log:read", "admin:ticket:delete", "admin:user:write", "admin:userdata:read", "admin:userdata:write", "analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write"}}, - }, - }, - { - name: "CurrentUserData", - args: args{method: "GET", url: "/api/currentuserdata"}, - want: want{ - status: 200, - body: map[string]interface{}{"email": "bob@example.org", "id": "bob", "name": "Bob Bad"}, - }, - }, - { - name: "DeleteAutomation", - args: args{method: "DELETE", url: "/api/automations/hash.sha1"}, - want: want{ - status: 204, - body: nil, - }, - }, - { - name: "DeletePlaybook", - args: args{method: "DELETE", url: "/api/playbooks/simple"}, - want: want{ - status: 204, - body: nil, - }, - }, - { - name: "DeleteTemplate", - args: args{method: "DELETE", url: "/api/templates/default"}, - want: want{ - status: 204, - body: nil, - }, - }, - { - name: "DeleteTicket", - args: args{method: "DELETE", url: "/api/tickets/8125"}, - want: want{ - status: 204, - body: nil, - }, - }, - { - name: "DeleteTicketType", - args: args{method: "DELETE", url: "/api/tickettypes/alert"}, - want: want{ - status: 204, - body: nil, - }, - }, - { - name: "DeleteUser", - args: args{method: "DELETE", url: "/api/users/script"}, - want: want{ - status: 204, - body: nil, - }, - }, - { - name: "EnrichArtifact", - args: args{method: "POST", url: "/api/tickets/8123/artifacts/leadreintermediate.io/enrich", data: map[string]interface{}{"data": map[string]interface{}{"hash": "b7a067a742c20d07a7456646de89bc2d408a1153"}, "name": "hash.sha1"}}, - want: want{ - status: 200, - body: map[string]interface{}{"artifacts": []interface{}{map[string]interface{}{"name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", "status": "unknown"}, map[string]interface{}{"name": "http://www.customerviral.io/scalable/vertical/killer", "status": "clean"}, map[string]interface{}{"enrichments": map[string]interface{}{"hash.sha1": map[string]interface{}{"created": "2021-12-12T12:12:12.000000012Z", "data": map[string]interface{}{"hash": "b7a067a742c20d07a7456646de89bc2d408a1153"}, "name": "hash.sha1"}}, "name": "leadreintermediate.io", "status": "malicious"}}, "created": "2021-10-02T16:04:59.078206Z", "id": 8123, "modified": "2021-10-02T16:04:59.078206Z", "name": "live zebra", "owner": "demo", "playbooks": map[string]interface{}{"phishing": map[string]interface{}{"name": "Phishing", "tasks": map[string]interface{}{"block-iocs": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Block IOCs", "order": 6, "type": "task"}, "block-sender": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Block sender", "next": map[string]interface{}{"extract-iocs": ""}, "order": 3, "type": "task"}, "board": map[string]interface{}{"active": true, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Board Involvement?", "next": map[string]interface{}{"escalate": "boardInvolved == true", "mail-available": "boardInvolved == false"}, "order": 0, "schema": map[string]interface{}{"properties": map[string]interface{}{"boardInvolved": map[string]interface{}{"default": false, "title": "A board member is involved.", "type": "boolean"}}, "required": []interface{}{"boardInvolved"}, "title": "Board Involvement?", "type": "object"}, "type": "input"}, "escalate": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Escalate to CISO", "order": 1, "type": "task"}, "extract-iocs": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Extract IOCs", "next": map[string]interface{}{"block-iocs": ""}, "order": 5, "schema": map[string]interface{}{"properties": map[string]interface{}{"iocs": map[string]interface{}{"items": map[string]interface{}{"type": "string"}, "title": "IOCs", "type": "array"}}, "title": "Extract IOCs", "type": "object"}, "type": "input"}, "mail-available": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Mail available", "next": map[string]interface{}{"block-sender": "schemaKey == 'yes'", "extract-iocs": "schemaKey == 'yes'", "search-email-gateway": "schemaKey == 'no'"}, "order": 2, "schema": map[string]interface{}{"oneOf": []interface{}{map[string]interface{}{"properties": map[string]interface{}{"mail": map[string]interface{}{"title": "Mail", "type": "string", "x-display": "textarea"}, "schemaKey": map[string]interface{}{"const": "yes", "type": "string"}}, "required": []interface{}{"mail"}, "title": "Yes"}, map[string]interface{}{"properties": map[string]interface{}{"schemaKey": map[string]interface{}{"const": "no", "type": "string"}}, "title": "No"}}, "title": "Mail available", "type": "object"}, "type": "input"}, "search-email-gateway": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Search email gateway", "next": map[string]interface{}{"extract-iocs": ""}, "order": 4, "type": "task"}}}}, "references": []interface{}{map[string]interface{}{"href": "https://www.leadmaximize.net/e-services/back-end", "name": "performance"}, map[string]interface{}{"href": "http://www.corporateinteractive.name/rich", "name": "autumn"}, map[string]interface{}{"href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", "name": "suggest"}}, "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", "status": "closed", "type": "incident"}, - }, - }, - { - name: "GetArtifact", - args: args{method: "GET", url: "/api/tickets/8123/artifacts/leadreintermediate.io"}, - want: want{ - status: 200, - body: map[string]interface{}{"name": "leadreintermediate.io", "status": "malicious"}, - }, - }, - { - name: "GetAutomation", - args: args{method: "GET", url: "/api/automations/hash.sha1"}, - want: want{ - status: 200, - body: map[string]interface{}{"id": "hash.sha1", "image": "docker.io/python:3", "schema": "{\"title\":\"Input\",\"type\":\"object\",\"properties\":{\"default\":{\"type\":\"string\",\"title\":\"Value\"}},\"required\":[\"default\"]}", "script": "#!/usr/bin/env python\n\nimport sys\nimport json\nimport hashlib\n\n\ndef run(msg):\n sha1 = hashlib.sha1(msg['payload']['default'].encode('utf-8'))\n return {\"hash\": sha1.hexdigest()}\n\n\nprint(json.dumps(run(json.loads(sys.argv[1]))))\n", "type": []interface{}{"global", "artifact", "playbook"}}, - }, - }, - { - name: "GetJob", - args: args{method: "GET", url: "/api/jobs/99cd67131b48"}, - want: want{ - status: 200, - body: map[string]interface{}{"automation": "hash.sha1", "id": "99cd67131b48", "payload": "test", "status": "created"}, - }, - }, - { - name: "GetLogs", - args: args{method: "GET", url: "/api/logs/tickets%252F294511"}, - want: want{ - status: 200, - body: []interface{}{map[string]interface{}{"created": "2021-12-12T12:12:12.000000012Z", "creator": "bob", "message": "Fail run account resist lend solve incident centre priority temperature. Cause change distribution examine location technique shape partner milk customer. Rail tea plate soil report cook railway interpretation breath action. Exercise dream accept park conclusion addition shoot assistance may answer. Gold writer link stop combine hear power name commitment operation. Determine lifespan support grow degree henry exclude detail set religion. Direct library policy convention chain retain discover ride walk student. Gather proposal select march aspect play noise avoid encourage employ. Assessment preserve transport combine wish influence income guess run stand. Charge limit crime ignore statement foundation study issue stop claim.", "reference": "tickets/294511", "type": "manual"}}, - }, - }, - { - name: "GetPlaybook", - args: args{method: "GET", url: "/api/playbooks/simple"}, - want: want{ - status: 200, - body: map[string]interface{}{"id": "simple", "name": "Simple", "yaml": "name: Simple\ntasks:\n input:\n name: Enter something to hash\n type: input\n schema:\n title: Something\n type: object\n properties:\n something:\n type: string\n title: Something\n default: \"\"\n next:\n hash: \"something != ''\"\n\n hash:\n name: Hash the something\n type: automation\n automation: hash.sha1\n payload:\n default: \"playbook.tasks['input'].data['something']\"\n next:\n comment: \"hash != ''\"\n\n comment:\n name: Comment the hash\n type: automation\n automation: comment\n payload:\n default: \"playbook.tasks['hash'].data['hash']\"\n next:\n done: \"done\"\n\n done:\n name: You can close this case now\n type: task\n"}, - }, - }, - { - name: "GetSettings", - args: args{method: "GET", url: "/api/settings"}, - want: want{ - status: 200, - body: map[string]interface{}{"artifactStates": []interface{}{map[string]interface{}{"color": "info", "icon": "mdi-help-circle-outline", "id": "unknown", "name": "Unknown"}, map[string]interface{}{"color": "error", "icon": "mdi-skull", "id": "malicious", "name": "Malicious"}, map[string]interface{}{"color": "success", "icon": "mdi-check", "id": "clean", "name": "Clean"}}, "roles": []interface{}{"admin:backup:read", "admin:backup:restore", "admin:group:write", "admin:job:read", "admin:job:write", "admin:log:read", "admin:ticket:delete", "admin:user:write", "admin:userdata:read", "admin:userdata:write", "analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write"}, "ticketTypes": []interface{}{map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-alert", "id": "alert", "name": "Alerts"}, map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-radioactive", "id": "incident", "name": "Incidents"}, map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-fingerprint", "id": "investigation", "name": "Forensic Investigations"}, map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-target", "id": "hunt", "name": "Threat Hunting"}}, "tier": "community", "timeformat": "YYYY-MM-DDThh:mm:ss", "version": "0.0.0-test"}, - }, - }, - { - name: "GetStatistics", - args: args{method: "GET", url: "/api/statistics"}, - want: want{ - status: 200, - body: map[string]interface{}{"open_tickets_per_user": map[string]interface{}{}, "tickets_per_type": map[string]interface{}{"alert": 2, "incident": 1}, "tickets_per_week": map[string]interface{}{"2021-39": 3}, "unassigned": 0}, - }, - }, - { - name: "GetTemplate", - args: args{method: "GET", url: "/api/templates/default"}, - want: want{ - status: 200, - body: map[string]interface{}{"id": "default", "name": "Default", "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Default\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n"}, - }, - }, - { - name: "GetTicket", - args: args{method: "GET", url: "/api/tickets/8125"}, - want: want{ - status: 200, - body: map[string]interface{}{"created": "2021-10-02T16:04:59.078186Z", "id": 8125, "modified": "2021-10-02T16:04:59.078186Z", "name": "phishing from selenafadel@von.com detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "https://www.seniorleading-edge.name/users/efficient", "name": "recovery"}, map[string]interface{}{"href": "http://www.dynamicseamless.com/clicks-and-mortar", "name": "force"}, map[string]interface{}{"href": "http://www.leadscalable.biz/envisioneer", "name": "fund"}}, "schema": "{}", "status": "closed", "tickets": []interface{}{map[string]interface{}{"created": "2021-10-02T16:04:59.078186Z", "id": 8126, "modified": "2021-10-02T16:04:59.078186Z", "name": "Surfaceintroduce virus detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "http://www.centralworld-class.io/synthesize", "name": "university"}, map[string]interface{}{"href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", "name": "goal"}, map[string]interface{}{"href": "http://www.chiefsyndicate.io/action-items", "name": "unemployment"}}, "schema": "{}", "status": "closed", "type": "alert"}}, "type": "alert"}, - }, - }, - { - name: "GetTicketType", - args: args{method: "GET", url: "/api/tickettypes/alert"}, - want: want{ - status: 200, - body: map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-alert", "id": "alert", "name": "Alerts"}, - }, - }, - { - name: "GetUser", - args: args{method: "GET", url: "/api/users/script"}, - want: want{ - status: 200, - body: map[string]interface{}{"apikey": true, "blocked": false, "id": "script", "roles": []interface{}{"analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write"}}, - }, - }, - { - name: "GetUserData", - args: args{method: "GET", url: "/api/userdata/bob"}, - want: want{ - status: 200, - body: map[string]interface{}{"email": "bob@example.org", "id": "bob", "name": "Bob Bad"}, - }, - }, - { - name: "LinkFiles", - args: args{method: "PUT", url: "/api/tickets/8125/files", data: []interface{}{map[string]interface{}{"key": "myfile", "name": "document.doc"}}}, - want: want{ - status: 200, - body: map[string]interface{}{"created": "2021-10-02T16:04:59.078186Z", "files": []interface{}{map[string]interface{}{"key": "myfile", "name": "document.doc"}}, "id": 8125, "modified": "2021-12-12T12:12:12.000000012Z", "name": "phishing from selenafadel@von.com detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "https://www.seniorleading-edge.name/users/efficient", "name": "recovery"}, map[string]interface{}{"href": "http://www.dynamicseamless.com/clicks-and-mortar", "name": "force"}, map[string]interface{}{"href": "http://www.leadscalable.biz/envisioneer", "name": "fund"}}, "schema": "{}", "status": "closed", "tickets": []interface{}{map[string]interface{}{"created": "2021-10-02T16:04:59.078186Z", "id": 8126, "modified": "2021-10-02T16:04:59.078186Z", "name": "Surfaceintroduce virus detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "http://www.centralworld-class.io/synthesize", "name": "university"}, map[string]interface{}{"href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", "name": "goal"}, map[string]interface{}{"href": "http://www.chiefsyndicate.io/action-items", "name": "unemployment"}}, "schema": "{}", "status": "closed", "type": "alert"}}, "type": "alert"}, - }, - }, - { - name: "LinkTicket", - args: args{method: "PATCH", url: "/api/tickets/8126/tickets", data: 8123}, - want: want{ - status: 200, - body: map[string]interface{}{"created": "2021-10-02T16:04:59.078186Z", "id": 8126, "modified": "2021-10-02T16:04:59.078186Z", "name": "Surfaceintroduce virus detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "http://www.centralworld-class.io/synthesize", "name": "university"}, map[string]interface{}{"href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", "name": "goal"}, map[string]interface{}{"href": "http://www.chiefsyndicate.io/action-items", "name": "unemployment"}}, "schema": "{}", "status": "closed", "tickets": []interface{}{map[string]interface{}{"artifacts": []interface{}{map[string]interface{}{"name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", "status": "unknown"}, map[string]interface{}{"name": "http://www.customerviral.io/scalable/vertical/killer", "status": "clean"}, map[string]interface{}{"name": "leadreintermediate.io", "status": "malicious"}}, "created": "2021-10-02T16:04:59.078206Z", "id": 8123, "modified": "2021-10-02T16:04:59.078206Z", "name": "live zebra", "owner": "demo", "playbooks": map[string]interface{}{"phishing": map[string]interface{}{"name": "Phishing", "tasks": map[string]interface{}{"block-iocs": map[string]interface{}{"created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Block IOCs", "type": "task"}, "block-sender": map[string]interface{}{"created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Block sender", "next": map[string]interface{}{"extract-iocs": ""}, "type": "task"}, "board": map[string]interface{}{"created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Board Involvement?", "next": map[string]interface{}{"escalate": "boardInvolved == true", "mail-available": "boardInvolved == false"}, "schema": map[string]interface{}{"properties": map[string]interface{}{"boardInvolved": map[string]interface{}{"default": false, "title": "A board member is involved.", "type": "boolean"}}, "required": []interface{}{"boardInvolved"}, "title": "Board Involvement?", "type": "object"}, "type": "input"}, "escalate": map[string]interface{}{"created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Escalate to CISO", "type": "task"}, "extract-iocs": map[string]interface{}{"created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Extract IOCs", "next": map[string]interface{}{"block-iocs": ""}, "schema": map[string]interface{}{"properties": map[string]interface{}{"iocs": map[string]interface{}{"items": map[string]interface{}{"type": "string"}, "title": "IOCs", "type": "array"}}, "title": "Extract IOCs", "type": "object"}, "type": "input"}, "mail-available": map[string]interface{}{"created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Mail available", "next": map[string]interface{}{"block-sender": "schemaKey == 'yes'", "extract-iocs": "schemaKey == 'yes'", "search-email-gateway": "schemaKey == 'no'"}, "schema": map[string]interface{}{"oneOf": []interface{}{map[string]interface{}{"properties": map[string]interface{}{"mail": map[string]interface{}{"title": "Mail", "type": "string", "x-display": "textarea"}, "schemaKey": map[string]interface{}{"const": "yes", "type": "string"}}, "required": []interface{}{"mail"}, "title": "Yes"}, map[string]interface{}{"properties": map[string]interface{}{"schemaKey": map[string]interface{}{"const": "no", "type": "string"}}, "title": "No"}}, "title": "Mail available", "type": "object"}, "type": "input"}, "search-email-gateway": map[string]interface{}{"created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Search email gateway", "next": map[string]interface{}{"extract-iocs": ""}, "type": "task"}}}}, "references": []interface{}{map[string]interface{}{"href": "https://www.leadmaximize.net/e-services/back-end", "name": "performance"}, map[string]interface{}{"href": "http://www.corporateinteractive.name/rich", "name": "autumn"}, map[string]interface{}{"href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", "name": "suggest"}}, "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", "status": "closed", "type": "incident"}, map[string]interface{}{"created": "2021-10-02T16:04:59.078186Z", "id": 8125, "modified": "2021-10-02T16:04:59.078186Z", "name": "phishing from selenafadel@von.com detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "https://www.seniorleading-edge.name/users/efficient", "name": "recovery"}, map[string]interface{}{"href": "http://www.dynamicseamless.com/clicks-and-mortar", "name": "force"}, map[string]interface{}{"href": "http://www.leadscalable.biz/envisioneer", "name": "fund"}}, "schema": "{}", "status": "closed", "type": "alert"}}, "type": "alert"}, - }, - }, - { - name: "ListAutomations", - args: args{method: "GET", url: "/api/automations"}, - want: want{ - status: 200, - body: []interface{}{map[string]interface{}{"id": "comment", "image": "docker.io/python:3", "script": "", "type": []interface{}{"playbook"}}, map[string]interface{}{"id": "hash.sha1", "image": "docker.io/python:3", "schema": "{\"title\":\"Input\",\"type\":\"object\",\"properties\":{\"default\":{\"type\":\"string\",\"title\":\"Value\"}},\"required\":[\"default\"]}", "script": "", "type": []interface{}{"global", "artifact", "playbook"}}, map[string]interface{}{"id": "thehive", "image": "docker.io/python:3", "schema": "{\"title\":\"TheHive credentials\",\"type\":\"object\",\"properties\":{\"thehiveurl\":{\"type\":\"string\",\"title\":\"TheHive URL (e.g. 'https://thehive.example.org')\"},\"thehivekey\":{\"type\":\"string\",\"title\":\"TheHive API Key\"},\"skip_files\":{\"type\":\"boolean\", \"default\": true, \"title\":\"Skip Files (much faster)\"},\"keep_ids\":{\"type\":\"boolean\", \"default\": true, \"title\":\"Keep IDs and overwrite existing IDs\"}},\"required\":[\"thehiveurl\", \"thehivekey\", \"skip_files\", \"keep_ids\"]}", "script": "", "type": []interface{}{"global"}}, map[string]interface{}{"id": "vt.hash", "image": "docker.io/python:3", "schema": "{\"title\":\"Input\",\"type\":\"object\",\"properties\":{\"default\":{\"type\":\"string\",\"title\":\"Value\"}},\"required\":[\"default\"]}", "script": "", "type": []interface{}{"global", "artifact", "playbook"}}}, - }, - }, - { - name: "ListJobs", - args: args{method: "GET", url: "/api/jobs"}, - want: want{ - status: 200, - body: []interface{}{map[string]interface{}{"automation": "hash.sha1", "id": "99cd67131b48", "payload": "test", "status": "created"}}, - }, - }, - { - name: "ListPlaybooks", - args: args{method: "GET", url: "/api/playbooks"}, - want: want{ - status: 200, - body: []interface{}{map[string]interface{}{"id": "malware", "name": "Malware", "yaml": "name: Malware\ntasks:\n file-or-hash:\n name: Do you have the file or the hash?\n type: input\n schema:\n title: Malware\n type: object\n properties:\n file:\n type: string\n title: \"I have the\"\n enum: [ \"File\", \"Hash\" ]\n next:\n enter-hash: \"file == 'Hash'\"\n upload: \"file == 'File'\"\n\n enter-hash:\n name: Please enter the hash\n type: input\n schema:\n title: Malware\n type: object\n properties:\n hash:\n type: string\n title: Please enter the hash value\n minlength: 32\n next:\n virustotal: \"hash != ''\"\n\n upload:\n name: Upload the malware\n type: input\n schema:\n title: Malware\n type: object\n properties:\n malware:\n type: object\n x-display: file\n title: Please upload the malware\n next:\n hash: \"malware\"\n\n hash:\n name: Hash the malware\n type: automation\n automation: hash.sha1\n payload:\n default: \"playbook.tasks['upload'].data['malware']\"\n next:\n virustotal:\n\n virustotal:\n name: Send hash to VirusTotal\n type: automation\n automation: vt.hash\n args:\n hash: \"playbook.tasks['enter-hash'].data['hash'] || playbook.tasks['hash'].data['hash']\"\n # next:\n # known-malware: \"score > 5\"\n # sandbox: \"score < 6\" # unknown-malware\n"}, map[string]interface{}{"id": "phishing", "name": "Phishing", "yaml": "name: Phishing\ntasks:\n board:\n name: Board Involvement?\n description: Is a board member involved?\n type: input\n schema:\n properties:\n boardInvolved:\n default: false\n title: A board member is involved.\n type: boolean\n required:\n - boardInvolved\n title: Board Involvement?\n type: object\n next:\n escalate: \"boardInvolved == true\"\n mail-available: \"boardInvolved == false\"\n\n escalate:\n name: Escalate to CISO\n description: Please escalate the task to the CISO\n type: task\n\n mail-available:\n name: Mail available\n type: input\n schema:\n oneOf:\n - properties:\n mail:\n title: Mail\n type: string\n x-display: textarea\n schemaKey:\n const: 'yes'\n type: string\n required:\n - mail\n title: 'Yes'\n - properties:\n schemaKey:\n const: 'no'\n type: string\n title: 'No'\n title: Mail available\n type: object\n next:\n block-sender: \"schemaKey == 'yes'\"\n extract-iocs: \"schemaKey == 'yes'\"\n search-email-gateway: \"schemaKey == 'no'\"\n\n search-email-gateway:\n name: Search email gateway\n description: Please search email-gateway for the phishing mail.\n type: task\n next:\n extract-iocs:\n\n block-sender:\n name: Block sender\n type: task\n next:\n extract-iocs:\n\n extract-iocs:\n name: Extract IOCs\n description: Please insert the IOCs\n type: input\n schema:\n properties:\n iocs:\n items:\n type: string\n title: IOCs\n type: array\n title: Extract IOCs\n type: object\n next:\n block-iocs:\n\n block-iocs:\n name: Block IOCs\n type: task\n"}, map[string]interface{}{"id": "simple", "name": "Simple", "yaml": "name: Simple\ntasks:\n input:\n name: Enter something to hash\n type: input\n schema:\n title: Something\n type: object\n properties:\n something:\n type: string\n title: Something\n default: \"\"\n next:\n hash: \"something != ''\"\n\n hash:\n name: Hash the something\n type: automation\n automation: hash.sha1\n payload:\n default: \"playbook.tasks['input'].data['something']\"\n next:\n comment: \"hash != ''\"\n\n comment:\n name: Comment the hash\n type: automation\n automation: comment\n payload:\n default: \"playbook.tasks['hash'].data['hash']\"\n next:\n done: \"done\"\n\n done:\n name: You can close this case now\n type: task\n"}}, - }, - }, - { - name: "ListTasks", - args: args{method: "GET", url: "/api/tasks"}, - want: want{ - status: 200, - body: []interface{}{}, - }, - }, - { - name: "ListTemplates", - args: args{method: "GET", url: "/api/templates"}, - want: want{ - status: 200, - body: []interface{}{map[string]interface{}{"id": "default", "name": "Default", "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Default\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n"}}, - }, - }, - { - name: "ListTicketTypes", - args: args{method: "GET", url: "/api/tickettypes"}, - want: want{ - status: 200, - body: []interface{}{map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-alert", "id": "alert", "name": "Alerts"}, map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-radioactive", "id": "incident", "name": "Incidents"}, map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-fingerprint", "id": "investigation", "name": "Forensic Investigations"}, map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-target", "id": "hunt", "name": "Threat Hunting"}}, - }, - }, - { - name: "ListTickets", - args: args{method: "GET", url: "/api/tickets"}, - want: want{ - status: 200, - body: map[string]interface{}{"count": 3, "tickets": []interface{}{map[string]interface{}{"artifacts": []interface{}{map[string]interface{}{"name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", "status": "unknown"}, map[string]interface{}{"name": "http://www.customerviral.io/scalable/vertical/killer", "status": "clean"}, map[string]interface{}{"name": "leadreintermediate.io", "status": "malicious"}}, "created": "2021-10-02T16:04:59.078206Z", "id": 8123, "modified": "2021-10-02T16:04:59.078206Z", "name": "live zebra", "owner": "demo", "playbooks": map[string]interface{}{"phishing": map[string]interface{}{"name": "Phishing", "tasks": map[string]interface{}{"block-iocs": map[string]interface{}{"created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Block IOCs", "type": "task"}, "block-sender": map[string]interface{}{"created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Block sender", "next": map[string]interface{}{"extract-iocs": ""}, "type": "task"}, "board": map[string]interface{}{"created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Board Involvement?", "next": map[string]interface{}{"escalate": "boardInvolved == true", "mail-available": "boardInvolved == false"}, "schema": map[string]interface{}{"properties": map[string]interface{}{"boardInvolved": map[string]interface{}{"default": false, "title": "A board member is involved.", "type": "boolean"}}, "required": []interface{}{"boardInvolved"}, "title": "Board Involvement?", "type": "object"}, "type": "input"}, "escalate": map[string]interface{}{"created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Escalate to CISO", "type": "task"}, "extract-iocs": map[string]interface{}{"created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Extract IOCs", "next": map[string]interface{}{"block-iocs": ""}, "schema": map[string]interface{}{"properties": map[string]interface{}{"iocs": map[string]interface{}{"items": map[string]interface{}{"type": "string"}, "title": "IOCs", "type": "array"}}, "title": "Extract IOCs", "type": "object"}, "type": "input"}, "mail-available": map[string]interface{}{"created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Mail available", "next": map[string]interface{}{"block-sender": "schemaKey == 'yes'", "extract-iocs": "schemaKey == 'yes'", "search-email-gateway": "schemaKey == 'no'"}, "schema": map[string]interface{}{"oneOf": []interface{}{map[string]interface{}{"properties": map[string]interface{}{"mail": map[string]interface{}{"title": "Mail", "type": "string", "x-display": "textarea"}, "schemaKey": map[string]interface{}{"const": "yes", "type": "string"}}, "required": []interface{}{"mail"}, "title": "Yes"}, map[string]interface{}{"properties": map[string]interface{}{"schemaKey": map[string]interface{}{"const": "no", "type": "string"}}, "title": "No"}}, "title": "Mail available", "type": "object"}, "type": "input"}, "search-email-gateway": map[string]interface{}{"created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Search email gateway", "next": map[string]interface{}{"extract-iocs": ""}, "type": "task"}}}}, "references": []interface{}{map[string]interface{}{"href": "https://www.leadmaximize.net/e-services/back-end", "name": "performance"}, map[string]interface{}{"href": "http://www.corporateinteractive.name/rich", "name": "autumn"}, map[string]interface{}{"href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", "name": "suggest"}}, "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", "status": "closed", "type": "incident"}, map[string]interface{}{"created": "2021-10-02T16:04:59.078186Z", "id": 8125, "modified": "2021-10-02T16:04:59.078186Z", "name": "phishing from selenafadel@von.com detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "https://www.seniorleading-edge.name/users/efficient", "name": "recovery"}, map[string]interface{}{"href": "http://www.dynamicseamless.com/clicks-and-mortar", "name": "force"}, map[string]interface{}{"href": "http://www.leadscalable.biz/envisioneer", "name": "fund"}}, "schema": "{}", "status": "closed", "type": "alert"}, map[string]interface{}{"created": "2021-10-02T16:04:59.078186Z", "id": 8126, "modified": "2021-10-02T16:04:59.078186Z", "name": "Surfaceintroduce virus detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "http://www.centralworld-class.io/synthesize", "name": "university"}, map[string]interface{}{"href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", "name": "goal"}, map[string]interface{}{"href": "http://www.chiefsyndicate.io/action-items", "name": "unemployment"}}, "schema": "{}", "status": "closed", "type": "alert"}}}, - }, - }, - { - name: "ListUserData", - args: args{method: "GET", url: "/api/userdata"}, - want: want{ - status: 200, - body: []interface{}{map[string]interface{}{"email": "bob@example.org", "id": "bob", "name": "Bob Bad"}}, - }, - }, - { - name: "ListUsers", - args: args{method: "GET", url: "/api/users"}, - want: want{ - status: 200, - body: []interface{}{map[string]interface{}{"apikey": false, "blocked": false, "id": "bob", "roles": []interface{}{"admin:backup:read", "admin:backup:restore", "admin:group:write", "admin:job:read", "admin:job:write", "admin:log:read", "admin:ticket:delete", "admin:user:write", "admin:userdata:read", "admin:userdata:write", "analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write"}}, map[string]interface{}{"apikey": true, "blocked": false, "id": "script", "roles": []interface{}{"analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write"}}}, - }, - }, - { - name: "RemoveArtifact", - args: args{method: "DELETE", url: "/api/tickets/8123/artifacts/leadreintermediate.io"}, - want: want{ - status: 200, - body: map[string]interface{}{"artifacts": []interface{}{map[string]interface{}{"name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", "status": "unknown"}, map[string]interface{}{"name": "http://www.customerviral.io/scalable/vertical/killer", "status": "clean"}}, "created": "2021-10-02T16:04:59.078206Z", "id": 8123, "modified": "2021-12-12T12:12:12.000000012Z", "name": "live zebra", "owner": "demo", "playbooks": map[string]interface{}{"phishing": map[string]interface{}{"name": "Phishing", "tasks": map[string]interface{}{"block-iocs": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Block IOCs", "order": 6, "type": "task"}, "block-sender": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Block sender", "next": map[string]interface{}{"extract-iocs": ""}, "order": 3, "type": "task"}, "board": map[string]interface{}{"active": true, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Board Involvement?", "next": map[string]interface{}{"escalate": "boardInvolved == true", "mail-available": "boardInvolved == false"}, "order": 0, "schema": map[string]interface{}{"properties": map[string]interface{}{"boardInvolved": map[string]interface{}{"default": false, "title": "A board member is involved.", "type": "boolean"}}, "required": []interface{}{"boardInvolved"}, "title": "Board Involvement?", "type": "object"}, "type": "input"}, "escalate": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Escalate to CISO", "order": 1, "type": "task"}, "extract-iocs": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Extract IOCs", "next": map[string]interface{}{"block-iocs": ""}, "order": 5, "schema": map[string]interface{}{"properties": map[string]interface{}{"iocs": map[string]interface{}{"items": map[string]interface{}{"type": "string"}, "title": "IOCs", "type": "array"}}, "title": "Extract IOCs", "type": "object"}, "type": "input"}, "mail-available": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Mail available", "next": map[string]interface{}{"block-sender": "schemaKey == 'yes'", "extract-iocs": "schemaKey == 'yes'", "search-email-gateway": "schemaKey == 'no'"}, "order": 2, "schema": map[string]interface{}{"oneOf": []interface{}{map[string]interface{}{"properties": map[string]interface{}{"mail": map[string]interface{}{"title": "Mail", "type": "string", "x-display": "textarea"}, "schemaKey": map[string]interface{}{"const": "yes", "type": "string"}}, "required": []interface{}{"mail"}, "title": "Yes"}, map[string]interface{}{"properties": map[string]interface{}{"schemaKey": map[string]interface{}{"const": "no", "type": "string"}}, "title": "No"}}, "title": "Mail available", "type": "object"}, "type": "input"}, "search-email-gateway": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Search email gateway", "next": map[string]interface{}{"extract-iocs": ""}, "order": 4, "type": "task"}}}}, "references": []interface{}{map[string]interface{}{"href": "https://www.leadmaximize.net/e-services/back-end", "name": "performance"}, map[string]interface{}{"href": "http://www.corporateinteractive.name/rich", "name": "autumn"}, map[string]interface{}{"href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", "name": "suggest"}}, "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", "status": "closed", "type": "incident"}, - }, - }, - { - name: "RemoveComment", - args: args{method: "DELETE", url: "/api/tickets/8123/comments/0"}, - want: want{ - status: 200, - body: map[string]interface{}{"artifacts": []interface{}{map[string]interface{}{"name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", "status": "unknown"}, map[string]interface{}{"name": "http://www.customerviral.io/scalable/vertical/killer", "status": "clean"}, map[string]interface{}{"name": "leadreintermediate.io", "status": "malicious"}}, "created": "2021-10-02T16:04:59.078206Z", "id": 8123, "modified": "2021-12-12T12:12:12.000000012Z", "name": "live zebra", "owner": "demo", "playbooks": map[string]interface{}{"phishing": map[string]interface{}{"name": "Phishing", "tasks": map[string]interface{}{"block-iocs": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Block IOCs", "order": 6, "type": "task"}, "block-sender": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Block sender", "next": map[string]interface{}{"extract-iocs": ""}, "order": 3, "type": "task"}, "board": map[string]interface{}{"active": true, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Board Involvement?", "next": map[string]interface{}{"escalate": "boardInvolved == true", "mail-available": "boardInvolved == false"}, "order": 0, "schema": map[string]interface{}{"properties": map[string]interface{}{"boardInvolved": map[string]interface{}{"default": false, "title": "A board member is involved.", "type": "boolean"}}, "required": []interface{}{"boardInvolved"}, "title": "Board Involvement?", "type": "object"}, "type": "input"}, "escalate": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Escalate to CISO", "order": 1, "type": "task"}, "extract-iocs": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Extract IOCs", "next": map[string]interface{}{"block-iocs": ""}, "order": 5, "schema": map[string]interface{}{"properties": map[string]interface{}{"iocs": map[string]interface{}{"items": map[string]interface{}{"type": "string"}, "title": "IOCs", "type": "array"}}, "title": "Extract IOCs", "type": "object"}, "type": "input"}, "mail-available": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Mail available", "next": map[string]interface{}{"block-sender": "schemaKey == 'yes'", "extract-iocs": "schemaKey == 'yes'", "search-email-gateway": "schemaKey == 'no'"}, "order": 2, "schema": map[string]interface{}{"oneOf": []interface{}{map[string]interface{}{"properties": map[string]interface{}{"mail": map[string]interface{}{"title": "Mail", "type": "string", "x-display": "textarea"}, "schemaKey": map[string]interface{}{"const": "yes", "type": "string"}}, "required": []interface{}{"mail"}, "title": "Yes"}, map[string]interface{}{"properties": map[string]interface{}{"schemaKey": map[string]interface{}{"const": "no", "type": "string"}}, "title": "No"}}, "title": "Mail available", "type": "object"}, "type": "input"}, "search-email-gateway": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Search email gateway", "next": map[string]interface{}{"extract-iocs": ""}, "order": 4, "type": "task"}}}}, "references": []interface{}{map[string]interface{}{"href": "https://www.leadmaximize.net/e-services/back-end", "name": "performance"}, map[string]interface{}{"href": "http://www.corporateinteractive.name/rich", "name": "autumn"}, map[string]interface{}{"href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", "name": "suggest"}}, "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", "status": "closed", "type": "incident"}, - }, - }, - { - name: "RemoveTicketPlaybook", - args: args{method: "DELETE", url: "/api/tickets/8123/playbooks/phishing"}, - want: want{ - status: 200, - body: map[string]interface{}{"artifacts": []interface{}{map[string]interface{}{"name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", "status": "unknown"}, map[string]interface{}{"name": "http://www.customerviral.io/scalable/vertical/killer", "status": "clean"}, map[string]interface{}{"name": "leadreintermediate.io", "status": "malicious"}}, "created": "2021-10-02T16:04:59.078206Z", "id": 8123, "modified": "2021-12-12T12:12:12.000000012Z", "name": "live zebra", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "https://www.leadmaximize.net/e-services/back-end", "name": "performance"}, map[string]interface{}{"href": "http://www.corporateinteractive.name/rich", "name": "autumn"}, map[string]interface{}{"href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", "name": "suggest"}}, "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", "status": "closed", "type": "incident"}, - }, - }, - { - name: "RunArtifact", - args: args{method: "POST", url: "/api/tickets/8123/artifacts/leadreintermediate.io/run/hash.sha1"}, - want: want{ - status: 204, - body: nil, - }, - }, - { - name: "RunJob", - args: args{method: "POST", url: "/api/jobs", data: map[string]interface{}{"automation": "hash.sha1", "message": map[string]interface{}{"payload": "test"}}}, - want: want{ - status: 204, - body: nil, - }, - }, - { - name: "RunTask", - args: args{method: "POST", url: "/api/tickets/8123/playbooks/phishing/task/board/run"}, - want: want{ - status: 204, - body: nil, - }, - }, - { - name: "SetArtifact", - args: args{method: "PUT", url: "/api/tickets/8123/artifacts/leadreintermediate.io", data: map[string]interface{}{"name": "leadreintermediate.io", "status": "clean"}}, - want: want{ - status: 200, - body: map[string]interface{}{"artifacts": []interface{}{map[string]interface{}{"name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", "status": "unknown"}, map[string]interface{}{"name": "http://www.customerviral.io/scalable/vertical/killer", "status": "clean"}, map[string]interface{}{"name": "leadreintermediate.io", "status": "clean"}}, "created": "2021-10-02T16:04:59.078206Z", "id": 8123, "modified": "2021-10-02T16:04:59.078206Z", "name": "live zebra", "owner": "demo", "playbooks": map[string]interface{}{"phishing": map[string]interface{}{"name": "Phishing", "tasks": map[string]interface{}{"block-iocs": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Block IOCs", "order": 6, "type": "task"}, "block-sender": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Block sender", "next": map[string]interface{}{"extract-iocs": ""}, "order": 3, "type": "task"}, "board": map[string]interface{}{"active": true, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Board Involvement?", "next": map[string]interface{}{"escalate": "boardInvolved == true", "mail-available": "boardInvolved == false"}, "order": 0, "schema": map[string]interface{}{"properties": map[string]interface{}{"boardInvolved": map[string]interface{}{"default": false, "title": "A board member is involved.", "type": "boolean"}}, "required": []interface{}{"boardInvolved"}, "title": "Board Involvement?", "type": "object"}, "type": "input"}, "escalate": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Escalate to CISO", "order": 1, "type": "task"}, "extract-iocs": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Extract IOCs", "next": map[string]interface{}{"block-iocs": ""}, "order": 5, "schema": map[string]interface{}{"properties": map[string]interface{}{"iocs": map[string]interface{}{"items": map[string]interface{}{"type": "string"}, "title": "IOCs", "type": "array"}}, "title": "Extract IOCs", "type": "object"}, "type": "input"}, "mail-available": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Mail available", "next": map[string]interface{}{"block-sender": "schemaKey == 'yes'", "extract-iocs": "schemaKey == 'yes'", "search-email-gateway": "schemaKey == 'no'"}, "order": 2, "schema": map[string]interface{}{"oneOf": []interface{}{map[string]interface{}{"properties": map[string]interface{}{"mail": map[string]interface{}{"title": "Mail", "type": "string", "x-display": "textarea"}, "schemaKey": map[string]interface{}{"const": "yes", "type": "string"}}, "required": []interface{}{"mail"}, "title": "Yes"}, map[string]interface{}{"properties": map[string]interface{}{"schemaKey": map[string]interface{}{"const": "no", "type": "string"}}, "title": "No"}}, "title": "Mail available", "type": "object"}, "type": "input"}, "search-email-gateway": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Search email gateway", "next": map[string]interface{}{"extract-iocs": ""}, "order": 4, "type": "task"}}}}, "references": []interface{}{map[string]interface{}{"href": "https://www.leadmaximize.net/e-services/back-end", "name": "performance"}, map[string]interface{}{"href": "http://www.corporateinteractive.name/rich", "name": "autumn"}, map[string]interface{}{"href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", "name": "suggest"}}, "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", "status": "closed", "type": "incident"}, - }, - }, - { - name: "SetReferences", - args: args{method: "PUT", url: "/api/tickets/8125/references", data: []interface{}{map[string]interface{}{"href": "http://www.leadscalable.biz/envisioneer", "name": "fund"}}}, - want: want{ - status: 200, - body: map[string]interface{}{"created": "2021-10-02T16:04:59.078186Z", "id": 8125, "modified": "2021-12-12T12:12:12.000000012Z", "name": "phishing from selenafadel@von.com detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "http://www.leadscalable.biz/envisioneer", "name": "fund"}}, "schema": "{}", "status": "closed", "tickets": []interface{}{map[string]interface{}{"created": "2021-10-02T16:04:59.078186Z", "id": 8126, "modified": "2021-10-02T16:04:59.078186Z", "name": "Surfaceintroduce virus detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "http://www.centralworld-class.io/synthesize", "name": "university"}, map[string]interface{}{"href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", "name": "goal"}, map[string]interface{}{"href": "http://www.chiefsyndicate.io/action-items", "name": "unemployment"}}, "schema": "{}", "status": "closed", "type": "alert"}}, "type": "alert"}, - }, - }, - { - name: "SetSchema", - args: args{method: "PUT", url: "/api/tickets/8125/schema", data: "{}"}, - want: want{ - status: 200, - body: map[string]interface{}{"created": "2021-10-02T16:04:59.078186Z", "id": 8125, "modified": "2021-10-02T16:04:59.078186Z", "name": "phishing from selenafadel@von.com detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "https://www.seniorleading-edge.name/users/efficient", "name": "recovery"}, map[string]interface{}{"href": "http://www.dynamicseamless.com/clicks-and-mortar", "name": "force"}, map[string]interface{}{"href": "http://www.leadscalable.biz/envisioneer", "name": "fund"}}, "schema": "{}", "status": "closed", "tickets": []interface{}{map[string]interface{}{"created": "2021-10-02T16:04:59.078186Z", "id": 8126, "modified": "2021-10-02T16:04:59.078186Z", "name": "Surfaceintroduce virus detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "http://www.centralworld-class.io/synthesize", "name": "university"}, map[string]interface{}{"href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", "name": "goal"}, map[string]interface{}{"href": "http://www.chiefsyndicate.io/action-items", "name": "unemployment"}}, "schema": "{}", "status": "closed", "type": "alert"}}, "type": "alert"}, - }, - }, - { - name: "SetTask", - args: args{method: "PUT", url: "/api/tickets/8123/playbooks/phishing/task/board", data: map[string]interface{}{"active": true, "data": map[string]interface{}{"boardInvolved": true}, "done": false, "name": "Board Involvement?", "next": map[string]interface{}{"escalate": "boardInvolved == true", "mail-available": "boardInvolved == false"}, "order": 0, "schema": map[string]interface{}{"properties": map[string]interface{}{"boardInvolved": map[string]interface{}{"default": false, "title": "A board member is involved.", "type": "boolean"}}, "required": []interface{}{"boardInvolved"}, "title": "Board Involvement?", "type": "object"}, "type": "input"}}, - want: want{ - status: 200, - body: map[string]interface{}{"artifacts": []interface{}{map[string]interface{}{"name": "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", "status": "unknown"}, map[string]interface{}{"name": "http://www.customerviral.io/scalable/vertical/killer", "status": "clean"}, map[string]interface{}{"name": "leadreintermediate.io", "status": "malicious"}}, "created": "2021-10-02T16:04:59.078206Z", "id": 8123, "modified": "2021-12-12T12:12:12.000000012Z", "name": "live zebra", "owner": "demo", "playbooks": map[string]interface{}{"phishing": map[string]interface{}{"name": "Phishing", "tasks": map[string]interface{}{"block-iocs": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Block IOCs", "order": 6, "type": "task"}, "block-sender": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Block sender", "next": map[string]interface{}{"extract-iocs": ""}, "order": 3, "type": "task"}, "board": map[string]interface{}{"active": true, "created": "2021-12-12T12:12:12.000000012Z", "data": map[string]interface{}{"boardInvolved": true}, "done": false, "name": "Board Involvement?", "next": map[string]interface{}{"escalate": "boardInvolved == true", "mail-available": "boardInvolved == false"}, "order": 0, "schema": map[string]interface{}{"properties": map[string]interface{}{"boardInvolved": map[string]interface{}{"default": false, "title": "A board member is involved.", "type": "boolean"}}, "required": []interface{}{"boardInvolved"}, "title": "Board Involvement?", "type": "object"}, "type": "input"}, "escalate": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Escalate to CISO", "order": 1, "type": "task"}, "extract-iocs": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Extract IOCs", "next": map[string]interface{}{"block-iocs": ""}, "order": 5, "schema": map[string]interface{}{"properties": map[string]interface{}{"iocs": map[string]interface{}{"items": map[string]interface{}{"type": "string"}, "title": "IOCs", "type": "array"}}, "title": "Extract IOCs", "type": "object"}, "type": "input"}, "mail-available": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Mail available", "next": map[string]interface{}{"block-sender": "schemaKey == 'yes'", "extract-iocs": "schemaKey == 'yes'", "search-email-gateway": "schemaKey == 'no'"}, "order": 2, "schema": map[string]interface{}{"oneOf": []interface{}{map[string]interface{}{"properties": map[string]interface{}{"mail": map[string]interface{}{"title": "Mail", "type": "string", "x-display": "textarea"}, "schemaKey": map[string]interface{}{"const": "yes", "type": "string"}}, "required": []interface{}{"mail"}, "title": "Yes"}, map[string]interface{}{"properties": map[string]interface{}{"schemaKey": map[string]interface{}{"const": "no", "type": "string"}}, "title": "No"}}, "title": "Mail available", "type": "object"}, "type": "input"}, "search-email-gateway": map[string]interface{}{"active": false, "created": "2021-12-12T12:12:12.000000012Z", "done": false, "name": "Search email gateway", "next": map[string]interface{}{"extract-iocs": ""}, "order": 4, "type": "task"}}}}, "references": []interface{}{map[string]interface{}{"href": "https://www.leadmaximize.net/e-services/back-end", "name": "performance"}, map[string]interface{}{"href": "http://www.corporateinteractive.name/rich", "name": "autumn"}, map[string]interface{}{"href": "https://www.corporateintuitive.org/intuitive/platforms/integrate", "name": "suggest"}}, "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n", "status": "closed", "type": "incident"}, - }, - }, - { - name: "UnlinkTicket", - args: args{method: "DELETE", url: "/api/tickets/8126/tickets", data: 8125}, - want: want{ - status: 200, - body: map[string]interface{}{"created": "2021-10-02T16:04:59.078186Z", "id": 8126, "modified": "2021-10-02T16:04:59.078186Z", "name": "Surfaceintroduce virus detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "http://www.centralworld-class.io/synthesize", "name": "university"}, map[string]interface{}{"href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", "name": "goal"}, map[string]interface{}{"href": "http://www.chiefsyndicate.io/action-items", "name": "unemployment"}}, "schema": "{}", "status": "closed", "type": "alert"}, - }, - }, - { - name: "UpdateAutomation", - args: args{method: "PUT", url: "/api/automations/hash.sha1", data: map[string]interface{}{"id": "hash.sha1", "image": "docker.io/python:3", "script": "import sys\nimport json\nimport hashlib\n\n\ndef run(msg):\n sha1 = hashlib.sha1(msg['payload'].encode('utf-8'))\n return {'hash': sha1.hexdigest()}\n\n\nprint(json.dumps(run(json.loads(sys.argv[1]))))\n", "type": []interface{}{"global", "artifact", "playbook"}}}, - want: want{ - status: 200, - body: map[string]interface{}{"id": "hash.sha1", "image": "docker.io/python:3", "script": "import sys\nimport json\nimport hashlib\n\n\ndef run(msg):\n sha1 = hashlib.sha1(msg['payload'].encode('utf-8'))\n return {'hash': sha1.hexdigest()}\n\n\nprint(json.dumps(run(json.loads(sys.argv[1]))))\n", "type": []interface{}{"global", "artifact", "playbook"}}, - }, - }, - { - name: "UpdateCurrentUserData", - args: args{method: "PUT", url: "/api/currentuserdata", data: map[string]interface{}{"email": "bob@example.org", "name": "Bob Bad"}}, - want: want{ - status: 200, - body: map[string]interface{}{"email": "bob@example.org", "id": "bob", "name": "Bob Bad"}, - }, - }, - { - name: "UpdateJob", - args: args{method: "PUT", url: "/api/jobs/99cd67131b48", data: map[string]interface{}{"automation": "hash.sha1", "id": "99cd67131b48", "payload": "test", "status": "failed"}}, - want: want{ - status: 200, - body: map[string]interface{}{"automation": "hash.sha1", "id": "99cd67131b48", "payload": "test", "status": "failed"}, - }, - }, - { - name: "UpdatePlaybook", - args: args{method: "PUT", url: "/api/playbooks/simple", data: map[string]interface{}{"yaml": "name: Simple\ntasks:\n input:\n name: Upload malware if possible\n type: input\n schema:\n title: Malware\n type: object\n properties:\n malware:\n type: string\n title: Select malware\n default: \"\"\n next:\n hash: \"malware != ''\"\n\n hash:\n name: Hash the malware\n type: automation\n automation: hash.sha1\n payload:\n default: \"playbook.tasks['input'].data['malware']\"\n next:\n escalate:\n\n escalate:\n name: Escalate to malware team\n type: task\n"}}, - want: want{ - status: 200, - body: map[string]interface{}{"id": "simple", "name": "Simple", "yaml": "name: Simple\ntasks:\n input:\n name: Upload malware if possible\n type: input\n schema:\n title: Malware\n type: object\n properties:\n malware:\n type: string\n title: Select malware\n default: \"\"\n next:\n hash: \"malware != ''\"\n\n hash:\n name: Hash the malware\n type: automation\n automation: hash.sha1\n payload:\n default: \"playbook.tasks['input'].data['malware']\"\n next:\n escalate:\n\n escalate:\n name: Escalate to malware team\n type: task\n"}, - }, - }, - { - name: "UpdateTemplate", - args: args{method: "PUT", url: "/api/templates/default", data: map[string]interface{}{"name": "My Template", "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n"}}, - want: want{ - status: 200, - body: map[string]interface{}{"id": "default", "name": "My Template", "schema": "{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n"}, - }, - }, - { - name: "UpdateTicket", - args: args{method: "PUT", url: "/api/tickets/8125", data: map[string]interface{}{"created": "2021-12-12T12:12:12.000000012Z", "modified": "2021-12-12T12:12:12.000000012Z", "name": "phishing from selenafadel@von.org detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "https://www.seniorleading-edge.name/users/efficient", "name": "recovery"}, map[string]interface{}{"href": "http://www.dynamicseamless.com/clicks-and-mortar", "name": "force"}, map[string]interface{}{"href": "http://www.leadscalable.biz/envisioneer", "name": "fund"}}, "schema": "{}", "status": "closed", "type": "alert"}}, - want: want{ - status: 200, - body: map[string]interface{}{"created": "2021-12-12T12:12:12.000000012Z", "id": 8125, "modified": "2021-12-12T12:12:12.000000012Z", "name": "phishing from selenafadel@von.org detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "https://www.seniorleading-edge.name/users/efficient", "name": "recovery"}, map[string]interface{}{"href": "http://www.dynamicseamless.com/clicks-and-mortar", "name": "force"}, map[string]interface{}{"href": "http://www.leadscalable.biz/envisioneer", "name": "fund"}}, "schema": "{}", "status": "closed", "tickets": []interface{}{map[string]interface{}{"created": "2021-10-02T16:04:59.078186Z", "id": 8126, "modified": "2021-10-02T16:04:59.078186Z", "name": "Surfaceintroduce virus detected", "owner": "demo", "references": []interface{}{map[string]interface{}{"href": "http://www.centralworld-class.io/synthesize", "name": "university"}, map[string]interface{}{"href": "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", "name": "goal"}, map[string]interface{}{"href": "http://www.chiefsyndicate.io/action-items", "name": "unemployment"}}, "schema": "{}", "status": "closed", "type": "alert"}}, "type": "alert"}, - }, - }, - { - name: "UpdateTicketType", - args: args{method: "PUT", url: "/api/tickettypes/alert", data: map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-bell", "id": "alert", "name": "Alerts"}}, - want: want{ - status: 200, - body: map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-bell", "id": "alert", "name": "Alerts"}, - }, - }, - { - name: "UpdateUser", - args: args{method: "PUT", url: "/api/users/bob", data: map[string]interface{}{"roles": []interface{}{"analyst", "admin"}}}, - want: want{ - status: 200, - body: map[string]interface{}{"apikey": false, "blocked": false, "id": "bob", "roles": []interface{}{"admin:backup:read", "admin:backup:restore", "admin:group:write", "admin:job:read", "admin:job:write", "admin:log:read", "admin:ticket:delete", "admin:user:write", "admin:userdata:read", "admin:userdata:write", "analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write"}}, - }, - }, - { - name: "UpdateUserData", - args: args{method: "PUT", url: "/api/userdata/bob", data: map[string]interface{}{"blocked": false, "email": "bob@example.org", "name": "Bob Bad"}}, - want: want{ - status: 200, - body: map[string]interface{}{"email": "bob@example.org", "id": "bob", "name": "Bob Bad"}, - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - ctx, _, _, _, _, db, _, server, cleanup, err := test.Server(t) - if err != nil { - t.Fatal(err) - } - defer cleanup() - - if err := test.SetupTestData(ctx, db); err != nil { - t.Fatal(err) - } - - setUser := func(context *gin.Context) { - busdb.SetContext(context, test.Bob) - } - server.ApiGroup.Use(setUser) - - server.ConfigureRoutes() - w := httptest.NewRecorder() - - // setup request - var req *http.Request - if tt.args.data != nil { - b, err := json.Marshal(tt.args.data) - if err != nil { - t.Fatal(err) - } - - req = httptest.NewRequest(tt.args.method, tt.args.url, bytes.NewBuffer(b)) - req.Header.Set("Content-Type", "application/json") - } else { - req = httptest.NewRequest(tt.args.method, tt.args.url, nil) - } - - // run request - server.ServeHTTP(w, req) - - result := w.Result() - - // assert results - if result.StatusCode != tt.want.status { - msg, _ := io.ReadAll(result.Body) - - t.Fatalf("Status got = %v, want %v: %s", result.Status, tt.want.status, msg) - } - if tt.want.status != http.StatusNoContent { - jsonEqual(t, result.Body, tt.want.body) - } - }) - } -} - -func jsonEqual(t *testing.T, got io.Reader, want interface{}) { - var gotObject, wantObject interface{} - - // load bytes - wantBytes, err := json.Marshal(want) - if err != nil { - t.Fatal(err) - } - gotBytes, err := io.ReadAll(got) - if err != nil { - t.Fatal(err) - } - - fields := []string{"secret"} - for _, field := range fields { - gField := gjson.GetBytes(wantBytes, field) - if gField.Exists() && gjson.GetBytes(gotBytes, field).Exists() { - gotBytes, err = sjson.SetBytes(gotBytes, field, gField.Value()) - if err != nil { - t.Fatal(err) - } - } - } - - // normalize bytes - if err = json.Unmarshal(wantBytes, &wantObject); err != nil { - t.Fatal(err) - } - if err := json.Unmarshal(gotBytes, &gotObject); err != nil { - t.Fatal(string(gotBytes), err) - } - - // compare - assert.Equal(t, wantObject, gotObject) -} diff --git a/generator/generator.go b/generator/generator.go deleted file mode 100644 index 35e5604..0000000 --- a/generator/generator.go +++ /dev/null @@ -1,342 +0,0 @@ -package main - -import ( - "bytes" - "embed" - "encoding/json" - "flag" - "fmt" - "go/format" - "log" - "net/url" - "os" - "path" - "strings" - "text/template" - - "github.com/go-openapi/analysis" - "github.com/go-swagger/go-swagger/generator" - "github.com/iancoleman/strcase" - "github.com/tidwall/sjson" - "gopkg.in/yaml.v3" -) - -//go:embed templates/simplemodel.gotmpl -var model embed.FS - -func gotype(name string, s Schema, required []string) string { - _, x := sgotype(name, s, required, false) - return x -} - -func sgotype(name string, s Schema, required []string, nopointer bool) (bool, string) { - req := "" - if !nopointer && !contains(required, name) { - req = "*" - } - - if s.Ref != "" { - return false, req + path.Base(s.Ref) - } - - primitive := false - t := "" - - switch s.Type { - case "string": - if s.Format == "date-time" { - t = req + "time.Time" - } else { - t = req + "string" - primitive = true - } - case "boolean": - t = req + "bool" - primitive = true - case "object": - if s.AdditionalProperties != nil { - subPrimitive, subType := sgotype(name, *s.AdditionalProperties, required, true) - if subPrimitive { - t = "map[string]" + subType - } else { - t = "map[string]*" + subType - } - } else { - t = "interface{}" - } - case "number", "integer": - if s.Format != "" { - t = req + s.Format - } else { - t = req + "int" - } - primitive = true - case "array": - subPrimitive, subType := sgotype(name, *s.Items, required, true) - if subPrimitive { - t = "[]" + subType - } else { - t = "[]*" + subType - } - case "": - t = "interface{}" - default: - panic(fmt.Sprintf("%#v", s)) - } - - return primitive, t -} - -func omitempty(name string, required []string) bool { - return !contains(required, name) -} - -func contains(required []string, name string) bool { - for _, r := range required { - if r == name { - return true - } - } - return false -} - -func tojson(name string, i Definition) string { - b, _ := json.Marshal(i) - b, _ = sjson.SetBytes(b, "$id", "#/definitions/"+name) - return string(b) -} - -func camel(s string) string { - if s == "id" { - return "ID" - } - return strcase.ToCamel(s) -} - -func main() { - flag.Parse() - p := flag.Arg(0) - - log.SetFlags(log.LstdFlags | log.Lshortfile) - f, err := os.Open("generated/community.yml") - if err != nil { - log.Fatalln(err) - } - defer f.Close() - - s := Swagger{} - dec := yaml.NewDecoder(f) - err = dec.Decode(&s) - if err != nil { - log.Fatalln(err) - } - - t := template.New("simplemodel.gotmpl") - t.Funcs(map[string]interface{}{ - "camel": camel, - "gotype": gotype, - "omitempty": omitempty, - "tojson": tojson, - }) - templ := template.Must(t.ParseFS(model, "templates/simplemodel.gotmpl")) - - err = os.MkdirAll("generated/models", os.ModePerm) - if err != nil { - log.Fatalln(err) - } - - buf := bytes.NewBufferString("") - - props := map[string][]string{} - for defName, definition := range s.Definitions { - for propName := range definition.Properties { - props[defName] = append(props[defName], propName) - } - } - - // for _, definition := range s.Definitions { - // if definition.Embed != "" { - // if parentProps, ok := props[definition.Embed]; ok { - // for _, parentProp := range parentProps { - // delete(definition.Properties, parentProp) - // } - // } - // } - // } - - err = templ.Execute(buf, &s) - if err != nil { - log.Fatalln(err) - } - - fmtCode, err := format.Source(buf.Bytes()) - if err != nil { - log.Println(err) - fmtCode = buf.Bytes() - } - - err = os.WriteFile("generated/models/models.go", fmtCode, os.ModePerm) - if err != nil { - log.Fatalln(err) - } - - generator.FuncMapFunc = func(opts *generator.LanguageOpts) template.FuncMap { - df := generator.DefaultFuncMap(opts) - - df["path"] = func(basePath, lpath string, parameters generator.GenParameters) string { - u := url.URL{Path: path.Join(basePath, lpath)} - q := u.Query() - for _, p := range parameters { - if p.Location == "path" { - if example, ok := p.Extensions["x-example"]; ok { - u.Path = strings.ReplaceAll(u.Path, "{"+p.Name+"}", fmt.Sprint(example)) - } - } - if p.Location == "query" { - if example, ok := p.Extensions["x-example"]; ok { - q.Set(p.Name, fmt.Sprint(example)) - } - } - } - u.RawQuery = q.Encode() - return u.String() - } - df["body"] = func(parameters generator.GenParameters) interface{} { - for _, p := range parameters { - if p.Location == "body" { - if example, ok := p.Extensions["x-example"]; ok { - return example - } - } - } - return nil - } - df["ginizePath"] = func(path string) string { - return strings.Replace(strings.Replace(path, "{", ":", -1), "}", "", -1) - } - df["export"] = func(name string) string { - return strings.ToUpper(name[0:1]) + name[1:] - } - df["basePaths"] = func(operations []generator.GenOperation) []string { - var l []string - var seen = map[string]bool{} - for _, operation := range operations { - if _, ok := seen[operation.BasePath]; !ok { - l = append(l, strings.TrimPrefix(operation.BasePath, "/")) - seen[operation.BasePath] = true - } - } - return l - } - df["roles"] = func(reqs []analysis.SecurityRequirement) string { - for _, req := range reqs { - if req.Name == "roles" { - var roles []string - for _, scope := range req.Scopes { - roles = append(roles, "role."+strcase.ToCamel(strings.ReplaceAll(scope, ":", "_"))) - // roles = append(roles, permission.FromString(scope)) - } - return strings.Join(roles, ", ") - } - } - return "" - } - return df - } - - opts := &generator.GenOpts{ - Spec: "generated/community.yml", - Target: "generated", - APIPackage: "operations", - ModelPackage: "models", - ServerPackage: "restapi", - ClientPackage: "client", - DefaultScheme: "http", - IncludeModel: true, - IncludeValidator: true, - IncludeHandler: true, - IncludeParameters: true, - IncludeResponses: true, - IncludeURLBuilder: true, - IncludeMain: true, - IncludeSupport: true, - ValidateSpec: true, - FlattenOpts: &analysis.FlattenOpts{ - Minimal: true, - Verbose: true, - }, - Name: "catalyst-test", - FlagStrategy: "go-flags", - CompatibilityMode: "modern", - Sections: generator.SectionOpts{ - Application: []generator.TemplateOpts{ - { - Name: "api-server-test", - Source: path.Join(p, "templates/api_server_test.gotmpl"), - Target: "{{ .Target }}/test", - FileName: "api_server_test.go", - }, - // { - // Name: "configure", - // Source: "generator/config.gotmpl", - // Target: "{{ joinFilePath .Target .ServerPackage }}", - // FileName: "config.go", - // SkipExists: false, - // SkipFormat: false, - // }, - { - Name: "embedded_spec", - Source: "asset:swaggerJsonEmbed", - Target: "{{ joinFilePath .Target .ServerPackage }}", - FileName: "embedded_spec.go", - }, - { - Name: "server", - Source: path.Join(p, "templates/api.gotmpl"), - Target: "{{ joinFilePath .Target .ServerPackage }}", - FileName: "api.go", - }, - { - Name: "response.go", - Source: path.Join(p, "templates/response.gotmpl"), - Target: "{{ .Target }}/restapi/api", - FileName: "response.go", - }, - }, - Operations: []generator.TemplateOpts{ - { - Name: "parameters", - Source: path.Join(p, "templates/parameter.gotmpl"), - Target: "{{ if gt (len .Tags) 0 }}{{ joinFilePath .Target .ServerPackage .APIPackage .Package }}{{ else }}{{ joinFilePath .Target .ServerPackage .Package }}{{ end }}", - FileName: "{{ (snakize (pascalize .Name)) }}_parameters.go", - }, - }, - Models: []generator.TemplateOpts{ - { - Name: "definition", - Source: "asset:model", - Target: "{{ joinFilePath .Target .ModelPackage }}/old", - FileName: "{{ (snakize (pascalize .Name)) }}.go", - }, - // { - // Name: "model", - // Source: "generator/model.gotmpl", - // Target: "{{ joinFilePath .Target .ModelPackage }}/old2", - // FileName: "{{ (snakize (pascalize .Name)) }}.go", - // }, - }, - }, - } - - err = opts.EnsureDefaults() - if err != nil { - log.Fatalln(err) - } - - err = generator.GenerateServer("catalyst", nil, nil, opts) - if err != nil { - log.Fatalln(err) - } - // loads.Spec() - // swagger. -} diff --git a/generator/swagger.go b/generator/swagger.go deleted file mode 100644 index b27d7cd..0000000 --- a/generator/swagger.go +++ /dev/null @@ -1,61 +0,0 @@ -package main - -type Swagger struct { - Swagger string `yaml:"swagger" json:"swagger"` - Info Info `yaml:"info" json:"info"` - Paths map[string]PathItem `yaml:"paths" json:"paths"` - Definitions map[string]Definition `yaml:"definitions" json:"definitions"` -} - -type Info struct { - Version string `yaml:"version" json:"version"` - Title string `yaml:"title" json:"title"` -} - -type PathItem struct { - Get Operation `yaml:"get" json:"get"` - Post Operation `yaml:"post" json:"post"` -} - -type Operation struct { - Tags []string `yaml:"tags" json:"tags"` - Summary string `yaml:"summary" json:"summary"` - Description string `yaml:"description" json:"description"` - OperationID string `yaml:"operationId" json:"operationId"` - Parameters []Parameter `yaml:"parameters" json:"parameters"` - Responses map[string]Response `yaml:"responses" json:"responses"` -} - -type Parameter struct { - // Description string `yaml:"description" json:"description"` - Name string `yaml:"name" json:"name"` - In string `yaml:"in" json:"in"` - Required bool `yaml:"required" json:"required"` - Schema Schema `yaml:"schema" json:"schema"` - Direct Schema `yaml:"-,inline" json:"-,inline"` -} - -type Schema struct { - Ref string `yaml:"$ref,omitempty" json:"$ref,omitempty"` - Format string `yaml:"format,omitempty" json:"format,omitempty"` - Title string `yaml:"title,omitempty" json:"title,omitempty"` - Description string `yaml:"description" json:"description,omitempty"` - Default interface{} `yaml:"default,omitempty" json:"default,omitempty"` - Maximum interface{} `yaml:"maximum,omitempty" json:"maximum,omitempty"` - Items *Schema `yaml:"items,omitempty" json:"items,omitempty"` - Type string `yaml:"type" json:"type,omitempty"` - AdditionalProperties *Schema `yaml:"additionalProperties,omitempty" json:"additionalProperties,omitempty"` - Enum []string `yaml:"enum,omitempty" json:"enum,omitempty"` -} - -type Response struct { - Description string `yaml:"description" json:"description"` - Schema Schema `yaml:"schema" json:"schema"` -} - -type Definition struct { - Type string `yaml:"type" json:"type"` - Required []string `yaml:"required,omitempty" json:"required,omitempty"` - Embed string `yaml:"x-embed" json:"x-embed"` - Properties map[string]Schema `yaml:"properties" json:"properties"` -} diff --git a/generator/templates/api.gotmpl b/generator/templates/api.gotmpl deleted file mode 100644 index 9e49a8e..0000000 --- a/generator/templates/api.gotmpl +++ /dev/null @@ -1,124 +0,0 @@ -package {{ .APIPackage }} - -import ( - "context" - "log" - "net/http" - "os" - "os/signal" - "syscall" - "time" - "strings" - - "golang.org/x/oauth2" - - "github.com/gin-gonic/gin" - {{range .DefaultImports}}{{printf "%q" .}} - {{end}} - {{range $key, $value := .Imports}}{{$key}} {{ printf "%q" $value}} - {{end}} - "github.com/SecurityBrewery/catalyst/generated/restapi/api" - "github.com/SecurityBrewery/catalyst/role" -) - -// Service is the interface that must be implemented in order to provide -// business logic for the Server service. -type Service interface { - {{range .Operations}}{{ pascalize .Name }}(ctx context.Context{{ if .Params }}, params *{{.Package}}.{{ pascalize .Name }}Params{{ end }}) *api.Response -{{end}} -} - -// Config defines the config options for the API server. -type Config struct { - Address string - InsecureHTTP bool - TLSCertFile string - TLSKeyFile string -} - -// Server defines the Server service. -type Server struct { - *gin.Engine - config *Config - server *http.Server - service Service - - {{ range .Operations | basePaths }}{{ . | export }}Group *gin.RouterGroup -{{end}} - - RoleAuth func([]role.Role) gin.HandlerFunc -} - -// New initializes a new Server service. -func New(svc Service, config *Config) *Server { - engine := gin.New() - engine.Use(gin.Recovery()) - - return &Server{ - Engine: engine, - service: svc, - config: config, - server: &http.Server{ - Addr: config.Address, - Handler: engine, - ReadTimeout: 10 * time.Second, - WriteTimeout: 10 * time.Second, - }, - - {{range .Operations | basePaths }}{{ . | export }}Group: engine.Group("/{{.}}"), -{{end}} - RoleAuth: func(i []role.Role) gin.HandlerFunc { return func(c *gin.Context) { c.Next() } }, - } -} - -// ConfigureRoutes configures the routes for the Server service. -// Configuring of routes includes setting up Auth if it is enabled. -func (s *Server) ConfigureRoutes() { - {{range .Operations}}s.{{ slice .BasePath 1 | export }}Group.{{.Method}}({{ .Path | ginizePath | printf "%q" }}, s.RoleAuth([]role.Role{ {{ .SecurityRequirements | roles }} }), {{.Package}}.{{ pascalize .Name }}Endpoint(s.service.{{ pascalize .Name }})) -{{end}}} - -// run the Server. It will listen on either HTTP or HTTPS depending on the -// config passed to NewServer. -func (s *Server) run() error { - log.Printf("Serving on address %s\n", s.server.Addr) - if s.config.InsecureHTTP { - return s.server.ListenAndServe() - } - return s.server.ListenAndServeTLS(s.config.TLSCertFile, s.config.TLSKeyFile) -} - -// Shutdown will gracefully shutdown the Server. -func (s *Server) Shutdown() error { - return s.server.Shutdown(context.Background()) -} - -// RunWithSigHandler runs the Server with SIGTERM handling automatically -// enabled. The server will listen for a SIGTERM signal and gracefully shutdown -// the web server. -// It's possible to optionally pass any number shutdown functions which will -// execute one by one after the webserver has been shutdown successfully. -func (s *Server) RunWithSigHandler(shutdown ...func() error) error { - sigCh := make(chan os.Signal, 1) - signal.Notify(sigCh, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM) - - go func() { - <-sigCh - s.Shutdown() - }() - - err := s.run() - if err != nil { - if err != http.ErrServerClosed { - return err - } - } - - for _, fn := range shutdown { - err := fn() - if err != nil { - return err - } - } - - return nil -} diff --git a/generator/templates/api_server_test.gotmpl b/generator/templates/api_server_test.gotmpl deleted file mode 100644 index e347e6b..0000000 --- a/generator/templates/api_server_test.gotmpl +++ /dev/null @@ -1,146 +0,0 @@ -package test - -import ( - "bytes" - "context" - "encoding/json" - "io" - "net/http" - "net/http/httptest" - "testing" - "time" - - "github.com/go-openapi/swag" - "github.com/gin-gonic/gin" - "github.com/stretchr/testify/assert" - "github.com/tidwall/gjson" - "github.com/tidwall/sjson" - - ctime "github.com/SecurityBrewery/catalyst/time" - "github.com/SecurityBrewery/catalyst/database" - "github.com/SecurityBrewery/catalyst/database/busdb" - "github.com/SecurityBrewery/catalyst/generated/models" - "github.com/SecurityBrewery/catalyst/test" -) - -type testClock struct {} - -func (testClock) Now() time.Time { - return time.Date(2021, 12, 12, 12, 12, 12, 12, time.UTC) -} - -func TestService(t *testing.T) { - gin.SetMode(gin.TestMode) - ctime.DefaultClock = testClock{} - - type args struct { - method string - url string - data interface{} - } - type want struct { - status int - body interface{} - } - tests := []struct { - name string - args args - want want - }{ - {{range .Operations}} - { - name: "{{ pascalize .Name }}", - args: args{method: "{{ .Method }}", url: {{ path .BasePath .Path .Params | printf "%#v" }}{{ if .Params | body }}, data: {{ .Params | body | printf "%#v" }}{{ end }}}, - want: want{ - status: {{ with index .Responses 0 }}{{ .Code }}, - body: {{ if ne (len .Examples) 0 }}{{ with index .Examples 0 }}{{ .Example | printf "%#v" }}{{ end }}{{ else }}nil{{ end }}{{ end }}, - }, - }, {{ end }} - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - ctx, _, _, _, _, db, _, server, cleanup, err := test.Server(t) - if err != nil { - t.Fatal(err) - } - defer cleanup() - - if err := test.SetupTestData(ctx, db); err != nil { - t.Fatal(err) - } - - setUser := func(context *gin.Context) { - busdb.SetContext(context, test.Bob) - } - server.ApiGroup.Use(setUser) - - server.ConfigureRoutes() - w := httptest.NewRecorder() - - // setup request - var req *http.Request - if tt.args.data != nil { - b, err := json.Marshal(tt.args.data) - if err != nil { - t.Fatal(err) - } - - req = httptest.NewRequest(tt.args.method, tt.args.url, bytes.NewBuffer(b)) - req.Header.Set("Content-Type", "application/json") - } else { - req = httptest.NewRequest(tt.args.method, tt.args.url, nil) - } - - // run request - server.ServeHTTP(w, req) - - result := w.Result() - - // assert results - if result.StatusCode != tt.want.status { - msg, _ := io.ReadAll(result.Body) - - t.Fatalf("Status got = %v, want %v: %s", result.Status, tt.want.status, msg) - } - if tt.want.status != http.StatusNoContent { - jsonEqual(t, result.Body, tt.want.body) - } - }) - } -} - -func jsonEqual(t *testing.T, got io.Reader, want interface{}) { - var gotObject, wantObject interface{} - - // load bytes - wantBytes, err := json.Marshal(want) - if err != nil { - t.Fatal(err) - } - gotBytes, err := io.ReadAll(got) - if err != nil { - t.Fatal(err) - } - - fields := []string{"secret"} - for _, field := range fields { - gField := gjson.GetBytes(wantBytes, field) - if gField.Exists() && gjson.GetBytes(gotBytes, field).Exists() { - gotBytes, err = sjson.SetBytes(gotBytes, field, gField.Value()) - if err != nil { - t.Fatal(err) - } - } - } - - // normalize bytes - if err = json.Unmarshal(wantBytes, &wantObject); err != nil { - t.Fatal(err) - } - if err := json.Unmarshal(gotBytes, &gotObject); err != nil { - t.Fatal(string(gotBytes), err) - } - - // compare - assert.Equal(t, wantObject, gotObject) -} diff --git a/generator/templates/parameter.gotmpl b/generator/templates/parameter.gotmpl deleted file mode 100644 index d10eb1a..0000000 --- a/generator/templates/parameter.gotmpl +++ /dev/null @@ -1,347 +0,0 @@ -{{ define "sliceparamvalidator"}} -{{ if or .MinItems .MaxItems }} -{{ camelize .Name }}Size := int64(len({{ if and (not .IsArray) (not .HasDiscriminator) (not .IsInterface) (not .IsStream) .IsNullable }}*{{ end }}{{ .ValueExpression }})) -{{ end }} -{{ if .MinItems }} -if err := validate.MinItems({{ .Path }}, {{ printf "%q" .Location }}, {{ camelize .Name }}Size, {{ .MinItems }}); err != nil { - return err -} -{{ end }} -{{ if .MaxItems }} -if err := validate.MaxItems({{ .Path }}, {{ printf "%q" .Location }}, {{ camelize .Name }}Size, {{.MaxItems}}); err != nil { - return err -} -{{ end }} -{{ if .UniqueItems }} -if err := validate.UniqueItems({{ .Path }}, {{ printf "%q" .Location }}, {{ if and (not .IsArray) (not .HasDiscriminator) (not .IsInterface) (not .IsStream) .IsNullable }}*{{ end }}{{ .ValueExpression }}); err != nil { - return err -} -{{ end }} -{{ if .Enum }} -if err := validate.Enum({{ .Path }}, {{ printf "%q" .Location }}, {{ if and (not .IsArray) (not .HasDiscriminator) (not .IsInterface) (not .IsStream) .IsNullable }}*{{ end }}{{ .ValueExpression }}, {{ .Enum }}); err != nil { - return err -} -{{ end }} -{{ end }} -{{ define "customValidationPrimitive" }} -{{if .MinLength}} -if err := validate.MinLength({{ if .Path }}{{ .Path }}{{else}}""{{end}}, {{ printf "%q" .Location }}, {{ if .IsNullable }}(*{{ end }}{{.ValueExpression}}{{ if .IsNullable }}){{ end }}{{ if .IsCustomFormatter }}.String(){{ end }}, {{.MinLength}}); err != nil { - return err -} -{{end}} -{{if .MaxLength}} -if err := validate.MaxLength({{ if .Path }}{{ .Path }}{{else}}""{{end}}, {{ printf "%q" .Location }}, {{ if .IsNullable }}(*{{ end }}{{.ValueExpression}}{{ if .IsNullable }}){{ end }}{{ if .IsCustomFormatter }}.String(){{ end }}, {{.MaxLength}}); err != nil { - return err -} -{{end}} -{{if .Pattern}} -if err := validate.Pattern({{ if .Path }}{{ .Path }}{{else}}""{{end}}, {{ printf "%q" .Location }}, {{ if .IsNullable }}(*{{ end }}{{.ValueExpression}}{{ if .IsNullable }}){{ end }}{{ if .IsCustomFormatter }}.String(){{ end }}, `{{.Pattern}}`); err != nil { - return err -} -{{end}} -{{if .Minimum}} -if err := validate.Minimum{{ if eq .SwaggerType "integer" }}Int{{ end }}({{ if .Path }}{{ .Path }}{{else}}""{{end}}, {{ printf "%q" .Location }}, {{ if eq .SwaggerType "integer" }}int{{ else }}float{{ end }}64({{ if .IsNullable }}*{{ end }}{{.ValueExpression}}), {{.Minimum}}, {{.ExclusiveMinimum}}); err != nil { - return err -} -{{end}} -{{if .Maximum}} -if err := validate.Maximum{{ if eq .SwaggerType "integer" }}Int{{ end }}({{ if .Path }}{{ .Path }}{{else}}""{{end}}, {{ printf "%q" .Location }}, {{ if eq .SwaggerType "integer" }}int{{ else }}float{{ end }}64({{ if .IsNullable }}*{{ end }}{{.ValueExpression}}), {{.Maximum}}, {{.ExclusiveMaximum}}); err != nil { - return err -} -{{end}} -{{if .MultipleOf}} -if err := validate.MultipleOf({{ if .Path }}{{ .Path }}{{else}}""{{end}}, {{ printf "%q" .Location }}, float64({{ if .IsNullable }}*{{ end }}{{.ValueExpression}}), {{.MultipleOf}}); err != nil { - return err -} -{{end}} -{{if .Enum}} -if err := validate.Enum({{ if .Path }}{{ .Path }}{{else}}""{{end}}, {{ printf "%q" .Location }}, {{ if and (not .IsArray) (not .HasDiscriminator) (not .IsInterface) .IsNullable }}*{{ end }}{{.ValueExpression}}{{ if .IsCustomFormatter }}.String(){{ end }}, {{ printf "%#v" .Enum}}); err != nil { - return err -} -{{end}} -{{end}} -{{ define "propertyparamvalidator" }} -{{ if .IsPrimitive }}{{ template "customValidationPrimitive" . }}{{ end }} -{{ if .IsCustomFormatter }} -if err := validate.FormatOf({{.Path}}, "{{.Location}}", "{{.SwaggerFormat}}", {{.ValueExpression}}.String(), formats); err != nil { - return err -}{{ end }} -{{ if .IsArray }}{{ template "sliceparamvalidator" . }}{{ end -}} -{{ end }} -{{define "bindprimitiveparam" }} -{{ end }} -{{ define "sliceparambinder" }} -var {{ varname .Child.ValueExpression }}R {{ .GoType }} -for {{ if or .Child.HasValidations .Child.Converter .Child.IsCustomFormatter }}{{ .IndexVar }}{{ else }}_{{ end }}, {{ varname .Child.ValueExpression }}V := range {{ varname .Child.ValueExpression }}C { - {{ if or .Child.IsArray -}} - {{ .Child.Child.ValueExpression }}C := swag.SplitByFormat({{ varname .Child.ValueExpression }}V, {{ printf "%q" .Child.CollectionFormat }}) - {{ template "sliceparambinder" .Child }} - {{- else -}} - {{ if .Child.Converter -}} - {{ varname .Child.ValueExpression }}, err := {{ .Child.Converter }}({{ varname .Child.ValueExpression }}V) - if err != nil { - return errors.InvalidType({{ .Child.Path }}, {{ printf "%q" .Child.Location }}, "{{ .Child.GoType }}", {{ varname .Child.ValueExpression }}) - } - {{- else if .Child.IsCustomFormatter -}} - {{ varname .Child.ValueExpression }}, err := formats.Parse({{ varname .Child.ValueExpression }}V) - if err != nil { - return errors.InvalidType({{ .Child.Path }}, {{ printf "%q" .Child.Location }}, "{{ .Child.GoType }}", {{ varname .Child.ValueExpression }}) - } - {{- else -}} - {{ varname .Child.ValueExpression }} := {{ varname .Child.ValueExpression }}V - {{ end }} - {{- end }} - - {{ template "propertyparamvalidator" .Child }} - {{ varname .Child.ValueExpression }}R = append({{ varname .Child.ValueExpression }}R, {{ varname .Child.ValueExpression }}) -} -{{ end }} -package {{ .Package }} - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/go-openapi/errors" - "github.com/go-openapi/validate" - "github.com/go-openapi/runtime" - "github.com/go-openapi/runtime/middleware" - "github.com/go-openapi/swag" - - strfmt "github.com/go-openapi/strfmt" - - {{ range .DefaultImports }}{{ printf "%q" .}} - {{ end }} - {{ range $key, $value := .Imports }}{{ $key }} {{ printf "%q" $value }} - {{ end }} - "github.com/SecurityBrewery/catalyst/generated/restapi/api" -) - -// {{ pascalize .Name }}Endpoint executes the core logic of the related -// route endpoint. -func {{ pascalize .Name }}Endpoint(handler func(ctx context.Context{{ if .Params }}, params *{{ pascalize .Name }}Params{{ end }}) *api.Response) gin.HandlerFunc { - return func (ctx *gin.Context) { - - {{ if .Params }}// generate params from request - params := New{{ pascalize .Name }}Params() - err := params.ReadRequest(ctx) - if err != nil { - errObj := err.(*errors.CompositeError) - ctx.Writer.Header().Set("Content-Type", "application/problem+json") - ctx.JSON(int(errObj.Code()), gin.H{"error": errObj.Error()}) - return - } - {{ end }} - - resp := handler(ctx{{ if .Params }}, params{{end}}) - - switch resp.Code { - case http.StatusNoContent: - ctx.AbortWithStatus(resp.Code) - default: - ctx.JSON(resp.Code, resp.Body) - } - } -} - -// New{{ pascalize .Name }}Params creates a new {{ pascalize .Name }}Params object -// with the default values initialized. -func New{{ pascalize .Name }}Params() *{{ pascalize .Name }}Params { - var ( - {{ range .Params }}{{ if .HasDefault }}{{ if not .IsFileParam }}{{ varname .ID}}Default = {{ if .IsPrimitive}}{{.GoType}}({{ end}}{{ printf "%#v" .Default }}{{ if .IsPrimitive }}){{ end }} - {{ end }}{{ end }}{{end}} - ) - return &{{ pascalize .Name }}Params{ {{ range .Params }}{{ if .HasDefault }} - {{ pascalize .ID}}: {{ if and (not .IsArray) (not .HasDiscriminator) (not .IsInterface) (not .IsStream) .IsNullable }}&{{ end }}{{ varname .ID }}Default, - {{ end }}{{ end }} } -} - -// {{ pascalize .Name }}Params contains all the bound params for the {{ humanize .Name }} operation -// typically these are obtained from a http.Request -// -// swagger:parameters {{ .Name }} -type {{ pascalize .Name }}Params struct { - - {{ range .Params }}/*{{ if .Description }}{{ .Description }}{{ end }}{{ if .Required }} - Required: true{{ end }}{{ if .Maximum }} - Maximum: {{ if .ExclusiveMaximum }}< {{ end }}{{ .Maximum }}{{ end }}{{ if .Minimum }} - Minimum: {{ if .ExclusiveMinimum }}> {{ end }}{{ .Minimum }}{{ end }}{{ if .MultipleOf }} - Multiple Of: {{ .MultipleOf }}{{ end }}{{ if .MaxLength }} - Max Length: {{ .MaxLength }}{{ end }}{{ if .MinLength }} - Min Length: {{ .MinLength }}{{ end }}{{ if .Pattern }} - Pattern: {{ .Pattern }}{{ end }}{{ if .MaxItems }} - Max Items: {{ .MaxItems }}{{ end }}{{ if .MinItems }} - Min Items: {{ .MinItems }}{{ end }}{{ if .UniqueItems }} - Unique: true{{ end }}{{ if .Location }} - In: {{ .Location }}{{ end }}{{ if .CollectionFormat }} - Collection Format: {{ .CollectionFormat }}{{ end }}{{ if .HasDefault }} - Default: {{ printf "%#v" .Default }}{{ end }} - */ - {{ if not .Schema }}{{ pascalize .ID }} {{ if and (not .IsArray) (not .HasDiscriminator) (not .IsInterface) (not .IsFileParam) (not .IsStream) .IsNullable }}*{{ end }}{{.GoType}}{{ else }}{{ pascalize .Name }} {{ if and (not .Schema.IsBaseType) .IsNullable (not .Schema.IsStream) }}*{{ end }}{{.GoType}}{{ end }} - {{ end}} -} - -// ReadRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls -func ({{ .ReceiverName }} *{{ pascalize .Name }}Params) ReadRequest(ctx *gin.Context) error { - var res []error - {{ if .HasQueryParams }}qs := runtime.Values(ctx.Request.URL.Query()){{ end }} - - {{ if .HasFormParams }}if err := ctx.Request.ParseMultipartForm(32 << 20); err != nil { - if err != http.ErrNotMultipart { - return err - } else if err := ctx.Request.ParseForm(); err != nil { - return err - } - }{{ if .HasFormValueParams }} - fds := runtime.Values(ctx.Request.Form) - {{ end }}{{ end }} - - {{ range .Params }} - {{ if not .IsArray }}{{ if .IsQueryParam }}q{{ pascalize .Name }}, qhk{{ pascalize .Name }}, _ := qs.GetOK({{ .Path }}) - if err := {{ .ReceiverName }}.bind{{ pascalize .ID }}(q{{ pascalize .Name }}, qhk{{ pascalize .Name }}); err != nil { - res = append(res, err) - } - {{ else if .IsPathParam }}r{{ pascalize .Name }} := []string{ctx.Param({{ .Path }})} - if err := {{ .ReceiverName }}.bind{{ pascalize .ID }}(r{{ pascalize .Name }}, true); err != nil { - res = append(res, err) - } - {{ else if .IsHeaderParam }}if err := {{ .ReceiverName }}.bind{{ pascalize .ID }}(ctx.Request.Header[http.CanonicalHeaderKey({{ .Path }})], true); err != nil { - res = append(res, err) - } - {{ else if .IsFormParam }}{{if .IsFileParam }}{{ camelize .Name }}, {{ camelize .Name }}Header, err := ctx.Request.FormFile({{ .Path }}) - if err != nil { - res = append(res, errors.New(400, "reading file %q failed: %v", {{ printf "%q" (camelize .Name) }}, err)) - } else { - {{ .ReceiverName }}.{{ pascalize .Name }} = &runtime.File{Data: {{ camelize .Name }}, Header: {{ camelize .Name }}Header} - } - {{ else }}fd{{ pascalize .Name }}, fdhk{{ pascalize .Name }}, _ := fds.GetOK({{ .Path }}) - if err := {{ .ReceiverName }}.bind{{ pascalize .ID }}(fd{{ pascalize .Name }}, fdhk{{ pascalize .Name }}); err != nil { - res = append(res, err) - } - {{ end }}{{ end }} - {{ else if .IsArray }}{{ if .IsQueryParam }}q{{ pascalize .Name }}, qhk{{ pascalize .Name }}, _ := qs.GetOK({{ .Path }}) - if err := {{ .ReceiverName }}.bind{{ pascalize .ID }}(q{{ pascalize .Name }}, qhk{{ pascalize .Name }}); err != nil { - res = append(res, err) - } - {{ else if and .IsFormParam }}fd{{ pascalize .Name }}, fdhk{{ pascalize .Name }}, _ := fds.GetOK({{ .Path }}) - if err := {{ .ReceiverName }}.bind{{ pascalize .ID }}(fd{{ pascalize .Name }}, fdhk{{ pascalize .Name }}); err != nil { - res = append(res, err) - } - {{ end }}{{ end }} - - {{ if and .IsBodyParam .Schema }}if runtime.HasBody(ctx.Request) { - {{ if .Schema.IsStream }}{{ .ReceiverName }}.{{ pascalize .Name }} = ctx.Request.Body - {{ else }}{{ if and .Schema.IsBaseType .Schema.IsExported }}body, err := {{ .ModelsPackage }}.Unmarshal{{ dropPackage .GoType }}{{ if .IsArray }}Slice{{ end }}(ctx.Request.Body, route.Consumer) - if err != nil { {{ if .Required }} - if err == io.EOF { - err = errors.Required({{ .Path }}, {{ printf "%q" .Location }}, "") - } - {{ end }}res = append(res, err) - {{ else }}var body {{ .GoType }} - if err := ctx.BindJSON(&body); err != nil { {{ if .Required }} - if err == io.EOF { - res = append(res, errors.Required({{ printf "%q" (camelize .Name) }}, {{ printf "%q" .Location }}, "")) - } else { {{ end }} - res = append(res, errors.NewParseError({{ printf "%q" (camelize .Name) }}, {{ printf "%q" .Location }}, "", err)){{ if .Required }} - } - {{ end }} - {{ end }}} else { - {{ .ReceiverName }}.{{ pascalize .Name }} = {{ if and (not .Schema.IsBaseType) .IsNullable }}&{{ end }}body - }{{ end }} - }{{ if .Required }} else { - res = append(res, errors.Required({{ printf "%q" (camelize .Name) }}, {{ printf "%q" .Location }}, "")) - } {{ end }} - - {{ end }} - {{ end }} - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -{{ $className := (pascalize .Name) }} -{{ range .Params }} -{{ if not (or .IsBodyParam .IsFileParam) }} -{{ if or .IsPrimitive .IsCustomFormatter }} -func ({{ .ReceiverName }} *{{ $className }}Params) bind{{ pascalize .ID }}(rawData []string, hasKey bool) error { - {{ if and (not .IsPathParam) .Required }}if !hasKey { - return errors.Required({{ .Path }}, {{ printf "%q" .Location }}, rawData) - } - {{ end }}var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - {{ if and (not .IsPathParam) .Required (not .AllowEmptyValue) }}if err := validate.RequiredString({{ .Path }}, {{ printf "%q" .Location }}, raw); err != nil { - return err - } - {{ else if and ( not .IsPathParam ) (or (not .Required) .AllowEmptyValue) }}if raw == "" { // empty values pass all other validations - {{ if .HasDefault }}var {{ camelize .Name}}Default {{ if not .IsFileParam }}{{ .GoType }}{{ else }}os.File{{end}} = {{ if .IsPrimitive}}{{.GoType}}({{ end}}{{ printf "%#v" .Default }}{{ if .IsPrimitive }}){{ end }} - {{ .ValueExpression }} = {{ if and (not .IsArray) (not .HasDiscriminator) (or .IsNullable ) (not .IsStream) }}&{{ end }}{{ camelize .Name }}Default - {{ end }}return nil - } - {{ end }} - {{ if .Converter }}value, err := {{ .Converter }}(raw) - if err != nil { - return errors.InvalidType({{ .Path }}, {{ printf "%q" .Location }}, {{ printf "%q" .GoType }}, raw) - } - {{ .ValueExpression }} = {{ if .IsNullable }}&{{ end }}value - {{ else if .IsCustomFormatter }}value, err := formats.Parse({{ printf "%q" .SwaggerFormat }}, raw) - if err != nil { - return errors.InvalidType({{ .Path }}, {{ printf "%q" .Location }}, {{ printf "%q" .GoType }}, raw) - } - {{ .ValueExpression }} = {{ if and (not .IsArray) (not .HasDiscriminator) (not .IsFileParam) (not .IsStream) (not .IsNullable) }}*{{ end }}(value.(*{{ .GoType }})) - {{else}}{{ .ValueExpression }} = {{ if .IsNullable }}&{{ end }}raw - {{ end }} - {{if .HasValidations }}if err := {{ .ReceiverName }}.validate{{ pascalize .ID }}(); err != nil { - return err - } - {{ end }} - return nil -} -{{else if .IsArray}} -func ({{ .ReceiverName }} *{{ $className }}Params) bind{{ pascalize .ID }}(rawData []string, hasKey bool) error { - {{if .Required }}if !hasKey { - return errors.Required({{ .Path }}, {{ printf "%q" .Location }}, rawData) - } - {{ end }} - {{ if eq .CollectionFormat "multi" }}{{ varname .Child.ValueExpression }}C := rawData{{ else }}var qv{{ pascalize .Name }} string - if len(rawData) > 0 { - qv{{ pascalize .Name }} = rawData[len(rawData) - 1] - } - - {{ varname .Child.ValueExpression }}C := swag.SplitByFormat(qv{{ pascalize .Name }}, {{ printf "%q" .CollectionFormat }}){{ end }} - {{if and .Required (not .AllowEmptyValue) }} - if len({{ varname .Child.ValueExpression }}C) == 0 { - return errors.Required({{ .Path }}, {{ printf "%q" .Location }}, {{ varname .Child.ValueExpression }}C) - } - {{ end }} - {{ if not .Required }}{{ if .HasDefault }}defValue := swag.SplitByFormat({{ .Default }}, {{ printf "%q" .CollectionFormat }}) - if len({{ varname .Child.ValueExpression }}C) == 0 && len(defValue) > 0 { - {{ .ValueExpression }} = defValue - {{ else }}if len({{ varname .Child.ValueExpression }}C) == 0 { - return nil{{ end }} - }{{ end }} - {{ template "sliceparambinder" . }} - {{ .ValueExpression }} = {{ varname .Child.ValueExpression }}R - {{ if .HasSliceValidations }}if err := {{ .ReceiverName }}.validate{{ pascalize .ID }}(); err != nil { - return err - } - {{ end }} - - return nil -} -{{ end }} -{{ if or .HasValidations .HasSliceValidations }} -func ({{ .ReceiverName }} *{{ $className }}Params) validate{{ pascalize .ID }}() error { - {{ template "propertyparamvalidator" . }} - return nil -} -{{ end }} -{{ end }} -{{ end }} diff --git a/generator/templates/response.gotmpl b/generator/templates/response.gotmpl deleted file mode 100644 index a24ac14..0000000 --- a/generator/templates/response.gotmpl +++ /dev/null @@ -1,6 +0,0 @@ -package api - -type Response struct { - Code int - Body interface{} -} diff --git a/generator/templates/simplemodel.gotmpl b/generator/templates/simplemodel.gotmpl deleted file mode 100644 index 169d2a5..0000000 --- a/generator/templates/simplemodel.gotmpl +++ /dev/null @@ -1,64 +0,0 @@ -{{- /*gotype: github.com/SecurityBrewery/catalyst/generator.Swagger */ -}} -package models - -import ( - "fmt" - "strings" - "time" - - "github.com/xeipuuv/gojsonschema" -) - -var ( - schemaLoader = gojsonschema.NewSchemaLoader() - {{ range $index, $element := .Definitions }}{{ $index }}Schema = new(gojsonschema.Schema) -{{ end }}) - -func init() { - err := schemaLoader.AddSchemas( - {{ range $index, $element := .Definitions }}gojsonschema.NewStringLoader(`{{ tojson $index $element }}`), - {{ end }} - ) - if err != nil { - panic(err) - } - - {{ range $index, $element := .Definitions }}{{ $index }}Schema = mustCompile(`#/definitions/{{ $index }}`) -{{ end }}} - -{{ range $index, $element := .Definitions }} -type {{ $index }} struct { - {{ range $pindex, $pelement := .Properties }} {{ camel $pindex }} {{ gotype $pindex $pelement $element.Required }} `json:"{{ $pindex }}{{ if omitempty $pindex $element.Required }},omitempty{{ end }}"` -{{ end }}} - -{{ end }} - -func mustCompile(uri string) *gojsonschema.Schema { - s, err := schemaLoader.Compile(gojsonschema.NewReferenceLoader(uri)) - if err != nil { - panic(err) - } - return s -} - -func validate(s *gojsonschema.Schema, b []byte) error { - res, err := s.Validate(gojsonschema.NewStringLoader(string(b))) - if err != nil { - return err - } - - if len(res.Errors()) > 0 { - var l []string - for _, e := range res.Errors() { - l = append(l, e.String()) - } - return fmt.Errorf("validation failed: %v", strings.Join(l, ", ")) - } - return nil -} - -const ( -{{ range $index, $element := .Definitions }}{{ range $pindex, $pelement := .Properties }}{{ range $eindex, $eelement := .Enum }} -{{ $index | camel }}{{ $pindex | camel }}{{ $eelement | camel }} = "{{ $eelement }}" -{{ end }}{{ end }}{{ end }} -) diff --git a/go.mod b/go.mod index bebcb14..e29306f 100644 --- a/go.mod +++ b/go.mod @@ -15,49 +15,36 @@ require ( github.com/bmizerany/pat v0.0.0-20210406213842-e4b6760bdd6f // indirect github.com/containerd/containerd v1.5.8 // indirect github.com/coreos/go-oidc/v3 v3.1.0 - // github.com/docker/docker v1.13.1 github.com/docker/docker v17.12.0-ce-rc1.0.20201201034508-7d75c1d40d88+incompatible github.com/docker/go-connections v0.4.0 // indirect github.com/eclipse/paho.mqtt.golang v1.3.5 // indirect github.com/emitter-io/go/v2 v2.0.9 - github.com/gin-contrib/cors v1.3.1 - github.com/gin-contrib/sessions v0.0.4 - github.com/gin-gonic/gin v1.7.4 - github.com/go-openapi/analysis v0.21.1 - github.com/go-openapi/errors v0.20.1 - github.com/go-openapi/runtime v0.21.0 - github.com/go-openapi/swag v0.19.15 - github.com/go-openapi/validate v0.20.3 - github.com/go-playground/validator/v10 v10.9.0 // indirect - github.com/go-stack/stack v1.8.1 // indirect - github.com/go-swagger/go-swagger v0.27.0 + github.com/go-chi/chi v1.5.4 + github.com/go-chi/cors v1.2.0 github.com/gobwas/ws v1.1.0 github.com/golang/snappy v0.0.4 // indirect github.com/google/uuid v1.3.0 github.com/gorilla/mux v1.8.0 // indirect - github.com/gorilla/sessions v1.2.1 // indirect github.com/iancoleman/strcase v0.2.0 github.com/icza/dyno v0.0.0-20210726202311-f1bafe5d9996 github.com/imdario/mergo v0.3.12 - github.com/json-iterator/go v1.1.12 // indirect - github.com/mattn/go-isatty v0.0.14 // indirect + github.com/kr/pretty v0.3.0 // indirect github.com/mingrammer/commonregex v1.0.1 - github.com/mitchellh/mapstructure v1.4.2 // indirect github.com/morikuni/aec v1.0.0 // indirect github.com/opencontainers/image-spec v1.0.2 // indirect + github.com/rogpeppe/go-internal v1.8.0 // indirect github.com/stretchr/testify v1.7.0 - github.com/tidwall/gjson v1.11.0 - github.com/tidwall/sjson v1.2.3 + github.com/tidwall/gjson v1.12.1 + github.com/tidwall/sjson v1.2.4 github.com/tus/tusd v1.8.0 - github.com/ugorji/go v1.2.6 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonschema v1.2.0 go.etcd.io/bbolt v1.3.6 // indirect - go.mongodb.org/mongo-driver v1.7.4 // indirect golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect golang.org/x/net v0.0.0-20211105192438-b53810dc28af // indirect golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 golang.org/x/sys v0.0.0-20211105183446-c75c47738b0c // indirect + golang.org/x/text v0.3.7 // indirect gopkg.in/square/go-jose.v2 v2.6.0 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b diff --git a/go.sum b/go.sum index 224ecfb..37e8079 100644 --- a/go.sum +++ b/go.sum @@ -34,7 +34,6 @@ cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4g cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -88,15 +87,11 @@ github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5 github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/RoaringBitmap/roaring v0.9.4 h1:ckvZSX5gwCRaJYBNe7syNawCU5oruY9gQmjXlp4riwo= github.com/RoaringBitmap/roaring v0.9.4/go.mod h1:icnadbWcNyfEHlYdr+tDlOTih1Bf/h+rzPpv4sbomAA= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= -github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= github.com/alecthomas/kong v0.2.12/go.mod h1:kQOmtJgV+Lb4aj+I2LEn40cbtawdWJ9Y8QLq+lElKxE= github.com/alecthomas/kong v0.2.17 h1:URDISCI96MIgcIlQyoCAlhOmrSw6pZScBNkctg8r0W0= github.com/alecthomas/kong v0.2.17/go.mod h1:ka3VZ8GZNPXv9Ov+j4YNLkI8mTuhXyr/0ktSlqIydQQ= @@ -108,28 +103,16 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= -github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20211101200231-0802afb9c160 h1:7qzNO1wqchnLQf8sOapBujDO/mFu8gYW/9jGZl1l96E= github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20211101200231-0802afb9c160/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= -github.com/antonlindstrom/pgstore v0.0.0-20200229204646-b08ebf1105e0/go.mod h1:2Ti6VUHVxpC0VSmTZzEvpzysnaGAfGBOoMIz5ykPyyw= github.com/arangodb/go-driver v1.2.1 h1:HREDHhDmzdIWxHmfkfTESbYUnRjESjPh4WUuXq7FZa8= github.com/arangodb/go-driver v1.2.1/go.mod h1:zdDkJJnCj8DAkfbtIjIXnsTrWIiy6VhP3Vy14p+uQeY= github.com/arangodb/go-velocypack v0.0.0-20200318135517-5af53c29c67e h1:Xg+hGrY2LcQBbxd0ZFdbGSyRKTYMZCfBbw/pMJFOk1g= github.com/arangodb/go-velocypack v0.0.0-20200318135517-5af53c29c67e/go.mod h1:mq7Shfa/CaixoDxiyAAc5jZ6CVBAyPaNQCGS7mkj4Ho= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= -github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= -github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ= -github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= -github.com/aws/aws-sdk-go v1.34.28/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48= github.com/aws/aws-sdk-go v1.41.13/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= github.com/aws/aws-sdk-go v1.41.19 h1:9QR2WTNj5bFdrNjRY9SeoG+3hwQmKXGX16851vdh+N8= github.com/aws/aws-sdk-go v1.41.19/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= @@ -142,7 +125,6 @@ github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngE github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/bits-and-blooms/bitset v1.2.1 h1:M+/hrU9xlMp7t4TyTDQW97d3tRPVuKFC6zBEK16QnXY= github.com/bits-and-blooms/bitset v1.2.1/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= -github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blevesearch/bleve/v2 v2.2.2 h1:kBLSCEcAs7VvH4S/JkpYwR4Jnpuv/3FNl6LWg6fqCmY= @@ -178,9 +160,6 @@ github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dR github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c= github.com/bmizerany/pat v0.0.0-20210406213842-e4b6760bdd6f h1:gOO/tNZMjjvTKZWpY7YnXC72ULNLErRtp94LountVE8= github.com/bmizerany/pat v0.0.0-20210406213842-e4b6760bdd6f/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c= -github.com/boj/redistore v0.0.0-20180917114910-cd5dcc76aeff/go.mod h1:+RTT1BOk5P97fT2CiHkbFQwkK3mjsFAP6zCYV2aXtjw= -github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA= -github.com/bradleypeabody/gorilla-sessions-memcache v0.0.0-20181103040241-659414f458e1/go.mod h1:dkChI7Tbtx7H1Tj7TqGSZMOeGpMP5gLHtjroHd4agiI= github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= @@ -293,14 +272,12 @@ github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgU github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-iptables v0.4.3/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= +github.com/coreos/go-oidc v2.1.0+incompatible h1:sdJrfw8akMnCuUlaZU3tE/uYXFgfqom8DBE9so9EBsM= github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= -github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk= -github.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-oidc/v3 v3.1.0 h1:6avEvcdvTa1qYsOZ6I5PRkSYHzpTNWgKYmaJfaYbrRw= github.com/coreos/go-oidc/v3 v3.1.0/go.mod h1:rEJ/idjfUyfkBit1eI1fvyr+64/g9dcKpAm8MJMesvo= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -346,7 +323,6 @@ github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6Uezg github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= -github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= @@ -373,27 +349,18 @@ github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go. github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gin-contrib/cors v1.3.1 h1:doAsuITavI4IOcd0Y19U4B+O0dNWihRyX//nn4sEmgA= -github.com/gin-contrib/cors v1.3.1/go.mod h1:jjEJ4268OPZUcU7k9Pm653S7lXUGcqMADzFA61xsmDk= -github.com/gin-contrib/sessions v0.0.4 h1:gq4fNa1Zmp564iHP5G6EBuktilEos8VKhe2sza1KMgo= -github.com/gin-contrib/sessions v0.0.4/go.mod h1:pQ3sIyviBBGcxgyR8mkeJuXbeV3h3NYmhJADQTq5+Vo= -github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= -github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do= -github.com/gin-gonic/gin v1.7.4 h1:QmUZXrvJ9qZ3GfWvQ+2wnW/1ePrTEJqPKMYEU3lD/DM= -github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY= -github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= -github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= +github.com/go-chi/chi v1.5.4 h1:QHdzF2szwjqVV4wmByUnTcsbIg7UGaQ0tPF2t5GcAIs= +github.com/go-chi/chi v1.5.4/go.mod h1:uaf8YgoFazUOkPBG7fxPftUylNumIev9awIWOENIuEg= +github.com/go-chi/cors v1.2.0 h1:tV1g1XENQ8ku4Bq3K9ub2AtgG+p16SmzeMSGTwrOKdE= +github.com/go-chi/cors v1.2.0/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -406,155 +373,14 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= -github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= -github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= -github.com/go-openapi/analysis v0.19.2/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk= -github.com/go-openapi/analysis v0.19.4/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk= -github.com/go-openapi/analysis v0.19.5/go.mod h1:hkEAkxagaIvIP7VTn8ygJNkd4kAYON2rCu0v0ObL0AU= -github.com/go-openapi/analysis v0.19.10/go.mod h1:qmhS3VNFxBlquFJ0RGoDtylO9y4pgTAUNE9AEEMdlJQ= -github.com/go-openapi/analysis v0.19.16/go.mod h1:GLInF007N83Ad3m8a/CbQ5TPzdnGT7workfHwuVjNVk= -github.com/go-openapi/analysis v0.20.0/go.mod h1:BMchjvaHDykmRMsK40iPtvyOfFdMMxlOmQr9FBZk+Og= -github.com/go-openapi/analysis v0.20.1/go.mod h1:BMchjvaHDykmRMsK40iPtvyOfFdMMxlOmQr9FBZk+Og= -github.com/go-openapi/analysis v0.21.1 h1:krcNCEvCttpSUFBPOrfvn7nniejvrOkoNYRlZwQFpEs= -github.com/go-openapi/analysis v0.21.1/go.mod h1:HZwRk4RRisyG8vx2Oe6aqeSQcoxRp47Xkp3+K6q+LdY= -github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= -github.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= -github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= -github.com/go-openapi/errors v0.19.3/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= -github.com/go-openapi/errors v0.19.6/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/errors v0.19.7/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/errors v0.19.8/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/errors v0.19.9/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/errors v0.20.0/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/errors v0.20.1 h1:j23mMDtRxMwIobkpId7sWh7Ddcx4ivaoqUbfXx5P+a8= -github.com/go-openapi/errors v0.20.1/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/inflect v0.19.0 h1:9jCH9scKIbHeV9m12SmPilScz6krDxKRasNNSNPXu/4= -github.com/go-openapi/inflect v0.19.0/go.mod h1:lHpZVlpIQqLyKwJ4N+YSc9hchQy/i12fJykb83CRBH4= -github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= -github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= -github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= -github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= -github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs= -github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns= -github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= -github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= -github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= -github.com/go-openapi/loads v0.19.2/go.mod h1:QAskZPMX5V0C2gvfkGZzJlINuP7Hx/4+ix5jWFxsNPs= -github.com/go-openapi/loads v0.19.3/go.mod h1:YVfqhUCdahYwR3f3iiwQLhicVRvLlU/WO5WPaZvcvSI= -github.com/go-openapi/loads v0.19.5/go.mod h1:dswLCAdonkRufe/gSUC3gN8nTSaB9uaS2es0x5/IbjY= -github.com/go-openapi/loads v0.19.6/go.mod h1:brCsvE6j8mnbmGBh103PT/QLHfbyDxA4hsKvYBNEGVc= -github.com/go-openapi/loads v0.19.7/go.mod h1:brCsvE6j8mnbmGBh103PT/QLHfbyDxA4hsKvYBNEGVc= -github.com/go-openapi/loads v0.20.0/go.mod h1:2LhKquiE513rN5xC6Aan6lYOSddlL8Mp20AW9kpviM4= -github.com/go-openapi/loads v0.20.2/go.mod h1:hTVUotJ+UonAMMZsvakEgmWKgtulweO9vYP2bQYKA/o= -github.com/go-openapi/loads v0.21.0 h1:jYtUO4wwP7psAweisP/MDoOpdzsYEESdoPcsWjHDR68= -github.com/go-openapi/loads v0.21.0/go.mod h1:rHYve9nZrQ4CJhyeIIFJINGCg1tQpx2yJrrNo8sf1ws= -github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA= -github.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt4sK4FXt0O64= -github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4= -github.com/go-openapi/runtime v0.19.15/go.mod h1:dhGWCTKRXlAfGnQG0ONViOZpjfg0m2gUt9nTQPQZuoo= -github.com/go-openapi/runtime v0.19.16/go.mod h1:5P9104EJgYcizotuXhEuUrzVc+j1RiSjahULvYmlv98= -github.com/go-openapi/runtime v0.19.24/go.mod h1:Lm9YGCeecBnUUkFTxPC4s1+lwrkJ0pthx8YvyjCfkgk= -github.com/go-openapi/runtime v0.19.27/go.mod h1:BvrQtn6iVb2QmiVXRsFAm6ZCAZBpbVKFfN6QWCp582M= -github.com/go-openapi/runtime v0.21.0 h1:giZ8eT26R+/rx6RX2MkYjZPY8vPYVKDhP/mOazrQHzM= -github.com/go-openapi/runtime v0.21.0/go.mod h1:aQg+kaIQEn+A2CRSY1TxbM8+sT9g2V3aLc1FbIAnbbs= -github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= -github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= -github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY= github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= -github.com/go-openapi/spec v0.19.6/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= -github.com/go-openapi/spec v0.19.8/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= -github.com/go-openapi/spec v0.19.15/go.mod h1:+81FIL1JwC5P3/Iuuozq3pPE9dXdIEGxFutcFKaVbmU= -github.com/go-openapi/spec v0.20.0/go.mod h1:+81FIL1JwC5P3/Iuuozq3pPE9dXdIEGxFutcFKaVbmU= -github.com/go-openapi/spec v0.20.1/go.mod h1:93x7oh+d+FQsmsieroS4cmR3u0p/ywH649a3qwC9OsQ= -github.com/go-openapi/spec v0.20.3/go.mod h1:gG4F8wdEDN+YPBMVnzE85Rbhf+Th2DTvA9nFPQ5AYEg= -github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M= -github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I= -github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= -github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= -github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY= -github.com/go-openapi/strfmt v0.19.2/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU= -github.com/go-openapi/strfmt v0.19.3/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU= -github.com/go-openapi/strfmt v0.19.4/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk= -github.com/go-openapi/strfmt v0.19.5/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk= -github.com/go-openapi/strfmt v0.19.11/go.mod h1:UukAYgTaQfqJuAFlNxxMWNvMYiwiXtLsF2VwmoFtbtc= -github.com/go-openapi/strfmt v0.20.0/go.mod h1:UukAYgTaQfqJuAFlNxxMWNvMYiwiXtLsF2VwmoFtbtc= -github.com/go-openapi/strfmt v0.20.1/go.mod h1:43urheQI9dNtE5lTZQfuFJvjYJKPrxicATpEfZwHUNk= -github.com/go-openapi/strfmt v0.20.2/go.mod h1:43urheQI9dNtE5lTZQfuFJvjYJKPrxicATpEfZwHUNk= -github.com/go-openapi/strfmt v0.21.0 h1:hX2qEZKmYks+t0hKeb4VTJpUm2UYsdL3+DCid5swxIs= -github.com/go-openapi/strfmt v0.21.0/go.mod h1:ZRQ409bWMj+SOgXofQAGTIo2Ebu72Gs+WaRADcS5iNg= -github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= -github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.7/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY= -github.com/go-openapi/swag v0.19.9/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY= -github.com/go-openapi/swag v0.19.12/go.mod h1:eFdyEBkTdoAf/9RXBvj4cr1nH7GD8Kzo5HTt47gr72M= -github.com/go-openapi/swag v0.19.13/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM= -github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= -github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= -github.com/go-openapi/validate v0.19.3/go.mod h1:90Vh6jjkTn+OT1Eefm0ZixWNFjhtOH7vS9k0lo6zwJo= -github.com/go-openapi/validate v0.19.10/go.mod h1:RKEZTUWDkxKQxN2jDT7ZnZi2bhZlbNMAuKvKB+IaGx8= -github.com/go-openapi/validate v0.19.12/go.mod h1:Rzou8hA/CBw8donlS6WNEUQupNvUZ0waH08tGe6kAQ4= -github.com/go-openapi/validate v0.19.15/go.mod h1:tbn/fdOwYHgrhPBzidZfJC2MIVvs9GA7monOmWBbeCI= -github.com/go-openapi/validate v0.20.1/go.mod h1:b60iJT+xNNLfaQJUqLI7946tYiFEOuE9E4k54HpKcJ0= -github.com/go-openapi/validate v0.20.2/go.mod h1:e7OJoKNgd0twXZwIn0A43tHbvIcr/rZIVCbJBpTUoY0= -github.com/go-openapi/validate v0.20.3 h1:GZPPhhKSZrE8HjB4eEkoYAZmoWA4+tCemSgINH1/vKw= -github.com/go-openapi/validate v0.20.3/go.mod h1:goDdqVGiigM3jChcrYJxD2joalke3ZXeftD16byIjA4= -github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= -github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM= -github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= -github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= -github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= -github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY= -github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= -github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= -github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= -github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= -github.com/go-playground/validator/v10 v10.9.0 h1:NgTtmN58D0m8+UuxtYmGztBJB7VnPgjj221I1QHci2A= -github.com/go-playground/validator/v10 v10.9.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= -github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= -github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= -github.com/go-swagger/go-swagger v0.27.0 h1:K7+nkBuf4oS1jTBrdvWqYFpqD69V5CN8HamZzCDDhAI= -github.com/go-swagger/go-swagger v0.27.0/go.mod h1:WodZVysInJilkW7e6IRw+dZGp5yW6rlMFZ4cb+THl9A= -github.com/go-swagger/scan-repo-boundary v0.0.0-20180623220736-973b3573c013/go.mod h1:b65mBPzqzZWxOZGxSWrqs4GInLIn+u99Q9q7p+GKni0= -github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= -github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= -github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg= -github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= -github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= -github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs= -github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= -github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= -github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk= -github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28= -github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo= -github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk= -github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw= -github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360= -github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg= -github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE= -github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8= -github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= -github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= -github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= -github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= -github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= -github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= -github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= @@ -615,7 +441,6 @@ github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -663,21 +488,11 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= -github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= -github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= -github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= -github.com/gorilla/sessions v1.1.1/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w= -github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= -github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI= -github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= @@ -691,29 +506,13 @@ github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= -github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/iancoleman/strcase v0.2.0 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHLwW0= github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= @@ -729,48 +528,33 @@ github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= -github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc= -github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= -github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= -github.com/kidstuff/mongostore v0.0.0-20181113001930-e650cd85ee4b/go.mod h1:g2nVr8KZVXJSS97Jo8pJ0jgq29P6H7dG0oplUA86MQw= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/kljensen/snowball v0.6.0/go.mod h1:27N7E8fVU5H68RlUmnWwZCfxgt4POBJfENGMvNRhldw= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -782,59 +566,24 @@ github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= -github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= -github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= -github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= -github.com/lib/pq v1.10.3/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= -github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= -github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= -github.com/mailru/easyjson v0.7.1/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= -github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= -github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-ieproxy v0.0.1/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/gNWuh88E= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/memcachier/mc v2.0.1+incompatible/go.mod h1:7bkvFE61leUBvXz+yxsOnGBQSZpBSPIMUQSmmSHvuXc= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/mingrammer/commonregex v1.0.1 h1:QY0Z1Bl80jw9M3+488HJXPWnZmvtu3UdvxyodP2FTyY= github.com/mingrammer/commonregex v1.0.1/go.mod h1:/HNZq7qReKgXBxJxce5SOxf33y0il/ZqL4Kxgo2NLcA= github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/mapstructure v1.4.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/mapstructure v1.4.2 h1:6h7AQ0yhTcIsmFmnAwQls75jp2Gzs4iB8W7pjMO+rqo= -github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= @@ -842,13 +591,9 @@ github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2J github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= @@ -861,9 +606,7 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRW github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -907,13 +650,7 @@ github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqi github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo= -github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= -github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM= github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= @@ -922,12 +659,9 @@ github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= -github.com/pquerna/cachecontrol v0.0.0-20201205024021-ac21108117ac/go.mod h1:hoLfEwdY11HjRfKFH6KqnPsfxlo3BP6bJehpDv8t6sQ= github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= @@ -959,12 +693,9 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/quasoft/memstore v0.0.0-20191010062613-2bce066d2b0b/go.mod h1:wTPjTepVu7uJBYgZ0SdWHQlIas582j6cn2jgk4DDdlg= github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= @@ -973,57 +704,39 @@ github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.19.0/go.mod h1:IzD0RJ65iWH0w97OQQebJEvTZYvsCUm9WVLWBQrJRjo= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sethgrid/pester v0.0.0-20190127155807-68a33a018ad0/go.mod h1:Ad7IjTpvzZO8Fl0vh9AzQ+j/jYZfyp2diGwI8m5q+ns= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= -github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= -github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= -github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk= -github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8= github.com/steveyen/gtreap v0.1.0 h1:CjhzTa274PyJLJuMZwIzCO1PfC00oRa8d1Kc78bFXJM= github.com/steveyen/gtreap v0.1.0/go.mod h1:kl/5J7XbrOmlIbYIXdRHDDE5QxHqpk0cmkT7Z4dM9/Y= @@ -1039,41 +752,29 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= -github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= -github.com/tidwall/gjson v1.10.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= -github.com/tidwall/gjson v1.11.0 h1:C16pk7tQNiH6VlCrtIXL1w8GaOsi1X3W8KDkE1BuYd4= -github.com/tidwall/gjson v1.11.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.12.1 h1:ikuZsLdhr8Ws0IdROXUS1Gi4v9Z4pGqpX/CvJkxvfpo= +github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= -github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= -github.com/tidwall/sjson v1.2.3 h1:5+deguEhHSEjmuICXZ21uSSsXotWMA0orU783+Z7Cp8= -github.com/tidwall/sjson v1.2.3/go.mod h1:5WdjKx3AQMvCJ4RG6/2UYT7dLrGvJUV1x4jdTAyGvZs= +github.com/tidwall/sjson v1.2.4 h1:cuiLzLnaMeBhRmEv00Lpk3tkYrcxpmbU81tAY4Dw0tc= +github.com/tidwall/sjson v1.2.4/go.mod h1:098SZ494YoMWPmMO6ct4dcFnqxwj9r/gF0Etp19pSNM= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/toqueteos/webbrowser v1.2.0/go.mod h1:XWoZq4cyp9WeUeak7w7LXRUQf1F1ATJMir8RTqb4ayM= github.com/tus/tusd v1.8.0 h1:QODQ5uMhL2tFX3Ouk7rUHHqPqeDBvi2+gYIoyUO0n8Q= github.com/tus/tusd v1.8.0/go.mod h1:stZzKpol4qz7lX2HXy/1H526dn5mRnkIICTW2lrh9NM= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= -github.com/ugorji/go v1.2.6 h1:tGiWC9HENWE2tqYycIqFTNorMmFRVhNwCpDOpWqnk8E= -github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ= -github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw= github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= github.com/vimeo/go-util v1.4.1/go.mod h1:r+yspV//C48HeMXV8nEvtUeNiIiGfVv3bbEHzOgudwE= github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= @@ -1085,11 +786,6 @@ github.com/warjiang/gojsonschema v1.2.1-0.20210329105853-aa9f9a8cfec7 h1:tBx6st5 github.com/warjiang/gojsonschema v1.2.1-0.20210329105853-aa9f9a8cfec7/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= -github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= -github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= -github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= -github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= -github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= @@ -1097,7 +793,6 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHo github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -1112,17 +807,6 @@ go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= -go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= -go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= -go.mongodb.org/mongo-driver v1.3.0/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS3gZBapIE= -go.mongodb.org/mongo-driver v1.3.4/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS3gZBapIE= -go.mongodb.org/mongo-driver v1.4.3/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4SoGjYphSc= -go.mongodb.org/mongo-driver v1.4.4/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4SoGjYphSc= -go.mongodb.org/mongo-driver v1.4.6/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4SoGjYphSc= -go.mongodb.org/mongo-driver v1.5.1/go.mod h1:gRXCHX4Jo7J0IJ1oDQyUxF7jfy19UfxniMS4xxMmUqw= -go.mongodb.org/mongo-driver v1.7.3/go.mod h1:NqaYOwnXWr5Pm7AOpO5QFxKJ503nbMse/R79oO62zWg= -go.mongodb.org/mongo-driver v1.7.4 h1:sllcioag8Mec0LYkftYWq+cKNPIR4Kqq3iv9ZXY0g/E= -go.mongodb.org/mongo-driver v1.7.4/go.mod h1:NqaYOwnXWr5Pm7AOpO5QFxKJ503nbMse/R79oO62zWg= go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= @@ -1139,25 +823,17 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1194,21 +870,16 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -1236,7 +907,6 @@ golang.org/x/net v0.0.0-20200505041828-1ed23360d12c/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= @@ -1244,15 +914,12 @@ golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= -golang.org/x/net v0.0.0-20210331060903-cb1fcc7394e5/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211105192438-b53810dc28af h1:SMeNJG/vclJ5wyBBd4xupMsSJIHTd1coW9g7q6KOjmY= @@ -1268,7 +935,6 @@ golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210323180902-22b0adad7558/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= @@ -1280,7 +946,6 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1288,27 +953,21 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181221143128-b4a75ba826a6/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1333,7 +992,6 @@ golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1376,7 +1034,6 @@ golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1414,22 +1071,16 @@ golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= @@ -1437,7 +1088,6 @@ golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20190828213141-aed303cbaa74/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1475,7 +1125,6 @@ golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1640,20 +1289,14 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= -gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= -gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= gopkg.in/h2non/gock.v1 v1.1.2/go.mod h1:n7UGz/ckNChHiK05rDoiC4MYSunEC/lyaUm2WWaDva0= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU= -gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= @@ -1673,8 +1316,6 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= diff --git a/hooks/hooks.go b/hooks/hooks.go index bffa129..e3dcc67 100644 --- a/hooks/hooks.go +++ b/hooks/hooks.go @@ -4,7 +4,6 @@ import ( "context" "github.com/arangodb/go-driver" - "github.com/gin-gonic/gin" "github.com/SecurityBrewery/catalyst/index" ) @@ -44,7 +43,7 @@ func (h *Hooks) TicketWriteFilter(ctx context.Context) (string, map[string]inter return "", nil, nil } -func (h *Hooks) GetGroups(ctx *gin.Context, username string) ([]string, error) { +func (h *Hooks) GetGroups(ctx context.Context, username string) ([]string, error) { if h.GetGroupsFunc != nil { return h.GetGroupsFunc(ctx, username) } diff --git a/index/index.go b/index/index.go index e54bee3..c147ec1 100644 --- a/index/index.go +++ b/index/index.go @@ -8,7 +8,7 @@ import ( "github.com/blevesearch/bleve/v2" - "github.com/SecurityBrewery/catalyst/generated/models" + "github.com/SecurityBrewery/catalyst/generated/model" ) type Index struct { @@ -31,7 +31,7 @@ func New(name string) (*Index, error) { return &Index{name: name, internal: bleveIndex}, nil } -func (i *Index) Index(incidents []*models.TicketSimpleResponse) { +func (i *Index) Index(incidents []*model.TicketSimpleResponse) { b := i.internal.NewBatch() for _, incident := range incidents { if incident.ID == 0 { diff --git a/index/index_test.go b/index/index_test.go index 24fd248..534aa65 100644 --- a/index/index_test.go +++ b/index/index_test.go @@ -4,7 +4,7 @@ import ( "reflect" "testing" - "github.com/SecurityBrewery/catalyst/generated/models" + "github.com/SecurityBrewery/catalyst/generated/model" "github.com/SecurityBrewery/catalyst/test" ) @@ -29,7 +29,7 @@ func TestIndex(t *testing.T) { } defer cleanup() - i.Index([]*models.TicketSimpleResponse{ + i.Index([]*model.TicketSimpleResponse{ {ID: 0, Name: "bar"}, {ID: 1, Name: "foo"}, }) @@ -61,7 +61,7 @@ func TestIndex_Truncate(t *testing.T) { } defer cleanup() - i.Index([]*models.TicketSimpleResponse{ + i.Index([]*model.TicketSimpleResponse{ {ID: 0, Name: "bar"}, {ID: 1, Name: "foo"}, }) diff --git a/restore.go b/restore.go index c906d61..3535ae2 100644 --- a/restore.go +++ b/restore.go @@ -8,7 +8,6 @@ import ( "fmt" "io" "io/fs" - "log" "net/http" "os" "os/exec" @@ -18,31 +17,24 @@ import ( "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/s3" "github.com/aws/aws-sdk-go/service/s3/s3manager" - "github.com/gin-gonic/gin" "github.com/SecurityBrewery/catalyst/database" + "github.com/SecurityBrewery/catalyst/generated/api" "github.com/SecurityBrewery/catalyst/pointer" "github.com/SecurityBrewery/catalyst/storage" ) -func RestoreHandler(catalystStorage *storage.Storage, db *database.Database, c *database.Config) gin.HandlerFunc { - return func(context *gin.Context) { - uf, err := context.FormFile("backup") +func RestoreHandler(catalystStorage *storage.Storage, db *database.Database, c *database.Config) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + uf, header, err := r.FormFile("backup") if err != nil { - log.Println(err) - context.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + api.JSONError(w, err) + return } - f, err := uf.Open() - if err != nil { - log.Println(err) - context.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) - } - defer f.Close() - - if err = Restore(context, catalystStorage, db, c, f, uf.Size); err != nil { - log.Println(err) - context.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + if err = Restore(r.Context(), catalystStorage, db, c, uf, header.Size); err != nil { + api.JSONError(w, err) + return } } } @@ -165,6 +157,7 @@ func arangorestore(dir string, config *database.Config) error { name = database.Name } args := []string{ + "--batch-size", "524288", "--input-directory", dir, "--server.endpoint", host, "--server.username", config.User, "--server.password", config.Password, "--server.database", name, diff --git a/role/role.go b/role/role.go index 46d3d02..c7fc85e 100644 --- a/role/role.go +++ b/role/role.go @@ -5,7 +5,7 @@ import ( "sort" "strings" - "github.com/SecurityBrewery/catalyst/generated/models" + "github.com/SecurityBrewery/catalyst/generated/model" ) type Role string @@ -52,7 +52,7 @@ func (p Role) String() string { return string(p) } -func UserHasRoles(user *models.UserResponse, roles []Role) bool { +func UserHasRoles(user *model.UserResponse, roles []Role) bool { hasRoles := true for _, role := range roles { if !UserHasRole(user, role) { @@ -63,7 +63,7 @@ func UserHasRoles(user *models.UserResponse, roles []Role) bool { return hasRoles } -func UserHasRole(user *models.UserResponse, role Role) bool { +func UserHasRole(user *model.UserResponse, role Role) bool { return ContainsRole(FromStrings(user.Roles), role) } diff --git a/server.go b/server.go index c26eb26..d96d6ef 100644 --- a/server.go +++ b/server.go @@ -2,18 +2,20 @@ package catalyst import ( "context" + "log" + "net/http" "time" - "github.com/gin-contrib/cors" - "github.com/gin-contrib/sessions" - "github.com/gin-contrib/sessions/cookie" + "github.com/go-chi/chi" + "github.com/go-chi/chi/middleware" + "github.com/go-chi/cors" "github.com/SecurityBrewery/catalyst/bus" "github.com/SecurityBrewery/catalyst/busservice" "github.com/SecurityBrewery/catalyst/database" "github.com/SecurityBrewery/catalyst/database/busdb" - "github.com/SecurityBrewery/catalyst/generated/models" - "github.com/SecurityBrewery/catalyst/generated/restapi" + "github.com/SecurityBrewery/catalyst/generated/api" + "github.com/SecurityBrewery/catalyst/generated/model" "github.com/SecurityBrewery/catalyst/hooks" "github.com/SecurityBrewery/catalyst/index" "github.com/SecurityBrewery/catalyst/role" @@ -27,7 +29,7 @@ type Config struct { Storage *storage.Config Bus *bus.Config - UISettings *models.Settings + UISettings *model.Settings Secret []byte Auth *AuthConfig ExternalAddress string @@ -39,7 +41,7 @@ type Server struct { DB *database.Database Index *index.Index Storage *storage.Storage - Server *restapi.Server + Server chi.Router } func New(hooks *hooks.Hooks, config *Config) (*Server, error) { @@ -85,7 +87,7 @@ func New(hooks *hooks.Hooks, config *Config) (*Server, error) { if config.InitialAPIKey != "" { _ = catalystDatabase.UserDelete(ctx, "setup") - ctx = busdb.UserContext(ctx, &models.UserResponse{ + ctx = busdb.UserContext(ctx, &model.UserResponse{ ID: "setup", Roles: role.Strings(role.Explode(role.Admin)), Apikey: false, @@ -111,33 +113,34 @@ func New(hooks *hooks.Hooks, config *Config) (*Server, error) { }, nil } -func setupAPI(catalystService *service.Service, catalystStorage *storage.Storage, catalystDatabase *database.Database, dbConfig *database.Config, bus *bus.Bus, config *Config) (*restapi.Server, error) { - // session - store := cookie.NewStore(config.Secret) - setSession := sessions.Sessions(SessionName, store) - - authenticate := Authenticate(catalystDatabase, config.Auth) - +func setupAPI(catalystService *service.Service, catalystStorage *storage.Storage, catalystDatabase *database.Database, dbConfig *database.Config, bus *bus.Bus, config *Config) (chi.Router, error) { // create server - apiServer := restapi.New(catalystService, &restapi.Config{Address: "0.0.0.0:8000", InsecureHTTP: true}) - apiServer.UseRawPath = true + allowAll := cors.AllowAll().Handler + apiServer := api.NewServer( + catalystService, + AuthorizeRole, + allowAll, Authenticate(catalystDatabase, config.Auth), AuthorizeBlockedUser(), + ) - apiServer.ApiGroup.Use(setSession, authenticate, AuthorizeBlockedUser) - apiServer.RoleAuth = AuthorizeRole + apiServer.With(AuthorizeRole([]string{role.FileReadWrite.String()})).Head("/files/:ticketID/upload/:id", upload(catalystStorage.S3(), config.ExternalAddress)) + apiServer.With(AuthorizeRole([]string{role.FileReadWrite.String()})).Patch("/files/:ticketID/upload/:id", upload(catalystStorage.S3(), config.ExternalAddress)) + apiServer.With(AuthorizeRole([]string{role.FileReadWrite.String()})).Post("/files/:ticketID/upload", upload(catalystStorage.S3(), config.ExternalAddress)) + apiServer.With(AuthorizeRole([]string{role.FileReadWrite.String()})).Get("/files/:ticketID/download/:key", download(catalystStorage.Downloader())) - apiServer.ConfigureRoutes() - apiServer.ApiGroup.HEAD("/files/:ticketID/upload/:id", AuthorizeRole([]role.Role{role.FileReadWrite}), upload(catalystStorage.S3(), config.ExternalAddress)) - apiServer.ApiGroup.PATCH("/files/:ticketID/upload/:id", AuthorizeRole([]role.Role{role.FileReadWrite}), upload(catalystStorage.S3(), config.ExternalAddress)) - apiServer.ApiGroup.POST("/files/:ticketID/upload", AuthorizeRole([]role.Role{role.FileReadWrite}), upload(catalystStorage.S3(), config.ExternalAddress)) - apiServer.ApiGroup.GET("/files/:ticketID/download/:key", AuthorizeRole([]role.Role{role.FileReadWrite}), download(catalystStorage.Downloader())) + apiServer.With(AuthorizeRole([]string{role.BackupRead.String()})).Get("/backup/create", BackupHandler(catalystStorage, dbConfig)) + apiServer.With(AuthorizeRole([]string{role.BackupRestore.String()})).Post("/backup/restore", RestoreHandler(catalystStorage, catalystDatabase, dbConfig)) - apiServer.ApiGroup.GET("/backup/create", AuthorizeRole([]role.Role{role.BackupRead}), BackupHandler(catalystStorage, dbConfig)) - apiServer.ApiGroup.POST("/backup/restore", AuthorizeRole([]role.Role{role.BackupRestore}), RestoreHandler(catalystStorage, catalystDatabase, dbConfig)) + server := chi.NewRouter() + server.Use(middleware.RequestID, middleware.RealIP, middleware.Logger, middleware.Recoverer, allowAll) + server.Mount("/api", apiServer) - apiServer.GET("/callback", setSession, callback(config.Auth)) - apiServer.Any("/wss", setSession, authenticate, AuthorizeBlockedUser, handleWebSocket(bus)) - apiServer.NoRoute(setSession, authenticate, AuthorizeBlockedUser, static) + server.Get("/callback", callback(config.Auth)) + server.With(Authenticate(catalystDatabase, config.Auth), AuthorizeBlockedUser()).Handle("/wss", handleWebSocket(bus)) + // server.With(Authenticate(catalystDatabase, config.Auth), AuthorizeBlockedUser()).NotFound(static) + server.NotFound(func(w http.ResponseWriter, r *http.Request) { + log.Println("not found") + Authenticate(catalystDatabase, config.Auth)(AuthorizeBlockedUser()(http.HandlerFunc(static))).ServeHTTP(w, r) + }) - apiServer.Use(cors.Default()) - return apiServer, nil + return server, nil } diff --git a/service/artifact.go b/service/artifact.go deleted file mode 100644 index 3b4b25f..0000000 --- a/service/artifact.go +++ /dev/null @@ -1,38 +0,0 @@ -package service - -import ( - "context" - - "github.com/google/uuid" - - "github.com/SecurityBrewery/catalyst/generated/models" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" - "github.com/SecurityBrewery/catalyst/generated/restapi/operations/tickets" -) - -func (s *Service) RunArtifact(ctx context.Context, params *tickets.RunArtifactParams) (r *api.Response) { - artifact, err := s.database.ArtifactGet(ctx, params.ID, params.Name) - if err != nil { - return s.response(ctx, "RunArtifact", ticketID(params.ID), nil, err) - } - - jobID := uuid.NewString() - origin := &models.Origin{ArtifactOrigin: &models.ArtifactOrigin{TicketId: params.ID, Artifact: params.Name}} - err = s.bus.PublishJob(jobID, params.Automation, params.Name, &models.Context{Artifact: artifact}, origin) - return s.response(ctx, "RunArtifact", ticketID(params.ID), nil, err) -} - -func (s *Service) EnrichArtifact(ctx context.Context, params *tickets.EnrichArtifactParams) *api.Response { - i, err := s.database.EnrichArtifact(ctx, params.ID, params.Name, params.Data) - return s.response(ctx, "EnrichArtifact", ticketID(params.ID), i, err) -} - -func (s *Service) SetArtifact(ctx context.Context, params *tickets.SetArtifactParams) *api.Response { - i, err := s.database.ArtifactUpdate(ctx, params.ID, params.Name, params.Artifact) - return s.response(ctx, "SetArtifact", ticketID(params.ID), i, err) -} - -func (s *Service) GetArtifact(ctx context.Context, params *tickets.GetArtifactParams) *api.Response { - i, err := s.database.ArtifactGet(ctx, params.ID, params.Name) - return s.response(ctx, "GetArtifact", nil, i, err) -} diff --git a/service/automation.go b/service/automation.go index 6fcd0bc..04e1a01 100644 --- a/service/automation.go +++ b/service/automation.go @@ -7,35 +7,39 @@ import ( "github.com/arangodb/go-driver" "github.com/SecurityBrewery/catalyst/database" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" - "github.com/SecurityBrewery/catalyst/generated/restapi/operations/automations" + "github.com/SecurityBrewery/catalyst/generated/model" ) +func automationResponseID(automation *model.AutomationResponse) []driver.DocumentID { + if automation == nil { + return nil + } + return automationID(automation.ID) +} + func automationID(id string) []driver.DocumentID { return []driver.DocumentID{driver.DocumentID(fmt.Sprintf("%s/%s", database.AutomationCollectionName, id))} } -func (s *Service) CreateAutomation(ctx context.Context, params *automations.CreateAutomationParams) *api.Response { - i, err := s.database.AutomationCreate(ctx, params.Automation) - return s.response(ctx, "CreateAutomation", automationID(i.ID), i, err) +func (s *Service) ListAutomations(ctx context.Context) ([]*model.AutomationResponse, error) { + return s.database.AutomationList(ctx) } -func (s *Service) GetAutomation(ctx context.Context, params *automations.GetAutomationParams) *api.Response { - i, err := s.database.AutomationGet(ctx, params.ID) - return s.response(ctx, "GetAutomation", nil, i, err) +func (s *Service) CreateAutomation(ctx context.Context, form *model.AutomationForm) (doc *model.AutomationResponse, err error) { + defer s.publishRequest(ctx, err, "CreateAutomation", automationResponseID(doc)) + return s.database.AutomationCreate(ctx, form) } -func (s *Service) UpdateAutomation(ctx context.Context, params *automations.UpdateAutomationParams) *api.Response { - i, err := s.database.AutomationUpdate(ctx, params.ID, params.Automation) - return s.response(ctx, "UpdateAutomation", automationID(i.ID), i, err) +func (s *Service) GetAutomation(ctx context.Context, id string) (*model.AutomationResponse, error) { + return s.database.AutomationGet(ctx, id) } -func (s *Service) DeleteAutomation(ctx context.Context, params *automations.DeleteAutomationParams) *api.Response { - err := s.database.AutomationDelete(ctx, params.ID) - return s.response(ctx, "DeleteAutomation", automationID(params.ID), nil, err) +func (s *Service) UpdateAutomation(ctx context.Context, id string, form *model.AutomationForm) (doc *model.AutomationResponse, err error) { + defer s.publishRequest(ctx, err, "UpdateAutomation", automationResponseID(doc)) + return s.database.AutomationUpdate(ctx, id, form) } -func (s *Service) ListAutomations(ctx context.Context) *api.Response { - i, err := s.database.AutomationList(ctx) - return s.response(ctx, "ListAutomations", nil, i, err) +func (s *Service) DeleteAutomation(ctx context.Context, id string) (err error) { + defer s.publishRequest(ctx, err, "DeleteAutomation", automationID(id)) + return s.database.AutomationDelete(ctx, id) } diff --git a/service/job.go b/service/job.go index 3c8e0be..1ec0558 100644 --- a/service/job.go +++ b/service/job.go @@ -8,32 +8,37 @@ import ( "github.com/google/uuid" "github.com/SecurityBrewery/catalyst/database" - "github.com/SecurityBrewery/catalyst/generated/models" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" - "github.com/SecurityBrewery/catalyst/generated/restapi/operations/jobs" + "github.com/SecurityBrewery/catalyst/generated/model" ) +func jobResponseID(job *model.JobResponse) []driver.DocumentID { + if job == nil { + return nil + } + return jobID(job.ID) +} + func jobID(id string) []driver.DocumentID { return []driver.DocumentID{driver.DocumentID(fmt.Sprintf("%s/%s", database.JobCollectionName, id))} } -func (s *Service) RunJob(ctx context.Context, params *jobs.RunJobParams) *api.Response { - msgContext := &models.Context{} +func (s *Service) ListJobs(ctx context.Context) ([]*model.JobResponse, error) { + return s.database.JobList(ctx) +} + +func (s *Service) RunJob(ctx context.Context, form *model.JobForm) (err error) { + msgContext := &model.Context{} newJobID := uuid.NewString() - return s.response(ctx, "RunJob", jobID(newJobID), nil, s.bus.PublishJob(newJobID, params.Job.Automation, params.Job.Payload, msgContext, params.Job.Origin)) + + defer s.publishRequest(ctx, err, "RunJob", jobID(newJobID)) + return s.bus.PublishJob(newJobID, form.Automation, form.Payload, msgContext, form.Origin) } -func (s *Service) GetJob(ctx context.Context, params *jobs.GetJobParams) *api.Response { - i, err := s.database.JobGet(ctx, params.ID) - return s.response(ctx, "GetJob", nil, i, err) +func (s *Service) GetJob(ctx context.Context, id string) (*model.JobResponse, error) { + return s.database.JobGet(ctx, id) } -func (s *Service) ListJobs(ctx context.Context) *api.Response { - i, err := s.database.JobList(ctx) - return s.response(ctx, "ListJobs", nil, i, err) -} - -func (s *Service) UpdateJob(ctx context.Context, params *jobs.UpdateJobParams) *api.Response { - i, err := s.database.JobUpdate(ctx, params.ID, params.Job) - return s.response(ctx, "UpdateJob", jobID(i.ID), i, err) +func (s *Service) UpdateJob(ctx context.Context, id string, job *model.Job) (doc *model.JobResponse, err error) { + defer s.publishRequest(ctx, err, "UpdateJob", jobResponseID(doc)) + return s.database.JobUpdate(ctx, id, job) } diff --git a/service/log.go b/service/log.go index d8d34cd..93364c2 100644 --- a/service/log.go +++ b/service/log.go @@ -4,12 +4,10 @@ import ( "context" "net/url" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" - "github.com/SecurityBrewery/catalyst/generated/restapi/operations/logs" + "github.com/SecurityBrewery/catalyst/generated/model" ) -func (s *Service) GetLogs(ctx context.Context, params *logs.GetLogsParams) *api.Response { - id, _ := url.QueryUnescape(params.Reference) - i, err := s.database.LogList(ctx, id) - return s.response(ctx, "GetLogs", nil, i, err) +func (s *Service) GetLogs(ctx context.Context, reference string) ([]*model.LogEntry, error) { + id, _ := url.QueryUnescape(reference) + return s.database.LogList(ctx, id) } diff --git a/service/playbook.go b/service/playbook.go index 550f5d0..378f092 100644 --- a/service/playbook.go +++ b/service/playbook.go @@ -3,62 +3,43 @@ package service import ( "context" "fmt" - "strings" "github.com/arangodb/go-driver" - "github.com/xeipuuv/gojsonschema" "github.com/SecurityBrewery/catalyst/database" - "github.com/SecurityBrewery/catalyst/generated/models" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" - "github.com/SecurityBrewery/catalyst/generated/restapi/operations/playbooks" + "github.com/SecurityBrewery/catalyst/generated/model" ) +func playbookResponseID(playbook *model.PlaybookTemplateResponse) []driver.DocumentID { + if playbook == nil { + return nil + } + return playbookID(playbook.ID) +} + func playbookID(id string) []driver.DocumentID { return []driver.DocumentID{driver.DocumentID(fmt.Sprintf("%s/%s", database.PlaybookCollectionName, id))} } -func (s *Service) CreatePlaybook(ctx context.Context, params *playbooks.CreatePlaybookParams) *api.Response { - i, err := s.database.PlaybookCreate(ctx, params.Playbook) - return s.response(ctx, "CreatePlaybook", playbookID(i.ID), i, err) +func (s *Service) ListPlaybooks(ctx context.Context) ([]*model.PlaybookTemplateResponse, error) { + return s.database.PlaybookList(ctx) } -func (s *Service) GetPlaybook(ctx context.Context, params *playbooks.GetPlaybookParams) *api.Response { - i, err := s.database.PlaybookGet(ctx, params.ID) - return s.response(ctx, "GetPlaybook", nil, i, err) +func (s *Service) CreatePlaybook(ctx context.Context, form *model.PlaybookTemplateForm) (doc *model.PlaybookTemplateResponse, err error) { + defer s.publishRequest(ctx, err, "CreatePlaybook", playbookResponseID(doc)) + return s.database.PlaybookCreate(ctx, form) } -func (s *Service) UpdatePlaybook(ctx context.Context, params *playbooks.UpdatePlaybookParams) *api.Response { - if err := validate(params.Playbook, models.PlaybookTemplateFormSchema); err != nil { - return s.response(ctx, "UpdatePlaybook", nil, nil, err) - } - - i, err := s.database.PlaybookUpdate(ctx, params.ID, params.Playbook) - return s.response(ctx, "UpdatePlaybook", playbookID(i.ID), i, err) +func (s *Service) GetPlaybook(ctx context.Context, id string) (*model.PlaybookTemplateResponse, error) { + return s.database.PlaybookGet(ctx, id) } -func (s *Service) DeletePlaybook(ctx context.Context, params *playbooks.DeletePlaybookParams) *api.Response { - err := s.database.PlaybookDelete(ctx, params.ID) - return s.response(ctx, "DeletePlaybook", playbookID(params.ID), nil, err) +func (s *Service) UpdatePlaybook(ctx context.Context, id string, form *model.PlaybookTemplateForm) (doc *model.PlaybookTemplateResponse, err error) { + defer s.publishRequest(ctx, err, "UpdatePlaybook", playbookResponseID(doc)) + return s.database.PlaybookUpdate(ctx, id, form) } -func (s *Service) ListPlaybooks(ctx context.Context) *api.Response { - i, err := s.database.PlaybookList(ctx) - return s.response(ctx, "ListPlaybooks", nil, i, err) -} - -func validate(e interface{}, schema *gojsonschema.Schema) error { - res, err := schema.Validate(gojsonschema.NewGoLoader(e)) - if err != nil { - return err - } - - if len(res.Errors()) > 0 { - var l []string - for _, e := range res.Errors() { - l = append(l, e.String()) - } - return fmt.Errorf("validation failed: %v", strings.Join(l, ", ")) - } - return nil +func (s *Service) DeletePlaybook(ctx context.Context, id string) (err error) { + defer s.publishRequest(ctx, err, "DeletePlaybook", playbookID(id)) + return s.database.PlaybookDelete(ctx, id) } diff --git a/service/service.go b/service/service.go index 9f45da2..e93ed9c 100644 --- a/service/service.go +++ b/service/service.go @@ -2,42 +2,31 @@ package service import ( "context" - "errors" - "log" - "net/http" "github.com/arangodb/go-driver" - "github.com/gin-gonic/gin" "github.com/SecurityBrewery/catalyst/bus" "github.com/SecurityBrewery/catalyst/database" "github.com/SecurityBrewery/catalyst/database/busdb" - "github.com/SecurityBrewery/catalyst/generated/models" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" + "github.com/SecurityBrewery/catalyst/generated/model" "github.com/SecurityBrewery/catalyst/storage" ) type Service struct { bus *bus.Bus database *database.Database - settings *models.Settings + settings *model.Settings storage *storage.Storage } -func New(bus *bus.Bus, database *database.Database, storage *storage.Storage, settings *models.Settings) (*Service, error) { +func New(bus *bus.Bus, database *database.Database, storage *storage.Storage, settings *model.Settings) (*Service, error) { return &Service{database: database, bus: bus, settings: settings, storage: storage}, nil } -func (s *Service) Healthy() bool { - return true -} - -func (s *Service) response(ctx context.Context, function string, ids []driver.DocumentID, v interface{}, err error) *api.Response { +func (s *Service) publishRequest(ctx context.Context, err error, function string, ids []driver.DocumentID) { if err != nil { - log.Println(err) - return &api.Response{Code: httpStatus(err), Body: gin.H{"error": err.Error()}} + return } - if ids != nil { userID := "unknown" user, ok := busdb.UserFromContext(ctx) @@ -47,18 +36,4 @@ func (s *Service) response(ctx context.Context, function string, ids []driver.Do go s.bus.PublishRequest(userID, function, ids) } - - if v == nil { - return &api.Response{Code: http.StatusNoContent, Body: v} - } - return &api.Response{Code: http.StatusOK, Body: v} -} - -func httpStatus(err error) int { - ae := driver.ArangoError{} - if errors.As(err, &ae) { - return ae.Code - } - - return http.StatusInternalServerError } diff --git a/service/statistics.go b/service/statistics.go index 248e233..c9a2449 100644 --- a/service/statistics.go +++ b/service/statistics.go @@ -3,10 +3,9 @@ package service import ( "context" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" + "github.com/SecurityBrewery/catalyst/generated/model" ) -func (s *Service) GetStatistics(ctx context.Context) *api.Response { - i, err := s.database.Statistics(ctx) - return s.response(ctx, "GetStatistics", nil, i, err) +func (s *Service) GetStatistics(ctx context.Context) (*model.Statistics, error) { + return s.database.Statistics(ctx) } diff --git a/service/task.go b/service/task.go index 52a2155..5935ea4 100644 --- a/service/task.go +++ b/service/task.go @@ -3,10 +3,9 @@ package service import ( "context" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" + "github.com/SecurityBrewery/catalyst/generated/model" ) -func (s *Service) ListTasks(ctx context.Context) *api.Response { - i, err := s.database.TaskList(ctx) - return s.response(ctx, "ListTasks", nil, i, err) +func (s *Service) ListTasks(ctx context.Context) ([]*model.TaskWithContext, error) { + return s.database.TaskList(ctx) } diff --git a/service/template.go b/service/template.go index 7e2fff6..c90457b 100644 --- a/service/template.go +++ b/service/template.go @@ -7,35 +7,39 @@ import ( "github.com/arangodb/go-driver" "github.com/SecurityBrewery/catalyst/database" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" - "github.com/SecurityBrewery/catalyst/generated/restapi/operations/templates" + "github.com/SecurityBrewery/catalyst/generated/model" ) -func templateID(s string) []driver.DocumentID { - return []driver.DocumentID{driver.DocumentID(fmt.Sprintf("%s/%s", database.TemplateCollectionName, s))} +func templateResponseID(template *model.TicketTemplateResponse) []driver.DocumentID { + if template == nil { + return nil + } + return templateID(template.ID) } -func (s *Service) CreateTemplate(ctx context.Context, params *templates.CreateTemplateParams) *api.Response { - i, err := s.database.TemplateCreate(ctx, params.Template) - return s.response(ctx, "CreateTemplate", templateID(i.ID), i, err) +func templateID(id string) []driver.DocumentID { + return []driver.DocumentID{driver.DocumentID(fmt.Sprintf("%s/%s", database.TemplateCollectionName, id))} } -func (s *Service) GetTemplate(ctx context.Context, params *templates.GetTemplateParams) *api.Response { - i, err := s.database.TemplateGet(ctx, params.ID) - return s.response(ctx, "GetTemplate", nil, i, err) +func (s *Service) ListTemplates(ctx context.Context) ([]*model.TicketTemplateResponse, error) { + return s.database.TemplateList(ctx) } -func (s *Service) UpdateTemplate(ctx context.Context, params *templates.UpdateTemplateParams) *api.Response { - i, err := s.database.TemplateUpdate(ctx, params.ID, params.Template) - return s.response(ctx, "UpdateTemplate", templateID(i.ID), i, err) +func (s *Service) CreateTemplate(ctx context.Context, form *model.TicketTemplateForm) (doc *model.TicketTemplateResponse, err error) { + defer s.publishRequest(ctx, err, "CreateTemplate", templateResponseID(doc)) + return s.database.TemplateCreate(ctx, form) } -func (s *Service) DeleteTemplate(ctx context.Context, params *templates.DeleteTemplateParams) *api.Response { - err := s.database.TemplateDelete(ctx, params.ID) - return s.response(ctx, "DeleteTemplate", templateID(params.ID), nil, err) +func (s *Service) GetTemplate(ctx context.Context, id string) (*model.TicketTemplateResponse, error) { + return s.database.TemplateGet(ctx, id) } -func (s *Service) ListTemplates(ctx context.Context) *api.Response { - i, err := s.database.TemplateList(ctx) - return s.response(ctx, "ListTemplates", nil, i, err) +func (s *Service) UpdateTemplate(ctx context.Context, id string, form *model.TicketTemplateForm) (doc *model.TicketTemplateResponse, err error) { + defer s.publishRequest(ctx, err, "UpdateTemplate", templateResponseID(doc)) + return s.database.TemplateUpdate(ctx, id, form) +} + +func (s *Service) DeleteTemplate(ctx context.Context, id string) (err error) { + defer s.publishRequest(ctx, err, "DeleteTemplate", templateID(id)) + return s.database.TemplateDelete(ctx, id) } diff --git a/service/ticket.go b/service/ticket.go index 9a8623a..1bc06c5 100644 --- a/service/ticket.go +++ b/service/ticket.go @@ -5,18 +5,25 @@ import ( "fmt" "github.com/arangodb/go-driver" + "github.com/google/uuid" "github.com/SecurityBrewery/catalyst/database" - "github.com/SecurityBrewery/catalyst/generated/models" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" - "github.com/SecurityBrewery/catalyst/generated/restapi/operations/tickets" + "github.com/SecurityBrewery/catalyst/generated/model" ) -func ticketID(id int64) []driver.DocumentID { - return []driver.DocumentID{driver.DocumentID(fmt.Sprintf("%s/%d", database.TicketCollectionName, id))} +func ticketWithTicketsID(ticketResponse *model.TicketWithTickets) []driver.DocumentID { + if ticketResponse == nil { + return nil + } + return ticketID(ticketResponse.ID) } -func ticketIDs(ticketResponses []*models.TicketResponse) []driver.DocumentID { +func ticketID(ticketID int64) []driver.DocumentID { + id := fmt.Sprintf("%s/%d", database.TicketCollectionName, ticketID) + return []driver.DocumentID{driver.DocumentID(id)} +} + +func ticketIDs(ticketResponses []*model.TicketResponse) []driver.DocumentID { var ids []driver.DocumentID for _, ticketResponse := range ticketResponses { ids = append(ids, ticketID(ticketResponse.ID)...) @@ -24,48 +31,161 @@ func ticketIDs(ticketResponses []*models.TicketResponse) []driver.DocumentID { return ids } -func (s *Service) CreateTicket(ctx context.Context, params *tickets.CreateTicketParams) *api.Response { - createdTickets, err := s.database.TicketBatchCreate(ctx, []*models.TicketForm{params.Ticket}) - if len(createdTickets) > 0 { - return s.response(ctx, "CreateTicket", ticketIDs(createdTickets), createdTickets[0], err) - } - return s.response(ctx, "CreateTicket", ticketIDs(createdTickets), nil, err) -} - -func (s *Service) CreateTicketBatch(ctx context.Context, params *tickets.CreateTicketBatchParams) *api.Response { - ticketBatch, err := s.database.TicketBatchCreate(ctx, params.Ticket) - return s.response(ctx, "CreateTicketBatch", ticketIDs(ticketBatch), nil, err) -} - -func (s *Service) GetTicket(ctx context.Context, params *tickets.GetTicketParams) *api.Response { - ticket, err := s.database.TicketGet(ctx, params.ID) - return s.response(ctx, "GetTicket", nil, ticket, err) -} - -func (s *Service) UpdateTicket(ctx context.Context, params *tickets.UpdateTicketParams) *api.Response { - ticket, err := s.database.TicketUpdate(ctx, params.ID, params.Ticket) - return s.response(ctx, "UpdateTicket", ticketID(ticket.ID), ticket, err) -} - -func (s *Service) DeleteTicket(ctx context.Context, params *tickets.DeleteTicketParams) *api.Response { - if err := s.database.TicketDelete(ctx, params.ID); err != nil { - return s.response(ctx, "DeleteTicket", ticketID(params.ID), nil, err) - } - - _ = s.storage.DeleteBucket(fmt.Sprint(params.ID)) - return s.response(ctx, "DeleteTicket", ticketID(params.ID), nil, nil) -} - -func (s *Service) ListTickets(ctx context.Context, params *tickets.ListTicketsParams) *api.Response { +func (s *Service) ListTickets(ctx context.Context, s3 *string, i *int, i2 *int, strings []string, bools []bool, s2 *string) (*model.TicketList, error) { q := "" - if params.Query != nil && *params.Query != "" { - q = *params.Query + if s2 != nil && *s2 != "" { + q = *s2 } t := "" - if params.Type != nil && *params.Type != "" { - t = *params.Type + if s3 != nil && *s3 != "" { + t = *s3 } - ticketList, err := s.database.TicketList(ctx, t, q, params.Sort, params.Desc, *params.Offset, *params.Count) - return s.response(ctx, "ListTickets", nil, ticketList, err) + offset := int64(0) + if i != nil { + offset = int64(*i) + } + + count := int64(25) + if i2 != nil { + count = int64(*i2) + } + + return s.database.TicketList(ctx, t, q, strings, bools, offset, count) +} + +func (s *Service) CreateTicket(ctx context.Context, form *model.TicketForm) (doc *model.TicketResponse, err error) { + createdTickets, err := s.database.TicketBatchCreate(ctx, []*model.TicketForm{form}) + defer s.publishRequest(ctx, err, "CreateTicket", ticketIDs(createdTickets)) + if len(createdTickets) > 0 { + return createdTickets[0], err + } + return nil, err +} + +func (s *Service) CreateTicketBatch(ctx context.Context, forms []*model.TicketForm) error { + createdTickets, err := s.database.TicketBatchCreate(ctx, forms) + defer s.publishRequest(ctx, err, "CreateTicket", ticketIDs(createdTickets)) + return err +} + +func (s *Service) GetTicket(ctx context.Context, i int64) (*model.TicketWithTickets, error) { + return s.database.TicketGet(ctx, i) +} + +func (s *Service) UpdateTicket(ctx context.Context, i int64, ticket *model.Ticket) (doc *model.TicketWithTickets, err error) { + defer s.publishRequest(ctx, err, "UpdateTicket", ticketWithTicketsID(doc)) + return s.database.TicketUpdate(ctx, i, ticket) +} + +func (s *Service) DeleteTicket(ctx context.Context, i int64) (err error) { + defer s.publishRequest(ctx, err, "DeleteTicket", ticketID(i)) + return s.database.TicketDelete(ctx, i) +} + +func (s *Service) AddArtifact(ctx context.Context, i int64, artifact *model.Artifact) (doc *model.TicketWithTickets, err error) { + defer s.publishRequest(ctx, err, "AddArtifact", ticketWithTicketsID(doc)) + return s.database.AddArtifact(ctx, i, artifact) +} + +func (s *Service) GetArtifact(ctx context.Context, i int64, s2 string) (*model.Artifact, error) { + return s.database.ArtifactGet(ctx, i, s2) +} + +func (s *Service) SetArtifact(ctx context.Context, i int64, s2 string, artifact *model.Artifact) (doc *model.TicketWithTickets, err error) { + defer s.publishRequest(ctx, err, "SetArtifact", ticketWithTicketsID(doc)) + return s.database.ArtifactUpdate(ctx, i, s2, artifact) +} + +func (s *Service) RemoveArtifact(ctx context.Context, i int64, s2 string) (doc *model.TicketWithTickets, err error) { + defer s.publishRequest(ctx, err, "RemoveArtifact", ticketWithTicketsID(doc)) + return s.database.RemoveArtifact(ctx, i, s2) +} + +func (s *Service) EnrichArtifact(ctx context.Context, i int64, s2 string, form *model.EnrichmentForm) (doc *model.TicketWithTickets, err error) { + defer s.publishRequest(ctx, err, "EnrichArtifact", ticketWithTicketsID(doc)) + return s.database.EnrichArtifact(ctx, i, s2, form) +} + +func (s *Service) RunArtifact(ctx context.Context, id int64, name string, automation string) error { + artifact, err := s.database.ArtifactGet(ctx, id, name) + if err != nil { + return err + } + + defer s.publishRequest(ctx, err, "RunArtifact", ticketID(id)) + + jobID := uuid.NewString() + origin := &model.Origin{ArtifactOrigin: &model.ArtifactOrigin{TicketId: id, Artifact: name}} + return s.bus.PublishJob(jobID, automation, name, &model.Context{Artifact: artifact}, origin) +} + +func (s *Service) AddComment(ctx context.Context, i int64, form *model.CommentForm) (doc *model.TicketWithTickets, err error) { + defer s.publishRequest(ctx, err, "AddComment", ticketWithTicketsID(doc)) + return s.database.AddComment(ctx, i, form) +} + +func (s *Service) RemoveComment(ctx context.Context, i int64, i2 int) (doc *model.TicketWithTickets, err error) { + defer s.publishRequest(ctx, err, "RemoveComment", ticketWithTicketsID(doc)) + return s.database.RemoveComment(ctx, i, int64(i2)) +} + +func (s *Service) LinkFiles(ctx context.Context, i int64, files []*model.File) (doc *model.TicketWithTickets, err error) { + defer s.publishRequest(ctx, err, "LinkFiles", ticketWithTicketsID(doc)) + return s.database.LinkFiles(ctx, i, files) +} + +func (s *Service) AddTicketPlaybook(ctx context.Context, i int64, form *model.PlaybookTemplateForm) (doc *model.TicketWithTickets, err error) { + defer s.publishRequest(ctx, err, "AddTicketPlaybook", ticketWithTicketsID(doc)) + return s.database.AddTicketPlaybook(ctx, i, form) +} + +func (s *Service) RemoveTicketPlaybook(ctx context.Context, i int64, s2 string) (doc *model.TicketWithTickets, err error) { + defer s.publishRequest(ctx, err, "RemoveTicketPlaybook", ticketWithTicketsID(doc)) + return s.database.RemoveTicketPlaybook(ctx, i, s2) +} + +func (s *Service) SetTask(ctx context.Context, i int64, s3 string, s2 string, task *model.Task) (doc *model.TicketWithTickets, err error) { + defer s.publishRequest(ctx, err, "SetTask", ticketWithTicketsID(doc)) + return s.database.TaskUpdate(ctx, i, s3, s2, task) +} + +func (s *Service) CompleteTask(ctx context.Context, i int64, s3 string, s2 string, m map[string]interface{}) (doc *model.TicketWithTickets, err error) { + defer s.publishRequest(ctx, err, "CompleteTask", ticketWithTicketsID(doc)) + return s.database.TaskComplete(ctx, i, s3, s2, m) +} + +func (s *Service) RunTask(ctx context.Context, i int64, s3 string, s2 string) (err error) { + defer s.publishRequest(ctx, err, "RunTask", ticketID(i)) + return s.database.TaskRun(ctx, i, s3, s2) +} + +func (s *Service) SetReferences(ctx context.Context, i int64, references []*model.Reference) (doc *model.TicketWithTickets, err error) { + defer s.publishRequest(ctx, err, "SetReferences", ticketID(i)) + return s.database.SetReferences(ctx, i, references) +} + +func (s *Service) SetSchema(ctx context.Context, i int64, s2 string) (doc *model.TicketWithTickets, err error) { + defer s.publishRequest(ctx, err, "SetSchema", ticketID(i)) + return s.database.SetTemplate(ctx, i, s2) +} + +func (s *Service) LinkTicket(ctx context.Context, i int64, i2 int64) (*model.TicketWithTickets, error) { + err := s.database.RelatedCreate(ctx, i, i2) + if err != nil { + return nil, err + } + defer s.publishRequest(ctx, err, "LinkTicket", ticketID(i)) + + return s.GetTicket(ctx, i) +} + +func (s *Service) UnlinkTicket(ctx context.Context, i int64, i2 int64) (*model.TicketWithTickets, error) { + err := s.database.RelatedRemove(ctx, i, i2) + if err != nil { + return nil, err + } + defer s.publishRequest(ctx, err, "UnlinkTicket", ticketID(i)) + + return s.GetTicket(ctx, i) } diff --git a/service/ticket_field.go b/service/ticket_field.go deleted file mode 100644 index aa6cd4b..0000000 --- a/service/ticket_field.go +++ /dev/null @@ -1,88 +0,0 @@ -package service - -import ( - "context" - - "github.com/SecurityBrewery/catalyst/generated/restapi/api" - "github.com/SecurityBrewery/catalyst/generated/restapi/operations/tickets" -) - -func (s *Service) AddArtifact(ctx context.Context, params *tickets.AddArtifactParams) *api.Response { - i, err := s.database.AddArtifact(ctx, params.ID, params.Artifact) - return s.response(ctx, "AddArtifact", ticketID(params.ID), i, err) -} - -func (s *Service) RemoveArtifact(ctx context.Context, params *tickets.RemoveArtifactParams) *api.Response { - i, err := s.database.RemoveArtifact(ctx, params.ID, params.Name) - return s.response(ctx, "RemoveArtifact", ticketID(params.ID), i, err) -} - -func (s *Service) SetSchema(ctx context.Context, params *tickets.SetSchemaParams) *api.Response { - i, err := s.database.SetTemplate(ctx, params.ID, params.Schema) - return s.response(ctx, "SetSchema", ticketID(params.ID), i, err) -} - -func (s *Service) AddComment(ctx context.Context, params *tickets.AddCommentParams) *api.Response { - i, err := s.database.AddComment(ctx, params.ID, params.Comment) - return s.response(ctx, "AddComment", ticketID(params.ID), i, err) -} - -func (s *Service) RemoveComment(ctx context.Context, params *tickets.RemoveCommentParams) *api.Response { - i, err := s.database.RemoveComment(ctx, params.ID, params.CommentID) - return s.response(ctx, "RemoveComment", ticketID(params.ID), i, err) -} - -func (s *Service) LinkTicket(ctx context.Context, params *tickets.LinkTicketParams) *api.Response { - err := s.database.RelatedCreate(ctx, params.ID, params.LinkedID) - if err != nil { - return s.response(ctx, "LinkTicket", ticketID(params.ID), nil, err) - } - - i, err := s.database.TicketGet(ctx, params.ID) - return s.response(ctx, "LinkTicket", ticketID(params.ID), i, err) -} - -func (s *Service) UnlinkTicket(ctx context.Context, params *tickets.UnlinkTicketParams) *api.Response { - err := s.database.RelatedRemove(ctx, params.ID, params.LinkedID) - if err != nil { - return s.response(ctx, "UnlinkTicket", ticketID(params.ID), nil, err) - } - - i, err := s.database.TicketGet(ctx, params.ID) - return s.response(ctx, "UnlinkTicket", ticketID(params.ID), i, err) -} - -func (s Service) SetReferences(ctx context.Context, params *tickets.SetReferencesParams) *api.Response { - i, err := s.database.SetReferences(ctx, params.ID, params.References) - return s.response(ctx, "SetReferences", ticketID(params.ID), i, err) -} - -func (s Service) LinkFiles(ctx context.Context, params *tickets.LinkFilesParams) *api.Response { - i, err := s.database.LinkFiles(ctx, params.ID, params.Files) - return s.response(ctx, "LinkFiles", ticketID(params.ID), i, err) -} - -func (s Service) AddTicketPlaybook(ctx context.Context, params *tickets.AddTicketPlaybookParams) *api.Response { - i, err := s.database.AddTicketPlaybook(ctx, params.ID, params.Playbook) - return s.response(ctx, "AddTicketPlaybook", ticketID(params.ID), i, err) -} - -func (s Service) RemoveTicketPlaybook(ctx context.Context, params *tickets.RemoveTicketPlaybookParams) *api.Response { - i, err := s.database.RemoveTicketPlaybook(ctx, params.ID, params.PlaybookID) - return s.response(ctx, "RemoveTicketPlaybook", ticketID(params.ID), i, err) -} - -func (s Service) CompleteTask(ctx context.Context, params *tickets.CompleteTaskParams) *api.Response { - i, err := s.database.TaskComplete(ctx, params.ID, params.PlaybookID, params.TaskID, params.Data) - return s.response(ctx, "CompleteTask", ticketID(params.ID), i, err) -} - -func (s Service) SetTask(ctx context.Context, params *tickets.SetTaskParams) *api.Response { - i, err := s.database.TaskUpdate(ctx, params.ID, params.PlaybookID, params.TaskID, params.Task) - return s.response(ctx, "SetTask", ticketID(params.ID), i, err) -} - -func (s *Service) RunTask(ctx context.Context, params *tickets.RunTaskParams) *api.Response { - err := s.database.TaskRun(ctx, params.ID, params.PlaybookID, params.TaskID) - return s.response(ctx, "RunTask", ticketID(params.ID), nil, err) -} diff --git a/service/tickettype.go b/service/tickettype.go index 84a34f5..e80e0aa 100644 --- a/service/tickettype.go +++ b/service/tickettype.go @@ -7,35 +7,39 @@ import ( "github.com/arangodb/go-driver" "github.com/SecurityBrewery/catalyst/database" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" - "github.com/SecurityBrewery/catalyst/generated/restapi/operations/tickettypes" + "github.com/SecurityBrewery/catalyst/generated/model" ) +func ticketTypeResponseID(ticketType *model.TicketTypeResponse) []driver.DocumentID { + if ticketType == nil { + return nil + } + return userDataID(ticketType.ID) +} + func ticketTypeID(id string) []driver.DocumentID { - return []driver.DocumentID{driver.DocumentID(fmt.Sprintf("%s/%s", database.TicketTypeCollectionName, id))} + return []driver.DocumentID{driver.DocumentID(fmt.Sprintf("%s/%s", database.UserDataCollectionName, id))} } -func (s *Service) CreateTicketType(ctx context.Context, params *tickettypes.CreateTicketTypeParams) *api.Response { - ticketType, err := s.database.TicketTypeCreate(ctx, params.Tickettype) - return s.response(ctx, "CreateTicketType", ticketTypeID(ticketType.ID), ticketType, err) +func (s *Service) ListTicketTypes(ctx context.Context) ([]*model.TicketTypeResponse, error) { + return s.database.TicketTypeList(ctx) } -func (s *Service) GetTicketType(ctx context.Context, params *tickettypes.GetTicketTypeParams) *api.Response { - ticketType, err := s.database.TicketTypeGet(ctx, params.ID) - return s.response(ctx, "GetTicketType", nil, ticketType, err) +func (s *Service) CreateTicketType(ctx context.Context, form *model.TicketTypeForm) (doc *model.TicketTypeResponse, err error) { + defer s.publishRequest(ctx, err, "CreateTicketType", ticketTypeResponseID(doc)) + return s.database.TicketTypeCreate(ctx, form) } -func (s *Service) UpdateTicketType(ctx context.Context, params *tickettypes.UpdateTicketTypeParams) *api.Response { - ticketType, err := s.database.TicketTypeUpdate(ctx, params.ID, params.Tickettype) - return s.response(ctx, "UpdateTicketType", ticketTypeID(ticketType.ID), ticketType, err) +func (s *Service) GetTicketType(ctx context.Context, id string) (*model.TicketTypeResponse, error) { + return s.database.TicketTypeGet(ctx, id) } -func (s *Service) DeleteTicketType(ctx context.Context, params *tickettypes.DeleteTicketTypeParams) *api.Response { - err := s.database.TicketTypeDelete(ctx, params.ID) - return s.response(ctx, "DeleteTicketType", ticketTypeID(params.ID), nil, err) +func (s *Service) UpdateTicketType(ctx context.Context, id string, form *model.TicketTypeForm) (doc *model.TicketTypeResponse, err error) { + defer s.publishRequest(ctx, err, "UpdateTicketType", ticketTypeResponseID(doc)) + return s.database.TicketTypeUpdate(ctx, id, form) } -func (s *Service) ListTicketTypes(ctx context.Context) *api.Response { - ticketTypes, err := s.database.TicketTypeList(ctx) - return s.response(ctx, "ListTicketTypes", nil, ticketTypes, err) +func (s *Service) DeleteTicketType(ctx context.Context, id string) (err error) { + defer s.publishRequest(ctx, err, "DeleteTicketType", ticketTypeID(id)) + return s.database.TicketTypeDelete(ctx, id) } diff --git a/service/uisettings.go b/service/uisettings.go index b7b5b92..2ea6fd8 100644 --- a/service/uisettings.go +++ b/service/uisettings.go @@ -6,35 +6,34 @@ import ( "sort" "github.com/SecurityBrewery/catalyst/database/busdb" - "github.com/SecurityBrewery/catalyst/generated/models" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" + "github.com/SecurityBrewery/catalyst/generated/model" "github.com/SecurityBrewery/catalyst/role" ) -func (s *Service) GetSettings(ctx context.Context) *api.Response { +func (s *Service) GetSettings(ctx context.Context) (*model.Settings, error) { user, ok := busdb.UserFromContext(ctx) if !ok { - return s.response(ctx, "GetSettings", nil, nil, errors.New("no user in context")) + return nil, errors.New("no user in context") } setting, err := s.database.UserDataGet(ctx, user.ID) if err != nil { - return s.response(ctx, "GetSettings", nil, nil, err) + return nil, err } settings := mergeSettings(s.settings, setting) ticketTypeList, err := s.database.TicketTypeList(ctx) if err != nil { - return s.response(ctx, "GetSettings", nil, nil, err) + return nil, err } settings.TicketTypes = ticketTypeList - return s.response(ctx, "GetSettings", nil, settings, nil) + return settings, nil } -func mergeSettings(globalSettings *models.Settings, user *models.UserDataResponse) *models.Settings { +func mergeSettings(globalSettings *model.Settings, user *model.UserDataResponse) *model.Settings { if user.Timeformat != nil { globalSettings.Timeformat = *user.Timeformat } diff --git a/service/user.go b/service/user.go index c99fda7..f5c6374 100644 --- a/service/user.go +++ b/service/user.go @@ -9,43 +9,55 @@ import ( "github.com/SecurityBrewery/catalyst/database" "github.com/SecurityBrewery/catalyst/database/busdb" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" - "github.com/SecurityBrewery/catalyst/generated/restapi/operations/users" + "github.com/SecurityBrewery/catalyst/generated/model" ) +func newUserResponseID(user *model.NewUserResponse) []driver.DocumentID { + if user == nil { + return nil + } + return userID(user.ID) +} + +func userResponseID(user *model.UserResponse) []driver.DocumentID { + if user == nil { + return nil + } + return userID(user.ID) +} + func userID(id string) []driver.DocumentID { return []driver.DocumentID{driver.DocumentID(fmt.Sprintf("%s/%s", database.UserCollectionName, id))} } -func (s *Service) GetUser(ctx context.Context, params *users.GetUserParams) *api.Response { - i, err := s.database.UserGet(ctx, params.ID) - return s.response(ctx, "GetUser", nil, i, err) +func (s *Service) ListUsers(ctx context.Context) ([]*model.UserResponse, error) { + return s.database.UserList(ctx) } -func (s *Service) ListUsers(ctx context.Context) *api.Response { - i, err := s.database.UserList(ctx) - return s.response(ctx, "ListUsers", nil, i, err) +func (s *Service) CreateUser(ctx context.Context, form *model.UserForm) (doc *model.NewUserResponse, err error) { + defer s.publishRequest(ctx, err, "CreateUser", newUserResponseID(doc)) + return s.database.UserCreate(ctx, form) } -func (s *Service) CreateUser(ctx context.Context, params *users.CreateUserParams) *api.Response { - i, err := s.database.UserCreate(ctx, params.User) - return s.response(ctx, "CreateUser", userID(i.ID), i, err) +func (s *Service) GetUser(ctx context.Context, s2 string) (*model.UserResponse, error) { + return s.database.UserGet(ctx, s2) } -func (s *Service) DeleteUser(ctx context.Context, params *users.DeleteUserParams) *api.Response { - err := s.database.UserDelete(ctx, params.ID) - return s.response(ctx, "DeleteUser", userID(params.ID), nil, err) +func (s *Service) UpdateUser(ctx context.Context, s2 string, form *model.UserForm) (doc *model.UserResponse, err error) { + defer s.publishRequest(ctx, err, "UpdateUser", userID(s2)) + return s.database.UserUpdate(ctx, s2, form) } -func (s *Service) CurrentUser(ctx context.Context) *api.Response { +func (s *Service) DeleteUser(ctx context.Context, s2 string) (err error) { + defer s.publishRequest(ctx, err, "DeleteUser", userID(s2)) + return s.database.UserDelete(ctx, s2) +} + +func (s *Service) CurrentUser(ctx context.Context) (*model.UserResponse, error) { user, ok := busdb.UserFromContext(ctx) if !ok { - return s.response(ctx, "CurrentUser", nil, nil, errors.New("no user in context")) + return nil, errors.New("no user in context") } - return s.response(ctx, "CurrentUser", nil, user, nil) -} - -func (s *Service) UpdateUser(ctx context.Context, params *users.UpdateUserParams) *api.Response { - i, err := s.database.UserUpdate(ctx, params.ID, params.User) - return s.response(ctx, "UpdateUser", userID(i.ID), i, err) + s.publishRequest(ctx, nil, "CurrentUser", userResponseID(user)) + return user, nil } diff --git a/service/userdata.go b/service/userdata.go index 5fae0f2..dcd46bc 100644 --- a/service/userdata.go +++ b/service/userdata.go @@ -9,44 +9,48 @@ import ( "github.com/SecurityBrewery/catalyst/database" "github.com/SecurityBrewery/catalyst/database/busdb" - "github.com/SecurityBrewery/catalyst/generated/restapi/api" - "github.com/SecurityBrewery/catalyst/generated/restapi/operations/userdata" + "github.com/SecurityBrewery/catalyst/generated/model" ) -func userdataID(id string) []driver.DocumentID { +func userDataResponseID(userData *model.UserDataResponse) []driver.DocumentID { + if userData == nil { + return nil + } + return userDataID(userData.ID) +} + +func userDataID(id string) []driver.DocumentID { return []driver.DocumentID{driver.DocumentID(fmt.Sprintf("%s/%s", database.UserDataCollectionName, id))} } -func (s *Service) GetUserData(ctx context.Context, params *userdata.GetUserDataParams) *api.Response { - userData, err := s.database.UserDataGet(ctx, params.ID) - return s.response(ctx, "GetUserData", nil, userData, err) +func (s *Service) ListUserData(ctx context.Context) (doc []*model.UserDataResponse, err error) { + return s.database.UserDataList(ctx) } -func (s *Service) ListUserData(ctx context.Context) *api.Response { - userData, err := s.database.UserDataList(ctx) - return s.response(ctx, "ListUserData", nil, userData, err) +func (s *Service) GetUserData(ctx context.Context, id string) (*model.UserDataResponse, error) { + return s.database.UserDataGet(ctx, id) } -func (s *Service) UpdateUserData(ctx context.Context, params *userdata.UpdateUserDataParams) *api.Response { - userData, err := s.database.UserDataUpdate(ctx, params.ID, params.Userdata) - return s.response(ctx, "UpdateUserData", userdataID(userData.ID), userData, err) +func (s *Service) UpdateUserData(ctx context.Context, id string, data *model.UserData) (doc *model.UserDataResponse, err error) { + defer s.publishRequest(ctx, err, "CreateUser", userDataResponseID(doc)) + return s.database.UserDataUpdate(ctx, id, data) } -func (s *Service) CurrentUserData(ctx context.Context) *api.Response { +func (s *Service) CurrentUserData(ctx context.Context) (doc *model.UserDataResponse, err error) { user, ok := busdb.UserFromContext(ctx) if !ok { - return s.response(ctx, "CurrentUserData", userdataID(user.ID), nil, errors.New("no user in context")) + return nil, errors.New("no user in context") } - userData, err := s.database.UserDataGet(ctx, user.ID) - return s.response(ctx, "GetUserData", nil, userData, err) + + return s.database.UserDataGet(ctx, user.ID) } -func (s *Service) UpdateCurrentUserData(ctx context.Context, params *userdata.UpdateCurrentUserDataParams) *api.Response { +func (s *Service) UpdateCurrentUserData(ctx context.Context, data *model.UserData) (doc *model.UserDataResponse, err error) { user, ok := busdb.UserFromContext(ctx) if !ok { - return s.response(ctx, "UpdateCurrentUserData", userdataID(user.ID), nil, errors.New("no user in context")) + return nil, errors.New("no user in context") } - userData, err := s.database.UserDataUpdate(ctx, user.ID, params.Userdata) - return s.response(ctx, "UpdateCurrentUserData", userdataID(user.ID), userData, err) + defer s.publishRequest(ctx, err, "UpdateCurrentUserData", userDataResponseID(doc)) + return s.database.UserDataUpdate(ctx, user.ID, data) } diff --git a/static.go b/static.go index 7ecc7ef..d5eb45c 100644 --- a/static.go +++ b/static.go @@ -5,20 +5,18 @@ import ( "net/http" "strings" - "github.com/gin-gonic/gin" - "github.com/SecurityBrewery/catalyst/ui" ) -func static(ctx *gin.Context) { +func static(w http.ResponseWriter, r *http.Request) { fsys, _ := fs.Sub(ui.UI, "dist") - upath := strings.TrimPrefix(ctx.Request.URL.Path, "/") + upath := strings.TrimPrefix(r.URL.Path, "/") if _, err := fs.Stat(fsys, upath); err != nil { - ctx.Request.URL.Path = "/" - ctx.Request.URL.RawPath = "/" + r.URL.Path = "/" + r.URL.RawPath = "/" } - http.FileServer(http.FS(fsys)).ServeHTTP(ctx.Writer, ctx.Request) + http.FileServer(http.FS(fsys)).ServeHTTP(w, r) } diff --git a/test/data.go b/test/data.go index 826976d..4f2a01b 100644 --- a/test/data.go +++ b/test/data.go @@ -6,13 +6,13 @@ import ( "github.com/SecurityBrewery/catalyst/database" "github.com/SecurityBrewery/catalyst/database/migrations" - "github.com/SecurityBrewery/catalyst/generated/models" + "github.com/SecurityBrewery/catalyst/generated/model" "github.com/SecurityBrewery/catalyst/pointer" ) -var bobSetting = &models.UserData{Email: pointer.String("bob@example.org"), Name: pointer.String("Bob Bad")} -var bobForm = &models.UserForm{ID: "bob", Blocked: false, Roles: []string{"admin"}} -var Bob = &models.UserResponse{ID: "bob", Blocked: false, Roles: []string{"admin"}} +var bobSetting = &model.UserData{Email: pointer.String("bob@example.org"), Name: pointer.String("Bob Bad")} +var bobForm = &model.UserForm{ID: "bob", Blocked: false, Roles: []string{"admin"}} +var Bob = &model.UserResponse{ID: "bob", Blocked: false, Roles: []string{"admin"}} func SetupTestData(ctx context.Context, db *database.Database) error { if err := db.UserDataCreate(ctx, "bob", bobSetting); err != nil { @@ -22,18 +22,18 @@ func SetupTestData(ctx context.Context, db *database.Database) error { if _, err := db.UserCreate(ctx, bobForm); err != nil { return err } - if _, err := db.UserCreate(ctx, &models.UserForm{ID: "script", Roles: []string{"engineer"}, Apikey: true}); err != nil { + if _, err := db.UserCreate(ctx, &model.UserForm{ID: "script", Roles: []string{"engineer"}, Apikey: true}); err != nil { return err } - if _, err := db.TicketBatchCreate(ctx, []*models.TicketForm{ + if _, err := db.TicketBatchCreate(ctx, []*model.TicketForm{ { ID: pointer.Int64(8125), Created: parse("2021-10-02T18:04:59.078186+02:00"), Modified: parse("2021-10-02T18:04:59.078186+02:00"), Name: "phishing from selenafadel@von.com detected", Owner: pointer.String("demo"), - References: []*models.Reference{{Href: "https://www.seniorleading-edge.name/users/efficient", Name: "recovery"}, {Href: "http://www.dynamicseamless.com/clicks-and-mortar", Name: "force"}, {Href: "http://www.leadscalable.biz/envisioneer", Name: "fund"}}, + References: []*model.Reference{{Href: "https://www.seniorleading-edge.name/users/efficient", Name: "recovery"}, {Href: "http://www.dynamicseamless.com/clicks-and-mortar", Name: "force"}, {Href: "http://www.leadscalable.biz/envisioneer", Name: "fund"}}, Schema: pointer.String("{}"), Status: "closed", Type: "alert", @@ -43,7 +43,7 @@ func SetupTestData(ctx context.Context, db *database.Database) error { Modified: parse("2021-10-02T18:04:59.078186+02:00"), Name: "Surfaceintroduce virus detected", Owner: pointer.String("demo"), - References: []*models.Reference{{Href: "http://www.centralworld-class.io/synthesize", Name: "university"}, {Href: "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", Name: "goal"}, {Href: "http://www.chiefsyndicate.io/action-items", Name: "unemployment"}}, + References: []*model.Reference{{Href: "http://www.centralworld-class.io/synthesize", Name: "university"}, {Href: "https://www.futurevirtual.org/supply-chains/markets/sticky/iterate", Name: "goal"}, {Href: "http://www.chiefsyndicate.io/action-items", Name: "unemployment"}}, Schema: pointer.String("{}"), Status: "closed", Type: "alert", @@ -51,18 +51,18 @@ func SetupTestData(ctx context.Context, db *database.Database) error { ID: pointer.Int64(8123), Created: parse("2021-10-02T18:04:59.078206+02:00"), Modified: parse("2021-10-02T18:04:59.078206+02:00"), - Artifacts: []*models.Artifact{ + Artifacts: []*model.Artifact{ {Name: "94d5cab6f5fe3422a447ab15436e7a672bc0c09a", Status: pointer.String("unknown")}, {Name: "http://www.customerviral.io/scalable/vertical/killer", Status: pointer.String("clean")}, {Name: "leadreintermediate.io", Status: pointer.String("malicious")}, }, Name: "live zebra", Owner: pointer.String("demo"), - References: []*models.Reference{{Href: "https://www.leadmaximize.net/e-services/back-end", Name: "performance"}, {Href: "http://www.corporateinteractive.name/rich", Name: "autumn"}, {Href: "https://www.corporateintuitive.org/intuitive/platforms/integrate", Name: "suggest"}}, + References: []*model.Reference{{Href: "https://www.leadmaximize.net/e-services/back-end", Name: "performance"}, {Href: "http://www.corporateinteractive.name/rich", Name: "autumn"}, {Href: "https://www.corporateintuitive.org/intuitive/platforms/integrate", Name: "suggest"}}, Schema: pointer.String("{\n \"definitions\": {},\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": \"https://example.com/object1618746510.json\",\n \"title\": \"Event\",\n \"type\": \"object\",\n \"required\": [\n \"severity\",\n \"description\",\n \"tlp\"\n ],\n \"properties\": {\n \"severity\": {\n \"$id\": \"#root/severity\",\n \"title\": \"Severity\",\n \"type\": \"string\",\n \"default\": \"Medium\",\n \"nx-enum\": [\n \"Low\",\n \"Medium\",\n \"High\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"Low\",\n \"title\": \"Low\",\n \"icon\": \"mdi-chevron-up\"\n },\n {\n \"const\": \"Medium\",\n \"title\": \"Medium\",\n \"icon\": \"mdi-chevron-double-up\"\n },\n {\n \"const\": \"High\",\n \"title\": \"High\",\n \"icon\": \"mdi-chevron-triple-up\"\n }\n ]\n },\n \"tlp\": {\n \"$id\": \"#root/tlp\",\n \"title\": \"TLP\",\n \"type\": \"string\",\n \"nx-enum\": [\n \"White\",\n \"Green\",\n \"Amber\",\n \"Red\"\n ],\n \"x-cols\": 6,\n \"x-class\": \"pr-2\",\n \"x-display\": \"icon\",\n \"x-itemIcon\": \"icon\",\n \"oneOf\": [\n {\n \"const\": \"White\",\n \"title\": \"White\",\n \"icon\": \"mdi-alpha-w\"\n },\n {\n \"const\": \"Green\",\n \"title\": \"Green\",\n \"icon\": \"mdi-alpha-g\"\n },\n {\n \"const\": \"Amber\",\n \"title\": \"Amber\",\n \"icon\": \"mdi-alpha-a\"\n },\n {\n \"const\": \"Red\",\n \"title\": \"Red\",\n \"icon\": \"mdi-alpha-r\"\n }\n ]\n },\n \"description\": {\n \"$id\": \"#root/description\",\n \"title\": \"Description\",\n \"type\": \"string\",\n \"x-display\": \"textarea\",\n \"x-class\": \"pr-2\"\n }\n }\n}\n"), Status: "closed", Type: "incident", - Playbooks: []*models.PlaybookTemplateForm{ + Playbooks: []*model.PlaybookTemplateForm{ {Yaml: migrations.PhishingPlaybook}, }, }, @@ -73,7 +73,7 @@ func SetupTestData(ctx context.Context, db *database.Database) error { if err := db.RelatedCreate(ctx, 8125, 8126); err != nil { return err } - if _, err := db.PlaybookCreate(ctx, &models.PlaybookTemplateForm{Yaml: "name: Simple\ntasks:\n input:\n name: Enter something to hash\n type: input\n schema:\n title: Something\n type: object\n properties:\n something:\n type: string\n title: Something\n default: \"\"\n next:\n hash: \"something != ''\"\n\n hash:\n name: Hash the something\n type: automation\n automation: hash.sha1\n payload:\n default: \"playbook.tasks['input'].data['something']\"\n next:\n comment: \"hash != ''\"\n\n comment:\n name: Comment the hash\n type: automation\n automation: comment\n payload:\n default: \"playbook.tasks['hash'].data['hash']\"\n next:\n done: \"done\"\n\n done:\n name: You can close this case now\n type: task\n"}); err != nil { + if _, err := db.PlaybookCreate(ctx, &model.PlaybookTemplateForm{Yaml: "name: Simple\ntasks:\n input:\n name: Enter something to hash\n type: input\n schema:\n title: Something\n type: object\n properties:\n something:\n type: string\n title: Something\n default: \"\"\n next:\n hash: \"something != ''\"\n\n hash:\n name: Hash the something\n type: automation\n automation: hash.sha1\n payload:\n default: \"playbook.tasks['input'].data['something']\"\n next:\n comment: \"hash != ''\"\n\n comment:\n name: Comment the hash\n type: automation\n automation: comment\n payload:\n default: \"playbook.tasks['hash'].data['hash']\"\n next:\n done: \"done\"\n\n done:\n name: You can close this case now\n type: task\n"}); err != nil { return err } diff --git a/test/server_test.go b/test/server_test.go index 93c6bb3..c1f05ec 100644 --- a/test/server_test.go +++ b/test/server_test.go @@ -10,25 +10,81 @@ import ( "mime/multipart" "net/http" "net/http/httptest" - "reflect" "regexp" + "strings" "testing" + "time" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/s3" "github.com/aws/aws-sdk-go/service/s3/s3manager" - "github.com/gin-gonic/gin" "github.com/stretchr/testify/assert" + "github.com/tidwall/gjson" + "github.com/tidwall/sjson" "github.com/SecurityBrewery/catalyst" - "github.com/SecurityBrewery/catalyst/database/busdb" - "github.com/SecurityBrewery/catalyst/generated/models" + "github.com/SecurityBrewery/catalyst/generated/api" + "github.com/SecurityBrewery/catalyst/generated/model" "github.com/SecurityBrewery/catalyst/pointer" + ctime "github.com/SecurityBrewery/catalyst/time" ) -func TestService(t *testing.T) { - gin.SetMode(gin.TestMode) +type testClock struct{} +func (testClock) Now() time.Time { + return time.Date(2021, 12, 12, 12, 12, 12, 12, time.UTC) +} + +func TestServer(t *testing.T) { + ctime.DefaultClock = testClock{} + + for _, tt := range api.Tests { + t.Run(tt.Name, func(t *testing.T) { + ctx, _, _, _, _, db, _, server, cleanup, err := Server(t) + if err != nil { + t.Fatal(err) + } + defer cleanup() + + if err := SetupTestData(ctx, db); err != nil { + t.Fatal(err) + } + + w := httptest.NewRecorder() + + // setup request + var req *http.Request + if tt.Args.Data != nil { + b, err := json.Marshal(tt.Args.Data) + if err != nil { + t.Fatal(err) + } + + req = httptest.NewRequest(strings.ToUpper(tt.Args.Method), tt.Args.URL, bytes.NewBuffer(b)) + req.Header.Set("Content-Type", "application/json") + } else { + req = httptest.NewRequest(strings.ToUpper(tt.Args.Method), tt.Args.URL, nil) + } + + // run request + server.ServeHTTP(w, req) + + result := w.Result() + + // assert results + if result.StatusCode != tt.Want.Status { + msg, _ := io.ReadAll(result.Body) + + t.Fatalf("Status got = %v, want %v: %s", result.Status, tt.Want.Status, msg) + } + if tt.Want.Status != http.StatusNoContent { + jsonEqual(t, result.Body, tt.Want.Body) + } + }) + } +} + +func TestService(t *testing.T) { type args struct { method string url string @@ -43,8 +99,8 @@ func TestService(t *testing.T) { args args want want }{ - {name: "GetUser not existing", args: args{method: http.MethodGet, url: "/api/users/123"}, want: want{status: http.StatusNotFound, body: gin.H{"error": "document not found"}}}, - {name: "ListUsers", args: args{method: http.MethodGet, url: "/api/users"}, want: want{status: http.StatusOK}}, + {name: "GetUser not existing", args: args{method: http.MethodGet, url: "/users/123"}, want: want{status: http.StatusNotFound, body: map[string]string{"error": "document not found"}}}, + {name: "ListUsers", args: args{method: http.MethodGet, url: "/users"}, want: want{status: http.StatusOK}}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -54,12 +110,7 @@ func TestService(t *testing.T) { } defer cleanup() - setUser := func(context *gin.Context) { - busdb.SetContext(context, Bob) - } - server.Use(setUser) - - server.ConfigureRoutes() + // server.ConfigureRoutes() w := httptest.NewRecorder() // setup request @@ -93,21 +144,13 @@ func TestService(t *testing.T) { } func TestBackupAndRestore(t *testing.T) { - gin.SetMode(gin.TestMode) log.SetFlags(log.LstdFlags | log.Lshortfile) - type args struct { - method string - url string - data interface{} - } type want struct { status int - // body interface{} } tests := []struct { name string - // args args want want }{ {name: "Backup", want: want{status: http.StatusOK}}, @@ -125,10 +168,6 @@ func TestBackupAndRestore(t *testing.T) { createFile(ctx, server) - server.Server.Use(func(context *gin.Context) { - busdb.SetContext(context, Bob) - }) - zipB := assertBackup(t, server) assertZipFile(t, readZipFile(t, zipB)) @@ -233,6 +272,8 @@ func assertRestore(t *testing.T, zipB []byte, server *catalyst.Server) { restoreResult := restoreRequestRecorder.Result() if !assert.Equal(t, http.StatusOK, restoreResult.StatusCode) { + b, _ := io.ReadAll(restoreResult.Body) + log.Println(string(b)) t.FailNow() } } @@ -246,7 +287,7 @@ func createFile(ctx context.Context, server *catalyst.Server) { log.Fatal(err) } - if _, err := server.DB.LinkFiles(ctx, 8125, []*models.File{{Key: "test.txt", Name: "test.txt"}}); err != nil { + if _, err := server.DB.LinkFiles(ctx, 8125, []*model.File{{Key: "test.txt", Name: "test.txt"}}); err != nil { log.Fatal(err) } } @@ -269,7 +310,7 @@ func assertTicketExists(t *testing.T, server *catalyst.Server) { } assert.NoError(t, backupResult.Body.Close()) - var ticket models.Ticket + var ticket model.Ticket assert.NoError(t, json.Unmarshal(zipBuf.Bytes(), &ticket)) assert.Equal(t, "phishing from selenafadel@von.com detected", ticket.Name) @@ -314,24 +355,37 @@ func readZipFile(t *testing.T, b []byte) *zip.Reader { } func jsonEqual(t *testing.T, got io.Reader, want interface{}) { - var j, j2 interface{} - c, err := io.ReadAll(got) + var gotObject, wantObject interface{} + + // load bytes + wantBytes, err := json.Marshal(want) if err != nil { t.Fatal(err) } - if err := json.Unmarshal(c, &j); err != nil { - t.Fatal(string(c), err) - } - - b, err := json.Marshal(want) + gotBytes, err := io.ReadAll(got) if err != nil { t.Fatal(err) } - if err = json.Unmarshal(b, &j2); err != nil { - t.Fatal(err) + + fields := []string{"secret"} + for _, field := range fields { + gField := gjson.GetBytes(wantBytes, field) + if gField.Exists() && gjson.GetBytes(gotBytes, field).Exists() { + gotBytes, err = sjson.SetBytes(gotBytes, field, gField.Value()) + if err != nil { + t.Fatal(err) + } + } } - if !reflect.DeepEqual(j2, j) { - t.Errorf("Body got = %T:%v, want %T:%v", j, j, j2, j2) + // normalize bytes + if err = json.Unmarshal(wantBytes, &wantObject); err != nil { + t.Fatal(err) } + if err := json.Unmarshal(gotBytes, &gotObject); err != nil { + t.Fatal(string(gotBytes), err) + } + + // compare + assert.Equal(t, wantObject, gotObject) } diff --git a/test/test.go b/test/test.go index 229a798..873695e 100644 --- a/test/test.go +++ b/test/test.go @@ -3,7 +3,7 @@ package test import ( "context" "log" - "net/http/httptest" + "net/http" "os" "path" "strings" @@ -11,15 +11,15 @@ import ( "github.com/arangodb/go-driver" "github.com/coreos/go-oidc/v3/oidc" - "github.com/gin-gonic/gin" + "github.com/go-chi/chi" "golang.org/x/oauth2" "github.com/SecurityBrewery/catalyst" "github.com/SecurityBrewery/catalyst/bus" "github.com/SecurityBrewery/catalyst/database" "github.com/SecurityBrewery/catalyst/database/busdb" - "github.com/SecurityBrewery/catalyst/generated/models" - "github.com/SecurityBrewery/catalyst/generated/restapi" + "github.com/SecurityBrewery/catalyst/generated/api" + "github.com/SecurityBrewery/catalyst/generated/model" "github.com/SecurityBrewery/catalyst/hooks" "github.com/SecurityBrewery/catalyst/index" "github.com/SecurityBrewery/catalyst/pointer" @@ -28,10 +28,7 @@ import ( ) func Context() context.Context { - w := httptest.NewRecorder() - gctx, _ := gin.CreateTestContext(w) - busdb.SetContext(gctx, Bob) - return gctx + return busdb.UserContext(context.Background(), Bob) } func Config(ctx context.Context) (*catalyst.Config, error) { @@ -53,20 +50,20 @@ func Config(ctx context.Context) (*catalyst.Config, error) { Key: "A9RysEsPJni8RaHeg_K0FKXQNfBrUyw-", APIUrl: "http://localhost:8002/api", }, - UISettings: &models.Settings{ - ArtifactStates: []*models.Type{ - {Icon: "mdi-help-circle-outline", ID: "unknown", Name: "Unknown", Color: pointer.String(models.TypeColorInfo)}, - {Icon: "mdi-skull", ID: "malicious", Name: "Malicious", Color: pointer.String(models.TypeColorError)}, - {Icon: "mdi-check", ID: "clean", Name: "Clean", Color: pointer.String(models.TypeColorSuccess)}, + UISettings: &model.Settings{ + ArtifactStates: []*model.Type{ + {Icon: "mdi-help-circle-outline", ID: "unknown", Name: "Unknown", Color: pointer.String(model.TypeColorInfo)}, + {Icon: "mdi-skull", ID: "malicious", Name: "Malicious", Color: pointer.String(model.TypeColorError)}, + {Icon: "mdi-check", ID: "clean", Name: "Clean", Color: pointer.String(model.TypeColorSuccess)}, }, - TicketTypes: []*models.TicketTypeResponse{ + TicketTypes: []*model.TicketTypeResponse{ {ID: "alert", Icon: "mdi-alert", Name: "Alerts"}, {ID: "incident", Icon: "mdi-radioactive", Name: "Incidents"}, {ID: "investigation", Icon: "mdi-fingerprint", Name: "Forensic Investigations"}, {ID: "hunt", Icon: "mdi-target", Name: "Threat Hunting"}, }, Version: "0.0.0-test", - Tier: models.SettingsTierCommunity, + Tier: model.SettingsTierCommunity, Timeformat: "YYYY-MM-DDThh:mm:ss", }, Secret: []byte("4ef5b29539b70233dd40c02a1799d25079595565e05a193b09da2c3e60ada1cd"), @@ -146,7 +143,7 @@ func DB(t *testing.T) (context.Context, *catalyst.Config, *bus.Bus, *index.Index return nil, nil, nil, nil, nil, nil, nil, err } - _, err = db.JobCreate(ctx, "99cd67131b48", &models.JobForm{ + _, err = db.JobCreate(ctx, "99cd67131b48", &model.JobForm{ Automation: "hash.sha1", Payload: "test", Origin: nil, @@ -178,13 +175,19 @@ func Service(t *testing.T) (context.Context, *catalyst.Config, *bus.Bus, *index. return ctx, config, rbus, catalystIndex, catalystStorage, db, catalystService, cleanup, err } -func Server(t *testing.T) (context.Context, *catalyst.Config, *bus.Bus, *index.Index, *storage.Storage, *database.Database, *service.Service, *restapi.Server, func(), error) { +func Server(t *testing.T) (context.Context, *catalyst.Config, *bus.Bus, *index.Index, *storage.Storage, *database.Database, *service.Service, chi.Router, func(), error) { ctx, config, rbus, catalystIndex, catalystStorage, db, catalystService, cleanup, err := Service(t) if err != nil { t.Fatal(err) } - catalystServer := restapi.New(catalystService, &restapi.Config{Address: "0.0.0.0:8000", InsecureHTTP: true}) + catalystServer := api.NewServer(catalystService, func(s []string) func(http.Handler) http.Handler { + return func(handler http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler.ServeHTTP(w, busdb.SetContext(r, Bob)) + }) + } + }) return ctx, config, rbus, catalystIndex, catalystStorage, db, catalystService, catalystServer, cleanup, err } diff --git a/ui/src/client/api.ts b/ui/src/client/api.ts index ee81ae9..2bcb1f7 100644 --- a/ui/src/client/api.ts +++ b/ui/src/client/api.ts @@ -3798,7 +3798,7 @@ export const PlaybooksApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async createPlaybook(playbook: PlaybookTemplateForm, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise>> { + async createPlaybook(playbook: PlaybookTemplateForm, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.createPlaybook(playbook, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, @@ -3863,7 +3863,7 @@ export const PlaybooksApiFactory = function (configuration?: Configuration, base * @param {*} [options] Override http request option. * @throws {RequiredError} */ - createPlaybook(playbook: PlaybookTemplateForm, options?: any): AxiosPromise> { + createPlaybook(playbook: PlaybookTemplateForm, options?: any): AxiosPromise { return localVarFp.createPlaybook(playbook, options).then((request) => request(axios, basePath)); }, /** @@ -4603,7 +4603,7 @@ export const TasksApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async listTasks(options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise>> { + async listTasks(options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise>> { const localVarAxiosArgs = await localVarAxiosParamCreator.listTasks(options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, @@ -4623,7 +4623,7 @@ export const TasksApiFactory = function (configuration?: Configuration, basePath * @param {*} [options] Override http request option. * @throws {RequiredError} */ - listTasks(options?: any): AxiosPromise> { + listTasks(options?: any): AxiosPromise> { return localVarFp.listTasks(options).then((request) => request(axios, basePath)); }, }; @@ -5848,13 +5848,15 @@ export const TicketsApiAxiosParamCreator = function (configuration?: Configurati * * @summary Set ticket schema * @param {number} id Ticket ID - * @param {string} [schema] New ticket schema + * @param {string} schema New ticket schema * @param {*} [options] Override http request option. * @throws {RequiredError} */ - setSchema: async (id: number, schema?: string, options: any = {}): Promise => { + setSchema: async (id: number, schema: string, options: any = {}): Promise => { // verify required parameter 'id' is not null or undefined assertParamExists('setSchema', 'id', id) + // verify required parameter 'schema' is not null or undefined + assertParamExists('setSchema', 'schema', schema) const localVarPath = `/tickets/{id}/schema` .replace(`{${"id"}}`, encodeURIComponent(String(id))); // use dummy base URL string because the URL constructor only accepts absolute URLs. @@ -6028,7 +6030,7 @@ export const TicketsApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async addArtifact(id: number, artifact: Artifact, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async addArtifact(id: number, artifact: Artifact, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.addArtifact(id, artifact, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, @@ -6040,7 +6042,7 @@ export const TicketsApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async addComment(id: number, comment: CommentForm, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async addComment(id: number, comment: CommentForm, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.addComment(id, comment, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, @@ -6052,7 +6054,7 @@ export const TicketsApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async addTicketPlaybook(id: number, playbook: PlaybookTemplateForm, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async addTicketPlaybook(id: number, playbook: PlaybookTemplateForm, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.addTicketPlaybook(id, playbook, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, @@ -6066,7 +6068,7 @@ export const TicketsApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async completeTask(id: number, playbookID: string, taskID: string, data: object, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async completeTask(id: number, playbookID: string, taskID: string, data: object, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.completeTask(id, playbookID, taskID, data, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, @@ -6112,7 +6114,7 @@ export const TicketsApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async enrichArtifact(id: number, name: string, data: EnrichmentForm, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async enrichArtifact(id: number, name: string, data: EnrichmentForm, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.enrichArtifact(id, name, data, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, @@ -6135,7 +6137,7 @@ export const TicketsApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async getTicket(id: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async getTicket(id: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.getTicket(id, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, @@ -6147,7 +6149,7 @@ export const TicketsApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async linkFiles(id: number, files: Array, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async linkFiles(id: number, files: Array, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.linkFiles(id, files, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, @@ -6159,7 +6161,7 @@ export const TicketsApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async linkTicket(id: number, linkedID: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async linkTicket(id: number, linkedID: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.linkTicket(id, linkedID, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, @@ -6187,7 +6189,7 @@ export const TicketsApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async removeArtifact(id: number, name: string, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async removeArtifact(id: number, name: string, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.removeArtifact(id, name, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, @@ -6199,7 +6201,7 @@ export const TicketsApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async removeComment(id: number, commentID: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async removeComment(id: number, commentID: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.removeComment(id, commentID, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, @@ -6211,7 +6213,7 @@ export const TicketsApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async removeTicketPlaybook(id: number, playbookID: string, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async removeTicketPlaybook(id: number, playbookID: string, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.removeTicketPlaybook(id, playbookID, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, @@ -6250,7 +6252,7 @@ export const TicketsApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async setArtifact(id: number, name: string, artifact: Artifact, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async setArtifact(id: number, name: string, artifact: Artifact, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.setArtifact(id, name, artifact, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, @@ -6262,7 +6264,7 @@ export const TicketsApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async setReferences(id: number, references: Array, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async setReferences(id: number, references: Array, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.setReferences(id, references, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, @@ -6270,11 +6272,11 @@ export const TicketsApiFp = function(configuration?: Configuration) { * * @summary Set ticket schema * @param {number} id Ticket ID - * @param {string} [schema] New ticket schema + * @param {string} schema New ticket schema * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async setSchema(id: number, schema?: string, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async setSchema(id: number, schema: string, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.setSchema(id, schema, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, @@ -6288,7 +6290,7 @@ export const TicketsApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async setTask(id: number, playbookID: string, taskID: string, task: Task, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async setTask(id: number, playbookID: string, taskID: string, task: Task, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.setTask(id, playbookID, taskID, task, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, @@ -6300,7 +6302,7 @@ export const TicketsApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async unlinkTicket(id: number, linkedID: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async unlinkTicket(id: number, linkedID: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.unlinkTicket(id, linkedID, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, @@ -6312,7 +6314,7 @@ export const TicketsApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async updateTicket(id: number, ticket: Ticket, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async updateTicket(id: number, ticket: Ticket, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.updateTicket(id, ticket, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, @@ -6334,7 +6336,7 @@ export const TicketsApiFactory = function (configuration?: Configuration, basePa * @param {*} [options] Override http request option. * @throws {RequiredError} */ - addArtifact(id: number, artifact: Artifact, options?: any): AxiosPromise { + addArtifact(id: number, artifact: Artifact, options?: any): AxiosPromise { return localVarFp.addArtifact(id, artifact, options).then((request) => request(axios, basePath)); }, /** @@ -6345,7 +6347,7 @@ export const TicketsApiFactory = function (configuration?: Configuration, basePa * @param {*} [options] Override http request option. * @throws {RequiredError} */ - addComment(id: number, comment: CommentForm, options?: any): AxiosPromise { + addComment(id: number, comment: CommentForm, options?: any): AxiosPromise { return localVarFp.addComment(id, comment, options).then((request) => request(axios, basePath)); }, /** @@ -6356,7 +6358,7 @@ export const TicketsApiFactory = function (configuration?: Configuration, basePa * @param {*} [options] Override http request option. * @throws {RequiredError} */ - addTicketPlaybook(id: number, playbook: PlaybookTemplateForm, options?: any): AxiosPromise { + addTicketPlaybook(id: number, playbook: PlaybookTemplateForm, options?: any): AxiosPromise { return localVarFp.addTicketPlaybook(id, playbook, options).then((request) => request(axios, basePath)); }, /** @@ -6369,7 +6371,7 @@ export const TicketsApiFactory = function (configuration?: Configuration, basePa * @param {*} [options] Override http request option. * @throws {RequiredError} */ - completeTask(id: number, playbookID: string, taskID: string, data: object, options?: any): AxiosPromise { + completeTask(id: number, playbookID: string, taskID: string, data: object, options?: any): AxiosPromise { return localVarFp.completeTask(id, playbookID, taskID, data, options).then((request) => request(axios, basePath)); }, /** @@ -6411,7 +6413,7 @@ export const TicketsApiFactory = function (configuration?: Configuration, basePa * @param {*} [options] Override http request option. * @throws {RequiredError} */ - enrichArtifact(id: number, name: string, data: EnrichmentForm, options?: any): AxiosPromise { + enrichArtifact(id: number, name: string, data: EnrichmentForm, options?: any): AxiosPromise { return localVarFp.enrichArtifact(id, name, data, options).then((request) => request(axios, basePath)); }, /** @@ -6432,7 +6434,7 @@ export const TicketsApiFactory = function (configuration?: Configuration, basePa * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getTicket(id: number, options?: any): AxiosPromise { + getTicket(id: number, options?: any): AxiosPromise { return localVarFp.getTicket(id, options).then((request) => request(axios, basePath)); }, /** @@ -6443,7 +6445,7 @@ export const TicketsApiFactory = function (configuration?: Configuration, basePa * @param {*} [options] Override http request option. * @throws {RequiredError} */ - linkFiles(id: number, files: Array, options?: any): AxiosPromise { + linkFiles(id: number, files: Array, options?: any): AxiosPromise { return localVarFp.linkFiles(id, files, options).then((request) => request(axios, basePath)); }, /** @@ -6454,7 +6456,7 @@ export const TicketsApiFactory = function (configuration?: Configuration, basePa * @param {*} [options] Override http request option. * @throws {RequiredError} */ - linkTicket(id: number, linkedID: number, options?: any): AxiosPromise { + linkTicket(id: number, linkedID: number, options?: any): AxiosPromise { return localVarFp.linkTicket(id, linkedID, options).then((request) => request(axios, basePath)); }, /** @@ -6480,7 +6482,7 @@ export const TicketsApiFactory = function (configuration?: Configuration, basePa * @param {*} [options] Override http request option. * @throws {RequiredError} */ - removeArtifact(id: number, name: string, options?: any): AxiosPromise { + removeArtifact(id: number, name: string, options?: any): AxiosPromise { return localVarFp.removeArtifact(id, name, options).then((request) => request(axios, basePath)); }, /** @@ -6491,7 +6493,7 @@ export const TicketsApiFactory = function (configuration?: Configuration, basePa * @param {*} [options] Override http request option. * @throws {RequiredError} */ - removeComment(id: number, commentID: number, options?: any): AxiosPromise { + removeComment(id: number, commentID: number, options?: any): AxiosPromise { return localVarFp.removeComment(id, commentID, options).then((request) => request(axios, basePath)); }, /** @@ -6502,7 +6504,7 @@ export const TicketsApiFactory = function (configuration?: Configuration, basePa * @param {*} [options] Override http request option. * @throws {RequiredError} */ - removeTicketPlaybook(id: number, playbookID: string, options?: any): AxiosPromise { + removeTicketPlaybook(id: number, playbookID: string, options?: any): AxiosPromise { return localVarFp.removeTicketPlaybook(id, playbookID, options).then((request) => request(axios, basePath)); }, /** @@ -6538,7 +6540,7 @@ export const TicketsApiFactory = function (configuration?: Configuration, basePa * @param {*} [options] Override http request option. * @throws {RequiredError} */ - setArtifact(id: number, name: string, artifact: Artifact, options?: any): AxiosPromise { + setArtifact(id: number, name: string, artifact: Artifact, options?: any): AxiosPromise { return localVarFp.setArtifact(id, name, artifact, options).then((request) => request(axios, basePath)); }, /** @@ -6549,18 +6551,18 @@ export const TicketsApiFactory = function (configuration?: Configuration, basePa * @param {*} [options] Override http request option. * @throws {RequiredError} */ - setReferences(id: number, references: Array, options?: any): AxiosPromise { + setReferences(id: number, references: Array, options?: any): AxiosPromise { return localVarFp.setReferences(id, references, options).then((request) => request(axios, basePath)); }, /** * * @summary Set ticket schema * @param {number} id Ticket ID - * @param {string} [schema] New ticket schema + * @param {string} schema New ticket schema * @param {*} [options] Override http request option. * @throws {RequiredError} */ - setSchema(id: number, schema?: string, options?: any): AxiosPromise { + setSchema(id: number, schema: string, options?: any): AxiosPromise { return localVarFp.setSchema(id, schema, options).then((request) => request(axios, basePath)); }, /** @@ -6573,7 +6575,7 @@ export const TicketsApiFactory = function (configuration?: Configuration, basePa * @param {*} [options] Override http request option. * @throws {RequiredError} */ - setTask(id: number, playbookID: string, taskID: string, task: Task, options?: any): AxiosPromise { + setTask(id: number, playbookID: string, taskID: string, task: Task, options?: any): AxiosPromise { return localVarFp.setTask(id, playbookID, taskID, task, options).then((request) => request(axios, basePath)); }, /** @@ -6584,7 +6586,7 @@ export const TicketsApiFactory = function (configuration?: Configuration, basePa * @param {*} [options] Override http request option. * @throws {RequiredError} */ - unlinkTicket(id: number, linkedID: number, options?: any): AxiosPromise { + unlinkTicket(id: number, linkedID: number, options?: any): AxiosPromise { return localVarFp.unlinkTicket(id, linkedID, options).then((request) => request(axios, basePath)); }, /** @@ -6595,7 +6597,7 @@ export const TicketsApiFactory = function (configuration?: Configuration, basePa * @param {*} [options] Override http request option. * @throws {RequiredError} */ - updateTicket(id: number, ticket: Ticket, options?: any): AxiosPromise { + updateTicket(id: number, ticket: Ticket, options?: any): AxiosPromise { return localVarFp.updateTicket(id, ticket, options).then((request) => request(axios, basePath)); }, }; @@ -6878,12 +6880,12 @@ export class TicketsApi extends BaseAPI { * * @summary Set ticket schema * @param {number} id Ticket ID - * @param {string} [schema] New ticket schema + * @param {string} schema New ticket schema * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof TicketsApi */ - public setSchema(id: number, schema?: string, options?: any) { + public setSchema(id: number, schema: string, options?: any) { return TicketsApiFp(this.configuration).setSchema(id, schema, options).then((request) => request(this.axios, this.basePath)); } diff --git a/ui/src/views/TaskList.vue b/ui/src/views/TaskList.vue index 75dacc0..15a759e 100644 --- a/ui/src/views/TaskList.vue +++ b/ui/src/views/TaskList.vue @@ -18,11 +18,11 @@