Flatten compliance portal package layout

Remove the root complianceportal package and the resolver
facade that existed only to break an IAM import cycle. Admin
policies, domain URL helpers, and actions live under
management; visitor OAuth metadata, brand URLs, and public
read paths live under visitor. Drop the duplicate trust API
magic-link mutations now that Connect handles portal auth, and
stop IAM from owning compliance page email branding.

Signed-off-by: Bryan Frimin <bryan@probo.com>
This commit is contained in:
Bryan Frimin
2026-07-17 16:19:39 +02:00
parent 4cec74c1a1
commit 7e0d187dcf
57 changed files with 737 additions and 1061 deletions

View File

@@ -0,0 +1,66 @@
// Copyright (c) 2026 Probo Inc <hello@probo.com>.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
package trust_test
import (
"regexp"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.probo.inc/probo/e2e/internal/testutil"
)
func TestTrustCenter_SlugHasEntropySuffix(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
organizationID := owner.GetOrganizationID().String()
const query = `
query($organizationId: ID!) {
node(id: $organizationId) {
... on Organization {
trustCenter {
slug
}
}
}
}
`
var result struct {
Node struct {
TrustCenter struct {
Slug string `json:"slug"`
} `json:"trustCenter"`
} `json:"node"`
}
err := owner.Execute(query, map[string]any{
"organizationId": organizationID,
}, &result)
require.NoError(t, err)
require.NotEmpty(t, result.Node.TrustCenter.Slug)
slugWithEntropy := regexp.MustCompile(`^[a-z0-9-]+-[0-9a-f]{8}$`)
assert.Regexp(t, slugWithEntropy, result.Node.TrustCenter.Slug)
}

View File

@@ -1,51 +0,0 @@
// Copyright (c) 2025-2026 Probo Inc <hello@probo.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 complianceportal
import (
"context"
"go.gearno.de/kit/pg"
"go.probo.inc/probo/pkg/complianceportal/resolver"
"go.probo.inc/probo/pkg/coredata"
)
// EffectiveDomainForTrustCenter returns the domain a compliance page is served
// under: the custom domain when it has an active certificate, otherwise the
// default subdomain when its certificate is active. It returns nil when no
// serving domain is available yet.
//
// It is the single certificate-status-aware domain resolver shared by the
// management and visitor sub-packages.
func EffectiveDomainForTrustCenter(
ctx context.Context,
conn pg.Querier,
scope coredata.Scoper,
trustCenter *coredata.TrustCenter,
) (*coredata.CustomDomain, error) {
return resolver.EffectiveDomainForTrustCenter(ctx, conn, scope, trustCenter)
}
// PublicURLForTrustCenter returns the canonical public URL of a compliance
// page on its dedicated domain.
func PublicURLForTrustCenter(
ctx context.Context,
conn pg.Querier,
scope coredata.Scoper,
trustCenter *coredata.TrustCenter,
baseDomain string,
) (string, error) {
return resolver.PublicURLForTrustCenter(ctx, conn, scope, trustCenter, baseDomain)
}

View File

