Refactor policies document

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
This commit is contained in:
Bryan Frimin
2026-01-02 11:04:48 +01:00
parent cbf338fd14
commit 4013b00841
75 changed files with 1958 additions and 1230 deletions

View File

@@ -56,6 +56,21 @@ func (a *Asset) CursorKey(field AssetOrderField) page.CursorKey {
panic(fmt.Sprintf("unsupported order by: %s", field))
}
// AuthorizationAttributes returns the authorization attributes for policy evaluation.
func (a *Asset) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM assets WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, a.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query asset authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (a *Asset) LoadByID(
ctx context.Context,
conn pg.Conn,

View File

@@ -60,6 +60,21 @@ func (a *Audit) CursorKey(field AuditOrderField) page.CursorKey {
panic(fmt.Sprintf("unsupported order by: %s", field))
}
// AuthorizationAttributes returns the authorization attributes for policy evaluation.
func (a *Audit) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM audits WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, a.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query audit authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (a *Audit) LoadByID(
ctx context.Context,
conn pg.Conn,

View File

@@ -17,16 +17,17 @@ package coredata
import (
"context"
"encoding/json"
"errors"
"fmt"
"maps"
"time"
"github.com/jackc/pgx/v5"
"go.gearno.de/kit/pg"
"go.probo.inc/probo/pkg/connector"
"go.probo.inc/probo/pkg/crypto/cipher"
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/page"
"github.com/jackc/pgx/v5"
"go.gearno.de/kit/pg"
)
type (
@@ -56,6 +57,21 @@ func (c *Connector) CursorKey(orderBy ConnectorOrderField) page.CursorKey {
panic(fmt.Sprintf("unsupported order by: %s", orderBy))
}
// AuthorizationAttributes returns the authorization attributes for policy evaluation.
func (c *Connector) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM connectors WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, c.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query connector authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (c *Connectors) LoadByOrganizationID(
ctx context.Context,
conn pg.Conn,

View File

@@ -16,14 +16,15 @@ package coredata
import (
"context"
"errors"
"fmt"
"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 (
@@ -63,6 +64,21 @@ func (ci *ContinualImprovement) CursorKey(field ContinualImprovementOrderField)
panic(fmt.Sprintf("unsupported order by: %s", field))
}
// AuthorizationAttributes returns the authorization attributes for policy evaluation.
func (ci *ContinualImprovement) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM continual_improvements WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, ci.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query continual improvement authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (ci *ContinualImprovement) LoadByID(
ctx context.Context,
conn pg.Conn,

View File

@@ -57,6 +57,21 @@ func (c Control) CursorKey(orderBy ControlOrderField) page.CursorKey {
panic(fmt.Sprintf("unsupported order by: %s", orderBy))
}
// AuthorizationAttributes returns the authorization attributes for policy evaluation.
func (c *Control) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM controls WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, c.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query control authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (c *Controls) CountByDocumentID(
ctx context.Context,
conn pg.Conn,

View File

@@ -65,6 +65,21 @@ func NewCustomDomain(tenantID gid.TenantID, domain string) *CustomDomain {
}
}
// AuthorizationAttributes returns the authorization attributes for policy evaluation.
func (cd *CustomDomain) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM custom_domains WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, cd.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query custom domain authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (cd *CustomDomain) CursorKey(field CustomDomainOrderField) page.CursorKey {
switch field {
case CustomDomainOrderFieldCreatedAt:

View File

@@ -69,6 +69,21 @@ func (dpia *DataProtectionImpactAssessment) CursorKey(field DataProtectionImpact
panic(fmt.Sprintf("unsupported order by: %s", field))
}
// AuthorizationAttributes returns the authorization attributes for policy evaluation.
func (dpia *DataProtectionImpactAssessment) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM processing_activity_data_protection_impact_assessments WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, dpia.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query data protection impact assessment authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (dpias *DataProtectionImpactAssessments) CountByOrganizationID(
ctx context.Context,
conn pg.Conn,

View File

@@ -16,14 +16,15 @@ package coredata
import (
"context"
"errors"
"fmt"
"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 (
@@ -59,6 +60,21 @@ func (d *Datum) CursorKey(field DatumOrderField) page.CursorKey {
panic(fmt.Sprintf("unsupported order by: %s", field))
}
// AuthorizationAttributes returns the authorization attributes for policy evaluation.
func (d *Datum) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM data WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, d.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query datum authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (d *Datum) LoadByID(
ctx context.Context,
conn pg.Conn,

View File

@@ -58,6 +58,21 @@ func (p Document) CursorKey(orderBy DocumentOrderField) page.CursorKey {
panic(fmt.Sprintf("unsupported order by: %s", orderBy))
}
// AuthorizationAttributes returns the authorization attributes for policy evaluation.
func (d *Document) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM documents WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, d.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query document authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (p *Document) LoadByID(
ctx context.Context,
conn pg.Conn,

View File

@@ -48,6 +48,21 @@ type (
DocumentVersions []*DocumentVersion
)
// AuthorizationAttributes returns the authorization attributes for policy evaluation.
func (dv *DocumentVersion) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM document_versions WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, dv.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query document version authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (p *DocumentVersions) LoadByDocumentID(
ctx context.Context,
conn pg.Conn,

View File

@@ -62,6 +62,21 @@ func (pvs DocumentVersionSignature) CursorKey(orderBy DocumentVersionSignatureOr
panic(fmt.Sprintf("unsupported order by: %s", orderBy))
}
// AuthorizationAttributes returns the authorization attributes for policy evaluation.
func (dvs *DocumentVersionSignature) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM document_version_signatures WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, dvs.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query document version signature authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (pvs *DocumentVersionSignature) LoadByDocumentVersionIDAndSignatory(
ctx context.Context,
conn pg.Conn,

View File

@@ -44,6 +44,12 @@ var (
ErrNoUnsentEmail = errors.New("no unsent email found")
)
// AuthorizationAttributes returns the authorization attributes for policy evaluation.
// Email is identity-scoped (not org-scoped), so it returns an empty map.
func (e *Email) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
return map[string]string{}, nil
}
func NewEmail(
recipientName string,
recipientEmail mail.Addr,

View File

@@ -14,6 +14,8 @@
package coredata
import "go.probo.inc/probo/pkg/gid"
type ctxKey struct{ name string }
var (
@@ -75,6 +77,109 @@ const (
MembershipProfileEntityType uint16 = 51
)
func NewEntityFromID(id gid.GID) (any, bool) {
switch id.EntityType() {
case OrganizationEntityType:
return &Organization{ID: id}, true
case FrameworkEntityType:
return &Framework{ID: id}, true
case MeasureEntityType:
return &Measure{ID: id}, true
case TaskEntityType:
return &Task{ID: id}, true
case EvidenceEntityType:
return &Evidence{ID: id}, true
case ConnectorEntityType:
return &Connector{ID: id}, true
case VendorRiskAssessmentEntityType:
return &VendorRiskAssessment{ID: id}, true
case VendorEntityType:
return &Vendor{ID: id}, true
case PeopleEntityType:
return &People{ID: id}, true
case VendorComplianceReportEntityType:
return &VendorComplianceReport{ID: id}, true
case DocumentEntityType:
return &Document{ID: id}, true
case IdentityEntityType:
return &Identity{ID: id}, true
case SessionEntityType:
return &Session{ID: id}, true
case EmailEntityType:
return &Email{ID: id}, true
case ControlEntityType:
return &Control{ID: id}, true
case RiskEntityType:
return &Risk{ID: id}, true
case DocumentVersionEntityType:
return &DocumentVersion{ID: id}, true
case DocumentVersionSignatureEntityType:
return &DocumentVersionSignature{ID: id}, true
case AssetEntityType:
return &Asset{ID: id}, true
case DatumEntityType:
return &Datum{ID: id}, true
case AuditEntityType:
return &Audit{ID: id}, true
case ReportEntityType:
return &Report{ID: id}, true
case TrustCenterEntityType:
return &TrustCenter{ID: id}, true
case TrustCenterAccessEntityType:
return &TrustCenterAccess{ID: id}, true
case VendorBusinessAssociateAgreementEntityType:
return &VendorBusinessAssociateAgreement{ID: id}, true
case FileEntityType:
return &File{ID: id}, true
case VendorContactEntityType:
return &VendorContact{ID: id}, true
case VendorDataPrivacyAgreementEntityType:
return &VendorDataPrivacyAgreement{ID: id}, true
case NonconformityEntityType:
return &Nonconformity{ID: id}, true
case ObligationEntityType:
return &Obligation{ID: id}, true
case VendorServiceEntityType:
return &VendorService{ID: id}, true
case SnapshotEntityType:
return &Snapshot{ID: id}, true
case ContinualImprovementEntityType:
return &ContinualImprovement{ID: id}, true
case ProcessingActivityEntityType:
return &ProcessingActivity{ID: id}, true
case ExportJobEntityType:
return &ExportJob{ID: id}, true
case TrustCenterReferenceEntityType:
return &TrustCenterReference{ID: id}, true
case TrustCenterDocumentAccessEntityType:
return &TrustCenterDocumentAccess{ID: id}, true
case CustomDomainEntityType:
return &CustomDomain{ID: id}, true
case InvitationEntityType:
return &Invitation{ID: id}, true
case MembershipEntityType:
return &Membership{ID: id}, true
case SlackMessageEntityType:
return &SlackMessage{ID: id}, true
case TrustCenterFileEntityType:
return &TrustCenterFile{ID: id}, true
case SAMLConfigurationEntityType:
return &SAMLConfiguration{ID: id}, true
case PersonalAPIKeyEntityType:
return &PersonalAPIKey{ID: id}, true
case MeetingEntityType:
return &Meeting{ID: id}, true
case DataProtectionImpactAssessmentEntityType:
return &DataProtectionImpactAssessment{ID: id}, true
case TransferImpactAssessmentEntityType:
return &TransferImpactAssessment{ID: id}, true
case MembershipProfileEntityType:
return &MembershipProfile{ID: id}, true
default:
return nil, false
}
}
type EntityInfo struct {
Model string
Table string

View File

@@ -56,6 +56,21 @@ func (e Evidence) CursorKey(orderBy EvidenceOrderField) page.CursorKey {
panic(fmt.Sprintf("unsupported order by: %s", orderBy))
}
// AuthorizationAttributes returns the authorization attributes for policy evaluation.
func (e *Evidence) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM evidences WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, e.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query evidence authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (e Evidence) Upsert(
ctx context.Context,
conn pg.Conn,

View File

@@ -16,18 +16,18 @@ import (
type (
ExportJob struct {
ID gid.GID `db:"id"`
OrganizationID gid.GID `db:"organization_id"`
Type ExportJobType `db:"type"`
Arguments json.RawMessage `db:"arguments"`
Error *string `db:"error"`
Status ExportJobStatus `db:"status"`
FileID *gid.GID `db:"file_id"`
RecipientEmail mail.Addr `db:"recipient_email"`
RecipientName string `db:"recipient_name"`
CreatedAt time.Time `db:"created_at"`
StartedAt *time.Time `db:"started_at"`
CompletedAt *time.Time `db:"completed_at"`
ID gid.GID `db:"id"`
OrganizationID gid.GID `db:"organization_id"`
Type ExportJobType `db:"type"`
Arguments json.RawMessage `db:"arguments"`
Error *string `db:"error"`
Status ExportJobStatus `db:"status"`
FileID *gid.GID `db:"file_id"`
RecipientEmail mail.Addr `db:"recipient_email"`
RecipientName string `db:"recipient_name"`
CreatedAt time.Time `db:"created_at"`
StartedAt *time.Time `db:"started_at"`
CompletedAt *time.Time `db:"completed_at"`
}
ExportJobs []*ExportJob
@@ -48,6 +48,21 @@ var (
ErrNoExportJobAvailable = errors.New("no export job available")
)
// AuthorizationAttributes returns the authorization attributes for policy evaluation.
func (ej *ExportJob) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM export_jobs WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, ej.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query export job authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (ej *ExportJob) Insert(
ctx context.Context,
conn pg.Conn,

View File

@@ -44,6 +44,21 @@ type (
Files []*File
)
// AuthorizationAttributes returns the authorization attributes for policy evaluation.
func (f *File) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM files WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, f.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query file authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (f *File) LoadByID(
ctx context.Context,
conn pg.Conn,

View File

@@ -53,6 +53,21 @@ func (f *Framework) CursorKey(orderBy FrameworkOrderField) page.CursorKey {
panic(fmt.Sprintf("unsupported order by: %s", orderBy))
}
// AuthorizationAttributes returns the authorization attributes for policy evaluation.
func (f *Framework) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM frameworks WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, f.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query framework authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (f *Frameworks) CountByOrganizationID(
ctx context.Context,
conn pg.Conn,

View File

@@ -220,6 +220,34 @@ LIMIT 1;
return nil
}
// AuthorizationAttributes loads the minimal authorization attributes for policy condition evaluation.
// It is intentionally lightweight and does not populate the Identity struct.
func (i *Identity) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `
SELECT
id,
email_address
FROM
identities
WHERE
id = $1
LIMIT 1;
`
var (
id gid.GID
emailAddress string
)
if err := conn.QueryRow(ctx, q, i.ID).Scan(&id, &emailAddress); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query identity iam attributes: %w", err)
}
return map[string]string{"id": id.String(), "email": emailAddress}, nil
}
func (i *Identity) Insert(
ctx context.Context,
conn pg.Conn,

View File

@@ -164,6 +164,35 @@ WHERE
return nil
}
// AuthorizationAttributes loads the minimal authorization attributes for policy condition evaluation.
// It is intentionally lightweight and does not populate the Invitation struct.
func (i *Invitation) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `
SELECT
email
, organization_id
FROM
iam_invitations
WHERE
id = $1
LIMIT 1;
`
var email string
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, i.ID).Scan(&email, &organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query invitation iam attributes: %w", err)
}
return map[string]string{
"email": email,
"organization_id": organizationID.String(),
}, nil
}
func (i *Invitation) Update(ctx context.Context, conn pg.Conn, scope Scoper) error {
query := `
UPDATE

View File

@@ -56,6 +56,21 @@ func (m Measure) CursorKey(orderBy MeasureOrderField) page.CursorKey {
panic(fmt.Sprintf("unsupported order by: %s", orderBy))
}
// AuthorizationAttributes returns the authorization attributes for policy evaluation.
func (m *Measure) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM measures WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, m.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query measure authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (m *Measures) CountByRiskID(
ctx context.Context,
conn pg.Conn,

View File

@@ -54,6 +54,21 @@ func (m Meeting) CursorKey(orderBy MeetingOrderField) page.CursorKey {
panic(fmt.Sprintf("unsupported order by: %s", orderBy))
}
// AuthorizationAttributes returns the authorization attributes for policy evaluation.
func (m *Meeting) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM meetings WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, m.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query meeting authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (m *Meeting) LoadByID(
ctx context.Context,
conn pg.Conn,

View File

@@ -226,6 +226,33 @@ LEFT JOIN
return nil
}
func (m *Membership) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `
SELECT
identity_id
, organization_id
FROM
iam_memberships
WHERE
id = $1
LIMIT 1;
`
var identityID gid.GID
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, m.ID).Scan(&identityID, &organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query membership iam attributes: %w", err)
}
return map[string]string{
"identity_id": identityID.String(),
"organization_id": organizationID.String(),
}, nil
}
func LoadRoleByIdentityAndEntityIDOnly(
ctx context.Context,
conn pg.Conn,
@@ -235,7 +262,6 @@ func LoadRoleByIdentityAndEntityIDOnly(
) (MembershipRole, error) {
entityType := entityID.EntityType()
// For organization, the entity ID is the organization ID - optimized path
if entityType == OrganizationEntityType {
query := `
SELECT role
@@ -595,3 +621,39 @@ WHERE
return count, nil
}
func (m *Memberships) LoadAllByIdentityID(
ctx context.Context,
conn pg.Conn,
identityID gid.GID,
) error {
q := `
SELECT
id,
identity_id,
organization_id,
role,
'' as full_name,
NULL as email_address,
created_at,
updated_at
FROM
iam_memberships
WHERE
identity_id = $1
;
`
rows, err := conn.Query(ctx, q, identityID)
if err != nil {
return fmt.Errorf("cannot query memberships: %w", err)
}
memberships, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[Membership])
if err != nil {
return fmt.Errorf("cannot collect memberships: %w", err)
}
*m = memberships
return nil
}

View File

@@ -36,6 +36,20 @@ type (
}
)
func (p *MembershipProfile) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT m.organization_id FROM iam_membership_profiles mp JOIN iam_memberships m ON mp.membership_id = m.id WHERE mp.id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, p.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query membership profile authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (p *MembershipProfile) LoadByMembershipID(
ctx context.Context,
conn pg.Conn,

View File

@@ -16,14 +16,15 @@ package coredata
import (
"context"
"errors"
"fmt"
"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 (
@@ -66,6 +67,20 @@ func (nc *Nonconformity) CursorKey(field NonconformityOrderField) page.CursorKey
panic(fmt.Sprintf("unsupported order by: %s", field))
}
func (nc *Nonconformity) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM nonconformities WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, nc.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query nonconformity authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (nc *Nonconformity) LoadByID(
ctx context.Context,
conn pg.Conn,
@@ -399,9 +414,9 @@ WHERE %s AND nc.organization_id = @organization_id AND nc.snapshot_id IS NULL
query = fmt.Sprintf(query, scope.SQLFragment())
args := pgx.StrictNamedArgs{
"tenant_id": scope.GetTenantID(),
"snapshot_id": snapshotID,
"organization_id": organizationID,
"tenant_id": scope.GetTenantID(),
"snapshot_id": snapshotID,
"organization_id": organizationID,
"nonconformity_entity_type": NonconformityEntityType,
}
maps.Copy(args, scope.SQLArguments())

View File

@@ -16,6 +16,7 @@ package coredata
import (
"context"
"errors"
"fmt"
"maps"
"time"
@@ -64,6 +65,20 @@ func (o *Obligation) CursorKey(field ObligationOrderField) page.CursorKey {
panic(fmt.Sprintf("unsupported order by: %s", field))
}
func (o *Obligation) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM obligations WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, o.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query obligation authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (o *Obligation) LoadByID(
ctx context.Context,
conn pg.Conn,

View File

@@ -46,6 +46,20 @@ type (
Organizations []*Organization
)
func (o *Organization) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT id FROM organizations WHERE id = $1 LIMIT 1;`
var id gid.GID
if err := conn.QueryRow(ctx, q, o.ID).Scan(&id); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query organization authorization attributes: %w", err)
}
return map[string]string{"organization_id": o.ID.String()}, nil
}
func (o Organization) CursorKey(orderBy OrganizationOrderField) page.CursorKey {
switch orderBy {
case OrganizationOrderFieldName:

View File

@@ -60,6 +60,20 @@ func (p People) CursorKey(orderBy PeopleOrderField) page.CursorKey {
panic(fmt.Sprintf("unsupported order by: %s", orderBy))
}
func (p *People) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM peoples WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, p.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query people authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (p *People) LoadByID(
ctx context.Context,
conn pg.Conn,

View File

@@ -91,6 +91,20 @@ LIMIT 1;
return nil
}
func (a *PersonalAPIKey) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := "SELECT identity_id FROM iam_personal_api_keys WHERE id = $1 LIMIT 1;"
var identityID gid.GID
if err := conn.QueryRow(ctx, q, a.ID).Scan(&identityID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query personal api key iam attributes: %w", err)
}
return map[string]string{"identity_id": identityID.String()}, nil
}
func (a *PersonalAPIKeys) LoadByIdentityID(
ctx context.Context,
conn pg.Conn,

View File

@@ -16,6 +16,7 @@ package coredata
import (
"context"
"errors"
"fmt"
"maps"
"time"
@@ -75,6 +76,20 @@ func (p *ProcessingActivity) CursorKey(field ProcessingActivityOrderField) page.
panic(fmt.Sprintf("unsupported order by: %s", field))
}
func (p *ProcessingActivity) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM processing_activities WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, p.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query processing activity authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (p *ProcessingActivity) LoadByID(
ctx context.Context,
conn pg.Conn,

View File

@@ -42,6 +42,20 @@ type (
Reports []*Report
)
func (r *Report) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM reports WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, r.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query report authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (r *Report) LoadByID(
ctx context.Context,
conn pg.Conn,

View File

@@ -80,6 +80,20 @@ func (r *Risk) CursorKey(orderBy RiskOrderField) page.CursorKey {
panic(fmt.Sprintf("unsupported order by: %s", orderBy))
}
func (r *Risk) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM risks WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, r.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query risk authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (r *Risks) CountByMeasureID(
ctx context.Context,
conn pg.Conn,

View File

@@ -63,6 +63,20 @@ func (s *SAMLConfiguration) CursorKey(orderBy SAMLConfigurationOrderField) page.
panic(fmt.Sprintf("unsupported order by: %s", orderBy))
}
func (s *SAMLConfiguration) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM iam_saml_configurations WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, s.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query saml configuration authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (s *SAMLConfiguration) GetIdPCertificate() (*x509.Certificate, error) {
block, _ := pem.Decode([]byte(s.IdPCertificate))
if block == nil {

View File

@@ -140,6 +140,30 @@ LIMIT 1;
return nil
}
// AuthorizationAttributes loads the minimal authorization attributes for policy condition evaluation.
// It is intentionally lightweight and does not populate the Session struct.
func (s *Session) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `
SELECT
identity_id
FROM
iam_sessions
WHERE
id = $1
LIMIT 1;
`
var identityID gid.GID
if err := conn.QueryRow(ctx, q, s.ID).Scan(&identityID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query session iam attributes: %w", err)
}
return map[string]string{"identity_id": identityID.String()}, nil
}
func (s *Session) Insert(
ctx context.Context,
conn pg.Conn,

View File

@@ -29,19 +29,19 @@ import (
type (
SlackMessage struct {
ID gid.GID `db:"id"`
OrganizationID gid.GID `db:"organization_id"`
Type SlackMessageType `db:"type"`
Body map[string]any `db:"body"`
MessageTS *string `db:"message_ts"`
ChannelID *string `db:"channel_id"`
RequesterEmail *mail.Addr `db:"requester_email"`
Metadata map[string]any `db:"metadata"`
InitialSlackMessageID gid.GID `db:"initial_slack_message_id"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
SentAt *time.Time `db:"sent_at"`
Error *string `db:"error"`
ID gid.GID `db:"id"`
OrganizationID gid.GID `db:"organization_id"`
Type SlackMessageType `db:"type"`
Body map[string]any `db:"body"`
MessageTS *string `db:"message_ts"`
ChannelID *string `db:"channel_id"`
RequesterEmail *mail.Addr `db:"requester_email"`
Metadata map[string]any `db:"metadata"`
InitialSlackMessageID gid.GID `db:"initial_slack_message_id"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
SentAt *time.Time `db:"sent_at"`
Error *string `db:"error"`
}
ErrNoUnsentSlackMessage struct{}
@@ -57,6 +57,20 @@ func (e ErrSlackMessageNotFound) Error() string {
return "slack message not found"
}
func (sm *SlackMessage) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM slack_messages WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, sm.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query slack message authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func NewSlackMessage(
scope Scoper,
organizationID gid.GID,

View File

@@ -16,6 +16,7 @@ package coredata
import (
"context"
"errors"
"fmt"
"maps"
"time"
@@ -52,6 +53,20 @@ func (s *Snapshot) CursorKey(field SnapshotOrderField) page.CursorKey {
panic(fmt.Sprintf("unsupported order by: %s", field))
}
func (s *Snapshot) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM snapshots WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, s.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query snapshot authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (s *Snapshot) LoadByID(
ctx context.Context,
conn pg.Conn,

View File

@@ -57,6 +57,20 @@ func (c Task) CursorKey(orderBy TaskOrderField) page.CursorKey {
panic(fmt.Sprintf("unsupported order by: %s", orderBy))
}
func (t *Task) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM tasks WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, t.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query task authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (c *Task) LoadByID(
ctx context.Context,
conn pg.Conn,

View File

@@ -69,6 +69,20 @@ func (tia *TransferImpactAssessment) CursorKey(field TransferImpactAssessmentOrd
panic(fmt.Sprintf("unsupported order by: %s", field))
}
func (tia *TransferImpactAssessment) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM processing_activity_transfer_impact_assessments WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, tia.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query transfer impact assessment authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (tias *TransferImpactAssessments) CountByOrganizationID(
ctx context.Context,
conn pg.Conn,

View File

@@ -52,6 +52,20 @@ func (tc *TrustCenter) CursorKey(orderBy TrustCenterOrderField) page.CursorKey {
panic(fmt.Sprintf("unsupported order by: %s", orderBy))
}
func (tc *TrustCenter) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM trust_centers WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, tc.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query trust center authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (tc *TrustCenter) LoadByID(
ctx context.Context,
conn pg.Conn,

View File

@@ -32,19 +32,19 @@ import (
type (
TrustCenterAccess struct {
ID gid.GID `db:"id"`
OrganizationID gid.GID `db:"organization_id"`
TenantID gid.TenantID `db:"tenant_id"`
TrustCenterID gid.GID `db:"trust_center_id"`
Email mail.Addr `db:"email"`
Name string `db:"name"`
Active bool `db:"active"`
HasAcceptedNonDisclosureAgreement bool `db:"has_accepted_non_disclosure_agreement"`
HasAcceptedNonDisclosureAgreementMetadata json.RawMessage `db:"has_accepted_non_disclosure_agreement_metadata"`
NDAFileID *gid.GID `db:"nda_file_id"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
LastTokenExpiresAt *time.Time `db:"last_token_expires_at"`
ID gid.GID `db:"id"`
OrganizationID gid.GID `db:"organization_id"`
TenantID gid.TenantID `db:"tenant_id"`
TrustCenterID gid.GID `db:"trust_center_id"`
Email mail.Addr `db:"email"`
Name string `db:"name"`
Active bool `db:"active"`
HasAcceptedNonDisclosureAgreement bool `db:"has_accepted_non_disclosure_agreement"`
HasAcceptedNonDisclosureAgreementMetadata json.RawMessage `db:"has_accepted_non_disclosure_agreement_metadata"`
NDAFileID *gid.GID `db:"nda_file_id"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
LastTokenExpiresAt *time.Time `db:"last_token_expires_at"`
}
TrustCenterAccesses []*TrustCenterAccess
@@ -59,6 +59,20 @@ func (tca *TrustCenterAccess) CursorKey(orderBy TrustCenterAccessOrderField) pag
panic(fmt.Sprintf("unsupported order by: %s", orderBy))
}
func (tca *TrustCenterAccess) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM trust_center_accesses WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, tca.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query trust center access authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (tca *TrustCenterAccess) LoadByID(
ctx context.Context,
conn pg.Conn,

View File

@@ -53,6 +53,20 @@ func (tcda *TrustCenterDocumentAccess) CursorKey(orderBy TrustCenterDocumentAcce
panic(fmt.Sprintf("unsupported order by: %s", orderBy))
}
func (tcda *TrustCenterDocumentAccess) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM trust_center_document_accesses WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, tcda.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query trust center document access authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (tcda *TrustCenterDocumentAccess) LoadByID(
ctx context.Context,
conn pg.Conn,

View File

@@ -16,6 +16,7 @@ package coredata
import (
"context"
"errors"
"fmt"
"maps"
"time"
@@ -53,6 +54,20 @@ func (t TrustCenterFile) CursorKey(orderBy TrustCenterFileOrderField) page.Curso
panic(fmt.Sprintf("unsupported order by: %s", orderBy))
}
func (t *TrustCenterFile) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM trust_center_files WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, t.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query trust center file authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (t *TrustCenterFile) LoadByID(
ctx context.Context,
conn pg.Conn,

View File

@@ -59,6 +59,20 @@ func (t TrustCenterReference) CursorKey(orderBy TrustCenterReferenceOrderField)
panic(fmt.Sprintf("unsupported order by: %s", orderBy))
}
func (t *TrustCenterReference) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM trust_center_references WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, t.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query trust center reference authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (t *TrustCenterReference) LoadByID(
ctx context.Context,
conn pg.Conn,

View File

@@ -78,6 +78,20 @@ func (v Vendor) CursorKey(orderBy VendorOrderField) page.CursorKey {
panic(fmt.Sprintf("unsupported order by: %s", orderBy))
}
func (v *Vendor) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM vendors WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, v.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query vendor authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (v *Vendor) LoadByID(
ctx context.Context,
conn pg.Conn,

View File

@@ -56,6 +56,20 @@ func (v VendorBusinessAssociateAgreement) CursorKey(orderBy VendorBusinessAssoci
panic(fmt.Sprintf("unsupported order by: %s", orderBy))
}
func (vbaa *VendorBusinessAssociateAgreement) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM vendor_business_associate_agreements WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, vbaa.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query vendor business associate agreement authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (vbaa *VendorBusinessAssociateAgreement) LoadByVendorID(
ctx context.Context,
conn pg.Conn,

View File

@@ -16,14 +16,15 @@ package coredata
import (
"context"
"errors"
"fmt"
"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 (
@@ -55,6 +56,20 @@ func (c VendorComplianceReport) CursorKey(orderBy VendorComplianceReportOrderFie
panic(fmt.Sprintf("unsupported order by: %s", orderBy))
}
func (v *VendorComplianceReport) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM vendor_compliance_reports WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, v.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query vendor compliance report authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (vcs *VendorComplianceReports) LoadForVendorID(
ctx context.Context,
conn pg.Conn,

View File

@@ -59,6 +59,20 @@ func (vc VendorContact) CursorKey(orderBy VendorContactOrderField) page.CursorKe
panic(fmt.Sprintf("unsupported order by: %s", orderBy))
}
func (vc *VendorContact) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM vendor_contacts WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, vc.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query vendor contact authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (vc *VendorContact) LoadByID(
ctx context.Context,
conn pg.Conn,

View File

@@ -56,6 +56,20 @@ func (v VendorDataPrivacyAgreement) CursorKey(orderBy VendorDataPrivacyAgreement
panic(fmt.Sprintf("unsupported order by: %s", orderBy))
}
func (vdpa *VendorDataPrivacyAgreement) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM vendor_data_privacy_agreements WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, vdpa.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query vendor data privacy agreement authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (vdpa *VendorDataPrivacyAgreement) LoadByVendorID(
ctx context.Context,
conn pg.Conn,

View File

@@ -16,6 +16,7 @@ package coredata
import (
"context"
"errors"
"fmt"
"maps"
"time"
@@ -56,6 +57,20 @@ func (v VendorRiskAssessment) CursorKey(orderBy VendorRiskAssessmentOrderField)
panic(fmt.Sprintf("unsupported order by: %s", orderBy))
}
func (v *VendorRiskAssessment) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM vendor_risk_assessments WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, v.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query vendor risk assessment authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
// Insert adds a new risk assessment to the database
func (r VendorRiskAssessment) Insert(
ctx context.Context,

View File

@@ -54,6 +54,20 @@ func (vs VendorService) CursorKey(orderBy VendorServiceOrderField) page.CursorKe
panic(fmt.Sprintf("unsupported order by: %s", orderBy))
}
func (vs *VendorService) AuthorizationAttributes(ctx context.Context, conn pg.Conn) (map[string]string, error) {
q := `SELECT organization_id FROM vendor_services WHERE id = $1 LIMIT 1;`
var organizationID gid.GID
if err := conn.QueryRow(ctx, q, vs.ID).Scan(&organizationID); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrResourceNotFound
}
return nil, fmt.Errorf("cannot query vendor service authorization attributes: %w", err)
}
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (vs *VendorService) LoadByID(
ctx context.Context,
conn pg.Conn,