diff --git a/pkg/coredata/mitigation.go b/pkg/coredata/mitigation.go index a16cc2d6b..9db4f8699 100644 --- a/pkg/coredata/mitigation.go +++ b/pkg/coredata/mitigation.go @@ -55,6 +55,74 @@ func (c Mitigation) CursorKey(orderBy MitigationOrderField) page.CursorKey { panic(fmt.Sprintf("unsupported order by: %s", orderBy)) } +func (c *Mitigations) LoadByRiskID( + ctx context.Context, + conn pg.Conn, + scope Scoper, + riskID gid.GID, + cursor *page.Cursor[MitigationOrderField], +) error { + q := ` +WITH mtgtns AS ( + SELECT + m.id, + m.tenant_id, + m.organization_id, + m.category, + m.name, + m.description, + m.state, + m.importance, + m.content_ref, + m.created_at, + m.updated_at, + m.standards + FROM + mitigations m + INNER JOIN + risks_mitigations rm ON m.id = rm.mitigation_id + WHERE + rm.risk_id = @risk_id +) +SELECT + id, + tenant_id, + organization_id, + category, + name, + description, + state, + importance, + content_ref, + created_at, + updated_at, + standards +FROM + mtgtns +WHERE %s + AND %s +` + q = fmt.Sprintf(q, scope.SQLFragment(), cursor.SQLFragment()) + + args := pgx.StrictNamedArgs{"risk_id": riskID} + maps.Copy(args, scope.SQLArguments()) + maps.Copy(args, cursor.SQLArguments()) + + rows, err := conn.Query(ctx, q, args) + if err != nil { + return fmt.Errorf("cannot query mitigations: %w", err) + } + + mitigations, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[Mitigation]) + if err != nil { + return fmt.Errorf("cannot collect mitigations: %w", err) + } + + *c = mitigations + + return nil +} + func (c *Mitigations) LoadByControlID( ctx context.Context, conn pg.Conn, diff --git a/pkg/coredata/risk.go b/pkg/coredata/risk.go index 9d4a52e00..4b152484e 100644 --- a/pkg/coredata/risk.go +++ b/pkg/coredata/risk.go @@ -50,6 +50,65 @@ func (r *Risk) CursorKey(orderBy RiskOrderField) page.CursorKey { panic(fmt.Sprintf("unsupported order by: %s", orderBy)) } +func (r *Risks) LoadByMitigationID( + ctx context.Context, + conn pg.Conn, + scope Scoper, + mitigationID gid.GID, + cursor *page.Cursor[RiskOrderField], +) error { + q := ` +WITH rsks AS ( + SELECT + r.id, + r.organization_id, + r.name, + r.description, + r.probability, + r.impact, + r.created_at, + r.updated_at + FROM + risks r + INNER JOIN + risks_mitigations rm ON r.id = rm.risk_id + WHERE + rm.mitigation_id = @mitigation_id +) +SELECT + id, + organization_id, + name, + description, + probability, + impact, + created_at, + updated_at +FROM + rsks +WHERE %s + AND %s +` + q = fmt.Sprintf(q, scope.SQLFragment(), cursor.SQLFragment()) + + args := pgx.NamedArgs{"mitigation_id": mitigationID} + maps.Copy(args, scope.SQLArguments()) + + rows, err := conn.Query(ctx, q, args) + if err != nil { + return fmt.Errorf("cannot query risks: %w", err) + } + + risks, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[Risk]) + if err != nil { + return fmt.Errorf("cannot collect risks: %w", err) + } + + *r = risks + + return nil +} + func (r *Risks) LoadByOrganizationID( ctx context.Context, conn pg.Conn, diff --git a/pkg/coredata/risk_mitigation.go b/pkg/coredata/risk_mitigation.go new file mode 100644 index 000000000..8fcf0b495 --- /dev/null +++ b/pkg/coredata/risk_mitigation.go @@ -0,0 +1,103 @@ +// Copyright (c) 2025 Probo Inc . +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +package coredata + +import ( + "context" + "fmt" + "maps" + "time" + + "github.com/getprobo/probo/pkg/gid" + "github.com/jackc/pgx/v5" + "go.gearno.de/kit/pg" +) + +type ( + RiskMitigation struct { + RiskID gid.GID `db:"risk_id"` + MitigationID gid.GID `db:"mitigation_id"` + TenantID gid.TenantID `db:"tenant_id"` + CreatedAt time.Time `db:"created_at"` + Probability float64 `db:"probability"` + Impact float64 `db:"impact"` + } + + RiskMitigations []*RiskMitigation +) + +func (rm RiskMitigation) Insert( + ctx context.Context, + conn pg.Conn, + scope Scoper, +) error { + q := ` +INSERT INTO + risks_mitigations ( + risk_id, + mitigation_id, + tenant_id, + probability, + impact, + created_at + ) +VALUES ( + @risk_id, + @mitigation_id, + @tenant_id, + @probability, + @impact, + @created_at +); +` + + args := pgx.StrictNamedArgs{ + "risk_id": rm.RiskID, + "mitigation_id": rm.MitigationID, + "tenant_id": scope.GetTenantID(), + "probability": rm.Probability, + "impact": rm.Impact, + "created_at": rm.CreatedAt, + } + _, err := conn.Exec(ctx, q, args) + return err +} + +func (rm RiskMitigation) Delete( + ctx context.Context, + conn pg.Conn, + scope Scoper, +) error { + q := ` +DELETE +FROM + risks_mitigations +WHERE + %s + AND risk_id = @risk_id + AND mitigation_id = @mitigation_id; +` + + q = fmt.Sprintf(q, scope.SQLFragment()) + + args := pgx.StrictNamedArgs{ + "risk_id": rm.RiskID, + "mitigation_id": rm.MitigationID, + } + maps.Copy(args, scope.SQLArguments()) + + _, err := conn.Exec(ctx, q, args) + return err +} diff --git a/pkg/probo/mitigation_service.go b/pkg/probo/mitigation_service.go index 027fc4cf8..6b9f80eb2 100644 --- a/pkg/probo/mitigation_service.go +++ b/pkg/probo/mitigation_service.go @@ -57,6 +57,27 @@ type ( } ) +func (s MitigationService) ListForRiskID( + ctx context.Context, + riskID gid.GID, + cursor *page.Cursor[coredata.MitigationOrderField], +) (*page.Page[*coredata.Mitigation, coredata.MitigationOrderField], error) { + var mitigations coredata.Mitigations + + err := s.svc.pg.WithConn( + ctx, + func(conn pg.Conn) error { + return mitigations.LoadByRiskID(ctx, conn, s.svc.scope, riskID, cursor) + }, + ) + + if err != nil { + return nil, err + } + + return page.NewPage(mitigations, cursor), nil +} + func (s MitigationService) ListForControlID( ctx context.Context, controlID gid.GID, diff --git a/pkg/probo/risk_service.go b/pkg/probo/risk_service.go index 8dbf3b616..050b3ead6 100644 --- a/pkg/probo/risk_service.go +++ b/pkg/probo/risk_service.go @@ -47,6 +47,71 @@ type ( } ) +func (s RiskService) ListForMitigationID( + ctx context.Context, + mitigationID gid.GID, + cursor *page.Cursor[coredata.RiskOrderField], +) (*page.Page[*coredata.Risk, coredata.RiskOrderField], error) { + var risks coredata.Risks + + err := s.svc.pg.WithConn( + ctx, + func(conn pg.Conn) error { + return risks.LoadByMitigationID(ctx, conn, s.svc.scope, mitigationID, cursor) + }, + ) + + if err != nil { + return nil, fmt.Errorf("cannot list risks: %w", err) + } + + return page.NewPage(risks, cursor), nil +} + +func (s RiskService) CreateMapping( + ctx context.Context, + riskID gid.GID, + mitigationID gid.GID, + probability float64, + impact float64, +) error { + riskMitigation := &coredata.RiskMitigation{ + RiskID: riskID, + MitigationID: mitigationID, + TenantID: s.svc.scope.GetTenantID(), + CreatedAt: time.Now(), + Probability: probability, + Impact: impact, + } + + return s.svc.pg.WithConn( + ctx, + func(conn pg.Conn) error { + return riskMitigation.Insert(ctx, conn, s.svc.scope) + }, + ) +} + +func (s RiskService) DeleteMapping( + ctx context.Context, + riskID gid.GID, + mitigationID gid.GID, +) error { + riskMitigation := &coredata.RiskMitigation{ + RiskID: riskID, + MitigationID: mitigationID, + TenantID: s.svc.scope.GetTenantID(), + CreatedAt: time.Now(), + } + + return s.svc.pg.WithConn( + ctx, + func(conn pg.Conn) error { + return riskMitigation.Delete(ctx, conn, s.svc.scope) + }, + ) +} + func (s RiskService) Create( ctx context.Context, req CreateRiskRequest, diff --git a/pkg/server/api/console/v1/schema.graphql b/pkg/server/api/console/v1/schema.graphql index 9c42bed6f..bde1ee2cb 100644 --- a/pkg/server/api/console/v1/schema.graphql +++ b/pkg/server/api/console/v1/schema.graphql @@ -543,13 +543,13 @@ type Risk implements Node { probability: Float! impact: Float! - controls( + mitigations( first: Int after: CursorKey last: Int before: CursorKey - orderBy: ControlOrder - ): ControlConnection! @goField(forceResolver: true) + orderBy: MitigationOrder + ): MitigationConnection! @goField(forceResolver: true) createdAt: Datetime! updatedAt: Datetime! @@ -747,6 +747,8 @@ type Mutation { createRisk(input: CreateRiskInput!): CreateRiskPayload! updateRisk(input: UpdateRiskInput!): UpdateRiskPayload! deleteRisk(input: DeleteRiskInput!): DeleteRiskPayload! + createRiskMapping(input: CreateRiskMappingInput!): CreateRiskMappingPayload! + deleteRiskMapping(input: DeleteRiskMappingInput!): DeleteRiskMappingPayload! # Evidence mutations uploadEvidence(input: UploadEvidenceInput!): UploadEvidencePayload! @@ -925,6 +927,18 @@ input DeleteRiskInput { riskId: ID! } +input CreateRiskMappingInput { + riskId: ID! + mitigationId: ID! + probability: Float! + impact: Float! +} + +input DeleteRiskMappingInput { + riskId: ID! + mitigationId: ID! +} + input UploadEvidenceInput { taskId: ID! name: String! @@ -1080,6 +1094,14 @@ type DeleteRiskPayload { deletedRiskId: ID! } +type CreateRiskMappingPayload { + success: Boolean! +} + +type DeleteRiskMappingPayload { + success: Boolean! +} + type UploadEvidencePayload { evidenceEdge: EvidenceEdge! } diff --git a/pkg/server/api/console/v1/schema/schema.go b/pkg/server/api/console/v1/schema/schema.go index 1237a3d35..366c9683e 100644 --- a/pkg/server/api/console/v1/schema/schema.go +++ b/pkg/server/api/console/v1/schema/schema.go @@ -111,6 +111,10 @@ type ComplexityRoot struct { PolicyEdge func(childComplexity int) int } + CreateRiskMappingPayload struct { + Success func(childComplexity int) int + } + CreateRiskPayload struct { RiskEdge func(childComplexity int) int } @@ -147,6 +151,10 @@ type ComplexityRoot struct { DeletedPolicyID func(childComplexity int) int } + DeleteRiskMappingPayload struct { + Success func(childComplexity int) int + } + DeleteRiskPayload struct { DeletedRiskID func(childComplexity int) int } @@ -248,6 +256,7 @@ type ComplexityRoot struct { CreatePeople func(childComplexity int, input types.CreatePeopleInput) int CreatePolicy func(childComplexity int, input types.CreatePolicyInput) int CreateRisk func(childComplexity int, input types.CreateRiskInput) int + CreateRiskMapping func(childComplexity int, input types.CreateRiskMappingInput) int CreateTask func(childComplexity int, input types.CreateTaskInput) int CreateVendor func(childComplexity int, input types.CreateVendorInput) int DeleteControlMapping func(childComplexity int, input types.DeleteControlMappingInput) int @@ -257,6 +266,7 @@ type ComplexityRoot struct { DeletePeople func(childComplexity int, input types.DeletePeopleInput) int DeletePolicy func(childComplexity int, input types.DeletePolicyInput) int DeleteRisk func(childComplexity int, input types.DeleteRiskInput) int + DeleteRiskMapping func(childComplexity int, input types.DeleteRiskMappingInput) int DeleteTask func(childComplexity int, input types.DeleteTaskInput) int DeleteVendor func(childComplexity int, input types.DeleteVendorInput) int ImportFramework func(childComplexity int, input types.ImportFrameworkInput) int @@ -358,11 +368,11 @@ type ComplexityRoot struct { } Risk struct { - Controls func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ControlOrderBy) int CreatedAt func(childComplexity int) int Description func(childComplexity int) int ID func(childComplexity int) int Impact func(childComplexity int) int + Mitigations func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.MitigationOrderBy) int Name func(childComplexity int) int Probability func(childComplexity int) int UpdatedAt func(childComplexity int) int @@ -539,6 +549,8 @@ type MutationResolver interface { CreateRisk(ctx context.Context, input types.CreateRiskInput) (*types.CreateRiskPayload, error) UpdateRisk(ctx context.Context, input types.UpdateRiskInput) (*types.UpdateRiskPayload, error) DeleteRisk(ctx context.Context, input types.DeleteRiskInput) (*types.DeleteRiskPayload, error) + CreateRiskMapping(ctx context.Context, input types.CreateRiskMappingInput) (*types.CreateRiskMappingPayload, error) + DeleteRiskMapping(ctx context.Context, input types.DeleteRiskMappingInput) (*types.DeleteRiskMappingPayload, error) UploadEvidence(ctx context.Context, input types.UploadEvidenceInput) (*types.UploadEvidencePayload, error) DeleteEvidence(ctx context.Context, input types.DeleteEvidenceInput) (*types.DeleteEvidencePayload, error) CreatePolicy(ctx context.Context, input types.CreatePolicyInput) (*types.CreatePolicyPayload, error) @@ -563,7 +575,7 @@ type QueryResolver interface { Viewer(ctx context.Context) (*types.Viewer, error) } type RiskResolver interface { - Controls(ctx context.Context, obj *types.Risk, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ControlOrderBy) (*types.ControlConnection, error) + Mitigations(ctx context.Context, obj *types.Risk, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.MitigationOrderBy) (*types.MitigationConnection, error) } type TaskResolver interface { AssignedTo(ctx context.Context, obj *types.Task) (*types.People, error) @@ -730,6 +742,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.CreatePolicyPayload.PolicyEdge(childComplexity), true + case "CreateRiskMappingPayload.success": + if e.complexity.CreateRiskMappingPayload.Success == nil { + break + } + + return e.complexity.CreateRiskMappingPayload.Success(childComplexity), true + case "CreateRiskPayload.riskEdge": if e.complexity.CreateRiskPayload.RiskEdge == nil { break @@ -793,6 +812,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.DeletePolicyPayload.DeletedPolicyID(childComplexity), true + case "DeleteRiskMappingPayload.success": + if e.complexity.DeleteRiskMappingPayload.Success == nil { + break + } + + return e.complexity.DeleteRiskMappingPayload.Success(childComplexity), true + case "DeleteRiskPayload.deletedRiskId": if e.complexity.DeleteRiskPayload.DeletedRiskID == nil { break @@ -1243,6 +1269,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Mutation.CreateRisk(childComplexity, args["input"].(types.CreateRiskInput)), true + case "Mutation.createRiskMapping": + if e.complexity.Mutation.CreateRiskMapping == nil { + break + } + + args, err := ec.field_Mutation_createRiskMapping_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.CreateRiskMapping(childComplexity, args["input"].(types.CreateRiskMappingInput)), true + case "Mutation.createTask": if e.complexity.Mutation.CreateTask == nil { break @@ -1351,6 +1389,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Mutation.DeleteRisk(childComplexity, args["input"].(types.DeleteRiskInput)), true + case "Mutation.deleteRiskMapping": + if e.complexity.Mutation.DeleteRiskMapping == nil { + break + } + + args, err := ec.field_Mutation_deleteRiskMapping_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.DeleteRiskMapping(childComplexity, args["input"].(types.DeleteRiskMappingInput)), true + case "Mutation.deleteTask": if e.complexity.Mutation.DeleteTask == nil { break @@ -1905,18 +1955,6 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.RemoveUserPayload.Success(childComplexity), true - case "Risk.controls": - if e.complexity.Risk.Controls == nil { - break - } - - args, err := ec.field_Risk_controls_args(context.TODO(), rawArgs) - if err != nil { - return 0, false - } - - return e.complexity.Risk.Controls(childComplexity, args["first"].(*int), args["after"].(*page.CursorKey), args["last"].(*int), args["before"].(*page.CursorKey), args["orderBy"].(*types.ControlOrderBy)), true - case "Risk.createdAt": if e.complexity.Risk.CreatedAt == nil { break @@ -1945,6 +1983,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Risk.Impact(childComplexity), true + case "Risk.mitigations": + if e.complexity.Risk.Mitigations == nil { + break + } + + args, err := ec.field_Risk_mitigations_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Risk.Mitigations(childComplexity, args["first"].(*int), args["after"].(*page.CursorKey), args["last"].(*int), args["before"].(*page.CursorKey), args["orderBy"].(*types.MitigationOrderBy)), true + case "Risk.name": if e.complexity.Risk.Name == nil { break @@ -2393,6 +2443,7 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { ec.unmarshalInputCreatePeopleInput, ec.unmarshalInputCreatePolicyInput, ec.unmarshalInputCreateRiskInput, + ec.unmarshalInputCreateRiskMappingInput, ec.unmarshalInputCreateTaskInput, ec.unmarshalInputCreateVendorInput, ec.unmarshalInputDeleteControlMappingInput, @@ -2402,6 +2453,7 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { ec.unmarshalInputDeletePeopleInput, ec.unmarshalInputDeletePolicyInput, ec.unmarshalInputDeleteRiskInput, + ec.unmarshalInputDeleteRiskMappingInput, ec.unmarshalInputDeleteTaskInput, ec.unmarshalInputDeleteVendorInput, ec.unmarshalInputEvidenceOrder, @@ -3070,13 +3122,13 @@ type Risk implements Node { probability: Float! impact: Float! - controls( + mitigations( first: Int after: CursorKey last: Int before: CursorKey - orderBy: ControlOrder - ): ControlConnection! @goField(forceResolver: true) + orderBy: MitigationOrder + ): MitigationConnection! @goField(forceResolver: true) createdAt: Datetime! updatedAt: Datetime! @@ -3274,6 +3326,8 @@ type Mutation { createRisk(input: CreateRiskInput!): CreateRiskPayload! updateRisk(input: UpdateRiskInput!): UpdateRiskPayload! deleteRisk(input: DeleteRiskInput!): DeleteRiskPayload! + createRiskMapping(input: CreateRiskMappingInput!): CreateRiskMappingPayload! + deleteRiskMapping(input: DeleteRiskMappingInput!): DeleteRiskMappingPayload! # Evidence mutations uploadEvidence(input: UploadEvidenceInput!): UploadEvidencePayload! @@ -3452,6 +3506,18 @@ input DeleteRiskInput { riskId: ID! } +input CreateRiskMappingInput { + riskId: ID! + mitigationId: ID! + probability: Float! + impact: Float! +} + +input DeleteRiskMappingInput { + riskId: ID! + mitigationId: ID! +} + input UploadEvidenceInput { taskId: ID! name: String! @@ -3607,6 +3673,14 @@ type DeleteRiskPayload { deletedRiskId: ID! } +type CreateRiskMappingPayload { + success: Boolean! +} + +type DeleteRiskMappingPayload { + success: Boolean! +} + type UploadEvidencePayload { evidenceEdge: EvidenceEdge! } @@ -4305,6 +4379,29 @@ func (ec *executionContext) field_Mutation_createPolicy_argsInput( return zeroVal, nil } +func (ec *executionContext) field_Mutation_createRiskMapping_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := ec.field_Mutation_createRiskMapping_argsInput(ctx, rawArgs) + if err != nil { + return nil, err + } + args["input"] = arg0 + return args, nil +} +func (ec *executionContext) field_Mutation_createRiskMapping_argsInput( + ctx context.Context, + rawArgs map[string]any, +) (types.CreateRiskMappingInput, error) { + ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) + if tmp, ok := rawArgs["input"]; ok { + return ec.unmarshalNCreateRiskMappingInput2githubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐCreateRiskMappingInput(ctx, tmp) + } + + var zeroVal types.CreateRiskMappingInput + return zeroVal, nil +} + func (ec *executionContext) field_Mutation_createRisk_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} @@ -4512,6 +4609,29 @@ func (ec *executionContext) field_Mutation_deletePolicy_argsInput( return zeroVal, nil } +func (ec *executionContext) field_Mutation_deleteRiskMapping_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := ec.field_Mutation_deleteRiskMapping_argsInput(ctx, rawArgs) + if err != nil { + return nil, err + } + args["input"] = arg0 + return args, nil +} +func (ec *executionContext) field_Mutation_deleteRiskMapping_argsInput( + ctx context.Context, + rawArgs map[string]any, +) (types.DeleteRiskMappingInput, error) { + ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) + if tmp, ok := rawArgs["input"]; ok { + return ec.unmarshalNDeleteRiskMappingInput2githubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐDeleteRiskMappingInput(ctx, tmp) + } + + var zeroVal types.DeleteRiskMappingInput + return zeroVal, nil +} + func (ec *executionContext) field_Mutation_deleteRisk_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} @@ -5614,37 +5734,37 @@ func (ec *executionContext) field_Query_node_argsID( return zeroVal, nil } -func (ec *executionContext) field_Risk_controls_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { +func (ec *executionContext) field_Risk_mitigations_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Risk_controls_argsFirst(ctx, rawArgs) + arg0, err := ec.field_Risk_mitigations_argsFirst(ctx, rawArgs) if err != nil { return nil, err } args["first"] = arg0 - arg1, err := ec.field_Risk_controls_argsAfter(ctx, rawArgs) + arg1, err := ec.field_Risk_mitigations_argsAfter(ctx, rawArgs) if err != nil { return nil, err } args["after"] = arg1 - arg2, err := ec.field_Risk_controls_argsLast(ctx, rawArgs) + arg2, err := ec.field_Risk_mitigations_argsLast(ctx, rawArgs) if err != nil { return nil, err } args["last"] = arg2 - arg3, err := ec.field_Risk_controls_argsBefore(ctx, rawArgs) + arg3, err := ec.field_Risk_mitigations_argsBefore(ctx, rawArgs) if err != nil { return nil, err } args["before"] = arg3 - arg4, err := ec.field_Risk_controls_argsOrderBy(ctx, rawArgs) + arg4, err := ec.field_Risk_mitigations_argsOrderBy(ctx, rawArgs) if err != nil { return nil, err } args["orderBy"] = arg4 return args, nil } -func (ec *executionContext) field_Risk_controls_argsFirst( +func (ec *executionContext) field_Risk_mitigations_argsFirst( ctx context.Context, rawArgs map[string]any, ) (*int, error) { @@ -5657,7 +5777,7 @@ func (ec *executionContext) field_Risk_controls_argsFirst( return zeroVal, nil } -func (ec *executionContext) field_Risk_controls_argsAfter( +func (ec *executionContext) field_Risk_mitigations_argsAfter( ctx context.Context, rawArgs map[string]any, ) (*page.CursorKey, error) { @@ -5670,7 +5790,7 @@ func (ec *executionContext) field_Risk_controls_argsAfter( return zeroVal, nil } -func (ec *executionContext) field_Risk_controls_argsLast( +func (ec *executionContext) field_Risk_mitigations_argsLast( ctx context.Context, rawArgs map[string]any, ) (*int, error) { @@ -5683,7 +5803,7 @@ func (ec *executionContext) field_Risk_controls_argsLast( return zeroVal, nil } -func (ec *executionContext) field_Risk_controls_argsBefore( +func (ec *executionContext) field_Risk_mitigations_argsBefore( ctx context.Context, rawArgs map[string]any, ) (*page.CursorKey, error) { @@ -5696,16 +5816,16 @@ func (ec *executionContext) field_Risk_controls_argsBefore( return zeroVal, nil } -func (ec *executionContext) field_Risk_controls_argsOrderBy( +func (ec *executionContext) field_Risk_mitigations_argsOrderBy( ctx context.Context, rawArgs map[string]any, -) (*types.ControlOrderBy, error) { +) (*types.MitigationOrderBy, error) { ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("orderBy")) if tmp, ok := rawArgs["orderBy"]; ok { - return ec.unmarshalOControlOrder2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐControlOrderBy(ctx, tmp) + return ec.unmarshalOMitigationOrder2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐMitigationOrderBy(ctx, tmp) } - var zeroVal *types.ControlOrderBy + var zeroVal *types.MitigationOrderBy return zeroVal, nil } @@ -6934,6 +7054,50 @@ func (ec *executionContext) fieldContext_CreatePolicyPayload_policyEdge(_ contex return fc, nil } +func (ec *executionContext) _CreateRiskMappingPayload_success(ctx context.Context, field graphql.CollectedField, obj *types.CreateRiskMappingPayload) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_CreateRiskMappingPayload_success(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.Success, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_CreateRiskMappingPayload_success(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "CreateRiskMappingPayload", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + return fc, nil +} + func (ec *executionContext) _CreateRiskPayload_riskEdge(ctx context.Context, field graphql.CollectedField, obj *types.CreateRiskPayload) (ret graphql.Marshaler) { fc, err := ec.fieldContext_CreateRiskPayload_riskEdge(ctx, field) if err != nil { @@ -7348,6 +7512,50 @@ func (ec *executionContext) fieldContext_DeletePolicyPayload_deletedPolicyId(_ c return fc, nil } +func (ec *executionContext) _DeleteRiskMappingPayload_success(ctx context.Context, field graphql.CollectedField, obj *types.DeleteRiskMappingPayload) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DeleteRiskMappingPayload_success(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.Success, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DeleteRiskMappingPayload_success(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DeleteRiskMappingPayload", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + return fc, nil +} + func (ec *executionContext) _DeleteRiskPayload_deletedRiskId(ctx context.Context, field graphql.CollectedField, obj *types.DeleteRiskPayload) (ret graphql.Marshaler) { fc, err := ec.fieldContext_DeleteRiskPayload_deletedRiskId(ctx, field) if err != nil { @@ -11267,6 +11475,124 @@ func (ec *executionContext) fieldContext_Mutation_deleteRisk(ctx context.Context return fc, nil } +func (ec *executionContext) _Mutation_createRiskMapping(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Mutation_createRiskMapping(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().CreateRiskMapping(rctx, fc.Args["input"].(types.CreateRiskMappingInput)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*types.CreateRiskMappingPayload) + fc.Result = res + return ec.marshalNCreateRiskMappingPayload2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐCreateRiskMappingPayload(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Mutation_createRiskMapping(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Mutation", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "success": + return ec.fieldContext_CreateRiskMappingPayload_success(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type CreateRiskMappingPayload", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Mutation_createRiskMapping_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Mutation_deleteRiskMapping(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Mutation_deleteRiskMapping(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().DeleteRiskMapping(rctx, fc.Args["input"].(types.DeleteRiskMappingInput)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*types.DeleteRiskMappingPayload) + fc.Result = res + return ec.marshalNDeleteRiskMappingPayload2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐDeleteRiskMappingPayload(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Mutation_deleteRiskMapping(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Mutation", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "success": + return ec.fieldContext_DeleteRiskMappingPayload_success(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type DeleteRiskMappingPayload", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Mutation_deleteRiskMapping_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + func (ec *executionContext) _Mutation_uploadEvidence(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Mutation_uploadEvidence(ctx, field) if err != nil { @@ -14187,8 +14513,8 @@ func (ec *executionContext) fieldContext_Risk_impact(_ context.Context, field gr return fc, nil } -func (ec *executionContext) _Risk_controls(ctx context.Context, field graphql.CollectedField, obj *types.Risk) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Risk_controls(ctx, field) +func (ec *executionContext) _Risk_mitigations(ctx context.Context, field graphql.CollectedField, obj *types.Risk) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Risk_mitigations(ctx, field) if err != nil { return graphql.Null } @@ -14201,7 +14527,7 @@ func (ec *executionContext) _Risk_controls(ctx context.Context, field graphql.Co }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Risk().Controls(rctx, obj, fc.Args["first"].(*int), fc.Args["after"].(*page.CursorKey), fc.Args["last"].(*int), fc.Args["before"].(*page.CursorKey), fc.Args["orderBy"].(*types.ControlOrderBy)) + return ec.resolvers.Risk().Mitigations(rctx, obj, fc.Args["first"].(*int), fc.Args["after"].(*page.CursorKey), fc.Args["last"].(*int), fc.Args["before"].(*page.CursorKey), fc.Args["orderBy"].(*types.MitigationOrderBy)) }) if err != nil { ec.Error(ctx, err) @@ -14213,12 +14539,12 @@ func (ec *executionContext) _Risk_controls(ctx context.Context, field graphql.Co } return graphql.Null } - res := resTmp.(*types.ControlConnection) + res := resTmp.(*types.MitigationConnection) fc.Result = res - return ec.marshalNControlConnection2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐControlConnection(ctx, field.Selections, res) + return ec.marshalNMitigationConnection2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐMitigationConnection(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Risk_controls(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Risk_mitigations(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Risk", Field: field, @@ -14227,11 +14553,11 @@ func (ec *executionContext) fieldContext_Risk_controls(ctx context.Context, fiel Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { case "edges": - return ec.fieldContext_ControlConnection_edges(ctx, field) + return ec.fieldContext_MitigationConnection_edges(ctx, field) case "pageInfo": - return ec.fieldContext_ControlConnection_pageInfo(ctx, field) + return ec.fieldContext_MitigationConnection_pageInfo(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type ControlConnection", field.Name) + return nil, fmt.Errorf("no field named %q was found under type MitigationConnection", field.Name) }, } defer func() { @@ -14241,7 +14567,7 @@ func (ec *executionContext) fieldContext_Risk_controls(ctx context.Context, fiel } }() ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Risk_controls_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + if fc.Args, err = ec.field_Risk_mitigations_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { ec.Error(ctx, err) return fc, err } @@ -14533,8 +14859,8 @@ func (ec *executionContext) fieldContext_RiskEdge_node(_ context.Context, field return ec.fieldContext_Risk_probability(ctx, field) case "impact": return ec.fieldContext_Risk_impact(ctx, field) - case "controls": - return ec.fieldContext_Risk_controls(ctx, field) + case "mitigations": + return ec.fieldContext_Risk_mitigations(ctx, field) case "createdAt": return ec.fieldContext_Risk_createdAt(ctx, field) case "updatedAt": @@ -15700,8 +16026,8 @@ func (ec *executionContext) fieldContext_UpdateRiskPayload_risk(_ context.Contex return ec.fieldContext_Risk_probability(ctx, field) case "impact": return ec.fieldContext_Risk_impact(ctx, field) - case "controls": - return ec.fieldContext_Risk_controls(ctx, field) + case "mitigations": + return ec.fieldContext_Risk_mitigations(ctx, field) case "createdAt": return ec.fieldContext_Risk_createdAt(ctx, field) case "updatedAt": @@ -19591,6 +19917,54 @@ func (ec *executionContext) unmarshalInputCreateRiskInput(ctx context.Context, o return it, nil } +func (ec *executionContext) unmarshalInputCreateRiskMappingInput(ctx context.Context, obj any) (types.CreateRiskMappingInput, error) { + var it types.CreateRiskMappingInput + asMap := map[string]any{} + for k, v := range obj.(map[string]any) { + asMap[k] = v + } + + fieldsInOrder := [...]string{"riskId", "mitigationId", "probability", "impact"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "riskId": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("riskId")) + data, err := ec.unmarshalNID2githubᚗcomᚋgetproboᚋproboᚋpkgᚋgidᚐGID(ctx, v) + if err != nil { + return it, err + } + it.RiskID = data + case "mitigationId": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("mitigationId")) + data, err := ec.unmarshalNID2githubᚗcomᚋgetproboᚋproboᚋpkgᚋgidᚐGID(ctx, v) + if err != nil { + return it, err + } + it.MitigationID = data + case "probability": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("probability")) + data, err := ec.unmarshalNFloat2float64(ctx, v) + if err != nil { + return it, err + } + it.Probability = data + case "impact": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("impact")) + data, err := ec.unmarshalNFloat2float64(ctx, v) + if err != nil { + return it, err + } + it.Impact = data + } + } + + return it, nil +} + func (ec *executionContext) unmarshalInputCreateTaskInput(ctx context.Context, obj any) (types.CreateTaskInput, error) { var it types.CreateTaskInput asMap := map[string]any{} @@ -19932,6 +20306,40 @@ func (ec *executionContext) unmarshalInputDeleteRiskInput(ctx context.Context, o return it, nil } +func (ec *executionContext) unmarshalInputDeleteRiskMappingInput(ctx context.Context, obj any) (types.DeleteRiskMappingInput, error) { + var it types.DeleteRiskMappingInput + asMap := map[string]any{} + for k, v := range obj.(map[string]any) { + asMap[k] = v + } + + fieldsInOrder := [...]string{"riskId", "mitigationId"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "riskId": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("riskId")) + data, err := ec.unmarshalNID2githubᚗcomᚋgetproboᚋproboᚋpkgᚋgidᚐGID(ctx, v) + if err != nil { + return it, err + } + it.RiskID = data + case "mitigationId": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("mitigationId")) + data, err := ec.unmarshalNID2githubᚗcomᚋgetproboᚋproboᚋpkgᚋgidᚐGID(ctx, v) + if err != nil { + return it, err + } + it.MitigationID = data + } + } + + return it, nil +} + func (ec *executionContext) unmarshalInputDeleteTaskInput(ctx context.Context, obj any) (types.DeleteTaskInput, error) { var it types.DeleteTaskInput asMap := map[string]any{} @@ -21613,6 +22021,45 @@ func (ec *executionContext) _CreatePolicyPayload(ctx context.Context, sel ast.Se return out } +var createRiskMappingPayloadImplementors = []string{"CreateRiskMappingPayload"} + +func (ec *executionContext) _CreateRiskMappingPayload(ctx context.Context, sel ast.SelectionSet, obj *types.CreateRiskMappingPayload) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, createRiskMappingPayloadImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("CreateRiskMappingPayload") + case "success": + out.Values[i] = ec._CreateRiskMappingPayload_success(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + var createRiskPayloadImplementors = []string{"CreateRiskPayload"} func (ec *executionContext) _CreateRiskPayload(ctx context.Context, sel ast.SelectionSet, obj *types.CreateRiskPayload) graphql.Marshaler { @@ -21964,6 +22411,45 @@ func (ec *executionContext) _DeletePolicyPayload(ctx context.Context, sel ast.Se return out } +var deleteRiskMappingPayloadImplementors = []string{"DeleteRiskMappingPayload"} + +func (ec *executionContext) _DeleteRiskMappingPayload(ctx context.Context, sel ast.SelectionSet, obj *types.DeleteRiskMappingPayload) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, deleteRiskMappingPayloadImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("DeleteRiskMappingPayload") + case "success": + out.Values[i] = ec._DeleteRiskMappingPayload_success(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + var deleteRiskPayloadImplementors = []string{"DeleteRiskPayload"} func (ec *executionContext) _DeleteRiskPayload(ctx context.Context, sel ast.SelectionSet, obj *types.DeleteRiskPayload) graphql.Marshaler { @@ -23075,6 +23561,20 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) if out.Values[i] == graphql.Null { out.Invalids++ } + case "createRiskMapping": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_createRiskMapping(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "deleteRiskMapping": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_deleteRiskMapping(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } case "uploadEvidence": out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { return ec._Mutation_uploadEvidence(ctx, field) @@ -24124,7 +24624,7 @@ func (ec *executionContext) _Risk(ctx context.Context, sel ast.SelectionSet, obj if out.Values[i] == graphql.Null { atomic.AddUint32(&out.Invalids, 1) } - case "controls": + case "mitigations": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -24133,7 +24633,7 @@ func (ec *executionContext) _Risk(ctx context.Context, sel ast.SelectionSet, obj ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Risk_controls(ctx, field, obj) + res = ec._Risk_mitigations(ctx, field, obj) if res == graphql.Null { atomic.AddUint32(&fs.Invalids, 1) } @@ -25945,6 +26445,25 @@ func (ec *executionContext) unmarshalNCreateRiskInput2githubᚗcomᚋgetproboᚋ return res, graphql.ErrorOnPath(ctx, err) } +func (ec *executionContext) unmarshalNCreateRiskMappingInput2githubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐCreateRiskMappingInput(ctx context.Context, v any) (types.CreateRiskMappingInput, error) { + res, err := ec.unmarshalInputCreateRiskMappingInput(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNCreateRiskMappingPayload2githubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐCreateRiskMappingPayload(ctx context.Context, sel ast.SelectionSet, v types.CreateRiskMappingPayload) graphql.Marshaler { + return ec._CreateRiskMappingPayload(ctx, sel, &v) +} + +func (ec *executionContext) marshalNCreateRiskMappingPayload2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐCreateRiskMappingPayload(ctx context.Context, sel ast.SelectionSet, v *types.CreateRiskMappingPayload) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._CreateRiskMappingPayload(ctx, sel, v) +} + func (ec *executionContext) marshalNCreateRiskPayload2githubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐCreateRiskPayload(ctx context.Context, sel ast.SelectionSet, v types.CreateRiskPayload) graphql.Marshaler { return ec._CreateRiskPayload(ctx, sel, &v) } @@ -26146,6 +26665,25 @@ func (ec *executionContext) unmarshalNDeleteRiskInput2githubᚗcomᚋgetproboᚋ return res, graphql.ErrorOnPath(ctx, err) } +func (ec *executionContext) unmarshalNDeleteRiskMappingInput2githubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐDeleteRiskMappingInput(ctx context.Context, v any) (types.DeleteRiskMappingInput, error) { + res, err := ec.unmarshalInputDeleteRiskMappingInput(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNDeleteRiskMappingPayload2githubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐDeleteRiskMappingPayload(ctx context.Context, sel ast.SelectionSet, v types.DeleteRiskMappingPayload) graphql.Marshaler { + return ec._DeleteRiskMappingPayload(ctx, sel, &v) +} + +func (ec *executionContext) marshalNDeleteRiskMappingPayload2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐDeleteRiskMappingPayload(ctx context.Context, sel ast.SelectionSet, v *types.DeleteRiskMappingPayload) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._DeleteRiskMappingPayload(ctx, sel, v) +} + func (ec *executionContext) marshalNDeleteRiskPayload2githubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐDeleteRiskPayload(ctx context.Context, sel ast.SelectionSet, v types.DeleteRiskPayload) graphql.Marshaler { return ec._DeleteRiskPayload(ctx, sel, &v) } diff --git a/pkg/server/api/console/v1/types/types.go b/pkg/server/api/console/v1/types/types.go index 72df53316..c3a702d94 100644 --- a/pkg/server/api/console/v1/types/types.go +++ b/pkg/server/api/console/v1/types/types.go @@ -131,6 +131,17 @@ type CreateRiskInput struct { Impact float64 `json:"impact"` } +type CreateRiskMappingInput struct { + RiskID gid.GID `json:"riskId"` + MitigationID gid.GID `json:"mitigationId"` + Probability float64 `json:"probability"` + Impact float64 `json:"impact"` +} + +type CreateRiskMappingPayload struct { + Success bool `json:"success"` +} + type CreateRiskPayload struct { RiskEdge *RiskEdge `json:"riskEdge"` } @@ -217,6 +228,15 @@ type DeleteRiskInput struct { RiskID gid.GID `json:"riskId"` } +type DeleteRiskMappingInput struct { + RiskID gid.GID `json:"riskId"` + MitigationID gid.GID `json:"mitigationId"` +} + +type DeleteRiskMappingPayload struct { + Success bool `json:"success"` +} + type DeleteRiskPayload struct { DeletedRiskID gid.GID `json:"deletedRiskId"` } @@ -444,14 +464,14 @@ type RemoveUserPayload struct { } type Risk struct { - ID gid.GID `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - Probability float64 `json:"probability"` - Impact float64 `json:"impact"` - Controls *ControlConnection `json:"controls"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` + ID gid.GID `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + Probability float64 `json:"probability"` + Impact float64 `json:"impact"` + Mitigations *MitigationConnection `json:"mitigations"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` } func (Risk) IsNode() {} diff --git a/pkg/server/api/console/v1/v1_resolver.go b/pkg/server/api/console/v1/v1_resolver.go index cbeccf6b6..cdda0fcf7 100644 --- a/pkg/server/api/console/v1/v1_resolver.go +++ b/pkg/server/api/console/v1/v1_resolver.go @@ -113,7 +113,27 @@ func (r *mitigationResolver) Tasks(ctx context.Context, obj *types.Mitigation, f // Risks is the resolver for the risks field. func (r *mitigationResolver) Risks(ctx context.Context, obj *types.Mitigation, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.RiskOrderBy) (*types.RiskConnection, error) { - panic(fmt.Errorf("not implemented: Risks - risks")) + svc := r.GetTenantServiceIfAuthorized(ctx, obj.ID.TenantID()) + + pageOrderBy := page.OrderBy[coredata.RiskOrderField]{ + Field: coredata.RiskOrderFieldCreatedAt, + Direction: page.OrderDirectionDesc, + } + if orderBy != nil { + pageOrderBy = page.OrderBy[coredata.RiskOrderField]{ + Field: orderBy.Field, + Direction: orderBy.Direction, + } + } + + cursor := types.NewCursor(first, after, last, before, pageOrderBy) + + page, err := svc.Risks.ListForMitigationID(ctx, obj.ID, cursor) + if err != nil { + return nil, fmt.Errorf("cannot list mitigation risks: %w", err) + } + + return types.NewRiskConnection(page), nil } // Controls is the resolver for the controls field. @@ -670,6 +690,34 @@ func (r *mutationResolver) DeleteRisk(ctx context.Context, input types.DeleteRis }, nil } +// CreateRiskMapping is the resolver for the createRiskMapping field. +func (r *mutationResolver) CreateRiskMapping(ctx context.Context, input types.CreateRiskMappingInput) (*types.CreateRiskMappingPayload, error) { + svc := r.GetTenantServiceIfAuthorized(ctx, input.RiskID.TenantID()) + + err := svc.Risks.CreateMapping(ctx, input.RiskID, input.MitigationID, input.Probability, input.Impact) + if err != nil { + panic(fmt.Errorf("cannot create risk mapping: %w", err)) + } + + return &types.CreateRiskMappingPayload{ + Success: true, + }, nil +} + +// DeleteRiskMapping is the resolver for the deleteRiskMapping field. +func (r *mutationResolver) DeleteRiskMapping(ctx context.Context, input types.DeleteRiskMappingInput) (*types.DeleteRiskMappingPayload, error) { + svc := r.GetTenantServiceIfAuthorized(ctx, input.RiskID.TenantID()) + + err := svc.Risks.DeleteMapping(ctx, input.RiskID, input.MitigationID) + if err != nil { + panic(fmt.Errorf("cannot delete risk mapping: %w", err)) + } + + return &types.DeleteRiskMappingPayload{ + Success: true, + }, nil +} + // UploadEvidence is the resolver for the uploadEvidence field. func (r *mutationResolver) UploadEvidence(ctx context.Context, input types.UploadEvidenceInput) (*types.UploadEvidencePayload, error) { svc := r.GetTenantServiceIfAuthorized(ctx, input.TaskID.TenantID()) @@ -700,7 +748,7 @@ func (r *mutationResolver) UploadEvidence(ctx context.Context, input types.Uploa evidence, err := svc.Evidences.Create(ctx, req) if err != nil { - return nil, fmt.Errorf("failed to create evidence: %w", err) + panic(fmt.Errorf("failed to create evidence: %w", err)) } return &types.UploadEvidencePayload{ @@ -714,7 +762,7 @@ func (r *mutationResolver) DeleteEvidence(ctx context.Context, input types.Delet err := svc.Evidences.Delete(ctx, input.EvidenceID) if err != nil { - return nil, fmt.Errorf("failed to delete evidence: %w", err) + panic(fmt.Errorf("failed to delete evidence: %w", err)) } return &types.DeleteEvidencePayload{ @@ -735,7 +783,7 @@ func (r *mutationResolver) CreatePolicy(ctx context.Context, input types.CreateP OwnerID: input.OwnerID, }) if err != nil { - return nil, fmt.Errorf("cannot create policy: %w", err) + panic(fmt.Errorf("cannot create policy: %w", err)) } return &types.CreatePolicyPayload{ @@ -756,7 +804,7 @@ func (r *mutationResolver) UpdatePolicy(ctx context.Context, input types.UpdateP OwnerID: input.OwnerID, }) if err != nil { - return nil, fmt.Errorf("cannot update policy: %w", err) + panic(fmt.Errorf("cannot update policy: %w", err)) } return &types.UpdatePolicyPayload{ @@ -770,7 +818,7 @@ func (r *mutationResolver) DeletePolicy(ctx context.Context, input types.DeleteP err := svc.Policies.Delete(ctx, input.PolicyID) if err != nil { - return nil, fmt.Errorf("cannot delete policy: %w", err) + panic(fmt.Errorf("cannot delete policy: %w", err)) } return &types.DeletePolicyPayload{ @@ -802,7 +850,7 @@ func (r *organizationResolver) Users(ctx context.Context, obj *types.Organizatio page, err := r.usrmgrSvc.ListUsersForTenant(ctx, obj.ID, cursor) if err != nil { - return nil, fmt.Errorf("cannot list users: %w", err) + panic(fmt.Errorf("cannot list users: %w", err)) } return types.NewUserConnection(page), nil @@ -827,7 +875,7 @@ func (r *organizationResolver) Frameworks(ctx context.Context, obj *types.Organi page, err := svc.Frameworks.ListForOrganizationID(ctx, obj.ID, cursor) if err != nil { - return nil, fmt.Errorf("cannot list organization frameworks: %w", err) + panic(fmt.Errorf("cannot list organization frameworks: %w", err)) } return types.NewFrameworkConnection(page), nil @@ -852,7 +900,7 @@ func (r *organizationResolver) Vendors(ctx context.Context, obj *types.Organizat page, err := svc.Vendors.ListForOrganizationID(ctx, obj.ID, cursor) if err != nil { - return nil, fmt.Errorf("cannot list organization vendors: %w", err) + panic(fmt.Errorf("cannot list organization vendors: %w", err)) } return types.NewVendorConnection(page), nil @@ -877,7 +925,7 @@ func (r *organizationResolver) Peoples(ctx context.Context, obj *types.Organizat page, err := svc.Peoples.ListForOrganizationID(ctx, obj.ID, cursor) if err != nil { - return nil, fmt.Errorf("cannot list organization peoples: %w", err) + panic(fmt.Errorf("cannot list organization peoples: %w", err)) } return types.NewPeopleConnection(page), nil @@ -902,7 +950,7 @@ func (r *organizationResolver) Policies(ctx context.Context, obj *types.Organiza page, err := svc.Policies.ListByOrganizationID(ctx, obj.ID, cursor) if err != nil { - return nil, fmt.Errorf("cannot list organization policies: %w", err) + panic(fmt.Errorf("cannot list organization policies: %w", err)) } return types.NewPolicyConnection(page), nil @@ -927,7 +975,7 @@ func (r *organizationResolver) Mitigations(ctx context.Context, obj *types.Organ page, err := svc.Mitigations.ListForOrganizationID(ctx, obj.ID, cursor) if err != nil { - return nil, fmt.Errorf("cannot list organization mitigations: %w", err) + panic(fmt.Errorf("cannot list organization mitigations: %w", err)) } return types.NewMitigationConnection(page), nil @@ -964,13 +1012,13 @@ func (r *policyResolver) Owner(ctx context.Context, obj *types.Policy) (*types.P policy, err := svc.Policies.Get(ctx, obj.ID) if err != nil { - return nil, fmt.Errorf("cannot get policy: %w", err) + panic(fmt.Errorf("cannot get policy: %w", err)) } // Get the owner owner, err := svc.Peoples.Get(ctx, policy.OwnerID) if err != nil { - return nil, fmt.Errorf("cannot get owner: %w", err) + panic(fmt.Errorf("cannot get owner: %w", err)) } return types.NewPeople(owner), nil @@ -984,69 +1032,69 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error case coredata.OrganizationEntityType: organization, err := svc.Organizations.Get(ctx, id) if err != nil { - return nil, err + panic(fmt.Errorf("cannot get organization: %w", err)) } return types.NewOrganization(organization), nil case coredata.PeopleEntityType: people, err := svc.Peoples.Get(ctx, id) if err != nil { - return nil, err + panic(fmt.Errorf("cannot get people: %w", err)) } return types.NewPeople(people), nil case coredata.VendorEntityType: vendor, err := svc.Vendors.Get(ctx, id) if err != nil { - return nil, err + panic(fmt.Errorf("cannot get vendor: %w", err)) } return types.NewVendor(vendor), nil case coredata.FrameworkEntityType: framework, err := svc.Frameworks.Get(ctx, id) if err != nil { - return nil, err + panic(fmt.Errorf("cannot get framework: %w", err)) } return types.NewFramework(framework), nil case coredata.MitigationEntityType: mitigation, err := svc.Mitigations.Get(ctx, id) if err != nil { - return nil, err + panic(fmt.Errorf("cannot get mitigation: %w", err)) } return types.NewMitigation(mitigation), nil case coredata.TaskEntityType: task, err := svc.Tasks.Get(ctx, id) if err != nil { - return nil, err + panic(fmt.Errorf("cannot get task: %w", err)) } return types.NewTask(task), nil case coredata.EvidenceEntityType: evidence, err := svc.Evidences.Get(ctx, id) if err != nil { - return nil, err + panic(fmt.Errorf("cannot get evidence: %w", err)) } return types.NewEvidence(evidence), nil case coredata.PolicyEntityType: policy, err := svc.Policies.Get(ctx, id) if err != nil { - return nil, err + panic(fmt.Errorf("cannot get policy: %w", err)) } return types.NewPolicy(policy), nil case coredata.ControlEntityType: control, err := svc.Controls.Get(ctx, id) if err != nil { - return nil, err + panic(fmt.Errorf("cannot get control: %w", err)) } return types.NewControl(control), nil case coredata.RiskEntityType: risk, err := svc.Risks.Get(ctx, id) if err != nil { - return nil, err + panic(fmt.Errorf("cannot get risk: %w", err)) } return types.NewRisk(risk), nil default: @@ -1066,9 +1114,29 @@ func (r *queryResolver) Viewer(ctx context.Context) (*types.Viewer, error) { }, nil } -// Controls is the resolver for the controls field. -func (r *riskResolver) Controls(ctx context.Context, obj *types.Risk, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ControlOrderBy) (*types.ControlConnection, error) { - panic(fmt.Errorf("not implemented: Controls - controls")) +// Mitigations is the resolver for the mitigations field. +func (r *riskResolver) Mitigations(ctx context.Context, obj *types.Risk, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.MitigationOrderBy) (*types.MitigationConnection, error) { + svc := r.GetTenantServiceIfAuthorized(ctx, obj.ID.TenantID()) + + pageOrderBy := page.OrderBy[coredata.MitigationOrderField]{ + Field: coredata.MitigationOrderFieldCreatedAt, + Direction: page.OrderDirectionDesc, + } + if orderBy != nil { + pageOrderBy = page.OrderBy[coredata.MitigationOrderField]{ + Field: orderBy.Field, + Direction: orderBy.Direction, + } + } + + cursor := types.NewCursor(first, after, last, before, pageOrderBy) + + page, err := svc.Mitigations.ListForRiskID(ctx, obj.ID, cursor) + if err != nil { + panic(fmt.Errorf("cannot list risk mitigations: %w", err)) + } + + return types.NewMitigationConnection(page), nil } // AssignedTo is the resolver for the assignedTo field. @@ -1077,7 +1145,7 @@ func (r *taskResolver) AssignedTo(ctx context.Context, obj *types.Task) (*types. task, err := svc.Tasks.Get(ctx, obj.ID) if err != nil { - return nil, fmt.Errorf("cannot get task: %w", err) + panic(fmt.Errorf("cannot get task: %w", err)) } if task.AssignedToID == nil { @@ -1086,7 +1154,7 @@ func (r *taskResolver) AssignedTo(ctx context.Context, obj *types.Task) (*types. people, err := svc.Peoples.Get(ctx, *task.AssignedToID) if err != nil { - return nil, fmt.Errorf("cannot get assigned to: %w", err) + panic(fmt.Errorf("cannot get assigned to: %w", err)) } return types.NewPeople(people), nil