Remove deprecated SOA code
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
@@ -30,17 +30,15 @@ import (
|
||||
|
||||
type (
|
||||
Control struct {
|
||||
ID gid.GID `db:"id"`
|
||||
OrganizationID gid.GID `db:"organization_id"`
|
||||
SectionTitle string `db:"section_title"`
|
||||
FrameworkID gid.GID `db:"framework_id"`
|
||||
Name string `db:"name"`
|
||||
Description *string `db:"description"`
|
||||
Status ControlStatus `db:"status"`
|
||||
ExclusionJustification *string `db:"exclusion_justification"`
|
||||
BestPractice bool `db:"best_practice"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
ID gid.GID `db:"id"`
|
||||
OrganizationID gid.GID `db:"organization_id"`
|
||||
SectionTitle string `db:"section_title"`
|
||||
FrameworkID gid.GID `db:"framework_id"`
|
||||
Name string `db:"name"`
|
||||
Description *string `db:"description"`
|
||||
BestPractice bool `db:"best_practice"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
}
|
||||
|
||||
Controls []*Control
|
||||
@@ -132,8 +130,6 @@ WITH ctrl AS (
|
||||
c.tenant_id,
|
||||
c.name,
|
||||
c.description,
|
||||
c.status,
|
||||
c.exclusion_justification,
|
||||
c.best_practice,
|
||||
c.created_at,
|
||||
c.updated_at,
|
||||
@@ -152,8 +148,6 @@ SELECT
|
||||
organization_id,
|
||||
name,
|
||||
description,
|
||||
status,
|
||||
exclusion_justification,
|
||||
best_practice,
|
||||
created_at,
|
||||
updated_at
|
||||
@@ -245,8 +239,6 @@ WITH ctrl AS (
|
||||
c.tenant_id,
|
||||
c.name,
|
||||
c.description,
|
||||
c.status,
|
||||
c.exclusion_justification,
|
||||
c.best_practice,
|
||||
c.created_at,
|
||||
c.updated_at,
|
||||
@@ -265,8 +257,6 @@ SELECT
|
||||
organization_id,
|
||||
name,
|
||||
description,
|
||||
status,
|
||||
exclusion_justification,
|
||||
best_practice,
|
||||
created_at,
|
||||
updated_at
|
||||
@@ -364,8 +354,6 @@ WITH ctrl AS (
|
||||
c.tenant_id,
|
||||
c.name,
|
||||
c.description,
|
||||
c.status,
|
||||
c.exclusion_justification,
|
||||
c.best_practice,
|
||||
c.created_at,
|
||||
c.updated_at,
|
||||
@@ -390,8 +378,6 @@ SELECT
|
||||
organization_id,
|
||||
name,
|
||||
description,
|
||||
status,
|
||||
exclusion_justification,
|
||||
best_practice,
|
||||
created_at,
|
||||
updated_at
|
||||
@@ -471,8 +457,6 @@ SELECT
|
||||
organization_id,
|
||||
name,
|
||||
description,
|
||||
status,
|
||||
exclusion_justification,
|
||||
best_practice,
|
||||
created_at,
|
||||
updated_at
|
||||
@@ -567,8 +551,6 @@ WITH ctrl AS (
|
||||
c.tenant_id,
|
||||
c.name,
|
||||
c.description,
|
||||
c.status,
|
||||
c.exclusion_justification,
|
||||
c.best_practice,
|
||||
c.created_at,
|
||||
c.updated_at,
|
||||
@@ -587,8 +569,6 @@ SELECT
|
||||
organization_id,
|
||||
name,
|
||||
description,
|
||||
status,
|
||||
exclusion_justification,
|
||||
best_practice,
|
||||
created_at,
|
||||
updated_at
|
||||
@@ -635,8 +615,6 @@ SELECT
|
||||
organization_id,
|
||||
name,
|
||||
description,
|
||||
status,
|
||||
exclusion_justification,
|
||||
best_practice,
|
||||
created_at,
|
||||
updated_at
|
||||
@@ -685,8 +663,6 @@ SELECT
|
||||
organization_id,
|
||||
name,
|
||||
description,
|
||||
status,
|
||||
exclusion_justification,
|
||||
best_practice,
|
||||
created_at,
|
||||
updated_at
|
||||
@@ -739,8 +715,6 @@ SELECT
|
||||
organization_id,
|
||||
name,
|
||||
description,
|
||||
status,
|
||||
exclusion_justification,
|
||||
best_practice,
|
||||
created_at,
|
||||
updated_at
|
||||
@@ -783,8 +757,6 @@ INSERT INTO
|
||||
section_title,
|
||||
name,
|
||||
description,
|
||||
status,
|
||||
exclusion_justification,
|
||||
best_practice,
|
||||
created_at,
|
||||
updated_at
|
||||
@@ -797,8 +769,6 @@ VALUES (
|
||||
@section_title,
|
||||
@name,
|
||||
@description,
|
||||
@status,
|
||||
@exclusion_justification,
|
||||
@best_practice,
|
||||
@created_at,
|
||||
@updated_at
|
||||
@@ -806,18 +776,16 @@ VALUES (
|
||||
`
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"tenant_id": scope.GetTenantID(),
|
||||
"control_id": c.ID,
|
||||
"organization_id": c.OrganizationID,
|
||||
"framework_id": c.FrameworkID,
|
||||
"section_title": c.SectionTitle,
|
||||
"name": c.Name,
|
||||
"description": c.Description,
|
||||
"status": c.Status,
|
||||
"exclusion_justification": c.ExclusionJustification,
|
||||
"best_practice": c.BestPractice,
|
||||
"created_at": c.CreatedAt,
|
||||
"updated_at": c.UpdatedAt,
|
||||
"tenant_id": scope.GetTenantID(),
|
||||
"control_id": c.ID,
|
||||
"organization_id": c.OrganizationID,
|
||||
"framework_id": c.FrameworkID,
|
||||
"section_title": c.SectionTitle,
|
||||
"name": c.Name,
|
||||
"description": c.Description,
|
||||
"best_practice": c.BestPractice,
|
||||
"created_at": c.CreatedAt,
|
||||
"updated_at": c.UpdatedAt,
|
||||
}
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
|
||||
@@ -866,8 +834,6 @@ UPDATE controls SET
|
||||
name = @name,
|
||||
description = @description,
|
||||
section_title = @section_title,
|
||||
status = @status,
|
||||
exclusion_justification = @exclusion_justification,
|
||||
best_practice = @best_practice,
|
||||
updated_at = @updated_at
|
||||
WHERE %s
|
||||
@@ -876,14 +842,12 @@ WHERE %s
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"control_id": c.ID,
|
||||
"name": c.Name,
|
||||
"description": c.Description,
|
||||
"section_title": c.SectionTitle,
|
||||
"status": c.Status,
|
||||
"exclusion_justification": c.ExclusionJustification,
|
||||
"best_practice": c.BestPractice,
|
||||
"updated_at": c.UpdatedAt,
|
||||
"control_id": c.ID,
|
||||
"name": c.Name,
|
||||
"description": c.Description,
|
||||
"section_title": c.SectionTitle,
|
||||
"best_practice": c.BestPractice,
|
||||
"updated_at": c.UpdatedAt,
|
||||
}
|
||||
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
@@ -963,8 +927,6 @@ WITH ctrl AS (
|
||||
c.tenant_id,
|
||||
c.name,
|
||||
c.description,
|
||||
c.status,
|
||||
c.exclusion_justification,
|
||||
c.best_practice,
|
||||
c.created_at,
|
||||
c.updated_at,
|
||||
@@ -983,8 +945,6 @@ SELECT
|
||||
organization_id,
|
||||
name,
|
||||
description,
|
||||
status,
|
||||
exclusion_justification,
|
||||
best_practice,
|
||||
created_at,
|
||||
updated_at
|
||||
@@ -1077,8 +1037,6 @@ WITH ctrl AS (
|
||||
c.tenant_id,
|
||||
c.name,
|
||||
c.description,
|
||||
c.status,
|
||||
c.exclusion_justification,
|
||||
c.best_practice,
|
||||
c.created_at,
|
||||
c.updated_at,
|
||||
@@ -1097,8 +1055,6 @@ SELECT
|
||||
organization_id,
|
||||
name,
|
||||
description,
|
||||
status,
|
||||
exclusion_justification,
|
||||
best_practice,
|
||||
created_at,
|
||||
updated_at
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
|
||||
//
|
||||
// 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 (
|
||||
"database/sql/driver"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type ControlStatus string
|
||||
|
||||
const (
|
||||
ControlStatusIncluded ControlStatus = "INCLUDED"
|
||||
ControlStatusExcluded ControlStatus = "EXCLUDED"
|
||||
)
|
||||
|
||||
func ControlStatuses() []ControlStatus {
|
||||
return []ControlStatus{
|
||||
ControlStatusIncluded,
|
||||
ControlStatusExcluded,
|
||||
}
|
||||
}
|
||||
|
||||
func (cs ControlStatus) String() string {
|
||||
return string(cs)
|
||||
}
|
||||
|
||||
func (cs *ControlStatus) Scan(value interface{}) error {
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
switch v {
|
||||
case "INCLUDED":
|
||||
*cs = ControlStatusIncluded
|
||||
case "EXCLUDED":
|
||||
*cs = ControlStatusExcluded
|
||||
default:
|
||||
return fmt.Errorf("invalid ControlStatus value: %q", v)
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("unsupported type for ControlStatus: %T", value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cs ControlStatus) Value() (driver.Value, error) {
|
||||
return cs.String(), nil
|
||||
}
|
||||
@@ -88,7 +88,7 @@ func (states DocumentVersionSignatureStates) Value() (driver.Value, error) {
|
||||
if i > 0 {
|
||||
result.WriteString(",")
|
||||
}
|
||||
result.WriteString(fmt.Sprintf("%q", state.String()))
|
||||
fmt.Fprintf(&result, "%q", state.String())
|
||||
}
|
||||
result.WriteString("}")
|
||||
return result.String(), nil
|
||||
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
)
|
||||
|
||||
type (
|
||||
InvitationStatus string
|
||||
InvitationStatus string
|
||||
InvitationStatuses []InvitationStatus
|
||||
)
|
||||
|
||||
@@ -74,7 +74,7 @@ func (statuses InvitationStatuses) Value() (driver.Value, error) {
|
||||
if i > 0 {
|
||||
result.WriteString(",")
|
||||
}
|
||||
result.WriteString(fmt.Sprintf("%q", status.String()))
|
||||
fmt.Fprintf(&result, "%q", status.String())
|
||||
}
|
||||
result.WriteString("}")
|
||||
return result.String(), nil
|
||||
|
||||
6
pkg/coredata/migrations/20260217T120000Z.sql
Normal file
6
pkg/coredata/migrations/20260217T120000Z.sql
Normal file
@@ -0,0 +1,6 @@
|
||||
ALTER TABLE controls ALTER COLUMN status DROP NOT NULL;
|
||||
|
||||
-- TODO: drop columns and type once all code references are fully removed
|
||||
-- ALTER TABLE controls DROP COLUMN status;
|
||||
-- ALTER TABLE controls DROP COLUMN exclusion_justification;
|
||||
-- DROP TYPE control_status;
|
||||
@@ -105,8 +105,7 @@ const (
|
||||
ActionFrameworkCreate = "core:framework:create"
|
||||
ActionFrameworkUpdate = "core:framework:update"
|
||||
ActionFrameworkDelete = "core:framework:delete"
|
||||
ActionFrameworkStateOfApplicabilityGenerate = "core:framework:generate-state-of-applicability"
|
||||
ActionFrameworkExport = "core:framework:export"
|
||||
ActionFrameworkExport = "core:framework:export"
|
||||
ActionFrameworkImport = "core:framework:import"
|
||||
|
||||
// Control actions
|
||||
|
||||
@@ -32,24 +32,20 @@ type (
|
||||
}
|
||||
|
||||
CreateControlRequest struct {
|
||||
ID gid.GID
|
||||
FrameworkID gid.GID
|
||||
Name string
|
||||
Description *string
|
||||
SectionTitle string
|
||||
Status *coredata.ControlStatus
|
||||
ExclusionJustification *string
|
||||
BestPractice bool
|
||||
ID gid.GID
|
||||
FrameworkID gid.GID
|
||||
Name string
|
||||
Description *string
|
||||
SectionTitle string
|
||||
BestPractice bool
|
||||
}
|
||||
|
||||
UpdateControlRequest struct {
|
||||
ID gid.GID
|
||||
Name *string
|
||||
Description **string
|
||||
SectionTitle *string
|
||||
Status *coredata.ControlStatus
|
||||
ExclusionJustification *string
|
||||
BestPractice *bool
|
||||
ID gid.GID
|
||||
Name *string
|
||||
Description **string
|
||||
SectionTitle *string
|
||||
BestPractice *bool
|
||||
}
|
||||
)
|
||||
|
||||
@@ -60,8 +56,6 @@ func (ccr *CreateControlRequest) Validate() error {
|
||||
v.Check(ccr.Name, "name", validator.Required(), validator.SafeTextNoNewLine(TitleMaxLength))
|
||||
v.Check(ccr.Description, "description", validator.Required(), validator.SafeText(ContentMaxLength))
|
||||
v.Check(ccr.SectionTitle, "section_title", validator.Required(), validator.SafeTextNoNewLine(TitleMaxLength))
|
||||
v.Check(ccr.Status, "status", validator.Required(), validator.OneOfSlice(coredata.ControlStatuses()))
|
||||
v.Check(ccr.ExclusionJustification, "exclusion_justification", validator.SafeText(TitleMaxLength))
|
||||
|
||||
return v.Error()
|
||||
}
|
||||
@@ -73,8 +67,6 @@ func (ucr *UpdateControlRequest) Validate() error {
|
||||
v.Check(ucr.Name, "name", validator.SafeTextNoNewLine(TitleMaxLength))
|
||||
v.Check(ucr.Description, "description", validator.SafeText(ContentMaxLength))
|
||||
v.Check(ucr.SectionTitle, "section_title", validator.SafeTextNoNewLine(TitleMaxLength))
|
||||
v.Check(ucr.Status, "status", validator.OneOfSlice(coredata.ControlStatuses()))
|
||||
v.Check(ucr.ExclusionJustification, "exclusion_justification", validator.SafeText(TitleMaxLength))
|
||||
|
||||
return v.Error()
|
||||
}
|
||||
@@ -839,16 +831,14 @@ func (s ControlService) Create(
|
||||
framework := &coredata.Framework{}
|
||||
|
||||
control := &coredata.Control{
|
||||
ID: gid.New(s.svc.scope.GetTenantID(), coredata.ControlEntityType),
|
||||
FrameworkID: req.FrameworkID,
|
||||
Name: req.Name,
|
||||
Description: req.Description,
|
||||
SectionTitle: req.SectionTitle,
|
||||
Status: *req.Status,
|
||||
ExclusionJustification: req.ExclusionJustification,
|
||||
BestPractice: req.BestPractice,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
ID: gid.New(s.svc.scope.GetTenantID(), coredata.ControlEntityType),
|
||||
FrameworkID: req.FrameworkID,
|
||||
Name: req.Name,
|
||||
Description: req.Description,
|
||||
SectionTitle: req.SectionTitle,
|
||||
BestPractice: req.BestPractice,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
|
||||
err := s.svc.pg.WithTx(
|
||||
@@ -921,14 +911,6 @@ func (s ControlService) Update(
|
||||
control.SectionTitle = *req.SectionTitle
|
||||
}
|
||||
|
||||
if req.Status != nil {
|
||||
control.Status = *req.Status
|
||||
}
|
||||
|
||||
if req.ExclusionJustification != nil {
|
||||
control.ExclusionJustification = req.ExclusionJustification
|
||||
}
|
||||
|
||||
if req.BestPractice != nil {
|
||||
control.BestPractice = *req.BestPractice
|
||||
}
|
||||
|
||||
@@ -36,12 +36,10 @@ import (
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
"go.probo.inc/probo/pkg/page"
|
||||
"go.probo.inc/probo/pkg/slug"
|
||||
"go.probo.inc/probo/pkg/soagen"
|
||||
"go.probo.inc/probo/pkg/validator"
|
||||
)
|
||||
|
||||
const (
|
||||
maxStateOfApplicabilityLimit = 10_000
|
||||
frameworkExportEmailExpiresIn = 24 * time.Hour
|
||||
)
|
||||
|
||||
@@ -584,7 +582,6 @@ func (s FrameworkService) Import(
|
||||
SectionTitle: control.ID,
|
||||
Name: control.Name,
|
||||
Description: &description,
|
||||
Status: coredata.ControlStatusIncluded,
|
||||
BestPractice: bestPractice,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
@@ -605,182 +602,6 @@ func (s FrameworkService) Import(
|
||||
return framework, nil
|
||||
}
|
||||
|
||||
func (s FrameworkService) StateOfApplicability(ctx context.Context, frameworkID gid.GID) ([]byte, error) {
|
||||
rows := []soagen.SOARowData{}
|
||||
|
||||
err := s.svc.pg.WithTx(
|
||||
ctx,
|
||||
func(conn pg.Conn) error {
|
||||
framework := &coredata.Framework{}
|
||||
if err := framework.LoadByID(ctx, conn, s.svc.scope, frameworkID); err != nil {
|
||||
return fmt.Errorf("cannot load framework: %w", err)
|
||||
}
|
||||
|
||||
controls := coredata.Controls{}
|
||||
err := controls.LoadByFrameworkID(
|
||||
ctx,
|
||||
conn,
|
||||
s.svc.scope,
|
||||
frameworkID,
|
||||
page.NewCursor(
|
||||
maxStateOfApplicabilityLimit,
|
||||
nil,
|
||||
page.Head,
|
||||
page.OrderBy[coredata.ControlOrderField]{
|
||||
Field: coredata.ControlOrderFieldSectionTitle,
|
||||
Direction: page.OrderDirectionAsc,
|
||||
},
|
||||
),
|
||||
coredata.NewControlFilter(nil),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot load controls: %w", err)
|
||||
}
|
||||
|
||||
for _, control := range controls {
|
||||
exclusionJustification := ""
|
||||
if control.Status == coredata.ControlStatusExcluded {
|
||||
if control.ExclusionJustification == nil {
|
||||
return fmt.Errorf("exclusion justification is required for excluded controls")
|
||||
}
|
||||
exclusionJustification = *control.ExclusionJustification
|
||||
}
|
||||
|
||||
applicability := soagen.NewApplicability("Yes", true)
|
||||
if control.Status == coredata.ControlStatusExcluded {
|
||||
applicability = soagen.NewApplicability("No", false)
|
||||
}
|
||||
|
||||
bestPractice := ref.Ref(true)
|
||||
if control.Status == coredata.ControlStatusExcluded {
|
||||
bestPractice = ref.Ref(false)
|
||||
}
|
||||
|
||||
row := soagen.SOARowData{
|
||||
SectionTitle: control.SectionTitle,
|
||||
ControlName: control.Name,
|
||||
Applicability: applicability,
|
||||
ExclusionJustification: exclusionJustification,
|
||||
Regulatory: ref.Ref(false),
|
||||
Contractual: ref.Ref(false),
|
||||
BestPractice: bestPractice,
|
||||
RiskAssessment: ref.Ref(false),
|
||||
SecurityMeasures: []string{},
|
||||
}
|
||||
|
||||
if control.Status == coredata.ControlStatusExcluded {
|
||||
rows = append(rows, row)
|
||||
continue
|
||||
}
|
||||
|
||||
measures := coredata.Measures{}
|
||||
err = measures.LoadByControlID(
|
||||
ctx,
|
||||
conn,
|
||||
s.svc.scope,
|
||||
control.ID,
|
||||
page.NewCursor(
|
||||
maxStateOfApplicabilityLimit,
|
||||
nil,
|
||||
page.Head,
|
||||
page.OrderBy[coredata.MeasureOrderField]{
|
||||
Field: coredata.MeasureOrderFieldCreatedAt,
|
||||
Direction: page.OrderDirectionAsc,
|
||||
},
|
||||
),
|
||||
coredata.NewMeasureFilter(nil, nil),
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot load measures: %w", err)
|
||||
}
|
||||
|
||||
for _, measure := range measures {
|
||||
risks := coredata.Risks{}
|
||||
var nilSnapshotID *gid.GID = nil
|
||||
risksCount, err := risks.CountByMeasureID(
|
||||
ctx,
|
||||
conn,
|
||||
s.svc.scope,
|
||||
measure.ID,
|
||||
coredata.NewRiskFilter(nil, &nilSnapshotID),
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot count risks: %w", err)
|
||||
}
|
||||
|
||||
if risksCount > 0 {
|
||||
row.RiskAssessment = ref.Ref(true)
|
||||
}
|
||||
|
||||
row.SecurityMeasures = append(row.SecurityMeasures, measure.Name)
|
||||
}
|
||||
|
||||
documents := coredata.Documents{}
|
||||
err = documents.LoadByControlID(
|
||||
ctx,
|
||||
conn,
|
||||
s.svc.scope,
|
||||
control.ID,
|
||||
page.NewCursor(
|
||||
0,
|
||||
nil,
|
||||
page.Head,
|
||||
page.OrderBy[coredata.DocumentOrderField]{
|
||||
Field: coredata.DocumentOrderFieldCreatedAt,
|
||||
Direction: page.OrderDirectionAsc,
|
||||
},
|
||||
),
|
||||
coredata.NewDocumentFilter(nil),
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot load documents: %w", err)
|
||||
}
|
||||
|
||||
for _, document := range documents {
|
||||
risks := coredata.Risks{}
|
||||
var nilSnapshotID *gid.GID = nil
|
||||
risksCount, err := risks.CountByDocumentID(
|
||||
ctx,
|
||||
conn,
|
||||
s.svc.scope,
|
||||
document.ID,
|
||||
coredata.NewRiskFilter(nil, &nilSnapshotID),
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot count risks: %w", err)
|
||||
}
|
||||
|
||||
if risksCount > 0 {
|
||||
row.RiskAssessment = ref.Ref(true)
|
||||
}
|
||||
|
||||
row.SecurityMeasures = append(row.SecurityMeasures, document.Title)
|
||||
}
|
||||
|
||||
rows = append(rows, row)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
output, err := soagen.GenerateExcel(
|
||||
soagen.SOAData{
|
||||
Rows: rows,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot generate Excel file: %w", err)
|
||||
}
|
||||
|
||||
return output, nil
|
||||
}
|
||||
|
||||
func (s FrameworkService) SendExportEmail(
|
||||
ctx context.Context,
|
||||
fileID gid.GID,
|
||||
|
||||
@@ -1030,14 +1030,6 @@ enum DataClassification
|
||||
)
|
||||
}
|
||||
|
||||
enum ControlStatus
|
||||
@goModel(model: "go.probo.inc/probo/pkg/coredata.ControlStatus") {
|
||||
INCLUDED
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.ControlStatusIncluded")
|
||||
EXCLUDED
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.ControlStatusExcluded")
|
||||
}
|
||||
|
||||
enum AuditOrderField
|
||||
@goModel(model: "go.probo.inc/probo/pkg/coredata.AuditOrderField") {
|
||||
CREATED_AT
|
||||
@@ -2051,8 +2043,6 @@ type Control implements Node {
|
||||
sectionTitle: String!
|
||||
name: String!
|
||||
description: String
|
||||
status: ControlStatus!
|
||||
exclusionJustification: String
|
||||
bestPractice: Boolean!
|
||||
regulatory: Boolean! @goField(forceResolver: true)
|
||||
contractual: Boolean! @goField(forceResolver: true)
|
||||
@@ -3287,9 +3277,6 @@ type Mutation {
|
||||
updateFramework(input: UpdateFrameworkInput!): UpdateFrameworkPayload!
|
||||
importFramework(input: ImportFrameworkInput!): ImportFrameworkPayload!
|
||||
deleteFramework(input: DeleteFrameworkInput!): DeleteFrameworkPayload!
|
||||
generateFrameworkStateOfApplicability(
|
||||
input: GenerateFrameworkStateOfApplicabilityInput!
|
||||
): GenerateFrameworkStateOfApplicabilityPayload!
|
||||
exportFramework(input: ExportFrameworkInput!): ExportFrameworkPayload!
|
||||
# Control mutations
|
||||
createControl(input: CreateControlInput!): CreateControlPayload!
|
||||
@@ -3576,14 +3563,6 @@ type Mutation {
|
||||
}
|
||||
|
||||
# Input Types
|
||||
input GenerateFrameworkStateOfApplicabilityInput {
|
||||
frameworkId: ID!
|
||||
}
|
||||
|
||||
type GenerateFrameworkStateOfApplicabilityPayload {
|
||||
data: String!
|
||||
}
|
||||
|
||||
input UpdateOrganizationContextInput {
|
||||
organizationId: ID!
|
||||
summary: String @goField(omittable: true)
|
||||
@@ -4146,8 +4125,6 @@ input CreateControlInput {
|
||||
sectionTitle: String!
|
||||
name: String!
|
||||
description: String
|
||||
status: ControlStatus!
|
||||
exclusionJustification: String
|
||||
bestPractice: Boolean!
|
||||
}
|
||||
|
||||
@@ -4156,8 +4133,6 @@ input UpdateControlInput {
|
||||
sectionTitle: String
|
||||
name: String
|
||||
description: String @goField(omittable: true)
|
||||
status: ControlStatus
|
||||
exclusionJustification: String
|
||||
bestPractice: Boolean
|
||||
}
|
||||
|
||||
|
||||
@@ -258,26 +258,24 @@ type ComplexityRoot struct {
|
||||
}
|
||||
|
||||
Control struct {
|
||||
Audits func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.AuditOrderBy) int
|
||||
BestPractice func(childComplexity int) int
|
||||
Contractual func(childComplexity int) int
|
||||
CreatedAt func(childComplexity int) int
|
||||
Description func(childComplexity int) int
|
||||
Documents func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentOrderBy, filter *types.DocumentFilter) int
|
||||
ExclusionJustification func(childComplexity int) int
|
||||
Framework func(childComplexity int) int
|
||||
ID func(childComplexity int) int
|
||||
Measures func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.MeasureOrderBy, filter *types.MeasureFilter) int
|
||||
Name func(childComplexity int) int
|
||||
Obligations func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ObligationOrderBy, filter *types.ObligationFilter) int
|
||||
Organization func(childComplexity int) int
|
||||
Permission func(childComplexity int, action string) int
|
||||
Regulatory func(childComplexity int) int
|
||||
RiskAssessment func(childComplexity int) int
|
||||
SectionTitle func(childComplexity int) int
|
||||
Snapshots func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.SnapshotOrderBy) int
|
||||
Status func(childComplexity int) int
|
||||
UpdatedAt func(childComplexity int) int
|
||||
Audits func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.AuditOrderBy) int
|
||||
BestPractice func(childComplexity int) int
|
||||
Contractual func(childComplexity int) int
|
||||
CreatedAt func(childComplexity int) int
|
||||
Description func(childComplexity int) int
|
||||
Documents func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentOrderBy, filter *types.DocumentFilter) int
|
||||
Framework func(childComplexity int) int
|
||||
ID func(childComplexity int) int
|
||||
Measures func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.MeasureOrderBy, filter *types.MeasureFilter) int
|
||||
Name func(childComplexity int) int
|
||||
Obligations func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ObligationOrderBy, filter *types.ObligationFilter) int
|
||||
Organization func(childComplexity int) int
|
||||
Permission func(childComplexity int, action string) int
|
||||
Regulatory func(childComplexity int) int
|
||||
RiskAssessment func(childComplexity int) int
|
||||
SectionTitle func(childComplexity int) int
|
||||
Snapshots func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.SnapshotOrderBy) int
|
||||
UpdatedAt func(childComplexity int) int
|
||||
}
|
||||
|
||||
ControlConnection struct {
|
||||
@@ -873,10 +871,6 @@ type ComplexityRoot struct {
|
||||
Changelog func(childComplexity int) int
|
||||
}
|
||||
|
||||
GenerateFrameworkStateOfApplicabilityPayload struct {
|
||||
Data func(childComplexity int) int
|
||||
}
|
||||
|
||||
GetTrustCenterFilePayload struct {
|
||||
TrustCenterFile func(childComplexity int) int
|
||||
}
|
||||
@@ -1034,7 +1028,6 @@ type ComplexityRoot struct {
|
||||
ExportStateOfApplicabilityPDF func(childComplexity int, input types.ExportStateOfApplicabilityPDFInput) int
|
||||
ExportTransferImpactAssessmentsPDF func(childComplexity int, input types.ExportTransferImpactAssessmentsPDFInput) int
|
||||
GenerateDocumentChangelog func(childComplexity int, input types.GenerateDocumentChangelogInput) int
|
||||
GenerateFrameworkStateOfApplicability func(childComplexity int, input types.GenerateFrameworkStateOfApplicabilityInput) int
|
||||
GetTrustCenterFile func(childComplexity int, input types.GetTrustCenterFileInput) int
|
||||
ImportFramework func(childComplexity int, input types.ImportFrameworkInput) int
|
||||
ImportMeasure func(childComplexity int, input types.ImportMeasureInput) int
|
||||
@@ -2164,7 +2157,6 @@ type MutationResolver interface {
|
||||
UpdateFramework(ctx context.Context, input types.UpdateFrameworkInput) (*types.UpdateFrameworkPayload, error)
|
||||
ImportFramework(ctx context.Context, input types.ImportFrameworkInput) (*types.ImportFrameworkPayload, error)
|
||||
DeleteFramework(ctx context.Context, input types.DeleteFrameworkInput) (*types.DeleteFrameworkPayload, error)
|
||||
GenerateFrameworkStateOfApplicability(ctx context.Context, input types.GenerateFrameworkStateOfApplicabilityInput) (*types.GenerateFrameworkStateOfApplicabilityPayload, error)
|
||||
ExportFramework(ctx context.Context, input types.ExportFrameworkInput) (*types.ExportFrameworkPayload, error)
|
||||
CreateControl(ctx context.Context, input types.CreateControlInput) (*types.CreateControlPayload, error)
|
||||
UpdateControl(ctx context.Context, input types.UpdateControlInput) (*types.UpdateControlPayload, error)
|
||||
@@ -3104,12 +3096,6 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
|
||||
}
|
||||
|
||||
return e.complexity.Control.Documents(childComplexity, args["first"].(*int), args["after"].(*page.CursorKey), args["last"].(*int), args["before"].(*page.CursorKey), args["orderBy"].(*types.DocumentOrderBy), args["filter"].(*types.DocumentFilter)), true
|
||||
case "Control.exclusionJustification":
|
||||
if e.complexity.Control.ExclusionJustification == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.Control.ExclusionJustification(childComplexity), true
|
||||
case "Control.framework":
|
||||
if e.complexity.Control.Framework == nil {
|
||||
break
|
||||
@@ -3196,12 +3182,6 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
|
||||
}
|
||||
|
||||
return e.complexity.Control.Snapshots(childComplexity, args["first"].(*int), args["after"].(*page.CursorKey), args["last"].(*int), args["before"].(*page.CursorKey), args["orderBy"].(*types.SnapshotOrderBy)), true
|
||||
case "Control.status":
|
||||
if e.complexity.Control.Status == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.Control.Status(childComplexity), true
|
||||
case "Control.updatedAt":
|
||||
if e.complexity.Control.UpdatedAt == nil {
|
||||
break
|
||||
@@ -4887,13 +4867,6 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
|
||||
|
||||
return e.complexity.GenerateDocumentChangelogPayload.Changelog(childComplexity), true
|
||||
|
||||
case "GenerateFrameworkStateOfApplicabilityPayload.data":
|
||||
if e.complexity.GenerateFrameworkStateOfApplicabilityPayload.Data == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.GenerateFrameworkStateOfApplicabilityPayload.Data(childComplexity), true
|
||||
|
||||
case "GetTrustCenterFilePayload.trustCenterFile":
|
||||
if e.complexity.GetTrustCenterFilePayload.TrustCenterFile == nil {
|
||||
break
|
||||
@@ -6182,17 +6155,6 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
|
||||
}
|
||||
|
||||
return e.complexity.Mutation.GenerateDocumentChangelog(childComplexity, args["input"].(types.GenerateDocumentChangelogInput)), true
|
||||
case "Mutation.generateFrameworkStateOfApplicability":
|
||||
if e.complexity.Mutation.GenerateFrameworkStateOfApplicability == nil {
|
||||
break
|
||||
}
|
||||
|
||||
args, err := ec.field_Mutation_generateFrameworkStateOfApplicability_args(ctx, rawArgs)
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
return e.complexity.Mutation.GenerateFrameworkStateOfApplicability(childComplexity, args["input"].(types.GenerateFrameworkStateOfApplicabilityInput)), true
|
||||
case "Mutation.getTrustCenterFile":
|
||||
if e.complexity.Mutation.GetTrustCenterFile == nil {
|
||||
break
|
||||
@@ -10419,7 +10381,6 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler {
|
||||
ec.unmarshalInputExportTransferImpactAssessmentsPDFInput,
|
||||
ec.unmarshalInputFrameworkOrder,
|
||||
ec.unmarshalInputGenerateDocumentChangelogInput,
|
||||
ec.unmarshalInputGenerateFrameworkStateOfApplicabilityInput,
|
||||
ec.unmarshalInputGetTrustCenterFileInput,
|
||||
ec.unmarshalInputImportFrameworkInput,
|
||||
ec.unmarshalInputImportMeasureInput,
|
||||
@@ -11627,14 +11588,6 @@ enum DataClassification
|
||||
)
|
||||
}
|
||||
|
||||
enum ControlStatus
|
||||
@goModel(model: "go.probo.inc/probo/pkg/coredata.ControlStatus") {
|
||||
INCLUDED
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.ControlStatusIncluded")
|
||||
EXCLUDED
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.ControlStatusExcluded")
|
||||
}
|
||||
|
||||
enum AuditOrderField
|
||||
@goModel(model: "go.probo.inc/probo/pkg/coredata.AuditOrderField") {
|
||||
CREATED_AT
|
||||
@@ -12648,8 +12601,6 @@ type Control implements Node {
|
||||
sectionTitle: String!
|
||||
name: String!
|
||||
description: String
|
||||
status: ControlStatus!
|
||||
exclusionJustification: String
|
||||
bestPractice: Boolean!
|
||||
regulatory: Boolean! @goField(forceResolver: true)
|
||||
contractual: Boolean! @goField(forceResolver: true)
|
||||
@@ -13884,9 +13835,6 @@ type Mutation {
|
||||
updateFramework(input: UpdateFrameworkInput!): UpdateFrameworkPayload!
|
||||
importFramework(input: ImportFrameworkInput!): ImportFrameworkPayload!
|
||||
deleteFramework(input: DeleteFrameworkInput!): DeleteFrameworkPayload!
|
||||
generateFrameworkStateOfApplicability(
|
||||
input: GenerateFrameworkStateOfApplicabilityInput!
|
||||
): GenerateFrameworkStateOfApplicabilityPayload!
|
||||
exportFramework(input: ExportFrameworkInput!): ExportFrameworkPayload!
|
||||
# Control mutations
|
||||
createControl(input: CreateControlInput!): CreateControlPayload!
|
||||
@@ -14173,14 +14121,6 @@ type Mutation {
|
||||
}
|
||||
|
||||
# Input Types
|
||||
input GenerateFrameworkStateOfApplicabilityInput {
|
||||
frameworkId: ID!
|
||||
}
|
||||
|
||||
type GenerateFrameworkStateOfApplicabilityPayload {
|
||||
data: String!
|
||||
}
|
||||
|
||||
input UpdateOrganizationContextInput {
|
||||
organizationId: ID!
|
||||
summary: String @goField(omittable: true)
|
||||
@@ -14743,8 +14683,6 @@ input CreateControlInput {
|
||||
sectionTitle: String!
|
||||
name: String!
|
||||
description: String
|
||||
status: ControlStatus!
|
||||
exclusionJustification: String
|
||||
bestPractice: Boolean!
|
||||
}
|
||||
|
||||
@@ -14753,8 +14691,6 @@ input UpdateControlInput {
|
||||
sectionTitle: String
|
||||
name: String
|
||||
description: String @goField(omittable: true)
|
||||
status: ControlStatus
|
||||
exclusionJustification: String
|
||||
bestPractice: Boolean
|
||||
}
|
||||
|
||||
@@ -17835,17 +17771,6 @@ func (ec *executionContext) field_Mutation_generateDocumentChangelog_args(ctx co
|
||||
return args, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) field_Mutation_generateFrameworkStateOfApplicability_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
|
||||
var err error
|
||||
args := map[string]any{}
|
||||
arg0, err := graphql.ProcessArgField(ctx, rawArgs, "input", ec.unmarshalNGenerateFrameworkStateOfApplicabilityInput2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐGenerateFrameworkStateOfApplicabilityInput)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
args["input"] = arg0
|
||||
return args, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) field_Mutation_getTrustCenterFile_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
|
||||
var err error
|
||||
args := map[string]any{}
|
||||
@@ -20211,10 +20136,6 @@ func (ec *executionContext) fieldContext_ApplicabilityStatement_control(_ contex
|
||||
return ec.fieldContext_Control_name(ctx, field)
|
||||
case "description":
|
||||
return ec.fieldContext_Control_description(ctx, field)
|
||||
case "status":
|
||||
return ec.fieldContext_Control_status(ctx, field)
|
||||
case "exclusionJustification":
|
||||
return ec.fieldContext_Control_exclusionJustification(ctx, field)
|
||||
case "bestPractice":
|
||||
return ec.fieldContext_Control_bestPractice(ctx, field)
|
||||
case "regulatory":
|
||||
@@ -23225,64 +23146,6 @@ func (ec *executionContext) fieldContext_Control_description(_ context.Context,
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Control_status(ctx context.Context, field graphql.CollectedField, obj *types.Control) (ret graphql.Marshaler) {
|
||||
return graphql.ResolveField(
|
||||
ctx,
|
||||
ec.OperationContext,
|
||||
field,
|
||||
ec.fieldContext_Control_status,
|
||||
func(ctx context.Context) (any, error) {
|
||||
return obj.Status, nil
|
||||
},
|
||||
nil,
|
||||
ec.marshalNControlStatus2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐControlStatus,
|
||||
true,
|
||||
true,
|
||||
)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_Control_status(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "Control",
|
||||
Field: field,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
return nil, errors.New("field of type ControlStatus does not have child fields")
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Control_exclusionJustification(ctx context.Context, field graphql.CollectedField, obj *types.Control) (ret graphql.Marshaler) {
|
||||
return graphql.ResolveField(
|
||||
ctx,
|
||||
ec.OperationContext,
|
||||
field,
|
||||
ec.fieldContext_Control_exclusionJustification,
|
||||
func(ctx context.Context) (any, error) {
|
||||
return obj.ExclusionJustification, nil
|
||||
},
|
||||
nil,
|
||||
ec.marshalOString2ᚖstring,
|
||||
true,
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_Control_exclusionJustification(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "Control",
|
||||
Field: field,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
return nil, errors.New("field of type String does not have child fields")
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Control_bestPractice(ctx context.Context, field graphql.CollectedField, obj *types.Control) (ret graphql.Marshaler) {
|
||||
return graphql.ResolveField(
|
||||
ctx,
|
||||
@@ -23960,10 +23823,6 @@ func (ec *executionContext) fieldContext_ControlEdge_node(_ context.Context, fie
|
||||
return ec.fieldContext_Control_name(ctx, field)
|
||||
case "description":
|
||||
return ec.fieldContext_Control_description(ctx, field)
|
||||
case "status":
|
||||
return ec.fieldContext_Control_status(ctx, field)
|
||||
case "exclusionJustification":
|
||||
return ec.fieldContext_Control_exclusionJustification(ctx, field)
|
||||
case "bestPractice":
|
||||
return ec.fieldContext_Control_bestPractice(ctx, field)
|
||||
case "regulatory":
|
||||
@@ -32598,35 +32457,6 @@ func (ec *executionContext) fieldContext_GenerateDocumentChangelogPayload_change
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _GenerateFrameworkStateOfApplicabilityPayload_data(ctx context.Context, field graphql.CollectedField, obj *types.GenerateFrameworkStateOfApplicabilityPayload) (ret graphql.Marshaler) {
|
||||
return graphql.ResolveField(
|
||||
ctx,
|
||||
ec.OperationContext,
|
||||
field,
|
||||
ec.fieldContext_GenerateFrameworkStateOfApplicabilityPayload_data,
|
||||
func(ctx context.Context) (any, error) {
|
||||
return obj.Data, nil
|
||||
},
|
||||
nil,
|
||||
ec.marshalNString2string,
|
||||
true,
|
||||
true,
|
||||
)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_GenerateFrameworkStateOfApplicabilityPayload_data(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "GenerateFrameworkStateOfApplicabilityPayload",
|
||||
Field: field,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
return nil, errors.New("field of type String does not have child fields")
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _GetTrustCenterFilePayload_trustCenterFile(ctx context.Context, field graphql.CollectedField, obj *types.GetTrustCenterFilePayload) (ret graphql.Marshaler) {
|
||||
return graphql.ResolveField(
|
||||
ctx,
|
||||
@@ -35189,51 +35019,6 @@ func (ec *executionContext) fieldContext_Mutation_deleteFramework(ctx context.Co
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Mutation_generateFrameworkStateOfApplicability(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||
return graphql.ResolveField(
|
||||
ctx,
|
||||
ec.OperationContext,
|
||||
field,
|
||||
ec.fieldContext_Mutation_generateFrameworkStateOfApplicability,
|
||||
func(ctx context.Context) (any, error) {
|
||||
fc := graphql.GetFieldContext(ctx)
|
||||
return ec.resolvers.Mutation().GenerateFrameworkStateOfApplicability(ctx, fc.Args["input"].(types.GenerateFrameworkStateOfApplicabilityInput))
|
||||
},
|
||||
nil,
|
||||
ec.marshalNGenerateFrameworkStateOfApplicabilityPayload2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐGenerateFrameworkStateOfApplicabilityPayload,
|
||||
true,
|
||||
true,
|
||||
)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_Mutation_generateFrameworkStateOfApplicability(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 "data":
|
||||
return ec.fieldContext_GenerateFrameworkStateOfApplicabilityPayload_data(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type GenerateFrameworkStateOfApplicabilityPayload", 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_generateFrameworkStateOfApplicability_args(ctx, field.ArgumentMap(ec.Variables)); err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return fc, err
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Mutation_exportFramework(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||
return graphql.ResolveField(
|
||||
ctx,
|
||||
@@ -53944,10 +53729,6 @@ func (ec *executionContext) fieldContext_UpdateControlPayload_control(_ context.
|
||||
return ec.fieldContext_Control_name(ctx, field)
|
||||
case "description":
|
||||
return ec.fieldContext_Control_description(ctx, field)
|
||||
case "status":
|
||||
return ec.fieldContext_Control_status(ctx, field)
|
||||
case "exclusionJustification":
|
||||
return ec.fieldContext_Control_exclusionJustification(ctx, field)
|
||||
case "bestPractice":
|
||||
return ec.fieldContext_Control_bestPractice(ctx, field)
|
||||
case "regulatory":
|
||||
@@ -63141,7 +62922,7 @@ func (ec *executionContext) unmarshalInputCreateControlInput(ctx context.Context
|
||||
asMap[k] = v
|
||||
}
|
||||
|
||||
fieldsInOrder := [...]string{"frameworkId", "sectionTitle", "name", "description", "status", "exclusionJustification", "bestPractice"}
|
||||
fieldsInOrder := [...]string{"frameworkId", "sectionTitle", "name", "description", "bestPractice"}
|
||||
for _, k := range fieldsInOrder {
|
||||
v, ok := asMap[k]
|
||||
if !ok {
|
||||
@@ -63176,20 +62957,6 @@ func (ec *executionContext) unmarshalInputCreateControlInput(ctx context.Context
|
||||
return it, err
|
||||
}
|
||||
it.Description = data
|
||||
case "status":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("status"))
|
||||
data, err := ec.unmarshalNControlStatus2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐControlStatus(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
it.Status = data
|
||||
case "exclusionJustification":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("exclusionJustification"))
|
||||
data, err := ec.unmarshalOString2ᚖstring(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
it.ExclusionJustification = data
|
||||
case "bestPractice":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("bestPractice"))
|
||||
data, err := ec.unmarshalNBoolean2bool(ctx, v)
|
||||
@@ -66924,33 +66691,6 @@ func (ec *executionContext) unmarshalInputGenerateDocumentChangelogInput(ctx con
|
||||
return it, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalInputGenerateFrameworkStateOfApplicabilityInput(ctx context.Context, obj any) (types.GenerateFrameworkStateOfApplicabilityInput, error) {
|
||||
var it types.GenerateFrameworkStateOfApplicabilityInput
|
||||
asMap := map[string]any{}
|
||||
for k, v := range obj.(map[string]any) {
|
||||
asMap[k] = v
|
||||
}
|
||||
|
||||
fieldsInOrder := [...]string{"frameworkId"}
|
||||
for _, k := range fieldsInOrder {
|
||||
v, ok := asMap[k]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
switch k {
|
||||
case "frameworkId":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("frameworkId"))
|
||||
data, err := ec.unmarshalNID2goᚗproboᚗincᚋproboᚋpkgᚋgidᚐGID(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
it.FrameworkID = data
|
||||
}
|
||||
}
|
||||
|
||||
return it, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalInputGetTrustCenterFileInput(ctx context.Context, obj any) (types.GetTrustCenterFileInput, error) {
|
||||
var it types.GetTrustCenterFileInput
|
||||
asMap := map[string]any{}
|
||||
@@ -68231,7 +67971,7 @@ func (ec *executionContext) unmarshalInputUpdateControlInput(ctx context.Context
|
||||
asMap[k] = v
|
||||
}
|
||||
|
||||
fieldsInOrder := [...]string{"id", "sectionTitle", "name", "description", "status", "exclusionJustification", "bestPractice"}
|
||||
fieldsInOrder := [...]string{"id", "sectionTitle", "name", "description", "bestPractice"}
|
||||
for _, k := range fieldsInOrder {
|
||||
v, ok := asMap[k]
|
||||
if !ok {
|
||||
@@ -68266,20 +68006,6 @@ func (ec *executionContext) unmarshalInputUpdateControlInput(ctx context.Context
|
||||
return it, err
|
||||
}
|
||||
it.Description = graphql.OmittableOf(data)
|
||||
case "status":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("status"))
|
||||
data, err := ec.unmarshalOControlStatus2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐControlStatus(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
it.Status = data
|
||||
case "exclusionJustification":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("exclusionJustification"))
|
||||
data, err := ec.unmarshalOString2ᚖstring(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
it.ExclusionJustification = data
|
||||
case "bestPractice":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("bestPractice"))
|
||||
data, err := ec.unmarshalOBoolean2ᚖbool(ctx, v)
|
||||
@@ -72533,13 +72259,6 @@ func (ec *executionContext) _Control(ctx context.Context, sel ast.SelectionSet,
|
||||
}
|
||||
case "description":
|
||||
out.Values[i] = ec._Control_description(ctx, field, obj)
|
||||
case "status":
|
||||
out.Values[i] = ec._Control_status(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
atomic.AddUint32(&out.Invalids, 1)
|
||||
}
|
||||
case "exclusionJustification":
|
||||
out.Values[i] = ec._Control_exclusionJustification(ctx, field, obj)
|
||||
case "bestPractice":
|
||||
out.Values[i] = ec._Control_bestPractice(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
@@ -79243,45 +78962,6 @@ func (ec *executionContext) _GenerateDocumentChangelogPayload(ctx context.Contex
|
||||
return out
|
||||
}
|
||||
|
||||
var generateFrameworkStateOfApplicabilityPayloadImplementors = []string{"GenerateFrameworkStateOfApplicabilityPayload"}
|
||||
|
||||
func (ec *executionContext) _GenerateFrameworkStateOfApplicabilityPayload(ctx context.Context, sel ast.SelectionSet, obj *types.GenerateFrameworkStateOfApplicabilityPayload) graphql.Marshaler {
|
||||
fields := graphql.CollectFields(ec.OperationContext, sel, generateFrameworkStateOfApplicabilityPayloadImplementors)
|
||||
|
||||
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("GenerateFrameworkStateOfApplicabilityPayload")
|
||||
case "data":
|
||||
out.Values[i] = ec._GenerateFrameworkStateOfApplicabilityPayload_data(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 getTrustCenterFilePayloadImplementors = []string{"GetTrustCenterFilePayload"}
|
||||
|
||||
func (ec *executionContext) _GetTrustCenterFilePayload(ctx context.Context, sel ast.SelectionSet, obj *types.GetTrustCenterFilePayload) graphql.Marshaler {
|
||||
@@ -80277,13 +79957,6 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet)
|
||||
if out.Values[i] == graphql.Null {
|
||||
out.Invalids++
|
||||
}
|
||||
case "generateFrameworkStateOfApplicability":
|
||||
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
|
||||
return ec._Mutation_generateFrameworkStateOfApplicability(ctx, field)
|
||||
})
|
||||
if out.Values[i] == graphql.Null {
|
||||
out.Invalids++
|
||||
}
|
||||
case "exportFramework":
|
||||
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
|
||||
return ec._Mutation_exportFramework(ctx, field)
|
||||
@@ -93049,34 +92722,6 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
func (ec *executionContext) unmarshalNControlStatus2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐControlStatus(ctx context.Context, v any) (coredata.ControlStatus, error) {
|
||||
tmp, err := graphql.UnmarshalString(v)
|
||||
res := unmarshalNControlStatus2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐControlStatus[tmp]
|
||||
return res, graphql.ErrorOnPath(ctx, err)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNControlStatus2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐControlStatus(ctx context.Context, sel ast.SelectionSet, v coredata.ControlStatus) graphql.Marshaler {
|
||||
_ = sel
|
||||
res := graphql.MarshalString(marshalNControlStatus2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐControlStatus[v])
|
||||
if res == graphql.Null {
|
||||
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
||||
graphql.AddErrorf(ctx, "the requested element is null which the schema does not allow")
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
var (
|
||||
unmarshalNControlStatus2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐControlStatus = map[string]coredata.ControlStatus{
|
||||
"INCLUDED": coredata.ControlStatusIncluded,
|
||||
"EXCLUDED": coredata.ControlStatusExcluded,
|
||||
}
|
||||
marshalNControlStatus2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐControlStatus = map[coredata.ControlStatus]string{
|
||||
coredata.ControlStatusIncluded: "INCLUDED",
|
||||
coredata.ControlStatusExcluded: "EXCLUDED",
|
||||
}
|
||||
)
|
||||
|
||||
func (ec *executionContext) unmarshalNCountryCode2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐCountryCode(ctx context.Context, v any) (coredata.CountryCode, error) {
|
||||
tmp, err := graphql.UnmarshalString(v)
|
||||
res := unmarshalNCountryCode2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐCountryCode[tmp]
|
||||
@@ -96474,25 +96119,6 @@ func (ec *executionContext) marshalNGenerateDocumentChangelogPayload2ᚖgoᚗpro
|
||||
return ec._GenerateDocumentChangelogPayload(ctx, sel, v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalNGenerateFrameworkStateOfApplicabilityInput2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐGenerateFrameworkStateOfApplicabilityInput(ctx context.Context, v any) (types.GenerateFrameworkStateOfApplicabilityInput, error) {
|
||||
res, err := ec.unmarshalInputGenerateFrameworkStateOfApplicabilityInput(ctx, v)
|
||||
return res, graphql.ErrorOnPath(ctx, err)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNGenerateFrameworkStateOfApplicabilityPayload2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐGenerateFrameworkStateOfApplicabilityPayload(ctx context.Context, sel ast.SelectionSet, v types.GenerateFrameworkStateOfApplicabilityPayload) graphql.Marshaler {
|
||||
return ec._GenerateFrameworkStateOfApplicabilityPayload(ctx, sel, &v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNGenerateFrameworkStateOfApplicabilityPayload2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐGenerateFrameworkStateOfApplicabilityPayload(ctx context.Context, sel ast.SelectionSet, v *types.GenerateFrameworkStateOfApplicabilityPayload) graphql.Marshaler {
|
||||
if v == nil {
|
||||
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
||||
graphql.AddErrorf(ctx, "the requested element is null which the schema does not allow")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
return ec._GenerateFrameworkStateOfApplicabilityPayload(ctx, sel, v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalNGetTrustCenterFileInput2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐGetTrustCenterFileInput(ctx context.Context, v any) (types.GetTrustCenterFileInput, error) {
|
||||
res, err := ec.unmarshalInputGetTrustCenterFileInput(ctx, v)
|
||||
return res, graphql.ErrorOnPath(ctx, err)
|
||||
@@ -101595,36 +101221,6 @@ func (ec *executionContext) unmarshalOControlOrder2ᚖgoᚗproboᚗincᚋprobo
|
||||
return &res, graphql.ErrorOnPath(ctx, err)
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalOControlStatus2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐControlStatus(ctx context.Context, v any) (*coredata.ControlStatus, error) {
|
||||
if v == nil {
|
||||
return nil, nil
|
||||
}
|
||||
tmp, err := graphql.UnmarshalString(v)
|
||||
res := unmarshalOControlStatus2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐControlStatus[tmp]
|
||||
return &res, graphql.ErrorOnPath(ctx, err)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalOControlStatus2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐControlStatus(ctx context.Context, sel ast.SelectionSet, v *coredata.ControlStatus) graphql.Marshaler {
|
||||
if v == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
_ = sel
|
||||
_ = ctx
|
||||
res := graphql.MarshalString(marshalOControlStatus2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐControlStatus[*v])
|
||||
return res
|
||||
}
|
||||
|
||||
var (
|
||||
unmarshalOControlStatus2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐControlStatus = map[string]coredata.ControlStatus{
|
||||
"INCLUDED": coredata.ControlStatusIncluded,
|
||||
"EXCLUDED": coredata.ControlStatusExcluded,
|
||||
}
|
||||
marshalOControlStatus2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐControlStatus = map[coredata.ControlStatus]string{
|
||||
coredata.ControlStatusIncluded: "INCLUDED",
|
||||
coredata.ControlStatusExcluded: "EXCLUDED",
|
||||
}
|
||||
)
|
||||
|
||||
func (ec *executionContext) unmarshalOCountryCode2ᚕgoᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐCountryCodeᚄ(ctx context.Context, v any) ([]coredata.CountryCode, error) {
|
||||
if v == nil {
|
||||
return nil, nil
|
||||
|
||||
@@ -57,13 +57,11 @@ func NewControl(control *coredata.Control) *Control {
|
||||
Framework: &Framework{
|
||||
ID: control.FrameworkID,
|
||||
},
|
||||
SectionTitle: control.SectionTitle,
|
||||
Name: control.Name,
|
||||
Description: control.Description,
|
||||
Status: control.Status,
|
||||
ExclusionJustification: control.ExclusionJustification,
|
||||
BestPractice: control.BestPractice,
|
||||
CreatedAt: control.CreatedAt,
|
||||
UpdatedAt: control.UpdatedAt,
|
||||
SectionTitle: control.SectionTitle,
|
||||
Name: control.Name,
|
||||
Description: control.Description,
|
||||
BestPractice: control.BestPractice,
|
||||
CreatedAt: control.CreatedAt,
|
||||
UpdatedAt: control.UpdatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,26 +179,24 @@ type ContinualImprovementFilter struct {
|
||||
}
|
||||
|
||||
type Control struct {
|
||||
ID gid.GID `json:"id"`
|
||||
Organization *Organization `json:"organization,omitempty"`
|
||||
SectionTitle string `json:"sectionTitle"`
|
||||
Name string `json:"name"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
Status coredata.ControlStatus `json:"status"`
|
||||
ExclusionJustification *string `json:"exclusionJustification,omitempty"`
|
||||
BestPractice bool `json:"bestPractice"`
|
||||
Regulatory bool `json:"regulatory"`
|
||||
Contractual bool `json:"contractual"`
|
||||
RiskAssessment bool `json:"riskAssessment"`
|
||||
Framework *Framework `json:"framework"`
|
||||
Measures *MeasureConnection `json:"measures"`
|
||||
Documents *DocumentConnection `json:"documents"`
|
||||
Audits *AuditConnection `json:"audits"`
|
||||
Obligations *ObligationConnection `json:"obligations"`
|
||||
Snapshots *SnapshotConnection `json:"snapshots"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
Permission bool `json:"permission"`
|
||||
ID gid.GID `json:"id"`
|
||||
Organization *Organization `json:"organization,omitempty"`
|
||||
SectionTitle string `json:"sectionTitle"`
|
||||
Name string `json:"name"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
BestPractice bool `json:"bestPractice"`
|
||||
Regulatory bool `json:"regulatory"`
|
||||
Contractual bool `json:"contractual"`
|
||||
RiskAssessment bool `json:"riskAssessment"`
|
||||
Framework *Framework `json:"framework"`
|
||||
Measures *MeasureConnection `json:"measures"`
|
||||
Documents *DocumentConnection `json:"documents"`
|
||||
Audits *AuditConnection `json:"audits"`
|
||||
Obligations *ObligationConnection `json:"obligations"`
|
||||
Snapshots *SnapshotConnection `json:"snapshots"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
Permission bool `json:"permission"`
|
||||
}
|
||||
|
||||
func (Control) IsNode() {}
|
||||
@@ -288,13 +286,11 @@ type CreateControlDocumentMappingPayload struct {
|
||||
}
|
||||
|
||||
type CreateControlInput struct {
|
||||
FrameworkID gid.GID `json:"frameworkId"`
|
||||
SectionTitle string `json:"sectionTitle"`
|
||||
Name string `json:"name"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
Status coredata.ControlStatus `json:"status"`
|
||||
ExclusionJustification *string `json:"exclusionJustification,omitempty"`
|
||||
BestPractice bool `json:"bestPractice"`
|
||||
FrameworkID gid.GID `json:"frameworkId"`
|
||||
SectionTitle string `json:"sectionTitle"`
|
||||
Name string `json:"name"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
BestPractice bool `json:"bestPractice"`
|
||||
}
|
||||
|
||||
type CreateControlMeasureMappingInput struct {
|
||||
@@ -1334,14 +1330,6 @@ type GenerateDocumentChangelogPayload struct {
|
||||
Changelog string `json:"changelog"`
|
||||
}
|
||||
|
||||
type GenerateFrameworkStateOfApplicabilityInput struct {
|
||||
FrameworkID gid.GID `json:"frameworkId"`
|
||||
}
|
||||
|
||||
type GenerateFrameworkStateOfApplicabilityPayload struct {
|
||||
Data string `json:"data"`
|
||||
}
|
||||
|
||||
type GetTrustCenterFileInput struct {
|
||||
ID gid.GID `json:"id"`
|
||||
}
|
||||
@@ -1994,13 +1982,11 @@ type UpdateContinualImprovementPayload struct {
|
||||
}
|
||||
|
||||
type UpdateControlInput struct {
|
||||
ID gid.GID `json:"id"`
|
||||
SectionTitle *string `json:"sectionTitle,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Description graphql.Omittable[*string] `json:"description,omitempty"`
|
||||
Status *coredata.ControlStatus `json:"status,omitempty"`
|
||||
ExclusionJustification *string `json:"exclusionJustification,omitempty"`
|
||||
BestPractice *bool `json:"bestPractice,omitempty"`
|
||||
ID gid.GID `json:"id"`
|
||||
SectionTitle *string `json:"sectionTitle,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Description graphql.Omittable[*string] `json:"description,omitempty"`
|
||||
BestPractice *bool `json:"bestPractice,omitempty"`
|
||||
}
|
||||
|
||||
type UpdateControlPayload struct {
|
||||
|
||||
@@ -2511,28 +2511,6 @@ func (r *mutationResolver) DeleteFramework(ctx context.Context, input types.Dele
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GenerateFrameworkStateOfApplicability is the resolver for the generateFrameworkStateOfApplicability field.
|
||||
func (r *mutationResolver) GenerateFrameworkStateOfApplicability(ctx context.Context, input types.GenerateFrameworkStateOfApplicabilityInput) (*types.GenerateFrameworkStateOfApplicabilityPayload, error) {
|
||||
if err := r.authorize(ctx, input.FrameworkID, probo.ActionFrameworkStateOfApplicabilityGenerate); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
prb := r.ProboService(ctx, input.FrameworkID.TenantID())
|
||||
|
||||
soa, err := prb.Frameworks.StateOfApplicability(ctx, input.FrameworkID)
|
||||
if err != nil {
|
||||
// TODO no panic use gqlutils.InternalError
|
||||
panic(fmt.Errorf("cannot generate framework SOA: %w", err))
|
||||
}
|
||||
|
||||
return &types.GenerateFrameworkStateOfApplicabilityPayload{
|
||||
Data: fmt.Sprintf(
|
||||
"data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,%s",
|
||||
base64.StdEncoding.EncodeToString(soa),
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ExportFramework is the resolver for the exportFramework field.
|
||||
func (r *mutationResolver) ExportFramework(ctx context.Context, input types.ExportFrameworkInput) (*types.ExportFrameworkPayload, error) {
|
||||
if err := r.authorize(ctx, input.FrameworkID, probo.ActionFrameworkExport); err != nil {
|
||||
@@ -2569,13 +2547,11 @@ func (r *mutationResolver) CreateControl(ctx context.Context, input types.Create
|
||||
control, err := prb.Controls.Create(
|
||||
ctx,
|
||||
probo.CreateControlRequest{
|
||||
FrameworkID: input.FrameworkID,
|
||||
Name: input.Name,
|
||||
Description: input.Description,
|
||||
SectionTitle: input.SectionTitle,
|
||||
Status: &input.Status,
|
||||
ExclusionJustification: input.ExclusionJustification,
|
||||
BestPractice: input.BestPractice,
|
||||
FrameworkID: input.FrameworkID,
|
||||
Name: input.Name,
|
||||
Description: input.Description,
|
||||
SectionTitle: input.SectionTitle,
|
||||
BestPractice: input.BestPractice,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
@@ -2603,13 +2579,11 @@ func (r *mutationResolver) UpdateControl(ctx context.Context, input types.Update
|
||||
control, err := prb.Controls.Update(
|
||||
ctx,
|
||||
probo.UpdateControlRequest{
|
||||
ID: input.ID,
|
||||
Name: input.Name,
|
||||
Description: gqlutils.UnwrapOmittable(input.Description),
|
||||
SectionTitle: input.SectionTitle,
|
||||
Status: input.Status,
|
||||
ExclusionJustification: input.ExclusionJustification,
|
||||
BestPractice: input.BestPractice,
|
||||
ID: input.ID,
|
||||
Name: input.Name,
|
||||
Description: gqlutils.UnwrapOmittable(input.Description),
|
||||
SectionTitle: input.SectionTitle,
|
||||
BestPractice: input.BestPractice,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@@ -1182,12 +1182,10 @@ func (r *Resolver) AddControlTool(ctx context.Context, req *mcp.CallToolRequest,
|
||||
control, err := svc.Controls.Create(
|
||||
ctx,
|
||||
probo.CreateControlRequest{
|
||||
FrameworkID: input.FrameworkID,
|
||||
Name: input.Name,
|
||||
Description: input.Description,
|
||||
SectionTitle: input.SectionTitle,
|
||||
Status: input.Status,
|
||||
ExclusionJustification: input.ExclusionJustification,
|
||||
FrameworkID: input.FrameworkID,
|
||||
Name: input.Name,
|
||||
Description: input.Description,
|
||||
SectionTitle: input.SectionTitle,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
@@ -1207,12 +1205,10 @@ func (r *Resolver) UpdateControlTool(ctx context.Context, req *mcp.CallToolReque
|
||||
control, err := svc.Controls.Update(
|
||||
ctx,
|
||||
probo.UpdateControlRequest{
|
||||
ID: input.ID,
|
||||
Name: input.Name,
|
||||
Description: UnwrapOmittable(input.Description),
|
||||
SectionTitle: input.SectionTitle,
|
||||
Status: input.Status,
|
||||
ExclusionJustification: input.ExclusionJustification,
|
||||
ID: input.ID,
|
||||
Name: input.Name,
|
||||
Description: UnwrapOmittable(input.Description),
|
||||
SectionTitle: input.SectionTitle,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
|
||||
@@ -2758,13 +2758,6 @@ components:
|
||||
audit:
|
||||
$ref: "#/components/schemas/Audit"
|
||||
|
||||
ControlStatus:
|
||||
type: string
|
||||
enum:
|
||||
- INCLUDED
|
||||
- EXCLUDED
|
||||
go.probo.inc/mcpgen/type: go.probo.inc/probo/pkg/coredata.ControlStatus
|
||||
|
||||
ControlOrderField:
|
||||
type: string
|
||||
enum:
|
||||
@@ -2793,7 +2786,6 @@ components:
|
||||
- framework_id
|
||||
- section_title
|
||||
- name
|
||||
- status
|
||||
- created_at
|
||||
- updated_at
|
||||
properties:
|
||||
@@ -2817,14 +2809,6 @@ components:
|
||||
- string
|
||||
- "null"
|
||||
description: Control description
|
||||
status:
|
||||
$ref: "#/components/schemas/ControlStatus"
|
||||
description: Control status
|
||||
exclusion_justification:
|
||||
type:
|
||||
- string
|
||||
- "null"
|
||||
description: Exclusion justification
|
||||
created_at:
|
||||
type: string
|
||||
format: date-time
|
||||
@@ -2914,12 +2898,6 @@ components:
|
||||
description:
|
||||
type: string
|
||||
description: Control description
|
||||
status:
|
||||
$ref: "#/components/schemas/ControlStatus"
|
||||
description: Control status
|
||||
exclusion_justification:
|
||||
type: string
|
||||
description: Exclusion justification
|
||||
|
||||
AddControlOutput:
|
||||
type: object
|
||||
@@ -2947,16 +2925,6 @@ components:
|
||||
type: ["string", "null"]
|
||||
description: Control description
|
||||
go.probo.inc/mcpgen/omittable: true
|
||||
status:
|
||||
anyOf:
|
||||
- $ref: "#/components/schemas/ControlStatus"
|
||||
description: Control status
|
||||
- type: "null"
|
||||
description: No status
|
||||
description: Control status
|
||||
exclusion_justification:
|
||||
type: string
|
||||
description: Exclusion justification
|
||||
|
||||
UpdateControlOutput:
|
||||
type: object
|
||||
|
||||
@@ -20,16 +20,14 @@ import (
|
||||
|
||||
func NewControl(c *coredata.Control) *Control {
|
||||
return &Control{
|
||||
ID: c.ID,
|
||||
OrganizationID: c.OrganizationID,
|
||||
SectionTitle: c.SectionTitle,
|
||||
FrameworkID: c.FrameworkID,
|
||||
Name: c.Name,
|
||||
Description: c.Description,
|
||||
Status: c.Status,
|
||||
ExclusionJustification: c.ExclusionJustification,
|
||||
CreatedAt: c.CreatedAt,
|
||||
UpdatedAt: c.UpdatedAt,
|
||||
ID: c.ID,
|
||||
OrganizationID: c.OrganizationID,
|
||||
SectionTitle: c.SectionTitle,
|
||||
FrameworkID: c.FrameworkID,
|
||||
Name: c.Name,
|
||||
Description: c.Description,
|
||||
CreatedAt: c.CreatedAt,
|
||||
UpdatedAt: c.UpdatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,8 +21,8 @@ var (
|
||||
AddAuditToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"audit":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"framework_id":{"type":"string","format":"string"},"id":{"type":"string","format":"string"},"name":{"description":"Audit name"},"organization_id":{"type":"string","format":"string"},"state":{"type":"string","enum":["NOT_STARTED","IN_PROGRESS","COMPLETED","REJECTED","OUTDATED"]},"trust_center_visibility":{"type":"string","enum":["NONE","PRIVATE","PUBLIC"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"},"valid_from":{"description":"Valid from date","format":"date-time"},"valid_until":{"description":"Valid until date","format":"date-time"}},"required":["id","organization_id","framework_id","state","trust_center_visibility","created_at","updated_at"]}},"required":["audit"]}`)
|
||||
AddContinualImprovementToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"description":{"type":"string","description":"Description"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"priority":{"description":"Priority","anyOf":[{"type":"string","enum":["LOW","MEDIUM","HIGH"]},{"type":"null","description":"No priority"}]},"reference_id":{"type":"string","description":"Reference ID"},"source":{"type":"string","description":"Source"},"status":{"description":"Status","anyOf":[{"type":"string","enum":["OPEN","IN_PROGRESS","CLOSED"]},{"type":"null","description":"No status"}]},"target_date":{"type":"string","description":"Target date","format":"date-time"}},"required":["organization_id","reference_id","owner_id"]}`)
|
||||
AddContinualImprovementToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"continual_improvement":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Description"},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"priority":{"type":"string","enum":["LOW","MEDIUM","HIGH"]},"reference_id":{"type":"string","description":"Reference ID"},"snapshot_id":{"description":"Snapshot ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No snapshot"}]},"source":{"description":"Source"},"source_id":{"description":"Source ID"},"status":{"type":"string","enum":["OPEN","IN_PROGRESS","CLOSED"]},"target_date":{"description":"Target date","format":"date-time"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","reference_id","owner_id","status","priority","created_at","updated_at"]}},"required":["continual_improvement"]}`)
|
||||
AddControlToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"description":{"type":"string","description":"Control description"},"exclusion_justification":{"type":"string","description":"Exclusion justification"},"framework_id":{"type":"string","format":"string"},"name":{"type":"string","description":"Control name"},"organization_id":{"type":"string","format":"string"},"section_title":{"type":"string","description":"Section title"},"status":{"type":"string","enum":["INCLUDED","EXCLUDED"]}},"required":["organization_id","framework_id","section_title","name"]}`)
|
||||
AddControlToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"control":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Control description"},"exclusion_justification":{"description":"Exclusion justification"},"framework_id":{"type":"string","format":"string"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Control name"},"organization_id":{"type":"string","format":"string"},"section_title":{"type":"string","description":"Section title"},"status":{"type":"string","enum":["INCLUDED","EXCLUDED"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","framework_id","section_title","name","status","created_at","updated_at"]}},"required":["control"]}`)
|
||||
AddControlToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"description":{"type":"string","description":"Control description"},"framework_id":{"type":"string","format":"string"},"name":{"type":"string","description":"Control name"},"organization_id":{"type":"string","format":"string"},"section_title":{"type":"string","description":"Section title"}},"required":["organization_id","framework_id","section_title","name"]}`)
|
||||
AddControlToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"control":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Control description"},"framework_id":{"type":"string","format":"string"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Control name"},"organization_id":{"type":"string","format":"string"},"section_title":{"type":"string","description":"Section title"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","framework_id","section_title","name","created_at","updated_at"]}},"required":["control"]}`)
|
||||
AddDatumToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"data_classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"name":{"type":"string","description":"Datum name"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"vendor_ids":{"type":"array","items":{"type":"string","format":"string"},"description":"Vendor IDs"}},"required":["organization_id","name","data_classification","owner_id"]}`)
|
||||
AddDatumToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"datum":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"data_classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Datum name"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"snapshot_id":{"description":"Snapshot ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No snapshot"}]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","name","data_classification","owner_id","created_at","updated_at"]}},"required":["datum"]}`)
|
||||
AddDocumentToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"approver_ids":{"type":"array","items":{"type":"string","format":"string"},"description":"Approver IDs"},"classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"content":{"type":"string","description":"Document content"},"document_type":{"type":"string","enum":["OTHER","ISMS","POLICY","PROCEDURE"]},"organization_id":{"type":"string","format":"string"},"title":{"type":"string","description":"Document title"},"trust_center_visibility":{"type":"string","enum":["NONE","PRIVATE","PUBLIC"]}},"required":["organization_id","title","content","approver_ids","classification","document_type"]}`)
|
||||
@@ -54,11 +54,11 @@ var (
|
||||
DeleteDraftDocumentVersionToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"document_version_id":{"type":"string","format":"string"}},"required":["document_version_id"]}`)
|
||||
DeleteDraftDocumentVersionToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"deleted_document_version_id":{"type":"string","format":"string"}},"required":["deleted_document_version_id"]}`)
|
||||
DeleteMeetingToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"id":{"type":"string","format":"string"}},"required":["id"]}`)
|
||||
DeleteTaskToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"id":{"type":"string","format":"string"}},"required":["id"]}`)
|
||||
DeleteTaskToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"deleted_task_id":{"type":"string","format":"string"}},"required":["deleted_task_id"]}`)
|
||||
DeleteMeetingToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"deleted_meeting_id":{"type":"string","format":"string"}},"required":["deleted_meeting_id"]}`)
|
||||
DeleteRiskToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"id":{"type":"string","format":"string"}},"required":["id"]}`)
|
||||
DeleteRiskToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"deleted_risk_id":{"type":"string","format":"string"}},"required":["deleted_risk_id"]}`)
|
||||
DeleteTaskToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"id":{"type":"string","format":"string"}},"required":["id"]}`)
|
||||
DeleteTaskToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"deleted_task_id":{"type":"string","format":"string"}},"required":["deleted_task_id"]}`)
|
||||
GetAssetToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"id":{"type":"string","format":"string"}},"required":["id"]}`)
|
||||
GetAssetToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"asset":{"type":"object","properties":{"amount":{"type":"integer","description":"Asset amount"},"asset_type":{"type":"string","enum":["PHYSICAL","VIRTUAL"]},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"data_types_stored":{"type":"string","description":"Data types stored"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Asset name"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"snapshot_id":{"description":"Snapshot ID"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","name","amount","owner_id","asset_type","data_types_stored","created_at","updated_at"]}},"required":["asset"]}`)
|
||||
GetAuditToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"id":{"type":"string","format":"string"}},"required":["id"]}`)
|
||||
@@ -66,7 +66,7 @@ var (
|
||||
GetContinualImprovementToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"id":{"type":"string","format":"string"}},"required":["id"]}`)
|
||||
GetContinualImprovementToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"continual_improvement":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Description"},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"priority":{"type":"string","enum":["LOW","MEDIUM","HIGH"]},"reference_id":{"type":"string","description":"Reference ID"},"snapshot_id":{"description":"Snapshot ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No snapshot"}]},"source":{"description":"Source"},"source_id":{"description":"Source ID"},"status":{"type":"string","enum":["OPEN","IN_PROGRESS","CLOSED"]},"target_date":{"description":"Target date","format":"date-time"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","reference_id","owner_id","status","priority","created_at","updated_at"]}},"required":["continual_improvement"]}`)
|
||||
GetControlToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"id":{"type":"string","format":"string"}},"required":["id"]}`)
|
||||
GetControlToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"control":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Control description"},"exclusion_justification":{"description":"Exclusion justification"},"framework_id":{"type":"string","format":"string"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Control name"},"organization_id":{"type":"string","format":"string"},"section_title":{"type":"string","description":"Section title"},"status":{"type":"string","enum":["INCLUDED","EXCLUDED"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","framework_id","section_title","name","status","created_at","updated_at"]}},"required":["control"]}`)
|
||||
GetControlToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"control":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Control description"},"framework_id":{"type":"string","format":"string"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Control name"},"organization_id":{"type":"string","format":"string"},"section_title":{"type":"string","description":"Section title"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","framework_id","section_title","name","created_at","updated_at"]}},"required":["control"]}`)
|
||||
GetDatumToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"id":{"type":"string","format":"string"}},"required":["id"]}`)
|
||||
GetDatumToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"datum":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"data_classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Datum name"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"snapshot_id":{"description":"Snapshot ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No snapshot"}]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","name","data_classification","owner_id","created_at","updated_at"]}},"required":["datum"]}`)
|
||||
GetDocumentToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"id":{"type":"string","format":"string"}},"required":["id"]}`)
|
||||
@@ -108,7 +108,7 @@ var (
|
||||
ListContinualImprovementsToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"cursor":{"type":"string","format":"string"},"filter":{"type":"object","properties":{"snapshot_id":{"type":"string","format":"string"}}},"order_by":{"type":"object","properties":{"direction":{"type":"string","enum":["ASC","DESC"]},"field":{"type":"string","enum":["CREATED_AT","REFERENCE_ID","TARGET_DATE","STATUS","PRIORITY"]}},"required":["field","direction"]},"organization_id":{"type":"string","format":"string"},"size":{"type":"integer","description":"Page size"}},"required":["organization_id"]}`)
|
||||
ListContinualImprovementsToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"continual_improvements":{"type":"array","items":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Description"},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"priority":{"type":"string","enum":["LOW","MEDIUM","HIGH"]},"reference_id":{"type":"string","description":"Reference ID"},"snapshot_id":{"description":"Snapshot ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No snapshot"}]},"source":{"description":"Source"},"source_id":{"description":"Source ID"},"status":{"type":"string","enum":["OPEN","IN_PROGRESS","CLOSED"]},"target_date":{"description":"Target date","format":"date-time"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","reference_id","owner_id","status","priority","created_at","updated_at"]}},"next_cursor":{"type":"string","format":"string"}},"required":["continual_improvements"]}`)
|
||||
ListControlsToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"cursor":{"type":"string","format":"string"},"filter":{"type":"object","properties":{"query":{"type":"string","description":"Search query"}}},"framework_id":{"type":"string","format":"string"},"order_by":{"type":"object","properties":{"direction":{"type":"string","enum":["ASC","DESC"]},"field":{"type":"string","enum":["CREATED_AT","SECTION_TITLE"]}},"required":["field","direction"]},"organization_id":{"type":"string","format":"string"},"size":{"type":"integer","description":"Page size"}},"required":["organization_id"]}`)
|
||||
ListControlsToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"controls":{"type":"array","items":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Control description"},"exclusion_justification":{"description":"Exclusion justification"},"framework_id":{"type":"string","format":"string"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Control name"},"organization_id":{"type":"string","format":"string"},"section_title":{"type":"string","description":"Section title"},"status":{"type":"string","enum":["INCLUDED","EXCLUDED"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","framework_id","section_title","name","status","created_at","updated_at"]}},"next_cursor":{"type":"string","format":"string"}},"required":["controls"]}`)
|
||||
ListControlsToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"controls":{"type":"array","items":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Control description"},"framework_id":{"type":"string","format":"string"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Control name"},"organization_id":{"type":"string","format":"string"},"section_title":{"type":"string","description":"Section title"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","framework_id","section_title","name","created_at","updated_at"]}},"next_cursor":{"type":"string","format":"string"}},"required":["controls"]}`)
|
||||
ListDataToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"cursor":{"type":"string","format":"string"},"filter":{"type":"object","properties":{"snapshot_id":{"type":"string","format":"string"}}},"order_by":{"type":"object","properties":{"direction":{"type":"string","enum":["ASC","DESC"]},"field":{"type":"string","enum":["CREATED_AT","NAME","DATA_CLASSIFICATION"]}},"required":["field","direction"]},"organization_id":{"type":"string","format":"string"},"size":{"type":"integer","description":"Page size"}},"required":["organization_id"]}`)
|
||||
ListDataToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"data_classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Datum name"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"snapshot_id":{"description":"Snapshot ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No snapshot"}]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","name","data_classification","owner_id","created_at","updated_at"]}},"next_cursor":{"type":"string","format":"string"}},"required":["data"]}`)
|
||||
ListDocumentVersionSignaturesToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"cursor":{"type":"string","format":"string"},"document_version_id":{"type":"string","format":"string"},"filter":{"type":"object","properties":{"active_contract":{"type":"boolean","description":"Signatory contract status"},"states":{"type":"array","items":{"type":"string","enum":["REQUESTED","SIGNED"]},"description":"Signature states"}}},"order_by":{"type":"object","properties":{"direction":{"type":"string","enum":["ASC","DESC"]},"field":{"type":"string","enum":["CREATED_AT","SIGNED_AT"]}},"required":["field","direction"]},"size":{"type":"integer","description":"Page size"}},"required":["document_version_id"]}`)
|
||||
@@ -163,8 +163,8 @@ var (
|
||||
UpdateAuditToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"audit":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"framework_id":{"type":"string","format":"string"},"id":{"type":"string","format":"string"},"name":{"description":"Audit name"},"organization_id":{"type":"string","format":"string"},"state":{"type":"string","enum":["NOT_STARTED","IN_PROGRESS","COMPLETED","REJECTED","OUTDATED"]},"trust_center_visibility":{"type":"string","enum":["NONE","PRIVATE","PUBLIC"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"},"valid_from":{"description":"Valid from date","format":"date-time"},"valid_until":{"description":"Valid until date","format":"date-time"}},"required":["id","organization_id","framework_id","state","trust_center_visibility","created_at","updated_at"]}},"required":["audit"]}`)
|
||||
UpdateContinualImprovementToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"description":{"description":"Description"},"id":{"type":"string","format":"string"},"owner_id":{"description":"Owner ID","anyOf":[{"type":"string","format":"string"},{"type":"null"}]},"priority":{"description":"Priority","anyOf":[{"type":"string","enum":["LOW","MEDIUM","HIGH"]},{"type":"null","description":"No priority"}]},"reference_id":{"type":"string","description":"Reference ID"},"source":{"description":"Source"},"status":{"description":"Status","anyOf":[{"type":"string","enum":["OPEN","IN_PROGRESS","CLOSED"]},{"type":"null","description":"No status"}]},"target_date":{"description":"Target date","format":"date-time"}},"required":["id"]}`)
|
||||
UpdateContinualImprovementToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"continual_improvement":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Description"},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"priority":{"type":"string","enum":["LOW","MEDIUM","HIGH"]},"reference_id":{"type":"string","description":"Reference ID"},"snapshot_id":{"description":"Snapshot ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No snapshot"}]},"source":{"description":"Source"},"source_id":{"description":"Source ID"},"status":{"type":"string","enum":["OPEN","IN_PROGRESS","CLOSED"]},"target_date":{"description":"Target date","format":"date-time"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","reference_id","owner_id","status","priority","created_at","updated_at"]}},"required":["continual_improvement"]}`)
|
||||
UpdateControlToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"description":{"description":"Control description"},"exclusion_justification":{"type":"string","description":"Exclusion justification"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Control name"},"section_title":{"type":"string","description":"Section title"},"status":{"description":"Control status","anyOf":[{"type":"string","enum":["INCLUDED","EXCLUDED"]},{"type":"null","description":"No status"}]}},"required":["id"]}`)
|
||||
UpdateControlToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"control":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Control description"},"exclusion_justification":{"description":"Exclusion justification"},"framework_id":{"type":"string","format":"string"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Control name"},"organization_id":{"type":"string","format":"string"},"section_title":{"type":"string","description":"Section title"},"status":{"type":"string","enum":["INCLUDED","EXCLUDED"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","framework_id","section_title","name","status","created_at","updated_at"]}},"required":["control"]}`)
|
||||
UpdateControlToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"description":{"description":"Control description"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Control name"},"section_title":{"type":"string","description":"Section title"}},"required":["id"]}`)
|
||||
UpdateControlToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"control":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Control description"},"framework_id":{"type":"string","format":"string"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Control name"},"organization_id":{"type":"string","format":"string"},"section_title":{"type":"string","description":"Section title"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","framework_id","section_title","name","created_at","updated_at"]}},"required":["control"]}`)
|
||||
UpdateDatumToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"data_classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Datum name"},"owner_id":{"description":"Owner ID","anyOf":[{"type":"string","format":"string"},{"type":"null"}]},"vendor_ids":{"type":"array","items":{"type":"string","format":"string"},"description":"Vendor IDs"}},"required":["id"]}`)
|
||||
UpdateDatumToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"datum":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"data_classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Datum name"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"snapshot_id":{"description":"Snapshot ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No snapshot"}]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","name","data_classification","owner_id","created_at","updated_at"]}},"required":["datum"]}`)
|
||||
UpdateDocumentToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"approver_ids":{"type":"array","items":{"type":"string","format":"string"},"description":"Approver IDs"},"classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"document_type":{"type":"string","enum":["OTHER","ISMS","POLICY","PROCEDURE"]},"id":{"type":"string","format":"string"},"title":{"type":"string","description":"Document title"},"trust_center_visibility":{"type":"string","enum":["NONE","PRIVATE","PUBLIC"]}},"required":["id"]}`)
|
||||
@@ -564,8 +564,6 @@ type AddContinualImprovementOutput struct {
|
||||
type AddControlInput struct {
|
||||
// Control description
|
||||
Description *string `json:"description,omitempty"`
|
||||
// Exclusion justification
|
||||
ExclusionJustification *string `json:"exclusion_justification,omitempty"`
|
||||
// Framework ID
|
||||
FrameworkID gid.GID `json:"framework_id"`
|
||||
// Control name
|
||||
@@ -574,8 +572,6 @@ type AddControlInput struct {
|
||||
OrganizationID gid.GID `json:"organization_id"`
|
||||
// Section title
|
||||
SectionTitle string `json:"section_title"`
|
||||
// Control status
|
||||
Status *coredata.ControlStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// AddControlOutput represents the schema
|
||||
@@ -975,8 +971,6 @@ type Control struct {
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
// Control description
|
||||
Description *string `json:"description,omitempty"`
|
||||
// Exclusion justification
|
||||
ExclusionJustification *string `json:"exclusion_justification,omitempty"`
|
||||
// Framework ID
|
||||
FrameworkID gid.GID `json:"framework_id"`
|
||||
// Control ID
|
||||
@@ -987,8 +981,6 @@ type Control struct {
|
||||
OrganizationID gid.GID `json:"organization_id"`
|
||||
// Section title
|
||||
SectionTitle string `json:"section_title"`
|
||||
// Control status
|
||||
Status coredata.ControlStatus `json:"status"`
|
||||
// Update timestamp
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
@@ -1088,6 +1080,18 @@ type DeleteRiskOutput struct {
|
||||
DeletedRiskID gid.GID `json:"deleted_risk_id"`
|
||||
}
|
||||
|
||||
// DeleteTaskInput represents the schema
|
||||
type DeleteTaskInput struct {
|
||||
// Task ID
|
||||
ID gid.GID `json:"id"`
|
||||
}
|
||||
|
||||
// DeleteTaskOutput represents the schema
|
||||
type DeleteTaskOutput struct {
|
||||
// Deleted task ID
|
||||
DeletedTaskID gid.GID `json:"deleted_task_id"`
|
||||
}
|
||||
|
||||
// Document represents the schema
|
||||
type Document struct {
|
||||
// Approver IDs
|
||||
@@ -2171,18 +2175,6 @@ type UnassignTaskOutput struct {
|
||||
Task *Task `json:"task"`
|
||||
}
|
||||
|
||||
// DeleteTaskInput represents the schema
|
||||
type DeleteTaskInput struct {
|
||||
// Task ID
|
||||
ID gid.GID `json:"id"`
|
||||
}
|
||||
|
||||
// DeleteTaskOutput represents the schema
|
||||
type DeleteTaskOutput struct {
|
||||
// Deleted task ID
|
||||
DeletedTaskID gid.GID `json:"deleted_task_id"`
|
||||
}
|
||||
|
||||
// UnlinkControlAuditInput represents the schema
|
||||
type UnlinkControlAuditInput struct {
|
||||
// Audit ID
|
||||
@@ -2304,16 +2296,12 @@ type UpdateContinualImprovementOutput struct {
|
||||
type UpdateControlInput struct {
|
||||
// Control description
|
||||
Description mcp.Omittable[*string] `json:"description,omitempty"`
|
||||
// Exclusion justification
|
||||
ExclusionJustification *string `json:"exclusion_justification,omitempty"`
|
||||
// Control ID
|
||||
ID gid.GID `json:"id"`
|
||||
// Control name
|
||||
Name *string `json:"name,omitempty"`
|
||||
// Section title
|
||||
SectionTitle *string `json:"section_title,omitempty"`
|
||||
// Control status
|
||||
Status *coredata.ControlStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// UpdateControlOutput represents the schema
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
|
||||
//
|
||||
// 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 soagen
|
||||
|
||||
import "github.com/xuri/excelize/v2"
|
||||
|
||||
type Applicability struct {
|
||||
Value string
|
||||
IsApplicable bool
|
||||
}
|
||||
|
||||
func NewApplicability(value string, isApplicable bool) Applicability {
|
||||
return Applicability{
|
||||
Value: value,
|
||||
IsApplicable: isApplicable,
|
||||
}
|
||||
}
|
||||
|
||||
func (a Applicability) String() string {
|
||||
return a.Value
|
||||
}
|
||||
|
||||
func (a Applicability) MarshalExcel() ExcelValue {
|
||||
color := "FFB6C1" // Light red for not applicable
|
||||
if a.IsApplicable {
|
||||
color = "90EE90" // Light green for applicable
|
||||
}
|
||||
|
||||
return ExcelValue{
|
||||
Value: a.Value,
|
||||
Style: &excelize.Style{
|
||||
Border: []excelize.Border{
|
||||
{Type: "left", Color: "000000", Style: 1},
|
||||
{Type: "top", Color: "000000", Style: 1},
|
||||
{Type: "bottom", Color: "000000", Style: 1},
|
||||
{Type: "right", Color: "000000", Style: 1},
|
||||
},
|
||||
Fill: excelize.Fill{Type: "pattern", Color: []string{color}, Pattern: 1},
|
||||
Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center", WrapText: true},
|
||||
},
|
||||
Validation: []string{"Yes", "No"},
|
||||
Width: 12,
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
|
||||
//
|
||||
// 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 soagen
|
||||
|
||||
import "github.com/xuri/excelize/v2"
|
||||
|
||||
type ExcelValue struct {
|
||||
Value interface{}
|
||||
Style *excelize.Style
|
||||
Validation []string
|
||||
Width float64
|
||||
}
|
||||
|
||||
type ExcelMarshaler interface {
|
||||
MarshalExcel() ExcelValue
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
|
||||
//
|
||||
// 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 soagen
|
||||
|
||||
type FieldConfiguration struct {
|
||||
Field string
|
||||
Columns []string
|
||||
FilterColumns []string // Specific columns that should have filters (subset of Columns)
|
||||
Width []float64 // Width for each column
|
||||
DefaultWidth float64 // Default width if not specified
|
||||
HasFilter bool // Whether to enable auto-filter
|
||||
}
|
||||
|
||||
var (
|
||||
soaFieldConfigs = []FieldConfiguration{
|
||||
{
|
||||
Field: "SectionTitle",
|
||||
Columns: []string{"A"},
|
||||
FilterColumns: []string{},
|
||||
Width: []float64{12},
|
||||
DefaultWidth: 12,
|
||||
HasFilter: false,
|
||||
},
|
||||
{
|
||||
Field: "ControlName",
|
||||
Columns: []string{"B"},
|
||||
FilterColumns: []string{},
|
||||
Width: []float64{35},
|
||||
DefaultWidth: 35,
|
||||
HasFilter: false,
|
||||
},
|
||||
{
|
||||
Field: "Applicability",
|
||||
Columns: []string{"C"},
|
||||
FilterColumns: []string{"C"},
|
||||
Width: []float64{12},
|
||||
DefaultWidth: 12,
|
||||
HasFilter: true,
|
||||
},
|
||||
{
|
||||
Field: "ExclusionJustification",
|
||||
Columns: []string{"D"},
|
||||
FilterColumns: []string{},
|
||||
Width: []float64{25},
|
||||
DefaultWidth: 25,
|
||||
HasFilter: false,
|
||||
},
|
||||
{
|
||||
Field: "Regulatory",
|
||||
Columns: []string{"E"},
|
||||
FilterColumns: []string{},
|
||||
Width: []float64{12},
|
||||
DefaultWidth: 12,
|
||||
HasFilter: false,
|
||||
},
|
||||
{
|
||||
Field: "Contractual",
|
||||
Columns: []string{"F"},
|
||||
FilterColumns: []string{},
|
||||
Width: []float64{12},
|
||||
DefaultWidth: 12,
|
||||
HasFilter: false,
|
||||
},
|
||||
{
|
||||
Field: "BestPractice",
|
||||
Columns: []string{"G"},
|
||||
FilterColumns: []string{},
|
||||
Width: []float64{12},
|
||||
DefaultWidth: 12,
|
||||
HasFilter: false,
|
||||
},
|
||||
{
|
||||
Field: "RiskAssessment",
|
||||
Columns: []string{"H"},
|
||||
FilterColumns: []string{},
|
||||
Width: []float64{12},
|
||||
DefaultWidth: 12,
|
||||
HasFilter: false,
|
||||
},
|
||||
{
|
||||
Field: "SecurityMeasures",
|
||||
Columns: []string{"I"},
|
||||
FilterColumns: []string{},
|
||||
Width: []float64{40},
|
||||
DefaultWidth: 40,
|
||||
HasFilter: false,
|
||||
},
|
||||
}
|
||||
)
|
||||
@@ -1,319 +0,0 @@
|
||||
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
|
||||
//
|
||||
// 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 soagen
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/xuri/excelize/v2"
|
||||
)
|
||||
|
||||
func GenerateSOAExcel(data SOAData) ([]byte, error) {
|
||||
f := excelize.NewFile()
|
||||
defer func() { _ = f.Close() }()
|
||||
|
||||
sheetName := "State of Applicability"
|
||||
_, err := f.NewSheet(sheetName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot create sheet: %w", err)
|
||||
}
|
||||
|
||||
if err := f.DeleteSheet("Sheet1"); err != nil {
|
||||
return nil, fmt.Errorf("cannot delete sheet: %w", err)
|
||||
}
|
||||
|
||||
if err := setupSOAHeader(f, sheetName); err != nil {
|
||||
return nil, fmt.Errorf("cannot setup Excel header: %w", err)
|
||||
}
|
||||
|
||||
if err := populateSOAData(f, sheetName, data.Rows); err != nil {
|
||||
return nil, fmt.Errorf("cannot populate Excel data: %w", err)
|
||||
}
|
||||
|
||||
if err := applySOAFinalFormatting(f, sheetName, len(data.Rows)); err != nil {
|
||||
return nil, fmt.Errorf("cannot apply final formatting: %w", err)
|
||||
}
|
||||
|
||||
buf, err := f.WriteToBuffer()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot write Excel file to buffer: %w", err)
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
func setupSOAHeader(f *excelize.File, sheetName string) error {
|
||||
headerStyle, err := f.NewStyle(getHeaderStyle())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cellStyle, err := f.NewStyle(getCellStyle())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return applyHeaderLayout(f, sheetName, getSOAHeaderLayout(), headerStyle, cellStyle)
|
||||
}
|
||||
|
||||
func populateSOAData(f *excelize.File, sheetName string, rows []SOARowData) error {
|
||||
dataStartRow := 8
|
||||
|
||||
for i, rowData := range rows {
|
||||
isFirstRow := i == 0
|
||||
filterColumns, err := writeSOARow(f, sheetName, dataStartRow+i, rowData, isFirstRow)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot write row %d: %w", dataStartRow+i, err)
|
||||
}
|
||||
|
||||
if isFirstRow && len(filterColumns) > 0 {
|
||||
if err := applySOAAutoFilter(f, sheetName, filterColumns); err != nil {
|
||||
return fmt.Errorf("cannot apply auto filter: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeSOARow(f *excelize.File, sheetName string, row int, data SOARowData, isFirstRow bool) ([]string, error) {
|
||||
var allFilterColumns []string
|
||||
|
||||
fields := []struct {
|
||||
name string
|
||||
value interface{}
|
||||
}{
|
||||
{"SectionTitle", data.SectionTitle},
|
||||
{"ControlName", data.ControlName},
|
||||
{"Applicability", data.Applicability},
|
||||
{"Regulatory", data.Regulatory},
|
||||
{"Contractual", data.Contractual},
|
||||
{"BestPractice", data.BestPractice},
|
||||
{"RiskAssessment", data.RiskAssessment},
|
||||
{"ExclusionJustification", data.ExclusionJustification},
|
||||
{"SecurityMeasures", data.SecurityMeasures},
|
||||
}
|
||||
|
||||
for _, field := range fields {
|
||||
fieldConfig := getSOAFieldConfig(field.name)
|
||||
if fieldConfig == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
filterColumns, err := processField(f, sheetName, row, field.value, *fieldConfig, isFirstRow)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot write field %s: %w", field.name, err)
|
||||
}
|
||||
|
||||
allFilterColumns = append(allFilterColumns, filterColumns...)
|
||||
}
|
||||
|
||||
return allFilterColumns, nil
|
||||
}
|
||||
|
||||
func getSOAFieldConfig(fieldName string) *FieldConfiguration {
|
||||
for _, config := range soaFieldConfigs {
|
||||
if config.Field == fieldName {
|
||||
return &config
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func applySOAAutoFilter(f *excelize.File, sheetName string, filterColumns []string) error {
|
||||
if len(filterColumns) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
firstCol, lastCol := filterColumns[0], filterColumns[0]
|
||||
for _, col := range filterColumns {
|
||||
if col < firstCol {
|
||||
firstCol = col
|
||||
}
|
||||
if col > lastCol {
|
||||
lastCol = col
|
||||
}
|
||||
}
|
||||
|
||||
filterRange := fmt.Sprintf("%s7:%s1000", firstCol, lastCol)
|
||||
return f.AutoFilter(sheetName, filterRange, []excelize.AutoFilterOptions{})
|
||||
}
|
||||
|
||||
func applySOAFinalFormatting(f *excelize.File, sheetName string, dataRowCount int) error {
|
||||
if dataRowCount > 0 {
|
||||
headerRowHeight := 30.0
|
||||
_ = f.SetRowHeight(sheetName, 6, headerRowHeight)
|
||||
_ = f.SetRowHeight(sheetName, 7, headerRowHeight)
|
||||
|
||||
return f.SetPanes(sheetName, &excelize.Panes{
|
||||
Freeze: true,
|
||||
XSplit: 0,
|
||||
YSplit: 7,
|
||||
TopLeftCell: "A8",
|
||||
})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func processField(f *excelize.File, sheetName string, row int, value interface{}, config FieldConfiguration, isFirstRow bool) ([]string, error) {
|
||||
switch v := value.(type) {
|
||||
case ExcelMarshaler:
|
||||
marshaler := v
|
||||
excelValue := marshaler.MarshalExcel()
|
||||
|
||||
styleID, err := createCellStyle(f, excelValue.Style)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return writeSingleColumnField(f, sheetName, row, excelValue, &config, styleID, isFirstRow)
|
||||
|
||||
case string:
|
||||
if len(config.Columns) == 0 {
|
||||
return []string{}, nil
|
||||
}
|
||||
|
||||
col := config.Columns[0]
|
||||
cellRef := fmt.Sprintf("%s%d", col, row)
|
||||
|
||||
if err := f.SetCellValue(sheetName, cellRef, v); err != nil {
|
||||
return nil, fmt.Errorf("cannot set cell value: %w", err)
|
||||
}
|
||||
|
||||
textStyleID, err := createCellStyle(f, getTextStyle())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot create text style: %w", err)
|
||||
}
|
||||
if err := f.SetCellStyle(sheetName, cellRef, cellRef, textStyleID); err != nil {
|
||||
return nil, fmt.Errorf("cannot set cell style: %w", err)
|
||||
}
|
||||
|
||||
if isFirstRow {
|
||||
width := config.DefaultWidth
|
||||
if len(config.Width) > 0 {
|
||||
width = config.Width[0]
|
||||
}
|
||||
if err := f.SetColWidth(sheetName, col, col, width); err != nil {
|
||||
return nil, fmt.Errorf("cannot set column width: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if config.HasFilter {
|
||||
if len(config.FilterColumns) > 0 {
|
||||
return config.FilterColumns, nil
|
||||
}
|
||||
return []string{col}, nil
|
||||
}
|
||||
return []string{}, nil
|
||||
|
||||
case []string:
|
||||
var formattedLines []string
|
||||
for _, item := range v {
|
||||
lines := strings.Split(item, "\n")
|
||||
for _, line := range lines {
|
||||
if strings.TrimSpace(line) != "" {
|
||||
formattedLines = append(formattedLines, "• "+strings.TrimSpace(line))
|
||||
}
|
||||
}
|
||||
}
|
||||
joinedValue := strings.Join(formattedLines, "\n")
|
||||
|
||||
if len(config.Columns) == 0 {
|
||||
return []string{}, nil
|
||||
}
|
||||
|
||||
col := config.Columns[0]
|
||||
cellRef := fmt.Sprintf("%s%d", col, row)
|
||||
|
||||
if err := f.SetCellValue(sheetName, cellRef, joinedValue); err != nil {
|
||||
return nil, fmt.Errorf("cannot set cell value: %w", err)
|
||||
}
|
||||
|
||||
textStyleID, err := createCellStyle(f, getTextStyle())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot create text style: %w", err)
|
||||
}
|
||||
if err := f.SetCellStyle(sheetName, cellRef, cellRef, textStyleID); err != nil {
|
||||
return nil, fmt.Errorf("cannot set cell style: %w", err)
|
||||
}
|
||||
|
||||
if isFirstRow {
|
||||
width := config.DefaultWidth
|
||||
if len(config.Width) > 0 {
|
||||
width = config.Width[0]
|
||||
}
|
||||
if err := f.SetColWidth(sheetName, col, col, width); err != nil {
|
||||
return nil, fmt.Errorf("cannot set column width: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if config.HasFilter {
|
||||
if len(config.FilterColumns) > 0 {
|
||||
return config.FilterColumns, nil
|
||||
}
|
||||
return []string{col}, nil
|
||||
}
|
||||
return []string{}, nil
|
||||
|
||||
case *bool:
|
||||
yesNoValue := boolToYesNo(v)
|
||||
excelValue := yesNoValue.MarshalExcel()
|
||||
|
||||
styleID, err := createCellStyle(f, excelValue.Style)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return writeSingleColumnField(f, sheetName, row, excelValue, &config, styleID, isFirstRow)
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("no handler found for field type: %T", value)
|
||||
}
|
||||
}
|
||||
|
||||
func GenerateExcel(data SOAData) ([]byte, error) {
|
||||
return GenerateSOAExcel(data)
|
||||
}
|
||||
|
||||
func writeSingleColumnField(f *excelize.File, sheetName string, row int, excelValue ExcelValue, colDef *FieldConfiguration, styleID int, isFirstRow bool) ([]string, error) {
|
||||
if len(colDef.Columns) == 0 {
|
||||
return []string{}, nil
|
||||
}
|
||||
|
||||
col := colDef.Columns[0]
|
||||
cellRef := fmt.Sprintf("%s%d", col, row)
|
||||
|
||||
_ = f.SetCellValue(sheetName, cellRef, excelValue.Value)
|
||||
_ = f.SetCellStyle(sheetName, cellRef, cellRef, styleID)
|
||||
|
||||
if isFirstRow {
|
||||
if err := applyDataValidation(f, sheetName, col, row, excelValue.Validation); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := setColumnWidth(f, sheetName, col, excelValue.Width); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if colDef.HasFilter {
|
||||
if len(colDef.FilterColumns) > 0 {
|
||||
return colDef.FilterColumns, nil
|
||||
}
|
||||
return []string{col}, nil
|
||||
}
|
||||
return []string{}, nil
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
|
||||
//
|
||||
// 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 soagen
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/xuri/excelize/v2"
|
||||
)
|
||||
|
||||
type HeaderCell struct {
|
||||
Cell string
|
||||
Value string
|
||||
Style string // "header" or "cell"
|
||||
}
|
||||
|
||||
type MergedCell struct {
|
||||
StartCell string
|
||||
EndCell string
|
||||
}
|
||||
|
||||
type HeaderLayout struct {
|
||||
InfoHeader []HeaderCell
|
||||
InfoData []HeaderCell
|
||||
MainHeader []HeaderCell
|
||||
SubHeader []HeaderCell
|
||||
Merges []MergedCell
|
||||
}
|
||||
|
||||
func getSOAHeaderLayout() HeaderLayout {
|
||||
return HeaderLayout{
|
||||
InfoHeader: []HeaderCell{
|
||||
{"A2", "Version", "header"},
|
||||
{"C2", "Date", "header"},
|
||||
{"D2", "Comment", "header"},
|
||||
{"E2", "Author", "header"},
|
||||
{"F2", "Approver", "header"},
|
||||
},
|
||||
InfoData: []HeaderCell{
|
||||
{"A3", "1.0", "cell"},
|
||||
{"C3", time.Now().Format("01/02/2006"), "cell"},
|
||||
{"D3", "Initial SoA", "cell"},
|
||||
{"E3", "System Admin", "cell"},
|
||||
{"F3", "Security Manager", "cell"},
|
||||
},
|
||||
MainHeader: []HeaderCell{
|
||||
{"A6", "Control", "header"},
|
||||
{"B6", "Control name", "header"},
|
||||
{"C6", "Applicability", "header"},
|
||||
{"D6", "Justification for exclusion", "header"},
|
||||
{"E6", "Justification for inclusion", "header"},
|
||||
{"F6", "Justification for inclusion", "header"},
|
||||
{"G6", "Justification for inclusion", "header"},
|
||||
{"H6", "Justification for inclusion", "header"},
|
||||
{"I6", "List of security measure or policy", "header"},
|
||||
},
|
||||
SubHeader: []HeaderCell{
|
||||
{"A7", "Control", "header"},
|
||||
{"B7", "Control name", "header"},
|
||||
{"C7", "Applicability", "header"},
|
||||
{"D7", "Justification for exclusion", "header"},
|
||||
{"E7", "Regulatory", "header"},
|
||||
{"F7", "Contractual", "header"},
|
||||
{"G7", "Best practice", "header"},
|
||||
{"H7", "Risk assessment", "header"},
|
||||
{"I7", "List of security measure or policy", "header"},
|
||||
},
|
||||
Merges: []MergedCell{
|
||||
{"A6", "A7"},
|
||||
{"B6", "B7"},
|
||||
{"C6", "C7"},
|
||||
{"D6", "D7"},
|
||||
{"E6", "H6"},
|
||||
{"I6", "I7"},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func applyHeaderLayout(f *excelize.File, sheetName string, layout HeaderLayout, headerStyle, cellStyle int) error {
|
||||
if err := applyCells(f, sheetName, layout.InfoHeader, headerStyle, cellStyle); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := applyCells(f, sheetName, layout.InfoData, headerStyle, cellStyle); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := applyCells(f, sheetName, layout.MainHeader, headerStyle, cellStyle); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := applyCells(f, sheetName, layout.SubHeader, headerStyle, cellStyle); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, merge := range layout.Merges {
|
||||
if err := f.MergeCell(sheetName, merge.StartCell, merge.EndCell); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func applyCells(f *excelize.File, sheetName string, cells []HeaderCell, headerStyle, cellStyle int) error {
|
||||
for _, cell := range cells {
|
||||
if err := f.SetCellValue(sheetName, cell.Cell, cell.Value); err != nil {
|
||||
return fmt.Errorf("cannot set cell value: %w", err)
|
||||
}
|
||||
|
||||
style := cellStyle
|
||||
if cell.Style == "header" {
|
||||
style = headerStyle
|
||||
}
|
||||
|
||||
if err := f.SetCellStyle(sheetName, cell.Cell, cell.Cell, style); err != nil {
|
||||
return fmt.Errorf("cannot set cell style: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
|
||||
//
|
||||
// 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 soagen
|
||||
|
||||
// SOARowData represents a single row in the State of Applicability Excel
|
||||
type SOARowData struct {
|
||||
SectionTitle string
|
||||
ControlName string
|
||||
Applicability Applicability
|
||||
Regulatory *bool
|
||||
Contractual *bool
|
||||
BestPractice *bool
|
||||
RiskAssessment *bool
|
||||
ExclusionJustification string
|
||||
SecurityMeasures []string
|
||||
}
|
||||
|
||||
// SOAData contains all the data needed for State of Applicability generation
|
||||
type SOAData struct {
|
||||
Rows []SOARowData
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
|
||||
//
|
||||
// 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 soagen
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/xuri/excelize/v2"
|
||||
)
|
||||
|
||||
// getTextStyle returns the standard text style for string fields
|
||||
func getTextStyle() *excelize.Style {
|
||||
return &excelize.Style{
|
||||
Border: []excelize.Border{
|
||||
{Type: "left", Color: "#000000", Style: 1},
|
||||
{Type: "top", Color: "#000000", Style: 1},
|
||||
{Type: "bottom", Color: "#000000", Style: 1},
|
||||
{Type: "right", Color: "#000000", Style: 1},
|
||||
},
|
||||
Alignment: &excelize.Alignment{Horizontal: "left", Vertical: "center", WrapText: true},
|
||||
}
|
||||
}
|
||||
|
||||
// getHeaderStyle returns the standard header style
|
||||
func getHeaderStyle() *excelize.Style {
|
||||
return &excelize.Style{
|
||||
Font: &excelize.Font{Bold: true, Size: 10, Color: "#000000"},
|
||||
Fill: excelize.Fill{Type: "pattern", Color: []string{"#D9D9D9"}, Pattern: 1},
|
||||
Border: []excelize.Border{
|
||||
{Type: "left", Color: "#000000", Style: 1},
|
||||
{Type: "top", Color: "#000000", Style: 1},
|
||||
{Type: "bottom", Color: "#000000", Style: 1},
|
||||
{Type: "right", Color: "#000000", Style: 1},
|
||||
},
|
||||
Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center", WrapText: true},
|
||||
}
|
||||
}
|
||||
|
||||
// getCellStyle returns the standard cell style
|
||||
func getCellStyle() *excelize.Style {
|
||||
return &excelize.Style{
|
||||
Border: []excelize.Border{
|
||||
{Type: "left", Color: "#000000", Style: 1},
|
||||
{Type: "top", Color: "#000000", Style: 1},
|
||||
{Type: "bottom", Color: "#000000", Style: 1},
|
||||
{Type: "right", Color: "#000000", Style: 1},
|
||||
},
|
||||
Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center", WrapText: true},
|
||||
}
|
||||
}
|
||||
|
||||
func createCellStyle(f *excelize.File, style *excelize.Style) (int, error) {
|
||||
styleID, err := f.NewStyle(style)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("cannot create style: %w", err)
|
||||
}
|
||||
return styleID, nil
|
||||
}
|
||||
|
||||
func applyDataValidation(f *excelize.File, sheetName, col string, row int, validation []string) error {
|
||||
if len(validation) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
dv := excelize.NewDataValidation(true)
|
||||
dv.Sqref = fmt.Sprintf("%s%d:%s1000", col, row, col) // Apply to reasonable range
|
||||
_ = dv.SetDropList(validation)
|
||||
dv.SetError(excelize.DataValidationErrorStyleStop, "Invalid Input", "Please select from the dropdown list.")
|
||||
if err := f.AddDataValidation(sheetName, dv); err != nil {
|
||||
return fmt.Errorf("cannot add data validation: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func setColumnWidth(f *excelize.File, sheetName, col string, width float64) error {
|
||||
if width > 0 {
|
||||
if err := f.SetColWidth(sheetName, col, col, width); err != nil {
|
||||
return fmt.Errorf("cannot set column width: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
|
||||
//
|
||||
// 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 soagen
|
||||
|
||||
import "github.com/xuri/excelize/v2"
|
||||
|
||||
// YesNo represents a YES/NO/Empty value
|
||||
type YesNo string
|
||||
|
||||
const (
|
||||
Yes YesNo = "YES"
|
||||
No YesNo = "NO"
|
||||
Empty YesNo = ""
|
||||
)
|
||||
|
||||
// String returns the string representation of YesNo
|
||||
func (yn YesNo) String() string {
|
||||
return string(yn)
|
||||
}
|
||||
|
||||
// MarshalExcel implements ExcelMarshaler for YesNo
|
||||
func (yn YesNo) MarshalExcel() ExcelValue {
|
||||
return ExcelValue{
|
||||
Value: yn.String(),
|
||||
Style: &excelize.Style{
|
||||
Border: []excelize.Border{
|
||||
{Type: "left", Color: "#000000", Style: 1},
|
||||
{Type: "top", Color: "#000000", Style: 1},
|
||||
{Type: "bottom", Color: "#000000", Style: 1},
|
||||
{Type: "right", Color: "#000000", Style: 1},
|
||||
},
|
||||
Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center", WrapText: true},
|
||||
},
|
||||
Validation: []string{string(Yes), string(No), string(Empty)},
|
||||
Width: 12,
|
||||
}
|
||||
}
|
||||
|
||||
// boolToYesNo converts *bool to YesNo type for Excel output
|
||||
func boolToYesNo(b *bool) YesNo {
|
||||
if b == nil {
|
||||
return Empty
|
||||
}
|
||||
if *b {
|
||||
return Yes
|
||||
}
|
||||
return No
|
||||
}
|
||||
@@ -154,8 +154,7 @@ func TestValidationErrors_Methods(t *testing.T) {
|
||||
first := errors.First()
|
||||
if first == nil {
|
||||
t.Fatal("expected first error")
|
||||
}
|
||||
if first.Field != "email" {
|
||||
} else if first.Field != "email" {
|
||||
t.Errorf("expected first field to be 'email', got '%s'", first.Field)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -40,8 +40,7 @@ func TestMinItems(t *testing.T) {
|
||||
err := MinItems(2)(&items)
|
||||
if err == nil {
|
||||
t.Fatal("expected validation error")
|
||||
}
|
||||
if err.Code != ErrorCodeOutOfRange {
|
||||
} else if err.Code != ErrorCodeOutOfRange {
|
||||
t.Errorf("expected error code %s, got %s", ErrorCodeOutOfRange, err.Code)
|
||||
}
|
||||
})
|
||||
@@ -85,8 +84,7 @@ func TestMaxItems(t *testing.T) {
|
||||
err := MaxItems(2)(&items)
|
||||
if err == nil {
|
||||
t.Fatal("expected validation error")
|
||||
}
|
||||
if err.Code != ErrorCodeOutOfRange {
|
||||
} else if err.Code != ErrorCodeOutOfRange {
|
||||
t.Errorf("expected error code %s, got %s", ErrorCodeOutOfRange, err.Code)
|
||||
}
|
||||
})
|
||||
@@ -114,8 +112,7 @@ func TestUniqueItems(t *testing.T) {
|
||||
err := UniqueItems()(&items)
|
||||
if err == nil {
|
||||
t.Fatal("expected validation error")
|
||||
}
|
||||
if err.Code != ErrorCodeInvalidFormat {
|
||||
} else if err.Code != ErrorCodeInvalidFormat {
|
||||
t.Errorf("expected error code %s, got %s", ErrorCodeInvalidFormat, err.Code)
|
||||
}
|
||||
})
|
||||
@@ -157,12 +154,13 @@ func TestUniqueItems(t *testing.T) {
|
||||
err := UniqueItems()(&items)
|
||||
if err == nil {
|
||||
t.Fatal("expected validation error for non-comparable type")
|
||||
}
|
||||
if err.Code != ErrorCodeInvalidFormat {
|
||||
t.Errorf("expected error code %s, got %s", ErrorCodeInvalidFormat, err.Code)
|
||||
}
|
||||
if err.Message != "cannot validate uniqueness for non-comparable types" {
|
||||
t.Errorf("unexpected error message: %s", err.Message)
|
||||
} else {
|
||||
if err.Code != ErrorCodeInvalidFormat {
|
||||
t.Errorf("expected error code %s, got %s", ErrorCodeInvalidFormat, err.Code)
|
||||
}
|
||||
if err.Message != "cannot validate uniqueness for non-comparable types" {
|
||||
t.Errorf("unexpected error message: %s", err.Message)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -171,8 +169,7 @@ func TestUniqueItems(t *testing.T) {
|
||||
err := UniqueItems()(&items)
|
||||
if err == nil {
|
||||
t.Fatal("expected validation error for non-comparable type")
|
||||
}
|
||||
if err.Code != ErrorCodeInvalidFormat {
|
||||
} else if err.Code != ErrorCodeInvalidFormat {
|
||||
t.Errorf("expected error code %s, got %s", ErrorCodeInvalidFormat, err.Code)
|
||||
}
|
||||
})
|
||||
@@ -185,8 +182,7 @@ func TestUniqueItems(t *testing.T) {
|
||||
err := UniqueItems()(&items)
|
||||
if err == nil {
|
||||
t.Fatal("expected validation error for non-comparable type")
|
||||
}
|
||||
if err.Code != ErrorCodeInvalidFormat {
|
||||
} else if err.Code != ErrorCodeInvalidFormat {
|
||||
t.Errorf("expected error code %s, got %s", ErrorCodeInvalidFormat, err.Code)
|
||||
}
|
||||
})
|
||||
@@ -212,8 +208,7 @@ func TestUniqueItems(t *testing.T) {
|
||||
err := UniqueItems()(&items)
|
||||
if err == nil {
|
||||
t.Fatal("expected validation error for duplicate comparable structs")
|
||||
}
|
||||
if err.Code != ErrorCodeInvalidFormat {
|
||||
} else if err.Code != ErrorCodeInvalidFormat {
|
||||
t.Errorf("expected error code %s, got %s", ErrorCodeInvalidFormat, err.Code)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -103,8 +103,7 @@ func TestRequired(t *testing.T) {
|
||||
err := Required()(&str)
|
||||
if err == nil {
|
||||
t.Fatal("expected validation error")
|
||||
}
|
||||
if err.Code != ErrorCodeRequired {
|
||||
} else if err.Code != ErrorCodeRequired {
|
||||
t.Errorf("expected error code %s, got %s", ErrorCodeRequired, err.Code)
|
||||
}
|
||||
})
|
||||
@@ -193,8 +192,7 @@ func TestRequired(t *testing.T) {
|
||||
err := Required()(slice)
|
||||
if err == nil {
|
||||
t.Fatal("expected validation error for empty []string slice")
|
||||
}
|
||||
if err.Code != ErrorCodeRequired {
|
||||
} else if err.Code != ErrorCodeRequired {
|
||||
t.Errorf("expected error code %s, got %s", ErrorCodeRequired, err.Code)
|
||||
}
|
||||
})
|
||||
@@ -212,8 +210,7 @@ func TestRequired(t *testing.T) {
|
||||
err := Required()(slice)
|
||||
if err == nil {
|
||||
t.Fatal("expected validation error for empty []int slice")
|
||||
}
|
||||
if err.Code != ErrorCodeRequired {
|
||||
} else if err.Code != ErrorCodeRequired {
|
||||
t.Errorf("expected error code %s, got %s", ErrorCodeRequired, err.Code)
|
||||
}
|
||||
})
|
||||
@@ -234,8 +231,7 @@ func TestRequired(t *testing.T) {
|
||||
err := Required()(slice)
|
||||
if err == nil {
|
||||
t.Fatal("expected validation error for empty custom type slice")
|
||||
}
|
||||
if err.Code != ErrorCodeRequired {
|
||||
} else if err.Code != ErrorCodeRequired {
|
||||
t.Errorf("expected error code %s, got %s", ErrorCodeRequired, err.Code)
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user