Files
probo/pkg/server/api/console/v1/v1_resolver.go
Sacha Al Himdani cd13f9aa00 Change registry names
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2025-12-19 19:39:44 +01:00

8000 lines
284 KiB
Go

package console_v1
// This file will be automatically regenerated based on the schema, any resolver
// implementations
// will be copied through when generating and any unknown code will be moved to the end.
// Code generated by github.com/99designs/gqlgen version v0.17.84
import (
"context"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"strings"
"time"
pgx "github.com/jackc/pgx/v5"
"github.com/vektah/gqlparser/v2/gqlerror"
"go.probo.inc/probo/pkg/auth"
"go.probo.inc/probo/pkg/authz"
"go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/mail"
"go.probo.inc/probo/pkg/page"
"go.probo.inc/probo/pkg/probo"
"go.probo.inc/probo/pkg/server/api/console/v1/schema"
"go.probo.inc/probo/pkg/server/api/console/v1/types"
serverauth "go.probo.inc/probo/pkg/server/auth"
"go.probo.inc/probo/pkg/server/gqlutils"
)
// Owner is the resolver for the owner field.
func (r *assetResolver) Owner(ctx context.Context, obj *types.Asset) (*types.People, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetOwner)
prb := r.ProboService(ctx, obj.ID.TenantID())
asset, err := prb.Assets.Get(ctx, obj.ID)
if err != nil {
var errNotFound *coredata.ErrAssetNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get asset: %w", err))
}
owner, err := prb.Peoples.Get(ctx, asset.OwnerID)
if err != nil {
var errNotFound *coredata.ErrPeopleNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get owner: %w", err))
}
return types.NewPeople(owner), nil
}
// Vendors is the resolver for the vendors field.
func (r *assetResolver) Vendors(ctx context.Context, obj *types.Asset, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.VendorOrderBy) (*types.VendorConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListVendors)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.VendorOrderField]{
Field: coredata.VendorOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.VendorOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := prb.Vendors.ListForAssetID(ctx, obj.ID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list asset vendors: %w", err))
}
return types.NewVendorConnection(page, r, obj.ID), nil
}
// AssetType is the resolver for the assetType field.
func (r *assetResolver) AssetType(ctx context.Context, obj *types.Asset) (coredata.AssetType, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetAssetType)
prb := r.ProboService(ctx, obj.ID.TenantID())
asset, err := prb.Assets.Get(ctx, obj.ID)
if err != nil {
var errNotFound *coredata.ErrAssetNotFound
if errors.As(err, &errNotFound) {
return "", errNotFound
}
panic(fmt.Errorf("cannot get asset: %w", err))
}
return asset.AssetType, nil
}
// Organization is the resolver for the organization field.
func (r *assetResolver) Organization(ctx context.Context, obj *types.Asset) (*types.Organization, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetOrganization)
prb := r.ProboService(ctx, obj.ID.TenantID())
asset, err := prb.Assets.Get(ctx, obj.ID)
if err != nil {
var errNotFound *coredata.ErrAuditNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot load audit: %w", err))
}
org, err := prb.Organizations.Get(ctx, asset.OrganizationID)
if err != nil {
var errNotFound *coredata.ErrOrganizationNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get organization: %w", err))
}
return types.NewOrganization(org), nil
}
// TotalCount is the resolver for the totalCount field.
func (r *assetConnectionResolver) TotalCount(ctx context.Context, obj *types.AssetConnection) (int, error) {
r.MustBeAuthorized(ctx, obj.ParentID, authz.ActionTotalCount)
prb := r.ProboService(ctx, obj.ParentID.TenantID())
switch obj.Resolver.(type) {
case *organizationResolver:
assetFilter := coredata.NewAssetFilter(nil)
if obj.Filter != nil {
assetFilter = coredata.NewAssetFilter(&obj.Filter.SnapshotID)
}
count, err := prb.Assets.CountForOrganizationID(ctx, obj.ParentID, assetFilter)
if err != nil {
panic(fmt.Errorf("cannot count assets: %w", err))
}
return count, nil
}
panic(fmt.Errorf("unsupported resolver: %T", obj.Resolver))
}
// Organization is the resolver for the organization field.
func (r *auditResolver) Organization(ctx context.Context, obj *types.Audit) (*types.Organization, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetOrganization)
prb := r.ProboService(ctx, obj.ID.TenantID())
audit, err := prb.Audits.Get(ctx, obj.ID)
if err != nil {
var errNotFound *coredata.ErrAuditNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot load audit: %w", err))
}
organization, err := prb.Organizations.Get(ctx, audit.OrganizationID)
if err != nil {
var errNotFound *coredata.ErrOrganizationNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot load organization: %w", err))
}
return types.NewOrganization(organization), nil
}
// Framework is the resolver for the framework field.
func (r *auditResolver) Framework(ctx context.Context, obj *types.Audit) (*types.Framework, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetFramework)
prb := r.ProboService(ctx, obj.ID.TenantID())
audit, err := prb.Audits.Get(ctx, obj.ID)
if err != nil {
var errNotFound *coredata.ErrAuditNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot load audit: %w", err))
}
framework, err := prb.Frameworks.Get(ctx, audit.FrameworkID)
if err != nil {
var errNotFound *coredata.ErrFrameworkNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot load framework: %w", err))
}
return types.NewFramework(framework), nil
}
// Report is the resolver for the report field.
func (r *auditResolver) Report(ctx context.Context, obj *types.Audit) (*types.Report, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionReport)
prb := r.ProboService(ctx, obj.ID.TenantID())
audit, err := prb.Audits.Get(ctx, obj.ID)
if err != nil {
var errNotFound *coredata.ErrAuditNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot load audit: %w", err))
}
if audit.ReportID == nil {
return nil, nil
}
report, err := prb.Reports.Get(ctx, *audit.ReportID)
if err != nil {
panic(fmt.Errorf("cannot load report: %w", err))
}
return types.NewReport(report), nil
}
// ReportURL is the resolver for the reportUrl field.
func (r *auditResolver) ReportURL(ctx context.Context, obj *types.Audit) (*string, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionReportUrl)
if obj.Report == nil {
return nil, nil
}
prb := r.ProboService(ctx, obj.ID.TenantID())
url, err := prb.Audits.GenerateReportURL(ctx, obj.ID, 15*time.Minute)
if err != nil {
panic(fmt.Errorf("cannot generate report URL: %w", err))
}
return url, nil
}
// Controls is the resolver for the controls field.
func (r *auditResolver) Controls(ctx context.Context, obj *types.Audit, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ControlOrderBy, filter *types.ControlFilter) (*types.ControlConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListControls)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.ControlOrderField]{
Field: coredata.ControlOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.ControlOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
var controlFilter = coredata.NewControlFilter(nil)
if filter != nil {
controlFilter = coredata.NewControlFilter(filter.Query)
}
page, err := prb.Controls.ListForAuditID(ctx, obj.ID, cursor, controlFilter)
if err != nil {
panic(fmt.Errorf("cannot list audit controls: %w", err))
}
return types.NewControlConnection(page, r, obj.ID, controlFilter), nil
}
// TotalCount is the resolver for the totalCount field.
func (r *auditConnectionResolver) TotalCount(ctx context.Context, obj *types.AuditConnection) (int, error) {
r.MustBeAuthorized(ctx, obj.ParentID, authz.ActionTotalCount)
prb := r.ProboService(ctx, obj.ParentID.TenantID())
count, err := prb.Audits.CountForOrganizationID(ctx, obj.ParentID)
if err != nil {
panic(fmt.Errorf("cannot count audits: %w", err))
}
return count, nil
}
// Organization is the resolver for the organization field.
func (r *continualImprovementResolver) Organization(ctx context.Context, obj *types.ContinualImprovement) (*types.Organization, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetOrganization)
prb := r.ProboService(ctx, obj.ID.TenantID())
continualImprovement, err := prb.ContinualImprovements.Get(ctx, obj.ID)
if err != nil {
panic(fmt.Errorf("cannot get continual improvement: %w", err))
}
organization, err := prb.Organizations.Get(ctx, continualImprovement.OrganizationID)
if err != nil {
var errNotFound *coredata.ErrOrganizationNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get continual improvement organization: %w", err))
}
return types.NewOrganization(organization), nil
}
// Owner is the resolver for the owner field.
func (r *continualImprovementResolver) Owner(ctx context.Context, obj *types.ContinualImprovement) (*types.People, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetOwner)
prb := r.ProboService(ctx, obj.ID.TenantID())
continualImprovement, err := prb.ContinualImprovements.Get(ctx, obj.ID)
if err != nil {
panic(fmt.Errorf("cannot get continual improvement: %w", err))
}
people, err := prb.Peoples.Get(ctx, continualImprovement.OwnerID)
if err != nil {
var errNotFound *coredata.ErrPeopleNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get continual improvement owner: %w", err))
}
return types.NewPeople(people), nil
}
// TotalCount is the resolver for the totalCount field.
func (r *continualImprovementConnectionResolver) TotalCount(ctx context.Context, obj *types.ContinualImprovementConnection) (int, error) {
r.MustBeAuthorized(ctx, obj.ParentID, authz.ActionTotalCount)
prb := r.ProboService(ctx, obj.ParentID.TenantID())
switch obj.Resolver.(type) {
case *organizationResolver:
continualImprovementFilter := coredata.NewContinualImprovementFilter(nil)
if obj.Filter != nil {
continualImprovementFilter = coredata.NewContinualImprovementFilter(&obj.Filter.SnapshotID)
}
count, err := prb.ContinualImprovements.CountByOrganizationID(ctx, obj.ParentID, continualImprovementFilter)
if err != nil {
panic(fmt.Errorf("cannot count continual improvements: %w", err))
}
return count, nil
}
panic(fmt.Errorf("unsupported resolver: %T", obj.Resolver))
}
// Framework is the resolver for the framework field.
func (r *controlResolver) Framework(ctx context.Context, obj *types.Control) (*types.Framework, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetFramework)
prb := r.ProboService(ctx, obj.ID.TenantID())
control, err := prb.Controls.Get(ctx, obj.ID)
if err != nil {
var errNotFound *coredata.ErrControlNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get control: %w", err))
}
framework, err := prb.Frameworks.Get(ctx, control.FrameworkID)
if err != nil {
var errNotFound *coredata.ErrFrameworkNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get framework: %w", err))
}
return types.NewFramework(framework), nil
}
// Measures is the resolver for the measures field.
func (r *controlResolver) Measures(ctx context.Context, obj *types.Control, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.MeasureOrderBy, filter *types.MeasureFilter) (*types.MeasureConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListMeasures)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.MeasureOrderField]{
Field: coredata.MeasureOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.MeasureOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
var measureFilter = coredata.NewMeasureFilter(nil, nil)
if filter != nil {
measureFilter = coredata.NewMeasureFilter(filter.Query, filter.State)
}
page, err := prb.Measures.ListForControlID(ctx, obj.ID, cursor, measureFilter)
if err != nil {
panic(fmt.Errorf("cannot list measures: %w", err))
}
return types.NewMeasureConnection(page, r, obj.ID, measureFilter), nil
}
// Documents is the resolver for the documents field.
func (r *controlResolver) Documents(ctx context.Context, obj *types.Control, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentOrderBy, filter *types.DocumentFilter) (*types.DocumentConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListDocuments)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.DocumentOrderField]{
Field: coredata.DocumentOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.DocumentOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
var documentFilter = coredata.NewDocumentFilter(nil)
if filter != nil {
documentFilter = coredata.NewDocumentFilter(filter.Query)
}
page, err := prb.Documents.ListForControlID(ctx, obj.ID, cursor, documentFilter)
if err != nil {
panic(fmt.Errorf("cannot list documents: %w", err))
}
return types.NewDocumentConnection(page, r, obj.ID, documentFilter), nil
}
// Audits is the resolver for the audits field.
func (r *controlResolver) Audits(ctx context.Context, obj *types.Control, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.AuditOrderBy) (*types.AuditConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListAudits)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.AuditOrderField]{
Field: coredata.AuditOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.AuditOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := prb.Audits.ListForControlID(ctx, obj.ID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list control audits: %w", err))
}
return types.NewAuditConnection(page, r, obj.ID), nil
}
// Snapshots is the resolver for the snapshots field.
func (r *controlResolver) Snapshots(ctx context.Context, obj *types.Control, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.SnapshotOrderBy) (*types.SnapshotConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListSnapshots)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.SnapshotOrderField]{
Field: coredata.SnapshotOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.SnapshotOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := prb.Snapshots.ListForControlID(ctx, obj.ID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list control snapshots: %w", err))
}
return types.NewSnapshotConnection(page, r, obj.ID), nil
}
// TotalCount is the resolver for the totalCount field.
func (r *controlConnectionResolver) TotalCount(ctx context.Context, obj *types.ControlConnection) (int, error) {
prb := r.ProboService(ctx, obj.ParentID.TenantID())
r.MustBeAuthorized(ctx, obj.ParentID, authz.ActionTotalCount)
switch obj.Resolver.(type) {
case *organizationResolver:
count, err := prb.Controls.CountForOrganizationID(ctx, obj.ParentID, obj.Filters)
if err != nil {
panic(fmt.Errorf("cannot count controls: %w", err))
}
return count, nil
case *frameworkResolver:
count, err := prb.Controls.CountForFrameworkID(ctx, obj.ParentID, obj.Filters)
if err != nil {
panic(fmt.Errorf("cannot count controls: %w", err))
}
return count, nil
case *documentResolver:
count, err := prb.Controls.CountForDocumentID(ctx, obj.ParentID, obj.Filters)
if err != nil {
panic(fmt.Errorf("cannot count controls: %w", err))
}
return count, nil
case *measureResolver:
count, err := prb.Controls.CountForMeasureID(ctx, obj.ParentID, obj.Filters)
if err != nil {
panic(fmt.Errorf("cannot count controls: %w", err))
}
return count, nil
case *riskResolver:
count, err := prb.Controls.CountForRiskID(ctx, obj.ParentID, obj.Filters)
if err != nil {
panic(fmt.Errorf("cannot count controls: %w", err))
}
return count, nil
}
panic(fmt.Errorf("unsupported resolver: %T", obj.Resolver))
}
// ProcessingActivity is the resolver for the processingActivity field.
func (r *dataProtectionImpactAssessmentResolver) ProcessingActivity(ctx context.Context, obj *types.DataProtectionImpactAssessment) (*types.ProcessingActivity, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGet)
prb := r.ProboService(ctx, obj.ID.TenantID())
dpia, err := prb.DataProtectionImpactAssessments.Get(ctx, obj.ID)
if err != nil {
panic(fmt.Errorf("cannot get processing activity dpia: %w", err))
}
processingActivity, err := prb.ProcessingActivities.Get(ctx, dpia.ProcessingActivityID)
if err != nil {
panic(fmt.Errorf("cannot get processing activity: %w", err))
}
return types.NewProcessingActivity(processingActivity), nil
}
// Organization is the resolver for the organization field.
func (r *dataProtectionImpactAssessmentResolver) Organization(ctx context.Context, obj *types.DataProtectionImpactAssessment) (*types.Organization, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetOrganization)
prb := r.ProboService(ctx, obj.ID.TenantID())
dpia, err := prb.DataProtectionImpactAssessments.Get(ctx, obj.ID)
if err != nil {
panic(fmt.Errorf("cannot get processing activity dpia: %w", err))
}
organization, err := prb.Organizations.Get(ctx, dpia.OrganizationID)
if err != nil {
var errNotFound *coredata.ErrOrganizationNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get organization: %w", err))
}
return types.NewOrganization(organization), nil
}
// TotalCount is the resolver for the totalCount field.
func (r *dataProtectionImpactAssessmentConnectionResolver) TotalCount(ctx context.Context, obj *types.DataProtectionImpactAssessmentConnection) (int, error) {
r.MustBeAuthorized(ctx, obj.ParentID, authz.ActionTotalCount)
prb := r.ProboService(ctx, obj.ParentID.TenantID())
switch obj.Resolver.(type) {
case *organizationResolver:
count, err := prb.DataProtectionImpactAssessments.CountForOrganizationID(ctx, obj.ParentID, obj.Filter)
if err != nil {
panic(fmt.Errorf("cannot count organization data protection impact assessments: %w", err))
}
return count, nil
}
panic(fmt.Errorf("unsupported resolver: %T", obj.Resolver))
}
// Owner is the resolver for the owner field.
func (r *datumResolver) Owner(ctx context.Context, obj *types.Datum) (*types.People, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetOwner)
prb := r.ProboService(ctx, obj.ID.TenantID())
data, err := prb.Data.Get(ctx, obj.ID)
if err != nil {
return nil, fmt.Errorf("cannot get datum: %w", err)
}
people, err := prb.Peoples.Get(ctx, data.OwnerID)
if err != nil {
var errNotFound *coredata.ErrPeopleNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
return nil, fmt.Errorf("cannot get owner: %w", err)
}
return types.NewPeople(people), nil
}
// Vendors is the resolver for the vendors field.
func (r *datumResolver) Vendors(ctx context.Context, obj *types.Datum, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.VendorOrderBy) (*types.VendorConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListVendors)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.VendorOrderField]{
Field: coredata.VendorOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.VendorOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := prb.Data.ListVendors(ctx, obj.ID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list data vendors: %w", err))
}
return types.NewVendorConnection(page, r, obj.ID), nil
}
// Organization is the resolver for the organization field.
func (r *datumResolver) Organization(ctx context.Context, obj *types.Datum) (*types.Organization, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetOrganization)
prb := r.ProboService(ctx, obj.ID.TenantID())
org, err := prb.Organizations.Get(ctx, obj.OrganizationID)
if err != nil {
var errNotFound *coredata.ErrOrganizationNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get organization: %w", err))
}
return types.NewOrganization(org), nil
}
// TotalCount is the resolver for the totalCount field.
func (r *datumConnectionResolver) TotalCount(ctx context.Context, obj *types.DatumConnection) (int, error) {
r.MustBeAuthorized(ctx, obj.ParentID, authz.ActionTotalCount)
prb := r.ProboService(ctx, obj.ParentID.TenantID())
switch obj.Resolver.(type) {
case *organizationResolver:
datumFilter := coredata.NewDatumFilter(nil)
if obj.Filter != nil {
datumFilter = coredata.NewDatumFilter(&obj.Filter.SnapshotID)
}
count, err := prb.Data.CountForOrganizationID(ctx, obj.ParentID, datumFilter)
if err != nil {
panic(fmt.Errorf("cannot count data: %w", err))
}
return count, nil
}
panic(fmt.Errorf("unsupported resolver: %T", obj.Resolver))
}
// Owner is the resolver for the owner field.
func (r *documentResolver) Owner(ctx context.Context, obj *types.Document) (*types.People, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetOwner)
prb := r.ProboService(ctx, obj.ID.TenantID())
document, err := prb.Documents.Get(ctx, obj.ID)
if err != nil {
var errNotFound *coredata.ErrDocumentNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get document: %w", err))
}
// Get the owner
owner, err := prb.Peoples.Get(ctx, document.OwnerID)
if err != nil {
var errNotFound *coredata.ErrPeopleNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get owner: %w", err))
}
return types.NewPeople(owner), nil
}
// Organization is the resolver for the organization field.
func (r *documentResolver) Organization(ctx context.Context, obj *types.Document) (*types.Organization, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetOrganization)
prb := r.ProboService(ctx, obj.ID.TenantID())
document, err := prb.Documents.Get(ctx, obj.ID)
if err != nil {
var errNotFound *coredata.ErrDocumentNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get document: %w", err))
}
organization, err := prb.Organizations.Get(ctx, document.OrganizationID)
if err != nil {
var errNotFound *coredata.ErrOrganizationNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get organization: %w", err))
}
return types.NewOrganization(organization), nil
}
// Versions is the resolver for the versions field.
func (r *documentResolver) Versions(ctx context.Context, obj *types.Document, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentVersionOrderBy, filter *types.DocumentVersionFilter) (*types.DocumentVersionConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListVersions)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.DocumentVersionOrderField]{
Field: coredata.DocumentVersionOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.DocumentVersionOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
versionFilter := coredata.NewDocumentVersionFilter()
page, err := prb.Documents.ListVersions(ctx, obj.ID, cursor, versionFilter)
if err != nil {
panic(fmt.Errorf("cannot list document versions: %w", err))
}
return types.NewDocumentVersionConnection(page), nil
}
// Controls is the resolver for the controls field.
func (r *documentResolver) Controls(ctx context.Context, obj *types.Document, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ControlOrderBy, filter *types.ControlFilter) (*types.ControlConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListControls)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.ControlOrderField]{
Field: coredata.ControlOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.ControlOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
var controlFilter = coredata.NewControlFilter(nil)
if filter != nil {
controlFilter = coredata.NewControlFilter(filter.Query)
}
page, err := prb.Controls.ListForDocumentID(ctx, obj.ID, cursor, controlFilter)
if err != nil {
panic(fmt.Errorf("cannot list document controls: %w", err))
}
return types.NewControlConnection(page, r, obj.ID, controlFilter), nil
}
// TotalCount is the resolver for the totalCount field.
func (r *documentConnectionResolver) TotalCount(ctx context.Context, obj *types.DocumentConnection) (int, error) {
r.MustBeAuthorized(ctx, obj.ParentID, authz.ActionTotalCount)
prb := r.ProboService(ctx, obj.ParentID.TenantID())
switch obj.Resolver.(type) {
case *controlResolver:
count, err := prb.Documents.CountForControlID(ctx, obj.ParentID, obj.Filters)
if err != nil {
panic(fmt.Errorf("cannot count controls: %w", err))
}
return count, nil
case *organizationResolver:
count, err := prb.Documents.CountForOrganizationID(ctx, obj.ParentID, obj.Filters)
if err != nil {
panic(fmt.Errorf("cannot count documents: %w", err))
}
return count, nil
case *riskResolver:
count, err := prb.Documents.CountForRiskID(ctx, obj.ParentID, obj.Filters)
if err != nil {
panic(fmt.Errorf("cannot count risks: %w", err))
}
return count, nil
}
panic(fmt.Errorf("unsupported resolver: %T", obj.Resolver))
}
// Document is the resolver for the document field.
func (r *documentVersionResolver) Document(ctx context.Context, obj *types.DocumentVersion) (*types.Document, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetDocument)
prb := r.ProboService(ctx, obj.ID.TenantID())
documentVersion, err := prb.Documents.GetVersion(ctx, obj.ID)
if err != nil {
panic(fmt.Errorf("cannot get document version: %w", err))
}
document, err := prb.Documents.Get(ctx, documentVersion.DocumentID)
if err != nil {
var errNotFound *coredata.ErrDocumentNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get document: %w", err))
}
return types.NewDocument(document), nil
}
// Owner is the resolver for the owner field.
func (r *documentVersionResolver) Owner(ctx context.Context, obj *types.DocumentVersion) (*types.People, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetOwner)
prb := r.ProboService(ctx, obj.ID.TenantID())
documentVersion, err := prb.Documents.GetVersion(ctx, obj.ID)
if err != nil {
panic(fmt.Errorf("cannot get document version: %w", err))
}
owner, err := prb.Peoples.Get(ctx, documentVersion.OwnerID)
if err != nil {
var errNotFound *coredata.ErrPeopleNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get owner: %w", err))
}
return types.NewPeople(owner), nil
}
// Signatures is the resolver for the signatures field.
func (r *documentVersionResolver) Signatures(ctx context.Context, obj *types.DocumentVersion, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentVersionSignatureOrder, filter *types.DocumentVersionSignatureFilter) (*types.DocumentVersionSignatureConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionSignatures)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.DocumentVersionSignatureOrderField]{
Field: coredata.DocumentVersionSignatureOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.DocumentVersionSignatureOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
var signatureStates []coredata.DocumentVersionSignatureState
if filter != nil && filter.States != nil {
signatureStates = filter.States
}
signatureFilter := coredata.NewDocumentVersionSignatureFilter(signatureStates)
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := prb.Documents.ListSignatures(ctx, obj.ID, cursor, signatureFilter)
if err != nil {
panic(fmt.Errorf("cannot list document version signatures: %w", err))
}
return types.NewDocumentVersionSignatureConnection(page), nil
}
// Signed is the resolver for the signed field.
func (r *documentVersionResolver) Signed(ctx context.Context, obj *types.DocumentVersion) (bool, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetSigned)
user := UserFromContext(ctx)
if user == nil {
panic(fmt.Errorf("user not found in context"))
}
prb := r.ProboService(ctx, obj.ID.TenantID())
signed, err := prb.Documents.IsVersionSignedByUserEmail(ctx, obj.ID, user.EmailAddress)
if err != nil {
panic(fmt.Errorf("cannot check if document version is signed: %w", err))
}
return signed, nil
}
// DocumentVersion is the resolver for the documentVersion field.
func (r *documentVersionSignatureResolver) DocumentVersion(ctx context.Context, obj *types.DocumentVersionSignature) (*types.DocumentVersion, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionDocumentVersion)
prb := r.ProboService(ctx, obj.ID.TenantID())
documentVersionSignature, err := prb.Documents.GetVersionSignature(ctx, obj.ID)
if err != nil {
panic(fmt.Errorf("cannot get document version signature: %w", err))
}
documentVersion, err := prb.Documents.GetVersion(ctx, documentVersionSignature.DocumentVersionID)
if err != nil {
panic(fmt.Errorf("cannot get document version: %w", err))
}
return types.NewDocumentVersion(documentVersion), nil
}
// SignedBy is the resolver for the signedBy field.
func (r *documentVersionSignatureResolver) SignedBy(ctx context.Context, obj *types.DocumentVersionSignature) (*types.People, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionSignedBy)
prb := r.ProboService(ctx, obj.ID.TenantID())
documentVersionSignature, err := prb.Documents.GetVersionSignature(ctx, obj.ID)
if err != nil {
panic(fmt.Errorf("cannot get document version signature: %w", err))
}
people, err := prb.Peoples.Get(ctx, documentVersionSignature.SignedBy)
if err != nil {
var errNotFound *coredata.ErrPeopleNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get people: %w", err))
}
return types.NewPeople(people), nil
}
// File is the resolver for the file field.
func (r *evidenceResolver) File(ctx context.Context, obj *types.Evidence) (*types.File, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetFile)
prb := r.ProboService(ctx, obj.ID.TenantID())
evidence, err := prb.Evidences.Get(ctx, obj.ID)
if err != nil {
panic(fmt.Errorf("cannot load evidence: %w", err))
}
if evidence.EvidenceFileId == nil {
return nil, nil
}
file, err := prb.Files.Get(ctx, *evidence.EvidenceFileId)
if err != nil {
var errNotFound *coredata.ErrFileNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot load evidence file: %w", err))
}
return types.NewFile(file), nil
}
// Task is the resolver for the task field.
func (r *evidenceResolver) Task(ctx context.Context, obj *types.Evidence) (*types.Task, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetTask)
prb := r.ProboService(ctx, obj.ID.TenantID())
evidence, err := prb.Evidences.Get(ctx, obj.ID)
if err != nil {
panic(fmt.Errorf("cannot load evidence: %w", err))
}
if evidence.TaskID == nil {
panic(fmt.Errorf("evidence is not associated with a task"))
}
task, err := prb.Tasks.Get(ctx, *evidence.TaskID)
if err != nil {
var errNotFound *coredata.ErrTaskNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot load task: %w", err))
}
return types.NewTask(task), nil
}
// Measure is the resolver for the measure field.
func (r *evidenceResolver) Measure(ctx context.Context, obj *types.Evidence) (*types.Measure, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetMeasure)
prb := r.ProboService(ctx, obj.ID.TenantID())
evidence, err := prb.Evidences.Get(ctx, obj.ID)
if err != nil {
panic(fmt.Errorf("cannot load evidence: %w", err))
}
measure, err := prb.Measures.Get(ctx, evidence.MeasureID)
if err != nil {
var errNotFound *coredata.ErrMeasureNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot load measure: %w", err))
}
return types.NewMeasure(measure), nil
}
// TotalCount is the resolver for the totalCount field.
func (r *evidenceConnectionResolver) TotalCount(ctx context.Context, obj *types.EvidenceConnection) (int, error) {
r.MustBeAuthorized(ctx, obj.ParentID, authz.ActionTotalCount)
prb := r.ProboService(ctx, obj.ParentID.TenantID())
switch obj.Resolver.(type) {
case *measureResolver:
count, err := prb.Evidences.CountForMeasureID(ctx, obj.ParentID)
if err != nil {
panic(fmt.Errorf("cannot count tasks: %w", err))
}
return count, nil
case *taskResolver:
count, err := prb.Evidences.CountForTaskID(ctx, obj.ParentID)
if err != nil {
panic(fmt.Errorf("cannot count tasks: %w", err))
}
return count, nil
}
panic(fmt.Errorf("unsupported resolver: %T", obj.Resolver))
}
// DownloadURL is the resolver for the downloadUrl field.
func (r *fileResolver) DownloadURL(ctx context.Context, obj *types.File) (string, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionDownloadUrl)
prb := r.ProboService(ctx, obj.ID.TenantID())
downloadUrl, err := prb.Files.GenerateFileTempURL(ctx, obj.ID, 60*time.Second)
if err != nil {
return "", fmt.Errorf("cannot generate download url: %w", err)
}
return downloadUrl, nil
}
// Organization is the resolver for the organization field.
func (r *frameworkResolver) Organization(ctx context.Context, obj *types.Framework) (*types.Organization, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetOrganization)
prb := r.ProboService(ctx, obj.ID.TenantID())
framework, err := prb.Frameworks.Get(ctx, obj.ID)
if err != nil {
var errNotFound *coredata.ErrFrameworkNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot load framework: %w", err))
}
organization, err := prb.Organizations.Get(ctx, framework.OrganizationID)
if err != nil {
var errNotFound *coredata.ErrOrganizationNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot load organization: %w", err))
}
return types.NewOrganization(organization), nil
}
// Controls is the resolver for the controls field.
func (r *frameworkResolver) Controls(ctx context.Context, obj *types.Framework, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ControlOrderBy, filter *types.ControlFilter) (*types.ControlConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListControls)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.ControlOrderField]{
Field: coredata.ControlOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.ControlOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
var controlFilter = coredata.NewControlFilter(nil)
if filter != nil {
controlFilter = coredata.NewControlFilter(filter.Query)
}
page, err := prb.Controls.ListForFrameworkID(ctx, obj.ID, cursor, controlFilter)
if err != nil {
panic(fmt.Errorf("cannot list controls: %w", err))
}
return types.NewControlConnection(page, r, obj.ID, controlFilter), nil
}
// LightLogoURL is the resolver for the lightLogoURL field.
func (r *frameworkResolver) LightLogoURL(ctx context.Context, obj *types.Framework) (*string, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetLogoUrl)
prb := r.ProboService(ctx, obj.ID.TenantID())
return prb.Frameworks.GenerateLightLogoURL(ctx, obj.ID, 1*time.Hour)
}
// DarkLogoURL is the resolver for the darkLogoURL field.
func (r *frameworkResolver) DarkLogoURL(ctx context.Context, obj *types.Framework) (*string, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetLogoUrl)
prb := r.ProboService(ctx, obj.ID.TenantID())
return prb.Frameworks.GenerateDarkLogoURL(ctx, obj.ID, 1*time.Hour)
}
// TotalCount is the resolver for the totalCount field.
func (r *frameworkConnectionResolver) TotalCount(ctx context.Context, obj *types.FrameworkConnection) (int, error) {
r.MustBeAuthorized(ctx, obj.ParentID, authz.ActionTotalCount)
switch obj.Resolver.(type) {
case *organizationResolver:
prb := r.ProboService(ctx, obj.ParentID.TenantID())
count, err := prb.Frameworks.CountForOrganizationID(ctx, obj.ParentID)
if err != nil {
panic(fmt.Errorf("cannot count frameworks: %w", err))
}
return count, nil
}
panic(fmt.Errorf("unsupported resolver: %T", obj.Resolver))
}
// Organization is the resolver for the organization field.
func (r *invitationResolver) Organization(ctx context.Context, obj *types.Invitation) (*types.Organization, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetOrganization)
authzSvc := r.AuthzService(ctx, obj.ID.TenantID())
organization, err := authzSvc.GetOrganizationByInvitationID(ctx, obj.ID)
if err != nil {
panic(fmt.Errorf("cannot load organization: %w", err))
}
return types.NewOrganization(organization), nil
}
// TotalCount is the resolver for the totalCount field.
func (r *invitationConnectionResolver) TotalCount(ctx context.Context, obj *types.InvitationConnection) (int, error) {
r.MustBeAuthorized(ctx, obj.ParentID, authz.ActionTotalCount)
switch obj.Resolver.(type) {
case *organizationResolver:
invitationFilter := coredata.NewInvitationFilter(nil)
if obj.Filter != nil {
invitationFilter = coredata.NewInvitationFilter(obj.Filter.Statuses)
}
authz := r.AuthzService(ctx, obj.ParentID.TenantID())
count, err := authz.CountOrganizationInvitations(ctx, obj.ParentID, invitationFilter)
if err != nil {
panic(fmt.Errorf("cannot count organization invitations: %w", err))
}
return count, nil
}
panic(fmt.Errorf("unsupported resolver: %T", obj.Resolver))
}
// Evidences is the resolver for the evidences field.
func (r *measureResolver) Evidences(ctx context.Context, obj *types.Measure, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.EvidenceOrderBy) (*types.EvidenceConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListEvidences)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.EvidenceOrderField]{
Field: coredata.EvidenceOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.EvidenceOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := prb.Evidences.ListForMeasureID(ctx, obj.ID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list measure evidences: %w", err))
}
return types.NewEvidenceConnection(page, r, obj.ID), nil
}
// Tasks is the resolver for the tasks field.
func (r *measureResolver) Tasks(ctx context.Context, obj *types.Measure, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.TaskOrderBy) (*types.TaskConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListTasks)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.TaskOrderField]{
Field: coredata.TaskOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.TaskOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := prb.Tasks.ListForMeasureID(ctx, obj.ID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list measure tasks: %w", err))
}
return types.NewTaskConnection(page, r, obj.ID), nil
}
// Risks is the resolver for the risks field.
func (r *measureResolver) Risks(ctx context.Context, obj *types.Measure, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.RiskOrderBy, filter *types.RiskFilter) (*types.RiskConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListRisks)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.RiskOrderField]{
Field: coredata.RiskOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.RiskOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
var riskFilter = coredata.NewRiskFilter(nil, nil)
if filter != nil {
riskFilter = coredata.NewRiskFilter(filter.Query, &filter.SnapshotID)
}
page, err := prb.Risks.ListForMeasureID(ctx, obj.ID, cursor, riskFilter)
if err != nil {
panic(fmt.Errorf("cannot list measure risks: %w", err))
}
return types.NewRiskConnection(page, r, obj.ID, riskFilter), nil
}
// Controls is the resolver for the controls field.
func (r *measureResolver) Controls(ctx context.Context, obj *types.Measure, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ControlOrderBy, filter *types.ControlFilter) (*types.ControlConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListControls)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.ControlOrderField]{
Field: coredata.ControlOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.ControlOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
var controlFilter = coredata.NewControlFilter(nil)
if filter != nil {
controlFilter = coredata.NewControlFilter(filter.Query)
}
page, err := prb.Controls.ListForMeasureID(ctx, obj.ID, cursor, controlFilter)
if err != nil {
panic(fmt.Errorf("cannot list measure controls: %w", err))
}
return types.NewControlConnection(page, r, obj.ID, controlFilter), nil
}
// TotalCount is the resolver for the totalCount field.
func (r *measureConnectionResolver) TotalCount(ctx context.Context, obj *types.MeasureConnection) (int, error) {
r.MustBeAuthorized(ctx, obj.ParentID, authz.ActionTotalCount)
prb := r.ProboService(ctx, obj.ParentID.TenantID())
switch obj.Resolver.(type) {
case *organizationResolver:
count, err := prb.Measures.CountForOrganizationID(ctx, obj.ParentID, obj.Filters)
if err != nil {
panic(fmt.Errorf("cannot count measures: %w", err))
}
return count, nil
case *controlResolver:
count, err := prb.Measures.CountForControlID(ctx, obj.ParentID, obj.Filters)
if err != nil {
panic(fmt.Errorf("cannot count measures: %w", err))
}
return count, nil
case *riskResolver:
count, err := prb.Measures.CountForRiskID(ctx, obj.ParentID, obj.Filters)
if err != nil {
panic(fmt.Errorf("cannot count measures: %w", err))
}
return count, nil
}
panic(fmt.Errorf("unsupported resolver: %T", obj.Resolver))
}
// Attendees is the resolver for the attendees field.
func (r *meetingResolver) Attendees(ctx context.Context, obj *types.Meeting) ([]*types.People, error) {
prb := r.ProboService(ctx, obj.ID.TenantID())
attendees, err := prb.Meetings.GetAttendees(ctx, obj.ID)
if err != nil {
panic(fmt.Errorf("cannot load meeting attendees: %w", err))
}
if len(attendees) == 0 {
return []*types.People{}, nil
}
people := make([]*types.People, len(attendees))
for i, attendee := range attendees {
people[i] = types.NewPeople(attendee)
}
return people, nil
}
// Organization is the resolver for the organization field.
func (r *meetingResolver) Organization(ctx context.Context, obj *types.Meeting) (*types.Organization, error) {
prb := r.ProboService(ctx, obj.ID.TenantID())
meeting, err := prb.Meetings.Get(ctx, obj.ID)
if err != nil {
var errNotFound *coredata.ErrMeetingNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot load meeting: %w", err))
}
organization, err := prb.Organizations.Get(ctx, meeting.OrganizationID)
if err != nil {
var errNotFound *coredata.ErrOrganizationNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot load organization: %w", err))
}
return types.NewOrganization(organization), nil
}
// TotalCount is the resolver for the totalCount field.
func (r *meetingConnectionResolver) TotalCount(ctx context.Context, obj *types.MeetingConnection) (int, error) {
prb := r.ProboService(ctx, obj.ParentID.TenantID())
switch obj.Resolver.(type) {
case *organizationResolver:
count, err := prb.Meetings.CountForOrganizationID(ctx, obj.ParentID)
if err != nil {
panic(fmt.Errorf("cannot count meetings: %w", err))
}
return count, nil
}
panic(fmt.Errorf("unsupported resolver: %T", obj.Resolver))
}
// AuthMethod is the resolver for the authMethod field.
func (r *membershipResolver) AuthMethod(ctx context.Context, obj *types.Membership) (coredata.UserAuthMethod, error) {
session := SessionFromContext(ctx)
if session == nil {
return coredata.UserAuthMethodPassword, nil
}
auth := r.AuthService(ctx, obj.OrganizationID.TenantID())
authMethod, err := auth.GetUserAuthMethod(ctx, obj.UserID, obj.OrganizationID, session)
if err != nil {
panic(fmt.Errorf("cannot get user auth method: %w", err))
}
return authMethod, nil
}
// TotalCount is the resolver for the totalCount field.
func (r *membershipConnectionResolver) TotalCount(ctx context.Context, obj *types.MembershipConnection) (int, error) {
r.MustBeAuthorized(ctx, obj.ParentID, authz.ActionTotalCount)
switch obj.Resolver.(type) {
case *organizationResolver:
authz := r.AuthzService(ctx, obj.ParentID.TenantID())
count, err := authz.CountOrganizationMemberships(ctx, obj.ParentID)
if err != nil {
panic(fmt.Errorf("cannot count organization memberships: %w", err))
}
return count, nil
}
panic(fmt.Errorf("unknown resolver type for membership connection"))
}
// CreateOrganization is the resolver for the createOrganization field.
func (r *mutationResolver) CreateOrganization(ctx context.Context, input types.CreateOrganizationInput) (*types.CreateOrganizationPayload, error) {
currentUser := UserFromContext(ctx)
currentAPIKey := UserAPIKeyFromContext(ctx)
tenantID := gid.NewTenantID()
prb := r.proboSvc.WithTenant(tenantID)
authz := r.authzSvc.WithTenant(tenantID)
organization, err := prb.Organizations.Create(
ctx,
probo.CreateOrganizationRequest{
Name: input.Name,
},
)
if err != nil {
var errAlreadyExists *coredata.ErrOrganizationAlreadyExists
if errors.As(err, &errAlreadyExists) {
return nil, gqlutils.Conflict(errAlreadyExists)
}
var errTrustCenterAlreadyExists *coredata.ErrTrustCenterAlreadyExists
if errors.As(err, &errTrustCenterAlreadyExists) {
return nil, gqlutils.Conflict(errTrustCenterAlreadyExists)
}
panic(fmt.Errorf("cannot create organization: %w", err))
}
err = authz.AddUserToOrganization(
ctx,
currentUser.ID,
organization.ID,
coredata.MembershipRoleOwner,
)
if err != nil {
panic(fmt.Errorf("cannot add user to organization: %w", err))
}
if currentAPIKey != nil {
membership, err := authz.GetMembershipByUserAndOrganizationID(ctx, currentUser.ID, organization.ID)
if err != nil {
panic(fmt.Errorf("cannot get user membership: %w", err))
}
err = r.authSvc.AddAPIKeyMembershipToOrganization(
ctx,
tenantID,
currentAPIKey.ID,
membership.ID,
organization.ID,
coredata.APIRoleFull,
)
if err != nil {
panic(fmt.Errorf("cannot add API key membership to organization: %w", err))
}
}
_, err = prb.Peoples.Create(
ctx,
probo.CreatePeopleRequest{
OrganizationID: organization.ID,
FullName: currentUser.FullName,
PrimaryEmailAddress: currentUser.EmailAddress,
AdditionalEmailAddresses: []mail.Addr{},
Kind: coredata.PeopleKindEmployee,
},
)
if err != nil {
var errAlreadyExists *coredata.ErrPeopleAlreadyExists
if errors.As(err, &errAlreadyExists) {
return nil, gqlutils.Conflict(errAlreadyExists)
}
panic(fmt.Errorf("cannot create people: %w", err))
}
// Append tenant to allowed one
access := serverauth.UserTenantAccessFromContext(ctx)
if access != nil {
access.TenantIDs = append(access.TenantIDs, organization.ID.TenantID())
}
return &types.CreateOrganizationPayload{
OrganizationEdge: types.NewOrganizationEdge(organization, coredata.OrganizationOrderFieldCreatedAt),
}, nil
}
// UpdateOrganization is the resolver for the updateOrganization field.
func (r *mutationResolver) UpdateOrganization(ctx context.Context, input types.UpdateOrganizationInput) (*types.UpdateOrganizationPayload, error) {
r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionUpdateOrganization)
prb := r.ProboService(ctx, input.OrganizationID.TenantID())
req := probo.UpdateOrganizationRequest{
ID: input.OrganizationID,
Name: input.Name,
Description: UnwrapOmittable(input.Description),
WebsiteURL: UnwrapOmittable(input.WebsiteURL),
Email: UnwrapOmittable(input.Email),
HeadquarterAddress: UnwrapOmittable(input.HeadquarterAddress),
}
if input.LogoFile != nil {
req.File = &probo.File{
Filename: input.LogoFile.Filename,
ContentType: input.LogoFile.ContentType,
Size: input.LogoFile.Size,
Content: input.LogoFile.File,
}
}
if input.HorizontalLogoFile != nil {
req.HorizontalLogoFile = &probo.File{
Filename: input.HorizontalLogoFile.Filename,
ContentType: input.HorizontalLogoFile.ContentType,
Size: input.HorizontalLogoFile.Size,
Content: input.HorizontalLogoFile.File,
}
}
organization, err := prb.Organizations.Update(ctx, req)
if err != nil {
panic(fmt.Errorf("cannot update organization: %w", err))
}
return &types.UpdateOrganizationPayload{
Organization: types.NewOrganization(organization),
}, nil
}
// UpdateOrganizationContext is the resolver for the updateOrganizationContext field.
func (r *mutationResolver) UpdateOrganizationContext(ctx context.Context, input types.UpdateOrganizationContextInput) (*types.UpdateOrganizationContextPayload, error) {
prb := r.ProboService(ctx, input.OrganizationID.TenantID())
req := probo.UpdateOrganizationContextRequest{
OrganizationID: input.OrganizationID,
Summary: UnwrapOmittable(input.Summary),
}
organizationContext, err := prb.Organizations.UpdateContext(ctx, req)
if err != nil {
panic(fmt.Errorf("cannot update organization context: %w", err))
}
return &types.UpdateOrganizationContextPayload{
Context: types.NewOrganizationContext(organizationContext),
}, nil
}
// DeleteOrganizationHorizontalLogo is the resolver for the deleteOrganizationHorizontalLogo field.
func (r *mutationResolver) DeleteOrganizationHorizontalLogo(ctx context.Context, input types.DeleteOrganizationHorizontalLogoInput) (*types.DeleteOrganizationHorizontalLogoPayload, error) {
r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionDeleteOrganizationHorizontalLogo)
prb := r.ProboService(ctx, input.OrganizationID.TenantID())
organization, err := prb.Organizations.DeleteHorizontalLogo(ctx, input.OrganizationID)
if err != nil {
panic(fmt.Errorf("cannot delete horizontal logo: %w", err))
}
return &types.DeleteOrganizationHorizontalLogoPayload{
Organization: types.NewOrganization(organization),
}, nil
}
// DeleteOrganization is the resolver for the deleteOrganization field.
func (r *mutationResolver) DeleteOrganization(ctx context.Context, input types.DeleteOrganizationInput) (*types.DeleteOrganizationPayload, error) {
r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionDeleteOrganization)
prb := r.ProboService(ctx, input.OrganizationID.TenantID())
err := prb.Organizations.Delete(ctx, input.OrganizationID)
if err != nil {
panic(fmt.Errorf("cannot delete organization: %w", err))
}
return &types.DeleteOrganizationPayload{
DeletedOrganizationID: input.OrganizationID,
}, nil
}
// UpdateTrustCenter is the resolver for the updateTrustCenter field.
func (r *mutationResolver) UpdateTrustCenter(ctx context.Context, input types.UpdateTrustCenterInput) (*types.UpdateTrustCenterPayload, error) {
r.MustBeAuthorized(ctx, input.TrustCenterID, authz.ActionUpdateTrustCenter)
prb := r.ProboService(ctx, input.TrustCenterID.TenantID())
trustCenter, file, err := prb.TrustCenters.Update(ctx, &probo.UpdateTrustCenterRequest{
ID: input.TrustCenterID,
Active: input.Active,
})
if err != nil {
panic(fmt.Errorf("cannot update trust center: %w", err))
}
return &types.UpdateTrustCenterPayload{
TrustCenter: types.NewTrustCenter(trustCenter, file),
}, nil
}
// UploadTrustCenterNda is the resolver for the uploadTrustCenterNDA field.
func (r *mutationResolver) UploadTrustCenterNda(ctx context.Context, input types.UploadTrustCenterNDAInput) (*types.UploadTrustCenterNDAPayload, error) {
r.MustBeAuthorized(ctx, input.TrustCenterID, authz.ActionUploadTrustCenterNDA)
prb := r.ProboService(ctx, input.TrustCenterID.TenantID())
trustCenter, file, err := prb.TrustCenters.UploadNDA(ctx, &probo.UploadTrustCenterNDARequest{
TrustCenterID: input.TrustCenterID,
File: input.File.File,
FileName: input.FileName,
})
if err != nil {
panic(fmt.Errorf("cannot upload trust center NDA: %w", err))
}
return &types.UploadTrustCenterNDAPayload{
TrustCenter: types.NewTrustCenter(trustCenter, file),
}, nil
}
// DeleteTrustCenterNda is the resolver for the deleteTrustCenterNDA field.
func (r *mutationResolver) DeleteTrustCenterNda(ctx context.Context, input types.DeleteTrustCenterNDAInput) (*types.DeleteTrustCenterNDAPayload, error) {
r.MustBeAuthorized(ctx, input.TrustCenterID, authz.ActionDeleteTrustCenterNDA)
prb := r.ProboService(ctx, input.TrustCenterID.TenantID())
trustCenter, file, err := prb.TrustCenters.DeleteNDA(ctx, input.TrustCenterID)
if err != nil {
panic(fmt.Errorf("cannot delete trust center NDA: %w", err))
}
return &types.DeleteTrustCenterNDAPayload{
TrustCenter: types.NewTrustCenter(trustCenter, file),
}, nil
}
// CreateTrustCenterAccess is the resolver for the createTrustCenterAccess field.
func (r *mutationResolver) CreateTrustCenterAccess(ctx context.Context, input types.CreateTrustCenterAccessInput) (*types.CreateTrustCenterAccessPayload, error) {
r.MustBeAuthorized(ctx, input.TrustCenterID, authz.ActionCreateTrustCenterAccess)
prb := r.ProboService(ctx, input.TrustCenterID.TenantID())
access, err := prb.TrustCenterAccesses.Create(ctx, &probo.CreateTrustCenterAccessRequest{
TrustCenterID: input.TrustCenterID,
Email: input.Email,
Name: input.Name,
})
if err != nil {
var errAlreadyExists *coredata.ErrTrustCenterAccessAlreadyExists
if errors.As(err, &errAlreadyExists) {
return nil, gqlutils.Conflict(errAlreadyExists)
}
panic(fmt.Errorf("cannot create trust center access: %w", err))
}
return &types.CreateTrustCenterAccessPayload{
TrustCenterAccessEdge: types.NewTrustCenterAccessEdge(access, coredata.TrustCenterAccessOrderFieldCreatedAt),
}, nil
}
// UpdateTrustCenterAccess is the resolver for the updateTrustCenterAccess field.
func (r *mutationResolver) UpdateTrustCenterAccess(ctx context.Context, input types.UpdateTrustCenterAccessInput) (*types.UpdateTrustCenterAccessPayload, error) {
r.MustBeAuthorized(ctx, input.ID, authz.ActionUpdateTrustCenterAccess)
prb := r.ProboService(ctx, input.ID.TenantID())
var documentAccesses []probo.UpdateTrustCenterDocumentAccessRequest
var reportAccesses []probo.UpdateTrustCenterDocumentAccessRequest
var fileAccesses []probo.UpdateTrustCenterDocumentAccessRequest
for _, documentAccess := range input.Documents {
documentAccesses = append(documentAccesses, probo.UpdateTrustCenterDocumentAccessRequest{
ID: documentAccess.ID,
Status: documentAccess.Status,
})
}
for _, reportAccess := range input.Reports {
reportAccesses = append(reportAccesses, probo.UpdateTrustCenterDocumentAccessRequest{
ID: reportAccess.ID,
Status: reportAccess.Status,
})
}
for _, fileAccess := range input.TrustCenterFiles {
fileAccesses = append(fileAccesses, probo.UpdateTrustCenterDocumentAccessRequest{
ID: fileAccess.ID,
Status: fileAccess.Status,
})
}
access, err := prb.TrustCenterAccesses.Update(ctx, &probo.UpdateTrustCenterAccessRequest{
ID: input.ID,
Name: input.Name,
Active: input.Active,
DocumentAccesses: documentAccesses,
ReportAccesses: reportAccesses,
TrustCenterFileAccesses: fileAccesses,
})
if err != nil {
panic(fmt.Errorf("cannot update trust center access: %w", err))
}
return &types.UpdateTrustCenterAccessPayload{
TrustCenterAccess: types.NewTrustCenterAccess(access),
}, nil
}
// DeleteTrustCenterAccess is the resolver for the deleteTrustCenterAccess field.
func (r *mutationResolver) DeleteTrustCenterAccess(ctx context.Context, input types.DeleteTrustCenterAccessInput) (*types.DeleteTrustCenterAccessPayload, error) {
r.MustBeAuthorized(ctx, input.ID, authz.ActionDeleteTrustCenterAccess)
prb := r.ProboService(ctx, input.ID.TenantID())
err := prb.TrustCenterAccesses.Delete(ctx, input.ID)
if err != nil {
panic(fmt.Errorf("cannot delete trust center access: %w", err))
}
return &types.DeleteTrustCenterAccessPayload{
DeletedTrustCenterAccessID: input.ID,
}, nil
}
// CreateTrustCenterReference is the resolver for the createTrustCenterReference field.
func (r *mutationResolver) CreateTrustCenterReference(ctx context.Context, input types.CreateTrustCenterReferenceInput) (*types.CreateTrustCenterReferencePayload, error) {
r.MustBeAuthorized(ctx, input.TrustCenterID, authz.ActionCreateTrustCenterReference)
prb := r.ProboService(ctx, input.TrustCenterID.TenantID())
reference, err := prb.TrustCenterReferences.Create(ctx, &probo.CreateTrustCenterReferenceRequest{
TrustCenterID: input.TrustCenterID,
Name: input.Name,
Description: input.Description,
WebsiteURL: input.WebsiteURL,
LogoFile: probo.File{
Content: input.LogoFile.File,
Filename: input.LogoFile.Filename,
Size: input.LogoFile.Size,
ContentType: input.LogoFile.ContentType,
},
})
if err != nil {
panic(fmt.Errorf("cannot create trust center reference: %w", err))
}
return &types.CreateTrustCenterReferencePayload{
TrustCenterReferenceEdge: types.NewTrustCenterReferenceEdge(reference, coredata.TrustCenterReferenceOrderFieldRank),
}, nil
}
// UpdateTrustCenterReference is the resolver for the updateTrustCenterReference field.
func (r *mutationResolver) UpdateTrustCenterReference(ctx context.Context, input types.UpdateTrustCenterReferenceInput) (*types.UpdateTrustCenterReferencePayload, error) {
r.MustBeAuthorized(ctx, input.ID, authz.ActionUpdateTrustCenterReference)
prb := r.ProboService(ctx, input.ID.TenantID())
req := &probo.UpdateTrustCenterReferenceRequest{
ID: input.ID,
Name: input.Name,
Description: UnwrapOmittable(input.Description),
WebsiteURL: input.WebsiteURL,
Rank: input.Rank,
}
if input.LogoFile != nil {
req.LogoFile = &probo.File{
Content: input.LogoFile.File,
Filename: input.LogoFile.Filename,
Size: input.LogoFile.Size,
ContentType: input.LogoFile.ContentType,
}
}
reference, err := prb.TrustCenterReferences.Update(ctx, req)
if err != nil {
panic(fmt.Errorf("cannot update trust center reference: %w", err))
}
return &types.UpdateTrustCenterReferencePayload{
TrustCenterReference: types.NewTrustCenterReference(reference),
}, nil
}
// DeleteTrustCenterReference is the resolver for the deleteTrustCenterReference field.
func (r *mutationResolver) DeleteTrustCenterReference(ctx context.Context, input types.DeleteTrustCenterReferenceInput) (*types.DeleteTrustCenterReferencePayload, error) {
r.MustBeAuthorized(ctx, input.ID, authz.ActionDeleteTrustCenterReference)
prb := r.ProboService(ctx, input.ID.TenantID())
err := prb.TrustCenterReferences.Delete(ctx, input.ID)
if err != nil {
panic(fmt.Errorf("cannot delete trust center reference: %w", err))
}
return &types.DeleteTrustCenterReferencePayload{
DeletedTrustCenterReferenceID: input.ID,
}, nil
}
// CreateTrustCenterFile is the resolver for the createTrustCenterFile field.
func (r *mutationResolver) CreateTrustCenterFile(ctx context.Context, input types.CreateTrustCenterFileInput) (*types.CreateTrustCenterFilePayload, error) {
r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionCreateTrustCenterFile)
prb := r.ProboService(ctx, input.OrganizationID.TenantID())
file, err := prb.TrustCenterFiles.Create(ctx, &probo.CreateTrustCenterFileRequest{
OrganizationID: input.OrganizationID,
Name: input.Name,
Category: input.Category,
File: probo.File{
Content: input.File.File,
Filename: input.File.Filename,
Size: input.File.Size,
ContentType: input.File.ContentType,
},
TrustCenterVisibility: input.TrustCenterVisibility,
})
if err != nil {
panic(fmt.Errorf("cannot create trust center file: %w", err))
}
return &types.CreateTrustCenterFilePayload{
TrustCenterFileEdge: types.NewTrustCenterFileEdge(file, coredata.TrustCenterFileOrderFieldCreatedAt),
}, nil
}
// UpdateTrustCenterFile is the resolver for the updateTrustCenterFile field.
func (r *mutationResolver) UpdateTrustCenterFile(ctx context.Context, input types.UpdateTrustCenterFileInput) (*types.UpdateTrustCenterFilePayload, error) {
r.MustBeAuthorized(ctx, input.ID, authz.ActionUpdateTrustCenterFile)
prb := r.ProboService(ctx, input.ID.TenantID())
file, err := prb.TrustCenterFiles.Update(ctx, &probo.UpdateTrustCenterFileRequest{
ID: input.ID,
Name: input.Name,
Category: input.Category,
TrustCenterVisibility: input.TrustCenterVisibility,
})
if err != nil {
panic(fmt.Errorf("cannot update trust center file: %w", err))
}
return &types.UpdateTrustCenterFilePayload{
TrustCenterFile: types.NewTrustCenterFile(file),
}, nil
}
// GetTrustCenterFile is the resolver for the getTrustCenterFile field.
func (r *mutationResolver) GetTrustCenterFile(ctx context.Context, input types.GetTrustCenterFileInput) (*types.GetTrustCenterFilePayload, error) {
r.MustBeAuthorized(ctx, input.ID, authz.ActionGetTrustCenterFile)
prb := r.ProboService(ctx, input.ID.TenantID())
file, err := prb.TrustCenterFiles.Get(ctx, input.ID)
if err != nil {
panic(fmt.Errorf("cannot get trust center file: %w", err))
}
return &types.GetTrustCenterFilePayload{
TrustCenterFile: types.NewTrustCenterFile(file),
}, nil
}
// DeleteTrustCenterFile is the resolver for the deleteTrustCenterFile field.
func (r *mutationResolver) DeleteTrustCenterFile(ctx context.Context, input types.DeleteTrustCenterFileInput) (*types.DeleteTrustCenterFilePayload, error) {
r.MustBeAuthorized(ctx, input.ID, authz.ActionDeleteTrustCenterFile)
prb := r.ProboService(ctx, input.ID.TenantID())
err := prb.TrustCenterFiles.Delete(ctx, input.ID)
if err != nil {
panic(fmt.Errorf("cannot delete trust center file: %w", err))
}
return &types.DeleteTrustCenterFilePayload{
DeletedTrustCenterFileID: input.ID,
}, nil
}
// ConfirmEmail is the resolver for the confirmEmail field.
func (r *mutationResolver) ConfirmEmail(ctx context.Context, input types.ConfirmEmailInput) (*types.ConfirmEmailPayload, error) {
err := r.authSvc.ConfirmEmail(ctx, input.Token)
if err != nil {
return nil, err
}
return &types.ConfirmEmailPayload{Success: true}, nil
}
// InviteUser is the resolver for the inviteUser field.
func (r *mutationResolver) InviteUser(ctx context.Context, input types.InviteUserInput) (*types.InviteUserPayload, error) {
r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionInviteUser)
user := UserFromContext(ctx)
apiKey := UserAPIKeyFromContext(ctx)
authzSvc := r.AuthzService(ctx, input.OrganizationID.TenantID())
if err := authzSvc.CanAssignRole(ctx, user, apiKey, input.OrganizationID, input.Role); err != nil {
panic(err)
}
invitation, err := authzSvc.InviteUserToOrganization(ctx, input.OrganizationID, input.Email, input.FullName, input.Role)
if err != nil {
panic(fmt.Errorf("cannot invite user to organization: %w", err))
}
if input.CreatePeople {
prb := r.ProboService(ctx, input.OrganizationID.TenantID())
_, err := prb.Peoples.Create(ctx, probo.CreatePeopleRequest{
OrganizationID: input.OrganizationID,
FullName: input.FullName,
PrimaryEmailAddress: input.Email,
AdditionalEmailAddresses: []mail.Addr{},
Kind: coredata.PeopleKindEmployee,
})
if err != nil {
var errAlreadyExists *coredata.ErrPeopleAlreadyExists
if errors.As(err, &errAlreadyExists) {
return nil, gqlutils.Conflict(errAlreadyExists)
}
return nil, fmt.Errorf("cannot create people record: %w", err)
}
}
return &types.InviteUserPayload{
InvitationEdge: types.NewInvitationEdge(invitation, coredata.InvitationOrderFieldCreatedAt),
}, nil
}
// AcceptInvitation is the resolver for the acceptInvitation field.
func (r *mutationResolver) AcceptInvitation(ctx context.Context, input types.AcceptInvitationInput) (*types.AcceptInvitationPayload, error) {
user := UserFromContext(ctx)
invitation, err := r.authzSvc.AcceptInvitationByID(ctx, input.InvitationID, user.ID)
if err != nil {
panic(fmt.Errorf("cannot accept invitation: %w", err))
}
return &types.AcceptInvitationPayload{Invitation: types.NewInvitation(invitation)}, nil
}
// DeleteInvitation is the resolver for the deleteInvitation field.
func (r *mutationResolver) DeleteInvitation(ctx context.Context, input types.DeleteInvitationInput) (*types.DeleteInvitationPayload, error) {
r.MustBeAuthorized(ctx, input.InvitationID, authz.ActionDeleteInvitation)
authzSvc := r.AuthzService(ctx, input.InvitationID.TenantID())
err := authzSvc.DeleteInvitation(ctx, input.InvitationID)
if err != nil {
panic(fmt.Errorf("cannot delete invitation: %w", err))
}
return &types.DeleteInvitationPayload{
DeletedInvitationID: input.InvitationID,
}, nil
}
// RemoveMember is the resolver for the removeMember field.
func (r *mutationResolver) RemoveMember(ctx context.Context, input types.RemoveMemberInput) (*types.RemoveMemberPayload, error) {
r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionRemoveMember)
authzSvc := r.AuthzService(ctx, input.OrganizationID.TenantID())
err := authzSvc.RemoveMemberFromOrganization(ctx, input.OrganizationID, input.MemberID)
if err != nil {
return nil, err
}
return &types.RemoveMemberPayload{DeletedMemberID: input.MemberID}, nil
}
// UpdateMembership is the resolver for the updateMembership field.
func (r *mutationResolver) UpdateMembership(ctx context.Context, input types.UpdateMembershipInput) (*types.UpdateMembershipPayload, error) {
r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionUpdateMembership)
user := UserFromContext(ctx)
apiKey := UserAPIKeyFromContext(ctx)
authzSvc := r.AuthzService(ctx, input.OrganizationID.TenantID())
if err := authzSvc.CanAssignRole(ctx, user, apiKey, input.OrganizationID, input.Role); err != nil {
return nil, err
}
membership, err := authzSvc.UpdateMembershipRole(ctx, input.OrganizationID, input.MemberID, input.Role)
if err != nil {
return nil, fmt.Errorf("cannot update membership: %w", err)
}
return &types.UpdateMembershipPayload{
Membership: types.NewMembership(membership),
}, nil
}
// CreatePeople is the resolver for the createPeople field.
func (r *mutationResolver) CreatePeople(ctx context.Context, input types.CreatePeopleInput) (*types.CreatePeoplePayload, error) {
r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionCreatePeople)
prb := r.ProboService(ctx, input.OrganizationID.TenantID())
people, err := prb.Peoples.Create(ctx, probo.CreatePeopleRequest{
OrganizationID: input.OrganizationID,
FullName: input.FullName,
PrimaryEmailAddress: input.PrimaryEmailAddress,
AdditionalEmailAddresses: []mail.Addr{},
Kind: input.Kind,
Position: input.Position,
ContractStartDate: input.ContractStartDate,
ContractEndDate: input.ContractEndDate,
})
if err != nil {
var errAlreadyExists *coredata.ErrPeopleAlreadyExists
if errors.As(err, &errAlreadyExists) {
return nil, gqlutils.Conflict(errAlreadyExists)
}
panic(fmt.Errorf("cannot create people: %w", err))
}
return &types.CreatePeoplePayload{
PeopleEdge: types.NewPeopleEdge(people, coredata.PeopleOrderFieldFullName),
}, nil
}
// UpdatePeople is the resolver for the updatePeople field.
func (r *mutationResolver) UpdatePeople(ctx context.Context, input types.UpdatePeopleInput) (*types.UpdatePeoplePayload, error) {
r.MustBeAuthorized(ctx, input.ID, authz.ActionUpdatePeople)
prb := r.ProboService(ctx, input.ID.TenantID())
people, err := prb.Peoples.Update(ctx, probo.UpdatePeopleRequest{
ID: input.ID,
FullName: input.FullName,
PrimaryEmailAddress: input.PrimaryEmailAddress,
AdditionalEmailAddresses: &input.AdditionalEmailAddresses,
Kind: input.Kind,
Position: UnwrapOmittable(input.Position),
ContractStartDate: UnwrapOmittable(input.ContractStartDate),
ContractEndDate: UnwrapOmittable(input.ContractEndDate),
})
if err != nil {
panic(fmt.Errorf("cannot update people: %w", err))
}
return &types.UpdatePeoplePayload{
People: types.NewPeople(people),
}, nil
}
// DeletePeople is the resolver for the deletePeople field.
func (r *mutationResolver) DeletePeople(ctx context.Context, input types.DeletePeopleInput) (*types.DeletePeoplePayload, error) {
r.MustBeAuthorized(ctx, input.PeopleID, authz.ActionDeletePeople)
prb := r.ProboService(ctx, input.PeopleID.TenantID())
err := prb.Peoples.Delete(ctx, input.PeopleID)
if err != nil {
panic(fmt.Errorf("cannot delete people: %w", err))
}
return &types.DeletePeoplePayload{
DeletedPeopleID: input.PeopleID,
}, nil
}
// CreateVendor is the resolver for the createVendor field.
func (r *mutationResolver) CreateVendor(ctx context.Context, input types.CreateVendorInput) (*types.CreateVendorPayload, error) {
r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionCreateVendor)
prb := r.ProboService(ctx, input.OrganizationID.TenantID())
vendor, err := prb.Vendors.Create(
ctx,
probo.CreateVendorRequest{
OrganizationID: input.OrganizationID,
Name: input.Name,
Description: input.Description,
StatusPageURL: input.StatusPageURL,
TermsOfServiceURL: input.TermsOfServiceURL,
PrivacyPolicyURL: input.PrivacyPolicyURL,
ServiceLevelAgreementURL: input.ServiceLevelAgreementURL,
LegalName: input.LegalName,
HeadquarterAddress: input.HeadquarterAddress,
WebsiteURL: input.WebsiteURL,
Category: input.Category,
DataProcessingAgreementURL: input.DataProcessingAgreementURL,
BusinessAssociateAgreementURL: input.BusinessAssociateAgreementURL,
SubprocessorsListURL: input.SubprocessorsListURL,
Certifications: input.Certifications,
SecurityPageURL: input.SecurityPageURL,
TrustPageURL: input.TrustPageURL,
BusinessOwnerID: input.BusinessOwnerID,
SecurityOwnerID: input.SecurityOwnerID,
Countries: input.Countries,
},
)
if err != nil {
var errAlreadyExists *coredata.ErrVendorAlreadyExists
if errors.As(err, &errAlreadyExists) {
return nil, gqlutils.Conflict(errAlreadyExists)
}
return nil, fmt.Errorf("cannot create vendor: %w", err)
}
return &types.CreateVendorPayload{
VendorEdge: types.NewVendorEdge(vendor, coredata.VendorOrderFieldName),
}, nil
}
// UpdateVendor is the resolver for the updateVendor field.
func (r *mutationResolver) UpdateVendor(ctx context.Context, input types.UpdateVendorInput) (*types.UpdateVendorPayload, error) {
r.MustBeAuthorized(ctx, input.ID, authz.ActionUpdateVendor)
prb := r.ProboService(ctx, input.ID.TenantID())
vendor, err := prb.Vendors.Update(ctx, probo.UpdateVendorRequest{
ID: input.ID,
Name: input.Name,
Description: UnwrapOmittable(input.Description),
StatusPageURL: UnwrapOmittable(input.StatusPageURL),
TermsOfServiceURL: UnwrapOmittable(input.TermsOfServiceURL),
PrivacyPolicyURL: UnwrapOmittable(input.PrivacyPolicyURL),
ServiceLevelAgreementURL: UnwrapOmittable(input.ServiceLevelAgreementURL),
DataProcessingAgreementURL: UnwrapOmittable(input.DataProcessingAgreementURL),
BusinessAssociateAgreementURL: UnwrapOmittable(input.BusinessAssociateAgreementURL),
SubprocessorsListURL: UnwrapOmittable(input.SubprocessorsListURL),
SecurityPageURL: UnwrapOmittable(input.SecurityPageURL),
TrustPageURL: UnwrapOmittable(input.TrustPageURL),
HeadquarterAddress: UnwrapOmittable(input.HeadquarterAddress),
LegalName: UnwrapOmittable(input.LegalName),
WebsiteURL: UnwrapOmittable(input.WebsiteURL),
Category: input.Category,
Certifications: input.Certifications,
BusinessOwnerID: UnwrapOmittable(input.BusinessOwnerID),
SecurityOwnerID: UnwrapOmittable(input.SecurityOwnerID),
ShowOnTrustCenter: input.ShowOnTrustCenter,
Countries: input.Countries,
})
if err != nil {
return nil, fmt.Errorf("cannot update vendor: %w", err)
}
return &types.UpdateVendorPayload{
Vendor: types.NewVendor(vendor),
}, nil
}
// DeleteVendor is the resolver for the deleteVendor field.
func (r *mutationResolver) DeleteVendor(ctx context.Context, input types.DeleteVendorInput) (*types.DeleteVendorPayload, error) {
r.MustBeAuthorized(ctx, input.VendorID, authz.ActionDeleteVendor)
prb := r.ProboService(ctx, input.VendorID.TenantID())
err := prb.Vendors.Delete(ctx, input.VendorID)
if err != nil {
panic(fmt.Errorf("cannot delete vendor: %w", err))
}
return &types.DeleteVendorPayload{
DeletedVendorID: input.VendorID,
}, nil
}
// CreateVendorContact is the resolver for the createVendorContact field.
func (r *mutationResolver) CreateVendorContact(ctx context.Context, input types.CreateVendorContactInput) (*types.CreateVendorContactPayload, error) {
r.MustBeAuthorized(ctx, input.VendorID, authz.ActionCreateVendorContact)
prb := r.ProboService(ctx, input.VendorID.TenantID())
req := probo.CreateVendorContactRequest{
VendorID: input.VendorID,
FullName: input.FullName,
Email: input.Email,
Phone: input.Phone,
Role: input.Role,
}
vendorContact, err := prb.VendorContacts.Create(ctx, req)
if err != nil {
return nil, fmt.Errorf("cannot create vendor contact: %w", err)
}
return &types.CreateVendorContactPayload{
VendorContactEdge: types.NewVendorContactEdge(vendorContact, coredata.VendorContactOrderFieldCreatedAt),
}, nil
}
// UpdateVendorContact is the resolver for the updateVendorContact field.
func (r *mutationResolver) UpdateVendorContact(ctx context.Context, input types.UpdateVendorContactInput) (*types.UpdateVendorContactPayload, error) {
r.MustBeAuthorized(ctx, input.ID, authz.ActionUpdateVendorContact)
prb := r.ProboService(ctx, input.ID.TenantID())
req := probo.UpdateVendorContactRequest{
ID: input.ID,
FullName: UnwrapOmittable(input.FullName),
Email: UnwrapOmittable(input.Email),
Phone: UnwrapOmittable(input.Phone),
Role: UnwrapOmittable(input.Role),
}
vendorContact, err := prb.VendorContacts.Update(ctx, req)
if err != nil {
panic(fmt.Errorf("cannot update vendor contact: %w", err))
}
return &types.UpdateVendorContactPayload{
VendorContact: types.NewVendorContact(vendorContact),
}, nil
}
// DeleteVendorContact is the resolver for the deleteVendorContact field.
func (r *mutationResolver) DeleteVendorContact(ctx context.Context, input types.DeleteVendorContactInput) (*types.DeleteVendorContactPayload, error) {
r.MustBeAuthorized(ctx, input.VendorContactID, authz.ActionDeleteVendorContact)
prb := r.ProboService(ctx, input.VendorContactID.TenantID())
err := prb.VendorContacts.Delete(ctx, input.VendorContactID)
if err != nil {
return nil, fmt.Errorf("cannot delete vendor contact: %w", err)
}
return &types.DeleteVendorContactPayload{
DeletedVendorContactID: input.VendorContactID,
}, nil
}
// CreateVendorService is the resolver for the createVendorService field.
func (r *mutationResolver) CreateVendorService(ctx context.Context, input types.CreateVendorServiceInput) (*types.CreateVendorServicePayload, error) {
r.MustBeAuthorized(ctx, input.VendorID, authz.ActionCreateVendorService)
prb := r.ProboService(ctx, input.VendorID.TenantID())
req := probo.CreateVendorServiceRequest{
VendorID: input.VendorID,
Name: input.Name,
Description: input.Description,
}
vendorService, err := prb.VendorServices.Create(ctx, req)
if err != nil {
return nil, fmt.Errorf("cannot create vendor service: %w", err)
}
return &types.CreateVendorServicePayload{
VendorServiceEdge: types.NewVendorServiceEdge(vendorService, coredata.VendorServiceOrderFieldCreatedAt),
}, nil
}
// UpdateVendorService is the resolver for the updateVendorService field.
func (r *mutationResolver) UpdateVendorService(ctx context.Context, input types.UpdateVendorServiceInput) (*types.UpdateVendorServicePayload, error) {
r.MustBeAuthorized(ctx, input.ID, authz.ActionUpdateVendorService)
prb := r.ProboService(ctx, input.ID.TenantID())
req := probo.UpdateVendorServiceRequest{
ID: input.ID,
Name: input.Name,
Description: UnwrapOmittable(input.Description),
}
vendorService, err := prb.VendorServices.Update(ctx, req)
if err != nil {
panic(fmt.Errorf("cannot update vendor service: %w", err))
}
return &types.UpdateVendorServicePayload{
VendorService: types.NewVendorService(vendorService),
}, nil
}
// DeleteVendorService is the resolver for the deleteVendorService field.
func (r *mutationResolver) DeleteVendorService(ctx context.Context, input types.DeleteVendorServiceInput) (*types.DeleteVendorServicePayload, error) {
r.MustBeAuthorized(ctx, input.VendorServiceID, authz.ActionDeleteVendorService)
prb := r.ProboService(ctx, input.VendorServiceID.TenantID())
err := prb.VendorServices.Delete(ctx, input.VendorServiceID)
if err != nil {
panic(fmt.Errorf("cannot delete vendor service: %w", err))
}
return &types.DeleteVendorServicePayload{
DeletedVendorServiceID: input.VendorServiceID,
}, nil
}
// CreateFramework is the resolver for the createFramework field.
func (r *mutationResolver) CreateFramework(ctx context.Context, input types.CreateFrameworkInput) (*types.CreateFrameworkPayload, error) {
r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionCreateFramework)
prb := r.ProboService(ctx, input.OrganizationID.TenantID())
framework, err := prb.Frameworks.Create(ctx, probo.CreateFrameworkRequest{
OrganizationID: input.OrganizationID,
Name: input.Name,
})
if err != nil {
return nil, fmt.Errorf("cannot create framework: %w", err)
}
return &types.CreateFrameworkPayload{
FrameworkEdge: types.NewFrameworkEdge(framework, coredata.FrameworkOrderFieldCreatedAt),
}, nil
}
// UpdateFramework is the resolver for the updateFramework field.
func (r *mutationResolver) UpdateFramework(ctx context.Context, input types.UpdateFrameworkInput) (*types.UpdateFrameworkPayload, error) {
r.MustBeAuthorized(ctx, input.ID, authz.ActionUpdateFramework)
prb := r.ProboService(ctx, input.ID.TenantID())
framework, err := prb.Frameworks.Update(ctx, probo.UpdateFrameworkRequest{
ID: input.ID,
Name: input.Name,
Description: UnwrapOmittable(input.Description),
})
if err != nil {
return nil, fmt.Errorf("cannot update framework: %w", err)
}
return &types.UpdateFrameworkPayload{
Framework: types.NewFramework(framework),
}, nil
}
// ImportFramework is the resolver for the importFramework field.
func (r *mutationResolver) ImportFramework(ctx context.Context, input types.ImportFrameworkInput) (*types.ImportFrameworkPayload, error) {
r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionImportFramework)
prb := r.ProboService(ctx, input.OrganizationID.TenantID())
req := probo.ImportFrameworkRequest{}
if err := json.NewDecoder(input.File.File).Decode(&req.Framework); err != nil {
panic(fmt.Errorf("cannot decode framework: %w", err))
}
framework, err := prb.Frameworks.Import(ctx, input.OrganizationID, req)
if err != nil {
var errFrameworkReferenceIDAlreadyExists *coredata.ErrFrameworkReferenceIDAlreadyExists
if errors.As(err, &errFrameworkReferenceIDAlreadyExists) {
return nil, &gqlerror.Error{
Err: err,
Message: fmt.Sprintf("framework %q already exists", req.Framework.Name),
Extensions: map[string]any{
"code": "CONFLICT",
"frameworkReferenceId": errFrameworkReferenceIDAlreadyExists.ReferenceID,
},
}
}
panic(fmt.Errorf("cannot import framework: %w", err))
}
return &types.ImportFrameworkPayload{
FrameworkEdge: types.NewFrameworkEdge(framework, coredata.FrameworkOrderFieldCreatedAt),
}, nil
}
// DeleteFramework is the resolver for the deleteFramework field.
func (r *mutationResolver) DeleteFramework(ctx context.Context, input types.DeleteFrameworkInput) (*types.DeleteFrameworkPayload, error) {
r.MustBeAuthorized(ctx, input.FrameworkID, authz.ActionDeleteFramework)
prb := r.ProboService(ctx, input.FrameworkID.TenantID())
err := prb.Frameworks.Delete(ctx, input.FrameworkID)
if err != nil {
panic(fmt.Errorf("cannot delete framework: %w", err))
}
return &types.DeleteFrameworkPayload{
DeletedFrameworkID: input.FrameworkID,
}, nil
}
// GenerateFrameworkStateOfApplicability is the resolver for the generateFrameworkStateOfApplicability field.
func (r *mutationResolver) GenerateFrameworkStateOfApplicability(ctx context.Context, input types.GenerateFrameworkStateOfApplicabilityInput) (*types.GenerateFrameworkStateOfApplicabilityPayload, error) {
r.MustBeAuthorized(ctx, input.FrameworkID, authz.ActionGenerateFrameworkStateOfApplicability)
prb := r.ProboService(ctx, input.FrameworkID.TenantID())
soa, err := prb.Frameworks.StateOfApplicability(ctx, input.FrameworkID)
if err != nil {
panic(fmt.Errorf("cannot generate framework SOA: %w", err))
}
return &types.GenerateFrameworkStateOfApplicabilityPayload{
Data: fmt.Sprintf(
"data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,%s",
base64.StdEncoding.EncodeToString(soa),
),
}, nil
}
// ExportFramework is the resolver for the exportFramework field.
func (r *mutationResolver) ExportFramework(ctx context.Context, input types.ExportFrameworkInput) (*types.ExportFrameworkPayload, error) {
r.MustBeAuthorized(ctx, input.FrameworkID, authz.ActionExportFramework)
prb := r.ProboService(ctx, input.FrameworkID.TenantID())
user := UserFromContext(ctx)
err, exportJobID := prb.Frameworks.RequestExport(
ctx,
input.FrameworkID,
user.EmailAddress,
user.FullName,
)
if err != nil {
panic(fmt.Errorf("cannot export framework: %w", err))
}
return &types.ExportFrameworkPayload{
ExportJobID: exportJobID.ID,
}, nil
}
// CreateControl is the resolver for the createControl field.
func (r *mutationResolver) CreateControl(ctx context.Context, input types.CreateControlInput) (*types.CreateControlPayload, error) {
r.MustBeAuthorized(ctx, input.FrameworkID, authz.ActionCreateControl)
prb := r.ProboService(ctx, input.FrameworkID.TenantID())
control, err := prb.Controls.Create(ctx, probo.CreateControlRequest{
FrameworkID: input.FrameworkID,
Name: input.Name,
Description: input.Description,
SectionTitle: input.SectionTitle,
Status: &input.Status,
ExclusionJustification: input.ExclusionJustification,
})
if err != nil {
var errAlreadyExists *coredata.ErrControlAlreadyExists
if errors.As(err, &errAlreadyExists) {
return nil, gqlutils.Conflict(errAlreadyExists)
}
panic(fmt.Errorf("cannot create control: %w", err))
}
return &types.CreateControlPayload{
ControlEdge: types.NewControlEdge(control, coredata.ControlOrderFieldCreatedAt),
}, nil
}
// UpdateControl is the resolver for the updateControl field.
func (r *mutationResolver) UpdateControl(ctx context.Context, input types.UpdateControlInput) (*types.UpdateControlPayload, error) {
r.MustBeAuthorized(ctx, input.ID, authz.ActionUpdateControl)
prb := r.ProboService(ctx, input.ID.TenantID())
control, err := prb.Controls.Update(ctx, probo.UpdateControlRequest{
ID: input.ID,
Name: input.Name,
Description: UnwrapOmittable(input.Description),
SectionTitle: input.SectionTitle,
Status: input.Status,
ExclusionJustification: input.ExclusionJustification,
})
if err != nil {
var errAlreadyExists *coredata.ErrControlAlreadyExists
if errors.As(err, &errAlreadyExists) {
return nil, gqlutils.Conflict(errAlreadyExists)
}
panic(fmt.Errorf("cannot update control: %w", err))
}
return &types.UpdateControlPayload{
Control: types.NewControl(control),
}, nil
}
// DeleteControl is the resolver for the deleteControl field.
func (r *mutationResolver) DeleteControl(ctx context.Context, input types.DeleteControlInput) (*types.DeleteControlPayload, error) {
prb := r.ProboService(ctx, input.ControlID.TenantID())
err := prb.Controls.Delete(ctx, input.ControlID)
if err != nil {
panic(fmt.Errorf("cannot delete control: %w", err))
}
return &types.DeleteControlPayload{
DeletedControlID: input.ControlID,
}, nil
}
// // CreateMeasure is the resolver for the createMeasure field.
func (r *mutationResolver) CreateMeasure(ctx context.Context, input types.CreateMeasureInput) (*types.CreateMeasurePayload, error) {
r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionCreateMeasure)
prb := r.ProboService(ctx, input.OrganizationID.TenantID())
measure, err := prb.Measures.Create(ctx, probo.CreateMeasureRequest{
OrganizationID: input.OrganizationID,
Name: input.Name,
Description: input.Description,
Category: input.Category,
})
if err != nil {
var errAlreadyExists *coredata.ErrMeasureAlreadyExists
if errors.As(err, &errAlreadyExists) {
return nil, gqlutils.Conflict(errAlreadyExists)
}
panic(fmt.Errorf("cannot create measure: %w", err))
}
return &types.CreateMeasurePayload{
MeasureEdge: types.NewMeasureEdge(measure, coredata.MeasureOrderFieldCreatedAt),
}, nil
}
// UpdateMeasure is the resolver for the updateMeasure field.
func (r *mutationResolver) UpdateMeasure(ctx context.Context, input types.UpdateMeasureInput) (*types.UpdateMeasurePayload, error) {
r.MustBeAuthorized(ctx, input.ID, authz.ActionUpdateMeasure)
prb := r.ProboService(ctx, input.ID.TenantID())
measure, err := prb.Measures.Update(ctx, probo.UpdateMeasureRequest{
ID: input.ID,
Name: input.Name,
Description: UnwrapOmittable(input.Description),
Category: input.Category,
State: input.State,
})
if err != nil {
panic(fmt.Errorf("cannot update measure: %w", err))
}
return &types.UpdateMeasurePayload{
Measure: types.NewMeasure(measure),
}, nil
}
// ImportMeasure is the resolver for the importMeasure field.
func (r *mutationResolver) ImportMeasure(ctx context.Context, input types.ImportMeasureInput) (*types.ImportMeasurePayload, error) {
r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionImportMeasure)
prb := r.ProboService(ctx, input.OrganizationID.TenantID())
var req probo.ImportMeasureRequest
if err := json.NewDecoder(input.File.File).Decode(&req.Measures); err != nil {
panic(fmt.Errorf("cannot unmarshal measure: %w", err))
}
measures, err := prb.Measures.Import(ctx, input.OrganizationID, req)
if err != nil {
panic(fmt.Errorf("cannot import measure: %w", err))
}
measureEdges := make([]*types.MeasureEdge, len(measures.Data))
for i, measure := range measures.Data {
measureEdges[i] = types.NewMeasureEdge(measure, coredata.MeasureOrderFieldCreatedAt)
}
return &types.ImportMeasurePayload{
MeasureEdges: measureEdges,
}, nil
}
// DeleteMeasure is the resolver for the deleteMeasure field.
func (r *mutationResolver) DeleteMeasure(ctx context.Context, input types.DeleteMeasureInput) (*types.DeleteMeasurePayload, error) {
r.MustBeAuthorized(ctx, input.MeasureID, authz.ActionDeleteMeasure)
prb := r.ProboService(ctx, input.MeasureID.TenantID())
err := prb.Measures.Delete(ctx, input.MeasureID)
if err != nil {
panic(fmt.Errorf("cannot delete measure: %w", err))
}
return &types.DeleteMeasurePayload{
DeletedMeasureID: input.MeasureID,
}, nil
}
// CreateControlMeasureMapping is the resolver for the createControlMeasureMapping field.
func (r *mutationResolver) CreateControlMeasureMapping(ctx context.Context, input types.CreateControlMeasureMappingInput) (*types.CreateControlMeasureMappingPayload, error) {
r.MustBeAuthorized(ctx, input.ControlID, authz.ActionCreateControlMeasureMapping)
prb := r.ProboService(ctx, input.MeasureID.TenantID())
control, measure, err := prb.Controls.CreateMeasureMapping(ctx, input.ControlID, input.MeasureID)
if err != nil {
panic(fmt.Errorf("cannot create control measure mapping: %w", err))
}
return &types.CreateControlMeasureMappingPayload{
ControlEdge: types.NewControlEdge(control, coredata.ControlOrderFieldCreatedAt),
MeasureEdge: types.NewMeasureEdge(measure, coredata.MeasureOrderFieldCreatedAt),
}, nil
}
// CreateControlDocumentMapping is the resolver for the createControlDocumentMapping field.
func (r *mutationResolver) CreateControlDocumentMapping(ctx context.Context, input types.CreateControlDocumentMappingInput) (*types.CreateControlDocumentMappingPayload, error) {
r.MustBeAuthorized(ctx, input.ControlID, authz.ActionCreateControlDocumentMapping)
prb := r.ProboService(ctx, input.DocumentID.TenantID())
control, document, err := prb.Controls.CreateDocumentMapping(ctx, input.ControlID, input.DocumentID)
if err != nil {
var errMappingExists *coredata.ErrControlDocumentMappingAlreadyExists
if errors.As(err, &errMappingExists) {
return nil, gqlutils.Conflict(errMappingExists)
}
panic(fmt.Errorf("cannot create control document mapping: %w", err))
}
return &types.CreateControlDocumentMappingPayload{
ControlEdge: types.NewControlEdge(control, coredata.ControlOrderFieldCreatedAt),
DocumentEdge: types.NewDocumentEdge(document, coredata.DocumentOrderFieldTitle),
}, nil
}
// DeleteControlMeasureMapping is the resolver for the deleteControlMeasureMapping field.
func (r *mutationResolver) DeleteControlMeasureMapping(ctx context.Context, input types.DeleteControlMeasureMappingInput) (*types.DeleteControlMeasureMappingPayload, error) {
r.MustBeAuthorized(ctx, input.ControlID, authz.ActionDeleteControlMeasureMapping)
prb := r.ProboService(ctx, input.MeasureID.TenantID())
control, measure, err := prb.Controls.DeleteMeasureMapping(ctx, input.ControlID, input.MeasureID)
if err != nil {
panic(fmt.Errorf("cannot delete control measure mapping: %w", err))
}
return &types.DeleteControlMeasureMappingPayload{
DeletedControlID: control.ID,
DeletedMeasureID: measure.ID,
}, nil
}
// DeleteControlDocumentMapping is the resolver for the deleteControlDocumentMapping field.
func (r *mutationResolver) DeleteControlDocumentMapping(ctx context.Context, input types.DeleteControlDocumentMappingInput) (*types.DeleteControlDocumentMappingPayload, error) {
r.MustBeAuthorized(ctx, input.ControlID, authz.ActionDeleteControlDocumentMapping)
prb := r.ProboService(ctx, input.DocumentID.TenantID())
control, document, err := prb.Controls.DeleteDocumentMapping(ctx, input.ControlID, input.DocumentID)
if err != nil {
panic(fmt.Errorf("cannot delete control document mapping: %w", err))
}
return &types.DeleteControlDocumentMappingPayload{
DeletedControlID: control.ID,
DeletedDocumentID: document.ID,
}, nil
}
// CreateControlAuditMapping is the resolver for the createControlAuditMapping field.
func (r *mutationResolver) CreateControlAuditMapping(ctx context.Context, input types.CreateControlAuditMappingInput) (*types.CreateControlAuditMappingPayload, error) {
r.MustBeAuthorized(ctx, input.ControlID, authz.ActionCreateControlAuditMapping)
prb := r.ProboService(ctx, input.AuditID.TenantID())
control, audit, err := prb.Controls.CreateAuditMapping(ctx, input.ControlID, input.AuditID)
if err != nil {
panic(fmt.Errorf("cannot create control audit mapping: %w", err))
}
return &types.CreateControlAuditMappingPayload{
ControlEdge: types.NewControlEdge(control, coredata.ControlOrderFieldCreatedAt),
AuditEdge: types.NewAuditEdge(audit, coredata.AuditOrderFieldCreatedAt),
}, nil
}
// DeleteControlAuditMapping is the resolver for the deleteControlAuditMapping field.
func (r *mutationResolver) DeleteControlAuditMapping(ctx context.Context, input types.DeleteControlAuditMappingInput) (*types.DeleteControlAuditMappingPayload, error) {
r.MustBeAuthorized(ctx, input.ControlID, authz.ActionDeleteControlAuditMapping)
prb := r.ProboService(ctx, input.AuditID.TenantID())
control, audit, err := prb.Controls.DeleteAuditMapping(ctx, input.ControlID, input.AuditID)
if err != nil {
panic(fmt.Errorf("cannot delete control audit mapping: %w", err))
}
return &types.DeleteControlAuditMappingPayload{
DeletedControlID: control.ID,
DeletedAuditID: audit.ID,
}, nil
}
// CreateControlSnapshotMapping is the resolver for the createControlSnapshotMapping field.
func (r *mutationResolver) CreateControlSnapshotMapping(ctx context.Context, input types.CreateControlSnapshotMappingInput) (*types.CreateControlSnapshotMappingPayload, error) {
r.MustBeAuthorized(ctx, input.ControlID, authz.ActionCreateControlSnapshotMapping)
prb := r.ProboService(ctx, input.SnapshotID.TenantID())
control, snapshot, err := prb.Controls.CreateSnapshotMapping(ctx, input.ControlID, input.SnapshotID)
if err != nil {
panic(fmt.Errorf("cannot create control snapshot mapping: %w", err))
}
return &types.CreateControlSnapshotMappingPayload{
ControlEdge: types.NewControlEdge(control, coredata.ControlOrderFieldCreatedAt),
SnapshotEdge: types.NewSnapshotEdge(snapshot, coredata.SnapshotOrderFieldCreatedAt),
}, nil
}
// DeleteControlSnapshotMapping is the resolver for the deleteControlSnapshotMapping field.
func (r *mutationResolver) DeleteControlSnapshotMapping(ctx context.Context, input types.DeleteControlSnapshotMappingInput) (*types.DeleteControlSnapshotMappingPayload, error) {
r.MustBeAuthorized(ctx, input.ControlID, authz.ActionDeleteControlSnapshotMapping)
prb := r.ProboService(ctx, input.SnapshotID.TenantID())
control, snapshot, err := prb.Controls.DeleteSnapshotMapping(ctx, input.ControlID, input.SnapshotID)
if err != nil {
panic(fmt.Errorf("cannot delete control snapshot mapping: %w", err))
}
return &types.DeleteControlSnapshotMappingPayload{
DeletedControlID: control.ID,
DeletedSnapshotID: snapshot.ID,
}, nil
}
// CreateTask is the resolver for the createTask field.
func (r *mutationResolver) CreateTask(ctx context.Context, input types.CreateTaskInput) (*types.CreateTaskPayload, error) {
r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionCreateTask)
prb := r.ProboService(ctx, input.MeasureID.TenantID())
task, err := prb.Tasks.Create(ctx, probo.CreateTaskRequest{
MeasureID: input.MeasureID,
OrganizationID: input.OrganizationID,
Name: input.Name,
Description: input.Description,
TimeEstimate: input.TimeEstimate,
Deadline: input.Deadline,
})
if err != nil {
var errAlreadyExists *coredata.ErrTaskAlreadyExists
if errors.As(err, &errAlreadyExists) {
return nil, gqlutils.Conflict(errAlreadyExists)
}
panic(fmt.Errorf("cannot create task: %w", err))
}
return &types.CreateTaskPayload{
TaskEdge: types.NewTaskEdge(task, coredata.TaskOrderFieldCreatedAt),
}, nil
}
// UpdateTask is the resolver for the updateTask field.
func (r *mutationResolver) UpdateTask(ctx context.Context, input types.UpdateTaskInput) (*types.UpdateTaskPayload, error) {
r.MustBeAuthorized(ctx, input.TaskID, authz.ActionUpdateTask)
prb := r.ProboService(ctx, input.TaskID.TenantID())
task, err := prb.Tasks.Update(ctx, probo.UpdateTaskRequest{
TaskID: input.TaskID,
Name: input.Name,
Description: UnwrapOmittable(input.Description),
State: input.State,
TimeEstimate: UnwrapOmittable(input.TimeEstimate),
Deadline: UnwrapOmittable(input.Deadline),
})
if err != nil {
panic(fmt.Errorf("cannot update task: %w", err))
}
return &types.UpdateTaskPayload{
Task: types.NewTask(task),
}, nil
}
// DeleteTask is the resolver for the deleteTask field.
func (r *mutationResolver) DeleteTask(ctx context.Context, input types.DeleteTaskInput) (*types.DeleteTaskPayload, error) {
r.MustBeAuthorized(ctx, input.TaskID, authz.ActionDeleteTask)
prb := r.ProboService(ctx, input.TaskID.TenantID())
err := prb.Tasks.Delete(ctx, input.TaskID)
if err != nil {
panic(fmt.Errorf("cannot delete task: %w", err))
}
return &types.DeleteTaskPayload{
DeletedTaskID: input.TaskID,
}, nil
}
// AssignTask is the resolver for the assignTask field.
func (r *mutationResolver) AssignTask(ctx context.Context, input types.AssignTaskInput) (*types.AssignTaskPayload, error) {
prb := r.ProboService(ctx, input.TaskID.TenantID())
task, err := prb.Tasks.Assign(ctx, input.TaskID, input.AssignedToID)
if err != nil {
panic(fmt.Errorf("cannot assign task: %w", err))
}
return &types.AssignTaskPayload{
Task: types.NewTask(task),
}, nil
}
// UnassignTask is the resolver for the unassignTask field.
func (r *mutationResolver) UnassignTask(ctx context.Context, input types.UnassignTaskInput) (*types.UnassignTaskPayload, error) {
prb := r.ProboService(ctx, input.TaskID.TenantID())
task, err := prb.Tasks.Unassign(ctx, input.TaskID)
if err != nil {
panic(fmt.Errorf("cannot unassign task: %w", err))
}
return &types.UnassignTaskPayload{
Task: types.NewTask(task),
}, nil
}
// CreateRisk is the resolver for the createRisk field.
func (r *mutationResolver) CreateRisk(ctx context.Context, input types.CreateRiskInput) (*types.CreateRiskPayload, error) {
r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionCreateRisk)
prb := r.ProboService(ctx, input.OrganizationID.TenantID())
risk, err := prb.Risks.Create(
ctx,
probo.CreateRiskRequest{
OrganizationID: input.OrganizationID,
Name: input.Name,
Description: input.Description,
Category: input.Category,
Treatment: input.Treatment,
OwnerID: input.OwnerID,
InherentLikelihood: input.InherentLikelihood,
InherentImpact: input.InherentImpact,
ResidualLikelihood: input.ResidualLikelihood,
ResidualImpact: input.ResidualImpact,
Note: input.Note,
},
)
if err != nil {
var errAlreadyExists *coredata.ErrRiskAlreadyExists
if errors.As(err, &errAlreadyExists) {
return nil, gqlutils.Conflict(errAlreadyExists)
}
panic(fmt.Errorf("cannot create risk: %w", err))
}
return &types.CreateRiskPayload{
RiskEdge: types.NewRiskEdge(risk, coredata.RiskOrderFieldCreatedAt),
}, nil
}
// UpdateRisk is the resolver for the updateRisk field.
func (r *mutationResolver) UpdateRisk(ctx context.Context, input types.UpdateRiskInput) (*types.UpdateRiskPayload, error) {
r.MustBeAuthorized(ctx, input.ID, authz.ActionUpdateRisk)
prb := r.ProboService(ctx, input.ID.TenantID())
risk, err := prb.Risks.Update(
ctx,
probo.UpdateRiskRequest{
ID: input.ID,
Name: input.Name,
Description: UnwrapOmittable(input.Description),
Category: input.Category,
Treatment: input.Treatment,
OwnerID: UnwrapOmittable(input.OwnerID),
InherentLikelihood: input.InherentLikelihood,
InherentImpact: input.InherentImpact,
ResidualLikelihood: input.ResidualLikelihood,
ResidualImpact: input.ResidualImpact,
Note: input.Note,
},
)
if err != nil {
panic(fmt.Errorf("cannot update risk: %w", err))
}
return &types.UpdateRiskPayload{
Risk: types.NewRisk(risk),
}, nil
}
// DeleteRisk is the resolver for the deleteRisk field.
func (r *mutationResolver) DeleteRisk(ctx context.Context, input types.DeleteRiskInput) (*types.DeleteRiskPayload, error) {
r.MustBeAuthorized(ctx, input.RiskID, authz.ActionDeleteRisk)
prb := r.ProboService(ctx, input.RiskID.TenantID())
err := prb.Risks.Delete(ctx, input.RiskID)
if err != nil {
panic(fmt.Errorf("cannot delete risk: %w", err))
}
return &types.DeleteRiskPayload{
DeletedRiskID: input.RiskID,
}, nil
}
// CreateRiskMeasureMapping is the resolver for the createRiskMeasureMapping field.
func (r *mutationResolver) CreateRiskMeasureMapping(ctx context.Context, input types.CreateRiskMeasureMappingInput) (*types.CreateRiskMeasureMappingPayload, error) {
r.MustBeAuthorized(ctx, input.RiskID, authz.ActionCreateRiskMeasureMapping)
prb := r.ProboService(ctx, input.RiskID.TenantID())
risk, measure, err := prb.Risks.CreateMeasureMapping(ctx, input.RiskID, input.MeasureID)
if err != nil {
panic(fmt.Errorf("cannot create risk measure mapping: %w", err))
}
return &types.CreateRiskMeasureMappingPayload{
RiskEdge: types.NewRiskEdge(risk, coredata.RiskOrderFieldCreatedAt),
MeasureEdge: types.NewMeasureEdge(measure, coredata.MeasureOrderFieldCreatedAt),
}, nil
}
// DeleteRiskMeasureMapping is the resolver for the deleteRiskMeasureMapping field.
func (r *mutationResolver) DeleteRiskMeasureMapping(ctx context.Context, input types.DeleteRiskMeasureMappingInput) (*types.DeleteRiskMeasureMappingPayload, error) {
r.MustBeAuthorized(ctx, input.RiskID, authz.ActionDeleteRiskMeasureMapping)
prb := r.ProboService(ctx, input.RiskID.TenantID())
risk, measure, err := prb.Risks.DeleteMeasureMapping(ctx, input.RiskID, input.MeasureID)
if err != nil {
panic(fmt.Errorf("cannot delete risk measure mapping: %w", err))
}
return &types.DeleteRiskMeasureMappingPayload{
DeletedRiskID: risk.ID,
DeletedMeasureID: measure.ID,
}, nil
}
// CreateRiskDocumentMapping is the resolver for the createRiskDocumentMapping field.
func (r *mutationResolver) CreateRiskDocumentMapping(ctx context.Context, input types.CreateRiskDocumentMappingInput) (*types.CreateRiskDocumentMappingPayload, error) {
r.MustBeAuthorized(ctx, input.RiskID, authz.ActionCreateRiskDocumentMapping)
prb := r.ProboService(ctx, input.RiskID.TenantID())
risk, document, err := prb.Risks.CreateDocumentMapping(ctx, input.RiskID, input.DocumentID)
if err != nil {
panic(fmt.Errorf("cannot create risk document mapping: %w", err))
}
return &types.CreateRiskDocumentMappingPayload{
RiskEdge: types.NewRiskEdge(risk, coredata.RiskOrderFieldCreatedAt),
DocumentEdge: types.NewDocumentEdge(document, coredata.DocumentOrderFieldTitle),
}, nil
}
// DeleteRiskDocumentMapping is the resolver for the deleteRiskDocumentMapping field.
func (r *mutationResolver) DeleteRiskDocumentMapping(ctx context.Context, input types.DeleteRiskDocumentMappingInput) (*types.DeleteRiskDocumentMappingPayload, error) {
r.MustBeAuthorized(ctx, input.RiskID, authz.ActionDeleteRiskDocumentMapping)
prb := r.ProboService(ctx, input.RiskID.TenantID())
risk, document, err := prb.Risks.DeleteDocumentMapping(ctx, input.RiskID, input.DocumentID)
if err != nil {
panic(fmt.Errorf("cannot delete risk document mapping: %w", err))
}
return &types.DeleteRiskDocumentMappingPayload{
DeletedRiskID: risk.ID,
DeletedDocumentID: document.ID,
}, nil
}
// CreateRiskObligationMapping is the resolver for the createRiskObligationMapping field.
func (r *mutationResolver) CreateRiskObligationMapping(ctx context.Context, input types.CreateRiskObligationMappingInput) (*types.CreateRiskObligationMappingPayload, error) {
r.MustBeAuthorized(ctx, input.RiskID, authz.ActionCreateRiskObligationMapping)
prb := r.ProboService(ctx, input.RiskID.TenantID())
risk, obligation, err := prb.Risks.CreateObligationMapping(ctx, input.RiskID, input.ObligationID)
if err != nil {
panic(fmt.Errorf("cannot create risk obligation mapping: %w", err))
}
return &types.CreateRiskObligationMappingPayload{
RiskEdge: types.NewRiskEdge(risk, coredata.RiskOrderFieldCreatedAt),
ObligationEdge: types.NewObligationEdge(obligation, coredata.ObligationOrderFieldCreatedAt),
}, nil
}
// DeleteRiskObligationMapping is the resolver for the deleteRiskObligationMapping field.
func (r *mutationResolver) DeleteRiskObligationMapping(ctx context.Context, input types.DeleteRiskObligationMappingInput) (*types.DeleteRiskObligationMappingPayload, error) {
r.MustBeAuthorized(ctx, input.RiskID, authz.ActionDeleteRiskObligationMapping)
prb := r.ProboService(ctx, input.RiskID.TenantID())
risk, obligation, err := prb.Risks.DeleteObligationMapping(ctx, input.RiskID, input.ObligationID)
if err != nil {
panic(fmt.Errorf("cannot delete risk obligation mapping: %w", err))
}
return &types.DeleteRiskObligationMappingPayload{
DeletedRiskID: risk.ID,
DeletedObligationID: obligation.ID,
}, nil
}
// DeleteEvidence is the resolver for the deleteEvidence field.
func (r *mutationResolver) DeleteEvidence(ctx context.Context, input types.DeleteEvidenceInput) (*types.DeleteEvidencePayload, error) {
r.MustBeAuthorized(ctx, input.EvidenceID, authz.ActionDeleteEvidence)
prb := r.ProboService(ctx, input.EvidenceID.TenantID())
err := prb.Evidences.Delete(ctx, input.EvidenceID)
if err != nil {
panic(fmt.Errorf("cannot delete evidence: %w", err))
}
return &types.DeleteEvidencePayload{
DeletedEvidenceID: input.EvidenceID,
}, nil
}
// UploadMeasureEvidence is the resolver for the uploadMeasureEvidence field.
func (r *mutationResolver) UploadMeasureEvidence(ctx context.Context, input types.UploadMeasureEvidenceInput) (*types.UploadMeasureEvidencePayload, error) {
r.MustBeAuthorized(ctx, input.MeasureID, authz.ActionUploadMeasureEvidence)
prb := r.ProboService(ctx, input.MeasureID.TenantID())
evidence, err := prb.Evidences.UploadMeasureEvidence(
ctx,
probo.UploadMeasureEvidenceRequest{
MeasureID: input.MeasureID,
File: probo.FileUpload{
Content: input.File.File,
Filename: input.File.Filename,
Size: input.File.Size,
ContentType: input.File.ContentType,
},
},
)
if err != nil {
panic(fmt.Errorf("cannot upload measure evidence: %w", err))
}
return &types.UploadMeasureEvidencePayload{
EvidenceEdge: types.NewEvidenceEdge(evidence, coredata.EvidenceOrderFieldCreatedAt),
}, nil
}
// UploadVendorComplianceReport is the resolver for the uploadVendorComplianceReport field.
func (r *mutationResolver) UploadVendorComplianceReport(ctx context.Context, input types.UploadVendorComplianceReportInput) (*types.UploadVendorComplianceReportPayload, error) {
r.MustBeAuthorized(ctx, input.VendorID, authz.ActionUploadVendorComplianceReport)
prb := r.ProboService(ctx, input.VendorID.TenantID())
vendorComplianceReport, err := prb.VendorComplianceReports.Upload(
ctx,
input.VendorID,
&probo.VendorComplianceReportCreateRequest{
File: probo.FileUpload{Filename: input.File.Filename, Size: input.File.Size, Content: input.File.File, ContentType: input.File.ContentType},
ReportDate: input.ReportDate,
ValidUntil: input.ValidUntil,
ReportName: input.ReportName,
},
)
if err != nil {
panic(fmt.Errorf("cannot upload vendor compliance report: %w", err))
}
return &types.UploadVendorComplianceReportPayload{
VendorComplianceReportEdge: types.NewVendorComplianceReportEdge(vendorComplianceReport, coredata.VendorComplianceReportOrderFieldCreatedAt),
}, nil
}
// DeleteVendorComplianceReport is the resolver for the deleteVendorComplianceReport field.
func (r *mutationResolver) DeleteVendorComplianceReport(ctx context.Context, input types.DeleteVendorComplianceReportInput) (*types.DeleteVendorComplianceReportPayload, error) {
r.MustBeAuthorized(ctx, input.ReportID, authz.ActionDeleteVendorComplianceReport)
prb := r.ProboService(ctx, input.ReportID.TenantID())
err := prb.VendorComplianceReports.Delete(ctx, input.ReportID)
if err != nil {
panic(fmt.Errorf("cannot delete vendor compliance report: %w", err))
}
return &types.DeleteVendorComplianceReportPayload{
DeletedVendorComplianceReportID: input.ReportID,
}, nil
}
// UploadVendorBusinessAssociateAgreement is the resolver for the uploadVendorBusinessAssociateAgreement field.
func (r *mutationResolver) UploadVendorBusinessAssociateAgreement(ctx context.Context, input types.UploadVendorBusinessAssociateAgreementInput) (*types.UploadVendorBusinessAssociateAgreementPayload, error) {
r.MustBeAuthorized(ctx, input.VendorID, authz.ActionUploadVendorBusinessAssociateAgreement)
prb := r.ProboService(ctx, input.VendorID.TenantID())
vendorBusinessAssociateAgreement, file, err := prb.VendorBusinessAssociateAgreements.Upload(
ctx,
input.VendorID,
&probo.VendorBusinessAssociateAgreementCreateRequest{
File: input.File.File,
ValidFrom: input.ValidFrom,
ValidUntil: input.ValidUntil,
FileName: input.FileName,
},
)
if err != nil {
panic(fmt.Errorf("cannot upload vendor business associate agreement: %w", err))
}
return &types.UploadVendorBusinessAssociateAgreementPayload{
VendorBusinessAssociateAgreement: types.NewVendorBusinessAssociateAgreement(vendorBusinessAssociateAgreement, file),
}, nil
}
// UpdateVendorBusinessAssociateAgreement is the resolver for the updateVendorBusinessAssociateAgreement field.
func (r *mutationResolver) UpdateVendorBusinessAssociateAgreement(ctx context.Context, input types.UpdateVendorBusinessAssociateAgreementInput) (*types.UpdateVendorBusinessAssociateAgreementPayload, error) {
r.MustBeAuthorized(ctx, input.VendorID, authz.ActionUpdateVendorBusinessAssociateAgreement)
prb := r.ProboService(ctx, input.VendorID.TenantID())
vendorBusinessAssociateAgreement, file, err := prb.VendorBusinessAssociateAgreements.Update(
ctx,
input.VendorID,
&probo.VendorBusinessAssociateAgreementUpdateRequest{
ValidFrom: UnwrapOmittable(input.ValidFrom),
ValidUntil: UnwrapOmittable(input.ValidUntil),
},
)
if err != nil {
panic(fmt.Errorf("cannot update vendor business associate agreement: %w", err))
}
return &types.UpdateVendorBusinessAssociateAgreementPayload{
VendorBusinessAssociateAgreement: types.NewVendorBusinessAssociateAgreement(vendorBusinessAssociateAgreement, file),
}, nil
}
// DeleteVendorBusinessAssociateAgreement is the resolver for the deleteVendorBusinessAssociateAgreement field.
func (r *mutationResolver) DeleteVendorBusinessAssociateAgreement(ctx context.Context, input types.DeleteVendorBusinessAssociateAgreementInput) (*types.DeleteVendorBusinessAssociateAgreementPayload, error) {
r.MustBeAuthorized(ctx, input.VendorID, authz.ActionDeleteVendorBusinessAssociateAgreement)
prb := r.ProboService(ctx, input.VendorID.TenantID())
err := prb.VendorBusinessAssociateAgreements.DeleteByVendorID(ctx, input.VendorID)
if err != nil {
panic(fmt.Errorf("cannot delete vendor business associate agreement: %w", err))
}
return &types.DeleteVendorBusinessAssociateAgreementPayload{
DeletedVendorID: input.VendorID,
}, nil
}
// UploadVendorDataPrivacyAgreement is the resolver for the uploadVendorDataPrivacyAgreement field.
func (r *mutationResolver) UploadVendorDataPrivacyAgreement(ctx context.Context, input types.UploadVendorDataPrivacyAgreementInput) (*types.UploadVendorDataPrivacyAgreementPayload, error) {
r.MustBeAuthorized(ctx, input.VendorID, authz.ActionUploadVendorDataPrivacyAgreement)
prb := r.ProboService(ctx, input.VendorID.TenantID())
vendorDataPrivacyAgreement, file, err := prb.VendorDataPrivacyAgreements.Upload(
ctx,
input.VendorID,
&probo.VendorDataPrivacyAgreementCreateRequest{
File: input.File.File,
ValidFrom: input.ValidFrom,
ValidUntil: input.ValidUntil,
FileName: input.FileName,
},
)
if err != nil {
panic(fmt.Errorf("cannot upload vendor data privacy agreement: %w", err))
}
return &types.UploadVendorDataPrivacyAgreementPayload{
VendorDataPrivacyAgreement: types.NewVendorDataPrivacyAgreement(vendorDataPrivacyAgreement, file),
}, nil
}
// UpdateVendorDataPrivacyAgreement is the resolver for the updateVendorDataPrivacyAgreement field.
func (r *mutationResolver) UpdateVendorDataPrivacyAgreement(ctx context.Context, input types.UpdateVendorDataPrivacyAgreementInput) (*types.UpdateVendorDataPrivacyAgreementPayload, error) {
r.MustBeAuthorized(ctx, input.VendorID, authz.ActionUpdateVendorDataPrivacyAgreement)
prb := r.ProboService(ctx, input.VendorID.TenantID())
vendorDataPrivacyAgreement, file, err := prb.VendorDataPrivacyAgreements.Update(
ctx,
input.VendorID,
&probo.VendorDataPrivacyAgreementUpdateRequest{
ValidFrom: UnwrapOmittable(input.ValidFrom),
ValidUntil: UnwrapOmittable(input.ValidUntil),
},
)
if err != nil {
panic(fmt.Errorf("cannot update vendor data privacy agreement: %w", err))
}
return &types.UpdateVendorDataPrivacyAgreementPayload{
VendorDataPrivacyAgreement: types.NewVendorDataPrivacyAgreement(vendorDataPrivacyAgreement, file),
}, nil
}
// DeleteVendorDataPrivacyAgreement is the resolver for the deleteVendorDataPrivacyAgreement field.
func (r *mutationResolver) DeleteVendorDataPrivacyAgreement(ctx context.Context, input types.DeleteVendorDataPrivacyAgreementInput) (*types.DeleteVendorDataPrivacyAgreementPayload, error) {
r.MustBeAuthorized(ctx, input.VendorID, authz.ActionDeleteVendorDataPrivacyAgreement)
prb := r.ProboService(ctx, input.VendorID.TenantID())
err := prb.VendorDataPrivacyAgreements.DeleteByVendorID(ctx, input.VendorID)
if err != nil {
panic(fmt.Errorf("cannot delete vendor data privacy agreement: %w", err))
}
return &types.DeleteVendorDataPrivacyAgreementPayload{
DeletedVendorID: input.VendorID,
}, nil
}
// CreateDocument is the resolver for the createDocument field.
func (r *mutationResolver) CreateDocument(ctx context.Context, input types.CreateDocumentInput) (*types.CreateDocumentPayload, error) {
r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionCreateDocument)
prb := r.ProboService(ctx, input.OrganizationID.TenantID())
document, documentVersion, err := prb.Documents.Create(
ctx,
probo.CreateDocumentRequest{
OrganizationID: input.OrganizationID,
DocumentType: input.DocumentType,
Title: input.Title,
OwnerID: input.OwnerID,
Content: input.Content,
Classification: input.Classification,
TrustCenterVisibility: input.TrustCenterVisibility,
},
)
if err != nil {
var errAlreadyExists *coredata.ErrDocumentAlreadyExists
if errors.As(err, &errAlreadyExists) {
return nil, gqlutils.Conflict(errAlreadyExists)
}
panic(fmt.Errorf("cannot create document: %w", err))
}
return &types.CreateDocumentPayload{
DocumentEdge: types.NewDocumentEdge(document, coredata.DocumentOrderFieldTitle),
DocumentVersionEdge: types.NewDocumentVersionEdge(documentVersion, coredata.DocumentVersionOrderFieldCreatedAt),
}, nil
}
// UpdateDocument is the resolver for the updateDocument field.
func (r *mutationResolver) UpdateDocument(ctx context.Context, input types.UpdateDocumentInput) (*types.UpdateDocumentPayload, error) {
r.MustBeAuthorized(ctx, input.ID, authz.ActionUpdateDocument)
prb := r.ProboService(ctx, input.ID.TenantID())
document, err := prb.Documents.Update(
ctx,
probo.UpdateDocumentRequest{
DocumentID: input.ID,
Title: input.Title,
OwnerID: input.OwnerID,
Classification: input.Classification,
DocumentType: input.DocumentType,
TrustCenterVisibility: input.TrustCenterVisibility,
},
)
if err != nil {
panic(fmt.Errorf("cannot update document: %w", err))
}
return &types.UpdateDocumentPayload{
Document: types.NewDocument(document),
}, nil
}
// DeleteDocument is the resolver for the deleteDocument field.
func (r *mutationResolver) DeleteDocument(ctx context.Context, input types.DeleteDocumentInput) (*types.DeleteDocumentPayload, error) {
r.MustBeAuthorized(ctx, input.DocumentID, authz.ActionDeleteDocument)
prb := r.ProboService(ctx, input.DocumentID.TenantID())
err := prb.Documents.SoftDelete(ctx, input.DocumentID)
if err != nil {
panic(fmt.Errorf("cannot soft delete document: %w", err))
}
return &types.DeleteDocumentPayload{
DeletedDocumentID: input.DocumentID,
}, nil
}
// CreateMeeting is the resolver for the createMeeting field.
func (r *mutationResolver) CreateMeeting(ctx context.Context, input types.CreateMeetingInput) (*types.CreateMeetingPayload, error) {
r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionCreateMeeting)
prb := r.ProboService(ctx, input.OrganizationID.TenantID())
meeting, err := prb.Meetings.Create(
ctx,
probo.CreateMeetingRequest{
OrganizationID: input.OrganizationID,
Name: input.Name,
Date: input.Date,
AttendeeIDs: input.AttendeeIds,
Minutes: input.Minutes,
},
)
if err != nil {
panic(fmt.Errorf("cannot create meeting: %w", err))
}
return &types.CreateMeetingPayload{
MeetingEdge: types.NewMeetingEdge(meeting, coredata.MeetingOrderFieldCreatedAt),
}, nil
}
// UpdateMeeting is the resolver for the updateMeeting field.
func (r *mutationResolver) UpdateMeeting(ctx context.Context, input types.UpdateMeetingInput) (*types.UpdateMeetingPayload, error) {
r.MustBeAuthorized(ctx, input.MeetingID, authz.ActionUpdateMeeting)
prb := r.ProboService(ctx, input.MeetingID.TenantID())
var attendeeIDs []gid.GID
if input.AttendeeIds != nil {
attendeeIDs = input.AttendeeIds
}
meeting, err := prb.Meetings.Update(
ctx,
probo.UpdateMeetingRequest{
MeetingID: input.MeetingID,
Name: input.Name,
Date: input.Date,
AttendeeIDs: attendeeIDs,
Minutes: UnwrapOmittable(input.Minutes),
},
)
if err != nil {
panic(fmt.Errorf("cannot update meeting: %w", err))
}
return &types.UpdateMeetingPayload{
Meeting: types.NewMeeting(meeting),
}, nil
}
// DeleteMeeting is the resolver for the deleteMeeting field.
func (r *mutationResolver) DeleteMeeting(ctx context.Context, input types.DeleteMeetingInput) (*types.DeleteMeetingPayload, error) {
r.MustBeAuthorized(ctx, input.MeetingID, authz.ActionDeleteMeeting)
prb := r.ProboService(ctx, input.MeetingID.TenantID())
err := prb.Meetings.Delete(ctx, input.MeetingID)
if err != nil {
panic(fmt.Errorf("cannot delete meeting: %w", err))
}
return &types.DeleteMeetingPayload{
DeletedMeetingID: input.MeetingID,
}, nil
}
// PublishDocumentVersion is the resolver for the publishDocumentVersion field.
func (r *mutationResolver) PublishDocumentVersion(ctx context.Context, input types.PublishDocumentVersionInput) (*types.PublishDocumentVersionPayload, error) {
r.MustBeAuthorized(ctx, input.DocumentID, authz.ActionPublishDocumentVersion)
prb := r.ProboService(ctx, input.DocumentID.TenantID())
user := UserFromContext(ctx)
document, documentVersion, err := prb.Documents.PublishVersion(ctx, input.DocumentID, user.ID, input.Changelog)
if err != nil {
var errNoChanges *coredata.ErrDocumentVersionNoChanges
if errors.As(err, &errNoChanges) {
return nil, gqlutils.Invalid(errNoChanges, nil)
}
panic(fmt.Errorf("cannot publish document version: %w", err))
}
return &types.PublishDocumentVersionPayload{
DocumentVersion: types.NewDocumentVersion(documentVersion),
Document: types.NewDocument(document),
}, nil
}
// BulkPublishDocumentVersions is the resolver for the bulkPublishDocumentVersions field.
func (r *mutationResolver) BulkPublishDocumentVersions(ctx context.Context, input types.BulkPublishDocumentVersionsInput) (*types.BulkPublishDocumentVersionsPayload, error) {
if len(input.DocumentIds) == 0 {
return &types.BulkPublishDocumentVersionsPayload{
DocumentVersionEdges: []*types.DocumentVersionEdge{},
DocumentEdges: []*types.DocumentEdge{},
}, nil
}
r.MustBeAuthorized(ctx, input.DocumentIds[0], authz.ActionBulkPublishDocumentVersions)
prb := r.ProboService(ctx, input.DocumentIds[0].TenantID())
user := UserFromContext(ctx)
documentVersions, documents, err := prb.Documents.BulkPublishVersions(
ctx,
probo.BulkPublishVersionsRequest{
DocumentIDs: input.DocumentIds,
PublishedBy: user.ID,
Changelog: input.Changelog,
},
)
if err != nil {
var errNoChanges *coredata.ErrDocumentVersionNoChanges
if errors.As(err, &errNoChanges) {
return nil, gqlutils.Invalid(errNoChanges, nil)
}
panic(fmt.Errorf("cannot bulk publish document versions: %w", err))
}
return &types.BulkPublishDocumentVersionsPayload{
DocumentVersionEdges: types.NewDocumentVersionEdges(documentVersions, coredata.DocumentVersionOrderFieldCreatedAt),
DocumentEdges: types.NewDocumentEdges(documents, coredata.DocumentOrderFieldTitle),
}, nil
}
// BulkDeleteDocuments is the resolver for the bulkDeleteDocuments field.
func (r *mutationResolver) BulkDeleteDocuments(ctx context.Context, input types.BulkDeleteDocumentsInput) (*types.BulkDeleteDocumentsPayload, error) {
if len(input.DocumentIds) == 0 {
return &types.BulkDeleteDocumentsPayload{
DeletedDocumentIds: []gid.GID{},
}, nil
}
r.MustBeAuthorized(ctx, input.DocumentIds[0], authz.ActionBulkDeleteDocuments)
prb := r.ProboService(ctx, input.DocumentIds[0].TenantID())
err := prb.Documents.BulkSoftDelete(ctx, input.DocumentIds)
if err != nil {
panic(fmt.Errorf("cannot bulk delete documents: %w", err))
}
return &types.BulkDeleteDocumentsPayload{
DeletedDocumentIds: input.DocumentIds,
}, nil
}
// BulkExportDocuments is the resolver for the bulkExportDocuments field.
func (r *mutationResolver) BulkExportDocuments(ctx context.Context, input types.BulkExportDocumentsInput) (*types.BulkExportDocumentsPayload, error) {
if len(input.DocumentIds) == 0 {
panic(fmt.Errorf("no document ids provided"))
}
r.MustBeAuthorized(ctx, input.DocumentIds[0], authz.ActionBulkExportDocuments)
prb := r.ProboService(ctx, input.DocumentIds[0].TenantID())
user := UserFromContext(ctx)
options := probo.ExportPDFOptions{
WithWatermark: input.WithWatermark,
WithSignatures: input.WithSignatures,
WatermarkEmail: input.WatermarkEmail,
}
documentExport, err := prb.Documents.RequestExport(ctx, input.DocumentIds, user.EmailAddress, user.FullName, options)
if err != nil {
panic(fmt.Errorf("cannot request document export: %w", err))
}
return &types.BulkExportDocumentsPayload{
ExportJobID: documentExport.ID,
}, nil
}
// GenerateDocumentChangelog is the resolver for the generateDocumentChangelog field.
func (r *mutationResolver) GenerateDocumentChangelog(ctx context.Context, input types.GenerateDocumentChangelogInput) (*types.GenerateDocumentChangelogPayload, error) {
r.MustBeAuthorized(ctx, input.DocumentID, authz.ActionGenerateDocumentChangelog)
prb := r.ProboService(ctx, input.DocumentID.TenantID())
changelog, err := prb.Documents.GenerateChangelog(ctx, input.DocumentID)
if err != nil {
panic(fmt.Errorf("cannot generate document changelog: %w", err))
}
return &types.GenerateDocumentChangelogPayload{
Changelog: *changelog,
}, nil
}
// CreateDraftDocumentVersion is the resolver for the createDraftDocumentVersion field.
func (r *mutationResolver) CreateDraftDocumentVersion(ctx context.Context, input types.CreateDraftDocumentVersionInput) (*types.CreateDraftDocumentVersionPayload, error) {
r.MustBeAuthorized(ctx, input.DocumentID, authz.ActionCreateDraftDocumentVersion)
prb := r.ProboService(ctx, input.DocumentID.TenantID())
documentVersion, err := prb.Documents.CreateDraft(ctx, input.DocumentID)
if err != nil {
panic(fmt.Errorf("cannot create draft document version: %w", err))
}
return &types.CreateDraftDocumentVersionPayload{
DocumentVersionEdge: types.NewDocumentVersionEdge(documentVersion, coredata.DocumentVersionOrderFieldCreatedAt),
}, nil
}
// DeleteDraftDocumentVersion is the resolver for the deleteDraftDocumentVersion field.
func (r *mutationResolver) DeleteDraftDocumentVersion(ctx context.Context, input types.DeleteDraftDocumentVersionInput) (*types.DeleteDraftDocumentVersionPayload, error) {
r.MustBeAuthorized(ctx, input.DocumentVersionID, authz.ActionDeleteDraftDocumentVersion)
prb := r.ProboService(ctx, input.DocumentVersionID.TenantID())
err := prb.Documents.DeleteDraft(ctx, input.DocumentVersionID)
if err != nil {
panic(fmt.Errorf("cannot delete draft document version: %w", err))
}
return &types.DeleteDraftDocumentVersionPayload{
DeletedDocumentVersionID: input.DocumentVersionID,
}, nil
}
// UpdateDocumentVersion is the resolver for the updateDocumentVersion field.
func (r *mutationResolver) UpdateDocumentVersion(ctx context.Context, input types.UpdateDocumentVersionInput) (*types.UpdateDocumentVersionPayload, error) {
r.MustBeAuthorized(ctx, input.DocumentVersionID, authz.ActionUpdateDocumentVersion)
prb := r.ProboService(ctx, input.DocumentVersionID.TenantID())
documentVersion, err := prb.Documents.UpdateVersion(ctx, probo.UpdateDocumentVersionRequest{
ID: input.DocumentVersionID,
Content: input.Content,
})
if err != nil {
panic(fmt.Errorf("cannot update document version: %w", err))
}
return &types.UpdateDocumentVersionPayload{
DocumentVersion: types.NewDocumentVersion(documentVersion),
}, nil
}
// RequestSignature is the resolver for the requestSignature field.
func (r *mutationResolver) RequestSignature(ctx context.Context, input types.RequestSignatureInput) (*types.RequestSignaturePayload, error) {
r.MustBeAuthorized(ctx, input.DocumentVersionID, authz.ActionRequestSignature)
prb := r.ProboService(ctx, input.DocumentVersionID.TenantID())
documentVersionSignature, err := prb.Documents.RequestSignature(
ctx,
probo.RequestSignatureRequest{
DocumentVersionID: input.DocumentVersionID,
Signatory: input.SignatoryID,
},
)
if err != nil {
panic(fmt.Errorf("cannot request signature: %w", err))
}
return &types.RequestSignaturePayload{
DocumentVersionSignatureEdge: types.NewDocumentVersionSignatureEdge(documentVersionSignature, coredata.DocumentVersionSignatureOrderFieldCreatedAt),
}, nil
}
// BulkRequestSignatures is the resolver for the bulkRequestSignatures field.
func (r *mutationResolver) BulkRequestSignatures(ctx context.Context, input types.BulkRequestSignaturesInput) (*types.BulkRequestSignaturesPayload, error) {
if len(input.DocumentIds) == 0 {
return &types.BulkRequestSignaturesPayload{
DocumentVersionSignatureEdges: []*types.DocumentVersionSignatureEdge{},
}, nil
}
r.MustBeAuthorized(ctx, input.DocumentIds[0], authz.ActionBulkRequestSignatures)
prb := r.ProboService(ctx, input.DocumentIds[0].TenantID())
documentVersionSignatures, err := prb.Documents.BulkRequestSignatures(
ctx,
probo.BulkRequestSignaturesRequest{
DocumentIDs: input.DocumentIds,
SignatoryIDs: input.SignatoryIds,
},
)
if err != nil {
panic(fmt.Errorf("cannot bulk request signatures: %w", err))
}
return &types.BulkRequestSignaturesPayload{
DocumentVersionSignatureEdges: types.NewDocumentVersionSignatureEdges(documentVersionSignatures, coredata.DocumentVersionSignatureOrderFieldCreatedAt),
}, nil
}
// SendSigningNotifications is the resolver for the sendSigningNotifications field.
func (r *mutationResolver) SendSigningNotifications(ctx context.Context, input types.SendSigningNotificationsInput) (*types.SendSigningNotificationsPayload, error) {
r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionSendSigningNotifications)
prb := r.ProboService(ctx, input.OrganizationID.TenantID())
err := prb.Documents.SendSigningNotifications(ctx, input.OrganizationID)
if err != nil {
panic(fmt.Errorf("cannot send signing notifications: %w", err))
}
return &types.SendSigningNotificationsPayload{
Success: true,
}, nil
}
// CancelSignatureRequest is the resolver for the cancelSignatureRequest field.
func (r *mutationResolver) CancelSignatureRequest(ctx context.Context, input types.CancelSignatureRequestInput) (*types.CancelSignatureRequestPayload, error) {
r.MustBeAuthorized(ctx, input.DocumentVersionSignatureID, authz.ActionCancelSignatureRequest)
prb := r.ProboService(ctx, input.DocumentVersionSignatureID.TenantID())
err := prb.Documents.CancelSignatureRequest(ctx, input.DocumentVersionSignatureID)
if err != nil {
panic(fmt.Errorf("cannot cancel signature request: %w", err))
}
return &types.CancelSignatureRequestPayload{
DeletedDocumentVersionSignatureID: input.DocumentVersionSignatureID,
}, nil
}
// SignDocument is the resolver for the signDocument field.
func (r *mutationResolver) SignDocument(ctx context.Context, input types.SignDocumentInput) (*types.SignDocumentPayload, error) {
r.MustBeAuthorized(ctx, input.DocumentVersionID, authz.ActionSignDocument)
user := UserFromContext(ctx)
if user == nil {
panic(fmt.Errorf("user not found in context"))
}
prb := r.ProboService(ctx, input.DocumentVersionID.TenantID())
documentVersionSignature, err := prb.Documents.SignDocumentVersionByEmail(ctx, input.DocumentVersionID, user.EmailAddress)
if err != nil {
var errAlreadySigned *coredata.ErrDocumentVersionSignatureAlreadySigned
if errors.As(err, &errAlreadySigned) {
return nil, gqlutils.Conflict(errAlreadySigned)
}
panic(fmt.Errorf("cannot sign document: %w", err))
}
return &types.SignDocumentPayload{
DocumentVersionSignature: types.NewDocumentVersionSignature(documentVersionSignature),
}, nil
}
// ExportDocumentVersionPDF is the resolver for the exportDocumentVersionPDF field.
func (r *mutationResolver) ExportDocumentVersionPDF(ctx context.Context, input types.ExportDocumentVersionPDFInput) (*types.ExportDocumentVersionPDFPayload, error) {
r.MustBeAuthorized(ctx, input.DocumentVersionID, authz.ActionExportDocumentVersionPDF)
prb := r.ProboService(ctx, input.DocumentVersionID.TenantID())
options := probo.ExportPDFOptions{
WithSignatures: input.WithSignatures,
WithWatermark: input.WithWatermark,
WatermarkEmail: input.WatermarkEmail,
}
pdf, err := prb.Documents.ExportPDF(ctx, input.DocumentVersionID, options)
if err != nil {
panic(fmt.Errorf("cannot export document version PDF: %w", err))
}
return &types.ExportDocumentVersionPDFPayload{
Data: fmt.Sprintf("data:application/pdf;base64,%s", base64.StdEncoding.EncodeToString(pdf)),
}, nil
}
// ExportSignableVersionDocumentPDF is the resolver for the exportSignableVersionDocumentPDF field.
func (r *mutationResolver) ExportSignableVersionDocumentPDF(ctx context.Context, input types.ExportSignableDocumentVersionPDFInput) (*types.ExportSignableDocumentVersionPDFPayload, error) {
r.MustBeAuthorized(ctx, input.DocumentVersionID, authz.ActionExportSignableVersionDocumentPDF)
prb := r.ProboService(ctx, input.DocumentVersionID.TenantID())
documentVersion, err := prb.Documents.GetVersion(ctx, input.DocumentVersionID)
if err != nil {
panic(fmt.Errorf("cannot get document version: %w", err))
}
user := UserFromContext(ctx)
if user == nil {
panic(fmt.Errorf("user not found in context"))
}
documentFilter := coredata.NewDocumentFilter(nil).WithUserEmail(&user.EmailAddress)
_, err = prb.Documents.GetWithFilter(ctx, documentVersion.DocumentID, documentFilter)
if err != nil {
var errNotFound *coredata.ErrDocumentNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get signable document: %w", err))
}
options := probo.ExportPDFOptions{
WithSignatures: false,
WithWatermark: true,
WatermarkEmail: &user.EmailAddress,
}
pdf, err := prb.Documents.ExportPDF(ctx, input.DocumentVersionID, options)
if err != nil {
panic(fmt.Errorf("cannot export signable document PDF: %w", err))
}
return &types.ExportSignableDocumentVersionPDFPayload{
Data: fmt.Sprintf("data:application/pdf;base64,%s", base64.StdEncoding.EncodeToString(pdf)),
}, nil
}
// CreateVendorRiskAssessment is the resolver for the createVendorRiskAssessment field.
func (r *mutationResolver) CreateVendorRiskAssessment(ctx context.Context, input types.CreateVendorRiskAssessmentInput) (*types.CreateVendorRiskAssessmentPayload, error) {
r.MustBeAuthorized(ctx, input.VendorID, authz.ActionCreateVendorRiskAssessment)
prb := r.ProboService(ctx, input.VendorID.TenantID())
vendorRiskAssessment, err := prb.Vendors.CreateRiskAssessment(
ctx,
probo.CreateVendorRiskAssessmentRequest{
VendorID: input.VendorID,
ExpiresAt: input.ExpiresAt,
DataSensitivity: input.DataSensitivity,
BusinessImpact: input.BusinessImpact,
Notes: input.Notes,
},
)
if err != nil {
panic(fmt.Errorf("cannot create vendor risk assessment: %w", err))
}
return &types.CreateVendorRiskAssessmentPayload{
VendorRiskAssessmentEdge: types.NewVendorRiskAssessmentEdge(vendorRiskAssessment, coredata.VendorRiskAssessmentOrderFieldCreatedAt),
}, nil
}
// AssessVendor is the resolver for the assessVendor field.
func (r *mutationResolver) AssessVendor(ctx context.Context, input types.AssessVendorInput) (*types.AssessVendorPayload, error) {
r.MustBeAuthorized(ctx, input.ID, authz.ActionAssessVendor)
prb := r.ProboService(ctx, input.ID.TenantID())
vendor, err := prb.Vendors.Assess(ctx, probo.AssessVendorRequest{
ID: input.ID,
WebsiteURL: input.WebsiteURL,
})
if err != nil {
panic(fmt.Errorf("cannot assess vendor: %w", err))
}
return &types.AssessVendorPayload{
Vendor: types.NewVendor(vendor),
}, nil
}
// CreateAsset is the resolver for the createAsset field.
func (r *mutationResolver) CreateAsset(ctx context.Context, input types.CreateAssetInput) (*types.CreateAssetPayload, error) {
r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionCreateAsset)
prb := r.ProboService(ctx, input.OrganizationID.TenantID())
asset, err := prb.Assets.Create(ctx, probo.CreateAssetRequest{
OrganizationID: input.OrganizationID,
Name: input.Name,
Amount: input.Amount,
OwnerID: input.OwnerID,
AssetType: input.AssetType,
DataTypesStored: input.DataTypesStored,
VendorIDs: input.VendorIds,
})
if err != nil {
panic(fmt.Errorf("cannot create asset: %w", err))
}
return &types.CreateAssetPayload{
AssetEdge: types.NewAssetEdge(asset, coredata.AssetOrderFieldCreatedAt),
}, nil
}
// UpdateAsset is the resolver for the updateAsset field.
func (r *mutationResolver) UpdateAsset(ctx context.Context, input types.UpdateAssetInput) (*types.UpdateAssetPayload, error) {
r.MustBeAuthorized(ctx, input.ID, authz.ActionUpdateAsset)
prb := r.ProboService(ctx, input.ID.TenantID())
asset, err := prb.Assets.Update(ctx, probo.UpdateAssetRequest{
ID: input.ID,
Name: input.Name,
Amount: input.Amount,
OwnerID: input.OwnerID,
AssetType: input.AssetType,
DataTypesStored: input.DataTypesStored,
VendorIDs: input.VendorIds,
})
if err != nil {
panic(fmt.Errorf("cannot update asset: %w", err))
}
return &types.UpdateAssetPayload{
Asset: types.NewAsset(asset),
}, nil
}
// DeleteAsset is the resolver for the deleteAsset field.
func (r *mutationResolver) DeleteAsset(ctx context.Context, input types.DeleteAssetInput) (*types.DeleteAssetPayload, error) {
r.MustBeAuthorized(ctx, input.AssetID, authz.ActionDeleteAsset)
prb := r.ProboService(ctx, input.AssetID.TenantID())
err := prb.Assets.Delete(ctx, input.AssetID)
if err != nil {
panic(fmt.Errorf("cannot delete asset: %w", err))
}
return &types.DeleteAssetPayload{
DeletedAssetID: input.AssetID,
}, nil
}
// CreateDatum is the resolver for the createDatum field.
func (r *mutationResolver) CreateDatum(ctx context.Context, input types.CreateDatumInput) (*types.CreateDatumPayload, error) {
r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionCreateDatum)
prb := r.ProboService(ctx, input.OrganizationID.TenantID())
data, err := prb.Data.Create(ctx, probo.CreateDatumRequest{
OrganizationID: input.OrganizationID,
Name: input.Name,
DataClassification: input.DataClassification,
OwnerID: input.OwnerID,
VendorIDs: input.VendorIds,
})
if err != nil {
panic(fmt.Errorf("cannot create datum: %w", err))
}
return &types.CreateDatumPayload{
DatumEdge: types.NewDatumEdge(data, coredata.DatumOrderFieldCreatedAt),
}, nil
}
// UpdateDatum is the resolver for the updateDatum field.
func (r *mutationResolver) UpdateDatum(ctx context.Context, input types.UpdateDatumInput) (*types.UpdateDatumPayload, error) {
r.MustBeAuthorized(ctx, input.ID, authz.ActionUpdateDatum)
prb := r.ProboService(ctx, input.ID.TenantID())
datum, err := prb.Data.Update(ctx, probo.UpdateDatumRequest{
ID: input.ID,
Name: input.Name,
DataClassification: input.DataClassification,
OwnerID: input.OwnerID,
VendorIDs: input.VendorIds,
})
if err != nil {
panic(fmt.Errorf("cannot update datum: %w", err))
}
return &types.UpdateDatumPayload{
Datum: types.NewDatum(datum),
}, nil
}
// DeleteDatum is the resolver for the deleteDatum field.
func (r *mutationResolver) DeleteDatum(ctx context.Context, input types.DeleteDatumInput) (*types.DeleteDatumPayload, error) {
r.MustBeAuthorized(ctx, input.DatumID, authz.ActionDeleteDatum)
prb := r.ProboService(ctx, input.DatumID.TenantID())
if err := prb.Data.Delete(ctx, input.DatumID); err != nil {
panic(fmt.Errorf("cannot delete datum: %w", err))
}
return &types.DeleteDatumPayload{
DeletedDatumID: input.DatumID,
}, nil
}
// CreateAudit is the resolver for the createAudit field.
func (r *mutationResolver) CreateAudit(ctx context.Context, input types.CreateAuditInput) (*types.CreateAuditPayload, error) {
r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionCreateAudit)
prb := r.ProboService(ctx, input.OrganizationID.TenantID())
req := probo.CreateAuditRequest{
OrganizationID: input.OrganizationID,
FrameworkID: input.FrameworkID,
Name: input.Name,
ValidFrom: input.ValidFrom,
ValidUntil: input.ValidUntil,
State: input.State,
TrustCenterVisibility: input.TrustCenterVisibility,
}
audit, err := prb.Audits.Create(ctx, &req)
if err != nil {
panic(fmt.Errorf("cannot create audit: %w", err))
}
return &types.CreateAuditPayload{
AuditEdge: types.NewAuditEdge(audit, coredata.AuditOrderFieldCreatedAt),
}, nil
}
// UpdateAudit is the resolver for the updateAudit field.
func (r *mutationResolver) UpdateAudit(ctx context.Context, input types.UpdateAuditInput) (*types.UpdateAuditPayload, error) {
r.MustBeAuthorized(ctx, input.ID, authz.ActionUpdateAudit)
prb := r.ProboService(ctx, input.ID.TenantID())
req := probo.UpdateAuditRequest{
ID: input.ID,
Name: UnwrapOmittable(input.Name),
ValidFrom: input.ValidFrom,
ValidUntil: input.ValidUntil,
State: input.State,
TrustCenterVisibility: input.TrustCenterVisibility,
}
audit, err := prb.Audits.Update(ctx, &req)
if err != nil {
panic(fmt.Errorf("cannot update audit: %w", err))
}
return &types.UpdateAuditPayload{
Audit: types.NewAudit(audit),
}, nil
}
// DeleteAudit is the resolver for the deleteAudit field.
func (r *mutationResolver) DeleteAudit(ctx context.Context, input types.DeleteAuditInput) (*types.DeleteAuditPayload, error) {
r.MustBeAuthorized(ctx, input.AuditID, authz.ActionDeleteAudit)
prb := r.ProboService(ctx, input.AuditID.TenantID())
err := prb.Audits.Delete(ctx, input.AuditID)
if err != nil {
panic(fmt.Errorf("cannot delete audit: %w", err))
}
return &types.DeleteAuditPayload{
DeletedAuditID: input.AuditID,
}, nil
}
// UploadAuditReport is the resolver for the uploadAuditReport field.
func (r *mutationResolver) UploadAuditReport(ctx context.Context, input types.UploadAuditReportInput) (*types.UploadAuditReportPayload, error) {
r.MustBeAuthorized(ctx, input.AuditID, authz.ActionUploadAuditReport)
prb := r.ProboService(ctx, input.AuditID.TenantID())
req := probo.UploadAuditReportRequest{
AuditID: input.AuditID,
File: probo.File{
Content: input.File.File,
Filename: input.File.Filename,
Size: input.File.Size,
ContentType: input.File.ContentType,
},
}
audit, err := prb.Audits.UploadReport(ctx, req)
if err != nil {
panic(fmt.Errorf("cannot upload audit report: %w", err))
}
return &types.UploadAuditReportPayload{
Audit: types.NewAudit(audit),
}, nil
}
// DeleteAuditReport is the resolver for the deleteAuditReport field.
func (r *mutationResolver) DeleteAuditReport(ctx context.Context, input types.DeleteAuditReportInput) (*types.DeleteAuditReportPayload, error) {
r.MustBeAuthorized(ctx, input.AuditID, authz.ActionDeleteAuditReport)
prb := r.ProboService(ctx, input.AuditID.TenantID())
audit, err := prb.Audits.DeleteReport(ctx, input.AuditID)
if err != nil {
panic(fmt.Errorf("cannot delete audit report: %w", err))
}
return &types.DeleteAuditReportPayload{
Audit: types.NewAudit(audit),
}, nil
}
// CreateNonconformity is the resolver for the createNonconformity field.
func (r *mutationResolver) CreateNonconformity(ctx context.Context, input types.CreateNonconformityInput) (*types.CreateNonconformityPayload, error) {
r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionCreateNonconformity)
prb := r.ProboService(ctx, input.OrganizationID.TenantID())
req := probo.CreateNonconformityRequest{
OrganizationID: input.OrganizationID,
ReferenceID: input.ReferenceID,
Description: input.Description,
AuditID: input.AuditID,
DateIdentified: input.DateIdentified,
RootCause: input.RootCause,
CorrectiveAction: input.CorrectiveAction,
OwnerID: input.OwnerID,
DueDate: input.DueDate,
Status: &input.Status,
EffectivenessCheck: input.EffectivenessCheck,
}
nonconformity, err := prb.Nonconformities.Create(ctx, &req)
if err != nil {
panic(fmt.Errorf("cannot create nonconformity: %w", err))
}
return &types.CreateNonconformityPayload{
NonconformityEdge: types.NewNonconformityEdge(nonconformity, coredata.NonconformityOrderFieldCreatedAt),
}, nil
}
// UpdateNonconformity is the resolver for the updateNonconformity field.
func (r *mutationResolver) UpdateNonconformity(ctx context.Context, input types.UpdateNonconformityInput) (*types.UpdateNonconformityPayload, error) {
r.MustBeAuthorized(ctx, input.ID, authz.ActionUpdateNonconformity)
prb := r.ProboService(ctx, input.ID.TenantID())
req := probo.UpdateNonconformityRequest{
ID: input.ID,
ReferenceID: input.ReferenceID,
Description: UnwrapOmittable(input.Description),
DateIdentified: UnwrapOmittable(input.DateIdentified),
RootCause: input.RootCause,
CorrectiveAction: UnwrapOmittable(input.CorrectiveAction),
OwnerID: input.OwnerID,
AuditID: UnwrapOmittable(input.AuditID),
DueDate: UnwrapOmittable(input.DueDate),
Status: input.Status,
EffectivenessCheck: UnwrapOmittable(input.EffectivenessCheck),
}
nonconformity, err := prb.Nonconformities.Update(ctx, &req)
if err != nil {
panic(fmt.Errorf("cannot update nonconformity: %w", err))
}
return &types.UpdateNonconformityPayload{
Nonconformity: types.NewNonconformity(nonconformity),
}, nil
}
// DeleteNonconformity is the resolver for the deleteNonconformity field.
func (r *mutationResolver) DeleteNonconformity(ctx context.Context, input types.DeleteNonconformityInput) (*types.DeleteNonconformityPayload, error) {
r.MustBeAuthorized(ctx, input.NonconformityID, authz.ActionDeleteNonconformity)
prb := r.ProboService(ctx, input.NonconformityID.TenantID())
err := prb.Nonconformities.Delete(ctx, input.NonconformityID)
if err != nil {
panic(fmt.Errorf("cannot delete nonconformity: %w", err))
}
return &types.DeleteNonconformityPayload{
DeletedNonconformityID: input.NonconformityID,
}, nil
}
// CreateObligation is the resolver for the createObligation field.
func (r *mutationResolver) CreateObligation(ctx context.Context, input types.CreateObligationInput) (*types.CreateObligationPayload, error) {
r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionCreateObligation)
prb := r.ProboService(ctx, input.OrganizationID.TenantID())
req := probo.CreateObligationRequest{
OrganizationID: input.OrganizationID,
Area: input.Area,
Source: input.Source,
Requirement: input.Requirement,
ActionsToBeImplemented: input.ActionsToBeImplemented,
Regulator: input.Regulator,
OwnerID: input.OwnerID,
LastReviewDate: input.LastReviewDate,
DueDate: input.DueDate,
Status: &input.Status,
}
obligation, err := prb.Obligations.Create(ctx, &req)
if err != nil {
panic(fmt.Errorf("cannot create obligation: %w", err))
}
return &types.CreateObligationPayload{
ObligationEdge: types.NewObligationEdge(obligation, coredata.ObligationOrderFieldCreatedAt),
}, nil
}
// UpdateObligation is the resolver for the updateObligation field.
func (r *mutationResolver) UpdateObligation(ctx context.Context, input types.UpdateObligationInput) (*types.UpdateObligationPayload, error) {
r.MustBeAuthorized(ctx, input.ID, authz.ActionUpdateObligation)
prb := r.ProboService(ctx, input.ID.TenantID())
req := probo.UpdateObligationRequest{
ID: input.ID,
Area: UnwrapOmittable(input.Area),
Source: UnwrapOmittable(input.Source),
Requirement: UnwrapOmittable(input.Requirement),
ActionsToBeImplemented: UnwrapOmittable(input.ActionsToBeImplemented),
Regulator: UnwrapOmittable(input.Regulator),
OwnerID: input.OwnerID,
LastReviewDate: UnwrapOmittable(input.LastReviewDate),
DueDate: UnwrapOmittable(input.DueDate),
Status: input.Status,
}
obligation, err := prb.Obligations.Update(ctx, &req)
if err != nil {
panic(fmt.Errorf("cannot update obligation: %w", err))
}
return &types.UpdateObligationPayload{
Obligation: types.NewObligation(obligation),
}, nil
}
// DeleteObligation is the resolver for the deleteObligation field.
func (r *mutationResolver) DeleteObligation(ctx context.Context, input types.DeleteObligationInput) (*types.DeleteObligationPayload, error) {
r.MustBeAuthorized(ctx, input.ObligationID, authz.ActionDeleteObligation)
prb := r.ProboService(ctx, input.ObligationID.TenantID())
err := prb.Obligations.Delete(ctx, input.ObligationID)
if err != nil {
panic(fmt.Errorf("cannot delete obligation: %w", err))
}
return &types.DeleteObligationPayload{
DeletedObligationID: input.ObligationID,
}, nil
}
// CreateContinualImprovement is the resolver for the createContinualImprovement field.
func (r *mutationResolver) CreateContinualImprovement(ctx context.Context, input types.CreateContinualImprovementInput) (*types.CreateContinualImprovementPayload, error) {
r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionCreateContinualImprovement)
prb := r.ProboService(ctx, input.OrganizationID.TenantID())
req := probo.CreateContinualImprovementRequest{
OrganizationID: input.OrganizationID,
ReferenceID: input.ReferenceID,
Description: input.Description,
Source: input.Source,
OwnerID: input.OwnerID,
TargetDate: input.TargetDate,
Status: &input.Status,
Priority: &input.Priority,
}
continualImprovement, err := prb.ContinualImprovements.Create(ctx, &req)
if err != nil {
panic(fmt.Errorf("cannot create continual improvement: %w", err))
}
return &types.CreateContinualImprovementPayload{
ContinualImprovementEdge: types.NewContinualImprovementEdge(continualImprovement, coredata.ContinualImprovementOrderFieldCreatedAt),
}, nil
}
// UpdateContinualImprovement is the resolver for the updateContinualImprovement field.
func (r *mutationResolver) UpdateContinualImprovement(ctx context.Context, input types.UpdateContinualImprovementInput) (*types.UpdateContinualImprovementPayload, error) {
r.MustBeAuthorized(ctx, input.ID, authz.ActionUpdateContinualImprovement)
prb := r.ProboService(ctx, input.ID.TenantID())
req := probo.UpdateContinualImprovementRequest{
ID: input.ID,
ReferenceID: input.ReferenceID,
Description: UnwrapOmittable(input.Description),
Source: UnwrapOmittable(input.Source),
OwnerID: input.OwnerID,
TargetDate: UnwrapOmittable(input.TargetDate),
Status: input.Status,
Priority: input.Priority,
}
continualImprovement, err := prb.ContinualImprovements.Update(ctx, &req)
if err != nil {
panic(fmt.Errorf("cannot update continual improvement: %w", err))
}
return &types.UpdateContinualImprovementPayload{
ContinualImprovement: types.NewContinualImprovement(continualImprovement),
}, nil
}
// DeleteContinualImprovement is the resolver for the deleteContinualImprovement field.
func (r *mutationResolver) DeleteContinualImprovement(ctx context.Context, input types.DeleteContinualImprovementInput) (*types.DeleteContinualImprovementPayload, error) {
r.MustBeAuthorized(ctx, input.ContinualImprovementID, authz.ActionDeleteContinualImprovement)
prb := r.ProboService(ctx, input.ContinualImprovementID.TenantID())
err := prb.ContinualImprovements.Delete(ctx, input.ContinualImprovementID)
if err != nil {
panic(fmt.Errorf("cannot delete continual improvement: %w", err))
}
return &types.DeleteContinualImprovementPayload{
DeletedContinualImprovementID: input.ContinualImprovementID,
}, nil
}
// CreateProcessingActivity is the resolver for the createProcessingActivity field.
func (r *mutationResolver) CreateProcessingActivity(ctx context.Context, input types.CreateProcessingActivityInput) (*types.CreateProcessingActivityPayload, error) {
r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionCreateProcessingActivity)
prb := r.ProboService(ctx, input.OrganizationID.TenantID())
req := probo.CreateProcessingActivityRequest{
OrganizationID: input.OrganizationID,
Name: input.Name,
Purpose: input.Purpose,
DataSubjectCategory: input.DataSubjectCategory,
PersonalDataCategory: input.PersonalDataCategory,
SpecialOrCriminalData: input.SpecialOrCriminalData,
LawfulBasis: input.LawfulBasis,
Recipients: input.Recipients,
Location: input.Location,
InternationalTransfers: input.InternationalTransfers,
TransferSafeguard: input.TransferSafeguards,
RetentionPeriod: input.RetentionPeriod,
SecurityMeasures: input.SecurityMeasures,
DataProtectionImpactAssessmentNeeded: input.DataProtectionImpactAssessmentNeeded,
TransferImpactAssessmentNeeded: input.TransferImpactAssessmentNeeded,
LastReviewDate: input.LastReviewDate,
NextReviewDate: input.NextReviewDate,
Role: input.Role,
DataProtectionOfficerID: input.DataProtectionOfficerID,
VendorIDs: input.VendorIds,
}
activity, err := prb.ProcessingActivities.Create(ctx, &req)
if err != nil {
panic(fmt.Errorf("cannot create processing activity: %w", err))
}
return &types.CreateProcessingActivityPayload{
ProcessingActivityEdge: types.NewProcessingActivityEdge(activity, coredata.ProcessingActivityOrderFieldCreatedAt),
}, nil
}
// UpdateProcessingActivity is the resolver for the updateProcessingActivity field.
func (r *mutationResolver) UpdateProcessingActivity(ctx context.Context, input types.UpdateProcessingActivityInput) (*types.UpdateProcessingActivityPayload, error) {
r.MustBeAuthorized(ctx, input.ID, authz.ActionUpdateProcessingActivity)
prb := r.ProboService(ctx, input.ID.TenantID())
req := probo.UpdateProcessingActivityRequest{
ID: input.ID,
Name: input.Name,
Purpose: UnwrapOmittable(input.Purpose),
DataSubjectCategory: UnwrapOmittable(input.DataSubjectCategory),
PersonalDataCategory: UnwrapOmittable(input.PersonalDataCategory),
SpecialOrCriminalData: input.SpecialOrCriminalData,
LawfulBasis: input.LawfulBasis,
Recipients: UnwrapOmittable(input.Recipients),
Location: UnwrapOmittable(input.Location),
InternationalTransfers: input.InternationalTransfers,
TransferSafeguard: UnwrapOmittable(input.TransferSafeguards),
RetentionPeriod: UnwrapOmittable(input.RetentionPeriod),
SecurityMeasures: UnwrapOmittable(input.SecurityMeasures),
DataProtectionImpactAssessmentNeeded: input.DataProtectionImpactAssessmentNeeded,
TransferImpactAssessmentNeeded: input.TransferImpactAssessmentNeeded,
LastReviewDate: UnwrapOmittable(input.LastReviewDate),
NextReviewDate: UnwrapOmittable(input.NextReviewDate),
Role: input.Role,
DataProtectionOfficerID: UnwrapOmittable(input.DataProtectionOfficerID),
VendorIDs: &input.VendorIds,
}
activity, err := prb.ProcessingActivities.Update(ctx, &req)
if err != nil {
panic(fmt.Errorf("cannot update processing activity: %w", err))
}
return &types.UpdateProcessingActivityPayload{
ProcessingActivity: types.NewProcessingActivity(activity),
}, nil
}
// DeleteProcessingActivity is the resolver for the deleteProcessingActivity field.
func (r *mutationResolver) DeleteProcessingActivity(ctx context.Context, input types.DeleteProcessingActivityInput) (*types.DeleteProcessingActivityPayload, error) {
r.MustBeAuthorized(ctx, input.ProcessingActivityID, authz.ActionDeleteProcessingActivity)
prb := r.ProboService(ctx, input.ProcessingActivityID.TenantID())
err := prb.ProcessingActivities.Delete(ctx, input.ProcessingActivityID)
if err != nil {
panic(fmt.Errorf("cannot delete processing activity: %w", err))
}
return &types.DeleteProcessingActivityPayload{
DeletedProcessingActivityID: input.ProcessingActivityID,
}, nil
}
// CreateDataProtectionImpactAssessment is the resolver for the createDataProtectionImpactAssessment field.
func (r *mutationResolver) CreateDataProtectionImpactAssessment(ctx context.Context, input types.CreateDataProtectionImpactAssessmentInput) (*types.CreateDataProtectionImpactAssessmentPayload, error) {
r.MustBeAuthorized(ctx, input.ProcessingActivityID, authz.ActionCreateDataProtectionImpactAssessment)
prb := r.ProboService(ctx, input.ProcessingActivityID.TenantID())
req := probo.CreateDataProtectionImpactAssessmentRequest{
ProcessingActivityID: input.ProcessingActivityID,
Description: input.Description,
NecessityAndProportionality: input.NecessityAndProportionality,
PotentialRisk: input.PotentialRisk,
Mitigations: input.Mitigations,
ResidualRisk: input.ResidualRisk,
}
dpia, err := prb.DataProtectionImpactAssessments.Create(ctx, &req)
if err != nil {
panic(fmt.Errorf("cannot create data protection impact assessment: %w", err))
}
return &types.CreateDataProtectionImpactAssessmentPayload{
DataProtectionImpactAssessment: types.NewDataProtectionImpactAssessment(dpia),
}, nil
}
// UpdateDataProtectionImpactAssessment is the resolver for the updateDataProtectionImpactAssessment field.
func (r *mutationResolver) UpdateDataProtectionImpactAssessment(ctx context.Context, input types.UpdateDataProtectionImpactAssessmentInput) (*types.UpdateDataProtectionImpactAssessmentPayload, error) {
r.MustBeAuthorized(ctx, input.ID, authz.ActionUpdateDataProtectionImpactAssessment)
prb := r.ProboService(ctx, input.ID.TenantID())
req := probo.UpdateDataProtectionImpactAssessmentRequest{
ID: input.ID,
Description: UnwrapOmittable(input.Description),
NecessityAndProportionality: UnwrapOmittable(input.NecessityAndProportionality),
PotentialRisk: UnwrapOmittable(input.PotentialRisk),
Mitigations: UnwrapOmittable(input.Mitigations),
ResidualRisk: input.ResidualRisk,
}
dpia, err := prb.DataProtectionImpactAssessments.Update(ctx, &req)
if err != nil {
panic(fmt.Errorf("cannot update data protection impact assessment: %w", err))
}
return &types.UpdateDataProtectionImpactAssessmentPayload{
DataProtectionImpactAssessment: types.NewDataProtectionImpactAssessment(dpia),
}, nil
}
// DeleteDataProtectionImpactAssessment is the resolver for the deleteDataProtectionImpactAssessment field.
func (r *mutationResolver) DeleteDataProtectionImpactAssessment(ctx context.Context, input types.DeleteDataProtectionImpactAssessmentInput) (*types.DeleteDataProtectionImpactAssessmentPayload, error) {
r.MustBeAuthorized(ctx, input.DataProtectionImpactAssessmentID, authz.ActionDeleteDataProtectionImpactAssessment)
prb := r.ProboService(ctx, input.DataProtectionImpactAssessmentID.TenantID())
err := prb.DataProtectionImpactAssessments.Delete(ctx, input.DataProtectionImpactAssessmentID)
if err != nil {
panic(fmt.Errorf("cannot delete data protection impact assessment: %w", err))
}
return &types.DeleteDataProtectionImpactAssessmentPayload{
DeletedDataProtectionImpactAssessmentID: input.DataProtectionImpactAssessmentID,
}, nil
}
// CreateTransferImpactAssessment is the resolver for the createTransferImpactAssessment field.
func (r *mutationResolver) CreateTransferImpactAssessment(ctx context.Context, input types.CreateTransferImpactAssessmentInput) (*types.CreateTransferImpactAssessmentPayload, error) {
r.MustBeAuthorized(ctx, input.ProcessingActivityID, authz.ActionCreateTransferImpactAssessment)
prb := r.ProboService(ctx, input.ProcessingActivityID.TenantID())
req := probo.CreateTransferImpactAssessmentRequest{
ProcessingActivityID: input.ProcessingActivityID,
DataSubjects: input.DataSubjects,
LegalMechanism: input.LegalMechanism,
Transfer: input.Transfer,
LocalLawRisk: input.LocalLawRisk,
SupplementaryMeasures: input.SupplementaryMeasures,
}
tia, err := prb.TransferImpactAssessments.Create(ctx, &req)
if err != nil {
panic(fmt.Errorf("cannot create transfer impact assessment: %w", err))
}
return &types.CreateTransferImpactAssessmentPayload{
TransferImpactAssessment: types.NewTransferImpactAssessment(tia),
}, nil
}
// UpdateTransferImpactAssessment is the resolver for the updateTransferImpactAssessment field.
func (r *mutationResolver) UpdateTransferImpactAssessment(ctx context.Context, input types.UpdateTransferImpactAssessmentInput) (*types.UpdateTransferImpactAssessmentPayload, error) {
r.MustBeAuthorized(ctx, input.ID, authz.ActionUpdateTransferImpactAssessment)
prb := r.ProboService(ctx, input.ID.TenantID())
req := probo.UpdateTransferImpactAssessmentRequest{
ID: input.ID,
DataSubjects: UnwrapOmittable(input.DataSubjects),
LegalMechanism: UnwrapOmittable(input.LegalMechanism),
Transfer: UnwrapOmittable(input.Transfer),
LocalLawRisk: UnwrapOmittable(input.LocalLawRisk),
SupplementaryMeasures: UnwrapOmittable(input.SupplementaryMeasures),
}
tia, err := prb.TransferImpactAssessments.Update(ctx, &req)
if err != nil {
panic(fmt.Errorf("cannot update transfer impact assessment: %w", err))
}
return &types.UpdateTransferImpactAssessmentPayload{
TransferImpactAssessment: types.NewTransferImpactAssessment(tia),
}, nil
}
// DeleteTransferImpactAssessment is the resolver for the deleteTransferImpactAssessment field.
func (r *mutationResolver) DeleteTransferImpactAssessment(ctx context.Context, input types.DeleteTransferImpactAssessmentInput) (*types.DeleteTransferImpactAssessmentPayload, error) {
r.MustBeAuthorized(ctx, input.TransferImpactAssessmentID, authz.ActionDeleteTransferImpactAssessment)
prb := r.ProboService(ctx, input.TransferImpactAssessmentID.TenantID())
err := prb.TransferImpactAssessments.Delete(ctx, input.TransferImpactAssessmentID)
if err != nil {
panic(fmt.Errorf("cannot delete transfer impact assessment: %w", err))
}
return &types.DeleteTransferImpactAssessmentPayload{
DeletedTransferImpactAssessmentID: input.TransferImpactAssessmentID,
}, nil
}
// CreateSnapshot is the resolver for the createSnapshot field.
func (r *mutationResolver) CreateSnapshot(ctx context.Context, input types.CreateSnapshotInput) (*types.CreateSnapshotPayload, error) {
r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionCreateSnapshot)
prb := r.ProboService(ctx, input.OrganizationID.TenantID())
snapshot, err := prb.Snapshots.Create(ctx, &probo.CreateSnapshotRequest{
OrganizationID: input.OrganizationID,
Name: input.Name,
Description: input.Description,
Type: input.Type,
})
if err != nil {
panic(fmt.Errorf("cannot create snapshot: %w", err))
}
return &types.CreateSnapshotPayload{
SnapshotEdge: types.NewSnapshotEdge(snapshot, coredata.SnapshotOrderFieldCreatedAt),
}, nil
}
// DeleteSnapshot is the resolver for the deleteSnapshot field.
func (r *mutationResolver) DeleteSnapshot(ctx context.Context, input types.DeleteSnapshotInput) (*types.DeleteSnapshotPayload, error) {
r.MustBeAuthorized(ctx, input.SnapshotID, authz.ActionDeleteSnapshot)
prb := r.ProboService(ctx, input.SnapshotID.TenantID())
err := prb.Snapshots.Delete(ctx, input.SnapshotID)
if err != nil {
panic(fmt.Errorf("cannot delete snapshot: %w", err))
}
return &types.DeleteSnapshotPayload{
DeletedSnapshotID: input.SnapshotID,
}, nil
}
// CreateCustomDomain is the resolver for the createCustomDomain field.
func (r *mutationResolver) CreateCustomDomain(ctx context.Context, input types.CreateCustomDomainInput) (*types.CreateCustomDomainPayload, error) {
r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionCreateCustomDomain)
prb := r.ProboService(ctx, input.OrganizationID.TenantID())
domain, err := prb.CustomDomains.CreateCustomDomain(ctx, probo.CreateCustomDomainRequest{
OrganizationID: input.OrganizationID,
Domain: input.Domain,
})
if err != nil {
panic(fmt.Errorf("cannot create custom domain: %w", err))
}
return &types.CreateCustomDomainPayload{
CustomDomain: types.NewCustomDomain(domain, r.customDomainCname),
}, nil
}
// DeleteCustomDomain is the resolver for the deleteCustomDomain field.
func (r *mutationResolver) DeleteCustomDomain(ctx context.Context, input types.DeleteCustomDomainInput) (*types.DeleteCustomDomainPayload, error) {
r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionDeleteCustomDomain)
prb := r.ProboService(ctx, input.OrganizationID.TenantID())
// Get the current custom domain ID before deleting
domain, err := prb.CustomDomains.GetOrganizationCustomDomain(ctx, input.OrganizationID)
if err != nil {
panic(fmt.Errorf("cannot get custom domain: %w", err))
}
if domain == nil {
return nil, fmt.Errorf("organization has no custom domain")
}
deletedDomainID := domain.ID
if err := prb.CustomDomains.DeleteCustomDomain(ctx, input.OrganizationID); err != nil {
panic(fmt.Errorf("cannot delete custom domain: %w", err))
}
return &types.DeleteCustomDomainPayload{
DeletedCustomDomainID: deletedDomainID,
}, nil
}
// InitiateDomainVerification is the resolver for the initiateDomainVerification field.
func (r *mutationResolver) InitiateDomainVerification(ctx context.Context, input types.InitiateDomainVerificationInput) (*types.InitiateDomainVerificationPayload, error) {
r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionInitiateDomainVerification)
organizationID := input.OrganizationID
tenantID := organizationID.TenantID()
authSvc := r.AuthService(ctx, tenantID)
config, err := authSvc.InitiateDomainVerification(ctx, organizationID, input.EmailDomain)
if err != nil {
return nil, fmt.Errorf("cannot initiate domain verification: %w", err)
}
dnsRecord := auth.GetDomainVerificationRecord(*config.DomainVerificationToken)
return &types.InitiateDomainVerificationPayload{
SamlConfiguration: types.NewSAMLConfigurationWithURLs(
config,
r.samlSvc.GetEntityID(),
r.samlSvc.GetAcsURL(),
),
DNSRecord: dnsRecord,
}, nil
}
// VerifyDomain is the resolver for the verifyDomain field.
func (r *mutationResolver) VerifyDomain(ctx context.Context, input types.VerifyDomainInput) (*types.VerifyDomainPayload, error) {
r.MustBeAuthorized(ctx, input.ID, authz.ActionVerifyDomain)
configID := input.ID
tenantID := configID.TenantID()
authSvc := r.AuthService(ctx, tenantID)
config, verified, err := authSvc.VerifyDomain(ctx, configID)
if err != nil {
return nil, fmt.Errorf("cannot verify domain: %w", err)
}
return &types.VerifyDomainPayload{
SamlConfiguration: types.NewSAMLConfigurationWithURLs(
config,
r.samlSvc.GetEntityID(),
r.samlSvc.GetAcsURL(),
),
Verified: verified,
}, nil
}
// CreateSAMLConfiguration is the resolver for the createSAMLConfiguration field.
func (r *mutationResolver) CreateSAMLConfiguration(ctx context.Context, input types.CreateSAMLConfigurationInput) (*types.CreateSAMLConfigurationPayload, error) {
r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionCreateSAMLConfiguration)
organizationID := input.OrganizationID
tenantID := organizationID.TenantID()
var idpEntityID, idpSsoURL, idpCertificate string
var idpMetadataURL *string
if input.IdpMetadataXML != nil && *input.IdpMetadataXML != "" {
metadata, err := auth.ParseIdPMetadata(*input.IdpMetadataXML)
if err != nil {
return nil, fmt.Errorf("cannot parse IdP metadata XML: %w", err)
}
idpEntityID = metadata.EntityID
idpSsoURL = metadata.SsoURL
idpCertificate = metadata.Certificate
idpMetadataURL = metadata.MetadataURL
} else {
if input.IdpEntityID == nil || *input.IdpEntityID == "" {
return nil, fmt.Errorf("either idpMetadataXml or idpEntityId must be provided")
}
if input.IdpSsoURL == nil || *input.IdpSsoURL == "" {
return nil, fmt.Errorf("either idpMetadataXml or idpSsoUrl must be provided")
}
if input.IdpCertificate == nil || *input.IdpCertificate == "" {
return nil, fmt.Errorf("either idpMetadataXml or idpCertificate must be provided")
}
idpEntityID = *input.IdpEntityID
idpSsoURL = *input.IdpSsoURL
idpCertificate = *input.IdpCertificate
idpMetadataURL = input.IdpMetadataURL
}
attributeEmail := "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"
if input.AttributeEmail != nil {
attributeEmail = *input.AttributeEmail
}
attributeFirstname := "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"
if input.AttributeFirstname != nil {
attributeFirstname = *input.AttributeFirstname
}
attributeLastname := "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname"
if input.AttributeLastname != nil {
attributeLastname = *input.AttributeLastname
}
attributeRole := "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role"
if input.AttributeRole != nil {
attributeRole = *input.AttributeRole
}
autoSignupEnabled := false
if input.AutoSignupEnabled != nil {
autoSignupEnabled = *input.AutoSignupEnabled
}
authSvc := r.AuthService(ctx, tenantID)
config, err := authSvc.CreateSAMLConfiguration(ctx, auth.CreateSAMLConfigurationRequest{
OrganizationID: organizationID,
EmailDomain: input.EmailDomain,
EnforcementPolicy: input.EnforcementPolicy,
IdPEntityID: idpEntityID,
IdPSsoURL: idpSsoURL,
IdPCertificate: idpCertificate,
IdPMetadataURL: idpMetadataURL,
AttributeEmail: attributeEmail,
AttributeFirstname: attributeFirstname,
AttributeLastname: attributeLastname,
AttributeRole: attributeRole,
AutoSignupEnabled: autoSignupEnabled,
})
if err != nil {
return nil, fmt.Errorf("cannot create SAML configuration: %w", err)
}
return &types.CreateSAMLConfigurationPayload{
SamlConfiguration: types.NewSAMLConfigurationWithURLs(
config,
r.samlSvc.GetEntityID(),
r.samlSvc.GetAcsURL(),
),
}, nil
}
// UpdateSAMLConfiguration is the resolver for the updateSAMLConfiguration field.
func (r *mutationResolver) UpdateSAMLConfiguration(ctx context.Context, input types.UpdateSAMLConfigurationInput) (*types.UpdateSAMLConfigurationPayload, error) {
r.MustBeAuthorized(ctx, input.ID, authz.ActionUpdateSAMLConfiguration)
configID := input.ID
tenantID := configID.TenantID()
authSvc := r.AuthService(ctx, tenantID)
updatedConfig, err := authSvc.UpdateSAMLConfiguration(ctx, auth.UpdateSAMLConfigurationRequest{
ID: configID,
Enabled: input.Enabled,
EnforcementPolicy: input.EnforcementPolicy,
IdPEntityID: input.IdpEntityID,
IdPSsoURL: input.IdpSsoURL,
IdPCertificate: input.IdpCertificate,
IdPMetadataURL: input.IdpMetadataURL,
AttributeEmail: input.AttributeEmail,
AttributeFirstname: input.AttributeFirstname,
AttributeLastname: input.AttributeLastname,
AttributeRole: input.AttributeRole,
AutoSignupEnabled: input.AutoSignupEnabled,
})
if err != nil {
return nil, fmt.Errorf("cannot update SAML configuration: %w", err)
}
return &types.UpdateSAMLConfigurationPayload{
SamlConfiguration: types.NewSAMLConfigurationWithURLs(
updatedConfig,
r.samlSvc.GetEntityID(),
r.samlSvc.GetAcsURL(),
),
}, nil
}
// DeleteSAMLConfiguration is the resolver for the deleteSAMLConfiguration field.
func (r *mutationResolver) DeleteSAMLConfiguration(ctx context.Context, input types.DeleteSAMLConfigurationInput) (*types.DeleteSAMLConfigurationPayload, error) {
r.MustBeAuthorized(ctx, input.ID, authz.ActionDeleteSAMLConfiguration)
configID := input.ID
tenantID := configID.TenantID()
authSvc := r.AuthService(ctx, tenantID)
err := authSvc.DeleteSAMLConfiguration(ctx, configID)
if err != nil {
return nil, fmt.Errorf("cannot delete SAML configuration: %w", err)
}
return &types.DeleteSAMLConfigurationPayload{
DeletedSAMLConfigurationID: configID,
}, nil
}
// EnableSaml is the resolver for the enableSAML field.
func (r *mutationResolver) EnableSaml(ctx context.Context, input types.EnableSAMLInput) (*types.EnableSAMLPayload, error) {
r.MustBeAuthorized(ctx, input.ID, authz.ActionEnableSAML)
configID := input.ID
tenantID := configID.TenantID()
authSvc := r.AuthService(ctx, tenantID)
enabledConfig, err := authSvc.EnableSAMLConfiguration(ctx, configID)
if err != nil {
return nil, fmt.Errorf("cannot enable SAML: %w", err)
}
return &types.EnableSAMLPayload{
SamlConfiguration: types.NewSAMLConfigurationWithURLs(
enabledConfig,
r.samlSvc.GetEntityID(),
r.samlSvc.GetAcsURL(),
),
}, nil
}
// DisableSaml is the resolver for the disableSAML field.
func (r *mutationResolver) DisableSaml(ctx context.Context, input types.DisableSAMLInput) (*types.DisableSAMLPayload, error) {
r.MustBeAuthorized(ctx, input.ID, authz.ActionDisableSAML)
configID := input.ID
tenantID := configID.TenantID()
authSvc := r.AuthService(ctx, tenantID)
disabledConfig, err := authSvc.DisableSAMLConfiguration(ctx, configID)
if err != nil {
return nil, fmt.Errorf("cannot disable SAML: %w", err)
}
return &types.DisableSAMLPayload{
SamlConfiguration: types.NewSAMLConfigurationWithURLs(
disabledConfig,
r.samlSvc.GetEntityID(),
r.samlSvc.GetAcsURL(),
),
}, nil
}
// Organization is the resolver for the organization field.
func (r *nonconformityResolver) Organization(ctx context.Context, obj *types.Nonconformity) (*types.Organization, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetOrganization)
prb := r.ProboService(ctx, obj.ID.TenantID())
nonconformity, err := prb.Nonconformities.Get(ctx, obj.ID)
if err != nil {
panic(fmt.Errorf("cannot get nonconformity: %w", err))
}
organization, err := prb.Organizations.Get(ctx, nonconformity.OrganizationID)
if err != nil {
var errNotFound *coredata.ErrOrganizationNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get nonconformity organization: %w", err))
}
return types.NewOrganization(organization), nil
}
// Audit is the resolver for the audit field.
func (r *nonconformityResolver) Audit(ctx context.Context, obj *types.Nonconformity) (*types.Audit, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionAudit)
prb := r.ProboService(ctx, obj.ID.TenantID())
nonconformity, err := prb.Nonconformities.Get(ctx, obj.ID)
if err != nil {
panic(fmt.Errorf("cannot get nonconformity: %w", err))
}
if nonconformity.AuditID == nil {
return nil, nil
}
audit, err := prb.Audits.Get(ctx, *nonconformity.AuditID)
if err != nil {
var errNotFound *coredata.ErrAuditNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get nonconformity audit: %w", err))
}
return types.NewAudit(audit), nil
}
// Owner is the resolver for the owner field.
func (r *nonconformityResolver) Owner(ctx context.Context, obj *types.Nonconformity) (*types.People, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetOwner)
prb := r.ProboService(ctx, obj.ID.TenantID())
nonconformity, err := prb.Nonconformities.Get(ctx, obj.ID)
if err != nil {
panic(fmt.Errorf("cannot get nonconformity: %w", err))
}
people, err := prb.Peoples.Get(ctx, nonconformity.OwnerID)
if err != nil {
var errNotFound *coredata.ErrPeopleNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get nonconformity owner: %w", err))
}
return types.NewPeople(people), nil
}
// TotalCount is the resolver for the totalCount field.
func (r *nonconformityConnectionResolver) TotalCount(ctx context.Context, obj *types.NonconformityConnection) (int, error) {
r.MustBeAuthorized(ctx, obj.ParentID, authz.ActionTotalCount)
prb := r.ProboService(ctx, obj.ParentID.TenantID())
switch obj.Resolver.(type) {
case *organizationResolver:
nonconformityFilter := coredata.NewNonconformityFilter(nil)
if obj.Filter != nil {
nonconformityFilter = coredata.NewNonconformityFilter(&obj.Filter.SnapshotID)
}
count, err := prb.Nonconformities.CountForOrganizationID(ctx, obj.ParentID, nonconformityFilter)
if err != nil {
panic(fmt.Errorf("cannot count nonconformities: %w", err))
}
return count, nil
}
panic(fmt.Errorf("unsupported resolver: %T", obj.Resolver))
}
// Organization is the resolver for the organization field.
func (r *obligationResolver) Organization(ctx context.Context, obj *types.Obligation) (*types.Organization, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetOrganization)
prb := r.ProboService(ctx, obj.ID.TenantID())
obligation, err := prb.Obligations.Get(ctx, obj.ID)
if err != nil {
panic(fmt.Errorf("cannot get obligation: %w", err))
}
organization, err := prb.Organizations.Get(ctx, obligation.OrganizationID)
if err != nil {
var errNotFound *coredata.ErrOrganizationNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get obligation organization: %w", err))
}
return types.NewOrganization(organization), nil
}
// Owner is the resolver for the owner field.
func (r *obligationResolver) Owner(ctx context.Context, obj *types.Obligation) (*types.People, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetOwner)
prb := r.ProboService(ctx, obj.ID.TenantID())
obligation, err := prb.Obligations.Get(ctx, obj.ID)
if err != nil {
panic(fmt.Errorf("cannot get obligation: %w", err))
}
people, err := prb.Peoples.Get(ctx, obligation.OwnerID)
if err != nil {
var errNotFound *coredata.ErrPeopleNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get obligation owner: %w", err))
}
return types.NewPeople(people), nil
}
// TotalCount is the resolver for the totalCount field.
func (r *obligationConnectionResolver) TotalCount(ctx context.Context, obj *types.ObligationConnection) (int, error) {
r.MustBeAuthorized(ctx, obj.ParentID, authz.ActionTotalCount)
prb := r.ProboService(ctx, obj.ParentID.TenantID())
switch obj.Resolver.(type) {
case *organizationResolver:
obligationFilter := coredata.NewObligationFilter(nil)
if obj.Filter != nil {
obligationFilter = coredata.NewObligationFilter(&obj.Filter.SnapshotID)
}
count, err := prb.Obligations.CountForOrganizationID(ctx, obj.ParentID, obligationFilter)
if err != nil {
panic(fmt.Errorf("cannot count obligations: %w", err))
}
return count, nil
case *riskResolver:
obligationFilter := coredata.NewObligationFilter(nil)
if obj.Filter != nil {
obligationFilter = coredata.NewObligationFilter(&obj.Filter.SnapshotID)
}
count, err := prb.Obligations.CountForRiskID(ctx, obj.ParentID, obligationFilter)
if err != nil {
panic(fmt.Errorf("cannot count risk obligations: %w", err))
}
return count, nil
}
panic(fmt.Errorf("unsupported resolver: %T", obj.Resolver))
}
// LogoURL is the resolver for the logoUrl field.
func (r *organizationResolver) LogoURL(ctx context.Context, obj *types.Organization) (*string, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetLogoUrl)
prb := r.ProboService(ctx, obj.ID.TenantID())
return prb.Organizations.GenerateLogoURL(ctx, obj.ID, 1*time.Hour)
}
// HorizontalLogoURL is the resolver for the horizontalLogoUrl field.
func (r *organizationResolver) HorizontalLogoURL(ctx context.Context, obj *types.Organization) (*string, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetHorizontalLogoUrl)
prb := r.ProboService(ctx, obj.ID.TenantID())
return prb.Organizations.GenerateHorizontalLogoURL(ctx, obj.ID, 1*time.Hour)
}
// Context is the resolver for the context field.
func (r *organizationResolver) Context(ctx context.Context, obj *types.Organization) (*types.OrganizationContext, error) {
prb := r.ProboService(ctx, obj.ID.TenantID())
orgContext, err := prb.Organizations.GetContextSummary(ctx, obj.ID)
if err != nil {
panic(fmt.Errorf("cannot load organization context: %w", err))
}
return types.NewOrganizationContext(orgContext), nil
}
// Memberships is the resolver for the memberships field.
func (r *organizationResolver) Memberships(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.MembershipOrderBy) (*types.MembershipConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionMemberships)
pageOrderBy := page.OrderBy[coredata.MembershipOrderField]{
Field: coredata.MembershipOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.MembershipOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
authzSvc := r.AuthzService(ctx, obj.ID.TenantID())
page, err := authzSvc.GetMembershipsByOrganizationID(ctx, obj.ID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list memberships: %w", err))
}
return types.NewMembershipConnection(page, r, obj.ID), nil
}
// Invitations is the resolver for the invitations field.
func (r *organizationResolver) Invitations(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.InvitationOrder, filter *types.InvitationFilter) (*types.InvitationConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListInvitations)
pageOrderBy := page.OrderBy[coredata.InvitationOrderField]{
Field: coredata.InvitationOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.InvitationOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
invitationFilter := coredata.NewInvitationFilter(nil)
if filter != nil {
invitationFilter = coredata.NewInvitationFilter(filter.Statuses)
}
authzSvc := r.AuthzService(ctx, obj.ID.TenantID())
page, err := authzSvc.GetInvitationsByOrganizationID(ctx, obj.ID, cursor, invitationFilter)
if err != nil {
panic(fmt.Errorf("cannot list invitations: %w", err))
}
return types.NewInvitationConnection(page, r, obj.ID, filter), nil
}
// SlackConnections is the resolver for the slackConnections field.
func (r *organizationResolver) SlackConnections(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.SlackConnectionConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListSlackConnections)
prb := r.ProboService(ctx, obj.ID.TenantID())
// Filter for Slack connectors only
slackProvider := coredata.ConnectorProviderSlack
filter := coredata.NewConnectorProviderFilter(&slackProvider)
pageOrderBy := page.OrderBy[coredata.ConnectorOrderField]{
Field: coredata.ConnectorOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := prb.Connectors.ListForOrganizationID(ctx, obj.ID, cursor, filter)
if err != nil {
panic(fmt.Errorf("cannot list organization slack connections: %w", err))
}
return types.NewSlackConnectionConnection(page), nil
}
// Frameworks is the resolver for the frameworks field.
func (r *organizationResolver) Frameworks(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.FrameworkOrderBy) (*types.FrameworkConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListFrameworks)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.FrameworkOrderField]{
Field: coredata.FrameworkOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.FrameworkOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := prb.Frameworks.ListForOrganizationID(ctx, obj.ID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list organization frameworks: %w", err))
}
return types.NewFrameworkConnection(page, r, obj.ID), nil
}
// Controls is the resolver for the controls field.
func (r *organizationResolver) Controls(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ControlOrderBy, filter *types.ControlFilter) (*types.ControlConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListControls)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.ControlOrderField]{
Field: coredata.ControlOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.ControlOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
var controlFilter = coredata.NewControlFilter(nil)
if filter != nil {
controlFilter = coredata.NewControlFilter(filter.Query)
}
page, err := prb.Controls.ListForOrganizationID(ctx, obj.ID, cursor, controlFilter)
if err != nil {
panic(fmt.Errorf("cannot list controls: %w", err))
}
return types.NewControlConnection(page, r, obj.ID, controlFilter), nil
}
// Vendors is the resolver for the vendors field.
func (r *organizationResolver) Vendors(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.VendorOrderBy, filter *types.VendorFilter) (*types.VendorConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListVendors)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.VendorOrderField]{
Field: coredata.VendorOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.VendorOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
var vendorFilter = coredata.NewVendorFilter(nil, nil)
if filter != nil {
vendorFilter = coredata.NewVendorFilter(&filter.SnapshotID, nil)
}
page, err := prb.Vendors.ListForOrganizationID(ctx, obj.ID, cursor, vendorFilter)
if err != nil {
panic(fmt.Errorf("cannot list organization vendors: %w", err))
}
return types.NewVendorConnection(page, r, obj.ID), nil
}
// Peoples is the resolver for the peoples field.
func (r *organizationResolver) Peoples(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.PeopleOrderBy, filter *types.PeopleFilter) (*types.PeopleConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionPeoples)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.PeopleOrderField]{
Field: coredata.PeopleOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.PeopleOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
var peopleFilter = coredata.NewPeopleFilter(nil)
if filter != nil {
peopleFilter = coredata.NewPeopleFilter(filter.ExcludeContractEnded)
}
page, err := prb.Peoples.ListForOrganizationID(ctx, obj.ID, cursor, peopleFilter)
if err != nil {
panic(fmt.Errorf("cannot list organization peoples: %w", err))
}
return types.NewPeopleConnection(page, r, obj.ID, peopleFilter), nil
}
// Documents is the resolver for the documents field.
func (r *organizationResolver) Documents(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentOrderBy, filter *types.DocumentFilter) (*types.DocumentConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListDocuments)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.DocumentOrderField]{
Field: coredata.DocumentOrderFieldTitle,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.DocumentOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
var documentFilter = coredata.NewDocumentFilter(nil)
if filter != nil {
documentFilter = coredata.NewDocumentFilter(filter.Query)
}
page, err := prb.Documents.ListByOrganizationID(ctx, obj.ID, cursor, documentFilter)
if err != nil {
panic(fmt.Errorf("cannot list organization documents: %w", err))
}
return types.NewDocumentConnection(page, r, obj.ID, documentFilter), nil
}
// Meetings is the resolver for the meetings field.
func (r *organizationResolver) Meetings(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.MeetingOrderBy) (*types.MeetingConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListMeetings)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.MeetingOrderField]{
Field: coredata.MeetingOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.MeetingOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := prb.Meetings.ListForOrganizationID(ctx, obj.ID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list organization meetings: %w", err))
}
return types.NewMeetingConnection(page, r, obj.ID), nil
}
// Measures is the resolver for the measures field.
func (r *organizationResolver) Measures(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.MeasureOrderBy, filter *types.MeasureFilter) (*types.MeasureConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListMeasures)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.MeasureOrderField]{
Field: coredata.MeasureOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.MeasureOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
var measureFilter = coredata.NewMeasureFilter(nil, nil)
if filter != nil {
measureFilter = coredata.NewMeasureFilter(filter.Query, filter.State)
}
page, err := prb.Measures.ListForOrganizationID(ctx, obj.ID, cursor, measureFilter)
if err != nil {
panic(fmt.Errorf("cannot list organization measures: %w", err))
}
return types.NewMeasureConnection(page, r, obj.ID, measureFilter), nil
}
// Risks is the resolver for the risks field.
func (r *organizationResolver) Risks(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.RiskOrderBy, filter *types.RiskFilter) (*types.RiskConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListRisks)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.RiskOrderField]{
Field: coredata.RiskOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.RiskOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
var riskFilter = coredata.NewRiskFilter(nil, nil)
if filter != nil {
riskFilter = coredata.NewRiskFilter(filter.Query, &filter.SnapshotID)
}
page, err := prb.Risks.ListForOrganizationID(ctx, obj.ID, cursor, riskFilter)
if err != nil {
panic(fmt.Errorf("cannot list organization risks: %w", err))
}
return types.NewRiskConnection(page, r, obj.ID, riskFilter), nil
}
// Tasks is the resolver for the tasks field.
func (r *organizationResolver) Tasks(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.TaskOrderBy) (*types.TaskConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListTasks)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.TaskOrderField]{
Field: coredata.TaskOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.TaskOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := prb.Tasks.ListForOrganizationID(ctx, obj.ID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list organization tasks: %w", err))
}
return types.NewTaskConnection(page, r, obj.ID), nil
}
// Assets is the resolver for the assets field.
func (r *organizationResolver) Assets(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.AssetOrderBy, filter *types.AssetFilter) (*types.AssetConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListAssets)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.AssetOrderField]{
Field: coredata.AssetOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.AssetOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
assetFilter := coredata.NewAssetFilter(nil)
if filter != nil {
assetFilter = coredata.NewAssetFilter(&filter.SnapshotID)
}
page, err := prb.Assets.ListForOrganizationID(ctx, obj.ID, cursor, assetFilter)
if err != nil {
panic(fmt.Errorf("cannot list organization assets: %w", err))
}
return types.NewAssetConnection(page, r, obj.ID, filter), nil
}
// Assets is the resolver for the assets field.
func (r *organizationResolver) Data(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DatumOrderBy, filter *types.DatumFilter) (*types.DatumConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListAssets)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.DatumOrderField]{
Field: coredata.DatumOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.DatumOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
datumFilter := coredata.NewDatumFilter(nil)
if filter != nil {
datumFilter = coredata.NewDatumFilter(&filter.SnapshotID)
}
page, err := prb.Data.ListForOrganizationID(ctx, obj.ID, cursor, datumFilter)
if err != nil {
panic(fmt.Errorf("cannot list organization data: %w", err))
}
return types.NewDataConnection(page, r, obj.ID, filter), nil
}
// Audits is the resolver for the audits field.
func (r *organizationResolver) Audits(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.AuditOrderBy) (*types.AuditConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListAudits)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.AuditOrderField]{
Field: coredata.AuditOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.AuditOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := prb.Audits.ListForOrganizationID(ctx, obj.ID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list organization audits: %w", err))
}
return types.NewAuditConnection(page, r, obj.ID), nil
}
// Nonconformities is the resolver for the nonconformities field.
func (r *organizationResolver) Nonconformities(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.NonconformityOrderBy, filter *types.NonconformityFilter) (*types.NonconformityConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListNonconformities)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.NonconformityOrderField]{
Field: coredata.NonconformityOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.NonconformityOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
nonconformityFilter := coredata.NewNonconformityFilter(nil)
if filter != nil {
nonconformityFilter = coredata.NewNonconformityFilter(&filter.SnapshotID)
}
page, err := prb.Nonconformities.ListForOrganizationID(ctx, obj.ID, cursor, nonconformityFilter)
if err != nil {
panic(fmt.Errorf("cannot list organization nonconformities: %w", err))
}
return types.NewNonconformityConnection(page, r, obj.ID, filter), nil
}
// Obligations is the resolver for the obligations field.
func (r *organizationResolver) Obligations(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ObligationOrderBy, filter *types.ObligationFilter) (*types.ObligationConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListObligations)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.ObligationOrderField]{
Field: coredata.ObligationOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.ObligationOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
obligationFilter := coredata.NewObligationFilter(nil)
if filter != nil {
obligationFilter = coredata.NewObligationFilter(&filter.SnapshotID)
}
page, err := prb.Obligations.ListForOrganizationID(ctx, obj.ID, cursor, obligationFilter)
if err != nil {
panic(fmt.Errorf("cannot list organization obligations: %w", err))
}
return types.NewObligationConnection(page, r, obj.ID, filter), nil
}
// ContinualImprovements is the resolver for the continualImprovements field.
func (r *organizationResolver) ContinualImprovements(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ContinualImprovementOrderBy, filter *types.ContinualImprovementFilter) (*types.ContinualImprovementConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListContinualImprovements)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.ContinualImprovementOrderField]{
Field: coredata.ContinualImprovementOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.ContinualImprovementOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
continualImprovementFilter := coredata.NewContinualImprovementFilter(nil)
if filter != nil {
continualImprovementFilter = coredata.NewContinualImprovementFilter(&filter.SnapshotID)
}
page, err := prb.ContinualImprovements.ListForOrganizationID(ctx, obj.ID, cursor, continualImprovementFilter)
if err != nil {
panic(fmt.Errorf("cannot list organization continual improvements: %w", err))
}
return types.NewContinualImprovementConnection(page, r, obj.ID, filter), nil
}
// ProcessingActivities is the resolver for the processingActivities field.
func (r *organizationResolver) ProcessingActivities(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ProcessingActivityOrderBy, filter *types.ProcessingActivityFilter) (*types.ProcessingActivityConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListProcessingActivities)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.ProcessingActivityOrderField]{
Field: coredata.ProcessingActivityOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.ProcessingActivityOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
processingActivityFilter := coredata.NewProcessingActivityFilter(nil)
if filter != nil {
processingActivityFilter = coredata.NewProcessingActivityFilter(&filter.SnapshotID)
}
page, err := prb.ProcessingActivities.ListForOrganizationID(ctx, obj.ID, cursor, processingActivityFilter)
if err != nil {
panic(fmt.Errorf("cannot list organization processing activities: %w", err))
}
return types.NewProcessingActivityConnection(page, r, obj.ID, filter), nil
}
// DataProtectionImpactAssessments is the resolver for the dataProtectionImpactAssessments field.
func (r *organizationResolver) DataProtectionImpactAssessments(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DataProtectionImpactAssessmentOrderBy, filter *types.DataProtectionImpactAssessmentFilter) (*types.DataProtectionImpactAssessmentConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListProcessingActivities)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.DataProtectionImpactAssessmentOrderField]{
Field: coredata.DataProtectionImpactAssessmentOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.DataProtectionImpactAssessmentOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
dpiaFilter := coredata.NewDataProtectionImpactAssessmentFilter(nil)
if filter != nil {
dpiaFilter = coredata.NewDataProtectionImpactAssessmentFilter(&filter.SnapshotID)
}
page, err := prb.DataProtectionImpactAssessments.ListForOrganizationID(ctx, obj.ID, cursor, dpiaFilter)
if err != nil {
panic(fmt.Errorf("cannot list organization data protection impact assessments: %w", err))
}
return types.NewDataProtectionImpactAssessmentConnection(page, r, obj.ID, dpiaFilter), nil
}
// TransferImpactAssessments is the resolver for the transferImpactAssessments field.
func (r *organizationResolver) TransferImpactAssessments(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.TransferImpactAssessmentOrderBy, filter *types.TransferImpactAssessmentFilter) (*types.TransferImpactAssessmentConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListProcessingActivities)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.TransferImpactAssessmentOrderField]{
Field: coredata.TransferImpactAssessmentOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.TransferImpactAssessmentOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
tiaFilter := coredata.NewTransferImpactAssessmentFilter(nil)
if filter != nil {
tiaFilter = coredata.NewTransferImpactAssessmentFilter(&filter.SnapshotID)
}
page, err := prb.TransferImpactAssessments.ListForOrganizationID(ctx, obj.ID, cursor, tiaFilter)
if err != nil {
panic(fmt.Errorf("cannot list organization transfer impact assessments: %w", err))
}
return types.NewTransferImpactAssessmentConnection(page, r, obj.ID, tiaFilter), nil
}
// Snapshots is the resolver for the snapshots field.
func (r *organizationResolver) Snapshots(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.SnapshotOrderBy) (*types.SnapshotConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListSnapshots)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.SnapshotOrderField]{
Field: coredata.SnapshotOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.SnapshotOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := prb.Snapshots.ListForOrganizationID(ctx, obj.ID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list organization snapshots: %w", err))
}
return types.NewSnapshotConnection(page, r, obj.ID), nil
}
// 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) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListTrustCenterFiles)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.TrustCenterFileOrderField]{
Field: coredata.TrustCenterFileOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.TrustCenterFileOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
pageResult, err := prb.TrustCenterFiles.ListForOrganizationID(ctx, obj.ID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list organization trust center files: %w", err))
}
return types.NewTrustCenterFileConnection(pageResult, obj.ID), nil
}
// TrustCenter is the resolver for the trustCenter field.
func (r *organizationResolver) TrustCenter(ctx context.Context, obj *types.Organization) (*types.TrustCenter, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetTrustCenter)
prb := r.ProboService(ctx, obj.ID.TenantID())
trustCenter, file, err := prb.TrustCenters.GetByOrganizationID(ctx, obj.ID)
if err != nil {
return nil, fmt.Errorf("cannot get trust center: %w", err)
}
return types.NewTrustCenter(trustCenter, file), nil
}
// CustomDomain is the resolver for the customDomain field.
func (r *organizationResolver) CustomDomain(ctx context.Context, obj *types.Organization) (*types.CustomDomain, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetCustomDomain)
prb := r.ProboService(ctx, obj.ID.TenantID())
domain, err := prb.CustomDomains.GetOrganizationCustomDomain(ctx, obj.ID)
if err != nil {
panic(fmt.Errorf("cannot get custom domain: %w", err))
}
if domain == nil {
return nil, nil
}
return types.NewCustomDomain(domain, r.customDomainCname), nil
}
// SamlConfigurations is the resolver for the samlConfigurations field.
func (r *organizationResolver) SamlConfigurations(ctx context.Context, obj *types.Organization) ([]*types.SAMLConfiguration, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListSAMLConfigurations)
tenantID := obj.ID.TenantID()
authSvc := r.AuthService(ctx, tenantID)
configs, err := authSvc.GetSAMLConfigurationsByOrganizationID(ctx, obj.ID)
if err != nil {
return nil, fmt.Errorf("cannot load SAML configurations: %w", err)
}
result := make([]*types.SAMLConfiguration, len(configs))
for i, config := range configs {
result[i] = types.NewSAMLConfigurationWithURLs(
config,
r.samlSvc.GetEntityID(),
r.samlSvc.GetAcsURL(),
)
}
return result, nil
}
// TotalCount is the resolver for the totalCount field.
func (r *peopleConnectionResolver) TotalCount(ctx context.Context, obj *types.PeopleConnection) (int, error) {
r.MustBeAuthorized(ctx, obj.ParentID, authz.ActionTotalCount)
prb := r.ProboService(ctx, obj.ParentID.TenantID())
switch obj.Resolver.(type) {
case *organizationResolver:
count, err := prb.Peoples.CountForOrganizationID(ctx, obj.ParentID, obj.Filters)
if err != nil {
panic(fmt.Errorf("cannot count peoples: %w", err))
}
return count, nil
}
panic(fmt.Errorf("unsupported resolver: %T", obj.Resolver))
}
// Organization is the resolver for the organization field.
func (r *processingActivityResolver) Organization(ctx context.Context, obj *types.ProcessingActivity) (*types.Organization, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetOrganization)
prb := r.ProboService(ctx, obj.ID.TenantID())
processingActivity, err := prb.ProcessingActivities.Get(ctx, obj.ID)
if err != nil {
panic(fmt.Errorf("cannot get processing activity: %w", err))
}
organization, err := prb.Organizations.Get(ctx, processingActivity.OrganizationID)
if err != nil {
var errNotFound *coredata.ErrOrganizationNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get organization: %w", err))
}
return types.NewOrganization(organization), nil
}
// DataProtectionOfficer is the resolver for the dataProtectionOfficer field.
func (r *processingActivityResolver) DataProtectionOfficer(ctx context.Context, obj *types.ProcessingActivity) (*types.People, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetDataProtectionOfficer)
prb := r.ProboService(ctx, obj.ID.TenantID())
processingActivity, err := prb.ProcessingActivities.Get(ctx, obj.ID)
if err != nil {
panic(fmt.Errorf("cannot get processing activity: %w", err))
}
if processingActivity.DataProtectionOfficerID == nil {
return nil, nil
}
people, err := prb.Peoples.Get(ctx, *processingActivity.DataProtectionOfficerID)
if err != nil {
panic(fmt.Errorf("cannot get data protection officer: %w", err))
}
return types.NewPeople(people), nil
}
// Vendors is the resolver for the vendors field.
func (r *processingActivityResolver) Vendors(ctx context.Context, obj *types.ProcessingActivity, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.VendorOrderBy) (*types.VendorConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListVendors)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.VendorOrderField]{
Field: coredata.VendorOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.VendorOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := prb.Vendors.ListForProcessingActivityID(ctx, obj.ID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list processing activity vendors: %w", err))
}
return types.NewVendorConnection(page, r, obj.ID), nil
}
// DataProtectionImpactAssessment is the resolver for the dataProtectionImpactAssessment field.
func (r *processingActivityResolver) DataProtectionImpactAssessment(ctx context.Context, obj *types.ProcessingActivity) (*types.DataProtectionImpactAssessment, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetDataProtectionImpactAssessment)
prb := r.ProboService(ctx, obj.ID.TenantID())
dpia, err := prb.DataProtectionImpactAssessments.GetByProcessingActivityID(ctx, obj.ID)
if err != nil {
var errNotFound *coredata.ErrDataProtectionImpactAssessmentNotFound
if errors.As(err, &errNotFound) {
return nil, nil
}
panic(fmt.Errorf("cannot get processing activity dpia: %w", err))
}
return types.NewDataProtectionImpactAssessment(dpia), nil
}
// TransferImpactAssessment is the resolver for the transferImpactAssessment field.
func (r *processingActivityResolver) TransferImpactAssessment(ctx context.Context, obj *types.ProcessingActivity) (*types.TransferImpactAssessment, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetTransferImpactAssessment)
prb := r.ProboService(ctx, obj.ID.TenantID())
tia, err := prb.TransferImpactAssessments.GetByProcessingActivityID(ctx, obj.ID)
if err != nil {
var errNotFound *coredata.ErrTransferImpactAssessmentNotFound
if errors.As(err, &errNotFound) {
return nil, nil
}
panic(fmt.Errorf("cannot get processing activity tia: %w", err))
}
return types.NewTransferImpactAssessment(tia), nil
}
// TotalCount is the resolver for the totalCount field.
func (r *processingActivityConnectionResolver) TotalCount(ctx context.Context, obj *types.ProcessingActivityConnection) (int, error) {
r.MustBeAuthorized(ctx, obj.ParentID, authz.ActionTotalCount)
prb := r.ProboService(ctx, obj.ParentID.TenantID())
switch obj.Resolver.(type) {
case *organizationResolver:
processingActivityFilter := coredata.NewProcessingActivityFilter(nil)
if obj.Filter != nil {
processingActivityFilter = coredata.NewProcessingActivityFilter(&obj.Filter.SnapshotID)
}
count, err := prb.ProcessingActivities.CountForOrganizationID(ctx, obj.ParentID, processingActivityFilter)
if err != nil {
panic(fmt.Errorf("cannot count organization processing activities: %w", err))
}
return count, nil
}
panic(fmt.Errorf("unsupported resolver: %T", obj.Resolver))
}
// Node is the resolver for the node field.
func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error) {
r.MustBeAuthorized(ctx, id, authz.ActionGet)
prb := r.ProboService(ctx, id.TenantID())
switch id.EntityType() {
case coredata.OrganizationEntityType:
organization, err := prb.Organizations.Get(ctx, id)
if err != nil {
var errNotFound *coredata.ErrOrganizationNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get organization: %w", err))
}
return types.NewOrganization(organization), nil
case coredata.PeopleEntityType:
people, err := prb.Peoples.Get(ctx, id)
if err != nil {
var errNotFound *coredata.ErrPeopleNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get people: %w", err))
}
return types.NewPeople(people), nil
case coredata.VendorEntityType:
vendor, err := prb.Vendors.Get(ctx, id)
if err != nil {
var errNotFound *coredata.ErrVendorNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get vendor: %w", err))
}
return types.NewVendor(vendor), nil
case coredata.FrameworkEntityType:
framework, err := prb.Frameworks.Get(ctx, id)
if err != nil {
var errNotFound *coredata.ErrFrameworkNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get framework: %w", err))
}
return types.NewFramework(framework), nil
case coredata.MeasureEntityType:
measure, err := prb.Measures.Get(ctx, id)
if err != nil {
var errNotFound *coredata.ErrMeasureNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get measure: %w", err))
}
return types.NewMeasure(measure), nil
case coredata.TaskEntityType:
task, err := prb.Tasks.Get(ctx, id)
if err != nil {
var errNotFound *coredata.ErrTaskNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get task: %w", err))
}
return types.NewTask(task), nil
case coredata.EvidenceEntityType:
evidence, err := prb.Evidences.Get(ctx, id)
if err != nil {
panic(fmt.Errorf("cannot get evidence: %w", err))
}
return types.NewEvidence(evidence), nil
case coredata.DocumentEntityType:
document, err := prb.Documents.Get(ctx, id)
if err != nil {
var errNotFound *coredata.ErrDocumentNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get document: %w", err))
}
return types.NewDocument(document), nil
case coredata.ControlEntityType:
control, err := prb.Controls.Get(ctx, id)
if err != nil {
var errNotFound *coredata.ErrControlNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get control: %w", err))
}
return types.NewControl(control), nil
case coredata.RiskEntityType:
risk, err := prb.Risks.Get(ctx, id)
if err != nil {
var errNotFound *coredata.ErrRiskNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get risk: %w", err))
}
return types.NewRisk(risk), nil
case coredata.VendorComplianceReportEntityType:
vendorComplianceReport, err := prb.VendorComplianceReports.Get(ctx, id)
if err != nil {
panic(fmt.Errorf("cannot get vendor compliance report: %w", err))
}
return types.NewVendorComplianceReport(vendorComplianceReport), nil
case coredata.VendorContactEntityType:
vendorContact, err := prb.VendorContacts.Get(ctx, id)
if err != nil {
panic(fmt.Errorf("cannot get vendor contact: %w", err))
}
return types.NewVendorContact(vendorContact), nil
case coredata.VendorServiceEntityType:
vendorService, err := prb.VendorServices.Get(ctx, id)
if err != nil {
panic(fmt.Errorf("cannot get vendor service: %w", err))
}
return types.NewVendorService(vendorService), nil
case coredata.DocumentVersionEntityType:
documentVersion, err := prb.Documents.GetVersion(ctx, id)
if err != nil {
panic(fmt.Errorf("cannot get document version: %w", err))
}
return types.NewDocumentVersion(documentVersion), nil
case coredata.DocumentVersionSignatureEntityType:
documentVersionSignature, err := prb.Documents.GetVersionSignature(ctx, id)
if err != nil {
panic(fmt.Errorf("cannot get document version signature: %w", err))
}
return types.NewDocumentVersionSignature(documentVersionSignature), nil
case coredata.AssetEntityType:
asset, err := prb.Assets.Get(ctx, id)
if err != nil {
var errNotFound *coredata.ErrAssetNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get asset: %w", err))
}
return types.NewAsset(asset), nil
case coredata.DatumEntityType:
datum, err := prb.Data.Get(ctx, id)
if err != nil {
panic(fmt.Errorf("cannot get data: %w", err))
}
return types.NewDatum(datum), nil
case coredata.AuditEntityType:
audit, err := prb.Audits.Get(ctx, id)
if err != nil {
var errNotFound *coredata.ErrAuditNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get audit: %w", err))
}
return types.NewAudit(audit), nil
case coredata.NonconformityEntityType:
nonconformity, err := prb.Nonconformities.Get(ctx, id)
if err != nil {
panic(fmt.Errorf("cannot get nonconformity: %w", err))
}
return types.NewNonconformity(nonconformity), nil
case coredata.ObligationEntityType:
obligation, err := prb.Obligations.Get(ctx, id)
if err != nil {
panic(fmt.Errorf("cannot get obligation: %w", err))
}
return types.NewObligation(obligation), nil
case coredata.ContinualImprovementEntityType:
continualImprovement, err := prb.ContinualImprovements.Get(ctx, id)
if err != nil {
panic(fmt.Errorf("cannot get continual improvement: %w", err))
}
return types.NewContinualImprovement(continualImprovement), nil
case coredata.ReportEntityType:
report, err := prb.Reports.Get(ctx, id)
if err != nil {
panic(fmt.Errorf("cannot get report: %w", err))
}
return types.NewReport(report), nil
case coredata.ProcessingActivityEntityType:
processingActivity, err := prb.ProcessingActivities.Get(ctx, id)
if err != nil {
panic(fmt.Errorf("cannot get processing activity: %w", err))
}
return types.NewProcessingActivity(processingActivity), nil
case coredata.DataProtectionImpactAssessmentEntityType:
dpia, err := prb.DataProtectionImpactAssessments.Get(ctx, id)
if err != nil {
panic(fmt.Errorf("cannot get processing activity dpia: %w", err))
}
return types.NewDataProtectionImpactAssessment(dpia), nil
case coredata.TransferImpactAssessmentEntityType:
tia, err := prb.TransferImpactAssessments.Get(ctx, id)
if err != nil {
panic(fmt.Errorf("cannot get processing activity tia: %w", err))
}
return types.NewTransferImpactAssessment(tia), nil
case coredata.SnapshotEntityType:
snapshot, err := prb.Snapshots.Get(ctx, id)
if err != nil {
panic(fmt.Errorf("cannot get snapshot: %w", err))
}
return types.NewSnapshot(snapshot), nil
case coredata.TrustCenterEntityType:
trustCenter, file, err := prb.TrustCenters.Get(ctx, id)
if err != nil {
panic(fmt.Errorf("cannot get trust center with file: %w", err))
}
return types.NewTrustCenter(trustCenter, file), nil
case coredata.TrustCenterAccessEntityType:
trustCenterAccess, err := prb.TrustCenterAccesses.Get(ctx, id)
if err != nil {
panic(fmt.Errorf("cannot get trust center access: %w", err))
}
return types.NewTrustCenterAccess(trustCenterAccess), nil
case coredata.MeetingEntityType:
meeting, err := prb.Meetings.Get(ctx, id)
if err != nil {
var errNotFound *coredata.ErrMeetingNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get meeting: %w", err))
}
return types.NewMeeting(meeting), nil
default:
}
panic(fmt.Errorf("unknown entity type: %d", id.EntityType()))
}
// Viewer is the resolver for the viewer field.
func (r *queryResolver) Viewer(ctx context.Context) (*types.Viewer, error) {
user := UserFromContext(ctx)
session := SessionFromContext(ctx)
apiKey := UserAPIKeyFromContext(ctx)
var viewerID gid.GID
if session != nil {
viewerID = session.ID
} else if apiKey != nil {
viewerID = apiKey.ID
} else {
viewerID = user.ID
}
return &types.Viewer{
ID: viewerID,
User: types.NewUser(user),
}, nil
}
// DownloadURL is the resolver for the downloadUrl field.
func (r *reportResolver) DownloadURL(ctx context.Context, obj *types.Report) (*string, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionDownloadUrl)
prb := r.ProboService(ctx, obj.ID.TenantID())
url, err := prb.Reports.GenerateDownloadURL(ctx, obj.ID, 15*time.Minute)
if err != nil {
panic(fmt.Errorf("cannot generate download URL: %w", err))
}
return url, nil
}
// Audit is the resolver for the audit field.
func (r *reportResolver) Audit(ctx context.Context, obj *types.Report) (*types.Audit, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetAudit)
prb := r.ProboService(ctx, obj.ID.TenantID())
audit, err := prb.Audits.GetByReportID(ctx, obj.ID)
if err != nil {
panic(fmt.Errorf("cannot load audit for report: %w", err))
}
return types.NewAudit(audit), nil
}
// Owner is the resolver for the owner field.
func (r *riskResolver) Owner(ctx context.Context, obj *types.Risk) (*types.People, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetOwner)
prb := r.ProboService(ctx, obj.ID.TenantID())
risk, err := prb.Risks.Get(ctx, obj.ID)
if err != nil {
var errNotFound *coredata.ErrRiskNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get risk: %w", err))
}
if risk.OwnerID == nil {
return nil, nil
}
owner, err := prb.Peoples.Get(ctx, *risk.OwnerID)
if err != nil {
var errNotFound *coredata.ErrPeopleNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get owner: %w", err))
}
return types.NewPeople(owner), nil
}
// Organization is the resolver for the organization field.
func (r *riskResolver) Organization(ctx context.Context, obj *types.Risk) (*types.Organization, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetOrganization)
prb := r.ProboService(ctx, obj.ID.TenantID())
risk, err := prb.Risks.Get(ctx, obj.ID)
if err != nil {
panic(fmt.Errorf("cannot get risk: %w", err))
}
organization, err := prb.Organizations.Get(ctx, risk.OrganizationID)
if err != nil {
var errNotFound *coredata.ErrOrganizationNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get organization: %w", err))
}
return types.NewOrganization(organization), nil
}
// Measures is the resolver for the measures field.
func (r *riskResolver) Measures(ctx context.Context, obj *types.Risk, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.MeasureOrderBy, filter *types.MeasureFilter) (*types.MeasureConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListMeasures)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.MeasureOrderField]{
Field: coredata.MeasureOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.MeasureOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
var measureFilter = coredata.NewMeasureFilter(nil, nil)
if filter != nil {
measureFilter = coredata.NewMeasureFilter(filter.Query, filter.State)
}
page, err := prb.Measures.ListForRiskID(ctx, obj.ID, cursor, measureFilter)
if err != nil {
panic(fmt.Errorf("cannot list risk measures: %w", err))
}
return types.NewMeasureConnection(page, r, obj.ID, measureFilter), nil
}
// Documents is the resolver for the documents field.
func (r *riskResolver) Documents(ctx context.Context, obj *types.Risk, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentOrderBy, filter *types.DocumentFilter) (*types.DocumentConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListDocuments)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.DocumentOrderField]{
Field: coredata.DocumentOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.DocumentOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
var documentFilter = coredata.NewDocumentFilter(nil)
if filter != nil {
documentFilter = coredata.NewDocumentFilter(filter.Query)
}
page, err := prb.Documents.ListForRiskID(ctx, obj.ID, cursor, documentFilter)
if err != nil {
panic(fmt.Errorf("cannot list risk documents: %w", err))
}
return types.NewDocumentConnection(page, r, obj.ID, documentFilter), nil
}
// Controls is the resolver for the controls field.
func (r *riskResolver) Controls(ctx context.Context, obj *types.Risk, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ControlOrderBy, filter *types.ControlFilter) (*types.ControlConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListControls)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.ControlOrderField]{
Field: coredata.ControlOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.ControlOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
var filters = coredata.NewControlFilter(nil)
if filter != nil {
filters = coredata.NewControlFilter(filter.Query)
}
page, err := prb.Controls.ListForRiskID(ctx, obj.ID, cursor, filters)
if err != nil {
panic(fmt.Errorf("cannot list risk controls: %w", err))
}
return types.NewControlConnection(page, r, obj.ID, filters), nil
}
// Obligations is the resolver for the obligations field.
func (r *riskResolver) Obligations(ctx context.Context, obj *types.Risk, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ObligationOrderBy, filter *types.ObligationFilter) (*types.ObligationConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListObligations)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.ObligationOrderField]{
Field: coredata.ObligationOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.ObligationOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
var obligationFilter = coredata.NewObligationFilter(nil)
if filter != nil {
obligationFilter = coredata.NewObligationFilter(&filter.SnapshotID)
}
page, err := prb.Obligations.ListForRiskID(ctx, obj.ID, cursor, obligationFilter)
if err != nil {
panic(fmt.Errorf("cannot list risk obligations: %w", err))
}
return types.NewObligationConnection(page, r, obj.ID, filter), nil
}
// TotalCount is the resolver for the totalCount field.
func (r *riskConnectionResolver) TotalCount(ctx context.Context, obj *types.RiskConnection) (int, error) {
r.MustBeAuthorized(ctx, obj.ParentID, authz.ActionTotalCount)
prb := r.ProboService(ctx, obj.ParentID.TenantID())
switch obj.Resolver.(type) {
case *measureResolver:
count, err := prb.Risks.CountForMeasureID(ctx, obj.ParentID, obj.Filters)
if err != nil {
panic(fmt.Errorf("cannot count risks: %w", err))
}
return count, nil
case *organizationResolver:
count, err := prb.Risks.CountForOrganizationID(ctx, obj.ParentID, obj.Filters)
if err != nil {
panic(fmt.Errorf("cannot count risks: %w", err))
}
return count, nil
}
panic(fmt.Errorf("unsupported resolver: %T", obj.Resolver))
}
// Organization is the resolver for the organization field.
func (r *sAMLConfigurationResolver) Organization(ctx context.Context, obj *types.SAMLConfiguration) (*types.Organization, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetOrganization)
tenantID := obj.ID.TenantID()
prb := r.ProboService(ctx, tenantID)
authSvc := r.AuthService(ctx, tenantID)
config, err := authSvc.GetSAMLConfigurationByID(ctx, obj.ID)
if err != nil {
return nil, fmt.Errorf("cannot load SAML configuration: %w", err)
}
org, err := prb.Organizations.Get(ctx, config.OrganizationID)
if err != nil {
return nil, fmt.Errorf("cannot load organization: %w", err)
}
return types.NewOrganization(org), nil
}
// SpMetadataURL is the resolver for the spMetadataUrl field.
// Returns global Entity ID (same as spEntityId since metadata URL no longer needs config parameter)
func (r *sAMLConfigurationResolver) SpMetadataURL(ctx context.Context, obj *types.SAMLConfiguration) (string, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionSpMetadataUrl)
return r.samlSvc.GetEntityID(), nil
}
// TestLoginURL is the resolver for the testLoginUrl field.
func (r *sAMLConfigurationResolver) TestLoginURL(ctx context.Context, obj *types.SAMLConfiguration) (string, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionTestLoginUrl)
entityID := r.samlSvc.GetEntityID()
parts := strings.Split(entityID, "/connect/saml/metadata")
if len(parts) != 2 {
return "", fmt.Errorf("invalid entity ID format")
}
return fmt.Sprintf("%s/connect/saml/login/%s", parts[0], obj.ID), nil
}
// Signed is the resolver for the signed field.
func (r *signableDocumentResolver) Signed(ctx context.Context, obj *types.SignableDocument) (bool, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetSigned)
user := UserFromContext(ctx)
if user == nil {
panic(fmt.Errorf("user not found in context"))
}
prb := r.ProboService(ctx, obj.ID.TenantID())
signed, err := prb.Documents.IsSigned(ctx, obj.ID, user.EmailAddress)
if err != nil {
panic(fmt.Errorf("cannot check if document is signed: %w", err))
}
return signed, nil
}
// Versions is the resolver for the versions field.
func (r *signableDocumentResolver) Versions(ctx context.Context, obj *types.SignableDocument, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentVersionOrderBy, filter *types.DocumentVersionFilter) (*types.DocumentVersionConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListSignableDocumentVersion)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.DocumentVersionOrderField]{
Field: coredata.DocumentVersionOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.DocumentVersionOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
user := UserFromContext(ctx)
if user == nil {
panic(fmt.Errorf("user not found in context"))
}
versionFilter := coredata.NewDocumentVersionFilter().WithUserEmail(&user.EmailAddress)
page, err := prb.Documents.ListVersions(ctx, obj.ID, cursor, versionFilter)
if err != nil {
panic(fmt.Errorf("cannot list signable document versions: %w", err))
}
return types.NewDocumentVersionConnection(page), nil
}
// Organization is the resolver for the organization field.
func (r *snapshotResolver) Organization(ctx context.Context, obj *types.Snapshot) (*types.Organization, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetOrganization)
prb := r.ProboService(ctx, obj.ID.TenantID())
snapshot, err := prb.Snapshots.Get(ctx, obj.ID)
if err != nil {
panic(fmt.Errorf("cannot get snapshot: %w", err))
}
organization, err := prb.Organizations.Get(ctx, snapshot.OrganizationID)
if err != nil {
var errNotFound *coredata.ErrOrganizationNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get organization: %w", err))
}
return types.NewOrganization(organization), nil
}
// Controls is the resolver for the controls field.
func (r *snapshotResolver) Controls(ctx context.Context, obj *types.Snapshot, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ControlOrderBy, filter *types.ControlFilter) (*types.ControlConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListControls)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.ControlOrderField]{
Field: coredata.ControlOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.ControlOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
var controlFilter = coredata.NewControlFilter(nil)
if filter != nil {
controlFilter = coredata.NewControlFilter(filter.Query)
}
page, err := prb.Controls.ListForSnapshotID(ctx, obj.ID, cursor, controlFilter)
if err != nil {
panic(fmt.Errorf("cannot list snapshot controls: %w", err))
}
return types.NewControlConnection(page, r, obj.ID, controlFilter), nil
}
// TotalCount is the resolver for the totalCount field.
func (r *snapshotConnectionResolver) TotalCount(ctx context.Context, obj *types.SnapshotConnection) (int, error) {
r.MustBeAuthorized(ctx, obj.ParentID, authz.ActionTotalCount)
prb := r.ProboService(ctx, obj.ParentID.TenantID())
switch obj.Resolver.(type) {
case *organizationResolver:
count, err := prb.Snapshots.CountForOrganizationID(ctx, obj.ParentID)
if err != nil {
panic(fmt.Errorf("cannot count snapshots: %w", err))
}
return count, nil
}
panic(fmt.Errorf("unsupported resolver: %T", obj.Resolver))
}
// AssignedTo is the resolver for the assignedTo field.
func (r *taskResolver) AssignedTo(ctx context.Context, obj *types.Task) (*types.People, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetAssignedTo)
prb := r.ProboService(ctx, obj.ID.TenantID())
task, err := prb.Tasks.Get(ctx, obj.ID)
if err != nil {
var errNotFound *coredata.ErrTaskNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get task: %w", err))
}
if task.AssignedToID == nil {
return nil, nil
}
people, err := prb.Peoples.Get(ctx, *task.AssignedToID)
if err != nil {
var errNotFound *coredata.ErrPeopleNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get assigned to: %w", err))
}
return types.NewPeople(people), nil
}
// Organization is the resolver for the organization field.
func (r *taskResolver) Organization(ctx context.Context, obj *types.Task) (*types.Organization, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetOrganization)
prb := r.ProboService(ctx, obj.ID.TenantID())
task, err := prb.Tasks.Get(ctx, obj.ID)
if err != nil {
var errNotFound *coredata.ErrTaskNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get task: %w", err))
}
organization, err := prb.Organizations.Get(ctx, task.OrganizationID)
if err != nil {
var errNotFound *coredata.ErrOrganizationNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get organization: %w", err))
}
return types.NewOrganization(organization), nil
}
// Measure is the resolver for the measure field.
func (r *taskResolver) Measure(ctx context.Context, obj *types.Task) (*types.Measure, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetMeasure)
prb := r.ProboService(ctx, obj.ID.TenantID())
task, err := prb.Tasks.Get(ctx, obj.ID)
if err != nil {
var errNotFound *coredata.ErrTaskNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get task: %w", err))
}
measure, err := prb.Measures.Get(ctx, *task.MeasureID)
if err != nil {
var errNotFound *coredata.ErrMeasureNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get measure: %w", err))
}
return types.NewMeasure(measure), nil
}
// Evidences is the resolver for the evidences field.
func (r *taskResolver) Evidences(ctx context.Context, obj *types.Task, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.EvidenceOrderBy) (*types.EvidenceConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListEvidences)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.EvidenceOrderField]{
Field: coredata.EvidenceOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.EvidenceOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := prb.Evidences.ListForTaskID(ctx, obj.ID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list task evidences: %w", err))
}
return types.NewEvidenceConnection(page, r, obj.ID), nil
}
// TotalCount is the resolver for the totalCount field.
func (r *taskConnectionResolver) TotalCount(ctx context.Context, obj *types.TaskConnection) (int, error) {
r.MustBeAuthorized(ctx, obj.ParentID, authz.ActionTotalCount)
prb := r.ProboService(ctx, obj.ParentID.TenantID())
switch obj.Resolver.(type) {
case *measureResolver:
count, err := prb.Tasks.CountForMeasureID(ctx, obj.ParentID)
if err != nil {
panic(fmt.Errorf("cannot count tasks: %w", err))
}
return count, nil
case *organizationResolver:
count, err := prb.Tasks.CountForOrganizationID(ctx, obj.ParentID)
if err != nil {
panic(fmt.Errorf("cannot count tasks: %w", err))
}
return count, nil
}
panic(fmt.Errorf("unsupported resolver: %T", obj.Resolver))
}
// ProcessingActivity is the resolver for the processingActivity field.
func (r *transferImpactAssessmentResolver) ProcessingActivity(ctx context.Context, obj *types.TransferImpactAssessment) (*types.ProcessingActivity, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGet)
prb := r.ProboService(ctx, obj.ID.TenantID())
tia, err := prb.TransferImpactAssessments.Get(ctx, obj.ID)
if err != nil {
panic(fmt.Errorf("cannot get transfer impact assessment: %w", err))
}
processingActivity, err := prb.ProcessingActivities.Get(ctx, tia.ProcessingActivityID)
if err != nil {
panic(fmt.Errorf("cannot get processing activity: %w", err))
}
return types.NewProcessingActivity(processingActivity), nil
}
// Organization is the resolver for the organization field.
func (r *transferImpactAssessmentResolver) Organization(ctx context.Context, obj *types.TransferImpactAssessment) (*types.Organization, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetOrganization)
prb := r.ProboService(ctx, obj.ID.TenantID())
tia, err := prb.TransferImpactAssessments.Get(ctx, obj.ID)
if err != nil {
panic(fmt.Errorf("cannot get transfer impact assessment: %w", err))
}
organization, err := prb.Organizations.Get(ctx, tia.OrganizationID)
if err != nil {
var errNotFound *coredata.ErrOrganizationNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get organization: %w", err))
}
return types.NewOrganization(organization), nil
}
// TotalCount is the resolver for the totalCount field.
func (r *transferImpactAssessmentConnectionResolver) TotalCount(ctx context.Context, obj *types.TransferImpactAssessmentConnection) (int, error) {
r.MustBeAuthorized(ctx, obj.ParentID, authz.ActionTotalCount)
prb := r.ProboService(ctx, obj.ParentID.TenantID())
switch obj.Resolver.(type) {
case *organizationResolver:
count, err := prb.TransferImpactAssessments.CountForOrganizationID(ctx, obj.ParentID, obj.Filter)
if err != nil {
panic(fmt.Errorf("cannot count organization transfer impact assessments: %w", err))
}
return count, nil
}
panic(fmt.Errorf("unsupported resolver: %T", obj.Resolver))
}
// NdaFileURL is the resolver for the ndaFileUrl field.
func (r *trustCenterResolver) NdaFileURL(ctx context.Context, obj *types.TrustCenter) (*string, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetNdaFileUrl)
prb := r.ProboService(ctx, obj.ID.TenantID())
fileURL, err := prb.TrustCenters.GenerateNDAFileURL(ctx, obj.ID, 15*time.Minute)
if err != nil {
panic(fmt.Errorf("cannot generate NDA file URL: %w", err))
}
return fileURL, nil
}
// Organization is the resolver for the organization field.
func (r *trustCenterResolver) Organization(ctx context.Context, obj *types.TrustCenter) (*types.Organization, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetOrganization)
prb := r.ProboService(ctx, obj.ID.TenantID())
trustCenter, _, err := prb.TrustCenters.Get(ctx, obj.ID)
if err != nil {
panic(fmt.Errorf("cannot get trust center: %w", err))
}
organization, err := prb.Organizations.Get(ctx, trustCenter.OrganizationID)
if err != nil {
var errNotFound *coredata.ErrOrganizationNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get organization: %w", err))
}
return types.NewOrganization(organization), nil
}
// 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) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListAccesses)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.TrustCenterAccessOrderField]{
Field: coredata.TrustCenterAccessOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.TrustCenterAccessOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
result, err := prb.TrustCenterAccesses.ListForTrustCenterID(ctx, obj.ID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list trust center accesses: %w", err))
}
return types.NewTrustCenterAccessConnection(result), nil
}
// 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) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListReferences)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.TrustCenterReferenceOrderField]{
Field: coredata.TrustCenterReferenceOrderFieldRank,
Direction: page.OrderDirectionAsc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.TrustCenterReferenceOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
result, err := prb.TrustCenterReferences.ListForTrustCenterID(ctx, obj.ID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list trust center references: %w", err))
}
return types.NewTrustCenterReferenceConnection(result, obj.ID), nil
}
// PendingRequestCount is the resolver for the pendingRequestCount field.
func (r *trustCenterAccessResolver) PendingRequestCount(ctx context.Context, obj *types.TrustCenterAccess) (int, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionPendingRequestCount)
prb := r.ProboService(ctx, obj.ID.TenantID())
count, err := prb.TrustCenterAccesses.CountPendingRequestDocumentAccesses(ctx, obj.ID)
if err != nil {
panic(fmt.Errorf("cannot count pending request document accesses: %w", err))
}
return count, nil
}
// ActiveCount is the resolver for the activeCount field.
func (r *trustCenterAccessResolver) ActiveCount(ctx context.Context, obj *types.TrustCenterAccess) (int, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionActiveCount)
prb := r.ProboService(ctx, obj.ID.TenantID())
count, err := prb.TrustCenterAccesses.CountActiveDocumentAccesses(ctx, obj.ID)
if err != nil {
panic(fmt.Errorf("cannot count active document accesses: %w", err))
}
return count, nil
}
// 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) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionAvailableDocumentAccesses)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.TrustCenterDocumentAccessOrderField]{
Field: coredata.TrustCenterDocumentAccessOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.TrustCenterDocumentAccessOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
result, err := prb.TrustCenterAccesses.ListAvailableDocumentAccesses(ctx, obj.ID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list trust center document accesses: %w", err))
}
return types.NewTrustCenterDocumentAccessConnection(result, obj, obj.ID), nil
}
// Document is the resolver for the document field.
func (r *trustCenterDocumentAccessResolver) Document(ctx context.Context, obj *types.TrustCenterDocumentAccess) (*types.Document, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGet)
if obj.DocumentID == nil {
return nil, nil
}
prb := r.ProboService(ctx, obj.TrustCenterAccessID.TenantID())
document, err := prb.Documents.Get(ctx, *obj.DocumentID)
if err != nil {
var errNotFound *coredata.ErrDocumentNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
return nil, fmt.Errorf("cannot load document: %w", err)
}
return types.NewDocument(document), nil
}
// Report is the resolver for the report field.
func (r *trustCenterDocumentAccessResolver) Report(ctx context.Context, obj *types.TrustCenterDocumentAccess) (*types.Report, error) {
r.MustBeAuthorized(ctx, obj.TrustCenterAccessID, authz.ActionGetReport)
if obj.ReportID == nil {
return nil, nil
}
prb := r.ProboService(ctx, obj.TrustCenterAccessID.TenantID())
report, err := prb.Reports.Get(ctx, *obj.ReportID)
if err != nil {
panic(fmt.Errorf("cannot load report: %w", err))
}
return types.NewReport(report), nil
}
// TrustCenterFile is the resolver for the trustCenterFile field.
func (r *trustCenterDocumentAccessResolver) TrustCenterFile(ctx context.Context, obj *types.TrustCenterDocumentAccess) (*types.TrustCenterFile, error) {
r.MustBeAuthorized(ctx, obj.TrustCenterAccessID, authz.ActionGetTrustCenterFile)
if obj.TrustCenterFileID == nil {
return nil, nil
}
prb := r.ProboService(ctx, obj.TrustCenterAccessID.TenantID())
trustCenterFile, err := prb.TrustCenterFiles.Get(ctx, *obj.TrustCenterFileID)
if err != nil {
panic(fmt.Errorf("cannot load trust center file: %w", err))
}
return types.NewTrustCenterFile(trustCenterFile), nil
}
// TotalCount is the resolver for the totalCount field.
func (r *trustCenterDocumentAccessConnectionResolver) TotalCount(ctx context.Context, obj *types.TrustCenterDocumentAccessConnection) (int, error) {
r.MustBeAuthorized(ctx, obj.ParentID, authz.ActionTotalCount)
prb := r.ProboService(ctx, obj.ParentID.TenantID())
count, err := prb.TrustCenterAccesses.CountDocumentAccesses(ctx, obj.ParentID)
if err != nil {
panic(fmt.Errorf("cannot count trust center document accesses: %w", err))
}
return count, nil
}
// FileURL is the resolver for the fileUrl field.
func (r *trustCenterFileResolver) FileURL(ctx context.Context, obj *types.TrustCenterFile) (string, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetFileUrl)
prb := r.ProboService(ctx, obj.ID.TenantID())
fileURL, err := prb.TrustCenterFiles.GenerateFileURL(ctx, obj.ID, 1*time.Hour)
if err != nil {
panic(fmt.Errorf("cannot generate file URL: %w", err))
}
return fileURL, nil
}
// Organization is the resolver for the organization field.
func (r *trustCenterFileResolver) Organization(ctx context.Context, obj *types.TrustCenterFile) (*types.Organization, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetOrganization)
prb := r.ProboService(ctx, obj.ID.TenantID())
trustCenterFile, err := prb.TrustCenterFiles.Get(ctx, obj.ID)
if err != nil {
panic(fmt.Errorf("cannot get trust center file: %w", err))
}
organization, err := prb.Organizations.Get(ctx, trustCenterFile.OrganizationID)
if err != nil {
var errNotFound *coredata.ErrOrganizationNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get organization: %w", err))
}
return types.NewOrganization(organization), nil
}
// TotalCount is the resolver for the totalCount field.
func (r *trustCenterFileConnectionResolver) TotalCount(ctx context.Context, obj *types.TrustCenterFileConnection) (int, error) {
r.MustBeAuthorized(ctx, obj.ParentID, authz.ActionTotalCount)
prb := r.ProboService(ctx, obj.ParentID.TenantID())
count, err := prb.TrustCenterFiles.CountForOrganizationID(ctx, obj.ParentID)
if err != nil {
panic(fmt.Errorf("cannot count trust center files: %w", err))
}
return count, nil
}
// LogoURL is the resolver for the logoUrl field.
func (r *trustCenterReferenceResolver) LogoURL(ctx context.Context, obj *types.TrustCenterReference) (string, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetLogoUrl)
prb := r.ProboService(ctx, obj.ID.TenantID())
fileURL, err := prb.TrustCenterReferences.GenerateLogoURL(ctx, obj.ID, 1*time.Hour)
if err != nil {
panic(fmt.Errorf("cannot generate logo URL: %w", err))
}
return fileURL, nil
}
// TotalCount is the resolver for the totalCount field.
func (r *trustCenterReferenceConnectionResolver) TotalCount(ctx context.Context, obj *types.TrustCenterReferenceConnection) (int, error) {
r.MustBeAuthorized(ctx, obj.ParentID, authz.ActionTotalCount)
prb := r.ProboService(ctx, obj.ParentID.TenantID())
count, err := prb.TrustCenterReferences.CountForTrustCenterID(ctx, obj.ParentID)
if err != nil {
panic(fmt.Errorf("cannot count trust center references: %w", err))
}
return count, nil
}
// TotalCount is the resolver for the totalCount field.
func (r *userConnectionResolver) TotalCount(ctx context.Context, obj *types.UserConnection) (int, error) {
r.MustBeAuthorized(ctx, obj.ParentID, authz.ActionTotalCount)
switch obj.Resolver.(type) {
case *organizationResolver:
authzSvc := r.AuthzService(ctx, obj.ParentID.TenantID())
count, err := authzSvc.CountOrganizationUsers(ctx, obj.ParentID)
if err != nil {
panic(fmt.Errorf("cannot count organization users: %w", err))
}
return count, nil
default:
panic(fmt.Errorf("unknown resolver type for user connection"))
}
}
// Organization is the resolver for the organization field.
func (r *vendorResolver) Organization(ctx context.Context, obj *types.Vendor) (*types.Organization, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetOrganization)
prb := r.ProboService(ctx, obj.ID.TenantID())
vendor, err := prb.Vendors.Get(ctx, obj.ID)
if err != nil {
var errNotFound *coredata.ErrVendorNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get vendor: %w", err))
}
organization, err := prb.Organizations.Get(ctx, vendor.OrganizationID)
if err != nil {
var errNotFound *coredata.ErrOrganizationNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get organization: %w", err))
}
return types.NewOrganization(organization), nil
}
// ComplianceReports is the resolver for the complianceReports field.
func (r *vendorResolver) ComplianceReports(ctx context.Context, obj *types.Vendor, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.VendorComplianceReportOrderBy) (*types.VendorComplianceReportConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListComplianceReports)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.VendorComplianceReportOrderField]{
Field: coredata.VendorComplianceReportOrderFieldReportDate,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.VendorComplianceReportOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := prb.VendorComplianceReports.ListForVendorID(ctx, obj.ID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list vendor compliance reports: %w", err))
}
return types.NewVendorComplianceReportConnection(page), nil
}
// BusinessAssociateAgreement is the resolver for the businessAssociateAgreement field.
func (r *vendorResolver) BusinessAssociateAgreement(ctx context.Context, obj *types.Vendor) (*types.VendorBusinessAssociateAgreement, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetBusinessAssociateAgreement)
prb := r.ProboService(ctx, obj.ID.TenantID())
vendorBusinessAssociateAgreement, file, err := prb.VendorBusinessAssociateAgreements.GetByVendorID(ctx, obj.ID)
if err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, nil
}
panic(fmt.Errorf("cannot get vendor business associate agreement: %w", err))
}
return types.NewVendorBusinessAssociateAgreement(vendorBusinessAssociateAgreement, file), nil
}
// DataPrivacyAgreement is the resolver for the dataPrivacyAgreement field.
func (r *vendorResolver) DataPrivacyAgreement(ctx context.Context, obj *types.Vendor) (*types.VendorDataPrivacyAgreement, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetDataPrivacyAgreement)
prb := r.ProboService(ctx, obj.ID.TenantID())
vendorDataPrivacyAgreement, file, err := prb.VendorDataPrivacyAgreements.GetByVendorID(ctx, obj.ID)
if err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, nil
}
panic(fmt.Errorf("cannot get vendor data privacy agreement: %w", err))
}
return types.NewVendorDataPrivacyAgreement(vendorDataPrivacyAgreement, file), nil
}
// Contacts is the resolver for the contacts field.
func (r *vendorResolver) Contacts(ctx context.Context, obj *types.Vendor, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.VendorContactOrderBy) (*types.VendorContactConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListContacts)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.VendorContactOrderField]{
Field: coredata.VendorContactOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.VendorContactOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := prb.VendorContacts.List(ctx, obj.ID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list vendor contacts: %w", err))
}
return types.NewVendorContactConnection(page), nil
}
// Services is the resolver for the services field.
func (r *vendorResolver) Services(ctx context.Context, obj *types.Vendor, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.VendorServiceOrderBy) (*types.VendorServiceConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListServices)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.VendorServiceOrderField]{
Field: coredata.VendorServiceOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.VendorServiceOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := prb.VendorServices.List(ctx, obj.ID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list vendor services: %w", err))
}
return types.NewVendorServiceConnection(page), nil
}
// RiskAssessments is the resolver for the riskAssessments field.
func (r *vendorResolver) RiskAssessments(ctx context.Context, obj *types.Vendor, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.VendorRiskAssessmentOrder) (*types.VendorRiskAssessmentConnection, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListRiskAssessments)
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.VendorRiskAssessmentOrderField]{
Field: coredata.VendorRiskAssessmentOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.VendorRiskAssessmentOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := prb.Vendors.ListRiskAssessments(ctx, obj.ID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list vendor risk assessments: %w", err))
}
return types.NewVendorRiskAssessmentConnection(page), nil
}
// BusinessOwner is the resolver for the businessOwner field.
func (r *vendorResolver) BusinessOwner(ctx context.Context, obj *types.Vendor) (*types.People, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetBusinessOwner)
prb := r.ProboService(ctx, obj.ID.TenantID())
vendor, err := prb.Vendors.Get(ctx, obj.ID)
if err != nil {
var errNotFound *coredata.ErrVendorNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get vendor: %w", err))
}
if vendor.BusinessOwnerID == nil {
return nil, nil
}
people, err := prb.Peoples.Get(ctx, *vendor.BusinessOwnerID)
if err != nil {
var errNotFound *coredata.ErrPeopleNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get business owner: %w", err))
}
return types.NewPeople(people), nil
}
// SecurityOwner is the resolver for the securityOwner field.
func (r *vendorResolver) SecurityOwner(ctx context.Context, obj *types.Vendor) (*types.People, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetSecurityOwner)
prb := r.ProboService(ctx, obj.ID.TenantID())
vendor, err := prb.Vendors.Get(ctx, obj.ID)
if err != nil {
var errNotFound *coredata.ErrVendorNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get vendor: %w", err))
}
if vendor.SecurityOwnerID == nil {
return nil, nil
}
people, err := prb.Peoples.Get(ctx, *vendor.SecurityOwnerID)
if err != nil {
var errNotFound *coredata.ErrPeopleNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get security owner: %w", err))
}
return types.NewPeople(people), nil
}
// Vendor is the resolver for the vendor field.
func (r *vendorBusinessAssociateAgreementResolver) Vendor(ctx context.Context, obj *types.VendorBusinessAssociateAgreement) (*types.Vendor, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetVendor)
prb := r.ProboService(ctx, obj.ID.TenantID())
vendor, err := prb.Vendors.Get(ctx, obj.ID)
if err != nil {
var errNotFound *coredata.ErrVendorNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
return nil, fmt.Errorf("cannot get vendor: %w", err)
}
return types.NewVendor(vendor), nil
}
// FileURL is the resolver for the fileUrl field.
func (r *vendorBusinessAssociateAgreementResolver) FileURL(ctx context.Context, obj *types.VendorBusinessAssociateAgreement) (string, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetFileUrl)
prb := r.ProboService(ctx, obj.ID.TenantID())
fileURL, err := prb.VendorBusinessAssociateAgreements.GenerateFileURL(ctx, obj.ID, 1*time.Hour)
if err != nil {
panic(fmt.Errorf("cannot generate file URL: %w", err))
}
return fileURL, nil
}
// Vendor is the resolver for the vendor field.
func (r *vendorComplianceReportResolver) Vendor(ctx context.Context, obj *types.VendorComplianceReport) (*types.Vendor, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetVendor)
prb := r.ProboService(ctx, obj.ID.TenantID())
vendor, err := prb.Vendors.Get(ctx, obj.ID)
if err != nil {
var errNotFound *coredata.ErrVendorNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get vendor: %w", err))
}
return types.NewVendor(vendor), nil
}
// File is the resolver for the file field.
func (r *vendorComplianceReportResolver) File(ctx context.Context, obj *types.VendorComplianceReport) (*types.File, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetFile)
prb := r.ProboService(ctx, obj.ID.TenantID())
evidence, err := prb.VendorComplianceReports.Get(ctx, obj.ID)
if err != nil {
panic(fmt.Errorf("cannot load evidence: %w", err))
}
if evidence.ReportFileId == nil {
return nil, nil
}
file, err := prb.Files.Get(ctx, *evidence.ReportFileId)
if err != nil {
var errNotFound *coredata.ErrFileNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot load evidence file: %w", err))
}
return types.NewFile(file), nil
}
// TotalCount is the resolver for the totalCount field.
func (r *vendorConnectionResolver) TotalCount(ctx context.Context, obj *types.VendorConnection) (int, error) {
r.MustBeAuthorized(ctx, obj.ParentID, authz.ActionTotalCount)
prb := r.ProboService(ctx, obj.ParentID.TenantID())
switch obj.Resolver.(type) {
case *organizationResolver:
count, err := prb.Vendors.CountForOrganizationID(ctx, obj.ParentID)
if err != nil {
panic(fmt.Errorf("cannot count vendors: %w", err))
}
return count, nil
case *assetResolver:
count, err := prb.Vendors.CountForAssetID(ctx, obj.ParentID)
if err != nil {
panic(fmt.Errorf("cannot count vendors: %w", err))
}
return count, nil
case *datumResolver:
count, err := prb.Vendors.CountForDatumID(ctx, obj.ParentID)
if err != nil {
panic(fmt.Errorf("cannot count vendors: %w", err))
}
return count, nil
}
panic(fmt.Errorf("unsupported resolver: %T", obj.Resolver))
}
// Vendor is the resolver for the vendor field.
func (r *vendorContactResolver) Vendor(ctx context.Context, obj *types.VendorContact) (*types.Vendor, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetVendor)
prb := r.ProboService(ctx, obj.ID.TenantID())
// Get the vendor contact to access the VendorID
vendorContact, err := prb.VendorContacts.Get(ctx, obj.ID)
if err != nil {
panic(fmt.Errorf("cannot get vendor contact: %w", err))
}
vendor, err := prb.Vendors.Get(ctx, vendorContact.VendorID)
if err != nil {
var errNotFound *coredata.ErrVendorNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get vendor: %w", err))
}
return types.NewVendor(vendor), nil
}
// Vendor is the resolver for the vendor field.
func (r *vendorDataPrivacyAgreementResolver) Vendor(ctx context.Context, obj *types.VendorDataPrivacyAgreement) (*types.Vendor, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetVendor)
prb := r.ProboService(ctx, obj.ID.TenantID())
vendor, err := prb.Vendors.Get(ctx, obj.ID)
if err != nil {
var errNotFound *coredata.ErrVendorNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get vendor: %w", err))
}
return types.NewVendor(vendor), nil
}
// FileURL is the resolver for the fileUrl field.
func (r *vendorDataPrivacyAgreementResolver) FileURL(ctx context.Context, obj *types.VendorDataPrivacyAgreement) (string, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetFileUrl)
prb := r.ProboService(ctx, obj.ID.TenantID())
fileURL, err := prb.VendorDataPrivacyAgreements.GenerateFileURL(ctx, obj.ID, 1*time.Hour)
if err != nil {
panic(fmt.Errorf("cannot generate file URL: %w", err))
}
return fileURL, nil
}
// Vendor is the resolver for the vendor field.
func (r *vendorRiskAssessmentResolver) Vendor(ctx context.Context, obj *types.VendorRiskAssessment) (*types.Vendor, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetVendor)
prb := r.ProboService(ctx, obj.ID.TenantID())
vendor, err := prb.Vendors.GetByRiskAssessmentID(ctx, obj.ID)
if err != nil {
var errNotFound *coredata.ErrVendorNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get vendor: %w", err))
}
return types.NewVendor(vendor), nil
}
// Vendor is the resolver for the vendor field.
func (r *vendorServiceResolver) Vendor(ctx context.Context, obj *types.VendorService) (*types.Vendor, error) {
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetVendor)
prb := r.ProboService(ctx, obj.ID.TenantID())
// Get the vendor service to access the VendorID
vendorService, err := prb.VendorServices.Get(ctx, obj.ID)
if err != nil {
panic(fmt.Errorf("cannot get vendor service: %w", err))
}
vendor, err := prb.Vendors.Get(ctx, vendorService.VendorID)
if err != nil {
var errNotFound *coredata.ErrVendorNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get vendor: %w", err))
}
return types.NewVendor(vendor), nil
}
// Organizations is the resolver for the organizations field.
func (r *viewerResolver) Organizations(ctx context.Context, obj *types.Viewer, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrganizationOrder) (*types.OrganizationConnection, error) {
user := UserFromContext(ctx)
pageOrderBy := page.OrderBy[coredata.OrganizationOrderField]{
Field: coredata.OrganizationOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.OrganizationOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
organizations, err := r.authzSvc.GetUserOrganizations(ctx, user.ID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list organizations for user: %w", err))
}
// Show all organizations the user is a member of
// Authentication requirements will be enforced when switching to an organization
page := page.NewPage(organizations, cursor)
return types.NewOrganizationConnection(page), nil
}
// SignableDocuments is the resolver for the signableDocuments field.
func (r *viewerResolver) SignableDocuments(ctx context.Context, obj *types.Viewer, organizationID gid.GID, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentOrderBy) (*types.SignableDocumentConnection, error) {
r.MustBeAuthorized(ctx, organizationID, authz.ActionListSignableDocuments)
prb := r.ProboService(ctx, organizationID.TenantID())
pageOrderBy := page.OrderBy[coredata.DocumentOrderField]{
Field: coredata.DocumentOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.DocumentOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
user := UserFromContext(ctx)
if user == nil {
panic(fmt.Errorf("user not found in context"))
}
documentFilter := coredata.NewDocumentFilter(nil).WithUserEmail(&user.EmailAddress)
documentsPage, err := prb.Documents.ListByOrganizationID(ctx, organizationID, cursor, documentFilter)
if err != nil {
panic(fmt.Errorf("cannot list organization signable documents: %w", err))
}
signableDocuments := make([]*types.SignableDocument, len(documentsPage.Data))
for i, doc := range documentsPage.Data {
signableDocuments[i] = &types.SignableDocument{
ID: doc.ID,
Title: doc.Title,
DocumentType: doc.DocumentType,
Classification: doc.Classification,
CreatedAt: doc.CreatedAt,
UpdatedAt: doc.UpdatedAt,
}
}
page := page.NewPage(signableDocuments, documentsPage.Cursor)
return types.NewSignableDocumentConnection(page), nil
}
// SignableDocument is the resolver for the signableDocument field.
func (r *viewerResolver) SignableDocument(ctx context.Context, obj *types.Viewer, id gid.GID) (*types.SignableDocument, error) {
r.MustBeAuthorized(ctx, id, authz.ActionGetSignableDocument)
prb := r.ProboService(ctx, id.TenantID())
user := UserFromContext(ctx)
if user == nil {
panic(fmt.Errorf("user not found in context"))
}
documentFilter := coredata.NewDocumentFilter(nil).WithUserEmail(&user.EmailAddress)
document, err := prb.Documents.GetWithFilter(ctx, id, documentFilter)
if err != nil {
var errNotFound *coredata.ErrDocumentNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get signable document: %w", err))
}
return &types.SignableDocument{
ID: document.ID,
Title: document.Title,
DocumentType: document.DocumentType,
Classification: document.Classification,
CreatedAt: document.CreatedAt,
UpdatedAt: document.UpdatedAt,
}, nil
}
// Asset returns schema.AssetResolver implementation.
func (r *Resolver) Asset() schema.AssetResolver { return &assetResolver{r} }
// AssetConnection returns schema.AssetConnectionResolver implementation.
func (r *Resolver) AssetConnection() schema.AssetConnectionResolver {
return &assetConnectionResolver{r}
}
// Audit returns schema.AuditResolver implementation.
func (r *Resolver) Audit() schema.AuditResolver { return &auditResolver{r} }
// AuditConnection returns schema.AuditConnectionResolver implementation.
func (r *Resolver) AuditConnection() schema.AuditConnectionResolver {
return &auditConnectionResolver{r}
}
// ContinualImprovement returns schema.ContinualImprovementResolver implementation.
func (r *Resolver) ContinualImprovement() schema.ContinualImprovementResolver {
return &continualImprovementResolver{r}
}
// ContinualImprovementConnection returns schema.ContinualImprovementConnectionResolver implementation.
func (r *Resolver) ContinualImprovementConnection() schema.ContinualImprovementConnectionResolver {
return &continualImprovementConnectionResolver{r}
}
// Control returns schema.ControlResolver implementation.
func (r *Resolver) Control() schema.ControlResolver { return &controlResolver{r} }
// ControlConnection returns schema.ControlConnectionResolver implementation.
func (r *Resolver) ControlConnection() schema.ControlConnectionResolver {
return &controlConnectionResolver{r}
}
// DataProtectionImpactAssessment returns schema.DataProtectionImpactAssessmentResolver implementation.
func (r *Resolver) DataProtectionImpactAssessment() schema.DataProtectionImpactAssessmentResolver {
return &dataProtectionImpactAssessmentResolver{r}
}
// DataProtectionImpactAssessmentConnection returns schema.DataProtectionImpactAssessmentConnectionResolver implementation.
func (r *Resolver) DataProtectionImpactAssessmentConnection() schema.DataProtectionImpactAssessmentConnectionResolver {
return &dataProtectionImpactAssessmentConnectionResolver{r}
}
// Datum returns schema.DatumResolver implementation.
func (r *Resolver) Datum() schema.DatumResolver { return &datumResolver{r} }
// DatumConnection returns schema.DatumConnectionResolver implementation.
func (r *Resolver) DatumConnection() schema.DatumConnectionResolver {
return &datumConnectionResolver{r}
}
// Document returns schema.DocumentResolver implementation.
func (r *Resolver) Document() schema.DocumentResolver { return &documentResolver{r} }
// DocumentConnection returns schema.DocumentConnectionResolver implementation.
func (r *Resolver) DocumentConnection() schema.DocumentConnectionResolver {
return &documentConnectionResolver{r}
}
// DocumentVersion returns schema.DocumentVersionResolver implementation.
func (r *Resolver) DocumentVersion() schema.DocumentVersionResolver {
return &documentVersionResolver{r}
}
// DocumentVersionSignature returns schema.DocumentVersionSignatureResolver implementation.
func (r *Resolver) DocumentVersionSignature() schema.DocumentVersionSignatureResolver {
return &documentVersionSignatureResolver{r}
}
// Evidence returns schema.EvidenceResolver implementation.
func (r *Resolver) Evidence() schema.EvidenceResolver { return &evidenceResolver{r} }
// EvidenceConnection returns schema.EvidenceConnectionResolver implementation.
func (r *Resolver) EvidenceConnection() schema.EvidenceConnectionResolver {
return &evidenceConnectionResolver{r}
}
// File returns schema.FileResolver implementation.
func (r *Resolver) File() schema.FileResolver { return &fileResolver{r} }
// Framework returns schema.FrameworkResolver implementation.
func (r *Resolver) Framework() schema.FrameworkResolver { return &frameworkResolver{r} }
// FrameworkConnection returns schema.FrameworkConnectionResolver implementation.
func (r *Resolver) FrameworkConnection() schema.FrameworkConnectionResolver {
return &frameworkConnectionResolver{r}
}
// Invitation returns schema.InvitationResolver implementation.
func (r *Resolver) Invitation() schema.InvitationResolver { return &invitationResolver{r} }
// InvitationConnection returns schema.InvitationConnectionResolver implementation.
func (r *Resolver) InvitationConnection() schema.InvitationConnectionResolver {
return &invitationConnectionResolver{r}
}
// Measure returns schema.MeasureResolver implementation.
func (r *Resolver) Measure() schema.MeasureResolver { return &measureResolver{r} }
// MeasureConnection returns schema.MeasureConnectionResolver implementation.
func (r *Resolver) MeasureConnection() schema.MeasureConnectionResolver {
return &measureConnectionResolver{r}
}
// Meeting returns schema.MeetingResolver implementation.
func (r *Resolver) Meeting() schema.MeetingResolver { return &meetingResolver{r} }
// MeetingConnection returns schema.MeetingConnectionResolver implementation.
func (r *Resolver) MeetingConnection() schema.MeetingConnectionResolver {
return &meetingConnectionResolver{r}
}
// Membership returns schema.MembershipResolver implementation.
func (r *Resolver) Membership() schema.MembershipResolver { return &membershipResolver{r} }
// MembershipConnection returns schema.MembershipConnectionResolver implementation.
func (r *Resolver) MembershipConnection() schema.MembershipConnectionResolver {
return &membershipConnectionResolver{r}
}
// Mutation returns schema.MutationResolver implementation.
func (r *Resolver) Mutation() schema.MutationResolver { return &mutationResolver{r} }
// Nonconformity returns schema.NonconformityResolver implementation.
func (r *Resolver) Nonconformity() schema.NonconformityResolver { return &nonconformityResolver{r} }
// NonconformityConnection returns schema.NonconformityConnectionResolver implementation.
func (r *Resolver) NonconformityConnection() schema.NonconformityConnectionResolver {
return &nonconformityConnectionResolver{r}
}
// Obligation returns schema.ObligationResolver implementation.
func (r *Resolver) Obligation() schema.ObligationResolver { return &obligationResolver{r} }
// ObligationConnection returns schema.ObligationConnectionResolver implementation.
func (r *Resolver) ObligationConnection() schema.ObligationConnectionResolver {
return &obligationConnectionResolver{r}
}
// Organization returns schema.OrganizationResolver implementation.
func (r *Resolver) Organization() schema.OrganizationResolver { return &organizationResolver{r} }
// PeopleConnection returns schema.PeopleConnectionResolver implementation.
func (r *Resolver) PeopleConnection() schema.PeopleConnectionResolver {
return &peopleConnectionResolver{r}
}
// ProcessingActivity returns schema.ProcessingActivityResolver implementation.
func (r *Resolver) ProcessingActivity() schema.ProcessingActivityResolver {
return &processingActivityResolver{r}
}
// ProcessingActivityConnection returns schema.ProcessingActivityConnectionResolver implementation.
func (r *Resolver) ProcessingActivityConnection() schema.ProcessingActivityConnectionResolver {
return &processingActivityConnectionResolver{r}
}
// Query returns schema.QueryResolver implementation.
func (r *Resolver) Query() schema.QueryResolver { return &queryResolver{r} }
// Report returns schema.ReportResolver implementation.
func (r *Resolver) Report() schema.ReportResolver { return &reportResolver{r} }
// Risk returns schema.RiskResolver implementation.
func (r *Resolver) Risk() schema.RiskResolver { return &riskResolver{r} }
// RiskConnection returns schema.RiskConnectionResolver implementation.
func (r *Resolver) RiskConnection() schema.RiskConnectionResolver { return &riskConnectionResolver{r} }
// SAMLConfiguration returns schema.SAMLConfigurationResolver implementation.
func (r *Resolver) SAMLConfiguration() schema.SAMLConfigurationResolver {
return &sAMLConfigurationResolver{r}
}
// SignableDocument returns schema.SignableDocumentResolver implementation.
func (r *Resolver) SignableDocument() schema.SignableDocumentResolver {
return &signableDocumentResolver{r}
}
// Snapshot returns schema.SnapshotResolver implementation.
func (r *Resolver) Snapshot() schema.SnapshotResolver { return &snapshotResolver{r} }
// SnapshotConnection returns schema.SnapshotConnectionResolver implementation.
func (r *Resolver) SnapshotConnection() schema.SnapshotConnectionResolver {
return &snapshotConnectionResolver{r}
}
// Task returns schema.TaskResolver implementation.
func (r *Resolver) Task() schema.TaskResolver { return &taskResolver{r} }
// TaskConnection returns schema.TaskConnectionResolver implementation.
func (r *Resolver) TaskConnection() schema.TaskConnectionResolver { return &taskConnectionResolver{r} }
// TransferImpactAssessment returns schema.TransferImpactAssessmentResolver implementation.
func (r *Resolver) TransferImpactAssessment() schema.TransferImpactAssessmentResolver {
return &transferImpactAssessmentResolver{r}
}
// TransferImpactAssessmentConnection returns schema.TransferImpactAssessmentConnectionResolver implementation.
func (r *Resolver) TransferImpactAssessmentConnection() schema.TransferImpactAssessmentConnectionResolver {
return &transferImpactAssessmentConnectionResolver{r}
}
// TrustCenter returns schema.TrustCenterResolver implementation.
func (r *Resolver) TrustCenter() schema.TrustCenterResolver { return &trustCenterResolver{r} }
// TrustCenterAccess returns schema.TrustCenterAccessResolver implementation.
func (r *Resolver) TrustCenterAccess() schema.TrustCenterAccessResolver {
return &trustCenterAccessResolver{r}
}
// TrustCenterDocumentAccess returns schema.TrustCenterDocumentAccessResolver implementation.
func (r *Resolver) TrustCenterDocumentAccess() schema.TrustCenterDocumentAccessResolver {
return &trustCenterDocumentAccessResolver{r}
}
// TrustCenterDocumentAccessConnection returns schema.TrustCenterDocumentAccessConnectionResolver implementation.
func (r *Resolver) TrustCenterDocumentAccessConnection() schema.TrustCenterDocumentAccessConnectionResolver {
return &trustCenterDocumentAccessConnectionResolver{r}
}
// TrustCenterFile returns schema.TrustCenterFileResolver implementation.
func (r *Resolver) TrustCenterFile() schema.TrustCenterFileResolver {
return &trustCenterFileResolver{r}
}
// TrustCenterFileConnection returns schema.TrustCenterFileConnectionResolver implementation.
func (r *Resolver) TrustCenterFileConnection() schema.TrustCenterFileConnectionResolver {
return &trustCenterFileConnectionResolver{r}
}
// TrustCenterReference returns schema.TrustCenterReferenceResolver implementation.
func (r *Resolver) TrustCenterReference() schema.TrustCenterReferenceResolver {
return &trustCenterReferenceResolver{r}
}
// TrustCenterReferenceConnection returns schema.TrustCenterReferenceConnectionResolver implementation.
func (r *Resolver) TrustCenterReferenceConnection() schema.TrustCenterReferenceConnectionResolver {
return &trustCenterReferenceConnectionResolver{r}
}
// UserConnection returns schema.UserConnectionResolver implementation.
func (r *Resolver) UserConnection() schema.UserConnectionResolver { return &userConnectionResolver{r} }
// Vendor returns schema.VendorResolver implementation.
func (r *Resolver) Vendor() schema.VendorResolver { return &vendorResolver{r} }
// VendorBusinessAssociateAgreement returns schema.VendorBusinessAssociateAgreementResolver implementation.
func (r *Resolver) VendorBusinessAssociateAgreement() schema.VendorBusinessAssociateAgreementResolver {
return &vendorBusinessAssociateAgreementResolver{r}
}
// VendorComplianceReport returns schema.VendorComplianceReportResolver implementation.
func (r *Resolver) VendorComplianceReport() schema.VendorComplianceReportResolver {
return &vendorComplianceReportResolver{r}
}
// VendorConnection returns schema.VendorConnectionResolver implementation.
func (r *Resolver) VendorConnection() schema.VendorConnectionResolver {
return &vendorConnectionResolver{r}
}
// VendorContact returns schema.VendorContactResolver implementation.
func (r *Resolver) VendorContact() schema.VendorContactResolver { return &vendorContactResolver{r} }
// VendorDataPrivacyAgreement returns schema.VendorDataPrivacyAgreementResolver implementation.
func (r *Resolver) VendorDataPrivacyAgreement() schema.VendorDataPrivacyAgreementResolver {
return &vendorDataPrivacyAgreementResolver{r}
}
// VendorRiskAssessment returns schema.VendorRiskAssessmentResolver implementation.
func (r *Resolver) VendorRiskAssessment() schema.VendorRiskAssessmentResolver {
return &vendorRiskAssessmentResolver{r}
}
// VendorService returns schema.VendorServiceResolver implementation.
func (r *Resolver) VendorService() schema.VendorServiceResolver { return &vendorServiceResolver{r} }
// Viewer returns schema.ViewerResolver implementation.
func (r *Resolver) Viewer() schema.ViewerResolver { return &viewerResolver{r} }
type assetResolver struct{ *Resolver }
type assetConnectionResolver struct{ *Resolver }
type auditResolver struct{ *Resolver }
type auditConnectionResolver struct{ *Resolver }
type continualImprovementResolver struct{ *Resolver }
type continualImprovementConnectionResolver struct{ *Resolver }
type controlResolver struct{ *Resolver }
type controlConnectionResolver struct{ *Resolver }
type dataProtectionImpactAssessmentResolver struct{ *Resolver }
type dataProtectionImpactAssessmentConnectionResolver struct{ *Resolver }
type datumResolver struct{ *Resolver }
type datumConnectionResolver struct{ *Resolver }
type documentResolver struct{ *Resolver }
type documentConnectionResolver struct{ *Resolver }
type documentVersionResolver struct{ *Resolver }
type documentVersionSignatureResolver struct{ *Resolver }
type evidenceResolver struct{ *Resolver }
type evidenceConnectionResolver struct{ *Resolver }
type fileResolver struct{ *Resolver }
type frameworkResolver struct{ *Resolver }
type frameworkConnectionResolver struct{ *Resolver }
type invitationResolver struct{ *Resolver }
type invitationConnectionResolver struct{ *Resolver }
type measureResolver struct{ *Resolver }
type measureConnectionResolver struct{ *Resolver }
type meetingResolver struct{ *Resolver }
type meetingConnectionResolver struct{ *Resolver }
type membershipResolver struct{ *Resolver }
type membershipConnectionResolver struct{ *Resolver }
type mutationResolver struct{ *Resolver }
type nonconformityResolver struct{ *Resolver }
type nonconformityConnectionResolver struct{ *Resolver }
type obligationResolver struct{ *Resolver }
type obligationConnectionResolver struct{ *Resolver }
type organizationResolver struct{ *Resolver }
type peopleConnectionResolver struct{ *Resolver }
type processingActivityResolver struct{ *Resolver }
type processingActivityConnectionResolver struct{ *Resolver }
type queryResolver struct{ *Resolver }
type reportResolver struct{ *Resolver }
type riskResolver struct{ *Resolver }
type riskConnectionResolver struct{ *Resolver }
type sAMLConfigurationResolver struct{ *Resolver }
type signableDocumentResolver struct{ *Resolver }
type snapshotResolver struct{ *Resolver }
type snapshotConnectionResolver struct{ *Resolver }
type taskResolver struct{ *Resolver }
type taskConnectionResolver struct{ *Resolver }
type transferImpactAssessmentResolver struct{ *Resolver }
type transferImpactAssessmentConnectionResolver struct{ *Resolver }
type trustCenterResolver struct{ *Resolver }
type trustCenterAccessResolver struct{ *Resolver }
type trustCenterDocumentAccessResolver struct{ *Resolver }
type trustCenterDocumentAccessConnectionResolver struct{ *Resolver }
type trustCenterFileResolver struct{ *Resolver }
type trustCenterFileConnectionResolver struct{ *Resolver }
type trustCenterReferenceResolver struct{ *Resolver }
type trustCenterReferenceConnectionResolver struct{ *Resolver }
type userConnectionResolver struct{ *Resolver }
type vendorResolver struct{ *Resolver }
type vendorBusinessAssociateAgreementResolver struct{ *Resolver }
type vendorComplianceReportResolver struct{ *Resolver }
type vendorConnectionResolver struct{ *Resolver }
type vendorContactResolver struct{ *Resolver }
type vendorDataPrivacyAgreementResolver struct{ *Resolver }
type vendorRiskAssessmentResolver struct{ *Resolver }
type vendorServiceResolver struct{ *Resolver }
type viewerResolver struct{ *Resolver }