Files
probo/pkg/server/api/console/v1/organization_resolvers.go
Émile Ré 4a276e3ef7 Split inactive profile state
Replace the binary profile ACTIVE/INACTIVE model with PENDING, ACTIVE,
and DEACTIVATED so invited-but-not-yet-activated members remain
assignable to assets, data, and risks instead of being treated like
deactivated users.

Add activated_at/deactivated_at timestamps and Mark* lifecycle helpers,
and update every transition (create, invite/re-invite, activation,
archive, SCIM, SAML, sessions, compliance-portal grant) to the new
states. Expose a multi-state states[] filter across coredata, GraphQL,
MCP, and the console owner pickers, which now request ACTIVE and
PENDING members.

A migration renames the membership_state enum, classifies existing
inactive profiles as PENDING from recent invitation activity, and
backfills the new timestamp columns.

Signed-off-by: Émile Ré <emile@probo.com>
2026-07-30 09:19:42 +02:00

1444 lines
49 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.94
import (
"context"
"errors"
"fmt"
"go.gearno.de/kit/log"
"go.probo.inc/probo/pkg/accessreview"
"go.probo.inc/probo/pkg/agentrun"
"go.probo.inc/probo/pkg/complianceportal/management"
"go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/iam"
"go.probo.inc/probo/pkg/itam"
"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) {
scope, err := r.authorize(ctx, input.OrganizationID, probo.ActionOrganizationContextUpdate)
if err != nil {
return nil, err
}
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 := r.probo.Organizations.UpdateContext(ctx, scope, 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
}
// Logo is the resolver for the logo field.
func (r *organizationResolver) Logo(ctx context.Context, obj *types.Organization) (*types.File, error) {
if _, err := r.authorize(ctx, obj.ID, probo.ActionOrganizationGetLogoUrl); err != nil {
return nil, err
}
if obj.Logo == nil {
return nil, nil
}
return r.loadFile(ctx, obj.Logo.ID)
}
// HorizontalLogo is the resolver for the horizontalLogo field.
func (r *organizationResolver) HorizontalLogo(ctx context.Context, obj *types.Organization) (*types.File, error) {
if _, err := r.authorize(ctx, obj.ID, probo.ActionOrganizationGetHorizontalLogoUrl); err != nil {
return nil, err
}
if obj.HorizontalLogo == nil {
return nil, nil
}
return r.loadFile(ctx, obj.HorizontalLogo.ID)
}
// Context is the resolver for the context field.
func (r *organizationResolver) Context(ctx context.Context, obj *types.Organization) (*types.OrganizationContext, error) {
scope, err := r.authorize(ctx, obj.ID, probo.ActionOrganizationContextGet)
if err != nil {
return nil, err
}
orgContext, err := r.probo.Organizations.GetContext(ctx, scope, 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 len(filter.States) > 0 {
filters.WithStates(filter.States...)
}
if filter.State != nil {
filters.WithState(*filter.State)
}
if filter.Query != nil {
filters.WithQuery(filter.Query)
}
if filter.Role != nil {
filters.WithRole(*filter.Role)
}
if filter.Kind != nil {
filters.WithKind(filter.Kind)
}
}
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) {
scope, err := r.authorize(ctx, obj.ID, probo.ActionMeasureList)
if err != nil {
return nil, err
}
categories, err := r.probo.Measures.ListDistinctCategoriesForOrganizationID(ctx, scope, obj.ID)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list measure categories", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return categories, nil
}
// AccessReviewSources is the resolver for the accessSources field.
func (r *organizationResolver) AccessReviewSources(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.AccessReviewSourceOrder) (*types.AccessReviewSourceConnection, error) {
scope, err := r.authorize(ctx, obj.ID, accessreview.ActionSourceList)
if err != nil {
return nil, err
}
pageOrderBy := page.OrderBy[coredata.AccessReviewSourceOrderField]{
Field: coredata.AccessReviewSourceOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.AccessReviewSourceOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
p, err := r.accessReview.ListSourcesForOrganizationID(ctx, scope, obj.ID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list access sources: %w", err))
}
return types.NewAccessReviewSourceConnection(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) {
scope, err := r.authorize(ctx, obj.ID, accessreview.ActionCampaignList)
if err != nil {
return nil, err
}
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.ListCampaignsForOrganizationID(ctx, scope, 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) {
scope, err := r.authorize(ctx, obj.ID, probo.ActionDocumentGet)
if err != nil {
return nil, err
}
assetDocumentID, err := r.probo.GeneratedDocuments.GetAssetListDocumentID(ctx, scope, 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 := r.probo.Documents.Get(ctx, scope, *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) {
scope, err := r.authorize(ctx, obj.ID, probo.ActionAssetList)
if err != nil {
return nil, err
}
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 := r.probo.Assets.ListForOrganizationID(ctx, scope, 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) {
scope, err := r.authorize(ctx, obj.ID, probo.ActionDocumentGet)
if err != nil {
return nil, err
}
dataDocumentID, err := r.probo.GeneratedDocuments.GetDataListDocumentID(ctx, scope, 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 := r.probo.Documents.Get(ctx, scope, *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) {
scope, err := r.authorize(ctx, obj.ID, probo.ActionDatumList)
if err != nil {
return nil, err
}
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 := r.probo.Data.ListForOrganizationID(ctx, scope, 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) {
scope, err := r.authorize(ctx, obj.ID, probo.ActionAuditList)
if err != nil {
return nil, err
}
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 := r.probo.Audits.ListForOrganizationID(ctx, scope, 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) {
scope, err := r.authorize(ctx, obj.ID, probo.ActionDocumentGet)
if err != nil {
return nil, err
}
findingDocumentID, err := r.probo.GeneratedDocuments.GetFindingsDocumentID(ctx, scope, 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 := r.probo.Documents.Get(ctx, scope, *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) {
scope, err := r.authorize(ctx, obj.ID, probo.ActionFindingList)
if err != nil {
return nil, err
}
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 := r.probo.Findings.ListForOrganizationID(ctx, scope, 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) {
scope, err := r.authorize(ctx, obj.ID, probo.ActionSlackConnectionList)
if err != nil {
return nil, err
}
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 := r.probo.Connectors.ListForOrganizationID(ctx, scope, 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) {
scope, err := r.authorize(ctx, obj.ID, probo.ActionConnectorList)
if err != nil {
return nil, err
}
connectors, err := r.probo.Connectors.ListAllForOrganizationID(ctx, scope, 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
}
// 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) {
scope, err := r.authorize(ctx, obj.ID, probo.ActionControlList)
if err != nil {
return nil, err
}
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 := r.probo.Controls.ListForOrganizationID(ctx, scope, 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) {
scope, err := r.authorize(ctx, obj.ID, probo.ActionStatementOfApplicabilityList)
if err != nil {
return nil, err
}
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 := r.probo.StatementsOfApplicability.ListForOrganizationID(ctx, scope, 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) {
scope, err := r.authorize(ctx, obj.ID, probo.ActionDataProtectionImpactAssessmentList)
if err != nil {
return nil, err
}
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 := r.probo.DataProtectionImpactAssessments.ListForOrganizationID(ctx, scope, 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) {
scope, err := r.authorize(ctx, obj.ID, probo.ActionDocumentGet)
if err != nil {
return nil, err
}
documentID, err := r.probo.GeneratedDocuments.GetDataProtectionImpactAssessmentsDocumentID(ctx, scope, 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 := r.probo.Documents.Get(ctx, scope, *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) {
scope, err := r.authorize(ctx, obj.ID, probo.ActionTransferImpactAssessmentList)
if err != nil {
return nil, err
}
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 := r.probo.TransferImpactAssessments.ListForOrganizationID(ctx, scope, 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) {
scope, err := r.authorize(ctx, obj.ID, probo.ActionDocumentGet)
if err != nil {
return nil, err
}
documentID, err := r.probo.GeneratedDocuments.GetTransferImpactAssessmentsDocumentID(ctx, scope, 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 := r.probo.Documents.Get(ctx, scope, *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) {
scope, err := r.authorize(ctx, obj.ID, probo.ActionDocumentList)
if err != nil {
return nil, err
}
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 := r.probo.Documents.ListByOrganizationID(ctx, scope, 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
}
// 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) {
scope, err := r.authorize(ctx, obj.ID, probo.ActionFrameworkList)
if err != nil {
return nil, err
}
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 := r.probo.Frameworks.ListForOrganizationID(ctx, scope, 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) {
scope, err := r.authorize(ctx, obj.ID, probo.ActionMeasureList)
if err != nil {
return nil, err
}
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 := r.probo.Measures.ListForOrganizationID(ctx, scope, 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) {
scope, err := r.authorize(ctx, obj.ID, probo.ActionDocumentGet)
if err != nil {
return nil, err
}
obligationDocumentID, err := r.probo.GeneratedDocuments.GetObligationsDocumentID(ctx, scope, 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 := r.probo.Documents.Get(ctx, scope, *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) {
scope, err := r.authorize(ctx, obj.ID, probo.ActionObligationList)
if err != nil {
return nil, err
}
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 := r.probo.Obligations.ListForOrganizationID(ctx, scope, 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) {
scope, err := r.authorize(ctx, obj.ID, probo.ActionProcessingActivityList)
if err != nil {
return nil, err
}
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 := r.probo.ProcessingActivities.ListForOrganizationID(ctx, scope, 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) {
scope, err := r.authorize(ctx, obj.ID, probo.ActionDocumentGet)
if err != nil {
return nil, err
}
documentID, err := r.probo.GeneratedDocuments.GetProcessingActivitiesDocumentID(ctx, scope, 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 := r.probo.Documents.Get(ctx, scope, *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) {
scope, err := r.authorize(ctx, obj.ID, probo.ActionRightsRequestList)
if err != nil {
return nil, err
}
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 := r.probo.RightsRequests.ListForOrganizationID(ctx, scope, 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) {
scope, err := r.authorize(ctx, obj.ID, probo.ActionRiskList)
if err != nil {
return nil, err
}
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 := r.probo.Risks.ListForOrganizationID(ctx, scope, 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) {
scope, err := r.authorize(ctx, obj.ID, probo.ActionDocumentGet)
if err != nil {
return nil, err
}
documentID, err := r.probo.GeneratedDocuments.GetRisksDocumentID(ctx, scope, 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 := r.probo.Documents.Get(ctx, scope, *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) {
scope, err := r.authorize(ctx, obj.ID, probo.ActionRiskAssessmentList)
if err != nil {
return nil, err
}
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) {
scope, err := r.authorize(ctx, obj.ID, probo.ActionRiskAssessmentScenarioList)
if err != nil {
return nil, err
}
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) {
scope, err := r.authorize(ctx, obj.ID, probo.ActionTaskList)
if err != nil {
return nil, err
}
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 := r.probo.Tasks.ListForOrganizationID(ctx, scope, 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
}
// AgentRuns is the resolver for the agentRuns field.
func (r *organizationResolver) AgentRuns(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.AgentRunOrderBy) (*types.AgentRunConnection, error) {
scope, err := r.authorize(ctx, obj.ID, agentrun.ActionAgentRunList)
if err != nil {
return nil, err
}
pageOrderBy := page.OrderBy[coredata.AgentRunOrderField]{
Field: coredata.AgentRunOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.AgentRunOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := r.agentRun.ListForOrganizationID(ctx, scope, obj.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization agent runs", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewAgentRunConnection(page, r, obj.ID), nil
}
// CompliancePortal is the resolver for the compliancePortal field.
func (r *organizationResolver) CompliancePortal(ctx context.Context, obj *types.Organization) (*types.CompliancePortal, error) {
scope, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalGet)
if err != nil {
return nil, err
}
compliancePortal, err := r.management.GetByOrganizationID(ctx, scope, obj.ID)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot get compliance portal", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewCompliancePortal(compliancePortal), nil
}
// CompliancePortalFiles is the resolver for the compliancePortalFiles field.
func (r *organizationResolver) CompliancePortalFiles(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrderBy[coredata.CompliancePortalFileOrderField]) (*types.CompliancePortalFileConnection, error) {
scope, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalFileList)
if err != nil {
return nil, err
}
pageOrderBy := page.OrderBy[coredata.CompliancePortalFileOrderField]{
Field: coredata.CompliancePortalFileOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.CompliancePortalFileOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
pageResult, err := r.management.ListFilesForOrganizationID(ctx, scope, obj.ID, cursor, &coredata.CompliancePortalFileFilter{})
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization compliance portal files", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewCompliancePortalFileConnection(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) {
scope, err := r.authorize(ctx, obj.ID, probo.ActionCookieBannerList)
if 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)
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, filter *types.ThirdPartyFilter) (*types.ThirdPartyConnection, error) {
scope, err := r.authorize(ctx, obj.ID, probo.ActionThirdPartyList)
if err != nil {
return nil, err
}
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)
var (
level *int
query *string
)
if filter != nil {
level = filter.Level
query = filter.Query
}
thirdPartyFilter := coredata.NewThirdPartyFilter(nil, level, query, nil, nil)
page, err := r.probo.ThirdParties.ListForOrganizationID(ctx, scope, 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, thirdPartyFilter), nil
}
// ThirdPartiesDocument is the resolver for the thirdPartiesDocument field.
func (r *organizationResolver) ThirdPartiesDocument(ctx context.Context, obj *types.Organization) (*types.Document, error) {
scope, err := r.authorize(ctx, obj.ID, probo.ActionDocumentGet)
if err != nil {
return nil, err
}
documentID, err := r.probo.GeneratedDocuments.GetThirdPartiesDocumentID(ctx, scope, 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 := r.probo.Documents.Get(ctx, scope, *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
}
// Devices is the resolver for the devices field.
func (r *organizationResolver) Devices(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DeviceOrderBy) (*types.DeviceConnection, error) {
scope, err := r.authorize(ctx, obj.ID, itam.ActionDeviceList)
if err != nil {
return nil, err
}
pageOrderBy := page.OrderBy[coredata.DeviceOrderField]{
Field: coredata.DeviceOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.DeviceOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
devicesPage, err := r.itam.ListForOrganizationID(ctx, scope, obj.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization devices", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewDeviceConnection(devicesPage, r, obj.ID), 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) {
scope, err := r.authorize(ctx, obj.ID, probo.ActionWebhookSubscriptionList)
if err != nil {
return nil, err
}
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 := r.probo.WebhookSubscriptions.ListForOrganizationID(ctx, scope, 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) {
scope, err := r.authorize(ctx, obj.ParentID, iam.ActionMembershipProfileList)
if 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:
count, err := r.probo.Documents.CountVersionApprovers(ctx, scope, 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 }
profileResolver struct{ *Resolver }
profileConnectionResolver struct{ *Resolver }
)