Make descriptions nullable

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
Sacha Al Himdani
2025-11-05 16:48:58 +01:00
parent 637f097cc6
commit 288c59a5f2
60 changed files with 311 additions and 375 deletions

View File

@@ -21,11 +21,11 @@ import (
"maps"
"time"
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/page"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgconn"
"go.gearno.de/kit/pg"
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/page"
)
type (
@@ -34,7 +34,7 @@ type (
SectionTitle string `db:"section_title"`
FrameworkID gid.GID `db:"framework_id"`
Name string `db:"name"`
Description string `db:"description"`
Description *string `db:"description"`
Status ControlStatus `db:"status"`
ExclusionJustification *string `db:"exclusion_justification"`
CreatedAt time.Time `db:"created_at"`
@@ -43,14 +43,6 @@ type (
Controls []*Control
UpdateControlParams struct {
Name *string
Description *string
SectionTitle *string
Status *ControlStatus
ExclusionJustification *string
}
ErrControlNotFound struct {
Identifier string
}
@@ -793,79 +785,45 @@ func (c *Control) Update(
ctx context.Context,
conn pg.Conn,
scope Scoper,
params UpdateControlParams,
) error {
q := `
UPDATE controls SET
name = COALESCE(@name, name),
description = COALESCE(@description, description),
section_title = COALESCE(@section_title, section_title),
status = COALESCE(@status, status),
exclusion_justification = COALESCE(@exclusion_justification, exclusion_justification),
name = @name,
description = @description,
section_title = @section_title,
status = @status,
exclusion_justification = @exclusion_justification,
updated_at = @updated_at
WHERE %s
AND id = @control_id
RETURNING
id,
framework_id,
name,
description,
section_title,
status,
exclusion_justification,
created_at,
updated_at
`
q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{
"control_id": c.ID,
"section_title": params.SectionTitle,
"status": params.Status,
"exclusion_justification": params.ExclusionJustification,
"updated_at": time.Now(),
}
if params.Name != nil {
args["name"] = *params.Name
}
if params.Description != nil {
args["description"] = *params.Description
}
if params.Status != nil {
args["status"] = *params.Status
}
if params.ExclusionJustification != nil {
args["exclusion_justification"] = *params.ExclusionJustification
"name": c.Name,
"description": c.Description,
"section_title": c.SectionTitle,
"status": c.Status,
"exclusion_justification": c.ExclusionJustification,
"updated_at": c.UpdatedAt,
}
maps.Copy(args, scope.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query controls: %w", err)
}
control, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[Control])
_, err := conn.Exec(ctx, q, args)
if err != nil {
var pgErr *pgconn.PgError
if errors.As(err, &pgErr) {
if pgErr.Code == "23505" && pgErr.ConstraintName == "controls_framework_ref_unique" {
sectionTitle := ""
if params.SectionTitle != nil {
sectionTitle = *params.SectionTitle
}
return &ErrControlAlreadyExists{
message: fmt.Sprintf("control with section_title %q already exists", sectionTitle),
message: fmt.Sprintf("control with section_title %q already exists", c.SectionTitle),
}
}
}
return fmt.Errorf("cannot collect control: %w", err)
return fmt.Errorf("cannot update control: %w", err)
}
*c = control
return nil
}

View File

@@ -21,10 +21,10 @@ import (
"maps"
"time"
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/page"
"github.com/jackc/pgx/v5"
"go.gearno.de/kit/pg"
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/page"
)
type (

View File

@@ -21,11 +21,11 @@ import (
"maps"
"time"
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/page"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgconn"
"go.gearno.de/kit/pg"
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/page"
)
type (
@@ -38,7 +38,7 @@ type (
Type EvidenceType `db:"type"`
URL string `db:"url"`
EvidenceFileId *gid.GID `db:"evidence_file_id"`
Description string `db:"description"`
Description *string `db:"description"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
}

View File

@@ -21,11 +21,11 @@ import (
"maps"
"time"
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/page"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgconn"
"go.gearno.de/kit/pg"
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/page"
)
type (
@@ -34,7 +34,7 @@ type (
OrganizationID gid.GID `db:"organization_id"`
ReferenceID string `db:"reference_id"`
Name string `db:"name"`
Description string `db:"description"`
Description *string `db:"description"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
}

View File

@@ -21,10 +21,10 @@ import (
"maps"
"time"
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/page"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgconn"
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/page"
"go.gearno.de/kit/pg"
)
@@ -35,7 +35,7 @@ type (
OrganizationID gid.GID `db:"organization_id"`
Category string `db:"category"`
Name string `db:"name"`
Description string `db:"description"`
Description *string `db:"description"`
State MeasureState `db:"state"`
ReferenceID string `db:"reference_id"`
CreatedAt time.Time `db:"created_at"`

View File

@@ -0,0 +1,8 @@
ALTER TABLE controls ALTER COLUMN description DROP NOT NULL;
ALTER TABLE documents ALTER COLUMN description DROP NOT NULL;
ALTER TABLE documents ALTER COLUMN description DROP DEFAULT;
ALTER TABLE evidences ALTER COLUMN description DROP NOT NULL;
ALTER TABLE frameworks ALTER COLUMN description DROP NOT NULL;
ALTER TABLE measures ALTER COLUMN description DROP NOT NULL;
ALTER TABLE tasks ALTER COLUMN description DROP NOT NULL;
ALTER TABLE trust_center_references ALTER COLUMN description DROP NOT NULL;

View File

@@ -21,10 +21,10 @@ import (
"maps"
"time"
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/page"
"github.com/jackc/pgx/v5"
"go.gearno.de/kit/pg"
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/page"
)
type (
@@ -32,7 +32,7 @@ type (
ID gid.GID `db:"id"`
OrganizationID gid.GID `db:"organization_id"`
Name string `db:"name"`
Description string `db:"description"`
Description *string `db:"description"`
Category string `db:"category"`
Treatment RiskTreatment `db:"treatment"`
Note string `db:"note"`

View File

@@ -21,10 +21,10 @@ import (
"maps"
"time"
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/page"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgconn"
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/page"
"go.gearno.de/kit/pg"
)
@@ -35,7 +35,7 @@ type (
OrganizationID gid.GID `db:"organization_id"`
MeasureID *gid.GID `db:"measure_id"`
Name string `db:"name"`
Description string `db:"description"`
Description *string `db:"description"`
State TaskState `db:"state"`
ReferenceID string `db:"reference_id"`
TimeEstimate *time.Duration `db:"time_estimate"`

View File

@@ -21,11 +21,11 @@ import (
"maps"
"time"
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/page"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgconn"
"go.gearno.de/kit/pg"
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/page"
)
type (
@@ -33,7 +33,7 @@ type (
ID gid.GID `db:"id"`
TrustCenterID gid.GID `db:"trust_center_id"`
Name string `db:"name"`
Description string `db:"description"`
Description *string `db:"description"`
WebsiteURL string `db:"website_url"`
LogoFileID gid.GID `db:"logo_file_id"`
Rank int `db:"rank"`