From 3f6795001a821d274fc5e404836171f205c5ad0b Mon Sep 17 00:00:00 2001 From: Bryan Frimin Date: Mon, 20 Jul 2026 22:48:38 +0200 Subject: [PATCH] Finish compliance portal rename leftovers across portal, trust, and n8n. Update mailing list queries to currentCompliancePortal, and include regenerated console resolvers plus sorted n8n/frontend imports from the rename. Signed-off-by: Bryan Frimin --- .../mailingList/SubscribeDialogProvider.tsx | 10 +- .../mailingList/useSubscribeToMailingList.ts | 4 +- apps/compliance-portal/src/pages/HomePage.tsx | 2 +- .../src/pages/documents/DocumentsPage.tsx | 2 +- apps/trust/src/pages/DocumentPage.tsx | 4 +- apps/trust/src/pages/DocumentsPage.tsx | 2 +- apps/trust/src/pages/OverviewPage.tsx | 2 +- apps/trust/src/routes.tsx | 2 +- packages/n8n-node/nodes/Probo/Probo.node.ts | 10 +- .../actions/document/update.operation.ts | 24 +- .../console/v1/compliance_portal_resolvers.go | 1298 ++++++++--------- 11 files changed, 679 insertions(+), 681 deletions(-) diff --git a/apps/compliance-portal/src/lib/mailingList/SubscribeDialogProvider.tsx b/apps/compliance-portal/src/lib/mailingList/SubscribeDialogProvider.tsx index 19e0b4754..b90214f88 100644 --- a/apps/compliance-portal/src/lib/mailingList/SubscribeDialogProvider.tsx +++ b/apps/compliance-portal/src/lib/mailingList/SubscribeDialogProvider.tsx @@ -43,11 +43,9 @@ export const subscribeDialogProviderFragment = graphql` viewer { email } - currentTrustCenter @required(action: THROW) { + currentCompliancePortal @required(action: THROW) { id - organization { - name - } + title viewerSubscription { id } @@ -73,7 +71,7 @@ export function SubscribeDialogProvider({ const [unsubscribeFromMailingList, isUnsubscribing] = useUnsubscribeFromMailingList(); const viewer = data.viewer; - const { id: trustCenterId, organization, viewerSubscription } = data.currentTrustCenter; + const { id: trustCenterId, title, viewerSubscription } = data.currentCompliancePortal; const isSubscribed = viewerSubscription != null; const openSubscribe = useCallback(() => { @@ -129,7 +127,7 @@ export function SubscribeDialogProvider({ onOpenChange={setDialogOpen} trustCenterId={trustCenterId} viewerEmail={viewer.email} - organizationName={organization.name} + organizationName={title} /> )} diff --git a/apps/compliance-portal/src/lib/mailingList/useSubscribeToMailingList.ts b/apps/compliance-portal/src/lib/mailingList/useSubscribeToMailingList.ts index c9e175151..23e2f6013 100644 --- a/apps/compliance-portal/src/lib/mailingList/useSubscribeToMailingList.ts +++ b/apps/compliance-portal/src/lib/mailingList/useSubscribeToMailingList.ts @@ -36,8 +36,8 @@ const subscribeToMailingListMutation = graphql` } `; -// Subscribes the authenticated viewer to the trust center mailing list and -// links the new subscriber onto currentTrustCenter.viewerSubscription. +// Subscribes the authenticated viewer to the compliance portal mailing list and +// links the new subscriber onto currentCompliancePortal.viewerSubscription. export function useSubscribeToMailingList(trustCenterId: string) { const { t } = useTranslation("updates"); const [commit, isSubscribing] = useMutation( diff --git a/apps/compliance-portal/src/pages/HomePage.tsx b/apps/compliance-portal/src/pages/HomePage.tsx index 7119fc721..9e683a7e9 100644 --- a/apps/compliance-portal/src/pages/HomePage.tsx +++ b/apps/compliance-portal/src/pages/HomePage.tsx @@ -23,8 +23,8 @@ import type { PreloadedQuery } from "react-relay"; import { graphql, usePreloadedQuery } from "react-relay"; import { ComplianceFrameworksSection } from "#/components/ComplianceFrameworks/ComplianceFrameworksSection"; -import { Hero } from "#/components/Hero/Hero"; import { CompliancePortalContactInfo } from "#/components/Hero/CompliancePortalContactInfo"; +import { Hero } from "#/components/Hero/Hero"; import { RecentUpdatesSection } from "#/components/RecentUpdates/RecentUpdatesSection"; import { SecurityCommitmentsSection } from "#/components/SecurityCommitments/SecurityCommitmentsSection"; import { TrustedBySection } from "#/components/TrustedBy/TrustedBySection"; diff --git a/apps/compliance-portal/src/pages/documents/DocumentsPage.tsx b/apps/compliance-portal/src/pages/documents/DocumentsPage.tsx index 891a3cf9a..a68f9d6de 100644 --- a/apps/compliance-portal/src/pages/documents/DocumentsPage.tsx +++ b/apps/compliance-portal/src/pages/documents/DocumentsPage.tsx @@ -31,11 +31,11 @@ import type { DocumentsPage_query$key } from "./__generated__/DocumentsPage_quer import type { DocumentsPageQuery } from "./__generated__/DocumentsPageQuery.graphql"; import type { DocumentsPageRefetchQuery } from "./__generated__/DocumentsPageRefetchQuery.graphql"; import { AuditReportListItem } from "./_components/AuditReportListItem"; +import { CompliancePortalFileListItem } from "./_components/CompliancePortalFileListItem"; import { DocumentListItem } from "./_components/DocumentListItem"; import { DocumentSection } from "./_components/DocumentSection"; import { DocumentsEmpty } from "./_components/DocumentsEmpty"; import { DocumentsToolbar } from "./_components/DocumentsToolbar"; -import { CompliancePortalFileListItem } from "./_components/CompliancePortalFileListItem"; import { toQueryVariables } from "./_lib/toQueryVariables"; import { useDocumentTab } from "./_lib/useDocumentTab"; import { documentsLayout } from "./variants"; diff --git a/apps/trust/src/pages/DocumentPage.tsx b/apps/trust/src/pages/DocumentPage.tsx index f0e702760..e1b57c582 100644 --- a/apps/trust/src/pages/DocumentPage.tsx +++ b/apps/trust/src/pages/DocumentPage.tsx @@ -41,13 +41,13 @@ import { graphql } from "relay-runtime"; import { PDFPreview } from "#/components/PDFPreview"; +import type { DocumentPageExportCompliancePortalFileMutation } from "./__generated__/DocumentPageExportCompliancePortalFileMutation.graphql"; import type { DocumentPageExportDocumentMutation } from "./__generated__/DocumentPageExportDocumentMutation.graphql"; import type { DocumentPageExportReportMutation } from "./__generated__/DocumentPageExportReportMutation.graphql"; -import type { DocumentPageExportCompliancePortalFileMutation } from "./__generated__/DocumentPageExportCompliancePortalFileMutation.graphql"; import type { DocumentPageQuery as DocumentPageQueryType } from "./__generated__/DocumentPageQuery.graphql"; +import type { DocumentPageRequestCompliancePortalFileAccessMutation } from "./__generated__/DocumentPageRequestCompliancePortalFileAccessMutation.graphql"; import type { DocumentPageRequestDocumentAccessMutation } from "./__generated__/DocumentPageRequestDocumentAccessMutation.graphql"; import type { DocumentPageRequestReportAccessMutation } from "./__generated__/DocumentPageRequestReportAccessMutation.graphql"; -import type { DocumentPageRequestCompliancePortalFileAccessMutation } from "./__generated__/DocumentPageRequestCompliancePortalFileAccessMutation.graphql"; export const documentPageQuery = graphql` query DocumentPageQuery($alias: String!) { diff --git a/apps/trust/src/pages/DocumentsPage.tsx b/apps/trust/src/pages/DocumentsPage.tsx index 3aa194b7a..91c372199 100644 --- a/apps/trust/src/pages/DocumentsPage.tsx +++ b/apps/trust/src/pages/DocumentsPage.tsx @@ -23,10 +23,10 @@ import { useTranslate } from "@probo/i18n"; import { Fragment } from "react"; import { type PreloadedQuery, usePreloadedQuery } from "react-relay"; +import { CompliancePortalFileRow } from "#/components/CompliancePortalFileRow"; import { DocumentRow } from "#/components/DocumentRow"; import { RowHeader } from "#/components/RowHeader"; import { Rows } from "#/components/Rows"; -import { CompliancePortalFileRow } from "#/components/CompliancePortalFileRow"; import { documentTypeLabel } from "#/helpers/documents"; import type { CompliancePortalGraphCurrentDocumentsQuery } from "#/queries/__generated__/CompliancePortalGraphCurrentDocumentsQuery.graphql"; import { currentTrustDocumentsQuery } from "#/queries/CompliancePortalGraph"; diff --git a/apps/trust/src/pages/OverviewPage.tsx b/apps/trust/src/pages/OverviewPage.tsx index b8e0ca30a..a7c2eafaf 100644 --- a/apps/trust/src/pages/OverviewPage.tsx +++ b/apps/trust/src/pages/OverviewPage.tsx @@ -32,11 +32,11 @@ import { Link, useOutletContext } from "react-router"; import { graphql } from "relay-runtime"; import { AuditRow } from "#/components/AuditRow"; +import { CompliancePortalFileRow } from "#/components/CompliancePortalFileRow"; import { DocumentRow } from "#/components/DocumentRow"; import { RowHeader } from "#/components/RowHeader"; import { Rows } from "#/components/Rows"; import { SubprocessorRow } from "#/components/SubprocessorRow"; -import { CompliancePortalFileRow } from "#/components/CompliancePortalFileRow"; import { documentTypeLabel } from "#/helpers/documents"; import type { CompliancePortalGraphCurrentQuery$data } from "#/queries/__generated__/CompliancePortalGraphCurrentQuery.graphql"; diff --git a/apps/trust/src/routes.tsx b/apps/trust/src/routes.tsx index a29597b40..dd81876ec 100644 --- a/apps/trust/src/routes.tsx +++ b/apps/trust/src/routes.tsx @@ -35,8 +35,8 @@ import { OverviewPage } from "#/pages/OverviewPage"; import { SubprocessorsPage } from "#/pages/SubprocessorsPage"; import { currentTrustUpdatesQuery, UpdatesPage } from "#/pages/UpdatesPage"; import { - currentTrustDocumentsQuery, currentCompliancePortalGraphQuery, + currentTrustDocumentsQuery, currentTrustSubprocessorsQuery, } from "#/queries/CompliancePortalGraph"; diff --git a/packages/n8n-node/nodes/Probo/Probo.node.ts b/packages/n8n-node/nodes/Probo/Probo.node.ts index def33e13c..6367481e6 100644 --- a/packages/n8n-node/nodes/Probo/Probo.node.ts +++ b/packages/n8n-node/nodes/Probo/Probo.node.ts @@ -97,6 +97,11 @@ export class Probo implements INodeType { value: 'auditLog', description: 'View audit log entries', }, + { + name: 'Compliance Portal', + value: 'compliancePortal', + description: 'Manage compliance portal', + }, { name: 'Control', value: 'control', @@ -222,11 +227,6 @@ export class Probo implements INodeType { value: 'trackerPattern', description: 'Manage tracker patterns', }, - { - name: 'Compliance Portal', - value: 'compliancePortal', - description: 'Manage compliance portal', - }, { name: 'User', value: 'user', diff --git a/packages/n8n-node/nodes/Probo/actions/document/update.operation.ts b/packages/n8n-node/nodes/Probo/actions/document/update.operation.ts index e43b10c0d..33979a9b1 100644 --- a/packages/n8n-node/nodes/Probo/actions/document/update.operation.ts +++ b/packages/n8n-node/nodes/Probo/actions/document/update.operation.ts @@ -62,6 +62,18 @@ export const description: INodeProperties[] = [ default: 'INTERNAL', description: 'The classification of the document. Updating it edits the current draft version, creating one from the latest published version if none exists.', }, + { + displayName: 'Compliance Portal Visibility', + name: 'compliancePortalVisibility', + type: 'options', + options: [ + { name: 'None', value: 'NONE' }, + { name: 'Private', value: 'PRIVATE' }, + { name: 'Public', value: 'PUBLIC' }, + ], + default: 'NONE', + description: 'The compliance portal visibility of the document', + }, { displayName: 'Content', name: 'content', @@ -104,18 +116,6 @@ export const description: INodeProperties[] = [ default: '', description: 'The title of the document. Updating it edits the current draft version, creating one from the latest published version if none exists.', }, - { - displayName: 'Compliance Portal Visibility', - name: 'compliancePortalVisibility', - type: 'options', - options: [ - { name: 'None', value: 'NONE' }, - { name: 'Private', value: 'PRIVATE' }, - { name: 'Public', value: 'PUBLIC' }, - ], - default: 'NONE', - description: 'The compliance portal visibility of the document', - }, ], }, ]; diff --git a/pkg/server/api/console/v1/compliance_portal_resolvers.go b/pkg/server/api/console/v1/compliance_portal_resolvers.go index 30dd60d3b..c81050c9b 100644 --- a/pkg/server/api/console/v1/compliance_portal_resolvers.go +++ b/pkg/server/api/console/v1/compliance_portal_resolvers.go @@ -52,6 +52,430 @@ func (r *complianceFrameworkResolver) Framework(ctx context.Context, obj *types. return types.NewFramework(framework), nil } +// Logo is the resolver for the logo field. +func (r *compliancePortalResolver) Logo(ctx context.Context, obj *types.CompliancePortal) (*types.File, error) { + if _, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalGet); err != nil { + return nil, err + } + + if obj.Logo == nil { + return nil, nil + } + + return r.loadFile(ctx, obj.Logo.ID) +} + +// DarkLogo is the resolver for the darkLogo field. +func (r *compliancePortalResolver) DarkLogo(ctx context.Context, obj *types.CompliancePortal) (*types.File, error) { + if _, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalGet); err != nil { + return nil, err + } + + if obj.DarkLogo == nil { + return nil, nil + } + + return r.loadFile(ctx, obj.DarkLogo.ID) +} + +// Nda is the resolver for the nda field. +func (r *compliancePortalResolver) Nda(ctx context.Context, obj *types.CompliancePortal) (*types.File, error) { + hasPermission, err := r.Resolver.Permission(ctx, obj, management.ActionCompliancePortalGetNda) + if err != nil { + r.logger.ErrorCtx(ctx, "cannot authorize", log.Error(err)) + return nil, gqlutils.Internal(ctx) + } + + if !hasPermission || obj.Nda == nil { + return nil, nil + } + + return r.loadFile(ctx, obj.Nda.ID) +} + +// Organization is the resolver for the organization field. +func (r *compliancePortalResolver) Organization(ctx context.Context, obj *types.CompliancePortal) (*types.Organization, error) { + scope, err := r.authorize(ctx, obj.ID, probo.ActionOrganizationGet) + if err != nil { + return nil, err + } + + compliancePortal, err := r.management.Get(ctx, scope, obj.ID) + if err != nil { + r.logger.ErrorCtx(ctx, "cannot get compliance portal", log.Error(err)) + return nil, gqlutils.Internal(ctx) + } + + organization, err := r.probo.Organizations.Get(ctx, scope, compliancePortal.OrganizationID) + if err != nil { + if errors.Is(err, coredata.ErrResourceNotFound) { + return nil, gqlutils.NotFound(ctx, err) + } + + r.logger.ErrorCtx(ctx, "cannot get organization", log.Error(err)) + + return nil, gqlutils.Internal(ctx) + } + + return types.NewOrganization(organization), nil +} + +// Accesses is the resolver for the accesses field. +func (r *compliancePortalResolver) Accesses(ctx context.Context, obj *types.CompliancePortal, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrderBy[coredata.CompliancePortalAccessOrderField]) (*types.CompliancePortalAccessConnection, error) { + scope, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalAccessList) + if err != nil { + return nil, err + } + + pageOrderBy := page.OrderBy[coredata.CompliancePortalAccessOrderField]{ + Field: coredata.CompliancePortalAccessOrderFieldCreatedAt, + Direction: page.OrderDirectionDesc, + } + + if orderBy != nil { + pageOrderBy = page.OrderBy[coredata.CompliancePortalAccessOrderField]{ + Field: orderBy.Field, + Direction: orderBy.Direction, + } + } + + cursor := types.NewCursor(first, after, last, before, pageOrderBy) + + result, err := r.management.ListAccesses(ctx, scope, obj.ID, cursor) + if err != nil { + r.logger.ErrorCtx(ctx, "cannot list compliance portal accesses", log.Error(err)) + return nil, gqlutils.Internal(ctx) + } + + return types.NewCompliancePortalAccessConnection(result), nil +} + +// References is the resolver for the references field. +func (r *compliancePortalResolver) References(ctx context.Context, obj *types.CompliancePortal, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrderBy[coredata.CompliancePortalReferenceOrderField]) (*types.CompliancePortalReferenceConnection, error) { + scope, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalReferenceList) + if err != nil { + return nil, err + } + + pageOrderBy := page.OrderBy[coredata.CompliancePortalReferenceOrderField]{ + Field: coredata.CompliancePortalReferenceOrderFieldRank, + Direction: page.OrderDirectionAsc, + } + + if orderBy != nil { + pageOrderBy = page.OrderBy[coredata.CompliancePortalReferenceOrderField]{ + Field: orderBy.Field, + Direction: orderBy.Direction, + } + } + + cursor := types.NewCursor(first, after, last, before, pageOrderBy) + + result, err := r.management.ListReferences(ctx, scope, obj.ID, cursor) + if err != nil { + r.logger.ErrorCtx(ctx, "cannot list compliance portal references", log.Error(err)) + return nil, gqlutils.Internal(ctx) + } + + return types.NewCompliancePortalReferenceConnection(result, obj.ID), nil +} + +// CommitmentGroups is the resolver for the commitmentGroups field. +func (r *compliancePortalResolver) CommitmentGroups(ctx context.Context, obj *types.CompliancePortal, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrderBy[coredata.CompliancePortalCommitmentGroupOrderField]) (*types.CompliancePortalCommitmentGroupConnection, error) { + scope, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalCommitmentGroupList) + if err != nil { + return nil, err + } + + pageOrderBy := page.OrderBy[coredata.CompliancePortalCommitmentGroupOrderField]{ + Field: coredata.CompliancePortalCommitmentGroupOrderFieldRank, + Direction: page.OrderDirectionAsc, + } + + if orderBy != nil { + pageOrderBy = page.OrderBy[coredata.CompliancePortalCommitmentGroupOrderField]{ + Field: orderBy.Field, + Direction: orderBy.Direction, + } + } + + cursor := types.NewCursor(first, after, last, before, pageOrderBy) + + result, err := r.management.ListCommitmentGroups(ctx, scope, obj.ID, cursor) + if err != nil { + r.logger.ErrorCtx(ctx, "cannot list compliance portal commitment groups", log.Error(err)) + return nil, gqlutils.Internal(ctx) + } + + return types.NewCompliancePortalCommitmentGroupConnection(result, obj.ID), nil +} + +// ComplianceFrameworks is the resolver for the complianceFrameworks field. +func (r *compliancePortalResolver) ComplianceFrameworks(ctx context.Context, obj *types.CompliancePortal, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrderBy[coredata.ComplianceFrameworkOrderField]) (*types.ComplianceFrameworkConnection, error) { + scope, err := r.authorize(ctx, obj.ID, management.ActionComplianceFrameworkList) + if err != nil { + return nil, err + } + + pageOrderBy := page.OrderBy[coredata.ComplianceFrameworkOrderField]{ + Field: coredata.ComplianceFrameworkOrderFieldRank, + Direction: page.OrderDirectionAsc, + } + + if orderBy != nil { + pageOrderBy = page.OrderBy[coredata.ComplianceFrameworkOrderField]{ + Field: orderBy.Field, + Direction: orderBy.Direction, + } + } + + cursor := types.NewCursor(first, after, last, before, pageOrderBy) + + result, err := r.management.ListFrameworksWithHidden(ctx, scope, obj.ID, cursor) + if err != nil { + r.logger.ErrorCtx(ctx, "cannot list compliance frameworks", log.Error(err)) + return nil, gqlutils.Internal(ctx) + } + + return types.NewComplianceFrameworkConnection(result), nil +} + +// CustomLinks is the resolver for the customLinks field. +func (r *compliancePortalResolver) CustomLinks(ctx context.Context, obj *types.CompliancePortal, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrderBy[coredata.ComplianceCustomLinkOrderField]) (*types.ComplianceCustomLinkConnection, error) { + scope, err := r.authorize(ctx, obj.ID, management.ActionComplianceCustomLinkList) + if err != nil { + return nil, err + } + + pageOrderBy := page.OrderBy[coredata.ComplianceCustomLinkOrderField]{ + Field: coredata.ComplianceCustomLinkOrderFieldRank, + Direction: page.OrderDirectionAsc, + } + + if orderBy != nil { + pageOrderBy = page.OrderBy[coredata.ComplianceCustomLinkOrderField]{ + Field: orderBy.Field, + Direction: orderBy.Direction, + } + } + + cursor := types.NewCursor(first, after, last, before, pageOrderBy) + + result, err := r.management.ListCustomLinks(ctx, scope, obj.ID, cursor) + if err != nil { + r.logger.ErrorCtx(ctx, "cannot list compliance custom links", log.Error(err)) + return nil, gqlutils.Internal(ctx) + } + + return types.NewComplianceCustomLinkConnection(result), nil +} + +// MailingList is the resolver for the mailingList field. +func (r *compliancePortalResolver) MailingList(ctx context.Context, obj *types.CompliancePortal) (*types.MailingList, error) { + scope, err := r.authorize(ctx, obj.ID, management.ActionMailingListSubscriberList) + if err != nil { + return nil, err + } + + if obj.MailingList != nil { + return obj.MailingList, nil + } + + ml, err := r.management.GetMailingList(ctx, scope, obj.ID) + if err != nil { + r.logger.ErrorCtx(ctx, "cannot get mailing list for compliance portal", log.Error(err)) + return nil, gqlutils.Internal(ctx) + } + + if ml == nil { + return nil, nil + } + + return types.NewMailingList(ml), nil +} + +// DefaultDomain is the resolver for the defaultDomain field. +func (r *compliancePortalResolver) DefaultDomain(ctx context.Context, obj *types.CompliancePortal) (*types.CustomDomain, error) { + if obj.DefaultDomain == nil { + return nil, nil + } + + scope, err := r.authorize(ctx, obj.ID, management.ActionCustomDomainGet) + if err != nil { + return nil, err + } + + domain, err := r.management.GetDomain(ctx, scope, obj.DefaultDomain.ID) + if err != nil { + if errors.Is(err, coredata.ErrResourceNotFound) { + return nil, nil + } + + r.logger.ErrorCtx(ctx, "cannot load default domain", log.Error(err)) + + return nil, gqlutils.Internal(ctx) + } + + return types.NewCustomDomain(domain, r.customDomainCname), nil +} + +// CustomDomain is the resolver for the customDomain field. +func (r *compliancePortalResolver) CustomDomain(ctx context.Context, obj *types.CompliancePortal) (*types.CustomDomain, error) { + if obj.CustomDomain == nil { + return nil, nil + } + + scope, err := r.authorize(ctx, obj.ID, management.ActionCustomDomainGet) + if err != nil { + return nil, err + } + + domain, err := r.management.GetDomain(ctx, scope, obj.CustomDomain.ID) + if err != nil { + if errors.Is(err, coredata.ErrResourceNotFound) { + return nil, nil + } + + r.logger.ErrorCtx(ctx, "cannot load custom domain", log.Error(err)) + + return nil, gqlutils.Internal(ctx) + } + + return types.NewCustomDomain(domain, r.customDomainCname), nil +} + +// PublicURL is the resolver for the publicUrl field. +func (r *compliancePortalResolver) PublicURL(ctx context.Context, obj *types.CompliancePortal) (string, error) { + scope, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalGet) + if err != nil { + return "", err + } + + publicURL, err := r.management.PublicURL(ctx, scope, obj.ID) + if err != nil { + r.logger.ErrorCtx(ctx, "cannot resolve compliance portal public url", log.Error(err)) + return "", gqlutils.Internal(ctx) + } + + return publicURL, nil +} + +// Permission is the resolver for the permission field. +func (r *compliancePortalResolver) Permission(ctx context.Context, obj *types.CompliancePortal, action string) (bool, error) { + return r.Resolver.Permission(ctx, obj, action) +} + +// NdaSignature is the resolver for the ndaSignature field. +func (r *compliancePortalAccessResolver) NdaSignature(ctx context.Context, obj *types.CompliancePortalAccess) (*types.ElectronicSignature, error) { + scope, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalAccessGet) + if err != nil { + return nil, err + } + + access, err := r.management.GetAccess(ctx, scope, obj.ID) + if err != nil { + return nil, fmt.Errorf("cannot load compliance portal access: %w", err) + } + + if access.ElectronicSignatureID == nil { + return nil, nil + } + + sig, err := r.esign.GetSignatureByID(ctx, scope, *access.ElectronicSignatureID) + if err != nil { + return nil, nil + } + + return types.NewElectronicSignature(sig), nil +} + +// PendingRequestCount is the resolver for the pendingRequestCount field. +func (r *compliancePortalAccessResolver) PendingRequestCount(ctx context.Context, obj *types.CompliancePortalAccess) (int, error) { + scope, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalAccessGet) + if err != nil { + return 0, err + } + + count, err := r.management.CountPendingRequestDocumentAccesses(ctx, scope, obj.ID) + if err != nil { + r.logger.ErrorCtx(ctx, "cannot count pending request document accesses", log.Error(err)) + return 0, gqlutils.Internal(ctx) + } + + return count, nil +} + +// ActiveCount is the resolver for the activeCount field. +func (r *compliancePortalAccessResolver) ActiveCount(ctx context.Context, obj *types.CompliancePortalAccess) (int, error) { + scope, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalAccessGet) + if err != nil { + return 0, err + } + + count, err := r.management.CountActiveDocumentAccesses(ctx, scope, obj.ID) + if err != nil { + r.logger.ErrorCtx(ctx, "cannot count active document accesses", log.Error(err)) + return 0, gqlutils.Internal(ctx) + } + + return count, nil +} + +// Profile is the resolver for the profile field. +func (r *compliancePortalAccessResolver) Profile(ctx context.Context, obj *types.CompliancePortalAccess) (*types.Profile, error) { + if _, err := r.authorize(ctx, obj.ID, iam.ActionMembershipProfileGet); err != nil { + return nil, err + } + + profile, err := r.iam.OrganizationService.GetProfileForIdentityAndOrganization(ctx, obj.IdentityID, obj.OrganizationID) + if err != nil { + if _, ok := errors.AsType[*iam.ErrProfileNotFound](err); ok { + return nil, gqlutils.NotFound(ctx, err) + } + + r.logger.ErrorCtx(ctx, "cannot get profile", log.Error(err)) + + return nil, gqlutils.Internal(ctx) + } + + return types.NewProfile(profile), nil +} + +// AvailableDocumentAccesses is the resolver for the availableDocumentAccesses field. +func (r *compliancePortalAccessResolver) AvailableDocumentAccesses(ctx context.Context, obj *types.CompliancePortalAccess, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrderBy[coredata.CompliancePortalDocumentAccessOrderField]) (*types.CompliancePortalDocumentAccessConnection, error) { + scope, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalAccessGet) + if err != nil { + return nil, err + } + + pageOrderBy := page.OrderBy[coredata.CompliancePortalDocumentAccessOrderField]{ + Field: coredata.CompliancePortalDocumentAccessOrderFieldCreatedAt, + Direction: page.OrderDirectionDesc, + } + + if orderBy != nil { + pageOrderBy = page.OrderBy[coredata.CompliancePortalDocumentAccessOrderField]{ + Field: orderBy.Field, + Direction: orderBy.Direction, + } + } + + cursor := types.NewCursor(first, after, last, before, pageOrderBy) + + result, err := r.management.ListAvailableDocumentAccesses(ctx, scope, obj.ID, cursor) + if err != nil { + r.logger.ErrorCtx(ctx, "cannot list compliance portal document accesses", log.Error(err)) + return nil, gqlutils.Internal(ctx) + } + + return types.NewCompliancePortalDocumentAccessConnection(result, obj, obj.ID), nil +} + +// Permission is the resolver for the permission field. +func (r *compliancePortalAccessResolver) Permission(ctx context.Context, obj *types.CompliancePortalAccess, action string) (bool, error) { + return r.Resolver.Permission(ctx, obj, action) +} + // Permission is the resolver for the permission field. func (r *compliancePortalCommitmentResolver) Permission(ctx context.Context, obj *types.CompliancePortalCommitment, action string) (bool, error) { return r.Resolver.Permission(ctx, obj, action) @@ -124,6 +548,215 @@ func (r *compliancePortalCommitmentGroupConnectionResolver) TotalCount(ctx conte return count, nil } +// Document is the resolver for the document field. +func (r *compliancePortalDocumentAccessResolver) Document(ctx context.Context, obj *types.CompliancePortalDocumentAccess) (*types.Document, error) { + scope, err := r.authorize(ctx, obj.ID, probo.ActionDocumentGet) + if err != nil { + return nil, err + } + + if obj.DocumentID == nil { + return nil, nil + } + + document, err := r.probo.Documents.Get(ctx, scope, *obj.DocumentID) + if err != nil { + if errors.Is(err, coredata.ErrResourceNotFound) { + return nil, gqlutils.NotFound(ctx, err) + } + + r.logger.ErrorCtx(ctx, "cannot load document", log.Error(err)) + + return nil, gqlutils.Internal(ctx) + } + + return types.NewDocument(document), nil +} + +// ReportFile is the resolver for the reportFile field. +func (r *compliancePortalDocumentAccessResolver) ReportFile(ctx context.Context, obj *types.CompliancePortalDocumentAccess) (*types.File, error) { + if obj.ReportFile == nil { + return nil, nil + } + + if _, err := r.authorize(ctx, obj.ReportFile.ID, probo.ActionFileGet); err != nil { + return nil, err + } + + loaders := dataloader.FromContext(ctx) + + file, err := loaders.File.Load(ctx, obj.ReportFile.ID) + if err != nil { + if errors.Is(err, coredata.ErrResourceNotFound) || errors.Is(err, dataloadgen.ErrNotFound) { + return nil, gqlutils.NotFound(ctx, err) + } + + r.logger.ErrorCtx(ctx, "cannot load report file", log.Error(err)) + + return nil, gqlutils.Internal(ctx) + } + + return types.NewFile(file, r.fileManager), nil +} + +// Audit is the resolver for the audit field. +func (r *compliancePortalDocumentAccessResolver) Audit(ctx context.Context, obj *types.CompliancePortalDocumentAccess) (*types.Audit, error) { + scope, err := r.authorize(ctx, obj.ID, probo.ActionAuditGet) + if err != nil { + return nil, err + } + + if obj.ReportFileID == nil { + return nil, nil + } + + audit, err := r.probo.Audits.GetByReportFileID(ctx, scope, *obj.ReportFileID) + if err != nil { + if errors.Is(err, coredata.ErrResourceNotFound) { + return nil, nil + } + + r.logger.ErrorCtx(ctx, "cannot load audit for report file", log.Error(err)) + + return nil, gqlutils.Internal(ctx) + } + + return types.NewAudit(audit), nil +} + +// CompliancePortalFile is the resolver for the compliancePortalFile field. +func (r *compliancePortalDocumentAccessResolver) CompliancePortalFile(ctx context.Context, obj *types.CompliancePortalDocumentAccess) (*types.CompliancePortalFile, error) { + scope, err := r.authorize(ctx, obj.CompliancePortalAccessID, management.ActionCompliancePortalFileGet) + if err != nil { + return nil, err + } + + if obj.CompliancePortalFileID == nil { + return nil, nil + } + + compliancePortalFile, err := r.management.GetFile(ctx, scope, *obj.CompliancePortalFileID) + if err != nil { + r.logger.ErrorCtx(ctx, "cannot load compliance portal file", log.Error(err)) + return nil, gqlutils.Internal(ctx) + } + + return types.NewCompliancePortalFile(compliancePortalFile), nil +} + +// TotalCount is the resolver for the totalCount field. +func (r *compliancePortalDocumentAccessConnectionResolver) TotalCount(ctx context.Context, obj *types.CompliancePortalDocumentAccessConnection) (int, error) { + scope, err := r.authorize(ctx, obj.ParentID, management.ActionCompliancePortalDocumentAccessList) + if err != nil { + return 0, err + } + + count, err := r.management.CountDocumentAccesses(ctx, scope, obj.ParentID) + if err != nil { + r.logger.ErrorCtx(ctx, "cannot count compliance portal document accesses", log.Error(err)) + return 0, gqlutils.Internal(ctx) + } + + return count, nil +} + +// File is the resolver for the file field. +func (r *compliancePortalFileResolver) File(ctx context.Context, obj *types.CompliancePortalFile) (*types.File, error) { + if _, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalFileGetFileUrl); err != nil { + return nil, err + } + + return r.loadFile(ctx, obj.File.ID) +} + +// Alias is the resolver for the alias field. +func (r *compliancePortalFileResolver) Alias(ctx context.Context, obj *types.CompliancePortalFile) (*string, error) { + scope, err := r.authorize(ctx, obj.ID, resourcealias.ActionAliasGet) + if err != nil { + return nil, err + } + + return r.resourceAlias.GetByResourceID(ctx, scope, obj.ID) +} + +// Organization is the resolver for the organization field. +func (r *compliancePortalFileResolver) Organization(ctx context.Context, obj *types.CompliancePortalFile) (*types.Organization, error) { + scope, err := r.authorize(ctx, obj.ID, probo.ActionOrganizationGet) + if err != nil { + return nil, err + } + + compliancePortalFile, err := r.management.GetFile(ctx, scope, obj.ID) + if err != nil { + r.logger.ErrorCtx(ctx, "cannot get compliance portal file", log.Error(err)) + return nil, gqlutils.Internal(ctx) + } + + organization, err := r.probo.Organizations.Get(ctx, scope, compliancePortalFile.OrganizationID) + if err != nil { + if errors.Is(err, coredata.ErrResourceNotFound) { + return nil, gqlutils.NotFound(ctx, err) + } + + r.logger.ErrorCtx(ctx, "cannot get organization", log.Error(err)) + + return nil, gqlutils.Internal(ctx) + } + + return types.NewOrganization(organization), nil +} + +// Permission is the resolver for the permission field. +func (r *compliancePortalFileResolver) Permission(ctx context.Context, obj *types.CompliancePortalFile, action string) (bool, error) { + return r.Resolver.Permission(ctx, obj, action) +} + +// TotalCount is the resolver for the totalCount field. +func (r *compliancePortalFileConnectionResolver) TotalCount(ctx context.Context, obj *types.CompliancePortalFileConnection) (int, error) { + scope, err := r.authorize(ctx, obj.ParentID, management.ActionCompliancePortalFileList) + if err != nil { + return 0, err + } + + count, err := r.management.CountFilesForOrganizationID(ctx, scope, obj.ParentID) + if err != nil { + r.logger.ErrorCtx(ctx, "cannot count compliance portal files", log.Error(err)) + return 0, gqlutils.Internal(ctx) + } + + return count, nil +} + +// Logo is the resolver for the logo field. +func (r *compliancePortalReferenceResolver) Logo(ctx context.Context, obj *types.CompliancePortalReference) (*types.File, error) { + if _, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalReferenceGetLogoUrl); err != nil { + return nil, err + } + + return r.loadFile(ctx, obj.Logo.ID) +} + +// Permission is the resolver for the permission field. +func (r *compliancePortalReferenceResolver) Permission(ctx context.Context, obj *types.CompliancePortalReference, action string) (bool, error) { + return r.Resolver.Permission(ctx, obj, action) +} + +// TotalCount is the resolver for the totalCount field. +func (r *compliancePortalReferenceConnectionResolver) TotalCount(ctx context.Context, obj *types.CompliancePortalReferenceConnection) (int, error) { + scope, err := r.authorize(ctx, obj.ParentID, management.ActionCompliancePortalReferenceList) + if err != nil { + return 0, err + } + + count, err := r.management.CountReferences(ctx, scope, obj.ParentID) + if err != nil { + r.logger.ErrorCtx(ctx, "cannot count compliance portal references", log.Error(err)) + return 0, gqlutils.Internal(ctx) + } + + return count, nil +} + // Certificate is the resolver for the certificate field. func (r *customDomainResolver) Certificate(ctx context.Context, obj *types.CustomDomain) (*types.Certificate, error) { if obj.Certificate == nil { @@ -945,639 +1578,6 @@ func (r *mutationResolver) DeleteCustomDomain(ctx context.Context, input types.D }, nil } -// Logo is the resolver for the logo field. -func (r *compliancePortalResolver) Logo(ctx context.Context, obj *types.CompliancePortal) (*types.File, error) { - if _, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalGet); err != nil { - return nil, err - } - - if obj.Logo == nil { - return nil, nil - } - - return r.loadFile(ctx, obj.Logo.ID) -} - -// DarkLogo is the resolver for the darkLogo field. -func (r *compliancePortalResolver) DarkLogo(ctx context.Context, obj *types.CompliancePortal) (*types.File, error) { - if _, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalGet); err != nil { - return nil, err - } - - if obj.DarkLogo == nil { - return nil, nil - } - - return r.loadFile(ctx, obj.DarkLogo.ID) -} - -// Nda is the resolver for the nda field. -func (r *compliancePortalResolver) Nda(ctx context.Context, obj *types.CompliancePortal) (*types.File, error) { - hasPermission, err := r.Resolver.Permission(ctx, obj, management.ActionCompliancePortalGetNda) - if err != nil { - r.logger.ErrorCtx(ctx, "cannot authorize", log.Error(err)) - return nil, gqlutils.Internal(ctx) - } - - if !hasPermission || obj.Nda == nil { - return nil, nil - } - - return r.loadFile(ctx, obj.Nda.ID) -} - -// Organization is the resolver for the organization field. -func (r *compliancePortalResolver) Organization(ctx context.Context, obj *types.CompliancePortal) (*types.Organization, error) { - scope, err := r.authorize(ctx, obj.ID, probo.ActionOrganizationGet) - if err != nil { - return nil, err - } - - compliancePortal, err := r.management.Get(ctx, scope, obj.ID) - if err != nil { - r.logger.ErrorCtx(ctx, "cannot get compliance portal", log.Error(err)) - return nil, gqlutils.Internal(ctx) - } - - organization, err := r.probo.Organizations.Get(ctx, scope, compliancePortal.OrganizationID) - if err != nil { - if errors.Is(err, coredata.ErrResourceNotFound) { - return nil, gqlutils.NotFound(ctx, err) - } - - r.logger.ErrorCtx(ctx, "cannot get organization", log.Error(err)) - - return nil, gqlutils.Internal(ctx) - } - - return types.NewOrganization(organization), nil -} - -// Accesses is the resolver for the accesses field. -func (r *compliancePortalResolver) Accesses(ctx context.Context, obj *types.CompliancePortal, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrderBy[coredata.CompliancePortalAccessOrderField]) (*types.CompliancePortalAccessConnection, error) { - scope, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalAccessList) - if err != nil { - return nil, err - } - - pageOrderBy := page.OrderBy[coredata.CompliancePortalAccessOrderField]{ - Field: coredata.CompliancePortalAccessOrderFieldCreatedAt, - Direction: page.OrderDirectionDesc, - } - - if orderBy != nil { - pageOrderBy = page.OrderBy[coredata.CompliancePortalAccessOrderField]{ - Field: orderBy.Field, - Direction: orderBy.Direction, - } - } - - cursor := types.NewCursor(first, after, last, before, pageOrderBy) - - result, err := r.management.ListAccesses(ctx, scope, obj.ID, cursor) - if err != nil { - r.logger.ErrorCtx(ctx, "cannot list compliance portal accesses", log.Error(err)) - return nil, gqlutils.Internal(ctx) - } - - return types.NewCompliancePortalAccessConnection(result), nil -} - -// References is the resolver for the references field. -func (r *compliancePortalResolver) References(ctx context.Context, obj *types.CompliancePortal, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrderBy[coredata.CompliancePortalReferenceOrderField]) (*types.CompliancePortalReferenceConnection, error) { - scope, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalReferenceList) - if err != nil { - return nil, err - } - - pageOrderBy := page.OrderBy[coredata.CompliancePortalReferenceOrderField]{ - Field: coredata.CompliancePortalReferenceOrderFieldRank, - Direction: page.OrderDirectionAsc, - } - - if orderBy != nil { - pageOrderBy = page.OrderBy[coredata.CompliancePortalReferenceOrderField]{ - Field: orderBy.Field, - Direction: orderBy.Direction, - } - } - - cursor := types.NewCursor(first, after, last, before, pageOrderBy) - - result, err := r.management.ListReferences(ctx, scope, obj.ID, cursor) - if err != nil { - r.logger.ErrorCtx(ctx, "cannot list compliance portal references", log.Error(err)) - return nil, gqlutils.Internal(ctx) - } - - return types.NewCompliancePortalReferenceConnection(result, obj.ID), nil -} - -// CommitmentGroups is the resolver for the commitmentGroups field. -func (r *compliancePortalResolver) CommitmentGroups(ctx context.Context, obj *types.CompliancePortal, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrderBy[coredata.CompliancePortalCommitmentGroupOrderField]) (*types.CompliancePortalCommitmentGroupConnection, error) { - scope, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalCommitmentGroupList) - if err != nil { - return nil, err - } - - pageOrderBy := page.OrderBy[coredata.CompliancePortalCommitmentGroupOrderField]{ - Field: coredata.CompliancePortalCommitmentGroupOrderFieldRank, - Direction: page.OrderDirectionAsc, - } - - if orderBy != nil { - pageOrderBy = page.OrderBy[coredata.CompliancePortalCommitmentGroupOrderField]{ - Field: orderBy.Field, - Direction: orderBy.Direction, - } - } - - cursor := types.NewCursor(first, after, last, before, pageOrderBy) - - result, err := r.management.ListCommitmentGroups(ctx, scope, obj.ID, cursor) - if err != nil { - r.logger.ErrorCtx(ctx, "cannot list compliance portal commitment groups", log.Error(err)) - return nil, gqlutils.Internal(ctx) - } - - return types.NewCompliancePortalCommitmentGroupConnection(result, obj.ID), nil -} - -// ComplianceFrameworks is the resolver for the complianceFrameworks field. -func (r *compliancePortalResolver) ComplianceFrameworks(ctx context.Context, obj *types.CompliancePortal, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrderBy[coredata.ComplianceFrameworkOrderField]) (*types.ComplianceFrameworkConnection, error) { - scope, err := r.authorize(ctx, obj.ID, management.ActionComplianceFrameworkList) - if err != nil { - return nil, err - } - - pageOrderBy := page.OrderBy[coredata.ComplianceFrameworkOrderField]{ - Field: coredata.ComplianceFrameworkOrderFieldRank, - Direction: page.OrderDirectionAsc, - } - - if orderBy != nil { - pageOrderBy = page.OrderBy[coredata.ComplianceFrameworkOrderField]{ - Field: orderBy.Field, - Direction: orderBy.Direction, - } - } - - cursor := types.NewCursor(first, after, last, before, pageOrderBy) - - result, err := r.management.ListFrameworksWithHidden(ctx, scope, obj.ID, cursor) - if err != nil { - r.logger.ErrorCtx(ctx, "cannot list compliance frameworks", log.Error(err)) - return nil, gqlutils.Internal(ctx) - } - - return types.NewComplianceFrameworkConnection(result), nil -} - -// CustomLinks is the resolver for the customLinks field. -func (r *compliancePortalResolver) CustomLinks(ctx context.Context, obj *types.CompliancePortal, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrderBy[coredata.ComplianceCustomLinkOrderField]) (*types.ComplianceCustomLinkConnection, error) { - scope, err := r.authorize(ctx, obj.ID, management.ActionComplianceCustomLinkList) - if err != nil { - return nil, err - } - - pageOrderBy := page.OrderBy[coredata.ComplianceCustomLinkOrderField]{ - Field: coredata.ComplianceCustomLinkOrderFieldRank, - Direction: page.OrderDirectionAsc, - } - - if orderBy != nil { - pageOrderBy = page.OrderBy[coredata.ComplianceCustomLinkOrderField]{ - Field: orderBy.Field, - Direction: orderBy.Direction, - } - } - - cursor := types.NewCursor(first, after, last, before, pageOrderBy) - - result, err := r.management.ListCustomLinks(ctx, scope, obj.ID, cursor) - if err != nil { - r.logger.ErrorCtx(ctx, "cannot list compliance custom links", log.Error(err)) - return nil, gqlutils.Internal(ctx) - } - - return types.NewComplianceCustomLinkConnection(result), nil -} - -// MailingList is the resolver for the mailingList field. -func (r *compliancePortalResolver) MailingList(ctx context.Context, obj *types.CompliancePortal) (*types.MailingList, error) { - scope, err := r.authorize(ctx, obj.ID, management.ActionMailingListSubscriberList) - if err != nil { - return nil, err - } - - if obj.MailingList != nil { - return obj.MailingList, nil - } - - ml, err := r.management.GetMailingList(ctx, scope, obj.ID) - if err != nil { - r.logger.ErrorCtx(ctx, "cannot get mailing list for compliance portal", log.Error(err)) - return nil, gqlutils.Internal(ctx) - } - - if ml == nil { - return nil, nil - } - - return types.NewMailingList(ml), nil -} - -// DefaultDomain is the resolver for the defaultDomain field. -func (r *compliancePortalResolver) DefaultDomain(ctx context.Context, obj *types.CompliancePortal) (*types.CustomDomain, error) { - if obj.DefaultDomain == nil { - return nil, nil - } - - scope, err := r.authorize(ctx, obj.ID, management.ActionCustomDomainGet) - if err != nil { - return nil, err - } - - domain, err := r.management.GetDomain(ctx, scope, obj.DefaultDomain.ID) - if err != nil { - if errors.Is(err, coredata.ErrResourceNotFound) { - return nil, nil - } - - r.logger.ErrorCtx(ctx, "cannot load default domain", log.Error(err)) - - return nil, gqlutils.Internal(ctx) - } - - return types.NewCustomDomain(domain, r.customDomainCname), nil -} - -// CustomDomain is the resolver for the customDomain field. -func (r *compliancePortalResolver) CustomDomain(ctx context.Context, obj *types.CompliancePortal) (*types.CustomDomain, error) { - if obj.CustomDomain == nil { - return nil, nil - } - - scope, err := r.authorize(ctx, obj.ID, management.ActionCustomDomainGet) - if err != nil { - return nil, err - } - - domain, err := r.management.GetDomain(ctx, scope, obj.CustomDomain.ID) - if err != nil { - if errors.Is(err, coredata.ErrResourceNotFound) { - return nil, nil - } - - r.logger.ErrorCtx(ctx, "cannot load custom domain", log.Error(err)) - - return nil, gqlutils.Internal(ctx) - } - - return types.NewCustomDomain(domain, r.customDomainCname), nil -} - -// PublicURL is the resolver for the publicUrl field. -func (r *compliancePortalResolver) PublicURL(ctx context.Context, obj *types.CompliancePortal) (string, error) { - scope, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalGet) - if err != nil { - return "", err - } - - publicURL, err := r.management.PublicURL(ctx, scope, obj.ID) - if err != nil { - r.logger.ErrorCtx(ctx, "cannot resolve compliance portal public url", log.Error(err)) - return "", gqlutils.Internal(ctx) - } - - return publicURL, nil -} - -// Permission is the resolver for the permission field. -func (r *compliancePortalResolver) Permission(ctx context.Context, obj *types.CompliancePortal, action string) (bool, error) { - return r.Resolver.Permission(ctx, obj, action) -} - -// NdaSignature is the resolver for the ndaSignature field. -func (r *compliancePortalAccessResolver) NdaSignature(ctx context.Context, obj *types.CompliancePortalAccess) (*types.ElectronicSignature, error) { - scope, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalAccessGet) - if err != nil { - return nil, err - } - - access, err := r.management.GetAccess(ctx, scope, obj.ID) - if err != nil { - return nil, fmt.Errorf("cannot load compliance portal access: %w", err) - } - - if access.ElectronicSignatureID == nil { - return nil, nil - } - - sig, err := r.esign.GetSignatureByID(ctx, scope, *access.ElectronicSignatureID) - if err != nil { - return nil, nil - } - - return types.NewElectronicSignature(sig), nil -} - -// PendingRequestCount is the resolver for the pendingRequestCount field. -func (r *compliancePortalAccessResolver) PendingRequestCount(ctx context.Context, obj *types.CompliancePortalAccess) (int, error) { - scope, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalAccessGet) - if err != nil { - return 0, err - } - - count, err := r.management.CountPendingRequestDocumentAccesses(ctx, scope, obj.ID) - if err != nil { - r.logger.ErrorCtx(ctx, "cannot count pending request document accesses", log.Error(err)) - return 0, gqlutils.Internal(ctx) - } - - return count, nil -} - -// ActiveCount is the resolver for the activeCount field. -func (r *compliancePortalAccessResolver) ActiveCount(ctx context.Context, obj *types.CompliancePortalAccess) (int, error) { - scope, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalAccessGet) - if err != nil { - return 0, err - } - - count, err := r.management.CountActiveDocumentAccesses(ctx, scope, obj.ID) - if err != nil { - r.logger.ErrorCtx(ctx, "cannot count active document accesses", log.Error(err)) - return 0, gqlutils.Internal(ctx) - } - - return count, nil -} - -// Profile is the resolver for the profile field. -func (r *compliancePortalAccessResolver) Profile(ctx context.Context, obj *types.CompliancePortalAccess) (*types.Profile, error) { - if _, err := r.authorize(ctx, obj.ID, iam.ActionMembershipProfileGet); err != nil { - return nil, err - } - - profile, err := r.iam.OrganizationService.GetProfileForIdentityAndOrganization(ctx, obj.IdentityID, obj.OrganizationID) - if err != nil { - if _, ok := errors.AsType[*iam.ErrProfileNotFound](err); ok { - return nil, gqlutils.NotFound(ctx, err) - } - - r.logger.ErrorCtx(ctx, "cannot get profile", log.Error(err)) - - return nil, gqlutils.Internal(ctx) - } - - return types.NewProfile(profile), nil -} - -// AvailableDocumentAccesses is the resolver for the availableDocumentAccesses field. -func (r *compliancePortalAccessResolver) AvailableDocumentAccesses(ctx context.Context, obj *types.CompliancePortalAccess, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrderBy[coredata.CompliancePortalDocumentAccessOrderField]) (*types.CompliancePortalDocumentAccessConnection, error) { - scope, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalAccessGet) - if err != nil { - return nil, err - } - - pageOrderBy := page.OrderBy[coredata.CompliancePortalDocumentAccessOrderField]{ - Field: coredata.CompliancePortalDocumentAccessOrderFieldCreatedAt, - Direction: page.OrderDirectionDesc, - } - - if orderBy != nil { - pageOrderBy = page.OrderBy[coredata.CompliancePortalDocumentAccessOrderField]{ - Field: orderBy.Field, - Direction: orderBy.Direction, - } - } - - cursor := types.NewCursor(first, after, last, before, pageOrderBy) - - result, err := r.management.ListAvailableDocumentAccesses(ctx, scope, obj.ID, cursor) - if err != nil { - r.logger.ErrorCtx(ctx, "cannot list compliance portal document accesses", log.Error(err)) - return nil, gqlutils.Internal(ctx) - } - - return types.NewCompliancePortalDocumentAccessConnection(result, obj, obj.ID), nil -} - -// Permission is the resolver for the permission field. -func (r *compliancePortalAccessResolver) Permission(ctx context.Context, obj *types.CompliancePortalAccess, action string) (bool, error) { - return r.Resolver.Permission(ctx, obj, action) -} - -// Document is the resolver for the document field. -func (r *compliancePortalDocumentAccessResolver) Document(ctx context.Context, obj *types.CompliancePortalDocumentAccess) (*types.Document, error) { - scope, err := r.authorize(ctx, obj.ID, probo.ActionDocumentGet) - if err != nil { - return nil, err - } - - if obj.DocumentID == nil { - return nil, nil - } - - document, err := r.probo.Documents.Get(ctx, scope, *obj.DocumentID) - if err != nil { - if errors.Is(err, coredata.ErrResourceNotFound) { - return nil, gqlutils.NotFound(ctx, err) - } - - r.logger.ErrorCtx(ctx, "cannot load document", log.Error(err)) - - return nil, gqlutils.Internal(ctx) - } - - return types.NewDocument(document), nil -} - -// ReportFile is the resolver for the reportFile field. -func (r *compliancePortalDocumentAccessResolver) ReportFile(ctx context.Context, obj *types.CompliancePortalDocumentAccess) (*types.File, error) { - if obj.ReportFile == nil { - return nil, nil - } - - if _, err := r.authorize(ctx, obj.ReportFile.ID, probo.ActionFileGet); err != nil { - return nil, err - } - - loaders := dataloader.FromContext(ctx) - - file, err := loaders.File.Load(ctx, obj.ReportFile.ID) - if err != nil { - if errors.Is(err, coredata.ErrResourceNotFound) || errors.Is(err, dataloadgen.ErrNotFound) { - return nil, gqlutils.NotFound(ctx, err) - } - - r.logger.ErrorCtx(ctx, "cannot load report file", log.Error(err)) - - return nil, gqlutils.Internal(ctx) - } - - return types.NewFile(file, r.fileManager), nil -} - -// Audit is the resolver for the audit field. -func (r *compliancePortalDocumentAccessResolver) Audit(ctx context.Context, obj *types.CompliancePortalDocumentAccess) (*types.Audit, error) { - scope, err := r.authorize(ctx, obj.ID, probo.ActionAuditGet) - if err != nil { - return nil, err - } - - if obj.ReportFileID == nil { - return nil, nil - } - - audit, err := r.probo.Audits.GetByReportFileID(ctx, scope, *obj.ReportFileID) - if err != nil { - if errors.Is(err, coredata.ErrResourceNotFound) { - return nil, nil - } - - r.logger.ErrorCtx(ctx, "cannot load audit for report file", log.Error(err)) - - return nil, gqlutils.Internal(ctx) - } - - return types.NewAudit(audit), nil -} - -// CompliancePortalFile is the resolver for the compliancePortalFile field. -func (r *compliancePortalDocumentAccessResolver) CompliancePortalFile(ctx context.Context, obj *types.CompliancePortalDocumentAccess) (*types.CompliancePortalFile, error) { - scope, err := r.authorize(ctx, obj.CompliancePortalAccessID, management.ActionCompliancePortalFileGet) - if err != nil { - return nil, err - } - - if obj.CompliancePortalFileID == nil { - return nil, nil - } - - compliancePortalFile, err := r.management.GetFile(ctx, scope, *obj.CompliancePortalFileID) - if err != nil { - r.logger.ErrorCtx(ctx, "cannot load compliance portal file", log.Error(err)) - return nil, gqlutils.Internal(ctx) - } - - return types.NewCompliancePortalFile(compliancePortalFile), nil -} - -// TotalCount is the resolver for the totalCount field. -func (r *compliancePortalDocumentAccessConnectionResolver) TotalCount(ctx context.Context, obj *types.CompliancePortalDocumentAccessConnection) (int, error) { - scope, err := r.authorize(ctx, obj.ParentID, management.ActionCompliancePortalDocumentAccessList) - if err != nil { - return 0, err - } - - count, err := r.management.CountDocumentAccesses(ctx, scope, obj.ParentID) - if err != nil { - r.logger.ErrorCtx(ctx, "cannot count compliance portal document accesses", log.Error(err)) - return 0, gqlutils.Internal(ctx) - } - - return count, nil -} - -// File is the resolver for the file field. -func (r *compliancePortalFileResolver) File(ctx context.Context, obj *types.CompliancePortalFile) (*types.File, error) { - if _, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalFileGetFileUrl); err != nil { - return nil, err - } - - return r.loadFile(ctx, obj.File.ID) -} - -// Alias is the resolver for the alias field. -func (r *compliancePortalFileResolver) Alias(ctx context.Context, obj *types.CompliancePortalFile) (*string, error) { - scope, err := r.authorize(ctx, obj.ID, resourcealias.ActionAliasGet) - if err != nil { - return nil, err - } - - return r.resourceAlias.GetByResourceID(ctx, scope, obj.ID) -} - -// Organization is the resolver for the organization field. -func (r *compliancePortalFileResolver) Organization(ctx context.Context, obj *types.CompliancePortalFile) (*types.Organization, error) { - scope, err := r.authorize(ctx, obj.ID, probo.ActionOrganizationGet) - if err != nil { - return nil, err - } - - compliancePortalFile, err := r.management.GetFile(ctx, scope, obj.ID) - if err != nil { - r.logger.ErrorCtx(ctx, "cannot get compliance portal file", log.Error(err)) - return nil, gqlutils.Internal(ctx) - } - - organization, err := r.probo.Organizations.Get(ctx, scope, compliancePortalFile.OrganizationID) - if err != nil { - if errors.Is(err, coredata.ErrResourceNotFound) { - return nil, gqlutils.NotFound(ctx, err) - } - - r.logger.ErrorCtx(ctx, "cannot get organization", log.Error(err)) - - return nil, gqlutils.Internal(ctx) - } - - return types.NewOrganization(organization), nil -} - -// Permission is the resolver for the permission field. -func (r *compliancePortalFileResolver) Permission(ctx context.Context, obj *types.CompliancePortalFile, action string) (bool, error) { - return r.Resolver.Permission(ctx, obj, action) -} - -// TotalCount is the resolver for the totalCount field. -func (r *compliancePortalFileConnectionResolver) TotalCount(ctx context.Context, obj *types.CompliancePortalFileConnection) (int, error) { - scope, err := r.authorize(ctx, obj.ParentID, management.ActionCompliancePortalFileList) - if err != nil { - return 0, err - } - - count, err := r.management.CountFilesForOrganizationID(ctx, scope, obj.ParentID) - if err != nil { - r.logger.ErrorCtx(ctx, "cannot count compliance portal files", log.Error(err)) - return 0, gqlutils.Internal(ctx) - } - - return count, nil -} - -// Logo is the resolver for the logo field. -func (r *compliancePortalReferenceResolver) Logo(ctx context.Context, obj *types.CompliancePortalReference) (*types.File, error) { - if _, err := r.authorize(ctx, obj.ID, management.ActionCompliancePortalReferenceGetLogoUrl); err != nil { - return nil, err - } - - return r.loadFile(ctx, obj.Logo.ID) -} - -// Permission is the resolver for the permission field. -func (r *compliancePortalReferenceResolver) Permission(ctx context.Context, obj *types.CompliancePortalReference, action string) (bool, error) { - return r.Resolver.Permission(ctx, obj, action) -} - -// TotalCount is the resolver for the totalCount field. -func (r *compliancePortalReferenceConnectionResolver) TotalCount(ctx context.Context, obj *types.CompliancePortalReferenceConnection) (int, error) { - scope, err := r.authorize(ctx, obj.ParentID, management.ActionCompliancePortalReferenceList) - if err != nil { - return 0, err - } - - count, err := r.management.CountReferences(ctx, scope, obj.ParentID) - if err != nil { - r.logger.ErrorCtx(ctx, "cannot count compliance portal references", log.Error(err)) - return 0, gqlutils.Internal(ctx) - } - - return count, nil -} - // ComplianceCustomLink returns schema.ComplianceCustomLinkResolver implementation. func (r *Resolver) ComplianceCustomLink() schema.ComplianceCustomLinkResolver { return &complianceCustomLinkResolver{r} @@ -1588,6 +1588,16 @@ func (r *Resolver) ComplianceFramework() schema.ComplianceFrameworkResolver { return &complianceFrameworkResolver{r} } +// CompliancePortal returns schema.CompliancePortalResolver implementation. +func (r *Resolver) CompliancePortal() schema.CompliancePortalResolver { + return &compliancePortalResolver{r} +} + +// CompliancePortalAccess returns schema.CompliancePortalAccessResolver implementation. +func (r *Resolver) CompliancePortalAccess() schema.CompliancePortalAccessResolver { + return &compliancePortalAccessResolver{r} +} + // CompliancePortalCommitment returns schema.CompliancePortalCommitmentResolver implementation. func (r *Resolver) CompliancePortalCommitment() schema.CompliancePortalCommitmentResolver { return &compliancePortalCommitmentResolver{r} @@ -1608,19 +1618,6 @@ func (r *Resolver) CompliancePortalCommitmentGroupConnection() schema.Compliance return &compliancePortalCommitmentGroupConnectionResolver{r} } -// CustomDomain returns schema.CustomDomainResolver implementation. -func (r *Resolver) CustomDomain() schema.CustomDomainResolver { return &customDomainResolver{r} } - -// CompliancePortal returns schema.CompliancePortalResolver implementation. -func (r *Resolver) CompliancePortal() schema.CompliancePortalResolver { - return &compliancePortalResolver{r} -} - -// CompliancePortalAccess returns schema.CompliancePortalAccessResolver implementation. -func (r *Resolver) CompliancePortalAccess() schema.CompliancePortalAccessResolver { - return &compliancePortalAccessResolver{r} -} - // CompliancePortalDocumentAccess returns schema.CompliancePortalDocumentAccessResolver implementation. func (r *Resolver) CompliancePortalDocumentAccess() schema.CompliancePortalDocumentAccessResolver { return &compliancePortalDocumentAccessResolver{r} @@ -1651,20 +1648,23 @@ func (r *Resolver) CompliancePortalReferenceConnection() schema.CompliancePortal return &compliancePortalReferenceConnectionResolver{r} } +// CustomDomain returns schema.CustomDomainResolver implementation. +func (r *Resolver) CustomDomain() schema.CustomDomainResolver { return &customDomainResolver{r} } + type ( complianceCustomLinkResolver struct{ *Resolver } complianceFrameworkResolver struct{ *Resolver } + compliancePortalResolver struct{ *Resolver } + compliancePortalAccessResolver struct{ *Resolver } compliancePortalCommitmentResolver struct{ *Resolver } compliancePortalCommitmentConnectionResolver struct{ *Resolver } compliancePortalCommitmentGroupResolver struct{ *Resolver } compliancePortalCommitmentGroupConnectionResolver struct{ *Resolver } - customDomainResolver struct{ *Resolver } - compliancePortalResolver struct{ *Resolver } - compliancePortalAccessResolver struct{ *Resolver } compliancePortalDocumentAccessResolver struct{ *Resolver } compliancePortalDocumentAccessConnectionResolver struct{ *Resolver } compliancePortalFileResolver struct{ *Resolver } compliancePortalFileConnectionResolver struct{ *Resolver } compliancePortalReferenceResolver struct{ *Resolver } compliancePortalReferenceConnectionResolver struct{ *Resolver } + customDomainResolver struct{ *Resolver } )