Add trust center configuration

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
Sacha Al Himdani
2025-07-24 21:11:46 +02:00
parent e85a7b4955
commit 32c47a1988
49 changed files with 4755 additions and 126 deletions

View File

@@ -28,15 +28,16 @@ import (
type (
Audit struct {
ID gid.GID `db:"id"`
OrganizationID gid.GID `db:"organization_id"`
FrameworkID gid.GID `db:"framework_id"`
ReportID *gid.GID `db:"report_id"`
ValidFrom *time.Time `db:"valid_from"`
ValidUntil *time.Time `db:"valid_until"`
State AuditState `db:"state"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
ID gid.GID `db:"id"`
OrganizationID gid.GID `db:"organization_id"`
FrameworkID gid.GID `db:"framework_id"`
ReportID *gid.GID `db:"report_id"`
ValidFrom *time.Time `db:"valid_from"`
ValidUntil *time.Time `db:"valid_until"`
State AuditState `db:"state"`
ShowOnTrustCenter bool `db:"show_on_trust_center"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
}
Audits []*Audit
@@ -72,6 +73,7 @@ SELECT
valid_from,
valid_until,
state,
show_on_trust_center,
created_at,
updated_at
FROM
@@ -150,6 +152,7 @@ SELECT
valid_from,
valid_until,
state,
show_on_trust_center,
created_at,
updated_at
FROM
@@ -196,6 +199,7 @@ INSERT INTO audits (
valid_from,
valid_until,
state,
show_on_trust_center,
created_at,
updated_at
) VALUES (
@@ -207,22 +211,24 @@ INSERT INTO audits (
@valid_from,
@valid_until,
@state,
@show_on_trust_center,
@created_at,
@updated_at
)
`
args := pgx.StrictNamedArgs{
"id": a.ID,
"tenant_id": scope.GetTenantID(),
"organization_id": a.OrganizationID,
"framework_id": a.FrameworkID,
"report_id": a.ReportID,
"valid_from": a.ValidFrom,
"valid_until": a.ValidUntil,
"state": a.State,
"created_at": a.CreatedAt,
"updated_at": a.UpdatedAt,
"id": a.ID,
"tenant_id": scope.GetTenantID(),
"organization_id": a.OrganizationID,
"framework_id": a.FrameworkID,
"report_id": a.ReportID,
"valid_from": a.ValidFrom,
"valid_until": a.ValidUntil,
"state": a.State,
"show_on_trust_center": a.ShowOnTrustCenter,
"created_at": a.CreatedAt,
"updated_at": a.UpdatedAt,
}
_, err := conn.Exec(ctx, q, args)
@@ -245,6 +251,7 @@ SET
valid_from = @valid_from,
valid_until = @valid_until,
state = @state,
show_on_trust_center = @show_on_trust_center,
updated_at = @updated_at
WHERE
%s
@@ -254,12 +261,13 @@ WHERE
q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{
"id": a.ID,
"report_id": a.ReportID,
"valid_from": a.ValidFrom,
"valid_until": a.ValidUntil,
"state": a.State,
"updated_at": a.UpdatedAt,
"id": a.ID,
"report_id": a.ReportID,
"valid_from": a.ValidFrom,
"valid_until": a.ValidUntil,
"state": a.State,
"show_on_trust_center": a.ShowOnTrustCenter,
"updated_at": a.UpdatedAt,
}
maps.Copy(args, scope.SQLArguments())

View File

@@ -34,6 +34,7 @@ type (
Title string `db:"title"`
DocumentType DocumentType `db:"document_type"`
CurrentPublishedVersion *int `db:"current_published_version"`
ShowOnTrustCenter bool `db:"show_on_trust_center"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
}
@@ -68,6 +69,7 @@ SELECT
title,
document_type,
current_published_version,
show_on_trust_center,
created_at,
updated_at
FROM
@@ -147,6 +149,7 @@ SELECT
title,
document_type,
current_published_version,
show_on_trust_center,
created_at,
updated_at
FROM
@@ -195,6 +198,7 @@ INSERT INTO
title,
document_type,
current_published_version,
show_on_trust_center,
created_at,
updated_at
)
@@ -206,6 +210,7 @@ VALUES (
@title,
@document_type,
@current_published_version,
@show_on_trust_center,
@created_at,
@updated_at
);
@@ -219,6 +224,7 @@ VALUES (
"title": p.Title,
"document_type": p.DocumentType,
"current_published_version": p.CurrentPublishedVersion,
"show_on_trust_center": p.ShowOnTrustCenter,
"created_at": p.CreatedAt,
"updated_at": p.UpdatedAt,
}
@@ -257,6 +263,7 @@ SET
current_published_version = @current_published_version,
owner_id = @owner_id,
document_type = @document_type,
show_on_trust_center = @show_on_trust_center,
updated_at = @updated_at
WHERE %s
AND id = @document_id
@@ -270,6 +277,7 @@ WHERE %s
"current_published_version": p.CurrentPublishedVersion,
"owner_id": p.OwnerID,
"document_type": p.DocumentType,
"show_on_trust_center": p.ShowOnTrustCenter,
}
maps.Copy(args, scope.SQLArguments())
@@ -342,6 +350,7 @@ WITH plcs AS (
p.title,
p.document_type,
p.current_published_version,
p.show_on_trust_center,
p.created_at,
p.updated_at
FROM
@@ -358,6 +367,7 @@ SELECT
title,
document_type,
current_published_version,
show_on_trust_center,
created_at,
updated_at
FROM
@@ -448,6 +458,7 @@ WITH plcs AS (
p.title,
p.document_type,
p.current_published_version,
p.show_on_trust_center,
p.created_at,
p.updated_at
FROM
@@ -464,6 +475,7 @@ SELECT
title,
document_type,
current_published_version,
show_on_trust_center,
created_at,
updated_at
FROM

View File

@@ -37,4 +37,5 @@ const (
DatumEntityType
AuditEntityType
ReportEntityType
TrustCenterEntityType
)

View File

@@ -0,0 +1,51 @@
CREATE EXTENSION IF NOT EXISTS unaccent;
CREATE TABLE trust_centers (
id TEXT PRIMARY KEY,
organization_id TEXT NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
tenant_id TEXT NOT NULL,
active BOOLEAN NOT NULL,
slug TEXT NOT NULL CHECK (slug ~ '^[a-z0-9_-]+$'),
created_at TIMESTAMP WITH TIME ZONE NOT NULL,
updated_at TIMESTAMP WITH TIME ZONE NOT NULL,
UNIQUE(slug)
);
INSERT INTO trust_centers (
id,
organization_id,
tenant_id,
active,
slug,
created_at,
updated_at
)
SELECT
generate_gid(decode_base64_unpadded(o.tenant_id), 22),
o.id,
o.tenant_id,
false,
LOWER(
REGEXP_REPLACE(
REGEXP_REPLACE(
unaccent(o.name),
'[^a-zA-Z0-9\s]', '', 'g'
),
'\s+', '-', 'g'
)
),
NOW(),
NOW()
FROM organizations o;
ALTER TABLE documents ADD COLUMN show_on_trust_center BOOLEAN NOT NULL DEFAULT false;
ALTER TABLE audits ADD COLUMN show_on_trust_center BOOLEAN NOT NULL DEFAULT false;
ALTER TABLE vendors ADD COLUMN show_on_trust_center BOOLEAN NOT NULL DEFAULT false;
ALTER TABLE documents ALTER COLUMN show_on_trust_center DROP DEFAULT;
ALTER TABLE audits ALTER COLUMN show_on_trust_center DROP DEFAULT;
ALTER TABLE vendors ALTER COLUMN show_on_trust_center DROP DEFAULT;

View File

@@ -0,0 +1,213 @@
// 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 (
"context"
"fmt"
"maps"
"time"
"github.com/getprobo/probo/pkg/gid"
"github.com/getprobo/probo/pkg/page"
"github.com/jackc/pgx/v5"
"go.gearno.de/kit/pg"
)
type (
TrustCenter struct {
ID gid.GID `db:"id"`
OrganizationID gid.GID `db:"organization_id"`
TenantID gid.TenantID `db:"tenant_id"`
Active bool `db:"active"`
Slug string `db:"slug"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
}
TrustCenters []*TrustCenter
)
func (tc *TrustCenter) CursorKey(orderBy TrustCenterOrderField) page.CursorKey {
switch orderBy {
case TrustCenterOrderFieldCreatedAt:
return page.NewCursorKey(tc.ID, tc.CreatedAt)
}
panic(fmt.Sprintf("unsupported order by: %s", orderBy))
}
func (tc *TrustCenter) LoadByID(
ctx context.Context,
conn pg.Conn,
scope Scoper,
trustCenterID gid.GID,
) error {
q := `
SELECT
id,
organization_id,
tenant_id,
active,
slug,
created_at,
updated_at
FROM
trust_centers
WHERE
%s
AND id = @trust_center_id
LIMIT 1;
`
q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{"trust_center_id": trustCenterID}
maps.Copy(args, scope.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query trust center: %w", err)
}
trustCenter, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[TrustCenter])
if err != nil {
return fmt.Errorf("cannot collect trust center: %w", err)
}
*tc = trustCenter
return nil
}
func (tc *TrustCenter) LoadByOrganizationID(
ctx context.Context,
conn pg.Conn,
scope Scoper,
organizationID gid.GID,
) error {
q := `
SELECT
id,
organization_id,
tenant_id,
active,
slug,
created_at,
updated_at
FROM
trust_centers
WHERE
%s
AND organization_id = @organization_id
LIMIT 1;
`
q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{"organization_id": organizationID}
maps.Copy(args, scope.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query trust center: %w", err)
}
trustCenter, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[TrustCenter])
if err != nil {
return fmt.Errorf("cannot collect trust center: %w", err)
}
*tc = trustCenter
return nil
}
func (tc *TrustCenter) Insert(
ctx context.Context,
conn pg.Conn,
scope Scoper,
) error {
q := `
INSERT INTO trust_centers (
id,
organization_id,
tenant_id,
active,
slug,
created_at,
updated_at
) VALUES (
@id,
@organization_id,
@tenant_id,
@active,
@slug,
@created_at,
@updated_at
)
`
args := pgx.StrictNamedArgs{
"id": tc.ID,
"organization_id": tc.OrganizationID,
"tenant_id": tc.TenantID,
"active": tc.Active,
"slug": tc.Slug,
"created_at": tc.CreatedAt,
"updated_at": tc.UpdatedAt,
}
_, err := conn.Exec(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot insert trust center: %w", err)
}
return nil
}
func (tc *TrustCenter) Update(
ctx context.Context,
conn pg.Conn,
scope Scoper,
) error {
q := `
UPDATE trust_centers
SET
active = @active,
slug = @slug,
updated_at = @updated_at
WHERE
%s
AND id = @id
`
q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{
"id": tc.ID,
"active": tc.Active,
"slug": tc.Slug,
"updated_at": tc.UpdatedAt,
}
maps.Copy(args, scope.SQLArguments())
_, err := conn.Exec(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot update trust center: %w", err)
}
return nil
}

View File

@@ -0,0 +1,38 @@
// 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
type TrustCenterOrderField string
const (
TrustCenterOrderFieldCreatedAt TrustCenterOrderField = "CREATED_AT"
)
func (p TrustCenterOrderField) Column() string {
return string(p)
}
func (p TrustCenterOrderField) String() string {
return string(p)
}
func (p TrustCenterOrderField) MarshalText() ([]byte, error) {
return []byte(p.String()), nil
}
func (p *TrustCenterOrderField) UnmarshalText(text []byte) error {
*p = TrustCenterOrderField(text)
return nil
}

View File

@@ -49,6 +49,7 @@ type (
TermsOfServiceURL *string `db:"terms_of_service_url"`
SecurityPageURL *string `db:"security_page_url"`
TrustPageURL *string `db:"trust_page_url"`
ShowOnTrustCenter bool `db:"show_on_trust_center"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
}
@@ -98,6 +99,7 @@ SELECT
terms_of_service_url,
security_page_url,
trust_page_url,
show_on_trust_center,
created_at,
updated_at
FROM
@@ -158,6 +160,7 @@ INSERT INTO
terms_of_service_url,
security_page_url,
trust_page_url,
show_on_trust_center,
created_at,
updated_at
)
@@ -183,6 +186,7 @@ VALUES (
@terms_of_service_url,
@security_page_url,
@trust_page_url,
@show_on_trust_center,
@created_at,
@updated_at
)
@@ -210,6 +214,7 @@ VALUES (
"terms_of_service_url": v.TermsOfServiceURL,
"security_page_url": v.SecurityPageURL,
"trust_page_url": v.TrustPageURL,
"show_on_trust_center": v.ShowOnTrustCenter,
"created_at": v.CreatedAt,
"updated_at": v.UpdatedAt,
}
@@ -297,6 +302,7 @@ SELECT
terms_of_service_url,
security_page_url,
trust_page_url,
show_on_trust_center,
created_at,
updated_at
FROM
@@ -353,6 +359,7 @@ SET
trust_page_url = @trust_page_url,
business_owner_id = @business_owner_id,
security_owner_id = @security_owner_id,
show_on_trust_center = @show_on_trust_center,
updated_at = @updated_at
WHERE %s
AND id = @vendor_id
@@ -380,6 +387,7 @@ WHERE %s
"trust_page_url": v.TrustPageURL,
"business_owner_id": v.BusinessOwnerID,
"security_owner_id": v.SecurityOwnerID,
"show_on_trust_center": v.ShowOnTrustCenter,
}
maps.Copy(args, scope.SQLArguments())