Files
probo/pkg/server/api/console/v1/organization_resolvers.go
Sacha Al Himdani b9262b5150 Add risk assessment system
Introduce a hierarchical risk assessment model with six entity types:

- Risk Assessment: top-level container scoped to an organization
- Risk Assessment Scope: sub-container for scoping threat modeling
  exercises within an assessment
- Risk Assessment Node: DFD elements typed as ENTITY, BOUNDARY,
  ASSET, or DATA within a scope
- Risk Assessment Process: directed data flows between two nodes
- Risk Assessment Threat: descriptive threats attached to a process
  with a free-text category (e.g. Confidentiality, Integrity)
- Risk Scenario: thin join linking a threat to a risk from the
  register, carrying only a name and description

Risk scoring (likelihood, impact, treatment) remains on the existing
Risk entity. Threats are purely descriptive. Risk Scenarios connect
the threat model to the risk register without duplicating scores.

Backend: migration with PG enum for node types, coredata structs,
service layer with full CRUD and validation, GraphQL schema with
18 mutations and paginated connections, authorization actions and
policies, and base_resolvers.go Node dispatch for all entity types.

Frontend: Risk Assessments list page with create dialog, detail page
showing scopes as cards with nodes/processes/threats tables, inline
create/edit/delete actions on all entities, and a Scenarios tab on
the Risk detail page linking threats to risks. Existing RiskGraph.ts
hook file removed in favor of colocated queries in page files.

E2E tests cover CRUD for all entity types, RBAC, and tenant
isolation.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-05-19 21:44:27 +02:00