@@ -83,7 +83,7 @@ func (utcar *UpdateAccessRequest) Validate() error {
func (s *Service) ListAccesses( func (s *Service) ListAccesses(
ctx context.Context, ctx context.Context,
scope coredata.Scoper, scope coredata.Scoper,
trustCenterID gid.GID, compliancePageID gid.GID,
cursor *page.Cursor[coredata.TrustCenterAccessOrderField], cursor *page.Cursor[coredata.TrustCenterAccessOrderField],
) (*page.Page[*coredata.TrustCenterAccess, coredata.TrustCenterAccessOrderField], error) { ) (*page.Page[*coredata.TrustCenterAccess, coredata.TrustCenterAccessOrderField], error) {
var accesses coredata.TrustCenterAccesses var accesses coredata.TrustCenterAccesses
@@ -91,7 +91,7 @@ func (s *Service) ListAccesses(
err := s.pg.WithConn( err := s.pg.WithConn(
ctx, ctx,
func(ctx context.Context, conn pg.Querier) error { func(ctx context.Context, conn pg.Querier) error {
return accesses.LoadByTrustCenterID(ctx, conn, scope, trustCenterID, cursor) return accesses.LoadByTrustCenterID(ctx, conn, scope, compliancePageID, cursor)
}, },
) )
if err != nil { if err != nil {
@@ -244,7 +244,7 @@ func (s *Service) UpdateAccess(
access = &coredata.TrustCenterAccess{} access = &coredata.TrustCenterAccess{}
if err := access.LoadByID(ctx, tx, scope, req.ID); err != nil { if err := access.LoadByID(ctx, tx, scope, req.ID); err != nil {
return fmt.Errorf("cannot load trust center access: %w", err) return fmt.Errorf("cannot load compliance page access: %w", err)
} }
var tcdas coredata.TrustCenterDocumentAccesses var tcdas coredata.TrustCenterDocumentAccesses
@@ -310,11 +310,11 @@ func (s *Service) UpdateAccess(
trustCenterFiles := &coredata.TrustCenterFiles{} trustCenterFiles := &coredata.TrustCenterFiles{}
if err := trustCenterFiles.LoadByIDs(ctx, tx, scope, trustCenterFileIDs); err != nil { if err := trustCenterFiles.LoadByIDs(ctx, tx, scope, trustCenterFileIDs); err != nil {
return fmt.Errorf("cannot load trust center files: %w", err) return fmt.Errorf("cannot load compliance page files: %w", err)
} }
if err := tcdas.MergeTrustCenterFileAccesses(ctx, tx, scope, access.OrganizationID, access.ID, fileData); err != nil { if err := tcdas.MergeTrustCenterFileAccesses(ctx, tx, scope, access.OrganizationID, access.ID, fileData); err != nil {
return fmt.Errorf("cannot merge trust center file accesses: %w", err) return fmt.Errorf("cannot merge compliance page file accesses: %w", err)
} }
} }
@@ -358,11 +358,11 @@ func (s *Service) DeleteAccess(
access := &coredata.TrustCenterAccess{} access := &coredata.TrustCenterAccess{}
if err := access.LoadByID(ctx, tx, scope, trustCenterAccessID); err != nil { if err := access.LoadByID(ctx, tx, scope, trustCenterAccessID); err != nil {
return fmt.Errorf("cannot load trust center access: %w", err) return fmt.Errorf("cannot load compliance page access: %w", err)
} }
if err := access.Delete(ctx, tx, scope); err != nil { if err := access.Delete(ctx, tx, scope); err != nil {
return fmt.Errorf("cannot delete trust center access: %w", err) return fmt.Errorf("cannot delete compliance page access: %w", err)
} }
return nil return nil
@@ -387,7 +387,7 @@ func (s *Service) sendAccessEmail(
access.UpdatedAt = now access.UpdatedAt = now
if err := access.Update(ctx, tx, scope); err != nil { if err := access.Update(ctx, tx, scope); err != nil {
return fmt.Errorf("cannot update trust center access with expiration: %w", err) return fmt.Errorf("cannot update compliance page access with expiration: %w", err)
} }
profile := &coredata.MembershipProfile{} profile := &coredata.MembershipProfile{}
@@ -410,7 +410,7 @@ func (s *Service) sendAccessEmail(
subject, textBody, htmlBody, err := emailPresenter.RenderTrustCenterAccess(ctx, organization.Name) subject, textBody, htmlBody, err := emailPresenter.RenderTrustCenterAccess(ctx, organization.Name)
if err != nil { if err != nil {
return fmt.Errorf("cannot render trust center access email: %w", err) return fmt.Errorf("cannot render compliance page access email: %w", err)
} }
accessEmail := coredata.NewEmail( accessEmail := coredata.NewEmail(

View File

@@ -12,7 +12,7 @@
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR // OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE. // PERFORMANCE OF THIS SOFTWARE.
package complianceportal package management
const ( const (
// Custom domain actions. // Custom domain actions.

View File

@@ -78,7 +78,7 @@ func (r *DeleteCustomLinkRequest) Validate() error {
func (s *Service) ListCustomLinks( func (s *Service) ListCustomLinks(
ctx context.Context, ctx context.Context,
scope coredata.Scoper, scope coredata.Scoper,
trustCenterID gid.GID, compliancePageID gid.GID,
cursor *page.Cursor[coredata.ComplianceCustomLinkOrderField], cursor *page.Cursor[coredata.ComplianceCustomLinkOrderField],
) (*page.Page[*coredata.ComplianceCustomLink, coredata.ComplianceCustomLinkOrderField], error) { ) (*page.Page[*coredata.ComplianceCustomLink, coredata.ComplianceCustomLinkOrderField], error) {
var items coredata.ComplianceCustomLinks var items coredata.ComplianceCustomLinks
@@ -86,7 +86,7 @@ func (s *Service) ListCustomLinks(
err := s.pg.WithConn( err := s.pg.WithConn(
ctx, ctx,
func(ctx context.Context, conn pg.Querier) error { func(ctx context.Context, conn pg.Querier) error {
if err := items.LoadByTrustCenterID(ctx, conn, scope, trustCenterID, cursor); err != nil { if err := items.LoadByTrustCenterID(ctx, conn, scope, compliancePageID, cursor); err != nil {
return fmt.Errorf("cannot load custom links: %w", err) return fmt.Errorf("cannot load custom links: %w", err)
} }
@@ -117,14 +117,14 @@ func (s *Service) CreateCustomLink(
err := s.pg.WithTx( err := s.pg.WithTx(
ctx, ctx,
func(ctx context.Context, tx pg.Tx) error { func(ctx context.Context, tx pg.Tx) error {
trustCenter := &coredata.TrustCenter{} compliancePage := &coredata.TrustCenter{}
if err := trustCenter.LoadByID(ctx, tx, scope, req.TrustCenterID); err != nil { if err := compliancePage.LoadByID(ctx, tx, scope, req.TrustCenterID); err != nil {
return fmt.Errorf("cannot load trust center: %w", err) return fmt.Errorf("cannot load compliance page: %w", err)
} }
item = &coredata.ComplianceCustomLink{ item = &coredata.ComplianceCustomLink{
ID: id, ID: id,
OrganizationID: trustCenter.OrganizationID, OrganizationID: compliancePage.OrganizationID,
TrustCenterID: req.TrustCenterID, TrustCenterID: req.TrustCenterID,
Name: req.Name, Name: req.Name,
URL: req.URL, URL: req.URL,

View File

@@ -12,7 +12,7 @@
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR // OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE. // PERFORMANCE OF THIS SOFTWARE.
package resolver package management
import ( import (
"context" "context"
@@ -23,29 +23,25 @@ import (
"go.probo.inc/probo/pkg/gid" "go.probo.inc/probo/pkg/gid"
) )
// EffectiveDomainForTrustCenter returns the domain a compliance page is served func (s *Service) EffectiveDomainForCompliancePage(
// under: the custom domain when it has an active certificate, otherwise the
// default subdomain when its certificate is active. It returns nil when no
// serving domain is available yet.
func EffectiveDomainForTrustCenter(
ctx context.Context, ctx context.Context,
conn pg.Querier, conn pg.Querier,
scope coredata.Scoper, scope coredata.Scoper,
trustCenter *coredata.TrustCenter, compliancePage *coredata.TrustCenter,
) (*coredata.CustomDomain, error) { ) (*coredata.CustomDomain, error) {
byID, active, err := loadDomains(ctx, conn, scope, trustCenter) byID, active, err := loadDomains(ctx, conn, scope, compliancePage)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if trustCenter.CustomDomainID != nil { if compliancePage.CustomDomainID != nil {
if d := byID[*trustCenter.CustomDomainID]; d != nil && active[d.ID] { if d := byID[*compliancePage.CustomDomainID]; d != nil && active[d.ID] {
return d, nil return d, nil
} }
} }
if trustCenter.DefaultDomainID != nil { if compliancePage.DefaultDomainID != nil {
if d := byID[*trustCenter.DefaultDomainID]; d != nil && active[d.ID] { if d := byID[*compliancePage.DefaultDomainID]; d != nil && active[d.ID] {
return d, nil return d, nil
} }
} }
@@ -53,20 +49,13 @@ func EffectiveDomainForTrustCenter(
return nil, nil return nil, nil
} }
// PublicURLForTrustCenter returns the canonical public URL of a compliance func (s *Service) PublicURLForCompliancePage(
// page. Compliance pages are always served on a dedicated domain: the custom
// domain when its certificate is active, otherwise the default probopage
// subdomain (even while its certificate provisions), and finally the default
// subdomain hostname derived from the page slug when no domain row is loaded
// yet.
func PublicURLForTrustCenter(
ctx context.Context, ctx context.Context,
conn pg.Querier, conn pg.Querier,
scope coredata.Scoper, scope coredata.Scoper,
trustCenter *coredata.TrustCenter, compliancePage *coredata.TrustCenter,
baseDomain string,
) (string, error) { ) (string, error) {
byID, active, err := loadDomains(ctx, conn, scope, trustCenter) byID, active, err := loadDomains(ctx, conn, scope, compliancePage)
if err != nil { if err != nil {
return "", err return "", err
} }
@@ -74,14 +63,14 @@ func PublicURLForTrustCenter(
var host string var host string
switch { switch {
case trustCenter.CustomDomainID != nil && byID[*trustCenter.CustomDomainID] != nil && active[*trustCenter.CustomDomainID]: case compliancePage.CustomDomainID != nil && byID[*compliancePage.CustomDomainID] != nil && active[*compliancePage.CustomDomainID]:
host = byID[*trustCenter.CustomDomainID].Domain host = byID[*compliancePage.CustomDomainID].Domain
case trustCenter.DefaultDomainID != nil && byID[*trustCenter.DefaultDomainID] != nil: case compliancePage.DefaultDomainID != nil && byID[*compliancePage.DefaultDomainID] != nil:
host = byID[*trustCenter.DefaultDomainID].Domain host = byID[*compliancePage.DefaultDomainID].Domain
} }
if host == "" { if host == "" {
host = trustCenter.Slug + "." + baseDomain host = compliancePage.Slug + "." + s.baseDomain
} }
return "https://" + host, nil return "https://" + host, nil
@@ -91,15 +80,15 @@ func loadDomains(
ctx context.Context, ctx context.Context,
conn pg.Querier, conn pg.Querier,
scope coredata.Scoper, scope coredata.Scoper,
trustCenter *coredata.TrustCenter, compliancePage *coredata.TrustCenter,
) (map[gid.GID]*coredata.CustomDomain, map[gid.GID]bool, error) { ) (map[gid.GID]*coredata.CustomDomain, map[gid.GID]bool, error) {
var ids []gid.GID var ids []gid.GID
if trustCenter.CustomDomainID != nil { if compliancePage.CustomDomainID != nil {
ids = append(ids, *trustCenter.CustomDomainID) ids = append(ids, *compliancePage.CustomDomainID)
} }
if trustCenter.DefaultDomainID != nil { if compliancePage.DefaultDomainID != nil {
ids = append(ids, *trustCenter.DefaultDomainID) ids = append(ids, *compliancePage.DefaultDomainID)
} }
byID := make(map[gid.GID]*coredata.CustomDomain) byID := make(map[gid.GID]*coredata.CustomDomain)

View File

@@ -21,27 +21,13 @@ import (
"time" "time"
"go.gearno.de/kit/pg" "go.gearno.de/kit/pg"
"go.probo.inc/probo/pkg/complianceportal"
"go.probo.inc/probo/pkg/coredata" "go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/gid" "go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/validator" "go.probo.inc/probo/pkg/validator"
) )
// The compliance portal service owns the relationship between a compliance
// page (trust center) and its domains. A page has two slots stored on the
// trust center row: a default {slug}.probopage.com domain provided by Probo and
// an optional custom domain. It provisions each domain's TLS certificate
// through the generic certmanager service within the trust center's transaction
// so slot changes stay atomic with the page.
// ErrCustomDomainSlotTaken is returned when a compliance page already has a
// custom domain and another one is added.
var ErrCustomDomainSlotTaken = errors.New("compliance page already has a custom domain") var ErrCustomDomainSlotTaken = errors.New("compliance page already has a custom domain")
// AddCustomDomain provisions the compliance page's custom domain. It fails
// when the page already has one. The default probopage subdomain, provisioned
// at page creation, keeps serving as a fallback while the new certificate
// provisions.
func (s *Service) AddCustomDomain( func (s *Service) AddCustomDomain(
ctx context.Context, ctx context.Context,
scope coredata.Scoper, scope coredata.Scoper,
@@ -60,12 +46,12 @@ func (s *Service) AddCustomDomain(
err := s.pg.WithTx( err := s.pg.WithTx(
ctx, ctx,
func(ctx context.Context, tx pg.Tx) error { func(ctx context.Context, tx pg.Tx) error {
trustCenter := &coredata.TrustCenter{} compliancePage := &coredata.TrustCenter{}
if err := trustCenter.LoadByID(ctx, tx, scope, compliancePageID); err != nil { if err := compliancePage.LoadByID(ctx, tx, scope, compliancePageID); err != nil {
return fmt.Errorf("cannot load trust center: %w", err) return fmt.Errorf("cannot load compliance page: %w", err)
} }
if trustCenter.CustomDomainID != nil { if compliancePage.CustomDomainID != nil {
return ErrCustomDomainSlotTaken return ErrCustomDomainSlotTaken
} }
@@ -76,7 +62,7 @@ func (s *Service) AddCustomDomain(
customDomain = coredata.NewCustomDomain( customDomain = coredata.NewCustomDomain(
scope.GetTenantID(), scope.GetTenantID(),
trustCenter.OrganizationID, compliancePage.OrganizationID,
domain, domain,
false, false,
) )
@@ -86,11 +72,11 @@ func (s *Service) AddCustomDomain(
return fmt.Errorf("cannot insert custom domain: %w", err) return fmt.Errorf("cannot insert custom domain: %w", err)
} }
trustCenter.CustomDomainID = &customDomain.ID compliancePage.CustomDomainID = &customDomain.ID
trustCenter.UpdatedAt = time.Now() compliancePage.UpdatedAt = time.Now()
if err := trustCenter.Update(ctx, tx, scope); err != nil { if err := compliancePage.Update(ctx, tx, scope); err != nil {
return fmt.Errorf("cannot update trust center: %w", err) return fmt.Errorf("cannot update compliance page: %w", err)
} }
return nil return nil
@@ -103,9 +89,6 @@ func (s *Service) AddCustomDomain(
return customDomain, nil return customDomain, nil
} }
// RemoveCustomDomain clears the compliance page's custom domain and deletes
// the underlying domain together with its certificate. The default domain
// cannot be removed.
func (s *Service) RemoveCustomDomain( func (s *Service) RemoveCustomDomain(
ctx context.Context, ctx context.Context,
scope coredata.Scoper, scope coredata.Scoper,
@@ -120,24 +103,24 @@ func (s *Service) RemoveCustomDomain(
} }
if domain.Managed { if domain.Managed {
return complianceportal.ErrCustomDomainManaged return ErrCustomDomainManaged
} }
trustCenter := &coredata.TrustCenter{} compliancePage := &coredata.TrustCenter{}
err := trustCenter.LoadByDomainID(ctx, tx, customDomainID) err := compliancePage.LoadByDomainID(ctx, tx, customDomainID)
switch { switch {
case err == nil: case err == nil:
if trustCenter.CustomDomainID != nil && *trustCenter.CustomDomainID == customDomainID { if compliancePage.CustomDomainID != nil && *compliancePage.CustomDomainID == customDomainID {
trustCenter.CustomDomainID = nil compliancePage.CustomDomainID = nil
trustCenter.UpdatedAt = time.Now() compliancePage.UpdatedAt = time.Now()
if err := trustCenter.Update(ctx, tx, scope); err != nil { if err := compliancePage.Update(ctx, tx, scope); err != nil {
return fmt.Errorf("cannot update trust center: %w", err) return fmt.Errorf("cannot update compliance page: %w", err)
} }
} }
case errors.Is(err, coredata.ErrResourceNotFound): case errors.Is(err, coredata.ErrResourceNotFound):
default: default:
return fmt.Errorf("cannot load trust center by domain id: %w", err) return fmt.Errorf("cannot load compliance page by domain id: %w", err)
} }
if err := domain.Delete(ctx, tx, scope); err != nil { if err := domain.Delete(ctx, tx, scope); err != nil {
@@ -155,78 +138,37 @@ func (s *Service) RemoveCustomDomain(
) )
} }
// GetCertificate returns the certificate backing a custom domain, or nil when
// the domain has no certificate yet.
func (s *Service) GetCertificate(
ctx context.Context,
scope coredata.Scoper,
domain *coredata.CustomDomain,
) (*coredata.Certificate, error) {
if domain == nil || domain.CertificateID == nil {
return nil, nil
}
return s.certManager.Get(ctx, scope, *domain.CertificateID)
}
// GetDefaultDomain returns the compliance page's default probopage subdomain, // GetDefaultDomain returns the compliance page's default probopage subdomain,
// or nil when it has not been provisioned yet. // or nil when it has not been provisioned yet.
func (s *Service) GetDefaultDomain( func (s *Service) GetDefaultDomain(
ctx context.Context, ctx context.Context,
scope coredata.Scoper, scope coredata.Scoper,
compliancePageID gid.GID, compliancePageID gid.GID,
) (*coredata.CustomDomain, error) {
return s.domainSlot(ctx, scope, compliancePageID, func(tc *coredata.TrustCenter) *gid.GID {
return tc.DefaultDomainID
},
)
}
// GetCustomDomain returns the compliance page's custom domain, or nil when
// none is configured.
func (s *Service) GetCustomDomain(
ctx context.Context,
scope coredata.Scoper,
compliancePageID gid.GID,
) (*coredata.CustomDomain, error) {
return s.domainSlot(ctx, scope, compliancePageID, func(tc *coredata.TrustCenter) *gid.GID {
return tc.CustomDomainID
},
)
}
func (s *Service) domainSlot(
ctx context.Context,
scope coredata.Scoper,
compliancePageID gid.GID,
slot func(*coredata.TrustCenter) *gid.GID,
) (*coredata.CustomDomain, error) { ) (*coredata.CustomDomain, error) {
var domain *coredata.CustomDomain var domain *coredata.CustomDomain
err := s.pg.WithConn( err := s.pg.WithConn(
ctx, ctx,
func(ctx context.Context, conn pg.Querier) error { func(ctx context.Context, conn pg.Querier) error {
trustCenter := &coredata.TrustCenter{} compliancePage := &coredata.TrustCenter{}
if err := trustCenter.LoadByID(ctx, conn, scope, compliancePageID); err != nil { if err := compliancePage.LoadByID(ctx, conn, scope, compliancePageID); err != nil {
return fmt.Errorf("cannot load trust center: %w", err) return fmt.Errorf("cannot load compliance page: %w", err)
} }
domainID := slot(trustCenter) if compliancePage.DefaultDomainID == nil {
if domainID == nil {
return nil return nil
} }
loaded := &coredata.CustomDomain{} domain = &coredata.CustomDomain{}
if err := loaded.LoadByID(ctx, conn, scope, *domainID); err != nil { if err := domain.LoadByID(ctx, conn, scope, *compliancePage.DefaultDomainID); err != nil {
if errors.Is(err, coredata.ErrResourceNotFound) { if errors.Is(err, coredata.ErrResourceNotFound) {
domain = nil
return nil return nil
} }
return fmt.Errorf("cannot load custom domain: %w", err) return fmt.Errorf("cannot load custom domain: %w", err)
} }
domain = loaded
return nil return nil
}, },
) )
@@ -237,31 +179,34 @@ func (s *Service) domainSlot(
return domain, nil return domain, nil
} }
// EffectiveDomain returns the domain a compliance page is served under: the func (s *Service) GetCustomDomain(
// custom domain when it has an active certificate, otherwise the default
// subdomain when its certificate is active. It returns nil when no serving
// domain is available yet.
func (s *Service) EffectiveDomain(
ctx context.Context, ctx context.Context,
scope coredata.Scoper, scope coredata.Scoper,
compliancePageID gid.GID, compliancePageID gid.GID,
) (*coredata.CustomDomain, error) { ) (*coredata.CustomDomain, error) {
var effective *coredata.CustomDomain var domain *coredata.CustomDomain
err := s.pg.WithConn( err := s.pg.WithConn(
ctx, ctx,
func(ctx context.Context, conn pg.Querier) error { func(ctx context.Context, conn pg.Querier) error {
trustCenter := &coredata.TrustCenter{} compliancePage := &coredata.TrustCenter{}
if err := trustCenter.LoadByID(ctx, conn, scope, compliancePageID); err != nil { if err := compliancePage.LoadByID(ctx, conn, scope, compliancePageID); err != nil {
return fmt.Errorf("cannot load trust center: %w", err) return fmt.Errorf("cannot load compliance page: %w", err)
} }
d, err := complianceportal.EffectiveDomainForTrustCenter(ctx, conn, scope, trustCenter) if compliancePage.CustomDomainID == nil {
if err != nil { return nil
return err
} }
effective = d domain = &coredata.CustomDomain{}
if err := domain.LoadByID(ctx, conn, scope, *compliancePage.CustomDomainID); err != nil {
if errors.Is(err, coredata.ErrResourceNotFound) {
domain = nil
return nil
}
return fmt.Errorf("cannot load custom domain: %w", err)
}
return nil return nil
}, },
@@ -270,26 +215,7 @@ func (s *Service) EffectiveDomain(
return nil, err return nil, err
} }
return effective, nil return domain, nil
}
// EffectiveCanonicalHost returns the host a compliance page should be served
// under, or an empty string when no serving host is available yet.
func (s *Service) EffectiveCanonicalHost(
ctx context.Context,
scope coredata.Scoper,
compliancePageID gid.GID,
) (string, error) {
domain, err := s.EffectiveDomain(ctx, scope, compliancePageID)
if err != nil {
return "", err
}
if domain == nil {
return "", nil
}
return domain.Domain, nil
} }
// PublicURL returns the canonical public URL of a compliance page on its // PublicURL returns the canonical public URL of a compliance page on its
@@ -304,18 +230,17 @@ func (s *Service) PublicURL(
err := s.pg.WithConn( err := s.pg.WithConn(
ctx, ctx,
func(ctx context.Context, conn pg.Querier) error { func(ctx context.Context, conn pg.Querier) error {
trustCenter := &coredata.TrustCenter{} compliancePage := &coredata.TrustCenter{}
if err := trustCenter.LoadByID(ctx, conn, scope, compliancePageID); err != nil { if err := compliancePage.LoadByID(ctx, conn, scope, compliancePageID); err != nil {
return fmt.Errorf("cannot load trust center: %w", err) return fmt.Errorf("cannot load compliance page: %w", err)
} }
url, err := complianceportal.PublicURLForTrustCenter(ctx, conn, scope, trustCenter, s.baseDomain) var err error
publicURL, err = s.PublicURLForCompliancePage(ctx, conn, scope, compliancePage)
if err != nil { if err != nil {
return err return fmt.Errorf("cannot resolve public url: %w", err)
} }
publicURL = url
return nil return nil
}, },
) )

View File

@@ -12,7 +12,7 @@
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR // OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE. // PERFORMANCE OF THIS SOFTWARE.
package complianceportal package management
import "errors" import "errors"

View File

@@ -92,7 +92,7 @@ func (s *Service) ListFilesForOrganizationID(
ctx, ctx,
func(ctx context.Context, conn pg.Querier) error { func(ctx context.Context, conn pg.Querier) error {
if err := files.LoadByOrganizationID(ctx, conn, scope, organizationID, cursor, filter); err != nil { if err := files.LoadByOrganizationID(ctx, conn, scope, organizationID, cursor, filter); err != nil {
return fmt.Errorf("cannot load trust center files: %w", err) return fmt.Errorf("cannot load compliance page files: %w", err)
} }
return nil return nil
@@ -119,7 +119,7 @@ func (s *Service) CountFilesForOrganizationID(
count, err = (&coredata.TrustCenterFiles{}).CountByOrganizationID(ctx, conn, scope, organizationID) count, err = (&coredata.TrustCenterFiles{}).CountByOrganizationID(ctx, conn, scope, organizationID)
if err != nil { if err != nil {
return fmt.Errorf("cannot count trust center files: %w", err) return fmt.Errorf("cannot count compliance page files: %w", err)
} }
return nil return nil
@@ -144,7 +144,7 @@ func (s *Service) GetFile(
func(ctx context.Context, conn pg.Querier) error { func(ctx context.Context, conn pg.Querier) error {
file = &coredata.TrustCenterFile{} file = &coredata.TrustCenterFile{}
if err := file.LoadByID(ctx, conn, scope, id); err != nil { if err := file.LoadByID(ctx, conn, scope, id); err != nil {
return fmt.Errorf("cannot load trust center file: %w", err) return fmt.Errorf("cannot load compliance page file: %w", err)
} }
return nil return nil
@@ -210,7 +210,7 @@ func (s *Service) CreateFile(
} }
if err := file.Insert(ctx, tx, scope); err != nil { if err := file.Insert(ctx, tx, scope); err != nil {
return fmt.Errorf("cannot insert trust center file: %w", err) return fmt.Errorf("cannot insert compliance page file: %w", err)
} }
return nil return nil
@@ -243,7 +243,7 @@ func (s *Service) UpdateFile(
file = &coredata.TrustCenterFile{} file = &coredata.TrustCenterFile{}
if err := file.LoadByID(ctx, tx, scope, req.ID); err != nil { if err := file.LoadByID(ctx, tx, scope, req.ID); err != nil {
return fmt.Errorf("cannot load trust center file: %w", err) return fmt.Errorf("cannot load compliance page file: %w", err)
} }
if req.Name != nil { if req.Name != nil {
@@ -261,7 +261,7 @@ func (s *Service) UpdateFile(
file.UpdatedAt = now file.UpdatedAt = now
if err := file.Update(ctx, tx, scope); err != nil { if err := file.Update(ctx, tx, scope); err != nil {
return fmt.Errorf("cannot update trust center file: %w", err) return fmt.Errorf("cannot update compliance page file: %w", err)
} }
return nil return nil
@@ -285,11 +285,11 @@ func (s *Service) DeleteFile(
file := &coredata.TrustCenterFile{} file := &coredata.TrustCenterFile{}
if err := file.LoadByID(ctx, tx, scope, trustCenterFileID); err != nil { if err := file.LoadByID(ctx, tx, scope, trustCenterFileID); err != nil {
return fmt.Errorf("cannot load trust center file: %w", err) return fmt.Errorf("cannot load compliance page file: %w", err)
} }
if err := file.Delete(ctx, tx, scope); err != nil { if err := file.Delete(ctx, tx, scope); err != nil {
return fmt.Errorf("cannot delete trust center file: %w", err) return fmt.Errorf("cannot delete compliance page file: %w", err)
} }
return nil return nil
@@ -311,7 +311,7 @@ func (s *Service) GenerateFileURL(
func(ctx context.Context, conn pg.Querier) error { func(ctx context.Context, conn pg.Querier) error {
file := &coredata.TrustCenterFile{} file := &coredata.TrustCenterFile{}
if err := file.LoadByID(ctx, conn, scope, trustCenterFileID); err != nil { if err := file.LoadByID(ctx, conn, scope, trustCenterFileID); err != nil {
return fmt.Errorf("cannot load trust center file: %w", err) return fmt.Errorf("cannot load compliance page file: %w", err)
} }
storedFile = &coredata.File{} storedFile = &coredata.File{}
@@ -405,8 +405,8 @@ func (s *Service) uploadFile(
ContentType: new(contentType), ContentType: new(contentType),
CacheControl: new("private, max-age=3600"), CacheControl: new("private, max-age=3600"),
Metadata: map[string]string{ Metadata: map[string]string{
"type": "trust-center-file", "type": "compliance-page-file",
"trust-center-file-id": trustCenterFileID.String(), "compliance-page-file-id": trustCenterFileID.String(),
"organization-id": organizationID.String(), "organization-id": organizationID.String(),
}, },
}, },

View File

@@ -76,7 +76,7 @@ func (r *DeleteFrameworkRequest) Validate() error {
func (s *Service) ListFrameworksWithHidden( func (s *Service) ListFrameworksWithHidden(
ctx context.Context, ctx context.Context,
scope coredata.Scoper, scope coredata.Scoper,
trustCenterID gid.GID, compliancePageID gid.GID,
cursor *page.Cursor[coredata.ComplianceFrameworkOrderField], cursor *page.Cursor[coredata.ComplianceFrameworkOrderField],
) (*page.Page[*coredata.ComplianceFramework, coredata.ComplianceFrameworkOrderField], error) { ) (*page.Page[*coredata.ComplianceFramework, coredata.ComplianceFrameworkOrderField], error) {
var cfs coredata.ComplianceFrameworks var cfs coredata.ComplianceFrameworks
@@ -84,7 +84,7 @@ func (s *Service) ListFrameworksWithHidden(
err := s.pg.WithConn( err := s.pg.WithConn(
ctx, ctx,
func(ctx context.Context, conn pg.Querier) error { func(ctx context.Context, conn pg.Querier) error {
if err := cfs.LoadWithHiddenByTrustCenterID(ctx, conn, scope, trustCenterID, cursor); err != nil { if err := cfs.LoadWithHiddenByTrustCenterID(ctx, conn, scope, compliancePageID, cursor); err != nil {
return fmt.Errorf("cannot load frameworks with hidden: %w", err) return fmt.Errorf("cannot load frameworks with hidden: %w", err)
} }
@@ -116,9 +116,9 @@ func (s *Service) CreateFramework(
err := s.pg.WithTx( err := s.pg.WithTx(
ctx, ctx,
func(ctx context.Context, tx pg.Tx) error { func(ctx context.Context, tx pg.Tx) error {
trustCenter := &coredata.TrustCenter{} compliancePage := &coredata.TrustCenter{}
if err := trustCenter.LoadByID(ctx, tx, scope, req.TrustCenterID); err != nil { if err := compliancePage.LoadByID(ctx, tx, scope, req.TrustCenterID); err != nil {
return fmt.Errorf("cannot load trust center: %w", err) return fmt.Errorf("cannot load compliance page: %w", err)
} }
framework := &coredata.Framework{} framework := &coredata.Framework{}
@@ -128,7 +128,7 @@ func (s *Service) CreateFramework(
cf = &coredata.ComplianceFramework{ cf = &coredata.ComplianceFramework{
ID: cfID, ID: cfID,
OrganizationID: trustCenter.OrganizationID, OrganizationID: compliancePage.OrganizationID,
TrustCenterID: req.TrustCenterID, TrustCenterID: req.TrustCenterID,
FrameworkID: req.FrameworkID, FrameworkID: req.FrameworkID,
CreatedAt: now, CreatedAt: now,

View File

@@ -12,7 +12,7 @@
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR // OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE. // PERFORMANCE OF THIS SOFTWARE.
package complianceportal package management
import ( import (
"go.probo.inc/probo/pkg/coredata" "go.probo.inc/probo/pkg/coredata"

View File

@@ -12,7 +12,7 @@
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR // OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE. // PERFORMANCE OF THIS SOFTWARE.
package complianceportal package management
import ( import (
"go.probo.inc/probo/pkg/iam" "go.probo.inc/probo/pkg/iam"

View File

@@ -33,7 +33,6 @@ import (
"go.gearno.de/crypto/uuid" "go.gearno.de/crypto/uuid"
"go.gearno.de/kit/pg" "go.gearno.de/kit/pg"
"go.probo.inc/probo/packages/emails" "go.probo.inc/probo/packages/emails"
"go.probo.inc/probo/pkg/complianceportal"
"go.probo.inc/probo/pkg/coredata" "go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/filevalidation" "go.probo.inc/probo/pkg/filevalidation"
"go.probo.inc/probo/pkg/gid" "go.probo.inc/probo/pkg/gid"
@@ -134,26 +133,26 @@ func (req *UpdateBrandRequest) Validate() error {
func (s *Service) Get( func (s *Service) Get(
ctx context.Context, ctx context.Context,
scope coredata.Scoper, scope coredata.Scoper,
trustCenterID gid.GID, compliancePageID gid.GID,
) (*coredata.TrustCenter, error) { ) (*coredata.TrustCenter, error) {
var trustCenter *coredata.TrustCenter var compliancePage *coredata.TrustCenter
err := s.pg.WithConn( err := s.pg.WithConn(
ctx, ctx,
func(ctx context.Context, conn pg.Querier) error { func(ctx context.Context, conn pg.Querier) error {
trustCenter = &coredata.TrustCenter{} compliancePage = &coredata.TrustCenter{}
if err := trustCenter.LoadByID(ctx, conn, scope, trustCenterID); err != nil { if err := compliancePage.LoadByID(ctx, conn, scope, compliancePageID); err != nil {
return fmt.Errorf("cannot load trust center: %w", err) return fmt.Errorf("cannot load compliance page: %w", err)
} }
return nil return nil
}, },
) )
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot load trust center: %w", err) return nil, fmt.Errorf("cannot load compliance page: %w", err)
} }
return trustCenter, nil return compliancePage, nil
} }
func (s *Service) GetByOrganizationID( func (s *Service) GetByOrganizationID(
@@ -161,14 +160,14 @@ func (s *Service) GetByOrganizationID(
scope coredata.Scoper, scope coredata.Scoper,
organizationID gid.GID, organizationID gid.GID,
) (*coredata.TrustCenter, error) { ) (*coredata.TrustCenter, error) {
var trustCenter *coredata.TrustCenter var compliancePage *coredata.TrustCenter
err := s.pg.WithConn( err := s.pg.WithConn(
ctx, ctx,
func(ctx context.Context, conn pg.Querier) error { func(ctx context.Context, conn pg.Querier) error {
trustCenter = &coredata.TrustCenter{} compliancePage = &coredata.TrustCenter{}
if err := trustCenter.LoadByOrganizationID(ctx, conn, scope, organizationID); err != nil { if err := compliancePage.LoadByOrganizationID(ctx, conn, scope, organizationID); err != nil {
return fmt.Errorf("cannot load trust center: %w", err) return fmt.Errorf("cannot load compliance page: %w", err)
} }
return nil return nil
@@ -178,7 +177,7 @@ func (s *Service) GetByOrganizationID(
return nil, err return nil, err
} }
return trustCenter, nil return compliancePage, nil
} }
func (s *Service) Update( func (s *Service) Update(
@@ -191,40 +190,40 @@ func (s *Service) Update(
} }
var ( var (
trustCenter *coredata.TrustCenter compliancePage *coredata.TrustCenter
file *coredata.File file *coredata.File
) )
err := s.pg.WithTx( err := s.pg.WithTx(
ctx, ctx,
func(ctx context.Context, conn pg.Tx) error { func(ctx context.Context, conn pg.Tx) error {
trustCenter = &coredata.TrustCenter{} compliancePage = &coredata.TrustCenter{}
if err := trustCenter.LoadByID(ctx, conn, scope, req.ID); err != nil { if err := compliancePage.LoadByID(ctx, conn, scope, req.ID); err != nil {
return fmt.Errorf("cannot load trust center: %w", err) return fmt.Errorf("cannot load compliance page: %w", err)
} }
if req.Active != nil { if req.Active != nil {
trustCenter.Active = *req.Active compliancePage.Active = *req.Active
} }
if req.Slug != nil { if req.Slug != nil {
trustCenter.Slug = *req.Slug compliancePage.Slug = *req.Slug
} }
if req.SearchEngineIndexing != nil { if req.SearchEngineIndexing != nil {
trustCenter.SearchEngineIndexing = *req.SearchEngineIndexing compliancePage.SearchEngineIndexing = *req.SearchEngineIndexing
} }
if req.Title != nil { if req.Title != nil {
trustCenter.Title = *req.Title compliancePage.Title = *req.Title
} }
if req.Description != nil { if req.Description != nil {
trustCenter.Description = *req.Description compliancePage.Description = *req.Description
} }
if req.WebsiteURL != nil { if req.WebsiteURL != nil {
trustCenter.WebsiteURL = *req.WebsiteURL compliancePage.WebsiteURL = *req.WebsiteURL
} }
if req.Email != nil { if req.Email != nil {
@@ -234,22 +233,22 @@ func (s *Service) Update(
} }
} }
trustCenter.Email = *req.Email compliancePage.Email = *req.Email
} }
if req.HeadquarterAddress != nil { if req.HeadquarterAddress != nil {
trustCenter.HeadquarterAddress = *req.HeadquarterAddress compliancePage.HeadquarterAddress = *req.HeadquarterAddress
} }
trustCenter.UpdatedAt = time.Now() compliancePage.UpdatedAt = time.Now()
if err := trustCenter.Update(ctx, conn, scope); err != nil { if err := compliancePage.Update(ctx, conn, scope); err != nil {
return fmt.Errorf("cannot update trust center: %w", err) return fmt.Errorf("cannot update compliance page: %w", err)
} }
if trustCenter.NonDisclosureAgreementFileID != nil { if compliancePage.NonDisclosureAgreementFileID != nil {
file = &coredata.File{} file = &coredata.File{}
if err := file.LoadByID(ctx, conn, scope, *trustCenter.NonDisclosureAgreementFileID); err != nil { if err := file.LoadByID(ctx, conn, scope, *compliancePage.NonDisclosureAgreementFileID); err != nil {
return fmt.Errorf("cannot load file: %w", err) return fmt.Errorf("cannot load file: %w", err)
} }
} }
@@ -261,7 +260,7 @@ func (s *Service) Update(
return nil, nil, err return nil, nil, err
} }
return trustCenter, file, nil return compliancePage, file, nil
} }
func (s *Service) UploadNDA( func (s *Service) UploadNDA(
@@ -274,20 +273,20 @@ func (s *Service) UploadNDA(
} }
var ( var (
trustCenter *coredata.TrustCenter compliancePage *coredata.TrustCenter
file *coredata.File file *coredata.File
) )
err := s.pg.WithTx( err := s.pg.WithTx(
ctx, ctx,
func(ctx context.Context, conn pg.Tx) error { func(ctx context.Context, conn pg.Tx) error {
trustCenter = &coredata.TrustCenter{} compliancePage = &coredata.TrustCenter{}
if err := trustCenter.LoadByID(ctx, conn, scope, req.TrustCenterID); err != nil { if err := compliancePage.LoadByID(ctx, conn, scope, req.TrustCenterID); err != nil {
return fmt.Errorf("cannot load trust center: %w", err) return fmt.Errorf("cannot load compliance page: %w", err)
} }
if trustCenter.OrganizationID == gid.Nil { if compliancePage.OrganizationID == gid.Nil {
return fmt.Errorf("trust center %s has no organization", req.TrustCenterID) return fmt.Errorf("compliance page %s has no organization", req.TrustCenterID)
} }
objectKey, err := uuid.NewV7() objectKey, err := uuid.NewV7()
@@ -305,7 +304,7 @@ func (s *Service) UploadNDA(
file = &coredata.File{ file = &coredata.File{
ID: fileID, ID: fileID,
OrganizationID: trustCenter.OrganizationID, OrganizationID: compliancePage.OrganizationID,
BucketName: s.bucket, BucketName: s.bucket,
MimeType: mimeType, MimeType: mimeType,
FileName: req.FileName, FileName: req.FileName,
@@ -320,9 +319,9 @@ func (s *Service) UploadNDA(
file, file,
req.File, req.File,
map[string]string{ map[string]string{
"type": "trust-center-nda", "type": "compliance-page-nda",
"trust-center-id": req.TrustCenterID.String(), "compliance-page-id": req.TrustCenterID.String(),
"organization-id": trustCenter.OrganizationID.String(), "organization-id": compliancePage.OrganizationID.String(),
}, },
) )
if err != nil { if err != nil {
@@ -335,11 +334,11 @@ func (s *Service) UploadNDA(
return fmt.Errorf("cannot insert file: %w", err) return fmt.Errorf("cannot insert file: %w", err)
} }
trustCenter.NonDisclosureAgreementFileID = &fileID compliancePage.NonDisclosureAgreementFileID = &fileID
trustCenter.UpdatedAt = now compliancePage.UpdatedAt = now
if err := trustCenter.Update(ctx, conn, scope); err != nil { if err := compliancePage.Update(ctx, conn, scope); err != nil {
return fmt.Errorf("cannot update trust center: %w", err) return fmt.Errorf("cannot update compliance page: %w", err)
} }
return nil return nil
@@ -349,29 +348,29 @@ func (s *Service) UploadNDA(
return nil, nil, err return nil, nil, err
} }
return trustCenter, file, nil return compliancePage, file, nil
} }
func (s *Service) DeleteNDA( func (s *Service) DeleteNDA(
ctx context.Context, ctx context.Context,
scope coredata.Scoper, scope coredata.Scoper,
trustCenterID gid.GID, compliancePageID gid.GID,
) (*coredata.TrustCenter, *coredata.File, error) { ) (*coredata.TrustCenter, *coredata.File, error) {
var trustCenter *coredata.TrustCenter var compliancePage *coredata.TrustCenter
err := s.pg.WithTx( err := s.pg.WithTx(
ctx, ctx,
func(ctx context.Context, conn pg.Tx) error { func(ctx context.Context, conn pg.Tx) error {
trustCenter = &coredata.TrustCenter{} compliancePage = &coredata.TrustCenter{}
if err := trustCenter.LoadByID(ctx, conn, scope, trustCenterID); err != nil { if err := compliancePage.LoadByID(ctx, conn, scope, compliancePageID); err != nil {
return fmt.Errorf("cannot load trust center: %w", err) return fmt.Errorf("cannot load compliance page: %w", err)
} }
trustCenter.NonDisclosureAgreementFileID = nil compliancePage.NonDisclosureAgreementFileID = nil
trustCenter.UpdatedAt = time.Now() compliancePage.UpdatedAt = time.Now()
if err := trustCenter.Update(ctx, conn, scope); err != nil { if err := compliancePage.Update(ctx, conn, scope); err != nil {
return fmt.Errorf("cannot update trust center: %w", err) return fmt.Errorf("cannot update compliance page: %w", err)
} }
return nil return nil
@@ -381,7 +380,7 @@ func (s *Service) DeleteNDA(
return nil, nil, err return nil, nil, err
} }
return trustCenter, nil, nil return compliancePage, nil, nil
} }
func (s *Service) UpdateBrand( func (s *Service) UpdateBrand(
@@ -394,55 +393,55 @@ func (s *Service) UpdateBrand(
} }
var ( var (
trustCenter *coredata.TrustCenter compliancePage *coredata.TrustCenter
ndaFile *coredata.File ndaFile *coredata.File
) )
err := s.pg.WithTx( err := s.pg.WithTx(
ctx, ctx,
func(ctx context.Context, conn pg.Tx) error { func(ctx context.Context, conn pg.Tx) error {
trustCenter = &coredata.TrustCenter{} compliancePage = &coredata.TrustCenter{}
if err := trustCenter.LoadByID(ctx, conn, scope, req.TrustCenterID); err != nil { if err := compliancePage.LoadByID(ctx, conn, scope, req.TrustCenterID); err != nil {
return fmt.Errorf("cannot load trust center: %w", err) return fmt.Errorf("cannot load compliance page: %w", err)
} }
now := time.Now() now := time.Now()
if req.LogoFile != nil { if req.LogoFile != nil {
if *req.LogoFile == nil { if *req.LogoFile == nil {
trustCenter.LogoFileID = nil compliancePage.LogoFileID = nil
} else { } else {
file, err := s.uploadBrandFile(ctx, scope, conn, *req.LogoFile, "trust-center-logo", trustCenter) file, err := s.uploadBrandFile(ctx, scope, conn, *req.LogoFile, "compliance-page-logo", compliancePage)
if err != nil { if err != nil {
return fmt.Errorf("cannot upload logo file: %w", err) return fmt.Errorf("cannot upload logo file: %w", err)
} }
trustCenter.LogoFileID = &file.ID compliancePage.LogoFileID = &file.ID
} }
} }
if req.DarkLogoFile != nil { if req.DarkLogoFile != nil {
if *req.DarkLogoFile == nil { if *req.DarkLogoFile == nil {
trustCenter.DarkLogoFileID = nil compliancePage.DarkLogoFileID = nil
} else { } else {
file, err := s.uploadBrandFile(ctx, scope, conn, *req.DarkLogoFile, "trust-center-dark-logo", trustCenter) file, err := s.uploadBrandFile(ctx, scope, conn, *req.DarkLogoFile, "compliance-page-dark-logo", compliancePage)
if err != nil { if err != nil {
return fmt.Errorf("cannot upload dark logo file: %w", err) return fmt.Errorf("cannot upload dark logo file: %w", err)
} }
trustCenter.DarkLogoFileID = &file.ID compliancePage.DarkLogoFileID = &file.ID
} }
} }
trustCenter.UpdatedAt = now compliancePage.UpdatedAt = now
if err := trustCenter.Update(ctx, conn, scope); err != nil { if err := compliancePage.Update(ctx, conn, scope); err != nil {
return fmt.Errorf("cannot update trust center: %w", err) return fmt.Errorf("cannot update compliance page: %w", err)
} }
if trustCenter.NonDisclosureAgreementFileID != nil { if compliancePage.NonDisclosureAgreementFileID != nil {
ndaFile = &coredata.File{} ndaFile = &coredata.File{}
if err := ndaFile.LoadByID(ctx, conn, scope, *trustCenter.NonDisclosureAgreementFileID); err != nil { if err := ndaFile.LoadByID(ctx, conn, scope, *compliancePage.NonDisclosureAgreementFileID); err != nil {
return fmt.Errorf("cannot load nda file: %w", err) return fmt.Errorf("cannot load nda file: %w", err)
} }
} }
@@ -454,7 +453,7 @@ func (s *Service) UpdateBrand(
return nil, nil, err return nil, nil, err
} }
return trustCenter, ndaFile, nil return compliancePage, ndaFile, nil
} }
func (s *Service) uploadBrandFile( func (s *Service) uploadBrandFile(
@@ -463,7 +462,7 @@ func (s *Service) uploadBrandFile(
conn pg.Tx, conn pg.Tx,
fileUpload *FileUpload, fileUpload *FileUpload,
fileType string, fileType string,
trustCenter *coredata.TrustCenter, compliancePage *coredata.TrustCenter,
) (*coredata.File, error) { ) (*coredata.File, error) {
objectKey, err := uuid.NewV7() objectKey, err := uuid.NewV7()
if err != nil { if err != nil {
@@ -483,8 +482,8 @@ func (s *Service) uploadBrandFile(
CacheControl: new("max-age=3600, public"), CacheControl: new("max-age=3600, public"),
Metadata: map[string]string{ Metadata: map[string]string{
"type": fileType, "type": fileType,
"trust-center-id": trustCenter.ID.String(), "compliance-page-id": compliancePage.ID.String(),
"organization-id": trustCenter.OrganizationID.String(), "organization-id": compliancePage.OrganizationID.String(),
}, },
}) })
if err != nil { if err != nil {
@@ -504,7 +503,7 @@ func (s *Service) uploadBrandFile(
file := &coredata.File{ file := &coredata.File{
ID: fileID, ID: fileID,
OrganizationID: trustCenter.OrganizationID, OrganizationID: compliancePage.OrganizationID,
BucketName: s.bucket, BucketName: s.bucket,
MimeType: mimeType, MimeType: mimeType,
FileName: fileUpload.Filename, FileName: fileUpload.Filename,
@@ -525,26 +524,26 @@ func (s *Service) uploadBrandFile(
func (s *Service) GenerateNDAFileURL( func (s *Service) GenerateNDAFileURL(
ctx context.Context, ctx context.Context,
scope coredata.Scoper, scope coredata.Scoper,
trustCenterID gid.GID, compliancePageID gid.GID,
expiresIn time.Duration, expiresIn time.Duration,
) (*string, error) { ) (*string, error) {
var file *coredata.File var file *coredata.File
trustCenter := &coredata.TrustCenter{} compliancePage := &coredata.TrustCenter{}
err := s.pg.WithConn( err := s.pg.WithConn(
ctx, ctx,
func(ctx context.Context, conn pg.Querier) error { func(ctx context.Context, conn pg.Querier) error {
if err := trustCenter.LoadByID(ctx, conn, scope, trustCenterID); err != nil { if err := compliancePage.LoadByID(ctx, conn, scope, compliancePageID); err != nil {
return fmt.Errorf("cannot load trust center: %w", err) return fmt.Errorf("cannot load compliance page: %w", err)
} }
if trustCenter.NonDisclosureAgreementFileID == nil { if compliancePage.NonDisclosureAgreementFileID == nil {
return nil return nil
} }
file = &coredata.File{} file = &coredata.File{}
if err := file.LoadByID(ctx, conn, scope, *trustCenter.NonDisclosureAgreementFileID); err != nil { if err := file.LoadByID(ctx, conn, scope, *compliancePage.NonDisclosureAgreementFileID); err != nil {
return fmt.Errorf("cannot load file: %w", err) return fmt.Errorf("cannot load file: %w", err)
} }
@@ -555,7 +554,7 @@ func (s *Service) GenerateNDAFileURL(
return nil, err return nil, err
} }
if trustCenter.NonDisclosureAgreementFileID == nil { if compliancePage.NonDisclosureAgreementFileID == nil {
return nil, nil return nil, nil
} }
@@ -691,13 +690,7 @@ func (s *Service) EmailPresenterConfig(
return fmt.Errorf("cannot load organization: %w", err) return fmt.Errorf("cannot load organization: %w", err)
} }
publicURL, err := complianceportal.PublicURLForTrustCenter( publicURL, err := s.PublicURLForCompliancePage(ctx, conn, scope, compliancePage)
ctx,
conn,
scope,
compliancePage,
s.baseDomain,
)
if err != nil { if err != nil {
return fmt.Errorf("cannot resolve compliance page URL: %w", err) return fmt.Errorf("cannot resolve compliance page URL: %w", err)
} }
@@ -736,24 +729,24 @@ func (s *Service) EmailPresenterConfig(
func (s *Service) GetMailingList( func (s *Service) GetMailingList(
ctx context.Context, ctx context.Context,
scope coredata.Scoper, scope coredata.Scoper,
trustCenterID gid.GID, compliancePageID gid.GID,
) (*coredata.MailingList, error) { ) (*coredata.MailingList, error) {
var mailingList *coredata.MailingList var mailingList *coredata.MailingList
err := s.pg.WithConn( err := s.pg.WithConn(
ctx, ctx,
func(ctx context.Context, conn pg.Querier) error { func(ctx context.Context, conn pg.Querier) error {
trustCenter := &coredata.TrustCenter{} compliancePage := &coredata.TrustCenter{}
if err := trustCenter.LoadByID(ctx, conn, scope, trustCenterID); err != nil { if err := compliancePage.LoadByID(ctx, conn, scope, compliancePageID); err != nil {
return fmt.Errorf("cannot load trust center: %w", err) return fmt.Errorf("cannot load compliance page: %w", err)
} }
if trustCenter.MailingListID == nil { if compliancePage.MailingListID == nil {
return nil return nil
} }
mailingList = &coredata.MailingList{} mailingList = &coredata.MailingList{}
if err := mailingList.LoadByID(ctx, conn, scope, *trustCenter.MailingListID); err != nil { if err := mailingList.LoadByID(ctx, conn, scope, *compliancePage.MailingListID); err != nil {
return fmt.Errorf("cannot load mailing list: %w", err) return fmt.Errorf("cannot load mailing list: %w", err)
} }

View File

@@ -82,7 +82,7 @@ func (utcrr *UpdateReferenceRequest) Validate() error {
func (s *Service) ListReferences( func (s *Service) ListReferences(
ctx context.Context, ctx context.Context,
scope coredata.Scoper, scope coredata.Scoper,
trustCenterID gid.GID, compliancePageID gid.GID,
cursor *page.Cursor[coredata.TrustCenterReferenceOrderField], cursor *page.Cursor[coredata.TrustCenterReferenceOrderField],
) (*page.Page[*coredata.TrustCenterReference, coredata.TrustCenterReferenceOrderField], error) { ) (*page.Page[*coredata.TrustCenterReference, coredata.TrustCenterReferenceOrderField], error) {
var references coredata.TrustCenterReferences var references coredata.TrustCenterReferences
@@ -90,9 +90,9 @@ func (s *Service) ListReferences(
err := s.pg.WithConn( err := s.pg.WithConn(
ctx, ctx,
func(ctx context.Context, conn pg.Querier) error { func(ctx context.Context, conn pg.Querier) error {
err := references.LoadByTrustCenterID(ctx, conn, scope, trustCenterID, cursor) err := references.LoadByTrustCenterID(ctx, conn, scope, compliancePageID, cursor)
if err != nil { if err != nil {
return fmt.Errorf("cannot load trust center references: %w", err) return fmt.Errorf("cannot load compliance page references: %w", err)
} }
return nil return nil
@@ -108,7 +108,7 @@ func (s *Service) ListReferences(
func (s *Service) CountReferences( func (s *Service) CountReferences(
ctx context.Context, ctx context.Context,
scope coredata.Scoper, scope coredata.Scoper,
trustCenterID gid.GID, compliancePageID gid.GID,
) (int, error) { ) (int, error) {
var count int var count int
@@ -117,9 +117,9 @@ func (s *Service) CountReferences(
func(ctx context.Context, conn pg.Querier) (err error) { func(ctx context.Context, conn pg.Querier) (err error) {
references := coredata.TrustCenterReferences{} references := coredata.TrustCenterReferences{}
count, err = references.CountByTrustCenterID(ctx, conn, scope, trustCenterID) count, err = references.CountByTrustCenterID(ctx, conn, scope, compliancePageID)
if err != nil { if err != nil {
return fmt.Errorf("cannot count trust center references: %w", err) return fmt.Errorf("cannot count compliance page references: %w", err)
} }
return nil return nil
@@ -144,7 +144,7 @@ func (s *Service) GetReference(
func(ctx context.Context, conn pg.Querier) error { func(ctx context.Context, conn pg.Querier) error {
err := reference.LoadByID(ctx, conn, scope, referenceID) err := reference.LoadByID(ctx, conn, scope, referenceID)
if err != nil { if err != nil {
return fmt.Errorf("cannot load trust center reference: %w", err) return fmt.Errorf("cannot load compliance page reference: %w", err)
} }
return nil return nil
@@ -177,9 +177,9 @@ func (s *Service) CreateReference(
err := s.pg.WithTx( err := s.pg.WithTx(
ctx, ctx,
func(ctx context.Context, tx pg.Tx) error { func(ctx context.Context, tx pg.Tx) error {
trustCenter := &coredata.TrustCenter{} compliancePage := &coredata.TrustCenter{}
if err := trustCenter.LoadByID(ctx, tx, scope, req.TrustCenterID); err != nil { if err := compliancePage.LoadByID(ctx, tx, scope, req.TrustCenterID); err != nil {
return fmt.Errorf("cannot load trust center: %w", err) return fmt.Errorf("cannot load compliance page: %w", err)
} }
fileID, s3Key, err := s.uploadReferenceLogoFile(ctx, scope, tx, req.LogoFile, referenceID, req.TrustCenterID, now) fileID, s3Key, err := s.uploadReferenceLogoFile(ctx, scope, tx, req.LogoFile, referenceID, req.TrustCenterID, now)
@@ -191,7 +191,7 @@ func (s *Service) CreateReference(
reference = &coredata.TrustCenterReference{ reference = &coredata.TrustCenterReference{
ID: referenceID, ID: referenceID,
OrganizationID: trustCenter.OrganizationID, OrganizationID: compliancePage.OrganizationID,
TrustCenterID: req.TrustCenterID, TrustCenterID: req.TrustCenterID,
Name: req.Name, Name: req.Name,
Description: req.Description, Description: req.Description,
@@ -202,7 +202,7 @@ func (s *Service) CreateReference(
} }
if err := reference.Insert(ctx, tx, scope); err != nil { if err := reference.Insert(ctx, tx, scope); err != nil {
return fmt.Errorf("cannot insert trust center reference: %w", err) return fmt.Errorf("cannot insert compliance page reference: %w", err)
} }
return nil return nil
@@ -239,7 +239,7 @@ func (s *Service) UpdateReference(
reference = &coredata.TrustCenterReference{} reference = &coredata.TrustCenterReference{}
if err := reference.LoadByID(ctx, tx, scope, req.ID); err != nil { if err := reference.LoadByID(ctx, tx, scope, req.ID); err != nil {
return fmt.Errorf("cannot load trust center reference: %w", err) return fmt.Errorf("cannot load compliance page reference: %w", err)
} }
if req.LogoFile != nil { if req.LogoFile != nil {
@@ -278,7 +278,7 @@ func (s *Service) UpdateReference(
} }
if err := reference.Update(ctx, tx, scope); err != nil { if err := reference.Update(ctx, tx, scope); err != nil {
return fmt.Errorf("cannot update trust center reference: %w", err) return fmt.Errorf("cannot update compliance page reference: %w", err)
} }
return nil return nil
@@ -303,11 +303,11 @@ func (s *Service) DeleteReference(
reference := &coredata.TrustCenterReference{} reference := &coredata.TrustCenterReference{}
if err := reference.LoadByID(ctx, tx, scope, trustCenterReferenceID); err != nil { if err := reference.LoadByID(ctx, tx, scope, trustCenterReferenceID); err != nil {
return fmt.Errorf("cannot load trust center reference: %w", err) return fmt.Errorf("cannot load compliance page reference: %w", err)
} }
if err := reference.Delete(ctx, tx, scope); err != nil { if err := reference.Delete(ctx, tx, scope); err != nil {
return fmt.Errorf("cannot delete trust center reference: %w", err) return fmt.Errorf("cannot delete compliance page reference: %w", err)
} }
return nil return nil
@@ -331,7 +331,7 @@ func (s *Service) GenerateReferenceLogoURL(
}, },
) )
if err != nil { if err != nil {
return "", fmt.Errorf("cannot load trust center reference: %w", err) return "", fmt.Errorf("cannot load compliance page reference: %w", err)
} }
file, err := s.fileManager.GetPublicFile(ctx, reference.LogoFileID) file, err := s.fileManager.GetPublicFile(ctx, reference.LogoFileID)
@@ -348,7 +348,7 @@ func (s *Service) uploadReferenceLogoFile(
tx pg.Tx, tx pg.Tx,
file File, file File,
referenceID gid.GID, referenceID gid.GID,
trustCenterID gid.GID, compliancePageID gid.GID,
now time.Time, now time.Time,
) (gid.GID, string, error) { ) (gid.GID, string, error) {
fileID := gid.New(scope.GetTenantID(), coredata.FileEntityType) fileID := gid.New(scope.GetTenantID(), coredata.FileEntityType)
@@ -358,9 +358,9 @@ func (s *Service) uploadReferenceLogoFile(
return gid.GID{}, "", fmt.Errorf("cannot generate object key: %w", err) return gid.GID{}, "", fmt.Errorf("cannot generate object key: %w", err)
} }
trustCenter := &coredata.TrustCenter{} compliancePage := &coredata.TrustCenter{}
if err := trustCenter.LoadByID(ctx, tx, scope, trustCenterID); err != nil { if err := compliancePage.LoadByID(ctx, tx, scope, compliancePageID); err != nil {
return gid.GID{}, "", fmt.Errorf("cannot load trust center: %w", err) return gid.GID{}, "", fmt.Errorf("cannot load compliance page: %w", err)
} }
var ( var (
@@ -418,9 +418,9 @@ func (s *Service) uploadReferenceLogoFile(
ContentType: new(contentType), ContentType: new(contentType),
CacheControl: new("max-age=3600, public"), CacheControl: new("max-age=3600, public"),
Metadata: map[string]string{ Metadata: map[string]string{
"type": "trust-center-reference-logo", "type": "compliance-page-reference-logo",
"trust-center-reference-id": referenceID.String(), "compliance-page-reference-id": referenceID.String(),
"organization-id": trustCenter.OrganizationID.String(), "organization-id": compliancePage.OrganizationID.String(),
}, },
}, },
) )
@@ -430,7 +430,7 @@ func (s *Service) uploadReferenceLogoFile(
fileRecord := &coredata.File{ fileRecord := &coredata.File{
ID: fileID, ID: fileID,
OrganizationID: trustCenter.OrganizationID, OrganizationID: compliancePage.OrganizationID,
BucketName: s.bucket, BucketName: s.bucket,
MimeType: contentType, MimeType: contentType,
FileName: filename, FileName: filename,

View File

@@ -13,7 +13,7 @@
// PERFORMANCE OF THIS SOFTWARE. // PERFORMANCE OF THIS SOFTWARE.
// Package management holds the scoped, admin-facing compliance portal services // Package management holds the scoped, admin-facing compliance portal services
// (trust center CRUD, domains, frameworks, external URLs, references, files and // (compliance page CRUD, domains, frameworks, external URLs, references, files and
// accesses). It is the write side of the compliance portal feature. // accesses). It is the write side of the compliance portal feature.
package management package management
@@ -37,7 +37,7 @@ const (
type ( type (
// Service is the admin-facing compliance portal service. It exposes the // Service is the admin-facing compliance portal service. It exposes the
// scoped CRUD operations for the trust center and its related resources as // scoped CRUD operations for the compliance page and its related resources as
// methods on a single type. // methods on a single type.
Service struct { Service struct {
pg *pg.Client pg *pg.Client

View File

@@ -12,7 +12,7 @@
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR // OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE. // PERFORMANCE OF THIS SOFTWARE.
package complianceportal package visitor
import ( import (
"fmt" "fmt"

View File

@@ -12,7 +12,7 @@
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR // OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE. // PERFORMANCE OF THIS SOFTWARE.
package complianceportal package visitor
import ( import (
"fmt" "fmt"

View File

@@ -12,7 +12,7 @@
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR // OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE. // PERFORMANCE OF THIS SOFTWARE.
package complianceportal package visitor
import ( import (
"testing" "testing"
@@ -66,7 +66,7 @@ func TestBuildClientMetadataDocument(t *testing.T) {
websiteURL := "https://www.acme.com" websiteURL := "https://www.acme.com"
portal := &coredata.TrustCenter{ portal := &coredata.TrustCenter{
Title: "Acme Trust Center", Title: "Acme Compliance Page",
WebsiteURL: &websiteURL, WebsiteURL: &websiteURL,
} }
@@ -76,7 +76,7 @@ func TestBuildClientMetadataDocument(t *testing.T) {
) )
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, "https://acme.example.com/.well-known/oauth-client-metadata", doc.ClientID) assert.Equal(t, "https://acme.example.com/.well-known/oauth-client-metadata", doc.ClientID)
assert.Equal(t, "Acme Trust Center", doc.ClientName) assert.Equal(t, "Acme Compliance Page", doc.ClientName)
assert.Equal(t, []string{"https://acme.example.com/callback"}, doc.RedirectURIs) assert.Equal(t, []string{"https://acme.example.com/callback"}, doc.RedirectURIs)
assert.Equal(t, "https://acme.example.com", doc.ClientURI) assert.Equal(t, "https://acme.example.com", doc.ClientURI)
assert.Equal(t, VisitorOAuthScope, doc.Scope) assert.Equal(t, VisitorOAuthScope, doc.Scope)
@@ -88,7 +88,7 @@ func TestBuildClientMetadataDocument_LogoURIUsesBrandLogoEndpoint(t *testing.T)
logoFileID := gid.MustParseGID("WR-qMrB5AAEAGQAAAZ9mIO8B8vDFQ-i3") logoFileID := gid.MustParseGID("WR-qMrB5AAEAGQAAAZ9mIO8B8vDFQ-i3")
portal := &coredata.TrustCenter{ portal := &coredata.TrustCenter{
Title: "Acme Trust Center", Title: "Acme Compliance Page",
LogoFileID: &logoFileID, LogoFileID: &logoFileID,
} }

View File

@@ -58,7 +58,7 @@ func (s *Service) GetComplianceFramework(
func (s *Service) ListComplianceFrameworksByPortalID( func (s *Service) ListComplianceFrameworksByPortalID(
ctx context.Context, ctx context.Context,
scope coredata.Scoper, scope coredata.Scoper,
trustCenterID gid.GID, compliancePageID gid.GID,
cursor *page.Cursor[coredata.ComplianceFrameworkOrderField], cursor *page.Cursor[coredata.ComplianceFrameworkOrderField],
) (*page.Page[*coredata.ComplianceFramework, coredata.ComplianceFrameworkOrderField], error) { ) (*page.Page[*coredata.ComplianceFramework, coredata.ComplianceFrameworkOrderField], error) {
var complianceFrameworks coredata.ComplianceFrameworks var complianceFrameworks coredata.ComplianceFrameworks
@@ -66,7 +66,7 @@ func (s *Service) ListComplianceFrameworksByPortalID(
err := s.pg.WithConn( err := s.pg.WithConn(
ctx, ctx,
func(ctx context.Context, conn pg.Querier) error { func(ctx context.Context, conn pg.Querier) error {
err := complianceFrameworks.LoadByTrustCenterID(ctx, conn, scope, trustCenterID, cursor) err := complianceFrameworks.LoadByTrustCenterID(ctx, conn, scope, compliancePageID, cursor)
if err != nil { if err != nil {
return fmt.Errorf("cannot load compliance frameworks: %w", err) return fmt.Errorf("cannot load compliance frameworks: %w", err)
} }

View File

@@ -122,40 +122,40 @@ type (
func (s *Service) RenderCompliancePageMarkdown( func (s *Service) RenderCompliancePageMarkdown(
ctx context.Context, ctx context.Context,
w io.Writer, w io.Writer,
trustCenterID gid.GID, compliancePageID gid.GID,
scope coredata.Scoper, scope coredata.Scoper,
) error { ) error {
org, err := s.GetPortalOrganization(ctx, trustCenterID) org, err := s.GetPortalOrganization(ctx, compliancePageID)
if err != nil { if err != nil {
return fmt.Errorf("cannot load organization for compliance page: %w", err) return fmt.Errorf("cannot load organization for compliance page: %w", err)
} }
trustCenter, err := s.GetPortalByID(ctx, trustCenterID) compliancePage, err := s.GetPortalByID(ctx, compliancePageID)
if err != nil { if err != nil {
return fmt.Errorf("cannot load trust center for compliance page: %w", err) return fmt.Errorf("cannot load compliance page: %w", err)
} }
data := &compliancePageData{ data := &compliancePageData{
OrgName: org.Name, OrgName: org.Name,
} }
if trustCenter.Description != nil && *trustCenter.Description != "" { if compliancePage.Description != nil && *compliancePage.Description != "" {
data.Description = *trustCenter.Description data.Description = *compliancePage.Description
} }
if trustCenter.WebsiteURL != nil && *trustCenter.WebsiteURL != "" { if compliancePage.WebsiteURL != nil && *compliancePage.WebsiteURL != "" {
data.Details = append(data.Details, compliancePageDetail{Label: "Website", Value: *trustCenter.WebsiteURL}) data.Details = append(data.Details, compliancePageDetail{Label: "Website", Value: *compliancePage.WebsiteURL})
} }
if trustCenter.Email != nil && *trustCenter.Email != "" { if compliancePage.Email != nil && *compliancePage.Email != "" {
data.Details = append(data.Details, compliancePageDetail{Label: "Email", Value: *trustCenter.Email}) data.Details = append(data.Details, compliancePageDetail{Label: "Email", Value: *compliancePage.Email})
} }
if trustCenter.HeadquarterAddress != nil && *trustCenter.HeadquarterAddress != "" { if compliancePage.HeadquarterAddress != nil && *compliancePage.HeadquarterAddress != "" {
data.Details = append(data.Details, compliancePageDetail{Label: "Headquarters", Value: *trustCenter.HeadquarterAddress}) data.Details = append(data.Details, compliancePageDetail{Label: "Headquarters", Value: *compliancePage.HeadquarterAddress})
} }
data.Frameworks, err = s.fetchComplianceFrameworks(ctx, scope, trustCenterID) data.Frameworks, err = s.fetchComplianceFrameworks(ctx, scope, compliancePageID)
if err != nil { if err != nil {
return fmt.Errorf("cannot fetch compliance frameworks: %w", err) return fmt.Errorf("cannot fetch compliance frameworks: %w", err)
} }
@@ -175,12 +175,12 @@ func (s *Service) RenderCompliancePageMarkdown(
return fmt.Errorf("cannot fetch thirdParties: %w", err) return fmt.Errorf("cannot fetch thirdParties: %w", err)
} }
data.References, err = s.fetchReferences(ctx, scope, trustCenterID) data.References, err = s.fetchReferences(ctx, scope, compliancePageID)
if err != nil { if err != nil {
return fmt.Errorf("cannot fetch references: %w", err) return fmt.Errorf("cannot fetch references: %w", err)
} }
data.CustomLinks, err = s.fetchCustomLinks(ctx, scope, trustCenterID) data.CustomLinks, err = s.fetchCustomLinks(ctx, scope, compliancePageID)
if err != nil { if err != nil {
return fmt.Errorf("cannot fetch external links: %w", err) return fmt.Errorf("cannot fetch external links: %w", err)
} }
@@ -207,11 +207,11 @@ type (
func (s *Service) RenderSitemap( func (s *Service) RenderSitemap(
ctx context.Context, ctx context.Context,
w io.Writer, w io.Writer,
trustCenterID gid.GID, compliancePageID gid.GID,
scope coredata.Scoper, scope coredata.Scoper,
baseURL string, baseURL string,
) error { ) error {
org, err := s.GetPortalOrganization(ctx, trustCenterID) org, err := s.GetPortalOrganization(ctx, compliancePageID)
if err != nil { if err != nil {
return fmt.Errorf("cannot load organization for sitemap: %w", err) return fmt.Errorf("cannot load organization for sitemap: %w", err)
} }
@@ -322,7 +322,7 @@ func (s *Service) fetchDocumentIDs(
coredata.NewTrustCenterFileFilter(), coredata.NewTrustCenterFileFilter(),
) )
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot list trust center files: %w", err) return nil, fmt.Errorf("cannot list compliance page files: %w", err)
} }
for _, file := range result.Data { for _, file := range result.Data {
@@ -401,7 +401,7 @@ func (s *Service) fetchDocumentIDs(
func (s *Service) fetchComplianceFrameworks( func (s *Service) fetchComplianceFrameworks(
ctx context.Context, ctx context.Context,
scope coredata.Scoper, scope coredata.Scoper,
trustCenterID gid.GID, compliancePageID gid.GID,
) ([]compliancePageFramework, error) { ) ([]compliancePageFramework, error) {
var frameworks []compliancePageFramework var frameworks []compliancePageFramework
@@ -417,7 +417,7 @@ func (s *Service) fetchComplianceFrameworks(
}, },
) )
result, err := s.ListComplianceFrameworksByPortalID(ctx, scope, trustCenterID, cursor) result, err := s.ListComplianceFrameworksByPortalID(ctx, scope, compliancePageID, cursor)
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot list compliance frameworks: %w", err) return nil, fmt.Errorf("cannot list compliance frameworks: %w", err)
} }
@@ -621,7 +621,7 @@ func (s *Service) fetchThirdParties(
func (s *Service) fetchReferences( func (s *Service) fetchReferences(
ctx context.Context, ctx context.Context,
scope coredata.Scoper, scope coredata.Scoper,
trustCenterID gid.GID, compliancePageID gid.GID,
) ([]compliancePageReference, error) { ) ([]compliancePageReference, error) {
var refs []compliancePageReference var refs []compliancePageReference
@@ -637,7 +637,7 @@ func (s *Service) fetchReferences(
}, },
) )
result, err := s.ListPortalReferencesForPortalID(ctx, scope, trustCenterID, cursor) result, err := s.ListPortalReferencesForPortalID(ctx, scope, compliancePageID, cursor)
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot list references: %w", err) return nil, fmt.Errorf("cannot list references: %w", err)
} }
@@ -669,7 +669,7 @@ func (s *Service) fetchReferences(
func (s *Service) fetchCustomLinks( func (s *Service) fetchCustomLinks(
ctx context.Context, ctx context.Context,
scope coredata.Scoper, scope coredata.Scoper,
trustCenterID gid.GID, compliancePageID gid.GID,
) ([]compliancePageCustomLink, error) { ) ([]compliancePageCustomLink, error) {
var links []compliancePageCustomLink var links []compliancePageCustomLink
@@ -685,7 +685,7 @@ func (s *Service) fetchCustomLinks(
}, },
) )
result, err := s.ListCustomLinksForPortalID(ctx, scope, trustCenterID, cursor) result, err := s.ListCustomLinksForPortalID(ctx, scope, compliancePageID, cursor)
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot list custom links: %w", err) return nil, fmt.Errorf("cannot list custom links: %w", err)
} }

View File

@@ -33,7 +33,7 @@ import (
func (s *Service) ListCustomLinksForPortalID( func (s *Service) ListCustomLinksForPortalID(
ctx context.Context, ctx context.Context,
scope coredata.Scoper, scope coredata.Scoper,
trustCenterID gid.GID, compliancePageID gid.GID,
cursor *page.Cursor[coredata.ComplianceCustomLinkOrderField], cursor *page.Cursor[coredata.ComplianceCustomLinkOrderField],
) (*page.Page[*coredata.ComplianceCustomLink, coredata.ComplianceCustomLinkOrderField], error) { ) (*page.Page[*coredata.ComplianceCustomLink, coredata.ComplianceCustomLinkOrderField], error) {
var links coredata.ComplianceCustomLinks var links coredata.ComplianceCustomLinks
@@ -41,7 +41,7 @@ func (s *Service) ListCustomLinksForPortalID(
err := s.pg.WithConn( err := s.pg.WithConn(
ctx, ctx,
func(ctx context.Context, conn pg.Querier) error { func(ctx context.Context, conn pg.Querier) error {
err := links.LoadByTrustCenterID(ctx, conn, scope, trustCenterID, cursor) err := links.LoadByTrustCenterID(ctx, conn, scope, compliancePageID, cursor)
if err != nil { if err != nil {
return fmt.Errorf("cannot load custom links: %w", err) return fmt.Errorf("cannot load custom links: %w", err)
} }

View File

@@ -159,7 +159,7 @@ func (s *Service) exportDocumentPDFData(
} }
if document.TrustCenterVisibility == coredata.TrustCenterVisibilityNone { if document.TrustCenterVisibility == coredata.TrustCenterVisibilityNone {
return fmt.Errorf("document not visible on trust center") return fmt.Errorf("document not visible on compliance page")
} }
if err := version.LoadLatestPublishedVersion(ctx, conn, scope, documentID); err != nil { if err := version.LoadLatestPublishedVersion(ctx, conn, scope, documentID); err != nil {

View File

@@ -34,6 +34,6 @@ var (
ErrDocumentNotFound = errors.New("document not found") ErrDocumentNotFound = errors.New("document not found")
ErrDocumentNotVisible = errors.New("document not visible") ErrDocumentNotVisible = errors.New("document not visible")
ErrReportNotFound = errors.New("report not found") ErrReportNotFound = errors.New("report not found")
ErrTrustCenterFileNotFound = errors.New("trust center file not found") ErrPortalFileNotFound = errors.New("portal file not found")
ErrTrustCenterFileNotVisible = errors.New("trust center file not visible") ErrPortalFileNotVisible = errors.New("portal file not visible")
) )

View File

@@ -60,9 +60,9 @@ func (s *Service) RequestPortalAccess(
err := s.pg.WithTx( err := s.pg.WithTx(
ctx, ctx,
func(ctx context.Context, tx pg.Tx) error { func(ctx context.Context, tx pg.Tx) error {
trustCenter := &coredata.TrustCenter{} compliancePage := &coredata.TrustCenter{}
if err := trustCenter.LoadByID(ctx, tx, scope, req.TrustCenterID); err != nil { if err := compliancePage.LoadByID(ctx, tx, scope, req.TrustCenterID); err != nil {
return fmt.Errorf("cannot load trust center: %w", err) return fmt.Errorf("cannot load compliance page: %w", err)
} }
access = &coredata.TrustCenterAccess{} access = &coredata.TrustCenterAccess{}
@@ -70,7 +70,7 @@ func (s *Service) RequestPortalAccess(
return fmt.Errorf("cannot load compliance page membership: %w", err) return fmt.Errorf("cannot load compliance page membership: %w", err)
} }
organizationID := trustCenter.OrganizationID organizationID := compliancePage.OrganizationID
documentIDs := req.DocumentIDs documentIDs := req.DocumentIDs
if req.DocumentIDs == nil { if req.DocumentIDs == nil {
@@ -145,7 +145,7 @@ func (s *Service) RequestPortalAccess(
func(ctx context.Context, cursor *page.Cursor[coredata.TrustCenterFileOrderField]) ([]*coredata.TrustCenterFile, error) { func(ctx context.Context, cursor *page.Cursor[coredata.TrustCenterFileOrderField]) ([]*coredata.TrustCenterFile, error) {
var batch coredata.TrustCenterFiles var batch coredata.TrustCenterFiles
if err := batch.LoadByOrganizationID(ctx, tx, scope, organizationID, cursor, filter); err != nil { if err := batch.LoadByOrganizationID(ctx, tx, scope, organizationID, cursor, filter); err != nil {
return nil, fmt.Errorf("cannot list trust center files: %w", err) return nil, fmt.Errorf("cannot list compliance page files: %w", err)
} }
return batch, nil return batch, nil
@@ -196,7 +196,7 @@ func (s *Service) RequestPortalAccess(
coredata.TrustCenterDocumentAccessStatusRequested, coredata.TrustCenterDocumentAccessStatusRequested,
now, now,
); err != nil { ); err != nil {
return fmt.Errorf("cannot bulk insert trust center document accesses: %w", err) return fmt.Errorf("cannot bulk insert compliance page document accesses: %w", err)
} }
if err := accesses.BulkInsertReportFileAccesses( if err := accesses.BulkInsertReportFileAccesses(
@@ -209,7 +209,7 @@ func (s *Service) RequestPortalAccess(
coredata.TrustCenterDocumentAccessStatusRequested, coredata.TrustCenterDocumentAccessStatusRequested,
now, now,
); err != nil { ); err != nil {
return fmt.Errorf("cannot bulk insert trust center report accesses: %w", err) return fmt.Errorf("cannot bulk insert compliance page report accesses: %w", err)
} }
if err := accesses.BulkInsertTrustCenterFileAccesses( if err := accesses.BulkInsertTrustCenterFileAccesses(
@@ -222,7 +222,7 @@ func (s *Service) RequestPortalAccess(
coredata.TrustCenterDocumentAccessStatusRequested, coredata.TrustCenterDocumentAccessStatusRequested,
now, now,
); err != nil { ); err != nil {
return fmt.Errorf("cannot bulk insert trust center file accesses: %w", err) return fmt.Errorf("cannot bulk insert compliance page file accesses: %w", err)
} }
return nil return nil
@@ -242,7 +242,7 @@ func (s *Service) RequestPortalAccess(
func (s *Service) GetPortalAccess( func (s *Service) GetPortalAccess(
ctx context.Context, ctx context.Context,
scope coredata.Scoper, scope coredata.Scoper,
trustCenterID gid.GID, compliancePageID gid.GID,
identityID gid.GID, identityID gid.GID,
) (coredata.TrustCenterAccess, error) { ) (coredata.TrustCenterAccess, error) {
var access coredata.TrustCenterAccess var access coredata.TrustCenterAccess
@@ -250,7 +250,7 @@ func (s *Service) GetPortalAccess(
err := s.pg.WithConn( err := s.pg.WithConn(
ctx, ctx,
func(ctx context.Context, conn pg.Querier) error { func(ctx context.Context, conn pg.Querier) error {
return access.LoadByTrustCenterIDAndIdentityID(ctx, conn, scope, trustCenterID, identityID) return access.LoadByTrustCenterIDAndIdentityID(ctx, conn, scope, compliancePageID, identityID)
}, },
) )
@@ -260,7 +260,7 @@ func (s *Service) GetPortalAccess(
func (s *Service) GetPortalDocumentAccess( func (s *Service) GetPortalDocumentAccess(
ctx context.Context, ctx context.Context,
scope coredata.Scoper, scope coredata.Scoper,
trustCenterID gid.GID, compliancePageID gid.GID,
identityID gid.GID, identityID gid.GID,
documentID gid.GID, documentID gid.GID,
) (*coredata.TrustCenterDocumentAccess, error) { ) (*coredata.TrustCenterDocumentAccess, error) {
@@ -271,13 +271,13 @@ func (s *Service) GetPortalDocumentAccess(
func(ctx context.Context, conn pg.Querier) error { func(ctx context.Context, conn pg.Querier) error {
access := &coredata.TrustCenterAccess{} access := &coredata.TrustCenterAccess{}
err := access.LoadByTrustCenterIDAndIdentityID(ctx, conn, scope, trustCenterID, identityID) err := access.LoadByTrustCenterIDAndIdentityID(ctx, conn, scope, compliancePageID, identityID)
if err != nil { if err != nil {
if errors.Is(err, coredata.ErrResourceNotFound) { if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrMembershipNotFound return ErrMembershipNotFound
} }
return fmt.Errorf("cannot load trust center access: %w", err) return fmt.Errorf("cannot load compliance page access: %w", err)
} }
profile := &coredata.MembershipProfile{} profile := &coredata.MembershipProfile{}
@@ -315,7 +315,7 @@ func (s *Service) GetPortalDocumentAccess(
func (s *Service) GetPortalReportFileAccess( func (s *Service) GetPortalReportFileAccess(
ctx context.Context, ctx context.Context,
scope coredata.Scoper, scope coredata.Scoper,
trustCenterID gid.GID, compliancePageID gid.GID,
identityID gid.GID, identityID gid.GID,
reportFileID gid.GID, reportFileID gid.GID,
) (*coredata.TrustCenterDocumentAccess, error) { ) (*coredata.TrustCenterDocumentAccess, error) {
@@ -326,13 +326,13 @@ func (s *Service) GetPortalReportFileAccess(
func(ctx context.Context, conn pg.Querier) error { func(ctx context.Context, conn pg.Querier) error {
access := &coredata.TrustCenterAccess{} access := &coredata.TrustCenterAccess{}
err := access.LoadByTrustCenterIDAndIdentityID(ctx, conn, scope, trustCenterID, identityID) err := access.LoadByTrustCenterIDAndIdentityID(ctx, conn, scope, compliancePageID, identityID)
if err != nil { if err != nil {
if errors.Is(err, coredata.ErrResourceNotFound) { if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrMembershipNotFound return ErrMembershipNotFound
} }
return fmt.Errorf("cannot load trust center access: %w", err) return fmt.Errorf("cannot load compliance page access: %w", err)
} }
profile := &coredata.MembershipProfile{} profile := &coredata.MembershipProfile{}
@@ -370,7 +370,7 @@ func (s *Service) GetPortalReportFileAccess(
func (s *Service) GetPortalFileAccess( func (s *Service) GetPortalFileAccess(
ctx context.Context, ctx context.Context,
scope coredata.Scoper, scope coredata.Scoper,
trustCenterID gid.GID, compliancePageID gid.GID,
identityID gid.GID, identityID gid.GID,
trustCenterFileID gid.GID, trustCenterFileID gid.GID,
) (*coredata.TrustCenterDocumentAccess, error) { ) (*coredata.TrustCenterDocumentAccess, error) {
@@ -381,13 +381,13 @@ func (s *Service) GetPortalFileAccess(
func(ctx context.Context, conn pg.Querier) error { func(ctx context.Context, conn pg.Querier) error {
access := &coredata.TrustCenterAccess{} access := &coredata.TrustCenterAccess{}
err := access.LoadByTrustCenterIDAndIdentityID(ctx, conn, scope, trustCenterID, identityID) err := access.LoadByTrustCenterIDAndIdentityID(ctx, conn, scope, compliancePageID, identityID)
if err != nil { if err != nil {
if errors.Is(err, coredata.ErrResourceNotFound) { if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrMembershipNotFound return ErrMembershipNotFound
} }
return fmt.Errorf("cannot load trust center access: %w", err) return fmt.Errorf("cannot load compliance page access: %w", err)
} }
profile := &coredata.MembershipProfile{} profile := &coredata.MembershipProfile{}
@@ -409,7 +409,7 @@ func (s *Service) GetPortalFileAccess(
return ErrDocumentAccessNotFound return ErrDocumentAccessNotFound
} }
return fmt.Errorf("cannot load trust center file access: %w", err) return fmt.Errorf("cannot load compliance page file access: %w", err)
} }
return nil return nil
@@ -434,9 +434,9 @@ func (s *Service) GrantPortalAccessByIDs(
return s.pg.WithTx( return s.pg.WithTx(
ctx, ctx,
func(ctx context.Context, tx pg.Tx) error { func(ctx context.Context, tx pg.Tx) error {
trustCenter := &coredata.TrustCenter{} compliancePage := &coredata.TrustCenter{}
if err := trustCenter.LoadByOrganizationID(ctx, tx, scope, organizationID); err != nil { if err := compliancePage.LoadByOrganizationID(ctx, tx, scope, organizationID); err != nil {
return fmt.Errorf("cannot load trust center: %w", err) return fmt.Errorf("cannot load compliance page: %w", err)
} }
identity := &coredata.Identity{} identity := &coredata.Identity{}
@@ -445,8 +445,8 @@ func (s *Service) GrantPortalAccessByIDs(
} }
access := &coredata.TrustCenterAccess{} access := &coredata.TrustCenterAccess{}
if err := access.LoadByTrustCenterIDAndIdentityID(ctx, tx, scope, trustCenter.ID, identity.ID); err != nil { if err := access.LoadByTrustCenterIDAndIdentityID(ctx, tx, scope, compliancePage.ID, identity.ID); err != nil {
return fmt.Errorf("cannot load trust center access: %w", err) return fmt.Errorf("cannot load compliance page access: %w", err)
} }
profile := &coredata.MembershipProfile{} profile := &coredata.MembershipProfile{}
@@ -477,7 +477,7 @@ func (s *Service) GrantPortalAccessByIDs(
if len(fileIDs) > 0 { if len(fileIDs) > 0 {
if err := coredata.GrantByTrustCenterFileIDs(ctx, tx, scope, access.ID, fileIDs, now); err != nil { if err := coredata.GrantByTrustCenterFileIDs(ctx, tx, scope, access.ID, fileIDs, now); err != nil {
return fmt.Errorf("cannot grant trust center file accesses: %w", err) return fmt.Errorf("cannot grant compliance page file accesses: %w", err)
} }
} }
@@ -515,7 +515,7 @@ func (s *Service) sendPortalAccessEmail(
access.UpdatedAt = now access.UpdatedAt = now
if err := access.Update(ctx, tx, scope); err != nil { if err := access.Update(ctx, tx, scope); err != nil {
return fmt.Errorf("cannot update trust center access with expiration: %w", err) return fmt.Errorf("cannot update compliance page access with expiration: %w", err)
} }
emailPresenterCfg, err := s.GetPortalEmailPresenterConfig(ctx, scope, access.TrustCenterID) emailPresenterCfg, err := s.GetPortalEmailPresenterConfig(ctx, scope, access.TrustCenterID)
@@ -527,7 +527,7 @@ func (s *Service) sendPortalAccessEmail(
subject, textBody, htmlBody, err := emailPresenter.RenderTrustCenterAccess(ctx, organization.Name) subject, textBody, htmlBody, err := emailPresenter.RenderTrustCenterAccess(ctx, organization.Name)
if err != nil { if err != nil {
return fmt.Errorf("cannot render trust center access email: %w", err) return fmt.Errorf("cannot render compliance page access email: %w", err)
} }
accessEmail := coredata.NewEmail( accessEmail := coredata.NewEmail(
@@ -560,9 +560,9 @@ func (s *Service) RejectOrRevokePortalAccessByIDs(
return s.pg.WithTx( return s.pg.WithTx(
ctx, ctx,
func(ctx context.Context, tx pg.Tx) error { func(ctx context.Context, tx pg.Tx) error {
trustCenter := &coredata.TrustCenter{} compliancePage := &coredata.TrustCenter{}
if err := trustCenter.LoadByOrganizationID(ctx, tx, scope, organizationID); err != nil { if err := compliancePage.LoadByOrganizationID(ctx, tx, scope, organizationID); err != nil {
return fmt.Errorf("cannot load trust center: %w", err) return fmt.Errorf("cannot load compliance page: %w", err)
} }
identity := &coredata.Identity{} identity := &coredata.Identity{}
@@ -571,8 +571,8 @@ func (s *Service) RejectOrRevokePortalAccessByIDs(
} }
access := &coredata.TrustCenterAccess{} access := &coredata.TrustCenterAccess{}
if err := access.LoadByTrustCenterIDAndIdentityID(ctx, tx, scope, trustCenter.ID, identity.ID); err != nil { if err := access.LoadByTrustCenterIDAndIdentityID(ctx, tx, scope, compliancePage.ID, identity.ID); err != nil {
return fmt.Errorf("cannot load trust center access: %w", err) return fmt.Errorf("cannot load compliance page access: %w", err)
} }
profile := &coredata.MembershipProfile{} profile := &coredata.MembershipProfile{}
@@ -603,7 +603,7 @@ func (s *Service) RejectOrRevokePortalAccessByIDs(
shouldSendEmail = true shouldSendEmail = true
if err := coredata.RejectOrRevokeByTrustCenterFileIDs(ctx, tx, scope, access.ID, fileIDs, now); err != nil { if err := coredata.RejectOrRevokeByTrustCenterFileIDs(ctx, tx, scope, access.ID, fileIDs, now); err != nil {
return fmt.Errorf("cannot reject/revoke trust center file accesses: %w", err) return fmt.Errorf("cannot reject/revoke compliance page file accesses: %w", err)
} }
} }
@@ -681,7 +681,7 @@ func (s *Service) sendPortalDocumentAccessRejectedEmail(
organization.Name, organization.Name,
) )
if err != nil { if err != nil {
return fmt.Errorf("cannot render trust center documents access rejected email: %w", err) return fmt.Errorf("cannot render compliance page documents access rejected email: %w", err)
} }
accessEmail := coredata.NewEmail( accessEmail := coredata.NewEmail(

View File

@@ -47,7 +47,7 @@ func (s *Service) GetPortalFile(
func(ctx context.Context, conn pg.Querier) error { func(ctx context.Context, conn pg.Querier) error {
err := trustCenterFile.LoadByID(ctx, conn, scope, trustCenterFileID) err := trustCenterFile.LoadByID(ctx, conn, scope, trustCenterFileID)
if err != nil { if err != nil {
return fmt.Errorf("cannot load trust center file: %w", err) return fmt.Errorf("cannot load compliance page file: %w", err)
} }
return nil return nil
@@ -58,11 +58,11 @@ func (s *Service) GetPortalFile(
} }
if trustCenterFile.OrganizationID != organizationID { if trustCenterFile.OrganizationID != organizationID {
return nil, ErrTrustCenterFileNotFound return nil, ErrPortalFileNotFound
} }
if trustCenterFile.TrustCenterVisibility == coredata.TrustCenterVisibilityNone { if trustCenterFile.TrustCenterVisibility == coredata.TrustCenterVisibilityNone {
return nil, ErrTrustCenterFileNotVisible return nil, ErrPortalFileNotVisible
} }
return trustCenterFile, nil return trustCenterFile, nil
@@ -82,7 +82,7 @@ func (s *Service) ListPortalFilesForOrganizationID(
func(ctx context.Context, conn pg.Querier) error { func(ctx context.Context, conn pg.Querier) error {
err := trustCenterFiles.LoadByOrganizationID(ctx, conn, scope, organizationID, cursor, filter) err := trustCenterFiles.LoadByOrganizationID(ctx, conn, scope, organizationID, cursor, filter)
if err != nil { if err != nil {
return fmt.Errorf("cannot load trust center files: %w", err) return fmt.Errorf("cannot load compliance page files: %w", err)
} }
return nil return nil
@@ -103,7 +103,7 @@ func (s *Service) ExportPortalFile(
) ([]byte, string, error) { ) ([]byte, string, error) {
fileData, mimeType, err := s.exportPortalFileData(ctx, scope, trustCenterFileID) fileData, mimeType, err := s.exportPortalFileData(ctx, scope, trustCenterFileID)
if err != nil { if err != nil {
return nil, "", fmt.Errorf("cannot export trust center file: %w", err) return nil, "", fmt.Errorf("cannot export compliance page file: %w", err)
} }
if mimeType == "application/pdf" { if mimeType == "application/pdf" {
@@ -141,7 +141,7 @@ func (s *Service) exportPortalFileData(
func(ctx context.Context, conn pg.Querier) error { func(ctx context.Context, conn pg.Querier) error {
trustCenterFile = &coredata.TrustCenterFile{} trustCenterFile = &coredata.TrustCenterFile{}
if err := trustCenterFile.LoadByID(ctx, conn, scope, trustCenterFileID); err != nil { if err := trustCenterFile.LoadByID(ctx, conn, scope, trustCenterFileID); err != nil {
return fmt.Errorf("cannot load trust center file: %w", err) return fmt.Errorf("cannot load compliance page file: %w", err)
} }
file = &coredata.File{} file = &coredata.File{}

View File

@@ -33,7 +33,7 @@ import (
func (s *Service) ListPortalReferencesForPortalID( func (s *Service) ListPortalReferencesForPortalID(
ctx context.Context, ctx context.Context,
scope coredata.Scoper, scope coredata.Scoper,
trustCenterID gid.GID, compliancePageID gid.GID,
cursor *page.Cursor[coredata.TrustCenterReferenceOrderField], cursor *page.Cursor[coredata.TrustCenterReferenceOrderField],
) (*page.Page[*coredata.TrustCenterReference, coredata.TrustCenterReferenceOrderField], error) { ) (*page.Page[*coredata.TrustCenterReference, coredata.TrustCenterReferenceOrderField], error) {
var references coredata.TrustCenterReferences var references coredata.TrustCenterReferences
@@ -43,9 +43,9 @@ func (s *Service) ListPortalReferencesForPortalID(
ctx, ctx,
func(ctx context.Context, conn pg.Querier) error { func(ctx context.Context, conn pg.Querier) error {
err := references.LoadByTrustCenterID(ctx, conn, scope, trustCenterID, cursor) err := references.LoadByTrustCenterID(ctx, conn, scope, compliancePageID, cursor)
if err != nil { if err != nil {
return fmt.Errorf("cannot load trust center references: %w", err) return fmt.Errorf("cannot load compliance page references: %w", err)
} }
return nil return nil
@@ -72,7 +72,7 @@ func (s *Service) GeneratePortalReferenceLogoURL(
}, },
) )
if err != nil { if err != nil {
return "", fmt.Errorf("cannot load trust center reference: %w", err) return "", fmt.Errorf("cannot load compliance page reference: %w", err)
} }
file, err := s.fileManager.GetPublicFile(ctx, reference.LogoFileID) file, err := s.fileManager.GetPublicFile(ctx, reference.LogoFileID)
@@ -95,7 +95,7 @@ func (s *Service) GetPortalReference(
func(ctx context.Context, conn pg.Querier) error { func(ctx context.Context, conn pg.Querier) error {
err := reference.LoadByID(ctx, conn, scope, referenceID) err := reference.LoadByID(ctx, conn, scope, referenceID)
if err != nil { if err != nil {
return fmt.Errorf("cannot load trust center reference: %w", err) return fmt.Errorf("cannot load compliance page reference: %w", err)
} }
return nil return nil

View File

@@ -28,7 +28,6 @@ import (
"go.gearno.de/kit/pg" "go.gearno.de/kit/pg"
"go.probo.inc/probo/packages/emails" "go.probo.inc/probo/packages/emails"
"go.probo.inc/probo/pkg/complianceportal"
"go.probo.inc/probo/pkg/coredata" "go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/gid" "go.probo.inc/probo/pkg/gid"
) )
@@ -36,26 +35,26 @@ import (
func (s *Service) GetPortal( func (s *Service) GetPortal(
ctx context.Context, ctx context.Context,
scope coredata.Scoper, scope coredata.Scoper,
trustCenterID gid.GID, compliancePageID gid.GID,
) (*coredata.TrustCenter, error) { ) (*coredata.TrustCenter, error) {
var trustCenter *coredata.TrustCenter var compliancePage *coredata.TrustCenter
err := s.pg.WithConn( err := s.pg.WithConn(
ctx, ctx,
func(ctx context.Context, conn pg.Querier) error { func(ctx context.Context, conn pg.Querier) error {
trustCenter = &coredata.TrustCenter{} compliancePage = &coredata.TrustCenter{}
if err := trustCenter.LoadByID(ctx, conn, scope, trustCenterID); err != nil { if err := compliancePage.LoadByID(ctx, conn, scope, compliancePageID); err != nil {
return fmt.Errorf("cannot load trust center: %w", err) return fmt.Errorf("cannot load compliance page: %w", err)
} }
return nil return nil
}, },
) )
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot load trust center: %w", err) return nil, fmt.Errorf("cannot load compliance page: %w", err)
} }
return trustCenter, nil return compliancePage, nil
} }
func (s *Service) GetPortalByOrganizationID( func (s *Service) GetPortalByOrganizationID(
@@ -63,14 +62,14 @@ func (s *Service) GetPortalByOrganizationID(
scope coredata.Scoper, scope coredata.Scoper,
organizationID gid.GID, organizationID gid.GID,
) (*coredata.TrustCenter, error) { ) (*coredata.TrustCenter, error) {
trustCenter := &coredata.TrustCenter{} compliancePage := &coredata.TrustCenter{}
err := s.pg.WithConn( err := s.pg.WithConn(
ctx, ctx,
func(ctx context.Context, conn pg.Querier) error { func(ctx context.Context, conn pg.Querier) error {
err := trustCenter.LoadByOrganizationID(ctx, conn, scope, organizationID) err := compliancePage.LoadByOrganizationID(ctx, conn, scope, organizationID)
if err != nil { if err != nil {
return fmt.Errorf("cannot load trust center: %w", err) return fmt.Errorf("cannot load compliance page: %w", err)
} }
return nil return nil
@@ -80,30 +79,30 @@ func (s *Service) GetPortalByOrganizationID(
return nil, err return nil, err
} }
return trustCenter, nil return compliancePage, nil
} }
func (s *Service) GetPortalNDAFile( func (s *Service) GetPortalNDAFile(
ctx context.Context, ctx context.Context,
scope coredata.Scoper, scope coredata.Scoper,
trustCenterID gid.GID, compliancePageID gid.GID,
) (*coredata.File, error) { ) (*coredata.File, error) {
var file *coredata.File var file *coredata.File
err := s.pg.WithConn( err := s.pg.WithConn(
ctx, ctx,
func(ctx context.Context, conn pg.Querier) error { func(ctx context.Context, conn pg.Querier) error {
trustCenter := &coredata.TrustCenter{} compliancePage := &coredata.TrustCenter{}
if err := trustCenter.LoadByID(ctx, conn, scope, trustCenterID); err != nil { if err := compliancePage.LoadByID(ctx, conn, scope, compliancePageID); err != nil {
return fmt.Errorf("cannot load trust center: %w", err) return fmt.Errorf("cannot load compliance page: %w", err)
} }
if trustCenter.NonDisclosureAgreementFileID == nil { if compliancePage.NonDisclosureAgreementFileID == nil {
return nil return nil
} }
file = &coredata.File{} file = &coredata.File{}
if err := file.LoadByID(ctx, conn, scope, *trustCenter.NonDisclosureAgreementFileID); err != nil { if err := file.LoadByID(ctx, conn, scope, *compliancePage.NonDisclosureAgreementFileID); err != nil {
return fmt.Errorf("cannot load file: %w", err) return fmt.Errorf("cannot load file: %w", err)
} }
@@ -120,7 +119,7 @@ func (s *Service) GetPortalNDAFile(
func (s *Service) GeneratePortalNDAFileURL( func (s *Service) GeneratePortalNDAFileURL(
ctx context.Context, ctx context.Context,
scope coredata.Scoper, scope coredata.Scoper,
trustCenterID gid.GID, compliancePageID gid.GID,
expiresIn time.Duration, expiresIn time.Duration,
) (string, error) { ) (string, error) {
var file *coredata.File var file *coredata.File
@@ -128,17 +127,17 @@ func (s *Service) GeneratePortalNDAFileURL(
err := s.pg.WithConn( err := s.pg.WithConn(
ctx, ctx,
func(ctx context.Context, conn pg.Querier) error { func(ctx context.Context, conn pg.Querier) error {
trustCenter := &coredata.TrustCenter{} compliancePage := &coredata.TrustCenter{}
if err := trustCenter.LoadByID(ctx, conn, scope, trustCenterID); err != nil { if err := compliancePage.LoadByID(ctx, conn, scope, compliancePageID); err != nil {
return fmt.Errorf("cannot load trust center: %w", err) return fmt.Errorf("cannot load compliance page: %w", err)
} }
if trustCenter.NonDisclosureAgreementFileID == nil { if compliancePage.NonDisclosureAgreementFileID == nil {
return fmt.Errorf("no NDA file found") return fmt.Errorf("no NDA file found")
} }
file = &coredata.File{} file = &coredata.File{}
if err := file.LoadByID(ctx, conn, scope, *trustCenter.NonDisclosureAgreementFileID); err != nil { if err := file.LoadByID(ctx, conn, scope, *compliancePage.NonDisclosureAgreementFileID); err != nil {
return fmt.Errorf("cannot load file: %w", err) return fmt.Errorf("cannot load file: %w", err)
} }
@@ -281,12 +280,11 @@ func (s *Service) GetPortalEmailPresenterConfig(
return fmt.Errorf("cannot load organization: %w", err) return fmt.Errorf("cannot load organization: %w", err)
} }
publicURL, err := complianceportal.PublicURLForTrustCenter( publicURL, err := s.management.PublicURLForCompliancePage(
ctx, ctx,
conn, conn,
scope, scope,
compliancePage, compliancePage,
s.baseDomain,
) )
if err != nil { if err != nil {
return fmt.Errorf("cannot resolve compliance page URL: %w", err) return fmt.Errorf("cannot resolve compliance page URL: %w", err)
@@ -327,24 +325,24 @@ func (s *Service) GetPortalEmailPresenterConfig(
func (s *Service) GetPortalMailingList( func (s *Service) GetPortalMailingList(
ctx context.Context, ctx context.Context,
scope coredata.Scoper, scope coredata.Scoper,
trustCenterID gid.GID, compliancePageID gid.GID,
) (*coredata.MailingList, error) { ) (*coredata.MailingList, error) {
var mailingList *coredata.MailingList var mailingList *coredata.MailingList
err := s.pg.WithConn( err := s.pg.WithConn(
ctx, ctx,
func(ctx context.Context, conn pg.Querier) error { func(ctx context.Context, conn pg.Querier) error {
trustCenter := &coredata.TrustCenter{} compliancePage := &coredata.TrustCenter{}
if err := trustCenter.LoadByID(ctx, conn, scope, trustCenterID); err != nil { if err := compliancePage.LoadByID(ctx, conn, scope, compliancePageID); err != nil {
return fmt.Errorf("cannot load trust center: %w", err) return fmt.Errorf("cannot load compliance page: %w", err)
} }
if trustCenter.MailingListID == nil { if compliancePage.MailingListID == nil {
return nil return nil
} }
mailingList = &coredata.MailingList{} mailingList = &coredata.MailingList{}
if err := mailingList.LoadByID(ctx, conn, scope, *trustCenter.MailingListID); err != nil { if err := mailingList.LoadByID(ctx, conn, scope, *compliancePage.MailingListID); err != nil {
return fmt.Errorf("cannot load mailing list: %w", err) return fmt.Errorf("cannot load mailing list: %w", err)
} }

View File

@@ -30,7 +30,7 @@ import (
"go.gearno.de/kit/log" "go.gearno.de/kit/log"
"go.gearno.de/kit/pg" "go.gearno.de/kit/pg"
"go.probo.inc/probo/packages/emails" "go.probo.inc/probo/packages/emails"
"go.probo.inc/probo/pkg/complianceportal" "go.probo.inc/probo/pkg/complianceportal/management"
"go.probo.inc/probo/pkg/coredata" "go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/esign" "go.probo.inc/probo/pkg/esign"
"go.probo.inc/probo/pkg/filemanager" "go.probo.inc/probo/pkg/filemanager"
@@ -45,7 +45,7 @@ const NDAConsentText = "By clicking \"Review and sign\", I consent to sign this
type ( type (
// Service is the visitor-facing compliance portal service. It exposes the // Service is the visitor-facing compliance portal service. It exposes the
// public read operations for the trust center and its related resources as // public read operations for the compliance page and its related resources as
// methods on a single type. // methods on a single type.
Service struct { Service struct {
pg *pg.Client pg *pg.Client
@@ -61,6 +61,7 @@ type (
logger *log.Logger logger *log.Logger
slack *slack.Service slack *slack.Service
resourceAlias *resourcealias.Service resourceAlias *resourcealias.Service
management *management.Service
} }
) )
@@ -78,6 +79,7 @@ func NewService(
logger *log.Logger, logger *log.Logger,
slack *slack.Service, slack *slack.Service,
resourceAliasSvc *resourcealias.Service, resourceAliasSvc *resourcealias.Service,
managementSvc *management.Service,
) *Service { ) *Service {
svc := &Service{ svc := &Service{
pg: pgClient, pg: pgClient,
@@ -93,6 +95,7 @@ func NewService(
logger: logger, logger: logger,
slack: slack, slack: slack,
resourceAlias: resourceAliasSvc, resourceAlias: resourceAliasSvc,
management: managementSvc,
} }
return svc return svc
@@ -102,18 +105,18 @@ func (s *Service) GetPortalByID(
ctx context.Context, ctx context.Context,
id gid.GID, id gid.GID,
) (*coredata.TrustCenter, error) { ) (*coredata.TrustCenter, error) {
trustCenter := &coredata.TrustCenter{} compliancePage := &coredata.TrustCenter{}
err := s.pg.WithConn( err := s.pg.WithConn(
ctx, ctx,
func(ctx context.Context, conn pg.Querier) error { func(ctx context.Context, conn pg.Querier) error {
err := trustCenter.LoadByID(ctx, conn, coredata.NewNoScope(), id) err := compliancePage.LoadByID(ctx, conn, coredata.NewNoScope(), id)
if err != nil { if err != nil {
if errors.Is(err, coredata.ErrResourceNotFound) { if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrPageNotFound return ErrPageNotFound
} }
return fmt.Errorf("cannot load trust center: %w", err) return fmt.Errorf("cannot load compliance page: %w", err)
} }
return nil return nil
@@ -123,25 +126,25 @@ func (s *Service) GetPortalByID(
return nil, err return nil, err
} }
return trustCenter, nil return compliancePage, nil
} }
func (s *Service) GetPortalBySlug( func (s *Service) GetPortalBySlug(
ctx context.Context, ctx context.Context,
slug string, slug string,
) (*coredata.TrustCenter, error) { ) (*coredata.TrustCenter, error) {
trustCenter := &coredata.TrustCenter{} compliancePage := &coredata.TrustCenter{}
err := s.pg.WithConn( err := s.pg.WithConn(
ctx, ctx,
func(ctx context.Context, conn pg.Querier) error { func(ctx context.Context, conn pg.Querier) error {
err := trustCenter.LoadBySlug(ctx, conn, slug) err := compliancePage.LoadBySlug(ctx, conn, slug)
if err != nil { if err != nil {
if errors.Is(err, coredata.ErrResourceNotFound) { if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrPageNotFound return ErrPageNotFound
} }
return fmt.Errorf("cannot load trust center: %w", err) return fmt.Errorf("cannot load compliance page: %w", err)
} }
return nil return nil
@@ -151,25 +154,25 @@ func (s *Service) GetPortalBySlug(
return nil, err return nil, err
} }
return trustCenter, nil return compliancePage, nil
} }
// GetEffectiveCanonicalHost returns the host a compliance page should be // GetEffectiveCanonicalHost returns the host a compliance page should be
// served under. It prefers the primary domain when its certificate is active, // served under. It prefers the primary domain when its certificate is active,
// and otherwise falls back to the managed probopage subdomain. An empty string // and otherwise falls back to the managed probopage subdomain. An empty string
// is returned when no serving host can be determined. // is returned when no serving host can be determined.
func (s *Service) GetPortalEffectiveCanonicalHost(ctx context.Context, trustCenterID gid.GID) (string, error) { func (s *Service) GetPortalEffectiveCanonicalHost(ctx context.Context, compliancePageID gid.GID) (string, error) {
var host string var host string
err := s.pg.WithConn( err := s.pg.WithConn(
ctx, ctx,
func(ctx context.Context, conn pg.Querier) error { func(ctx context.Context, conn pg.Querier) error {
trustCenter := &coredata.TrustCenter{} compliancePage := &coredata.TrustCenter{}
if err := trustCenter.LoadByID(ctx, conn, coredata.NewNoScope(), trustCenterID); err != nil { if err := compliancePage.LoadByID(ctx, conn, coredata.NewNoScope(), compliancePageID); err != nil {
return fmt.Errorf("cannot load trust center: %w", err) return fmt.Errorf("cannot load compliance page: %w", err)
} }
domain, err := complianceportal.EffectiveDomainForTrustCenter(ctx, conn, coredata.NewNoScope(), trustCenter) domain, err := s.management.EffectiveDomainForCompliancePage(ctx, conn, coredata.NewNoScope(), compliancePage)
if err != nil { if err != nil {
return err return err
} }
@@ -189,7 +192,7 @@ func (s *Service) GetPortalEffectiveCanonicalHost(ctx context.Context, trustCent
} }
func (s *Service) GetPortalByDomainName(ctx context.Context, domain string) (*coredata.TrustCenter, error) { func (s *Service) GetPortalByDomainName(ctx context.Context, domain string) (*coredata.TrustCenter, error) {
trustCenter := &coredata.TrustCenter{} compliancePage := &coredata.TrustCenter{}
err := s.pg.WithConn( err := s.pg.WithConn(
ctx, ctx,
@@ -203,13 +206,13 @@ func (s *Service) GetPortalByDomainName(ctx context.Context, domain string) (*co
return fmt.Errorf("cannot load custom domain: %w", err) return fmt.Errorf("cannot load custom domain: %w", err)
} }
trustCenter = &coredata.TrustCenter{} compliancePage = &coredata.TrustCenter{}
if err := trustCenter.LoadByDomainID(ctx, conn, customDomain.ID); err != nil { if err := compliancePage.LoadByDomainID(ctx, conn, customDomain.ID); err != nil {
if errors.Is(err, coredata.ErrResourceNotFound) { if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrPageNotFound return ErrPageNotFound
} }
return fmt.Errorf("cannot load trust center: %w", err) return fmt.Errorf("cannot load compliance page: %w", err)
} }
return nil return nil
@@ -219,37 +222,37 @@ func (s *Service) GetPortalByDomainName(ctx context.Context, domain string) (*co
return nil, err return nil, err
} }
return trustCenter, err return compliancePage, err
} }
// GetPortalEmailPresenterConfigByOrganizationID resolves the emails.PresenterConfig for // GetPortalEmailPresenterConfigByOrganizationID resolves the emails.PresenterConfig for
// the trust center that belongs to the given organization. This is used by the // the compliance page that belongs to the given organization. This is used by the
// esign certificate worker which needs per-org branding at render time. // esign certificate worker which needs per-org branding at render time.
func (s *Service) GetPortalEmailPresenterConfigByOrganizationID(ctx context.Context, orgID gid.GID) (emails.PresenterConfig, error) { func (s *Service) GetPortalEmailPresenterConfigByOrganizationID(ctx context.Context, orgID gid.GID) (emails.PresenterConfig, error) {
var trustCenter coredata.TrustCenter var compliancePage coredata.TrustCenter
scope := coredata.NewScopeFromObjectID(orgID) scope := coredata.NewScopeFromObjectID(orgID)
err := s.pg.WithConn( err := s.pg.WithConn(
ctx, ctx,
func(ctx context.Context, conn pg.Querier) error { func(ctx context.Context, conn pg.Querier) error {
return trustCenter.LoadByOrganizationID(ctx, conn, scope, orgID) return compliancePage.LoadByOrganizationID(ctx, conn, scope, orgID)
}, },
) )
if err != nil { if err != nil {
return emails.PresenterConfig{}, fmt.Errorf("cannot load trust center for org %s: %w", orgID, err) return emails.PresenterConfig{}, fmt.Errorf("cannot load compliance page for org %s: %w", orgID, err)
} }
return s.GetPortalEmailPresenterConfig(ctx, scope, trustCenter.ID) return s.GetPortalEmailPresenterConfig(ctx, scope, compliancePage.ID)
} }
func (s *Service) GetPortalOrganization( func (s *Service) GetPortalOrganization(
ctx context.Context, ctx context.Context,
trustCenterID gid.GID, compliancePageID gid.GID,
) (*coredata.Organization, error) { ) (*coredata.Organization, error) {
trustCenter, err := s.GetPortalByID(ctx, trustCenterID) compliancePage, err := s.GetPortalByID(ctx, compliancePageID)
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot load trust center: %w", err) return nil, fmt.Errorf("cannot load compliance page: %w", err)
} }
org := &coredata.Organization{} org := &coredata.Organization{}
@@ -257,7 +260,7 @@ func (s *Service) GetPortalOrganization(
err = s.pg.WithConn( err = s.pg.WithConn(
ctx, ctx,
func(ctx context.Context, conn pg.Querier) error { func(ctx context.Context, conn pg.Querier) error {
return org.LoadByID(ctx, conn, coredata.NewNoScope(), trustCenter.OrganizationID) return org.LoadByID(ctx, conn, coredata.NewNoScope(), compliancePage.OrganizationID)
}, },
) )
if err != nil { if err != nil {
@@ -305,17 +308,17 @@ func (s *Service) GetPortalNDAFileByID(
err := s.pg.WithConn( err := s.pg.WithConn(
ctx, ctx,
func(ctx context.Context, conn pg.Querier) error { func(ctx context.Context, conn pg.Querier) error {
trustCenter := &coredata.TrustCenter{} compliancePage := &coredata.TrustCenter{}
if err := trustCenter.LoadByID(ctx, conn, scope, compliancePageID); err != nil { if err := compliancePage.LoadByID(ctx, conn, scope, compliancePageID); err != nil {
return fmt.Errorf("cannot load trust center: %w", err) return fmt.Errorf("cannot load compliance page: %w", err)
} }
if trustCenter.NonDisclosureAgreementFileID == nil { if compliancePage.NonDisclosureAgreementFileID == nil {
return ErrNDAFileNotFound return ErrNDAFileNotFound
} }
file = &coredata.File{} file = &coredata.File{}
if err := file.LoadByID(ctx, conn, scope, *trustCenter.NonDisclosureAgreementFileID); err != nil { if err := file.LoadByID(ctx, conn, scope, *compliancePage.NonDisclosureAgreementFileID); err != nil {
if errors.Is(err, coredata.ErrResourceNotFound) { if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrNDAFileNotFound return ErrNDAFileNotFound
} }
@@ -349,7 +352,7 @@ func (s *Service) ProvisionPortalMember(
func(ctx context.Context, tx pg.Tx) error { func(ctx context.Context, tx pg.Tx) error {
compliancePage := &coredata.TrustCenter{} compliancePage := &coredata.TrustCenter{}
if err := compliancePage.LoadByID(ctx, tx, scope, compliancePageID); err != nil { if err := compliancePage.LoadByID(ctx, tx, scope, compliancePageID); err != nil {
return fmt.Errorf("cannot load trust center: %w", err) return fmt.Errorf("cannot load compliance page: %w", err)
} }
identity := &coredata.Identity{} identity := &coredata.Identity{}
@@ -360,7 +363,7 @@ func (s *Service) ProvisionPortalMember(
access = &coredata.TrustCenterAccess{} access = &coredata.TrustCenterAccess{}
if err := access.LoadByTrustCenterIDAndIdentityID(ctx, tx, scope, compliancePageID, identityID); err != nil { if err := access.LoadByTrustCenterIDAndIdentityID(ctx, tx, scope, compliancePageID, identityID); err != nil {
if !errors.Is(err, coredata.ErrResourceNotFound) { if !errors.Is(err, coredata.ErrResourceNotFound) {
return fmt.Errorf("cannot load trust center access: %w", err) return fmt.Errorf("cannot load compliance page access: %w", err)
} }
access = &coredata.TrustCenterAccess{ access = &coredata.TrustCenterAccess{
@@ -399,7 +402,7 @@ func (s *Service) ProvisionPortalMember(
} }
if err := access.Insert(ctx, tx, scope); err != nil { if err := access.Insert(ctx, tx, scope); err != nil {
return fmt.Errorf("cannot insert trust center access: %w", err) return fmt.Errorf("cannot insert compliance page access: %w", err)
} }
} }

View File

@@ -87,7 +87,7 @@ func (s *Service) ListThirdPartiesForOrganizationID(
return page.NewPage(thirdParties, cursor), nil return page.NewPage(thirdParties, cursor), nil
} }
func (s *Service) ListDistinctTrustCenterCategoriesForOrganizationID( func (s *Service) ListDistinctPortalCategoriesForOrganizationID(
ctx context.Context, ctx context.Context,
scope coredata.Scoper, scope coredata.Scoper,
organizationID gid.GID, organizationID gid.GID,
@@ -116,7 +116,7 @@ func (s *Service) ListDistinctTrustCenterCategoriesForOrganizationID(
return categories, nil return categories, nil
} }
func (s *Service) ListDistinctTrustCenterCountriesForOrganizationID( func (s *Service) ListDistinctPortalCountriesForOrganizationID(
ctx context.Context, ctx context.Context,
scope coredata.Scoper, scope coredata.Scoper,
organizationID gid.GID, organizationID gid.GID,
@@ -148,7 +148,7 @@ func (s *Service) ListDistinctTrustCenterCountriesForOrganizationID(
func (s *Service) CountThirdPartiesForPortalID( func (s *Service) CountThirdPartiesForPortalID(
ctx context.Context, ctx context.Context,
scope coredata.Scoper, scope coredata.Scoper,
trustCenterID gid.GID, compliancePageID gid.GID,
filter *coredata.ThirdPartyFilter, filter *coredata.ThirdPartyFilter,
) (int, error) { ) (int, error) {
if filter == nil { if filter == nil {
@@ -161,14 +161,14 @@ func (s *Service) CountThirdPartiesForPortalID(
err := s.pg.WithConn( err := s.pg.WithConn(
ctx, ctx,
func(ctx context.Context, conn pg.Querier) (err error) { func(ctx context.Context, conn pg.Querier) (err error) {
trustCenter, err := s.GetPortal(ctx, scope, trustCenterID) compliancePage, err := s.GetPortal(ctx, scope, compliancePageID)
if err != nil { if err != nil {
return fmt.Errorf("cannot load trust center: %w", err) return fmt.Errorf("cannot load compliance page: %w", err)
} }
thirdParties := &coredata.ThirdParties{} thirdParties := &coredata.ThirdParties{}
count, err = thirdParties.CountByOrganizationID(ctx, conn, scope, trustCenter.OrganizationID, filter) count, err = thirdParties.CountByOrganizationID(ctx, conn, scope, compliancePage.OrganizationID, filter)
if err != nil { if err != nil {
return fmt.Errorf("cannot count thirdParties: %w", err) return fmt.Errorf("cannot count thirdParties: %w", err)
} }

View File

@@ -0,0 +1,21 @@
-- Copyright (c) 2026 Probo Inc <hello@probo.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.
-- Append a random hex suffix to every compliance page slug so public URLs
-- are no longer guessable from the organization name.
UPDATE trust_centers
SET
slug = slug || '-' || encode(gen_random_bytes(4), 'hex'),
updated_at = clock_timestamp();

View File

@@ -65,10 +65,6 @@ type (
Email mail.Addr Email mail.Addr
URLPath string URLPath string
Continue *string Continue *string
// If users tries to connect to compliance page, we must brand the emails accordingly
CompliancePageID *gid.GID
// OrganizationID brands compliance portal magic-link emails.
OrganizationID *gid.GID
// OAuth2ClientIDRaw brands connect authorize magic-link emails. // OAuth2ClientIDRaw brands connect authorize magic-link emails.
OAuth2ClientIDRaw *string OAuth2ClientIDRaw *string
MagicLinkBaseURL *string MagicLinkBaseURL *string
@@ -621,27 +617,10 @@ func (s AuthService) SendMagicLink(ctx context.Context, req *SendMagicLinkReques
if branding != nil { if branding != nil {
senderName = branding.Name senderName = branding.Name
} }
} else if req.OrganizationID != nil {
organization := &coredata.Organization{}
if err := organization.LoadByID(ctx, tx, coredata.NewNoScope(), *req.OrganizationID); err != nil {
return fmt.Errorf("cannot load organization: %w", err)
}
senderName = organization.Name
} }
emailPresenterCfg := emails.DefaultPresenterConfig(s.baseURL) emailPresenterCfg := emails.DefaultPresenterConfig(s.baseURL)
if req.CompliancePageID != nil {
var err error
emailPresenterCfg, err = s.CompliancePageService.EmailPresenterConfig(ctx, *req.CompliancePageID)
if err != nil {
return fmt.Errorf("cannot get compliance page email presenter config: %w", err)
}
}
if req.MagicLinkBaseURL != nil { if req.MagicLinkBaseURL != nil {
emailPresenterCfg.BaseURL = *req.MagicLinkBaseURL emailPresenterCfg.BaseURL = *req.MagicLinkBaseURL
} }
@@ -659,20 +638,13 @@ func (s AuthService) SendMagicLink(ctx context.Context, req *SendMagicLinkReques
return fmt.Errorf("cannot render magic link email: %w", err) return fmt.Errorf("cannot render magic link email: %w", err)
} }
var emailOpts *coredata.EmailOptions
if req.CompliancePageID != nil {
emailOpts = &coredata.EmailOptions{
SenderName: &senderName,
}
}
magicLinkEmail := coredata.NewEmail( magicLinkEmail := coredata.NewEmail(
fullName, fullName,
req.Email, req.Email,
subject, subject,
textBody, textBody,
htmlBody, htmlBody,
emailOpts, nil,
) )
if err := magicLinkEmail.Insert(ctx, tx); err != nil { if err := magicLinkEmail.Insert(ctx, tx); err != nil {

View File

@@ -1,163 +0,0 @@
// Copyright (c) 2026 Probo Inc <hello@probo.com>.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
package iam
import (
"context"
"fmt"
"path/filepath"
"time"
"go.gearno.de/kit/pg"
"go.probo.inc/probo/packages/emails"
"go.probo.inc/probo/pkg/complianceportal/resolver"
"go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/gid"
)
type (
CompliancePageService struct {
*Service
}
)
func NewCompliancePageService(svc *Service) *CompliancePageService {
return &CompliancePageService{Service: svc}
}
func (s *CompliancePageService) GenerateLogoURL(
ctx context.Context,
compliancePageID gid.GID,
expiresIn time.Duration,
) (*string, error) {
file := &coredata.File{}
compliancePage := &coredata.TrustCenter{}
scope := coredata.NewScopeFromObjectID(compliancePageID)
err := s.pg.WithConn(
ctx,
func(ctx context.Context, conn pg.Querier) error {
if err := compliancePage.LoadByID(ctx, conn, scope, compliancePageID); err != nil {
return fmt.Errorf("cannot load compliance page: %w", err)
}
if compliancePage.LogoFileID == nil {
return nil
}
if err := file.LoadByID(ctx, conn, scope, *compliancePage.LogoFileID); err != nil {
return fmt.Errorf("cannot load file: %w", err)
}
return nil
},
)
if err != nil {
return nil, err
}
if compliancePage.LogoFileID == nil {
return nil, nil
}
if file.FileKey == "" {
return nil, nil
}
presignedURL, err := s.fm.GeneratePresignedURL(ctx, file, expiresIn)
if err != nil {
return nil, fmt.Errorf("cannot generate file URL: %w", err)
}
return &presignedURL, nil
}
func (s *CompliancePageService) EmailPresenterConfig(ctx context.Context, compliancePageID gid.GID) (emails.PresenterConfig, error) {
var (
compliancePage = &coredata.TrustCenter{}
organization = &coredata.Organization{}
compliancePageURL string
logoFile = &coredata.File{}
emailPresenterCfg = emails.DefaultPresenterConfig(s.baseURL)
)
scope := coredata.NewScopeFromObjectID(compliancePageID)
err := s.pg.WithConn(
ctx,
func(ctx context.Context, conn pg.Querier) error {
if err := compliancePage.LoadByID(ctx, conn, scope, compliancePageID); err != nil {
return fmt.Errorf("cannot load compliance page: %w", err)
}
if compliancePage.LogoFileID != nil {
if err := logoFile.LoadByID(ctx, conn, scope, *compliancePage.LogoFileID); err != nil {
return fmt.Errorf("cannot load logoFile: %w", err)
}
}
if err := organization.LoadByID(ctx, conn, scope, compliancePage.OrganizationID); err != nil {
return fmt.Errorf("cannot load organization: %w", err)
}
publicURL, err := resolver.PublicURLForTrustCenter(
ctx,
conn,
scope,
compliancePage,
s.trustCenterBaseDomain,
)
if err != nil {
return fmt.Errorf("cannot resolve compliance page URL: %w", err)
}
compliancePageURL = publicURL
return nil
},
)
if err != nil {
return emailPresenterCfg, err
}
emailPresenterCfg.BaseURL = compliancePageURL
if compliancePage.LogoFileID != nil {
if logoFile.FileKey == "" {
return emailPresenterCfg, nil
}
// If logo exists, then we will brand the emails with the org as a sender
emailPresenterCfg.SenderCompanyLogoPath = filepath.Join("/api/files/v1/public/", logoFile.ID.String())
emailPresenterCfg.SenderCompanyName = organization.Name
if compliancePage.WebsiteURL != nil {
emailPresenterCfg.SenderCompanyWebsiteURL = *compliancePage.WebsiteURL
}
if compliancePage.HeadquarterAddress != nil {
emailPresenterCfg.SenderCompanyHeadquarterAddress = *compliancePage.HeadquarterAddress
}
}
return emailPresenterCfg, nil
}

View File

@@ -613,7 +613,7 @@ func (s *OrganizationService) CreateOrganization(
OrganizationID: organization.ID, OrganizationID: organization.ID,
TenantID: organization.TenantID, TenantID: organization.TenantID,
Active: false, Active: false,
Slug: slug.Make(organization.Name), Slug: slug.MakeWithEntropy(organization.Name),
Title: organization.Name, Title: organization.Name,
SearchEngineIndexing: coredata.SearchEngineIndexingNotIndexable, SearchEngineIndexing: coredata.SearchEngineIndexingNotIndexable,
MailingListID: &mailingList.ID, MailingListID: &mailingList.ID,

View File

@@ -71,7 +71,6 @@ type (
AccountService *AccountService AccountService *AccountService
OrganizationService *OrganizationService OrganizationService *OrganizationService
CompliancePageService *CompliancePageService
SessionService *SessionService SessionService *SessionService
AuthService *AuthService AuthService *AuthService
SAMLService *saml.Service SAMLService *saml.Service
@@ -174,7 +173,6 @@ func NewService(
svc.AccountService = NewAccountService(svc) svc.AccountService = NewAccountService(svc)
svc.OrganizationService = NewOrganizationService(svc) svc.OrganizationService = NewOrganizationService(svc)
svc.CompliancePageService = NewCompliancePageService(svc)
svc.SessionService = NewSessionService(svc) svc.SessionService = NewSessionService(svc)
svc.AuthService = NewAuthService(svc) svc.AuthService = NewAuthService(svc)
svc.APIKeyService = NewAPIKeyService(svc) svc.APIKeyService = NewAPIKeyService(svc)

View File

@@ -29,7 +29,6 @@ import (
"go.gearno.de/kit/pg" "go.gearno.de/kit/pg"
"go.probo.inc/probo/packages/emails" "go.probo.inc/probo/packages/emails"
"go.probo.inc/probo/pkg/baseurl" "go.probo.inc/probo/pkg/baseurl"
"go.probo.inc/probo/pkg/complianceportal/resolver"
"go.probo.inc/probo/pkg/coredata" "go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/gid" "go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/mail" "go.probo.inc/probo/pkg/mail"
@@ -98,12 +97,11 @@ func (s *Service) mailingListEmailConfig(
return fmt.Errorf("cannot load organization: %w", err) return fmt.Errorf("cannot load organization: %w", err)
} }
publicURL, err := resolver.PublicURLForTrustCenter( publicURL, err := s.compliancePortal.PublicURLForCompliancePage(
ctx, ctx,
conn, conn,
scope, scope,
compliancePage, compliancePage,
s.trustCenterBaseDomain,
) )
if err != nil { if err != nil {
return fmt.Errorf("cannot resolve compliance page URL: %w", err) return fmt.Errorf("cannot resolve compliance page URL: %w", err)

View File

@@ -30,6 +30,7 @@ import (
"go.gearno.de/kit/pg" "go.gearno.de/kit/pg"
"go.probo.inc/probo/packages/emails" "go.probo.inc/probo/packages/emails"
"go.probo.inc/probo/pkg/baseurl" "go.probo.inc/probo/pkg/baseurl"
"go.probo.inc/probo/pkg/complianceportal/management"
"go.probo.inc/probo/pkg/coredata" "go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/crypto/cipher" "go.probo.inc/probo/pkg/crypto/cipher"
"go.probo.inc/probo/pkg/filemanager" "go.probo.inc/probo/pkg/filemanager"
@@ -55,7 +56,7 @@ type Service struct {
fm *filemanager.Service fm *filemanager.Service
tokenSecret string tokenSecret string
apiBaseURL *baseurl.BaseURL apiBaseURL *baseurl.BaseURL
trustCenterBaseDomain string compliancePortal *management.Service
bucket string bucket string
encryptionKey cipher.EncryptionKey encryptionKey cipher.EncryptionKey
logger *log.Logger logger *log.Logger
@@ -66,7 +67,7 @@ func NewService(
fm *filemanager.Service, fm *filemanager.Service,
tokenSecret string, tokenSecret string,
apiBaseURL *baseurl.BaseURL, apiBaseURL *baseurl.BaseURL,
trustCenterBaseDomain string, compliancePortal *management.Service,
bucket string, bucket string,
encryptionKey cipher.EncryptionKey, encryptionKey cipher.EncryptionKey,
logger *log.Logger, logger *log.Logger,
@@ -76,7 +77,7 @@ func NewService(
fm: fm, fm: fm,
tokenSecret: tokenSecret, tokenSecret: tokenSecret,
apiBaseURL: apiBaseURL, apiBaseURL: apiBaseURL,
trustCenterBaseDomain: trustCenterBaseDomain, compliancePortal: compliancePortal,
bucket: bucket, bucket: bucket,
encryptionKey: encryptionKey, encryptionKey: encryptionKey,
logger: logger, logger: logger,

View File

@@ -52,7 +52,6 @@ import (
"go.probo.inc/probo/pkg/awsconfig" "go.probo.inc/probo/pkg/awsconfig"
"go.probo.inc/probo/pkg/baseurl" "go.probo.inc/probo/pkg/baseurl"
"go.probo.inc/probo/pkg/certmanager" "go.probo.inc/probo/pkg/certmanager"
"go.probo.inc/probo/pkg/complianceportal"
"go.probo.inc/probo/pkg/complianceportal/management" "go.probo.inc/probo/pkg/complianceportal/management"
"go.probo.inc/probo/pkg/complianceportal/visitor" "go.probo.inc/probo/pkg/complianceportal/visitor"
"go.probo.inc/probo/pkg/connector" "go.probo.inc/probo/pkg/connector"
@@ -495,7 +494,7 @@ func (impl *Implm) Run(
oauth2ScopeRegistry := oauth2scope.NewRegistry(). oauth2ScopeRegistry := oauth2scope.NewRegistry().
Register(iam.IAMOAuth2ScopeMappings). Register(iam.IAMOAuth2ScopeMappings).
Register(probo.OAuth2ScopeMappings). Register(probo.OAuth2ScopeMappings).
Register(complianceportal.OAuth2ScopeMappings). Register(management.OAuth2ScopeMappings).
Register(agentrun.OAuth2ScopeMappings). Register(agentrun.OAuth2ScopeMappings).
Register(accessreview.OAuth2ScopeMappings). Register(accessreview.OAuth2ScopeMappings).
Register(resourcealias.OAuth2ScopeMappings) Register(resourcealias.OAuth2ScopeMappings)
@@ -618,12 +617,26 @@ func (impl *Implm) Run(
l.Named("esign"), l.Named("esign"),
) )
resourceAliasService := resourcealias.NewService(pgClient)
managementService := management.NewService(
pgClient,
s3Client,
impl.cfg.AWS.Bucket,
baseURL.String(),
impl.cfg.TrustCenter.BaseDomain,
fileManagerService,
certManagerService,
slackService,
l.Named("compliance-portal-management"),
)
mailmanService := mailman.NewService( mailmanService := mailman.NewService(
pgClient, pgClient,
fileManagerService, fileManagerService,
impl.cfg.Auth.Cookie.Secret, impl.cfg.Auth.Cookie.Secret,
baseURL, baseURL,
impl.cfg.TrustCenter.BaseDomain, managementService,
impl.cfg.AWS.Bucket, impl.cfg.AWS.Bucket,
encryptionKey, encryptionKey,
l, l,
@@ -658,20 +671,6 @@ func (impl *Implm) Run(
return fmt.Errorf("cannot create probo service: %w", err) return fmt.Errorf("cannot create probo service: %w", err)
} }
resourceAliasService := resourcealias.NewService(pgClient)
managementService := management.NewService(
pgClient,
s3Client,
impl.cfg.AWS.Bucket,
baseURL.String(),
impl.cfg.TrustCenter.BaseDomain,
fileManagerService,
certManagerService,
slackService,
l.Named("compliance-portal-management"),
)
trustService := visitor.NewService( trustService := visitor.NewService(
pgClient, pgClient,
s3Client, s3Client,
@@ -686,6 +685,7 @@ func (impl *Implm) Run(
l, l,
slackService, slackService,
resourceAliasService, resourceAliasService,
managementService,
) )
staticCIMDAllow := oauth2.CIMDAllowFromClientIDs(impl.cfg.Auth.OAuth2Server.CIMDAllowedClientIDs) staticCIMDAllow := oauth2.CIMDAllowFromClientIDs(impl.cfg.Auth.OAuth2Server.CIMDAllowedClientIDs)
@@ -716,7 +716,7 @@ func (impl *Implm) Run(
iamService.Authorizer.RegisterPolicySet(agentrun.PolicySet()) iamService.Authorizer.RegisterPolicySet(agentrun.PolicySet())
iamService.Authorizer.RegisterPolicySet(accessreview.PolicySet()) iamService.Authorizer.RegisterPolicySet(accessreview.PolicySet())
iamService.Authorizer.RegisterPolicySet(resourcealias.PolicySet()) iamService.Authorizer.RegisterPolicySet(resourcealias.PolicySet())
iamService.Authorizer.RegisterPolicySet(complianceportal.PolicySet()) iamService.Authorizer.RegisterPolicySet(management.PolicySet())
thirdPartyService := thirdparty.NewService(pgClient, fileManagerService, thirdPartyVetter) thirdPartyService := thirdparty.NewService(pgClient, fileManagerService, thirdPartyVetter)
riskManagementService := riskmanagement.NewService(pgClient) riskManagementService := riskmanagement.NewService(pgClient)
@@ -732,6 +732,7 @@ func (impl *Implm) Run(
Trust: trustService, Trust: trustService,
ESign: esignService, ESign: esignService,
Management: managementService, Management: managementService,
CertManager: certManagerService,
AccessReview: accessReviewService, AccessReview: accessReviewService,
AgentRun: agentRunService, AgentRun: agentRunService,
Mailman: mailmanService, Mailman: mailmanService,

View File

@@ -34,6 +34,7 @@ import (
"go.probo.inc/probo/pkg/accessreview" "go.probo.inc/probo/pkg/accessreview"
"go.probo.inc/probo/pkg/agentrun" "go.probo.inc/probo/pkg/agentrun"
"go.probo.inc/probo/pkg/baseurl" "go.probo.inc/probo/pkg/baseurl"
"go.probo.inc/probo/pkg/certmanager"
"go.probo.inc/probo/pkg/complianceportal/management" "go.probo.inc/probo/pkg/complianceportal/management"
"go.probo.inc/probo/pkg/complianceportal/visitor" "go.probo.inc/probo/pkg/complianceportal/visitor"
"go.probo.inc/probo/pkg/connector" "go.probo.inc/probo/pkg/connector"
@@ -70,6 +71,7 @@ type (
Trust *visitor.Service Trust *visitor.Service
ESign *esign.Service ESign *esign.Service
Management *management.Service Management *management.Service
CertManager *certmanager.Service
AccessReview *accessreview.Service AccessReview *accessreview.Service
AgentRun *agentrun.Service AgentRun *agentrun.Service
Slack *slack.Service Slack *slack.Service
@@ -192,6 +194,7 @@ func NewServer(cfg Config) (*Server, error) {
cfg.IAM, cfg.IAM,
cfg.ESign, cfg.ESign,
cfg.Management, cfg.Management,
cfg.CertManager,
cfg.AccessReview, cfg.AccessReview,
cfg.AgentRun, cfg.AgentRun,
cfg.Mailman, cfg.Mailman,
@@ -225,6 +228,7 @@ func NewServer(cfg Config) (*Server, error) {
cfg.Logger.Named("mcp.v1"), cfg.Logger.Named("mcp.v1"),
cfg.Probo, cfg.Probo,
cfg.Management, cfg.Management,
cfg.CertManager,
cfg.ResourceAlias, cfg.ResourceAlias,
cfg.ThirdParty, cfg.ThirdParty,
cfg.IAM, cfg.IAM,

View File

@@ -15,23 +15,23 @@
package complianceportal package complianceportal
import ( import (
portal "go.probo.inc/probo/pkg/complianceportal" "go.probo.inc/probo/pkg/complianceportal/visitor"
) )
const ( const (
VisitorOAuthScope = portal.VisitorOAuthScope VisitorOAuthScope = visitor.VisitorOAuthScope
GraphQLPath = "/graphql" GraphQLPath = "/graphql"
CIMDMetadataPath = portal.CIMDMetadataPath CIMDMetadataPath = visitor.CIMDMetadataPath
BrandLogoPath = portal.BrandLogoPath BrandLogoPath = visitor.BrandLogoPath
BrandDarkLogoPath = portal.BrandDarkLogoPath BrandDarkLogoPath = visitor.BrandDarkLogoPath
OAuthInitiatePath = "/initiate" OAuthInitiatePath = "/initiate"
OAuthCallbackPath = portal.OAuthCallbackPath OAuthCallbackPath = visitor.OAuthCallbackPath
) )
func CIMDClientIDURL(portalBaseURL string) (string, error) { func CIMDClientIDURL(portalBaseURL string) (string, error) {
return portal.CIMDClientIDURL(portalBaseURL) return visitor.CIMDClientIDURL(portalBaseURL)
} }
func OAuthCallbackURL(portalBaseURL string) (string, error) { func OAuthCallbackURL(portalBaseURL string) (string, error) {
return portal.OAuthCallbackURL(portalBaseURL) return visitor.OAuthCallbackURL(portalBaseURL)
} }

View File

@@ -10,150 +10,14 @@ import (
"errors" "errors"
"go.gearno.de/kit/log" "go.gearno.de/kit/log"
"go.probo.inc/probo/pkg/baseurl"
"go.probo.inc/probo/pkg/coredata" "go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/iam" "go.probo.inc/probo/pkg/iam"
"go.probo.inc/probo/pkg/saferedirect"
"go.probo.inc/probo/pkg/server/api/authn" "go.probo.inc/probo/pkg/server/api/authn"
"go.probo.inc/probo/pkg/server/api/complianceportal" "go.probo.inc/probo/pkg/server/api/complianceportal"
"go.probo.inc/probo/pkg/server/api/complianceportal/v1/types" "go.probo.inc/probo/pkg/server/api/complianceportal/v1/types"
"go.probo.inc/probo/pkg/server/gqlutils" "go.probo.inc/probo/pkg/server/gqlutils"
) )
// SendMagicLink is the resolver for the sendMagicLink field.
func (r *mutationResolver) SendMagicLink(ctx context.Context, input types.SendMagicLinkInput) (*types.SendMagicLinkPayload, error) {
trustCenter := complianceportal.CompliancePageFromContext(ctx)
baseURL := complianceportal.CompliancePageBaseURLFromContext(ctx)
safeRedirect := saferedirect.New(saferedirect.StaticHosts(baseurl.MustParse(*baseURL).Host()))
if input.Continue != nil {
_, ok := safeRedirect.Validate(ctx, *input.Continue)
if !ok {
return nil, gqlutils.Invalidf(ctx, "invalid continue URL")
}
}
req := &iam.SendMagicLinkRequest{
Email: input.Email,
CompliancePageID: &trustCenter.ID,
OrganizationID: &trustCenter.OrganizationID,
URLPath: "verify-magic-link",
Continue: input.Continue,
}
if err := r.iam.AuthService.SendMagicLink(ctx, req); err != nil {
r.logger.ErrorCtx(ctx, "cannot send magic link", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return nil, nil
}
// VerifyMagicLink is the resolver for the verifyMagicLink field.
func (r *mutationResolver) VerifyMagicLink(ctx context.Context, input types.VerifyMagicLinkInput) (*types.VerifyMagicLinkPayload, error) {
session := authn.SessionFromContext(ctx)
identity := authn.IdentityFromContext(ctx)
email, err := r.iam.AuthService.GetMagicLinkEmail(ctx, input.Token)
if err != nil {
if _, ok := errors.AsType[*iam.ErrExpiredToken](err); ok {
return nil, gqlutils.TokenExpired(ctx, err)
}
if _, ok := errors.AsType[*iam.ErrInvalidToken](err); ok {
return nil, gqlutils.Invalid(ctx, err)
}
r.logger.ErrorCtx(ctx, "cannot get magic link email", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
var continueURL *string
switch {
case session == nil:
var err error
identity, session, continueURL, err = r.iam.AuthService.OpenSessionWithMagicLink(ctx, input.Token)
if err != nil {
if _, ok := errors.AsType[*iam.ErrExpiredToken](err); ok {
return nil, gqlutils.TokenExpired(ctx, err)
}
if _, ok := errors.AsType[*iam.ErrTokenAlreadyUsed](err); ok {
return nil, gqlutils.TokenAlreadyUsed(ctx, err)
}
if _, ok := errors.AsType[*iam.ErrInvalidToken](err); ok {
return nil, gqlutils.Invalid(ctx, err)
}
r.logger.ErrorCtx(ctx, "cannot open session with magic link", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
case identity.EmailAddress != email:
if err := r.iam.SessionService.CloseSession(ctx, session.ID); err != nil {
r.logger.ErrorCtx(ctx, "cannot close session", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
var err error
identity, session, continueURL, err = r.iam.AuthService.OpenSessionWithMagicLink(ctx, input.Token)
if err != nil {
if _, ok := errors.AsType[*iam.ErrExpiredToken](err); ok {
return nil, gqlutils.TokenExpired(ctx, err)
}
if _, ok := errors.AsType[*iam.ErrTokenAlreadyUsed](err); ok {
return nil, gqlutils.TokenAlreadyUsed(ctx, err)
}
if _, ok := errors.AsType[*iam.ErrInvalidToken](err); ok {
return nil, gqlutils.Invalid(ctx, err)
}
r.logger.ErrorCtx(ctx, "cannot open session with magic link", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
}
req := gqlutils.HTTPRequestFromContext(ctx)
if req == nil {
return nil, gqlutils.Internal(ctx)
}
host, ok := complianceportal.TrustedRequestHost(req)
if !ok {
return nil, gqlutils.Internal(ctx)
}
session.Data = coredata.SessionDataForHost(host)
if err := r.iam.SessionService.UpdateSessionData(ctx, session.ID, session.Data); err != nil {
r.logger.ErrorCtx(ctx, "cannot bind session to host", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
trustCenter := complianceportal.CompliancePageFromContext(ctx)
if _, err := r.trust.ProvisionPortalMember(ctx, trustCenter.ID, identity.ID); err != nil {
r.logger.ErrorCtx(ctx, "cannot provision member", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
w := gqlutils.HTTPResponseWriterFromContext(ctx)
r.sessionCookie.Set(w, session)
return &types.VerifyMagicLinkPayload{
Continue: continueURL,
}, nil
}
// UpdateFullName is the resolver for the updateFullName field. // UpdateFullName is the resolver for the updateFullName field.
func (r *mutationResolver) UpdateFullName(ctx context.Context, input types.UpdateFullNameInput) (*types.UpdateFullNamePayload, error) { func (r *mutationResolver) UpdateFullName(ctx context.Context, input types.UpdateFullNameInput) (*types.UpdateFullNamePayload, error) {
identity := authn.IdentityFromContext(ctx) identity := authn.IdentityFromContext(ctx)

View File

@@ -132,7 +132,7 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error
trustCenterFile, err := trustService.GetPortalFile(ctx, scope, trustCenter.OrganizationID, id) trustCenterFile, err := trustService.GetPortalFile(ctx, scope, trustCenter.OrganizationID, id)
if err != nil { if err != nil {
if errors.Is(err, visitor.ErrTrustCenterFileNotFound) || errors.Is(err, visitor.ErrTrustCenterFileNotVisible) { if errors.Is(err, visitor.ErrPortalFileNotFound) || errors.Is(err, visitor.ErrPortalFileNotVisible) {
return nil, gqlutils.NotFoundf(ctx, "node %q not found", id) return nil, gqlutils.NotFoundf(ctx, "node %q not found", id)
} }

View File

@@ -1,30 +1,9 @@
extend type Mutation { extend type Mutation {
sendMagicLink(input: SendMagicLinkInput!): SendMagicLinkPayload
@authentication(required: OPTIONAL)
verifyMagicLink(input: VerifyMagicLinkInput!): VerifyMagicLinkPayload
@authentication(required: OPTIONAL)
updateFullName(input: UpdateFullNameInput!): UpdateFullNamePayload updateFullName(input: UpdateFullNameInput!): UpdateFullNamePayload
@authentication(required: PRESENT) @sessionOnly @authentication(required: PRESENT) @sessionOnly
signOut: SignOutPayload! @authentication(required: PRESENT) @sessionOnly signOut: SignOutPayload! @authentication(required: PRESENT) @sessionOnly
} }
input SendMagicLinkInput {
email: EmailAddr!
continue: String
}
type SendMagicLinkPayload {
success: Boolean!
}
input VerifyMagicLinkInput {
token: String!
}
type VerifyMagicLinkPayload {
continue: String
}
input UpdateFullNameInput { input UpdateFullNameInput {
fullName: String! fullName: String!
} }

View File

@@ -22,7 +22,6 @@ import (
"go.gearno.de/kit/log" "go.gearno.de/kit/log"
"go.gearno.de/x/ref" "go.gearno.de/x/ref"
"go.probo.inc/probo/pkg/baseurl" "go.probo.inc/probo/pkg/baseurl"
page "go.probo.inc/probo/pkg/complianceportal"
visitor "go.probo.inc/probo/pkg/complianceportal/visitor" visitor "go.probo.inc/probo/pkg/complianceportal/visitor"
"go.probo.inc/probo/pkg/esign" "go.probo.inc/probo/pkg/esign"
"go.probo.inc/probo/pkg/filemanager" "go.probo.inc/probo/pkg/filemanager"
@@ -148,7 +147,7 @@ func compliancePageHeadData() HeadDataFunc {
} }
if tc.LogoFileID != nil && compliancePageBaseURL != nil { if tc.LogoFileID != nil && compliancePageBaseURL != nil {
faviconURL, err := page.BrandLogoURL(*compliancePageBaseURL) faviconURL, err := visitor.BrandLogoURL(*compliancePageBaseURL)
if err == nil { if err == nil {
headData.FaviconURL = faviconURL headData.FaviconURL = faviconURL
} }

View File

@@ -19,7 +19,7 @@ import (
"net/http" "net/http"
"go.gearno.de/kit/httpserver" "go.gearno.de/kit/httpserver"
portal "go.probo.inc/probo/pkg/complianceportal" "go.probo.inc/probo/pkg/complianceportal/visitor"
"go.probo.inc/probo/pkg/server/api/complianceportal" "go.probo.inc/probo/pkg/server/api/complianceportal"
) )
@@ -38,7 +38,7 @@ func (h *oauthClientMetadataHandler) ServeHTTP(w http.ResponseWriter, r *http.Re
return return
} }
doc, err := portal.BuildClientMetadataDocument(compliancePage, *baseURL) doc, err := visitor.BuildClientMetadataDocument(compliancePage, *baseURL)
if err != nil { if err != nil {
httpserver.RenderError(w, http.StatusInternalServerError, errInternal) httpserver.RenderError(w, http.StatusInternalServerError, errInternal)
return return

View File

@@ -467,7 +467,7 @@ func (r *mutationResolver) ExportTrustCenterFile(ctx context.Context, input type
trustCenterFile, err := trustService.GetPortalFile(ctx, scope, trustCenter.OrganizationID, input.TrustCenterFileID) trustCenterFile, err := trustService.GetPortalFile(ctx, scope, trustCenter.OrganizationID, input.TrustCenterFileID)
if err != nil { if err != nil {
if errors.Is(err, visitor.ErrTrustCenterFileNotFound) || errors.Is(err, visitor.ErrTrustCenterFileNotVisible) { if errors.Is(err, visitor.ErrPortalFileNotFound) || errors.Is(err, visitor.ErrPortalFileNotVisible) {
return nil, gqlutils.NotFoundf(ctx, "trust center file %q not found", input.TrustCenterFileID) return nil, gqlutils.NotFoundf(ctx, "trust center file %q not found", input.TrustCenterFileID)
} }
@@ -620,7 +620,7 @@ func (r *mutationResolver) RequestTrustCenterFileAccess(ctx context.Context, inp
trustCenterFile, err := trustService.GetPortalFile(ctx, scope, trustCenter.OrganizationID, input.TrustCenterFileID) trustCenterFile, err := trustService.GetPortalFile(ctx, scope, trustCenter.OrganizationID, input.TrustCenterFileID)
if err != nil { if err != nil {
if errors.Is(err, visitor.ErrTrustCenterFileNotFound) || errors.Is(err, visitor.ErrTrustCenterFileNotVisible) { if errors.Is(err, visitor.ErrPortalFileNotFound) || errors.Is(err, visitor.ErrPortalFileNotVisible) {
return nil, gqlutils.NotFoundf(ctx, "trust center file %q not found", input.TrustCenterFileID) return nil, gqlutils.NotFoundf(ctx, "trust center file %q not found", input.TrustCenterFileID)
} }
@@ -836,7 +836,7 @@ func (r *trustCenterResolver) SubprocessorCategories(ctx context.Context, obj *t
trustCenter := complianceportal.CompliancePageFromContext(ctx) trustCenter := complianceportal.CompliancePageFromContext(ctx)
scope := coredata.NewScopeFromObjectID(obj.ID) scope := coredata.NewScopeFromObjectID(obj.ID)
categories, err := r.trust.ListDistinctTrustCenterCategoriesForOrganizationID(ctx, scope, trustCenter.OrganizationID) categories, err := r.trust.ListDistinctPortalCategoriesForOrganizationID(ctx, scope, trustCenter.OrganizationID)
if err != nil { if err != nil {
r.logger.ErrorCtx(ctx, "cannot list subprocessor categories", log.Error(err)) r.logger.ErrorCtx(ctx, "cannot list subprocessor categories", log.Error(err))
return nil, gqlutils.Internal(ctx) return nil, gqlutils.Internal(ctx)
@@ -850,7 +850,7 @@ func (r *trustCenterResolver) SubprocessorCountries(ctx context.Context, obj *ty
trustCenter := complianceportal.CompliancePageFromContext(ctx) trustCenter := complianceportal.CompliancePageFromContext(ctx)
scope := coredata.NewScopeFromObjectID(obj.ID) scope := coredata.NewScopeFromObjectID(obj.ID)
countries, err := r.trust.ListDistinctTrustCenterCountriesForOrganizationID(ctx, scope, trustCenter.OrganizationID) countries, err := r.trust.ListDistinctPortalCountriesForOrganizationID(ctx, scope, trustCenter.OrganizationID)
if err != nil { if err != nil {
r.logger.ErrorCtx(ctx, "cannot list subprocessor countries", log.Error(err)) r.logger.ErrorCtx(ctx, "cannot list subprocessor countries", log.Error(err))
return nil, gqlutils.Internal(ctx) return nil, gqlutils.Internal(ctx)
@@ -986,7 +986,7 @@ func (r *trustCenterFileResolver) IsUserAuthorized(ctx context.Context, obj *typ
trustCenterFile, err := trustService.GetPortalFile(ctx, scope, trustCenter.OrganizationID, obj.ID) trustCenterFile, err := trustService.GetPortalFile(ctx, scope, trustCenter.OrganizationID, obj.ID)
if err != nil { if err != nil {
if errors.Is(err, visitor.ErrTrustCenterFileNotFound) || errors.Is(err, visitor.ErrTrustCenterFileNotVisible) { if errors.Is(err, visitor.ErrPortalFileNotFound) || errors.Is(err, visitor.ErrPortalFileNotVisible) {
return false, gqlutils.NotFoundf(ctx, "trust center file %q not found", obj.ID) return false, gqlutils.NotFoundf(ctx, "trust center file %q not found", obj.ID)
} }

View File

@@ -14,7 +14,7 @@ import (
"go.gearno.de/kit/log" "go.gearno.de/kit/log"
"go.probo.inc/probo/pkg/accessreview" "go.probo.inc/probo/pkg/accessreview"
"go.probo.inc/probo/pkg/agentrun" "go.probo.inc/probo/pkg/agentrun"
"go.probo.inc/probo/pkg/complianceportal" "go.probo.inc/probo/pkg/complianceportal/management"
"go.probo.inc/probo/pkg/coredata" "go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/gid" "go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/probo" "go.probo.inc/probo/pkg/probo"
@@ -335,7 +335,7 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error
return types.NewTransferImpactAssessment(tia), nil return types.NewTransferImpactAssessment(tia), nil
} }
case coredata.TrustCenterEntityType: case coredata.TrustCenterEntityType:
action = complianceportal.ActionCompliancePortalGet action = management.ActionCompliancePortalGet
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) { loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
trustCenter, err := r.management.Get(ctx, scope, id) trustCenter, err := r.management.Get(ctx, scope, id)
if err != nil { if err != nil {
@@ -345,7 +345,7 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error
return types.NewTrustCenter(trustCenter), nil return types.NewTrustCenter(trustCenter), nil
} }
case coredata.TrustCenterAccessEntityType: case coredata.TrustCenterAccessEntityType:
action = complianceportal.ActionCompliancePortalAccessGet action = management.ActionCompliancePortalAccessGet
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) { loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
trustCenterAccess, err := r.management.GetAccess(ctx, scope, id) trustCenterAccess, err := r.management.GetAccess(ctx, scope, id)
if err != nil { if err != nil {

View File

@@ -27,6 +27,7 @@ import (
"go.probo.inc/probo/pkg/accessreview" "go.probo.inc/probo/pkg/accessreview"
"go.probo.inc/probo/pkg/agentrun" "go.probo.inc/probo/pkg/agentrun"
"go.probo.inc/probo/pkg/baseurl" "go.probo.inc/probo/pkg/baseurl"
"go.probo.inc/probo/pkg/certmanager"
"go.probo.inc/probo/pkg/complianceportal/management" "go.probo.inc/probo/pkg/complianceportal/management"
"go.probo.inc/probo/pkg/connector" "go.probo.inc/probo/pkg/connector"
"go.probo.inc/probo/pkg/connector/provider" "go.probo.inc/probo/pkg/connector/provider"
@@ -51,6 +52,7 @@ func NewGraphQLHandler(
resourceAliasSvc *resourcealias.Service, resourceAliasSvc *resourcealias.Service,
esignSvc *esign.Service, esignSvc *esign.Service,
managementSvc *management.Service, managementSvc *management.Service,
certManagerSvc *certmanager.Service,
accessReviewSvc *accessreview.Service, accessReviewSvc *accessreview.Service,
agentRunSvc *agentrun.Service, agentRunSvc *agentrun.Service,
mailmanSvc *mailman.Service, mailmanSvc *mailman.Service,
@@ -75,6 +77,7 @@ func NewGraphQLHandler(
iam: iamSvc, iam: iamSvc,
esign: esignSvc, esign: esignSvc,
management: managementSvc, management: managementSvc,
certManager: certManagerSvc,
accessReview: accessReviewSvc, accessReview: accessReviewSvc,
agentRun: agentRunSvc, agentRun: agentRunSvc,
mailman: mailmanSvc, mailman: mailmanSvc,

View File

@@ -11,7 +11,7 @@ import (
"fmt" "fmt"
"go.gearno.de/kit/log" "go.gearno.de/kit/log"
"go.probo.inc/probo/pkg/complianceportal" "go.probo.inc/probo/pkg/complianceportal/management"
"go.probo.inc/probo/pkg/coredata" "go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/mailman" "go.probo.inc/probo/pkg/mailman"
"go.probo.inc/probo/pkg/page" "go.probo.inc/probo/pkg/page"
@@ -23,7 +23,7 @@ import (
// Subscribers is the resolver for the subscribers field on MailingList. // Subscribers is the resolver for the subscribers field on MailingList.
func (r *mailingListResolver) Subscribers(ctx context.Context, obj *types.MailingList, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.MailingListSubscriberConnection, error) { func (r *mailingListResolver) Subscribers(ctx context.Context, obj *types.MailingList, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.MailingListSubscriberConnection, error) {
if _, err := r.authorize(ctx, obj.ID, complianceportal.ActionMailingListSubscriberList); err != nil { if _, err := r.authorize(ctx, obj.ID, management.ActionMailingListSubscriberList); err != nil {
return nil, err return nil, err
} }
@@ -45,7 +45,7 @@ func (r *mailingListResolver) Subscribers(ctx context.Context, obj *types.Mailin
// Updates is the resolver for the updates field on MailingList. // Updates is the resolver for the updates field on MailingList.
func (r *mailingListResolver) Updates(ctx context.Context, obj *types.MailingList, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.MailingListUpdateConnection, error) { func (r *mailingListResolver) Updates(ctx context.Context, obj *types.MailingList, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.MailingListUpdateConnection, error) {
if _, err := r.authorize(ctx, obj.ID, complianceportal.ActionMailingListUpdateList); err != nil { if _, err := r.authorize(ctx, obj.ID, management.ActionMailingListUpdateList); err != nil {
return nil, err return nil, err
} }
@@ -67,7 +67,7 @@ func (r *mailingListResolver) Updates(ctx context.Context, obj *types.MailingLis
// TotalCount is the resolver for the totalCount field. // TotalCount is the resolver for the totalCount field.
func (r *mailingListSubscriberConnectionResolver) TotalCount(ctx context.Context, obj *types.MailingListSubscriberConnection) (int, error) { func (r *mailingListSubscriberConnectionResolver) TotalCount(ctx context.Context, obj *types.MailingListSubscriberConnection) (int, error) {
if _, err := r.authorize(ctx, obj.ParentID, complianceportal.ActionMailingListSubscriberList); err != nil { if _, err := r.authorize(ctx, obj.ParentID, management.ActionMailingListSubscriberList); err != nil {
return 0, err return 0, err
} }
@@ -89,7 +89,7 @@ func (r *mailingListSubscriberConnectionResolver) TotalCount(ctx context.Context
// TotalCount is the resolver for the totalCount field on MailingListUpdateConnection. // TotalCount is the resolver for the totalCount field on MailingListUpdateConnection.
func (r *mailingListUpdateConnectionResolver) TotalCount(ctx context.Context, obj *types.MailingListUpdateConnection) (int, error) { func (r *mailingListUpdateConnectionResolver) TotalCount(ctx context.Context, obj *types.MailingListUpdateConnection) (int, error) {
if _, err := r.authorize(ctx, obj.ParentID, complianceportal.ActionMailingListUpdateList); err != nil { if _, err := r.authorize(ctx, obj.ParentID, management.ActionMailingListUpdateList); err != nil {
return 0, err return 0, err
} }
@@ -104,7 +104,7 @@ func (r *mailingListUpdateConnectionResolver) TotalCount(ctx context.Context, ob
// CreateMailingListUpdate is the resolver for the createMailingListUpdate field. // CreateMailingListUpdate is the resolver for the createMailingListUpdate field.
func (r *mutationResolver) CreateMailingListUpdate(ctx context.Context, input types.CreateMailingListUpdateInput) (*types.CreateMailingListUpdatePayload, error) { func (r *mutationResolver) CreateMailingListUpdate(ctx context.Context, input types.CreateMailingListUpdateInput) (*types.CreateMailingListUpdatePayload, error) {
if _, err := r.authorize(ctx, input.MailingListID, complianceportal.ActionMailingListUpdateCreate); err != nil { if _, err := r.authorize(ctx, input.MailingListID, management.ActionMailingListUpdateCreate); err != nil {
return nil, err return nil, err
} }
@@ -133,7 +133,7 @@ func (r *mutationResolver) CreateMailingListUpdate(ctx context.Context, input ty
// UpdateMailingListUpdate is the resolver for the updateMailingListUpdate field. // UpdateMailingListUpdate is the resolver for the updateMailingListUpdate field.
func (r *mutationResolver) UpdateMailingListUpdate(ctx context.Context, input types.UpdateMailingListUpdateInput) (*types.UpdateMailingListUpdatePayload, error) { func (r *mutationResolver) UpdateMailingListUpdate(ctx context.Context, input types.UpdateMailingListUpdateInput) (*types.UpdateMailingListUpdatePayload, error) {
if _, err := r.authorize(ctx, input.ID, complianceportal.ActionMailingListUpdateUpdate); err != nil { if _, err := r.authorize(ctx, input.ID, management.ActionMailingListUpdateUpdate); err != nil {
return nil, err return nil, err
} }
@@ -170,7 +170,7 @@ func (r *mutationResolver) UpdateMailingListUpdate(ctx context.Context, input ty
// SendMailingListUpdate is the resolver for the sendMailingListUpdate field. // SendMailingListUpdate is the resolver for the sendMailingListUpdate field.
func (r *mutationResolver) SendMailingListUpdate(ctx context.Context, input types.SendMailingListUpdateInput) (*types.SendMailingListUpdatePayload, error) { func (r *mutationResolver) SendMailingListUpdate(ctx context.Context, input types.SendMailingListUpdateInput) (*types.SendMailingListUpdatePayload, error) {
if _, err := r.authorize(ctx, input.ID, complianceportal.ActionMailingListUpdateUpdate); err != nil { if _, err := r.authorize(ctx, input.ID, management.ActionMailingListUpdateUpdate); err != nil {
return nil, err return nil, err
} }
@@ -196,7 +196,7 @@ func (r *mutationResolver) SendMailingListUpdate(ctx context.Context, input type
// DeleteMailingListUpdate is the resolver for the deleteMailingListUpdate field. // DeleteMailingListUpdate is the resolver for the deleteMailingListUpdate field.
func (r *mutationResolver) DeleteMailingListUpdate(ctx context.Context, input types.DeleteMailingListUpdateInput) (*types.DeleteMailingListUpdatePayload, error) { func (r *mutationResolver) DeleteMailingListUpdate(ctx context.Context, input types.DeleteMailingListUpdateInput) (*types.DeleteMailingListUpdatePayload, error) {
if _, err := r.authorize(ctx, input.ID, complianceportal.ActionMailingListUpdateDelete); err != nil { if _, err := r.authorize(ctx, input.ID, management.ActionMailingListUpdateDelete); err != nil {
return nil, err return nil, err
} }
@@ -217,7 +217,7 @@ func (r *mutationResolver) DeleteMailingListUpdate(ctx context.Context, input ty
// UpdateMailingList is the resolver for the updateMailingList field. // UpdateMailingList is the resolver for the updateMailingList field.
func (r *mutationResolver) UpdateMailingList(ctx context.Context, input types.UpdateMailingListInput) (*types.UpdateMailingListPayload, error) { func (r *mutationResolver) UpdateMailingList(ctx context.Context, input types.UpdateMailingListInput) (*types.UpdateMailingListPayload, error) {
if _, err := r.authorize(ctx, input.ID, complianceportal.ActionMailingListUpdate); err != nil { if _, err := r.authorize(ctx, input.ID, management.ActionMailingListUpdate); err != nil {
return nil, err return nil, err
} }
@@ -234,7 +234,7 @@ func (r *mutationResolver) UpdateMailingList(ctx context.Context, input types.Up
// CreateMailingListSubscriber is the resolver for the createMailingListSubscriber field. // CreateMailingListSubscriber is the resolver for the createMailingListSubscriber field.
func (r *mutationResolver) CreateMailingListSubscriber(ctx context.Context, input types.CreateMailingListSubscriberInput) (*types.CreateMailingListSubscriberPayload, error) { func (r *mutationResolver) CreateMailingListSubscriber(ctx context.Context, input types.CreateMailingListSubscriberInput) (*types.CreateMailingListSubscriberPayload, error) {
if _, err := r.authorize(ctx, input.MailingListID, complianceportal.ActionMailingListSubscriberCreate); err != nil { if _, err := r.authorize(ctx, input.MailingListID, management.ActionMailingListSubscriberCreate); err != nil {
return nil, err return nil, err
} }
@@ -268,7 +268,7 @@ func (r *mutationResolver) CreateMailingListSubscriber(ctx context.Context, inpu
// DeleteMailingListSubscriber is the resolver for the deleteMailingListSubscriber field. // DeleteMailingListSubscriber is the resolver for the deleteMailingListSubscriber field.
func (r *mutationResolver) DeleteMailingListSubscriber(ctx context.Context, input types.DeleteMailingListSubscriberInput) (*types.DeleteMailingListSubscriberPayload, error) { func (r *mutationResolver) DeleteMailingListSubscriber(ctx context.Context, input types.DeleteMailingListSubscriberInput) (*types.DeleteMailingListSubscriberPayload, error) {
if _, err := r.authorize(ctx, input.ID, complianceportal.ActionMailingListSubscriberDelete); err != nil { if _, err := r.authorize(ctx, input.ID, management.ActionMailingListSubscriberDelete); err != nil {
return nil, err return nil, err
} }

View File

@@ -13,7 +13,7 @@ import (
"go.gearno.de/kit/log" "go.gearno.de/kit/log"
"go.probo.inc/probo/pkg/accessreview" "go.probo.inc/probo/pkg/accessreview"
"go.probo.inc/probo/pkg/agentrun" "go.probo.inc/probo/pkg/agentrun"
"go.probo.inc/probo/pkg/complianceportal" "go.probo.inc/probo/pkg/complianceportal/management"
"go.probo.inc/probo/pkg/coredata" "go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/gid" "go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/iam" "go.probo.inc/probo/pkg/iam"
@@ -1159,7 +1159,7 @@ func (r *organizationResolver) AgentRuns(ctx context.Context, obj *types.Organiz
// TrustCenter is the resolver for the trustCenter field. // TrustCenter is the resolver for the trustCenter field.
func (r *organizationResolver) TrustCenter(ctx context.Context, obj *types.Organization) (*types.TrustCenter, error) { func (r *organizationResolver) TrustCenter(ctx context.Context, obj *types.Organization) (*types.TrustCenter, error) {
scope, err := r.authorize(ctx, obj.ID, complianceportal.ActionCompliancePortalGet) scope, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalGet)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -1175,7 +1175,7 @@ func (r *organizationResolver) TrustCenter(ctx context.Context, obj *types.Organ
// TrustCenterFiles is the resolver for the trustCenterFiles field. // TrustCenterFiles is the resolver for the trustCenterFiles field.
func (r *organizationResolver) TrustCenterFiles(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrderBy[coredata.TrustCenterFileOrderField]) (*types.TrustCenterFileConnection, error) { func (r *organizationResolver) TrustCenterFiles(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrderBy[coredata.TrustCenterFileOrderField]) (*types.TrustCenterFileConnection, error) {
scope, err := r.authorize(ctx, obj.ID, complianceportal.ActionCompliancePortalFileList) scope, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalFileList)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -35,6 +35,7 @@ import (
"go.probo.inc/probo/pkg/accessreview" "go.probo.inc/probo/pkg/accessreview"
"go.probo.inc/probo/pkg/agentrun" "go.probo.inc/probo/pkg/agentrun"
"go.probo.inc/probo/pkg/baseurl" "go.probo.inc/probo/pkg/baseurl"
"go.probo.inc/probo/pkg/certmanager"
"go.probo.inc/probo/pkg/complianceportal/management" "go.probo.inc/probo/pkg/complianceportal/management"
"go.probo.inc/probo/pkg/connector" "go.probo.inc/probo/pkg/connector"
"go.probo.inc/probo/pkg/connector/provider" "go.probo.inc/probo/pkg/connector/provider"
@@ -67,6 +68,7 @@ type (
iam *iam.Service iam *iam.Service
esign *esign.Service esign *esign.Service
management *management.Service management *management.Service
certManager *certmanager.Service
accessReview *accessreview.Service accessReview *accessreview.Service
agentRun *agentrun.Service agentRun *agentrun.Service
mailman *mailman.Service mailman *mailman.Service
@@ -90,11 +92,15 @@ func (r *Resolver) newCustomDomainType(
scope coredata.Scoper, scope coredata.Scoper,
domain *coredata.CustomDomain, domain *coredata.CustomDomain,
) (*types.CustomDomain, error) { ) (*types.CustomDomain, error) {
cert, err := r.management.GetCertificate(ctx, scope, domain) var cert *coredata.Certificate
if domain != nil && domain.CertificateID != nil {
var err error
cert, err = r.certManager.Get(ctx, scope, *domain.CertificateID)
if err != nil { if err != nil {
r.logger.ErrorCtx(ctx, "cannot load certificate", log.Error(err)) r.logger.ErrorCtx(ctx, "cannot load certificate", log.Error(err))
return nil, gqlutils.Internal(ctx) return nil, gqlutils.Internal(ctx)
} }
}
return types.NewCustomDomain(domain, cert, r.customDomainCname), nil return types.NewCustomDomain(domain, cert, r.customDomainCname), nil
} }
@@ -106,6 +112,7 @@ func NewMux(
iamSvc *iam.Service, iamSvc *iam.Service,
esignSvc *esign.Service, esignSvc *esign.Service,
managementSvc *management.Service, managementSvc *management.Service,
certManagerSvc *certmanager.Service,
accessReviewSvc *accessreview.Service, accessReviewSvc *accessreview.Service,
agentRunSvc *agentrun.Service, agentRunSvc *agentrun.Service,
mailmanSvc *mailman.Service, mailmanSvc *mailman.Service,
@@ -131,6 +138,7 @@ func NewMux(
resourceAliasSvc, resourceAliasSvc,
esignSvc, esignSvc,
managementSvc, managementSvc,
certManagerSvc,
accessReviewSvc, accessReviewSvc,
agentRunSvc, agentRunSvc,
mailmanSvc, mailmanSvc,

View File

@@ -12,7 +12,6 @@ import (
"github.com/vikstrous/dataloadgen" "github.com/vikstrous/dataloadgen"
"go.gearno.de/kit/log" "go.gearno.de/kit/log"
"go.probo.inc/probo/pkg/complianceportal"
"go.probo.inc/probo/pkg/complianceportal/management" "go.probo.inc/probo/pkg/complianceportal/management"
"go.probo.inc/probo/pkg/coredata" "go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/iam" "go.probo.inc/probo/pkg/iam"
@@ -60,7 +59,7 @@ func (r *customDomainResolver) Permission(ctx context.Context, obj *types.Custom
// UpdateTrustCenter is the resolver for the updateTrustCenter field. // UpdateTrustCenter is the resolver for the updateTrustCenter field.
func (r *mutationResolver) UpdateTrustCenter(ctx context.Context, input types.UpdateTrustCenterInput) (*types.UpdateTrustCenterPayload, error) { func (r *mutationResolver) UpdateTrustCenter(ctx context.Context, input types.UpdateTrustCenterInput) (*types.UpdateTrustCenterPayload, error) {
scope, err := r.authorize(ctx, input.TrustCenterID, complianceportal.ActionCompliancePortalUpdate) scope, err := r.authorize(ctx, input.TrustCenterID, management.ActionCompliancePortalUpdate)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -95,7 +94,7 @@ func (r *mutationResolver) UpdateTrustCenter(ctx context.Context, input types.Up
// UploadTrustCenterNda is the resolver for the uploadTrustCenterNDA field. // UploadTrustCenterNda is the resolver for the uploadTrustCenterNDA field.
func (r *mutationResolver) UploadTrustCenterNda(ctx context.Context, input types.UploadTrustCenterNDAInput) (*types.UploadTrustCenterNDAPayload, error) { func (r *mutationResolver) UploadTrustCenterNda(ctx context.Context, input types.UploadTrustCenterNDAInput) (*types.UploadTrustCenterNDAPayload, error) {
scope, err := r.authorize(ctx, input.TrustCenterID, complianceportal.ActionCompliancePortalNonDisclosureAgreementUpload) scope, err := r.authorize(ctx, input.TrustCenterID, management.ActionCompliancePortalNonDisclosureAgreementUpload)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -125,7 +124,7 @@ func (r *mutationResolver) UploadTrustCenterNda(ctx context.Context, input types
// DeleteTrustCenterNda is the resolver for the deleteTrustCenterNDA field. // DeleteTrustCenterNda is the resolver for the deleteTrustCenterNDA field.
func (r *mutationResolver) DeleteTrustCenterNda(ctx context.Context, input types.DeleteTrustCenterNDAInput) (*types.DeleteTrustCenterNDAPayload, error) { func (r *mutationResolver) DeleteTrustCenterNda(ctx context.Context, input types.DeleteTrustCenterNDAInput) (*types.DeleteTrustCenterNDAPayload, error) {
scope, err := r.authorize(ctx, input.TrustCenterID, complianceportal.ActionCompliancePortalNonDisclosureAgreementDelete) scope, err := r.authorize(ctx, input.TrustCenterID, management.ActionCompliancePortalNonDisclosureAgreementDelete)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -143,7 +142,7 @@ func (r *mutationResolver) DeleteTrustCenterNda(ctx context.Context, input types
// UpdateTrustCenterBrand is the resolver for the updateTrustCenterBrand field. // UpdateTrustCenterBrand is the resolver for the updateTrustCenterBrand field.
func (r *mutationResolver) UpdateTrustCenterBrand(ctx context.Context, input types.UpdateTrustCenterBrandInput) (*types.UpdateTrustCenterBrandPayload, error) { func (r *mutationResolver) UpdateTrustCenterBrand(ctx context.Context, input types.UpdateTrustCenterBrandInput) (*types.UpdateTrustCenterBrandPayload, error) {
scope, err := r.authorize(ctx, input.TrustCenterID, complianceportal.ActionCompliancePortalUpdate) scope, err := r.authorize(ctx, input.TrustCenterID, management.ActionCompliancePortalUpdate)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -204,7 +203,7 @@ func (r *mutationResolver) UpdateTrustCenterBrand(ctx context.Context, input typ
// UpdateTrustCenterAccess is the resolver for the updateTrustCenterAccess field. // UpdateTrustCenterAccess is the resolver for the updateTrustCenterAccess field.
func (r *mutationResolver) UpdateTrustCenterAccess(ctx context.Context, input types.UpdateTrustCenterAccessInput) (*types.UpdateTrustCenterAccessPayload, error) { func (r *mutationResolver) UpdateTrustCenterAccess(ctx context.Context, input types.UpdateTrustCenterAccessInput) (*types.UpdateTrustCenterAccessPayload, error) {
scope, err := r.authorize(ctx, input.ID, complianceportal.ActionCompliancePortalAccessUpdate) scope, err := r.authorize(ctx, input.ID, management.ActionCompliancePortalAccessUpdate)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -262,7 +261,7 @@ func (r *mutationResolver) UpdateTrustCenterAccess(ctx context.Context, input ty
// DeleteTrustCenterAccess is the resolver for the deleteTrustCenterAccess field. // DeleteTrustCenterAccess is the resolver for the deleteTrustCenterAccess field.
func (r *mutationResolver) DeleteTrustCenterAccess(ctx context.Context, input types.DeleteTrustCenterAccessInput) (*types.DeleteTrustCenterAccessPayload, error) { func (r *mutationResolver) DeleteTrustCenterAccess(ctx context.Context, input types.DeleteTrustCenterAccessInput) (*types.DeleteTrustCenterAccessPayload, error) {
scope, err := r.authorize(ctx, input.ID, complianceportal.ActionCompliancePortalAccessDelete) scope, err := r.authorize(ctx, input.ID, management.ActionCompliancePortalAccessDelete)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -279,7 +278,7 @@ func (r *mutationResolver) DeleteTrustCenterAccess(ctx context.Context, input ty
// CreateTrustCenterReference is the resolver for the createTrustCenterReference field. // CreateTrustCenterReference is the resolver for the createTrustCenterReference field.
func (r *mutationResolver) CreateTrustCenterReference(ctx context.Context, input types.CreateTrustCenterReferenceInput) (*types.CreateTrustCenterReferencePayload, error) { func (r *mutationResolver) CreateTrustCenterReference(ctx context.Context, input types.CreateTrustCenterReferenceInput) (*types.CreateTrustCenterReferencePayload, error) {
scope, err := r.authorize(ctx, input.TrustCenterID, complianceportal.ActionCompliancePortalReferenceCreate) scope, err := r.authorize(ctx, input.TrustCenterID, management.ActionCompliancePortalReferenceCreate)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -316,7 +315,7 @@ func (r *mutationResolver) CreateTrustCenterReference(ctx context.Context, input
// UpdateTrustCenterReference is the resolver for the updateTrustCenterReference field. // UpdateTrustCenterReference is the resolver for the updateTrustCenterReference field.
func (r *mutationResolver) UpdateTrustCenterReference(ctx context.Context, input types.UpdateTrustCenterReferenceInput) (*types.UpdateTrustCenterReferencePayload, error) { func (r *mutationResolver) UpdateTrustCenterReference(ctx context.Context, input types.UpdateTrustCenterReferenceInput) (*types.UpdateTrustCenterReferencePayload, error) {
scope, err := r.authorize(ctx, input.ID, complianceportal.ActionCompliancePortalReferenceUpdate) scope, err := r.authorize(ctx, input.ID, management.ActionCompliancePortalReferenceUpdate)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -356,7 +355,7 @@ func (r *mutationResolver) UpdateTrustCenterReference(ctx context.Context, input
// DeleteTrustCenterReference is the resolver for the deleteTrustCenterReference field. // DeleteTrustCenterReference is the resolver for the deleteTrustCenterReference field.
func (r *mutationResolver) DeleteTrustCenterReference(ctx context.Context, input types.DeleteTrustCenterReferenceInput) (*types.DeleteTrustCenterReferencePayload, error) { func (r *mutationResolver) DeleteTrustCenterReference(ctx context.Context, input types.DeleteTrustCenterReferenceInput) (*types.DeleteTrustCenterReferencePayload, error) {
scope, err := r.authorize(ctx, input.ID, complianceportal.ActionCompliancePortalReferenceDelete) scope, err := r.authorize(ctx, input.ID, management.ActionCompliancePortalReferenceDelete)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -373,7 +372,7 @@ func (r *mutationResolver) DeleteTrustCenterReference(ctx context.Context, input
// CreateComplianceFramework is the resolver for the createComplianceFramework field. // CreateComplianceFramework is the resolver for the createComplianceFramework field.
func (r *mutationResolver) CreateComplianceFramework(ctx context.Context, input types.CreateComplianceFrameworkInput) (*types.CreateComplianceFrameworkPayload, error) { func (r *mutationResolver) CreateComplianceFramework(ctx context.Context, input types.CreateComplianceFrameworkInput) (*types.CreateComplianceFrameworkPayload, error) {
scope, err := r.authorize(ctx, input.TrustCenterID, complianceportal.ActionComplianceFrameworkCreate) scope, err := r.authorize(ctx, input.TrustCenterID, management.ActionComplianceFrameworkCreate)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -402,7 +401,7 @@ func (r *mutationResolver) CreateComplianceFramework(ctx context.Context, input
// UpdateComplianceFramework is the resolver for the updateComplianceFramework field. // UpdateComplianceFramework is the resolver for the updateComplianceFramework field.
func (r *mutationResolver) UpdateComplianceFramework(ctx context.Context, input types.UpdateComplianceFrameworkInput) (*types.UpdateComplianceFrameworkPayload, error) { func (r *mutationResolver) UpdateComplianceFramework(ctx context.Context, input types.UpdateComplianceFrameworkInput) (*types.UpdateComplianceFrameworkPayload, error) {
scope, err := r.authorize(ctx, input.ID, complianceportal.ActionComplianceFrameworkUpdateRank) scope, err := r.authorize(ctx, input.ID, management.ActionComplianceFrameworkUpdateRank)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -428,7 +427,7 @@ func (r *mutationResolver) UpdateComplianceFramework(ctx context.Context, input
// DeleteComplianceFramework is the resolver for the deleteComplianceFramework field. // DeleteComplianceFramework is the resolver for the deleteComplianceFramework field.
func (r *mutationResolver) DeleteComplianceFramework(ctx context.Context, input types.DeleteComplianceFrameworkInput) (*types.DeleteComplianceFrameworkPayload, error) { func (r *mutationResolver) DeleteComplianceFramework(ctx context.Context, input types.DeleteComplianceFrameworkInput) (*types.DeleteComplianceFrameworkPayload, error) {
scope, err := r.authorize(ctx, input.ID, complianceportal.ActionComplianceFrameworkDelete) scope, err := r.authorize(ctx, input.ID, management.ActionComplianceFrameworkDelete)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -455,7 +454,7 @@ func (r *mutationResolver) DeleteComplianceFramework(ctx context.Context, input
// CreateComplianceCustomLink is the resolver for the createComplianceCustomLink field. // CreateComplianceCustomLink is the resolver for the createComplianceCustomLink field.
func (r *mutationResolver) CreateComplianceCustomLink(ctx context.Context, input types.CreateComplianceCustomLinkInput) (*types.CreateComplianceCustomLinkPayload, error) { func (r *mutationResolver) CreateComplianceCustomLink(ctx context.Context, input types.CreateComplianceCustomLinkInput) (*types.CreateComplianceCustomLinkPayload, error) {
scope, err := r.authorize(ctx, input.TrustCenterID, complianceportal.ActionComplianceCustomLinkCreate) scope, err := r.authorize(ctx, input.TrustCenterID, management.ActionComplianceCustomLinkCreate)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -485,7 +484,7 @@ func (r *mutationResolver) CreateComplianceCustomLink(ctx context.Context, input
// UpdateComplianceCustomLink is the resolver for the updateComplianceCustomLink field. // UpdateComplianceCustomLink is the resolver for the updateComplianceCustomLink field.
func (r *mutationResolver) UpdateComplianceCustomLink(ctx context.Context, input types.UpdateComplianceCustomLinkInput) (*types.UpdateComplianceCustomLinkPayload, error) { func (r *mutationResolver) UpdateComplianceCustomLink(ctx context.Context, input types.UpdateComplianceCustomLinkInput) (*types.UpdateComplianceCustomLinkPayload, error) {
scope, err := r.authorize(ctx, input.ID, complianceportal.ActionComplianceCustomLinkUpdate) scope, err := r.authorize(ctx, input.ID, management.ActionComplianceCustomLinkUpdate)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -513,7 +512,7 @@ func (r *mutationResolver) UpdateComplianceCustomLink(ctx context.Context, input
// DeleteComplianceCustomLink is the resolver for the deleteComplianceCustomLink field. // DeleteComplianceCustomLink is the resolver for the deleteComplianceCustomLink field.
func (r *mutationResolver) DeleteComplianceCustomLink(ctx context.Context, input types.DeleteComplianceCustomLinkInput) (*types.DeleteComplianceCustomLinkPayload, error) { func (r *mutationResolver) DeleteComplianceCustomLink(ctx context.Context, input types.DeleteComplianceCustomLinkInput) (*types.DeleteComplianceCustomLinkPayload, error) {
scope, err := r.authorize(ctx, input.ID, complianceportal.ActionComplianceCustomLinkDelete) scope, err := r.authorize(ctx, input.ID, management.ActionComplianceCustomLinkDelete)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -535,7 +534,7 @@ func (r *mutationResolver) DeleteComplianceCustomLink(ctx context.Context, input
// CreateTrustCenterFile is the resolver for the createTrustCenterFile field. // CreateTrustCenterFile is the resolver for the createTrustCenterFile field.
func (r *mutationResolver) CreateTrustCenterFile(ctx context.Context, input types.CreateTrustCenterFileInput) (*types.CreateTrustCenterFilePayload, error) { func (r *mutationResolver) CreateTrustCenterFile(ctx context.Context, input types.CreateTrustCenterFileInput) (*types.CreateTrustCenterFilePayload, error) {
scope, err := r.authorize(ctx, input.OrganizationID, complianceportal.ActionCompliancePortalFileCreate) scope, err := r.authorize(ctx, input.OrganizationID, management.ActionCompliancePortalFileCreate)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -572,7 +571,7 @@ func (r *mutationResolver) CreateTrustCenterFile(ctx context.Context, input type
// UpdateTrustCenterFile is the resolver for the updateTrustCenterFile field. // UpdateTrustCenterFile is the resolver for the updateTrustCenterFile field.
func (r *mutationResolver) UpdateTrustCenterFile(ctx context.Context, input types.UpdateTrustCenterFileInput) (*types.UpdateTrustCenterFilePayload, error) { func (r *mutationResolver) UpdateTrustCenterFile(ctx context.Context, input types.UpdateTrustCenterFileInput) (*types.UpdateTrustCenterFilePayload, error) {
scope, err := r.authorize(ctx, input.ID, complianceportal.ActionCompliancePortalFileUpdate) scope, err := r.authorize(ctx, input.ID, management.ActionCompliancePortalFileUpdate)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -603,7 +602,7 @@ func (r *mutationResolver) UpdateTrustCenterFile(ctx context.Context, input type
// GetTrustCenterFile is the resolver for the getTrustCenterFile field. // GetTrustCenterFile is the resolver for the getTrustCenterFile field.
func (r *mutationResolver) GetTrustCenterFile(ctx context.Context, input types.GetTrustCenterFileInput) (*types.GetTrustCenterFilePayload, error) { func (r *mutationResolver) GetTrustCenterFile(ctx context.Context, input types.GetTrustCenterFileInput) (*types.GetTrustCenterFilePayload, error) {
scope, err := r.authorize(ctx, input.ID, complianceportal.ActionCompliancePortalFileGet) scope, err := r.authorize(ctx, input.ID, management.ActionCompliancePortalFileGet)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -621,7 +620,7 @@ func (r *mutationResolver) GetTrustCenterFile(ctx context.Context, input types.G
// DeleteTrustCenterFile is the resolver for the deleteTrustCenterFile field. // DeleteTrustCenterFile is the resolver for the deleteTrustCenterFile field.
func (r *mutationResolver) DeleteTrustCenterFile(ctx context.Context, input types.DeleteTrustCenterFileInput) (*types.DeleteTrustCenterFilePayload, error) { func (r *mutationResolver) DeleteTrustCenterFile(ctx context.Context, input types.DeleteTrustCenterFileInput) (*types.DeleteTrustCenterFilePayload, error) {
scope, err := r.authorize(ctx, input.ID, complianceportal.ActionCompliancePortalFileDelete) scope, err := r.authorize(ctx, input.ID, management.ActionCompliancePortalFileDelete)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -638,7 +637,7 @@ func (r *mutationResolver) DeleteTrustCenterFile(ctx context.Context, input type
// CreateCustomDomain is the resolver for the createCustomDomain field. // CreateCustomDomain is the resolver for the createCustomDomain field.
func (r *mutationResolver) CreateCustomDomain(ctx context.Context, input types.CreateCustomDomainInput) (*types.CreateCustomDomainPayload, error) { func (r *mutationResolver) CreateCustomDomain(ctx context.Context, input types.CreateCustomDomainInput) (*types.CreateCustomDomainPayload, error) {
scope, err := r.authorize(ctx, input.TrustCenterID, complianceportal.ActionCustomDomainCreate) scope, err := r.authorize(ctx, input.TrustCenterID, management.ActionCustomDomainCreate)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -674,13 +673,13 @@ func (r *mutationResolver) CreateCustomDomain(ctx context.Context, input types.C
// DeleteCustomDomain is the resolver for the deleteCustomDomain field. // DeleteCustomDomain is the resolver for the deleteCustomDomain field.
func (r *mutationResolver) DeleteCustomDomain(ctx context.Context, input types.DeleteCustomDomainInput) (*types.DeleteCustomDomainPayload, error) { func (r *mutationResolver) DeleteCustomDomain(ctx context.Context, input types.DeleteCustomDomainInput) (*types.DeleteCustomDomainPayload, error) {
scope, err := r.authorize(ctx, input.CustomDomainID, complianceportal.ActionCustomDomainDelete) scope, err := r.authorize(ctx, input.CustomDomainID, management.ActionCustomDomainDelete)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if err := r.management.RemoveCustomDomain(ctx, scope, input.CustomDomainID); err != nil { if err := r.management.RemoveCustomDomain(ctx, scope, input.CustomDomainID); err != nil {
if errors.Is(err, complianceportal.ErrCustomDomainManaged) { if errors.Is(err, management.ErrCustomDomainManaged) {
return nil, gqlutils.Conflictf(ctx, "managed domain cannot be deleted") return nil, gqlutils.Conflictf(ctx, "managed domain cannot be deleted")
} }
@@ -696,7 +695,7 @@ func (r *mutationResolver) DeleteCustomDomain(ctx context.Context, input types.D
// Logo is the resolver for the logo field. // Logo is the resolver for the logo field.
func (r *trustCenterResolver) Logo(ctx context.Context, obj *types.TrustCenter) (*types.File, error) { func (r *trustCenterResolver) Logo(ctx context.Context, obj *types.TrustCenter) (*types.File, error) {
if _, err := r.authorize(ctx, obj.ID, complianceportal.ActionCompliancePortalGet); err != nil { if _, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalGet); err != nil {
return nil, err return nil, err
} }
@@ -709,7 +708,7 @@ func (r *trustCenterResolver) Logo(ctx context.Context, obj *types.TrustCenter)
// DarkLogo is the resolver for the darkLogo field. // DarkLogo is the resolver for the darkLogo field.
func (r *trustCenterResolver) DarkLogo(ctx context.Context, obj *types.TrustCenter) (*types.File, error) { func (r *trustCenterResolver) DarkLogo(ctx context.Context, obj *types.TrustCenter) (*types.File, error) {
if _, err := r.authorize(ctx, obj.ID, complianceportal.ActionCompliancePortalGet); err != nil { if _, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalGet); err != nil {
return nil, err return nil, err
} }
@@ -722,7 +721,7 @@ func (r *trustCenterResolver) DarkLogo(ctx context.Context, obj *types.TrustCent
// Nda is the resolver for the nda field. // Nda is the resolver for the nda field.
func (r *trustCenterResolver) Nda(ctx context.Context, obj *types.TrustCenter) (*types.File, error) { func (r *trustCenterResolver) Nda(ctx context.Context, obj *types.TrustCenter) (*types.File, error) {
hasPermission, err := r.Resolver.Permission(ctx, obj, complianceportal.ActionCompliancePortalGetNda) hasPermission, err := r.Resolver.Permission(ctx, obj, management.ActionCompliancePortalGetNda)
if err != nil { if err != nil {
r.logger.ErrorCtx(ctx, "cannot authorize", log.Error(err)) r.logger.ErrorCtx(ctx, "cannot authorize", log.Error(err))
return nil, gqlutils.Internal(ctx) return nil, gqlutils.Internal(ctx)
@@ -764,7 +763,7 @@ func (r *trustCenterResolver) Organization(ctx context.Context, obj *types.Trust
// Accesses is the resolver for the accesses field. // Accesses is the resolver for the accesses field.
func (r *trustCenterResolver) Accesses(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrderBy[coredata.TrustCenterAccessOrderField]) (*types.TrustCenterAccessConnection, error) { func (r *trustCenterResolver) Accesses(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrderBy[coredata.TrustCenterAccessOrderField]) (*types.TrustCenterAccessConnection, error) {
scope, err := r.authorize(ctx, obj.ID, complianceportal.ActionCompliancePortalAccessList) scope, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalAccessList)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -794,7 +793,7 @@ func (r *trustCenterResolver) Accesses(ctx context.Context, obj *types.TrustCent
// References is the resolver for the references field. // References is the resolver for the references field.
func (r *trustCenterResolver) References(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrderBy[coredata.TrustCenterReferenceOrderField]) (*types.TrustCenterReferenceConnection, error) { func (r *trustCenterResolver) References(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrderBy[coredata.TrustCenterReferenceOrderField]) (*types.TrustCenterReferenceConnection, error) {
scope, err := r.authorize(ctx, obj.ID, complianceportal.ActionCompliancePortalReferenceList) scope, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalReferenceList)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -824,7 +823,7 @@ func (r *trustCenterResolver) References(ctx context.Context, obj *types.TrustCe
// ComplianceFrameworks is the resolver for the complianceFrameworks field. // ComplianceFrameworks is the resolver for the complianceFrameworks field.
func (r *trustCenterResolver) ComplianceFrameworks(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrderBy[coredata.ComplianceFrameworkOrderField]) (*types.ComplianceFrameworkConnection, error) { func (r *trustCenterResolver) ComplianceFrameworks(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrderBy[coredata.ComplianceFrameworkOrderField]) (*types.ComplianceFrameworkConnection, error) {
scope, err := r.authorize(ctx, obj.ID, complianceportal.ActionComplianceFrameworkList) scope, err := r.authorize(ctx, obj.ID, management.ActionComplianceFrameworkList)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -854,7 +853,7 @@ func (r *trustCenterResolver) ComplianceFrameworks(ctx context.Context, obj *typ
// CustomLinks is the resolver for the customLinks field. // CustomLinks is the resolver for the customLinks field.
func (r *trustCenterResolver) CustomLinks(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrderBy[coredata.ComplianceCustomLinkOrderField]) (*types.ComplianceCustomLinkConnection, error) { func (r *trustCenterResolver) CustomLinks(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrderBy[coredata.ComplianceCustomLinkOrderField]) (*types.ComplianceCustomLinkConnection, error) {
scope, err := r.authorize(ctx, obj.ID, complianceportal.ActionComplianceCustomLinkList) scope, err := r.authorize(ctx, obj.ID, management.ActionComplianceCustomLinkList)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -884,7 +883,7 @@ func (r *trustCenterResolver) CustomLinks(ctx context.Context, obj *types.TrustC
// MailingList is the resolver for the mailingList field. // MailingList is the resolver for the mailingList field.
func (r *trustCenterResolver) MailingList(ctx context.Context, obj *types.TrustCenter) (*types.MailingList, error) { func (r *trustCenterResolver) MailingList(ctx context.Context, obj *types.TrustCenter) (*types.MailingList, error) {
scope, err := r.authorize(ctx, obj.ID, complianceportal.ActionMailingListSubscriberList) scope, err := r.authorize(ctx, obj.ID, management.ActionMailingListSubscriberList)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -908,7 +907,7 @@ func (r *trustCenterResolver) MailingList(ctx context.Context, obj *types.TrustC
// DefaultDomain is the resolver for the defaultDomain field. // DefaultDomain is the resolver for the defaultDomain field.
func (r *trustCenterResolver) DefaultDomain(ctx context.Context, obj *types.TrustCenter) (*types.CustomDomain, error) { func (r *trustCenterResolver) DefaultDomain(ctx context.Context, obj *types.TrustCenter) (*types.CustomDomain, error) {
scope, err := r.authorize(ctx, obj.ID, complianceportal.ActionCustomDomainGet) scope, err := r.authorize(ctx, obj.ID, management.ActionCustomDomainGet)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -928,7 +927,7 @@ func (r *trustCenterResolver) DefaultDomain(ctx context.Context, obj *types.Trus
// CustomDomain is the resolver for the customDomain field. // CustomDomain is the resolver for the customDomain field.
func (r *trustCenterResolver) CustomDomain(ctx context.Context, obj *types.TrustCenter) (*types.CustomDomain, error) { func (r *trustCenterResolver) CustomDomain(ctx context.Context, obj *types.TrustCenter) (*types.CustomDomain, error) {
scope, err := r.authorize(ctx, obj.ID, complianceportal.ActionCustomDomainGet) scope, err := r.authorize(ctx, obj.ID, management.ActionCustomDomainGet)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -948,7 +947,7 @@ func (r *trustCenterResolver) CustomDomain(ctx context.Context, obj *types.Trust
// PublicURL is the resolver for the publicUrl field. // PublicURL is the resolver for the publicUrl field.
func (r *trustCenterResolver) PublicURL(ctx context.Context, obj *types.TrustCenter) (string, error) { func (r *trustCenterResolver) PublicURL(ctx context.Context, obj *types.TrustCenter) (string, error) {
scope, err := r.authorize(ctx, obj.ID, complianceportal.ActionCompliancePortalGet) scope, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalGet)
if err != nil { if err != nil {
return "", err return "", err
} }
@@ -969,7 +968,7 @@ func (r *trustCenterResolver) Permission(ctx context.Context, obj *types.TrustCe
// NdaSignature is the resolver for the ndaSignature field. // NdaSignature is the resolver for the ndaSignature field.
func (r *trustCenterAccessResolver) NdaSignature(ctx context.Context, obj *types.TrustCenterAccess) (*types.ElectronicSignature, error) { func (r *trustCenterAccessResolver) NdaSignature(ctx context.Context, obj *types.TrustCenterAccess) (*types.ElectronicSignature, error) {
scope, err := r.authorize(ctx, obj.ID, complianceportal.ActionCompliancePortalAccessGet) scope, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalAccessGet)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -993,7 +992,7 @@ func (r *trustCenterAccessResolver) NdaSignature(ctx context.Context, obj *types
// PendingRequestCount is the resolver for the pendingRequestCount field. // PendingRequestCount is the resolver for the pendingRequestCount field.
func (r *trustCenterAccessResolver) PendingRequestCount(ctx context.Context, obj *types.TrustCenterAccess) (int, error) { func (r *trustCenterAccessResolver) PendingRequestCount(ctx context.Context, obj *types.TrustCenterAccess) (int, error) {
scope, err := r.authorize(ctx, obj.ID, complianceportal.ActionCompliancePortalAccessGet) scope, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalAccessGet)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@@ -1009,7 +1008,7 @@ func (r *trustCenterAccessResolver) PendingRequestCount(ctx context.Context, obj
// ActiveCount is the resolver for the activeCount field. // ActiveCount is the resolver for the activeCount field.
func (r *trustCenterAccessResolver) ActiveCount(ctx context.Context, obj *types.TrustCenterAccess) (int, error) { func (r *trustCenterAccessResolver) ActiveCount(ctx context.Context, obj *types.TrustCenterAccess) (int, error) {
scope, err := r.authorize(ctx, obj.ID, complianceportal.ActionCompliancePortalAccessGet) scope, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalAccessGet)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@@ -1045,7 +1044,7 @@ func (r *trustCenterAccessResolver) Profile(ctx context.Context, obj *types.Trus
// AvailableDocumentAccesses is the resolver for the availableDocumentAccesses field. // AvailableDocumentAccesses is the resolver for the availableDocumentAccesses field.
func (r *trustCenterAccessResolver) AvailableDocumentAccesses(ctx context.Context, obj *types.TrustCenterAccess, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrderBy[coredata.TrustCenterDocumentAccessOrderField]) (*types.TrustCenterDocumentAccessConnection, error) { func (r *trustCenterAccessResolver) AvailableDocumentAccesses(ctx context.Context, obj *types.TrustCenterAccess, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrderBy[coredata.TrustCenterDocumentAccessOrderField]) (*types.TrustCenterDocumentAccessConnection, error) {
scope, err := r.authorize(ctx, obj.ID, complianceportal.ActionCompliancePortalAccessGet) scope, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalAccessGet)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -1156,7 +1155,7 @@ func (r *trustCenterDocumentAccessResolver) Audit(ctx context.Context, obj *type
// TrustCenterFile is the resolver for the trustCenterFile field. // TrustCenterFile is the resolver for the trustCenterFile field.
func (r *trustCenterDocumentAccessResolver) TrustCenterFile(ctx context.Context, obj *types.TrustCenterDocumentAccess) (*types.TrustCenterFile, error) { func (r *trustCenterDocumentAccessResolver) TrustCenterFile(ctx context.Context, obj *types.TrustCenterDocumentAccess) (*types.TrustCenterFile, error) {
scope, err := r.authorize(ctx, obj.TrustCenterAccessID, complianceportal.ActionCompliancePortalFileGet) scope, err := r.authorize(ctx, obj.TrustCenterAccessID, management.ActionCompliancePortalFileGet)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -1176,7 +1175,7 @@ func (r *trustCenterDocumentAccessResolver) TrustCenterFile(ctx context.Context,
// TotalCount is the resolver for the totalCount field. // TotalCount is the resolver for the totalCount field.
func (r *trustCenterDocumentAccessConnectionResolver) TotalCount(ctx context.Context, obj *types.TrustCenterDocumentAccessConnection) (int, error) { func (r *trustCenterDocumentAccessConnectionResolver) TotalCount(ctx context.Context, obj *types.TrustCenterDocumentAccessConnection) (int, error) {
scope, err := r.authorize(ctx, obj.ParentID, complianceportal.ActionCompliancePortalDocumentAccessList) scope, err := r.authorize(ctx, obj.ParentID, management.ActionCompliancePortalDocumentAccessList)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@@ -1192,7 +1191,7 @@ func (r *trustCenterDocumentAccessConnectionResolver) TotalCount(ctx context.Con
// File is the resolver for the file field. // File is the resolver for the file field.
func (r *trustCenterFileResolver) File(ctx context.Context, obj *types.TrustCenterFile) (*types.File, error) { func (r *trustCenterFileResolver) File(ctx context.Context, obj *types.TrustCenterFile) (*types.File, error) {
if _, err := r.authorize(ctx, obj.ID, complianceportal.ActionCompliancePortalFileGetFileUrl); err != nil { if _, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalFileGetFileUrl); err != nil {
return nil, err return nil, err
} }
@@ -1243,7 +1242,7 @@ func (r *trustCenterFileResolver) Permission(ctx context.Context, obj *types.Tru
// TotalCount is the resolver for the totalCount field. // TotalCount is the resolver for the totalCount field.
func (r *trustCenterFileConnectionResolver) TotalCount(ctx context.Context, obj *types.TrustCenterFileConnection) (int, error) { func (r *trustCenterFileConnectionResolver) TotalCount(ctx context.Context, obj *types.TrustCenterFileConnection) (int, error) {
scope, err := r.authorize(ctx, obj.ParentID, complianceportal.ActionCompliancePortalFileList) scope, err := r.authorize(ctx, obj.ParentID, management.ActionCompliancePortalFileList)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@@ -1259,7 +1258,7 @@ func (r *trustCenterFileConnectionResolver) TotalCount(ctx context.Context, obj
// Logo is the resolver for the logo field. // Logo is the resolver for the logo field.
func (r *trustCenterReferenceResolver) Logo(ctx context.Context, obj *types.TrustCenterReference) (*types.File, error) { func (r *trustCenterReferenceResolver) Logo(ctx context.Context, obj *types.TrustCenterReference) (*types.File, error) {
if _, err := r.authorize(ctx, obj.ID, complianceportal.ActionCompliancePortalReferenceGetLogoUrl); err != nil { if _, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalReferenceGetLogoUrl); err != nil {
return nil, err return nil, err
} }
@@ -1273,7 +1272,7 @@ func (r *trustCenterReferenceResolver) Permission(ctx context.Context, obj *type
// TotalCount is the resolver for the totalCount field. // TotalCount is the resolver for the totalCount field.
func (r *trustCenterReferenceConnectionResolver) TotalCount(ctx context.Context, obj *types.TrustCenterReferenceConnection) (int, error) { func (r *trustCenterReferenceConnectionResolver) TotalCount(ctx context.Context, obj *types.TrustCenterReferenceConnection) (int, error) {
scope, err := r.authorize(ctx, obj.ParentID, complianceportal.ActionCompliancePortalReferenceList) scope, err := r.authorize(ctx, obj.ParentID, management.ActionCompliancePortalReferenceList)
if err != nil { if err != nil {
return 0, err return 0, err
} }

View File

@@ -31,6 +31,7 @@ import (
"go.gearno.de/kit/log" "go.gearno.de/kit/log"
"go.probo.inc/probo/pkg/accessreview" "go.probo.inc/probo/pkg/accessreview"
"go.probo.inc/probo/pkg/baseurl" "go.probo.inc/probo/pkg/baseurl"
"go.probo.inc/probo/pkg/certmanager"
"go.probo.inc/probo/pkg/complianceportal/management" "go.probo.inc/probo/pkg/complianceportal/management"
"go.probo.inc/probo/pkg/cookiebanner" "go.probo.inc/probo/pkg/cookiebanner"
"go.probo.inc/probo/pkg/coredata" "go.probo.inc/probo/pkg/coredata"
@@ -49,6 +50,7 @@ import (
type Resolver struct { type Resolver struct {
proboSvc *probo.Service proboSvc *probo.Service
management *management.Service management *management.Service
certManager *certmanager.Service
resourceAlias *resourcealias.Service resourceAlias *resourcealias.Service
thirdPartySvc *thirdparty.Service thirdPartySvc *thirdparty.Service
iamSvc *iam.Service iamSvc *iam.Service

View File

@@ -14,7 +14,6 @@ import (
"github.com/modelcontextprotocol/go-sdk/mcp" "github.com/modelcontextprotocol/go-sdk/mcp"
"go.gearno.de/kit/log" "go.gearno.de/kit/log"
"go.probo.inc/probo/pkg/accessreview" "go.probo.inc/probo/pkg/accessreview"
"go.probo.inc/probo/pkg/complianceportal"
"go.probo.inc/probo/pkg/complianceportal/management" "go.probo.inc/probo/pkg/complianceportal/management"
"go.probo.inc/probo/pkg/cookiebanner" "go.probo.inc/probo/pkg/cookiebanner"
"go.probo.inc/probo/pkg/coredata" "go.probo.inc/probo/pkg/coredata"
@@ -4884,7 +4883,7 @@ func (r *Resolver) DeleteRightsRequestTool(ctx context.Context, req *mcp.CallToo
// GetTrustCenterTool handles the getTrustCenter tool // GetTrustCenterTool handles the getTrustCenter tool
// Get the trust center for an organization // Get the trust center for an organization
func (r *Resolver) GetTrustCenterTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetTrustCenterInput) (*mcp.CallToolResult, types.GetTrustCenterOutput, error) { func (r *Resolver) GetTrustCenterTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetTrustCenterInput) (*mcp.CallToolResult, types.GetTrustCenterOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, complianceportal.ActionCompliancePortalGet) scope, err := r.Authorize(ctx, input.OrganizationID, management.ActionCompliancePortalGet)
if err != nil { if err != nil {
return nil, types.GetTrustCenterOutput{}, err return nil, types.GetTrustCenterOutput{}, err
} }
@@ -4931,7 +4930,7 @@ func (r *Resolver) GetTrustCenterTool(ctx context.Context, req *mcp.CallToolRequ
// UpdateTrustCenterTool handles the updateTrustCenter tool // UpdateTrustCenterTool handles the updateTrustCenter tool
// Update the trust center settings // Update the trust center settings
func (r *Resolver) UpdateTrustCenterTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateTrustCenterInput) (*mcp.CallToolResult, types.UpdateTrustCenterOutput, error) { func (r *Resolver) UpdateTrustCenterTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateTrustCenterInput) (*mcp.CallToolResult, types.UpdateTrustCenterOutput, error) {
scope, err := r.Authorize(ctx, input.TrustCenterID, complianceportal.ActionCompliancePortalUpdate) scope, err := r.Authorize(ctx, input.TrustCenterID, management.ActionCompliancePortalUpdate)
if err != nil { if err != nil {
return nil, types.UpdateTrustCenterOutput{}, err return nil, types.UpdateTrustCenterOutput{}, err
} }
@@ -4969,7 +4968,7 @@ func (r *Resolver) UpdateTrustCenterTool(ctx context.Context, req *mcp.CallToolR
// ListTrustCenterReferencesTool handles the listTrustCenterReferences tool // ListTrustCenterReferencesTool handles the listTrustCenterReferences tool
// List all references for a trust center // List all references for a trust center
func (r *Resolver) ListTrustCenterReferencesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListTrustCenterReferencesInput) (*mcp.CallToolResult, types.ListTrustCenterReferencesOutput, error) { func (r *Resolver) ListTrustCenterReferencesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListTrustCenterReferencesInput) (*mcp.CallToolResult, types.ListTrustCenterReferencesOutput, error) {
scope, err := r.Authorize(ctx, input.TrustCenterID, complianceportal.ActionCompliancePortalReferenceList) scope, err := r.Authorize(ctx, input.TrustCenterID, management.ActionCompliancePortalReferenceList)
if err != nil { if err != nil {
return nil, types.ListTrustCenterReferencesOutput{}, err return nil, types.ListTrustCenterReferencesOutput{}, err
} }
@@ -5015,7 +5014,7 @@ func (r *Resolver) ListTrustCenterReferencesTool(ctx context.Context, req *mcp.C
// AddTrustCenterReferenceTool handles the addTrustCenterReference tool // AddTrustCenterReferenceTool handles the addTrustCenterReference tool
// Add a new reference to the trust center // Add a new reference to the trust center
func (r *Resolver) AddTrustCenterReferenceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddTrustCenterReferenceInput) (*mcp.CallToolResult, types.AddTrustCenterReferenceOutput, error) { func (r *Resolver) AddTrustCenterReferenceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddTrustCenterReferenceInput) (*mcp.CallToolResult, types.AddTrustCenterReferenceOutput, error) {
scope, err := r.Authorize(ctx, input.TrustCenterID, complianceportal.ActionCompliancePortalReferenceCreate) scope, err := r.Authorize(ctx, input.TrustCenterID, management.ActionCompliancePortalReferenceCreate)
if err != nil { if err != nil {
return nil, types.AddTrustCenterReferenceOutput{}, err return nil, types.AddTrustCenterReferenceOutput{}, err
} }
@@ -5046,7 +5045,7 @@ func (r *Resolver) AddTrustCenterReferenceTool(ctx context.Context, req *mcp.Cal
// UpdateTrustCenterReferenceTool handles the updateTrustCenterReference tool // UpdateTrustCenterReferenceTool handles the updateTrustCenterReference tool
// Update a trust center reference // Update a trust center reference
func (r *Resolver) UpdateTrustCenterReferenceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateTrustCenterReferenceInput) (*mcp.CallToolResult, types.UpdateTrustCenterReferenceOutput, error) { func (r *Resolver) UpdateTrustCenterReferenceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateTrustCenterReferenceInput) (*mcp.CallToolResult, types.UpdateTrustCenterReferenceOutput, error) {
scope, err := r.Authorize(ctx, input.ID, complianceportal.ActionCompliancePortalReferenceUpdate) scope, err := r.Authorize(ctx, input.ID, management.ActionCompliancePortalReferenceUpdate)
if err != nil { if err != nil {
return nil, types.UpdateTrustCenterReferenceOutput{}, err return nil, types.UpdateTrustCenterReferenceOutput{}, err
} }
@@ -5081,7 +5080,7 @@ func (r *Resolver) UpdateTrustCenterReferenceTool(ctx context.Context, req *mcp.
// DeleteTrustCenterReferenceTool handles the deleteTrustCenterReference tool // DeleteTrustCenterReferenceTool handles the deleteTrustCenterReference tool
// Delete a trust center reference // Delete a trust center reference
func (r *Resolver) DeleteTrustCenterReferenceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteTrustCenterReferenceInput) (*mcp.CallToolResult, types.DeleteTrustCenterReferenceOutput, error) { func (r *Resolver) DeleteTrustCenterReferenceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteTrustCenterReferenceInput) (*mcp.CallToolResult, types.DeleteTrustCenterReferenceOutput, error) {
scope, err := r.Authorize(ctx, input.ID, complianceportal.ActionCompliancePortalReferenceDelete) scope, err := r.Authorize(ctx, input.ID, management.ActionCompliancePortalReferenceDelete)
if err != nil { if err != nil {
return nil, types.DeleteTrustCenterReferenceOutput{}, err return nil, types.DeleteTrustCenterReferenceOutput{}, err
} }
@@ -5099,7 +5098,7 @@ func (r *Resolver) DeleteTrustCenterReferenceTool(ctx context.Context, req *mcp.
// ListTrustCenterFilesTool handles the listTrustCenterFiles tool // ListTrustCenterFilesTool handles the listTrustCenterFiles tool
// List all files for the trust center // List all files for the trust center
func (r *Resolver) ListTrustCenterFilesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListTrustCenterFilesInput) (*mcp.CallToolResult, types.ListTrustCenterFilesOutput, error) { func (r *Resolver) ListTrustCenterFilesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListTrustCenterFilesInput) (*mcp.CallToolResult, types.ListTrustCenterFilesOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, complianceportal.ActionCompliancePortalFileList) scope, err := r.Authorize(ctx, input.OrganizationID, management.ActionCompliancePortalFileList)
if err != nil { if err != nil {
return nil, types.ListTrustCenterFilesOutput{}, err return nil, types.ListTrustCenterFilesOutput{}, err
} }
@@ -5142,7 +5141,7 @@ func (r *Resolver) ListTrustCenterFilesTool(ctx context.Context, req *mcp.CallTo
// DeleteTrustCenterFileTool handles the deleteTrustCenterFile tool // DeleteTrustCenterFileTool handles the deleteTrustCenterFile tool
// Delete a trust center file // Delete a trust center file
func (r *Resolver) DeleteTrustCenterFileTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteTrustCenterFileInput) (*mcp.CallToolResult, types.DeleteTrustCenterFileOutput, error) { func (r *Resolver) DeleteTrustCenterFileTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteTrustCenterFileInput) (*mcp.CallToolResult, types.DeleteTrustCenterFileOutput, error) {
scope, err := r.Authorize(ctx, input.ID, complianceportal.ActionCompliancePortalFileDelete) scope, err := r.Authorize(ctx, input.ID, management.ActionCompliancePortalFileDelete)
if err != nil { if err != nil {
return nil, types.DeleteTrustCenterFileOutput{}, err return nil, types.DeleteTrustCenterFileOutput{}, err
} }
@@ -5160,7 +5159,7 @@ func (r *Resolver) DeleteTrustCenterFileTool(ctx context.Context, req *mcp.CallT
// ListComplianceCustomLinksTool handles the listComplianceCustomLinks tool // ListComplianceCustomLinksTool handles the listComplianceCustomLinks tool
// List all custom links for a trust center // List all custom links for a trust center
func (r *Resolver) ListComplianceCustomLinksTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListComplianceCustomLinksInput) (*mcp.CallToolResult, types.ListComplianceCustomLinksOutput, error) { func (r *Resolver) ListComplianceCustomLinksTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListComplianceCustomLinksInput) (*mcp.CallToolResult, types.ListComplianceCustomLinksOutput, error) {
scope, err := r.Authorize(ctx, input.TrustCenterID, complianceportal.ActionComplianceCustomLinkList) scope, err := r.Authorize(ctx, input.TrustCenterID, management.ActionComplianceCustomLinkList)
if err != nil { if err != nil {
return nil, types.ListComplianceCustomLinksOutput{}, err return nil, types.ListComplianceCustomLinksOutput{}, err
} }
@@ -5192,7 +5191,7 @@ func (r *Resolver) ListComplianceCustomLinksTool(ctx context.Context, req *mcp.C
// AddComplianceCustomLinkTool handles the addComplianceCustomLink tool // AddComplianceCustomLinkTool handles the addComplianceCustomLink tool
// Add a new custom link to the trust center // Add a new custom link to the trust center
func (r *Resolver) AddComplianceCustomLinkTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddComplianceCustomLinkInput) (*mcp.CallToolResult, types.AddComplianceCustomLinkOutput, error) { func (r *Resolver) AddComplianceCustomLinkTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddComplianceCustomLinkInput) (*mcp.CallToolResult, types.AddComplianceCustomLinkOutput, error) {
scope, err := r.Authorize(ctx, input.TrustCenterID, complianceportal.ActionComplianceCustomLinkCreate) scope, err := r.Authorize(ctx, input.TrustCenterID, management.ActionComplianceCustomLinkCreate)
if err != nil { if err != nil {
return nil, types.AddComplianceCustomLinkOutput{}, err return nil, types.AddComplianceCustomLinkOutput{}, err
} }
@@ -5217,7 +5216,7 @@ func (r *Resolver) AddComplianceCustomLinkTool(ctx context.Context, req *mcp.Cal
// UpdateComplianceCustomLinkTool handles the updateComplianceCustomLink tool // UpdateComplianceCustomLinkTool handles the updateComplianceCustomLink tool
// Update a compliance custom link // Update a compliance custom link
func (r *Resolver) UpdateComplianceCustomLinkTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateComplianceCustomLinkInput) (*mcp.CallToolResult, types.UpdateComplianceCustomLinkOutput, error) { func (r *Resolver) UpdateComplianceCustomLinkTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateComplianceCustomLinkInput) (*mcp.CallToolResult, types.UpdateComplianceCustomLinkOutput, error) {
scope, err := r.Authorize(ctx, input.ID, complianceportal.ActionComplianceCustomLinkUpdate) scope, err := r.Authorize(ctx, input.ID, management.ActionComplianceCustomLinkUpdate)
if err != nil { if err != nil {
return nil, types.UpdateComplianceCustomLinkOutput{}, err return nil, types.UpdateComplianceCustomLinkOutput{}, err
} }
@@ -5251,7 +5250,7 @@ func (r *Resolver) UpdateComplianceCustomLinkTool(ctx context.Context, req *mcp.
// DeleteComplianceCustomLinkTool handles the deleteComplianceCustomLink tool // DeleteComplianceCustomLinkTool handles the deleteComplianceCustomLink tool
// Delete a compliance custom link // Delete a compliance custom link
func (r *Resolver) DeleteComplianceCustomLinkTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteComplianceCustomLinkInput) (*mcp.CallToolResult, types.DeleteComplianceCustomLinkOutput, error) { func (r *Resolver) DeleteComplianceCustomLinkTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteComplianceCustomLinkInput) (*mcp.CallToolResult, types.DeleteComplianceCustomLinkOutput, error) {
scope, err := r.Authorize(ctx, input.ID, complianceportal.ActionComplianceCustomLinkDelete) scope, err := r.Authorize(ctx, input.ID, management.ActionComplianceCustomLinkDelete)
if err != nil { if err != nil {
return nil, types.DeleteComplianceCustomLinkOutput{}, err return nil, types.DeleteComplianceCustomLinkOutput{}, err
} }
@@ -5274,7 +5273,7 @@ func (r *Resolver) DeleteComplianceCustomLinkTool(ctx context.Context, req *mcp.
// CreateCustomDomainTool handles the createCustomDomain tool // CreateCustomDomainTool handles the createCustomDomain tool
// Create a custom domain for a compliance page // Create a custom domain for a compliance page
func (r *Resolver) CreateCustomDomainTool(ctx context.Context, req *mcp.CallToolRequest, input *types.CreateCustomDomainInput) (*mcp.CallToolResult, types.CreateCustomDomainOutput, error) { func (r *Resolver) CreateCustomDomainTool(ctx context.Context, req *mcp.CallToolRequest, input *types.CreateCustomDomainInput) (*mcp.CallToolResult, types.CreateCustomDomainOutput, error) {
scope, err := r.Authorize(ctx, input.TrustCenterID, complianceportal.ActionCustomDomainCreate) scope, err := r.Authorize(ctx, input.TrustCenterID, management.ActionCustomDomainCreate)
if err != nil { if err != nil {
return nil, types.CreateCustomDomainOutput{}, err return nil, types.CreateCustomDomainOutput{}, err
} }
@@ -5288,10 +5287,13 @@ func (r *Resolver) CreateCustomDomainTool(ctx context.Context, req *mcp.CallTool
return nil, types.CreateCustomDomainOutput{}, fmt.Errorf("cannot create custom domain: %w", err) return nil, types.CreateCustomDomainOutput{}, fmt.Errorf("cannot create custom domain: %w", err)
} }
cert, err := r.management.GetCertificate(ctx, scope, domain) var cert *coredata.Certificate
if domain.CertificateID != nil {
cert, err = r.certManager.Get(ctx, scope, *domain.CertificateID)
if err != nil { if err != nil {
return nil, types.CreateCustomDomainOutput{}, fmt.Errorf("cannot load certificate: %w", err) return nil, types.CreateCustomDomainOutput{}, fmt.Errorf("cannot load certificate: %w", err)
} }
}
return nil, types.CreateCustomDomainOutput{CustomDomain: types.NewCustomDomain(domain, cert)}, nil return nil, types.CreateCustomDomainOutput{CustomDomain: types.NewCustomDomain(domain, cert)}, nil
} }
@@ -5299,7 +5301,7 @@ func (r *Resolver) CreateCustomDomainTool(ctx context.Context, req *mcp.CallTool
// DeleteCustomDomainTool handles the deleteCustomDomain tool // DeleteCustomDomainTool handles the deleteCustomDomain tool
// Delete the custom domain of a compliance page // Delete the custom domain of a compliance page
func (r *Resolver) DeleteCustomDomainTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteCustomDomainInput) (*mcp.CallToolResult, types.DeleteCustomDomainOutput, error) { func (r *Resolver) DeleteCustomDomainTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteCustomDomainInput) (*mcp.CallToolResult, types.DeleteCustomDomainOutput, error) {
scope, err := r.Authorize(ctx, input.TrustCenterID, complianceportal.ActionCustomDomainDelete) scope, err := r.Authorize(ctx, input.TrustCenterID, management.ActionCustomDomainDelete)
if err != nil { if err != nil {
return nil, types.DeleteCustomDomainOutput{}, err return nil, types.DeleteCustomDomainOutput{}, err
} }
@@ -5313,10 +5315,13 @@ func (r *Resolver) DeleteCustomDomainTool(ctx context.Context, req *mcp.CallTool
return nil, types.DeleteCustomDomainOutput{}, fmt.Errorf("compliance page has no custom domain") return nil, types.DeleteCustomDomainOutput{}, fmt.Errorf("compliance page has no custom domain")
} }
cert, err := r.management.GetCertificate(ctx, scope, domain) var cert *coredata.Certificate
if domain.CertificateID != nil {
cert, err = r.certManager.Get(ctx, scope, *domain.CertificateID)
if err != nil { if err != nil {
return nil, types.DeleteCustomDomainOutput{}, fmt.Errorf("cannot load certificate: %w", err) return nil, types.DeleteCustomDomainOutput{}, fmt.Errorf("cannot load certificate: %w", err)
} }
}
deletedDomain := types.NewCustomDomain(domain, cert) deletedDomain := types.NewCustomDomain(domain, cert)

View File

@@ -29,6 +29,7 @@ import (
mcpgenmcp "go.probo.inc/mcpgen/mcp" mcpgenmcp "go.probo.inc/mcpgen/mcp"
"go.probo.inc/probo/pkg/accessreview" "go.probo.inc/probo/pkg/accessreview"
"go.probo.inc/probo/pkg/baseurl" "go.probo.inc/probo/pkg/baseurl"
"go.probo.inc/probo/pkg/certmanager"
"go.probo.inc/probo/pkg/complianceportal/management" "go.probo.inc/probo/pkg/complianceportal/management"
"go.probo.inc/probo/pkg/cookiebanner" "go.probo.inc/probo/pkg/cookiebanner"
"go.probo.inc/probo/pkg/filemanager" "go.probo.inc/probo/pkg/filemanager"
@@ -46,6 +47,7 @@ func NewMux(
logger *log.Logger, logger *log.Logger,
proboSvc *probo.Service, proboSvc *probo.Service,
managementSvc *management.Service, managementSvc *management.Service,
certManagerSvc *certmanager.Service,
resourceAliasSvc *resourcealias.Service, resourceAliasSvc *resourcealias.Service,
thirdPartySvc *thirdparty.Service, thirdPartySvc *thirdparty.Service,
iamSvc *iam.Service, iamSvc *iam.Service,
@@ -63,6 +65,7 @@ func NewMux(
resolver := &Resolver{ resolver := &Resolver{
proboSvc: proboSvc, proboSvc: proboSvc,
management: managementSvc, management: managementSvc,
certManager: certManagerSvc,
resourceAlias: resourceAliasSvc, resourceAlias: resourceAliasSvc,
thirdPartySvc: thirdPartySvc, thirdPartySvc: thirdPartySvc,
iamSvc: iamSvc, iamSvc: iamSvc,

View File

@@ -29,6 +29,7 @@ import (
"go.probo.inc/probo/pkg/accessreview" "go.probo.inc/probo/pkg/accessreview"
"go.probo.inc/probo/pkg/agentrun" "go.probo.inc/probo/pkg/agentrun"
"go.probo.inc/probo/pkg/baseurl" "go.probo.inc/probo/pkg/baseurl"
"go.probo.inc/probo/pkg/certmanager"
"go.probo.inc/probo/pkg/complianceportal/management" "go.probo.inc/probo/pkg/complianceportal/management"
"go.probo.inc/probo/pkg/complianceportal/visitor" "go.probo.inc/probo/pkg/complianceportal/visitor"
"go.probo.inc/probo/pkg/connector" "go.probo.inc/probo/pkg/connector"
@@ -64,6 +65,7 @@ type Config struct {
Trust *visitor.Service Trust *visitor.Service
ESign *esign.Service ESign *esign.Service
Management *management.Service Management *management.Service
CertManager *certmanager.Service
AccessReview *accessreview.Service AccessReview *accessreview.Service
AgentRun *agentrun.Service AgentRun *agentrun.Service
Slack *slack.Service Slack *slack.Service
@@ -105,6 +107,7 @@ func NewServer(cfg Config) (*Server, error) {
Trust: cfg.Trust, Trust: cfg.Trust,
ESign: cfg.ESign, ESign: cfg.ESign,
Management: cfg.Management, Management: cfg.Management,
CertManager: cfg.CertManager,
AccessReview: cfg.AccessReview, AccessReview: cfg.AccessReview,
AgentRun: cfg.AgentRun, AgentRun: cfg.AgentRun,
Slack: cfg.Slack, Slack: cfg.Slack,

View File

@@ -23,6 +23,8 @@ package slug
import ( import (
"regexp" "regexp"
"strings" "strings"
"go.probo.inc/probo/pkg/crypto/rand"
) )
var ( var (
@@ -42,3 +44,14 @@ func Make(s string) string {
return s return s
} }
func MakeWithEntropy(s string) string {
base := Make(s)
suffix := rand.MustHexString(4)
if base == "" {
return suffix
}
return base + "-" + suffix
}

View File

@@ -22,30 +22,73 @@ package slug
import ( import (
"testing" "testing"
"github.com/stretchr/testify/assert"
) )
func TestMake(t *testing.T) { func TestMake(t *testing.T) {
t.Parallel()
tests := []struct { tests := []struct {
name string
input string input string
expected string expected string
}{ }{
{"Hello World", "hello-world"}, {name: "hello world", input: "Hello World", expected: "hello-world"},
{"This is a test", "this-is-a-test"}, {name: "this is a test", input: "This is a test", expected: "this-is-a-test"},
{"Special characters: !@#$%^&*()", "special-characters"}, {name: "special characters", input: "Special characters: !@#$%^&*()", expected: "special-characters"},
{"Multiple---Hyphens", "multiple-hyphens"}, {name: "multiple hyphens", input: "Multiple---Hyphens", expected: "multiple-hyphens"},
{"-Trim-Hyphens-", "trim-hyphens"}, {name: "trim hyphens", input: "-Trim-Hyphens-", expected: "trim-hyphens"},
{"123 Numbers", "123-numbers"}, {name: "numbers", input: "123 Numbers", expected: "123-numbers"},
{" Spaces ", "spaces"}, {name: "spaces", input: " Spaces ", expected: "spaces"},
{"", ""}, {name: "empty", input: "", expected: ""},
{"UPPERCASE", "uppercase"}, {name: "uppercase", input: "UPPERCASE", expected: "uppercase"},
{"under_score", "under-score"}, {name: "underscore", input: "under_score", expected: "under-score"},
{"dots.and.more.dots", "dotsandmoredots"}, {name: "dots", input: "dots.and.more.dots", expected: "dotsandmoredots"},
} }
for _, test := range tests { for _, tt := range tests {
slug := Make(test.input) t.Run(
if slug != test.expected { tt.name,
t.Errorf("Slug(%q) = %q; expected %q", test.input, slug, test.expected) func(t *testing.T) {
} t.Parallel()
assert.Equal(t, tt.expected, Make(tt.input))
},
)
} }
} }
func TestMakeWithEntropy(t *testing.T) {
t.Parallel()
t.Run(
"empty input returns hex only",
func(t *testing.T) {
t.Parallel()
assert.Regexp(t, `^[0-9a-f]{8}$`, MakeWithEntropy(""))
},
)
t.Run(
"non-empty input returns base with hex suffix",
func(t *testing.T) {
t.Parallel()
got := MakeWithEntropy("Hello World")
assert.Regexp(t, `^hello-world-[0-9a-f]{8}$`, got)
},
)
t.Run(
"successive calls differ",
func(t *testing.T) {
t.Parallel()
first := MakeWithEntropy("Acme Corp")
second := MakeWithEntropy("Acme Corp")
assert.NotEqual(t, first, second, "MakeWithEntropy should produce distinct slugs")
},
)
}