Decouple each campaign from the live access-review sources it was started with by introducing a per-campaign source snapshot table (access_review_campaign_sources). The snapshot captures the source name, category, and connector at start time, so a review remains coherent even after the underlying source is edited or deleted. Fetch tracking becomes an append-only log (access_review_campaign_source_fetch_attempts) that preserves every attempt with its own status and error rather than overwriting a single row. Rename the shared access-review tables and enums to use a consistent access_review_ prefix throughout: access_entries → access_review_entries access_sources → access_review_sources access_source_category → access_review_source_category access_entry_* → access_review_entry_* The same rename propagates to every coredata type, service, GraphQL schema, MCP specification, CLI command, frontend component, and e2e test. The accessreview package gains dedicated actions.go and policies.go files for its own IAM policy set, mirroring the agentrun package pattern. Signed-off-by: Bryan Frimin <bryan@probo.com>
1414 lines
48 KiB
Go
1414 lines
48 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"
|
|
|
|
"go.gearno.de/kit/log"
|
|
"go.probo.inc/probo/pkg/accessreview"
|
|
"go.probo.inc/probo/pkg/agentrun"
|
|
"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) {
|
|
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 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) {
|
|
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
|
|
}
|
|
|
|
// TrustCenter is the resolver for the trustCenter field.
|
|
func (r *organizationResolver) TrustCenter(ctx context.Context, obj *types.Organization) (*types.TrustCenter, error) {
|
|
scope, err := r.authorize(ctx, obj.ID, probo.ActionTrustCenterGet)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
trustCenter, err := r.probo.TrustCenters.GetByOrganizationID(ctx, scope, obj.ID)
|
|
if err != nil {
|
|
r.logger.ErrorCtx(ctx, "cannot get trust center", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
return types.NewTrustCenter(trustCenter), nil
|
|
}
|
|
|
|
// CustomDomain is the resolver for the customDomain field.
|
|
func (r *organizationResolver) CustomDomain(ctx context.Context, obj *types.Organization) (*types.CustomDomain, error) {
|
|
scope, err := r.authorize(ctx, obj.ID, probo.ActionCustomDomainGet)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
domain, err := r.probo.CustomDomains.GetOrganizationCustomDomain(ctx, scope, 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) {
|
|
scope, err := r.authorize(ctx, obj.ID, probo.ActionTrustCenterFileList)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
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 := r.probo.TrustCenterFiles.ListForOrganizationID(ctx, scope, 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) {
|
|
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)
|
|
|
|
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
|
|
}
|
|
|
|
// 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 }
|
|
type profileResolver struct{ *Resolver }
|
|
type profileConnectionResolver struct{ *Resolver }
|