1414 lines
50 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.90
import (
"context"
"errors"
"fmt"
"time"
"go.gearno.de/kit/log"
"go.probo.inc/probo/pkg/accessreview/drivers"
"go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/iam"
"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"
"go.probo.inc/probo/pkg/server/gqlutils"
"go.probo.inc/probo/pkg/server/gqlutils/types/cursor"
"go.probo.inc/probo/pkg/slack"
"go.probo.inc/probo/pkg/validator"
)
// UpdateOrganizationContext is the resolver for the updateOrganizationContext field.
func (r *mutationResolver) UpdateOrganizationContext(ctx context.Context, input types.UpdateOrganizationContextInput) (*types.UpdateOrganizationContextPayload, error) {
if err := r.authorize(ctx, input.OrganizationID, probo.ActionOrganizationContextUpdate); err != nil {
return nil, err
}
prb := r.ProboService(ctx, input.OrganizationID.TenantID())
req := probo.UpdateOrganizationContextRequest{
OrganizationID: input.OrganizationID,
Product: gqlutils.UnwrapOmittable(input.Product),
Architecture: gqlutils.UnwrapOmittable(input.Architecture),
Team: gqlutils.UnwrapOmittable(input.Team),
Processes: gqlutils.UnwrapOmittable(input.Processes),
Customers: gqlutils.UnwrapOmittable(input.Customers),
}
organizationContext, err := prb.Organizations.UpdateContext(ctx, req)
if err != nil {
if validationErrors, ok := errors.AsType[validator.ValidationErrors](err); ok {
return nil, gqlutils.InvalidValidationErrors(ctx, validationErrors)
}
r.logger.ErrorCtx(ctx, "cannot update organization context", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return &types.UpdateOrganizationContextPayload{
Context: types.NewOrganizationContext(organizationContext),
}, nil
}
// LogoURL is the resolver for the logoUrl field.
func (r *organizationResolver) LogoURL(ctx context.Context, obj *types.Organization) (*string, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionOrganizationGetLogoUrl); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
logoURL, err := prb.Organizations.GenerateLogoURL(ctx, obj.ID, 1*time.Hour)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot generate logo url", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return logoURL, nil
}
// HorizontalLogoURL is the resolver for the horizontalLogoUrl field.
func (r *organizationResolver) HorizontalLogoURL(ctx context.Context, obj *types.Organization) (*string, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionOrganizationGetHorizontalLogoUrl); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
horizontalLogoURL, err := prb.Organizations.GenerateHorizontalLogoURL(ctx, obj.ID, 1*time.Hour)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot generate horizontal logo url", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return horizontalLogoURL, nil
}
// Context is the resolver for the context field.
func (r *organizationResolver) Context(ctx context.Context, obj *types.Organization) (*types.OrganizationContext, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionOrganizationContextGet); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
orgContext, err := prb.Organizations.GetContext(ctx, obj.ID)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot load organization context", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewOrganizationContext(orgContext), nil
}
// Profiles is the resolver for the profiles field.
func (r *organizationResolver) Profiles(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ProfileOrderBy, filter *types.ProfileFilter) (*types.ProfileConnection, error) {
if err := r.authorize(ctx, obj.ID, iam.ActionMembershipProfileList); err != nil {
return nil, err
}
if gqlutils.OnlyTotalCountSelected(ctx) {
return &types.ProfileConnection{
Resolver: r,
ParentID: obj.ID,
}, nil
}
filters := coredata.NewMembershipProfileFilter(nil).WithMembership()
if filter != nil {
filters = coredata.NewMembershipProfileFilter(filter.ContractEnded).WithMembership()
if filter.State != nil {
filters.WithState(*filter.State)
}
}
pageOrderBy := page.OrderBy[coredata.MembershipProfileOrderField]{
Field: coredata.MembershipProfileOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy.Field = coredata.MembershipProfileOrderField(orderBy.Field)
pageOrderBy.Direction = page.OrderDirection(orderBy.Direction)
}
cursor := cursor.NewCursor(first, after, last, before, pageOrderBy)
page, err := r.iam.OrganizationService.ListProfiles(ctx, obj.ID, cursor, filters)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list profiles", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewProfileConnection(page, r, obj.ID, filters), nil
}
// MeasureCategories is the resolver for the measureCategories field.
func (r *organizationResolver) MeasureCategories(ctx context.Context, obj *types.Organization) ([]string, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionMeasureList); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
categories, err := prb.Measures.ListDistinctCategoriesForOrganizationID(ctx, obj.ID)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list measure categories", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return categories, nil
}
// AccessSources is the resolver for the accessSources field.
func (r *organizationResolver) AccessSources(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.AccessSourceOrder) (*types.AccessSourceConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionAccessSourceList); err != nil {
return nil, err
}
scope := coredata.NewScopeFromObjectID(obj.ID)
pageOrderBy := page.OrderBy[coredata.AccessSourceOrderField]{
Field: coredata.AccessSourceOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.AccessSourceOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
p, err := r.accessReview.Sources(scope).ListForOrganizationID(ctx, obj.ID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list access sources: %w", err))
}
return types.NewAccessSourceConnection(p, r, obj.ID), nil
}
// AccessReviewCampaigns is the resolver for the accessReviewCampaigns field.
func (r *organizationResolver) AccessReviewCampaigns(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.AccessReviewCampaignOrder) (*types.AccessReviewCampaignConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionAccessReviewCampaignList); err != nil {
return nil, err
}
scope := coredata.NewScopeFromObjectID(obj.ID)
pageOrderBy := page.OrderBy[coredata.AccessReviewCampaignOrderField]{
Field: coredata.AccessReviewCampaignOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.AccessReviewCampaignOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
p, err := r.accessReview.Campaigns(scope).ListForOrganizationID(ctx, obj.ID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list access review campaigns: %w", err))
}
return types.NewAccessReviewCampaignConnection(p, r, obj.ID), nil
}
// AssetListDocument is the resolver for the assetListDocument field.
func (r *organizationResolver) AssetListDocument(ctx context.Context, obj *types.Organization) (*types.Document, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionDocumentGet); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
assetDocumentID, err := prb.GeneratedDocuments.GetAssetListDocumentID(ctx, obj.ID)
if err != nil {
return nil, fmt.Errorf("cannot get asset list document ID: %w", err)
}
if assetDocumentID == nil {
return nil, nil
}
doc, err := prb.Documents.Get(ctx, *assetDocumentID)
if err != nil {
return nil, fmt.Errorf("cannot get asset list document: %w", err)
}
return types.NewDocument(doc), 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) (*types.AssetConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionAssetList); err != nil {
return nil, err
}
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)
page, err := prb.Assets.ListForOrganizationID(ctx, obj.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization assets", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewAssetConnection(page, r, obj.ID), nil
}
// DataListDocument is the resolver for the dataListDocument field.
func (r *organizationResolver) DataListDocument(ctx context.Context, obj *types.Organization) (*types.Document, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionDocumentGet); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
dataDocumentID, err := prb.GeneratedDocuments.GetDataListDocumentID(ctx, obj.ID)
if err != nil {
return nil, fmt.Errorf("cannot get data export document ID: %w", err)
}
if dataDocumentID == nil {
return nil, nil
}
doc, err := prb.Documents.Get(ctx, *dataDocumentID)
if err != nil {
return nil, fmt.Errorf("cannot get data export document: %w", err)
}
return types.NewDocument(doc), nil
}
// Data is the resolver for the data field.
func (r *organizationResolver) Data(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DatumOrderBy) (*types.DatumConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionDatumList); err != nil {
return nil, err
}
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)
page, err := prb.Data.ListForOrganizationID(ctx, obj.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization data", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewDataConnection(page, r, obj.ID), 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) {
if err := r.authorize(ctx, obj.ID, probo.ActionAuditList); err != nil {
return nil, err
}
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 {
r.logger.ErrorCtx(ctx, "cannot list organization audits", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewAuditConnection(page, r, obj.ID), nil
}
// FindingsDocument is the resolver for the findingsDocument field.
func (r *organizationResolver) FindingsDocument(ctx context.Context, obj *types.Organization) (*types.Document, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionDocumentGet); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
findingDocumentID, err := prb.GeneratedDocuments.GetFindingsDocumentID(ctx, obj.ID)
if err != nil {
return nil, fmt.Errorf("cannot get finding list document ID: %w", err)
}
if findingDocumentID == nil {
return nil, nil
}
doc, err := prb.Documents.Get(ctx, *findingDocumentID)
if err != nil {
return nil, fmt.Errorf("cannot get finding list document: %w", err)
}
return types.NewDocument(doc), nil
}
// Findings is the resolver for the findings field.
func (r *organizationResolver) Findings(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.FindingOrder, filter *types.FindingFilter) (*types.FindingConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionFindingList); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.FindingOrderField]{
Field: coredata.FindingOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.FindingOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
var (
kind *coredata.FindingKind
status *coredata.FindingStatus
priority *coredata.FindingPriority
ownerID *gid.GID
)
if filter != nil {
kind = filter.Kind
status = filter.Status
priority = filter.Priority
ownerID = filter.OwnerID
}
findingFilter := coredata.NewFindingFilter(kind, status, priority, ownerID)
page, err := prb.Findings.ListForOrganizationID(ctx, obj.ID, cursor, findingFilter)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization findings", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewFindingConnection(page, r, obj.ID, filter), nil
}
// AuditLogEntries is the resolver for the auditLogEntries field.
func (r *organizationResolver) AuditLogEntries(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.AuditLogEntryOrderBy, filter *types.AuditLogEntryFilter) (*types.AuditLogEntryConnection, error) {
if err := r.authorize(ctx, obj.ID, iam.ActionAuditLogEntryList); err != nil {
return nil, err
}
pageOrderBy := page.OrderBy[coredata.AuditLogEntryOrderField]{
Field: coredata.AuditLogEntryOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.AuditLogEntryOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
coredataFilter := coredata.NewAuditLogEntryFilter()
if filter != nil {
if filter.Action != nil {
coredataFilter.WithAction(*filter.Action)
}
if filter.ActorID != nil {
coredataFilter.WithActorID(*filter.ActorID)
}
if filter.ResourceType != nil {
coredataFilter.WithResourceType(*filter.ResourceType)
}
if filter.ResourceID != nil {
coredataFilter.WithResourceID(*filter.ResourceID)
}
}
p, err := r.iam.OrganizationService.ListAuditLogEntries(ctx, obj.ID, cursor, coredataFilter)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list audit log entries", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewAuditLogEntryConnection(p, r, obj.ID, coredataFilter), 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) {
if err := r.authorize(ctx, obj.ID, probo.ActionSlackConnectionList); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
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 {
r.logger.ErrorCtx(ctx, "cannot list organization slack connections", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewSlackConnectionConnection(page), nil
}
// SlackOAuth2Scopes is the resolver for the slackOAuth2Scopes field.
func (r *organizationResolver) SlackOAuth2Scopes(ctx context.Context, obj *types.Organization) ([]string, error) {
return slack.OAuth2Scopes, nil
}
// Connectors is the resolver for the connectors field.
func (r *organizationResolver) Connectors(ctx context.Context, obj *types.Organization, filter *types.ConnectorFilter) ([]*types.Connector, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionConnectorList); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
connectors, err := prb.Connectors.ListAllForOrganizationID(ctx, obj.ID)
if err != nil {
panic(fmt.Errorf("cannot list organization connectors: %w", err))
}
if filter != nil && len(filter.Providers) > 0 {
allowed := make(map[coredata.ConnectorProvider]struct{}, len(filter.Providers))
for _, provider := range filter.Providers {
allowed[provider] = struct{}{}
}
filtered := make(coredata.Connectors, 0, len(connectors))
for _, cnnctr := range connectors {
if _, ok := allowed[cnnctr.Provider]; ok {
filtered = append(filtered, cnnctr)
}
}
connectors = filtered
}
return types.NewConnectors(connectors), nil
}
// ConnectorProviderInfos is the resolver for the connectorProviderInfos field.
func (r *organizationResolver) ConnectorProviderInfos(ctx context.Context, obj *types.Organization) ([]*types.ConnectorProviderInfo, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionConnectorList); err != nil {
return nil, err
}
var infos []*types.ConnectorProviderInfo
for _, provider := range coredata.ConnectorProviders() {
_, oauthErr := r.connectorRegistry.Get(string(provider))
scopes := drivers.ProviderOAuth2Scopes(provider)
if scopes == nil {
scopes = []string{}
}
info := &types.ConnectorProviderInfo{
Provider: provider,
DisplayName: providerDisplayName(provider),
OauthConfigured: oauthErr == nil,
APIKeySupported: providerSupportsAPIKey(provider),
ClientCredentialsSupported: providerSupportsClientCredentials(provider),
Oauth2Scopes: scopes,
ExtraSettings: providerExtraSettings(provider),
}
infos = append(infos, info)
}
return infos, 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) {
if err := r.authorize(ctx, obj.ID, probo.ActionControlList); err != nil {
return nil, err
}
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 {
r.logger.ErrorCtx(ctx, "cannot list controls", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewControlConnection(page, r, obj.ID, controlFilter), nil
}
// StatementsOfApplicability is the resolver for the statementsOfApplicability field.
func (r *organizationResolver) StatementsOfApplicability(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.StatementOfApplicabilityOrderBy) (*types.StatementOfApplicabilityConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionStatementOfApplicabilityList); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.StatementOfApplicabilityOrderField]{
Field: coredata.StatementOfApplicabilityOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.StatementOfApplicabilityOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := prb.StatementsOfApplicability.ListForOrganizationID(ctx, obj.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization statements_of_applicability", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewStatementOfApplicabilityConnection(page, r, obj.ID), 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) (*types.DataProtectionImpactAssessmentConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionDataProtectionImpactAssessmentList); err != nil {
return nil, err
}
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)
page, err := prb.DataProtectionImpactAssessments.ListForOrganizationID(ctx, obj.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization data protection impact assessments", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewDataProtectionImpactAssessmentConnection(page, r, obj.ID), nil
}
// DataProtectionImpactAssessmentsDocument is the resolver for the dataProtectionImpactAssessmentsDocument field.
func (r *organizationResolver) DataProtectionImpactAssessmentsDocument(ctx context.Context, obj *types.Organization) (*types.Document, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionDocumentGet); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
documentID, err := prb.GeneratedDocuments.GetDataProtectionImpactAssessmentsDocumentID(ctx, obj.ID)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot get DPIA list document ID", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
if documentID == nil {
return nil, nil
}
document, err := prb.Documents.Get(ctx, *documentID)
if err != nil {
if errors.Is(err, coredata.ErrResourceNotFound) {
return nil, nil
}
r.logger.ErrorCtx(ctx, "cannot load DPIA list document", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewDocument(document), 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) (*types.TransferImpactAssessmentConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionTransferImpactAssessmentList); err != nil {
return nil, err
}
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)
page, err := prb.TransferImpactAssessments.ListForOrganizationID(ctx, obj.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization transfer impact assessments", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewTransferImpactAssessmentConnection(page, r, obj.ID), nil
}
// TransferImpactAssessmentsDocument is the resolver for the transferImpactAssessmentsDocument field.
func (r *organizationResolver) TransferImpactAssessmentsDocument(ctx context.Context, obj *types.Organization) (*types.Document, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionDocumentGet); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
documentID, err := prb.GeneratedDocuments.GetTransferImpactAssessmentsDocumentID(ctx, obj.ID)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot get TIA list document ID", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
if documentID == nil {
return nil, nil
}
document, err := prb.Documents.Get(ctx, *documentID)
if err != nil {
if errors.Is(err, coredata.ErrResourceNotFound) {
return nil, nil
}
r.logger.ErrorCtx(ctx, "cannot load TIA list document", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewDocument(document), 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) {
if err := r.authorize(ctx, obj.ID, probo.ActionDocumentList); err != nil {
return nil, err
}
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).
WithWriteModes(filter.WriteModes).
WithDocumentTypes(filter.DocumentTypes).
WithClassifications(filter.Classifications).
WithStatus(filter.Status)
}
page, err := prb.Documents.ListByOrganizationID(ctx, obj.ID, cursor, documentFilter)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization documents", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewDocumentConnection(page, r, obj.ID, documentFilter), nil
}
// Evidences is the resolver for the evidences field.
func (r *organizationResolver) Evidences(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.EvidenceOrderBy) (*types.EvidenceConnection, error) {
panic(fmt.Errorf("not implemented: Evidences - evidences"))
}
// 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) {
if err := r.authorize(ctx, obj.ID, probo.ActionFrameworkList); err != nil {
return nil, err
}
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 {
r.logger.ErrorCtx(ctx, "cannot list organization frameworks", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewFrameworkConnection(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) {
if err := r.authorize(ctx, obj.ID, probo.ActionMeasureList); err != nil {
return nil, err
}
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, nil)
if filter != nil {
measureFilter = coredata.NewMeasureFilter(filter.Query, filter.State, filter.Category)
}
page, err := prb.Measures.ListForOrganizationID(ctx, obj.ID, cursor, measureFilter)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization measures", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewMeasureConnection(page, r, obj.ID, measureFilter), nil
}
// ObligationsDocument is the resolver for the obligationsDocument field.
func (r *organizationResolver) ObligationsDocument(ctx context.Context, obj *types.Organization) (*types.Document, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionDocumentGet); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
obligationDocumentID, err := prb.GeneratedDocuments.GetObligationsDocumentID(ctx, obj.ID)
if err != nil {
return nil, fmt.Errorf("cannot get obligation list document ID: %w", err)
}
if obligationDocumentID == nil {
return nil, nil
}
doc, err := prb.Documents.Get(ctx, *obligationDocumentID)
if err != nil {
return nil, fmt.Errorf("cannot get obligation list document: %w", err)
}
return types.NewDocument(doc), 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) (*types.ObligationConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionObligationList); err != nil {
return nil, err
}
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)
page, err := prb.Obligations.ListForOrganizationID(ctx, obj.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization obligations", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewObligationConnection(page, r, obj.ID), 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) (*types.ProcessingActivityConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionProcessingActivityList); err != nil {
return nil, err
}
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)
page, err := prb.ProcessingActivities.ListForOrganizationID(ctx, obj.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization processing activities", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewProcessingActivityConnection(page, r, obj.ID), nil
}
// ProcessingActivitiesDocument is the resolver for the processingActivitiesDocument field.
func (r *organizationResolver) ProcessingActivitiesDocument(ctx context.Context, obj *types.Organization) (*types.Document, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionDocumentGet); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
documentID, err := prb.GeneratedDocuments.GetProcessingActivitiesDocumentID(ctx, obj.ID)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot get processing activities document ID", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
if documentID == nil {
return nil, nil
}
document, err := prb.Documents.Get(ctx, *documentID)
if err != nil {
if errors.Is(err, coredata.ErrResourceNotFound) {
return nil, nil
}
r.logger.ErrorCtx(ctx, "cannot load processing activities document", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewDocument(document), nil
}
// RightsRequests is the resolver for the rightsRequests field.
func (r *organizationResolver) RightsRequests(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.RightsRequestOrderBy) (*types.RightsRequestConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionRightsRequestList); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.RightsRequestOrderField]{
Field: coredata.RightsRequestOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.RightsRequestOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := prb.RightsRequests.ListForOrganizationID(ctx, obj.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization rights requests", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewRightsRequestConnection(page, r, obj.ID), 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) {
if err := r.authorize(ctx, obj.ID, probo.ActionRiskList); err != nil {
return nil, err
}
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)
if filter != nil {
riskFilter = coredata.NewRiskFilter(filter.Query)
}
page, err := prb.Risks.ListForOrganizationID(ctx, obj.ID, cursor, riskFilter)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization risks", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewRiskConnection(page, r, obj.ID, riskFilter), nil
}
// RisksDocument is the resolver for the risksDocument field.
func (r *organizationResolver) RisksDocument(ctx context.Context, obj *types.Organization) (*types.Document, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionDocumentGet); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
documentID, err := prb.GeneratedDocuments.GetRisksDocumentID(ctx, obj.ID)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot get risks document ID", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
if documentID == nil {
return nil, nil
}
document, err := prb.Documents.Get(ctx, *documentID)
if err != nil {
if errors.Is(err, coredata.ErrResourceNotFound) {
return nil, nil
}
r.logger.ErrorCtx(ctx, "cannot load risks document", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewDocument(document), nil
}
// RiskAssessments is the resolver for the riskAssessments field.
func (r *organizationResolver) RiskAssessments(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.RiskAssessmentOrderBy) (*types.RiskAssessmentConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionRiskAssessmentList); err != nil {
return nil, err
}
scope := coredata.NewScopeFromObjectID(obj.ID)
pageOrderBy := page.OrderBy[coredata.RiskAssessmentOrderField]{
Field: coredata.RiskAssessmentOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.RiskAssessmentOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
p, err := r.riskManagement.ListForOrganizationID(ctx, scope, obj.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list risk assessments", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewRiskAssessmentConnection(p, r, obj.ID), nil
}
// RiskAssessmentScenarios is the resolver for the riskAssessmentScenarios field.
func (r *organizationResolver) RiskAssessmentScenarios(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.RiskAssessmentScenarioOrderBy) (*types.RiskAssessmentScenarioConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionRiskAssessmentScenarioList); err != nil {
return nil, err
}
scope := coredata.NewScopeFromObjectID(obj.ID)
pageOrderBy := page.OrderBy[coredata.RiskAssessmentScenarioOrderField]{
Field: coredata.RiskAssessmentScenarioOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.RiskAssessmentScenarioOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
p, err := r.riskManagement.ListScenariosForOrganizationID(ctx, scope, obj.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list risk scenarios", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewRiskAssessmentScenarioConnection(p, r, obj.ID), 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) {
if err := r.authorize(ctx, obj.ID, probo.ActionTaskList); err != nil {
return nil, err
}
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 {
r.logger.ErrorCtx(ctx, "cannot list organization tasks", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewTaskConnection(page, r, obj.ID), nil
}
// TrustCenter is the resolver for the trustCenter field.
func (r *organizationResolver) TrustCenter(ctx context.Context, obj *types.Organization) (*types.TrustCenter, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionTrustCenterGet); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
trustCenter, err := prb.TrustCenters.GetByOrganizationID(ctx, obj.ID)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot get trust center", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
var file *coredata.File
if trustCenter.NonDisclosureAgreementFileID != nil {
file, err = prb.Files.Get(ctx, *trustCenter.NonDisclosureAgreementFileID)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot get NDA file", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
}
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) {
if err := r.authorize(ctx, obj.ID, probo.ActionCustomDomainGet); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
domain, err := prb.CustomDomains.GetOrganizationCustomDomain(ctx, obj.ID)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot get custom domain", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
if domain == nil {
return nil, nil
}
return types.NewCustomDomain(domain, r.customDomainCname), 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) {
if err := r.authorize(ctx, obj.ID, probo.ActionTrustCenterFileList); err != nil {
return nil, err
}
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, &coredata.TrustCenterFileFilter{})
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization trust center files", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewTrustCenterFileConnection(pageResult, obj.ID), nil
}
// CookieBanners is the resolver for the cookieBanners field.
func (r *organizationResolver) CookieBanners(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.CookieBannerOrderBy) (*types.CookieBannerConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionCookieBannerList); err != nil {
return nil, err
}
pageOrderBy := page.OrderBy[coredata.CookieBannerOrderField]{
Field: coredata.CookieBannerOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.CookieBannerOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
scope := coredata.NewScopeFromObjectID(obj.ID)
banners, err := r.cookieBanner.ListCookieBannersForOrganization(ctx, scope, obj.ID, cursor, coredata.NewCookieBannerFilter(nil))
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list cookie banners", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
p := page.NewPage(banners, cursor)
return types.NewCookieBannerConnection(p, r, obj.ID), nil
}
// ThirdParties is the resolver for the thirdParties field.
func (r *organizationResolver) ThirdParties(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ThirdPartyOrderBy) (*types.ThirdPartyConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionThirdPartyList); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.ThirdPartyOrderField]{
Field: coredata.ThirdPartyOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.ThirdPartyOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
thirdPartyFilter := coredata.NewThirdPartyFilter(nil)
page, err := prb.ThirdParties.ListForOrganizationID(ctx, obj.ID, cursor, thirdPartyFilter)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization thirdParties", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewThirdPartyConnection(page, r, obj.ID), nil
}
// ThirdPartiesDocument is the resolver for the thirdPartiesDocument field.
func (r *organizationResolver) ThirdPartiesDocument(ctx context.Context, obj *types.Organization) (*types.Document, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionDocumentGet); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
documentID, err := prb.GeneratedDocuments.GetThirdPartiesDocumentID(ctx, obj.ID)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot get thirdParties document ID", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
if documentID == nil {
return nil, nil
}
document, err := prb.Documents.Get(ctx, *documentID)
if err != nil {
if errors.Is(err, coredata.ErrResourceNotFound) {
return nil, nil
}
r.logger.ErrorCtx(ctx, "cannot load thirdParties document", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewDocument(document), nil
}
// WebhookSubscriptions is the resolver for the webhookSubscriptions field.
func (r *organizationResolver) WebhookSubscriptions(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.WebhookSubscriptionOrderBy) (*types.WebhookSubscriptionConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionWebhookSubscriptionList); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.WebhookSubscriptionOrderField]{
Field: coredata.WebhookSubscriptionOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.WebhookSubscriptionOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := prb.WebhookSubscriptions.ListForOrganizationID(ctx, obj.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization webhook subscriptions", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewWebhookSubscriptionConnection(page, r, obj.ID), nil
}
// Permission is the resolver for the permission field.
func (r *organizationResolver) Permission(ctx context.Context, obj *types.Organization, action string) (bool, error) {
return r.Resolver.Permission(ctx, obj, action)
}
// Permission is the resolver for the permission field.
func (r *profileResolver) Permission(ctx context.Context, obj *types.Profile, action string) (bool, error) {
return r.Resolver.Permission(ctx, obj, action)
}
// TotalCount is the resolver for the totalCount field.
func (r *profileConnectionResolver) TotalCount(ctx context.Context, obj *types.ProfileConnection) (int, error) {
if err := r.authorize(ctx, obj.ParentID, iam.ActionMembershipProfileList); err != nil {
return 0, err
}
switch obj.Resolver.(type) {
case *organizationResolver:
count, err := r.iam.OrganizationService.CountProfiles(ctx, obj.ParentID, obj.Filters)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot count profiles", log.Error(err))
return 0, gqlutils.Internal(ctx)
}
return count, nil
case *documentVersionResolver:
prb := r.ProboService(ctx, obj.ParentID.TenantID())
count, err := prb.Documents.CountVersionApprovers(ctx, obj.ParentID)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot count document version approvers", log.Error(err))
return 0, gqlutils.Internal(ctx)
}
return count, nil
}
r.logger.ErrorCtx(ctx, "unsupported resolver for profile connection", log.String("resolver", fmt.Sprintf("%T", obj.Resolver)))
return 0, gqlutils.Internal(ctx)
}
// Organization returns schema.OrganizationResolver implementation.
func (r *Resolver) Organization() schema.OrganizationResolver { return &organizationResolver{r} }
// Profile returns schema.ProfileResolver implementation.
func (r *Resolver) Profile() schema.ProfileResolver { return &profileResolver{r} }
// ProfileConnection returns schema.ProfileConnectionResolver implementation.
func (r *Resolver) ProfileConnection() schema.ProfileConnectionResolver {
return &profileConnectionResolver{r}
}
type organizationResolver struct{ *Resolver }
type profileResolver struct{ *Resolver }
type profileConnectionResolver struct{ *Resolver }