From 16503a7df4ba82821a627c39192dd74a1362c87b Mon Sep 17 00:00:00 2001 From: Bryan Frimin Date: Fri, 20 Feb 2026 09:22:37 +0100 Subject: [PATCH] Use electronic signature for compliage page NDA Signed-off-by: Bryan Frimin --- apps/trust/src/layouts/MainLayout.tsx | 9 +- apps/trust/src/pages/NDAPage.tsx | 39 +- .../__generated__/NDAPageFragment.graphql.ts | 75 +- .../__generated__/NDAPageQuery.graphql.ts | 84 +- ...APageRecordSigningEventMutation.graphql.ts | 4 +- .../NDAPageRefetchQuery.graphql.ts | 57 +- apps/trust/src/queries/TrustGraph.ts | 10 +- .../TrustGraphCurrentQuery.graphql.ts | 66 +- go.mod | 2 +- pkg/coredata/electronic_signature.go | 52 -- pkg/coredata/migrations/20260220T092400Z.sql | 2 + pkg/coredata/trust_center_access.go | 13 +- pkg/esign/service.go | 66 +- pkg/esign/tsa.go | 2 +- pkg/probo/trust_center_access_service.go | 12 +- pkg/probo/trust_center_service.go | 28 +- pkg/server/api/console/v1/v1_resolver.go | 31 +- pkg/server/api/trust/v1/schema.graphql | 29 +- pkg/server/api/trust/v1/schema/schema.go | 821 +++++++----------- pkg/server/api/trust/v1/types/trust_center.go | 20 +- pkg/server/api/trust/v1/types/types.go | 43 +- pkg/server/api/trust/v1/v1_resolver.go | 355 ++++---- pkg/trust/trust_center_access_service.go | 105 +-- pkg/trust/trust_center_service.go | 47 +- pkg/trust/vendor_service.go | 2 +- 25 files changed, 849 insertions(+), 1125 deletions(-) create mode 100644 pkg/coredata/migrations/20260220T092400Z.sql diff --git a/apps/trust/src/layouts/MainLayout.tsx b/apps/trust/src/layouts/MainLayout.tsx index e1aec50b8..664e35dc5 100644 --- a/apps/trust/src/layouts/MainLayout.tsx +++ b/apps/trust/src/layouts/MainLayout.tsx @@ -27,12 +27,9 @@ export function MainLayout(props: Props) { return null; } - const ndaSig = trustCenter.ndaSignature; - const hasPendingNDA - = trustCenter.isViewerMember - && trustCenter.ndaFileUrl - && ndaSig - && ndaSig.status !== "COMPLETED"; + const nda = trustCenter.nonDisclosureAgreement; + const hasPendingNDA = nda?.viewerSignature + && (nda.viewerSignature.status === "PENDING" || nda.viewerSignature.status === "FAILED"); if (hasPendingNDA) { return ; diff --git a/apps/trust/src/pages/NDAPage.tsx b/apps/trust/src/pages/NDAPage.tsx index c5a5bc507..d5f40f5e8 100644 --- a/apps/trust/src/pages/NDAPage.tsx +++ b/apps/trust/src/pages/NDAPage.tsx @@ -31,10 +31,12 @@ export const ndaPageQuery = graphql` organization { name } - ndaFileUrl - ndaFileName - ndaSignature { - status + nonDisclosureAgreement { + fileName + fileUrl + viewerSignature { + status + } } ...NDAPageFragment } @@ -44,11 +46,13 @@ export const ndaPageQuery = graphql` const ndaPageFragment = graphql` fragment NDAPageFragment on TrustCenter @refetchable(queryName: "NDAPageRefetchQuery") { - ndaSignature @required(action: THROW) { - id - status - consentText - lastError + nonDisclosureAgreement @required(action: THROW) { + viewerSignature @required(action: THROW) { + id + status + consentText + lastError + } } } `; @@ -95,7 +99,7 @@ export function NDAPage(props: { ndaPageFragment, trustCenter, ); - const ndaSignature = data.ndaSignature; + const ndaSignature = data.nonDisclosureAgreement.viewerSignature; const { width } = useWindowSize(); const isMobile = width < 1100; @@ -208,10 +212,11 @@ export function NDAPage(props: { } }; + const nda = trustCenter.nonDisclosureAgreement; if ( - !trustCenter.ndaFileUrl - || !trustCenter.ndaSignature - || trustCenter.ndaSignature.status === "COMPLETED" + !nda + || !nda.viewerSignature + || nda.viewerSignature.status === "COMPLETED" ) { return ; } @@ -241,11 +246,11 @@ export function NDAPage(props: { trustCenter.organization.name, )}

- {isMobile && trustCenter.ndaFileUrl && ( + {isMobile && nda?.fileUrl && ( - {trustCenter.ndaFileName} + {nda?.fileName} @@ -323,7 +328,7 @@ export function NDAPage(props: { {isDesktop && (
- {trustCenter.ndaFileUrl && } + {nda?.fileUrl && }
)} diff --git a/apps/trust/src/pages/__generated__/NDAPageFragment.graphql.ts b/apps/trust/src/pages/__generated__/NDAPageFragment.graphql.ts index 672159d34..1915f4026 100644 --- a/apps/trust/src/pages/__generated__/NDAPageFragment.graphql.ts +++ b/apps/trust/src/pages/__generated__/NDAPageFragment.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<93f8676826dfa28c1681da68a6ac1cf2>> + * @generated SignedSource<<99908411212decf464eafa45b1fc0e04>> * @lightSyntaxTransform * @nogrep */ @@ -13,11 +13,13 @@ export type ElectronicSignatureStatus = "ACCEPTED" | "COMPLETED" | "FAILED" | "P import { FragmentRefs } from "relay-runtime"; export type NDAPageFragment$data = { readonly id: string; - readonly ndaSignature: { - readonly consentText: string; - readonly id: string; - readonly lastError: string | null | undefined; - readonly status: ElectronicSignatureStatus; + readonly nonDisclosureAgreement: { + readonly viewerSignature: { + readonly consentText: string; + readonly id: string; + readonly lastError: string | null | undefined; + readonly status: ElectronicSignatureStatus; + }; }; readonly " $fragmentType": "NDAPageFragment"; }; @@ -59,32 +61,47 @@ return { "field": { "alias": null, "args": null, - "concreteType": "ElectronicSignature", + "concreteType": "NonDisclosureAgreement", "kind": "LinkedField", - "name": "ndaSignature", + "name": "nonDisclosureAgreement", "plural": false, "selections": [ - (v0/*: any*/), { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "status", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "consentText", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "lastError", - "storageKey": null + "kind": "RequiredField", + "field": { + "alias": null, + "args": null, + "concreteType": "ElectronicSignature", + "kind": "LinkedField", + "name": "viewerSignature", + "plural": false, + "selections": [ + (v0/*: any*/), + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "status", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "consentText", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "lastError", + "storageKey": null + } + ], + "storageKey": null + }, + "action": "THROW" } ], "storageKey": null @@ -98,6 +115,6 @@ return { }; })(); -(node as any).hash = "b53a5f455508ed45124b7d09cfb573da"; +(node as any).hash = "503859b8c00b27214f9f3253bffcb670"; export default node; diff --git a/apps/trust/src/pages/__generated__/NDAPageQuery.graphql.ts b/apps/trust/src/pages/__generated__/NDAPageQuery.graphql.ts index dd2832ed8..4ab0f365f 100644 --- a/apps/trust/src/pages/__generated__/NDAPageQuery.graphql.ts +++ b/apps/trust/src/pages/__generated__/NDAPageQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<<10a0ee1dfa19239c5c5820f3d58a1e19>> * @lightSyntaxTransform * @nogrep */ @@ -14,10 +14,12 @@ export type ElectronicSignatureStatus = "ACCEPTED" | "COMPLETED" | "FAILED" | "P export type NDAPageQuery$variables = Record; export type NDAPageQuery$data = { readonly currentTrustCenter: { - readonly ndaFileName: string | null | undefined; - readonly ndaFileUrl: string | null | undefined; - readonly ndaSignature: { - readonly status: ElectronicSignatureStatus; + readonly nonDisclosureAgreement: { + readonly fileName: string; + readonly fileUrl: string; + readonly viewerSignature: { + readonly status: ElectronicSignatureStatus; + } | null | undefined; } | null | undefined; readonly organization: { readonly name: string; @@ -52,14 +54,14 @@ v2 = { "alias": null, "args": null, "kind": "ScalarField", - "name": "ndaFileUrl", + "name": "fileName", "storageKey": null }, v3 = { "alias": null, "args": null, "kind": "ScalarField", - "name": "ndaFileName", + "name": "fileUrl", "storageKey": null }, v4 = { @@ -117,17 +119,28 @@ return { ], "storageKey": null }, - (v2/*: any*/), - (v3/*: any*/), { "alias": null, "args": null, - "concreteType": "ElectronicSignature", + "concreteType": "NonDisclosureAgreement", "kind": "LinkedField", - "name": "ndaSignature", + "name": "nonDisclosureAgreement", "plural": false, "selections": [ - (v4/*: any*/) + (v2/*: any*/), + (v3/*: any*/), + { + "alias": null, + "args": null, + "concreteType": "ElectronicSignature", + "kind": "LinkedField", + "name": "viewerSignature", + "plural": false, + "selections": [ + (v4/*: any*/) + ], + "storageKey": null + } ], "storageKey": null }, @@ -185,30 +198,41 @@ return { ], "storageKey": null }, - (v2/*: any*/), - (v3/*: any*/), { "alias": null, "args": null, - "concreteType": "ElectronicSignature", + "concreteType": "NonDisclosureAgreement", "kind": "LinkedField", - "name": "ndaSignature", + "name": "nonDisclosureAgreement", "plural": false, "selections": [ - (v4/*: any*/), - (v5/*: any*/), + (v2/*: any*/), + (v3/*: any*/), { "alias": null, "args": null, - "kind": "ScalarField", - "name": "consentText", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "lastError", + "concreteType": "ElectronicSignature", + "kind": "LinkedField", + "name": "viewerSignature", + "plural": false, + "selections": [ + (v4/*: any*/), + (v5/*: any*/), + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "consentText", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "lastError", + "storageKey": null + } + ], "storageKey": null } ], @@ -221,16 +245,16 @@ return { ] }, "params": { - "cacheID": "c0b175c435c5730e390fcfde596d8bc3", + "cacheID": "e1ab3a5206a4ea200ebdb991023a0e99", "id": null, "metadata": {}, "name": "NDAPageQuery", "operationKind": "query", - "text": "query NDAPageQuery {\n viewer {\n fullName\n id\n }\n currentTrustCenter {\n organization {\n name\n id\n }\n ndaFileUrl\n ndaFileName\n ndaSignature {\n status\n id\n }\n ...NDAPageFragment\n id\n }\n}\n\nfragment NDAPageFragment on TrustCenter {\n ndaSignature {\n id\n status\n consentText\n lastError\n }\n id\n}\n" + "text": "query NDAPageQuery {\n viewer {\n fullName\n id\n }\n currentTrustCenter {\n organization {\n name\n id\n }\n nonDisclosureAgreement {\n fileName\n fileUrl\n viewerSignature {\n status\n id\n }\n }\n ...NDAPageFragment\n id\n }\n}\n\nfragment NDAPageFragment on TrustCenter {\n nonDisclosureAgreement {\n viewerSignature {\n id\n status\n consentText\n lastError\n }\n }\n id\n}\n" } }; })(); -(node as any).hash = "a78bf8b65feba4627ecb265ca882f645"; +(node as any).hash = "4f0f0dd672862fb6c3fb5ef2eff80cd9"; export default node; diff --git a/apps/trust/src/pages/__generated__/NDAPageRecordSigningEventMutation.graphql.ts b/apps/trust/src/pages/__generated__/NDAPageRecordSigningEventMutation.graphql.ts index a25042db5..4756f8f47 100644 --- a/apps/trust/src/pages/__generated__/NDAPageRecordSigningEventMutation.graphql.ts +++ b/apps/trust/src/pages/__generated__/NDAPageRecordSigningEventMutation.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<<58dbdcc5fc52f0dab9eb156856522fd1>> * @lightSyntaxTransform * @nogrep */ @@ -9,7 +9,7 @@ // @ts-nocheck import { ConcreteRequest } from 'relay-runtime'; -export type ElectronicSignatureEventType = "CERTIFICATE_GENERATED" | "CONSENT_GIVEN" | "DOCUMENT_VIEWED" | "FULL_NAME_TYPED" | "SEAL_COMPUTED" | "SIGNATURE_ACCEPTED" | "SIGNATURE_COMPLETED" | "TIMESTAMP_REQUESTED"; +export type ElectronicSignatureEventType = "CERTIFICATE_GENERATED" | "CONSENT_GIVEN" | "DOCUMENT_VIEWED" | "FULL_NAME_TYPED" | "PROCESSING_ERROR" | "SEAL_COMPUTED" | "SIGNATURE_ACCEPTED" | "SIGNATURE_COMPLETED" | "TIMESTAMP_REQUESTED"; export type RecordSigningEventInput = { eventType: ElectronicSignatureEventType; signatureId: string; diff --git a/apps/trust/src/pages/__generated__/NDAPageRefetchQuery.graphql.ts b/apps/trust/src/pages/__generated__/NDAPageRefetchQuery.graphql.ts index c5fac0509..e1158a4f9 100644 --- a/apps/trust/src/pages/__generated__/NDAPageRefetchQuery.graphql.ts +++ b/apps/trust/src/pages/__generated__/NDAPageRefetchQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<47d15b007fc81de3850393c9b158726c>> + * @generated SignedSource<<5c6134b4d6615f24a63ea534c80e76c1>> * @lightSyntaxTransform * @nogrep */ @@ -100,31 +100,42 @@ return { { "alias": null, "args": null, - "concreteType": "ElectronicSignature", + "concreteType": "NonDisclosureAgreement", "kind": "LinkedField", - "name": "ndaSignature", + "name": "nonDisclosureAgreement", "plural": false, "selections": [ - (v2/*: any*/), { "alias": null, "args": null, - "kind": "ScalarField", - "name": "status", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "consentText", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "lastError", + "concreteType": "ElectronicSignature", + "kind": "LinkedField", + "name": "viewerSignature", + "plural": false, + "selections": [ + (v2/*: any*/), + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "status", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "consentText", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "lastError", + "storageKey": null + } + ], "storageKey": null } ], @@ -140,16 +151,16 @@ return { ] }, "params": { - "cacheID": "1c61baa555ad2b24794ce0bf5ecc14ac", + "cacheID": "fcf227efd02b14a0cb1599e4a5f944bd", "id": null, "metadata": {}, "name": "NDAPageRefetchQuery", "operationKind": "query", - "text": "query NDAPageRefetchQuery(\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...NDAPageFragment\n id\n }\n}\n\nfragment NDAPageFragment on TrustCenter {\n ndaSignature {\n id\n status\n consentText\n lastError\n }\n id\n}\n" + "text": "query NDAPageRefetchQuery(\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...NDAPageFragment\n id\n }\n}\n\nfragment NDAPageFragment on TrustCenter {\n nonDisclosureAgreement {\n viewerSignature {\n id\n status\n consentText\n lastError\n }\n }\n id\n}\n" } }; })(); -(node as any).hash = "b53a5f455508ed45124b7d09cfb573da"; +(node as any).hash = "503859b8c00b27214f9f3253bffcb670"; export default node; diff --git a/apps/trust/src/queries/TrustGraph.ts b/apps/trust/src/queries/TrustGraph.ts index 5333f104f..6f98f7b87 100644 --- a/apps/trust/src/queries/TrustGraph.ts +++ b/apps/trust/src/queries/TrustGraph.ts @@ -13,10 +13,12 @@ export const currentTrustGraphQuery = graphql` isViewerMember logoFileUrl darkLogoFileUrl - ndaFileName - ndaFileUrl - ndaSignature { - status + nonDisclosureAgreement { + fileName + fileUrl + viewerSignature { + status + } } organization { name diff --git a/apps/trust/src/queries/__generated__/TrustGraphCurrentQuery.graphql.ts b/apps/trust/src/queries/__generated__/TrustGraphCurrentQuery.graphql.ts index bacc0b9b2..5521a6934 100644 --- a/apps/trust/src/queries/__generated__/TrustGraphCurrentQuery.graphql.ts +++ b/apps/trust/src/queries/__generated__/TrustGraphCurrentQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<4bf04c5599ef88c6104919907fb182dd>> + * @generated SignedSource<> * @lightSyntaxTransform * @nogrep */ @@ -26,10 +26,12 @@ export type TrustGraphCurrentQuery$data = { readonly id: string; readonly isViewerMember: boolean; readonly logoFileUrl: string | null | undefined; - readonly ndaFileName: string | null | undefined; - readonly ndaFileUrl: string | null | undefined; - readonly ndaSignature: { - readonly status: ElectronicSignatureStatus; + readonly nonDisclosureAgreement: { + readonly fileName: string; + readonly fileUrl: string; + readonly viewerSignature: { + readonly status: ElectronicSignatureStatus; + } | null | undefined; } | null | undefined; readonly organization: { readonly description: string | null | undefined; @@ -108,14 +110,14 @@ v7 = { "alias": null, "args": null, "kind": "ScalarField", - "name": "ndaFileName", + "name": "fileName", "storageKey": null }, v8 = { "alias": null, "args": null, "kind": "ScalarField", - "name": "ndaFileUrl", + "name": "fileUrl", "storageKey": null }, v9 = { @@ -238,17 +240,28 @@ return { (v4/*: any*/), (v5/*: any*/), (v6/*: any*/), - (v7/*: any*/), - (v8/*: any*/), { "alias": null, "args": null, - "concreteType": "ElectronicSignature", + "concreteType": "NonDisclosureAgreement", "kind": "LinkedField", - "name": "ndaSignature", + "name": "nonDisclosureAgreement", "plural": false, "selections": [ - (v9/*: any*/) + (v7/*: any*/), + (v8/*: any*/), + { + "alias": null, + "args": null, + "concreteType": "ElectronicSignature", + "kind": "LinkedField", + "name": "viewerSignature", + "plural": false, + "selections": [ + (v9/*: any*/) + ], + "storageKey": null + } ], "storageKey": null }, @@ -353,18 +366,29 @@ return { (v4/*: any*/), (v5/*: any*/), (v6/*: any*/), - (v7/*: any*/), - (v8/*: any*/), { "alias": null, "args": null, - "concreteType": "ElectronicSignature", + "concreteType": "NonDisclosureAgreement", "kind": "LinkedField", - "name": "ndaSignature", + "name": "nonDisclosureAgreement", "plural": false, "selections": [ - (v9/*: any*/), - (v2/*: any*/) + (v7/*: any*/), + (v8/*: any*/), + { + "alias": null, + "args": null, + "concreteType": "ElectronicSignature", + "kind": "LinkedField", + "name": "viewerSignature", + "plural": false, + "selections": [ + (v9/*: any*/), + (v2/*: any*/) + ], + "storageKey": null + } ], "storageKey": null }, @@ -667,16 +691,16 @@ return { ] }, "params": { - "cacheID": "5756e245b9ad1dc00d25c505e4764a62", + "cacheID": "011070e93164ecde082cc2e74651ef2e", "id": null, "metadata": {}, "name": "TrustGraphCurrentQuery", "operationKind": "query", - "text": "query TrustGraphCurrentQuery {\n viewer {\n email\n fullName\n id\n }\n currentTrustCenter {\n id\n slug\n isViewerMember\n logoFileUrl\n darkLogoFileUrl\n ndaFileName\n ndaFileUrl\n ndaSignature {\n status\n id\n }\n organization {\n name\n description\n websiteUrl\n email\n headquarterAddress\n id\n }\n ...OverviewPageFragment\n vendorInfo: vendors(first: 0) {\n totalCount\n }\n audits(first: 50) {\n edges {\n node {\n id\n ...AuditRowFragment\n }\n }\n }\n }\n}\n\nfragment AuditRowFragment on Audit {\n report {\n id\n filename\n isUserAuthorized\n hasUserRequestedAccess\n }\n framework {\n id\n name\n lightLogoURL\n darkLogoURL\n }\n}\n\nfragment DocumentRowFragment on Document {\n id\n title\n isUserAuthorized\n hasUserRequestedAccess\n}\n\nfragment OverviewPageFragment on TrustCenter {\n references(first: 14) {\n edges {\n node {\n id\n name\n logoUrl\n websiteUrl\n }\n }\n }\n vendors(first: 3) {\n edges {\n node {\n id\n countries\n ...VendorRowFragment\n }\n }\n }\n documents(first: 5) {\n edges {\n node {\n id\n ...DocumentRowFragment\n documentType\n }\n }\n }\n trustCenterFiles(first: 5) {\n edges {\n node {\n id\n category\n ...TrustCenterFileRowFragment\n }\n }\n }\n}\n\nfragment TrustCenterFileRowFragment on TrustCenterFile {\n id\n name\n isUserAuthorized\n hasUserRequestedAccess\n}\n\nfragment VendorRowFragment on Vendor {\n name\n description\n websiteUrl\n countries\n}\n" + "text": "query TrustGraphCurrentQuery {\n viewer {\n email\n fullName\n id\n }\n currentTrustCenter {\n id\n slug\n isViewerMember\n logoFileUrl\n darkLogoFileUrl\n nonDisclosureAgreement {\n fileName\n fileUrl\n viewerSignature {\n status\n id\n }\n }\n organization {\n name\n description\n websiteUrl\n email\n headquarterAddress\n id\n }\n ...OverviewPageFragment\n vendorInfo: vendors(first: 0) {\n totalCount\n }\n audits(first: 50) {\n edges {\n node {\n id\n ...AuditRowFragment\n }\n }\n }\n }\n}\n\nfragment AuditRowFragment on Audit {\n report {\n id\n filename\n isUserAuthorized\n hasUserRequestedAccess\n }\n framework {\n id\n name\n lightLogoURL\n darkLogoURL\n }\n}\n\nfragment DocumentRowFragment on Document {\n id\n title\n isUserAuthorized\n hasUserRequestedAccess\n}\n\nfragment OverviewPageFragment on TrustCenter {\n references(first: 14) {\n edges {\n node {\n id\n name\n logoUrl\n websiteUrl\n }\n }\n }\n vendors(first: 3) {\n edges {\n node {\n id\n countries\n ...VendorRowFragment\n }\n }\n }\n documents(first: 5) {\n edges {\n node {\n id\n ...DocumentRowFragment\n documentType\n }\n }\n }\n trustCenterFiles(first: 5) {\n edges {\n node {\n id\n category\n ...TrustCenterFileRowFragment\n }\n }\n }\n}\n\nfragment TrustCenterFileRowFragment on TrustCenterFile {\n id\n name\n isUserAuthorized\n hasUserRequestedAccess\n}\n\nfragment VendorRowFragment on Vendor {\n name\n description\n websiteUrl\n countries\n}\n" } }; })(); -(node as any).hash = "3b8d99e97c59c613f0ef2f01951a5221"; +(node as any).hash = "6cbe676214b698d12e2cae08060a7285"; export default node; diff --git a/go.mod b/go.mod index be37cf7dd..d37bd2dc4 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,6 @@ require ( github.com/elimity-com/scim v0.0.0-20240320110924-172bf2aee9c8 github.com/go-chi/chi/v5 v5.2.4 github.com/go-chi/cors v1.2.2 - github.com/google/uuid v1.6.0 github.com/jackc/pgx/v5 v5.8.0 github.com/jhillyerd/enmime v1.3.0 github.com/modelcontextprotocol/go-sdk v1.2.0 @@ -85,6 +84,7 @@ require ( github.com/google/jsonschema-go v0.4.2 // indirect github.com/google/s2a-go v0.1.9 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.9 // indirect github.com/googleapis/gax-go/v2 v2.16.0 // indirect github.com/gorilla/websocket v1.5.3 // indirect diff --git a/pkg/coredata/electronic_signature.go b/pkg/coredata/electronic_signature.go index 29e10228f..d8b46d9cd 100644 --- a/pkg/coredata/electronic_signature.go +++ b/pkg/coredata/electronic_signature.go @@ -216,58 +216,6 @@ LIMIT 1 return nil } -func (es *ElectronicSignature) LoadByOrgEmailAndDocType( - ctx context.Context, - conn pg.Conn, - scope Scoper, - orgID gid.GID, - email string, - docType ElectronicSignatureDocumentType, - fileID gid.GID, -) error { - q := ` -SELECT - id, tenant_id, organization_id, status, document_type, file_id, - signer_email, consent_text, signer_full_name, signer_ip_address, - signer_user_agent, file_hash, seal, seal_version, tsa_token, signed_at, - certificate_file_id, certificate_processing_started_at, - attempt_count, max_attempts, last_attempted_at, last_error, - processing_started_at, created_at, updated_at -FROM electronic_signatures -WHERE %s - AND organization_id = @organization_id - AND signer_email = @signer_email - AND document_type = @document_type - AND file_id = @file_id -LIMIT 1 -` - q = fmt.Sprintf(q, scope.SQLFragment()) - - args := pgx.StrictNamedArgs{ - "organization_id": orgID, - "signer_email": email, - "document_type": docType, - "file_id": fileID, - } - maps.Copy(args, scope.SQLArguments()) - - rows, err := conn.Query(ctx, q, args) - if err != nil { - return fmt.Errorf("cannot query electronic signature: %w", err) - } - - sig, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[ElectronicSignature]) - if err != nil { - if errors.Is(err, pgx.ErrNoRows) { - return ErrResourceNotFound - } - return fmt.Errorf("cannot collect electronic signature: %w", err) - } - - *es = sig - return nil -} - func (es *ElectronicSignature) LoadNextAcceptedForUpdateSkipLocked( ctx context.Context, conn pg.Conn, diff --git a/pkg/coredata/migrations/20260220T092400Z.sql b/pkg/coredata/migrations/20260220T092400Z.sql new file mode 100644 index 000000000..42ac4a06e --- /dev/null +++ b/pkg/coredata/migrations/20260220T092400Z.sql @@ -0,0 +1,2 @@ +ALTER TABLE trust_center_accesses + ADD COLUMN electronic_signature_id TEXT REFERENCES electronic_signatures(id); \ No newline at end of file diff --git a/pkg/coredata/trust_center_access.go b/pkg/coredata/trust_center_access.go index 85300289e..515ef02ec 100644 --- a/pkg/coredata/trust_center_access.go +++ b/pkg/coredata/trust_center_access.go @@ -42,6 +42,7 @@ type ( HasAcceptedNonDisclosureAgreement bool `db:"has_accepted_non_disclosure_agreement"` HasAcceptedNonDisclosureAgreementMetadata json.RawMessage `db:"has_accepted_non_disclosure_agreement_metadata"` NDAFileID *gid.GID `db:"nda_file_id"` + ElectronicSignatureID *gid.GID `db:"electronic_signature_id"` CreatedAt time.Time `db:"created_at"` UpdatedAt time.Time `db:"updated_at"` } @@ -90,6 +91,7 @@ SELECT has_accepted_non_disclosure_agreement, has_accepted_non_disclosure_agreement_metadata, nda_file_id, + electronic_signature_id, created_at, updated_at FROM @@ -143,6 +145,7 @@ SELECT has_accepted_non_disclosure_agreement, has_accepted_non_disclosure_agreement_metadata, nda_file_id, + electronic_signature_id, created_at, updated_at FROM @@ -196,6 +199,7 @@ INSERT INTO trust_center_accesses ( name, state, has_accepted_non_disclosure_agreement, + electronic_signature_id, created_at, updated_at ) VALUES ( @@ -207,6 +211,7 @@ INSERT INTO trust_center_accesses ( @name, @state, @has_accepted_non_disclosure_agreement, + @electronic_signature_id, @created_at, @updated_at ) @@ -221,6 +226,7 @@ INSERT INTO trust_center_accesses ( "name": tca.Name, "state": tca.State, "has_accepted_non_disclosure_agreement": tca.HasAcceptedNonDisclosureAgreement, + "electronic_signature_id": tca.ElectronicSignatureID, "created_at": tca.CreatedAt, "updated_at": tca.UpdatedAt, } @@ -251,7 +257,8 @@ UPDATE trust_center_accesses SET updated_at = @updated_at, has_accepted_non_disclosure_agreement = @has_accepted_non_disclosure_agreement, has_accepted_non_disclosure_agreement_metadata = @has_accepted_non_disclosure_agreement_metadata, - nda_file_id = @nda_file_id + nda_file_id = @nda_file_id, + electronic_signature_id = @electronic_signature_id WHERE %s AND id = @id @@ -266,7 +273,8 @@ WHERE "updated_at": tca.UpdatedAt, "has_accepted_non_disclosure_agreement": tca.HasAcceptedNonDisclosureAgreement, "has_accepted_non_disclosure_agreement_metadata": tca.HasAcceptedNonDisclosureAgreementMetadata, - "nda_file_id": tca.NDAFileID, + "nda_file_id": tca.NDAFileID, + "electronic_signature_id": tca.ElectronicSignatureID, } maps.Copy(args, scope.SQLArguments()) @@ -324,6 +332,7 @@ SELECT has_accepted_non_disclosure_agreement, has_accepted_non_disclosure_agreement_metadata, nda_file_id, + electronic_signature_id, created_at, updated_at FROM diff --git a/pkg/esign/service.go b/pkg/esign/service.go index dc8294dda..577e07e7d 100644 --- a/pkg/esign/service.go +++ b/pkg/esign/service.go @@ -174,16 +174,16 @@ func (s *Service) CreateSignature( return sig, nil } -func (s *Service) AcceptSignature(ctx context.Context, req *AcceptSignatureRequest) error { +func (s *Service) AcceptSignature(ctx context.Context, req *AcceptSignatureRequest) (*coredata.ElectronicSignature, error) { var ( - scope = coredata.NewScopeFromObjectID(req.SignatureID) - now = time.Now() + scope = coredata.NewScopeFromObjectID(req.SignatureID) + now = time.Now() + signature = coredata.ElectronicSignature{} ) - return s.pg.WithTx( + err := s.pg.WithTx( ctx, func(tx pg.Conn) error { - var signature coredata.ElectronicSignature if err := signature.LoadByID(ctx, tx, scope, req.SignatureID); err != nil { return fmt.Errorf("cannot load electronic signature: %w", err) } @@ -193,7 +193,6 @@ func (s *Service) AcceptSignature(ctx context.Context, req *AcceptSignatureReque return fmt.Errorf("cannot accept electronic signature in status %s", signature.Status) } - // If retrying from FAILED, reset attempt tracking. if signature.Status == coredata.ElectronicSignatureStatusFailed { signature.AttemptCount = 0 signature.LastError = nil @@ -210,7 +209,7 @@ func (s *Service) AcceptSignature(ctx context.Context, req *AcceptSignatureReque return fmt.Errorf("cannot update signature: %w", err) } - s.recordEvent( + if err := s.recordEvent( ctx, tx, &RecordEventRequest{ @@ -221,11 +220,18 @@ func (s *Service) AcceptSignature(ctx context.Context, req *AcceptSignatureReque ActorIPAddr: req.SignerIPAddr, ActorUA: req.SignerUA, }, - ) + ); err != nil { + return fmt.Errorf("cannot record event: %w", err) + } return nil }, ) + if err != nil { + return nil, err + } + + return &signature, nil } func (s *Service) RecordEvent(ctx context.Context, req *RecordEventRequest) error { @@ -262,7 +268,7 @@ func (s *Service) recordEvent(ctx context.Context, tx pg.Conn, req *RecordEventR return nil } -func (s *Service) LoadSignatureByID(ctx context.Context, id gid.GID) (*coredata.ElectronicSignature, error) { +func (s *Service) GetSignatureByID(ctx context.Context, id gid.GID) (*coredata.ElectronicSignature, error) { var ( scope = coredata.NewScopeFromObjectID(id) signature = coredata.ElectronicSignature{} @@ -285,36 +291,28 @@ func (s *Service) LoadSignatureByID(ctx context.Context, id gid.GID) (*coredata. return &signature, nil } -func (s *Service) LoadSignatureByOrgEmailAndDocType( - ctx context.Context, - orgID gid.GID, - email string, - docType coredata.ElectronicSignatureDocumentType, - fileID gid.GID, -) (*coredata.ElectronicSignature, error) { - scope := coredata.NewScopeFromObjectID(orgID) - var sig coredata.ElectronicSignature - err := s.pg.WithConn(ctx, func(conn pg.Conn) error { - return sig.LoadByOrgEmailAndDocType(ctx, conn, scope, orgID, email, docType, fileID) - }) - if err != nil { - return nil, err - } - return &sig, nil -} - func (s *Service) GenerateCertificateFileURL( ctx context.Context, certificateFileID gid.GID, expiresIn time.Duration, ) (string, error) { - scope := coredata.NewScopeFromObjectID(certificateFileID) - var file coredata.File - err := s.pg.WithConn(ctx, func(conn pg.Conn) error { - return file.LoadByID(ctx, conn, scope, certificateFileID) - }) + var ( + scope = coredata.NewScopeFromObjectID(certificateFileID) + file = coredata.File{} + ) + + err := s.pg.WithConn( + ctx, + func(conn pg.Conn) error { + if err := file.LoadByID(ctx, conn, scope, certificateFileID); err != nil { + return fmt.Errorf("cannot load certificate file: %w", err) + } + + return nil + }, + ) if err != nil { - return "", fmt.Errorf("cannot load certificate file: %w", err) + return "", err } url, err := s.fileManager.GenerateFileUrl(ctx, &file, expiresIn) @@ -325,7 +323,7 @@ func (s *Service) GenerateCertificateFileURL( return url, nil } -func (s *Service) LoadEventsBySignatureID( +func (s *Service) GetEventsBySignatureID( ctx context.Context, signatureID gid.GID, ) (coredata.ElectronicSignatureEvents, error) { diff --git a/pkg/esign/tsa.go b/pkg/esign/tsa.go index 0cce04e0d..f38deaea0 100644 --- a/pkg/esign/tsa.go +++ b/pkg/esign/tsa.go @@ -63,7 +63,7 @@ func (c *TSAClient) Timestamp(ctx context.Context, data []byte) ([]byte, error) if err != nil { return nil, fmt.Errorf("esign: TSA request failed: %w", err) } - defer resp.Body.Close() + defer func() { _ = resp.Body.Close() }() if resp.StatusCode != http.StatusOK { return nil, fmt.Errorf("esign: TSA returned HTTP %d", resp.StatusCode) diff --git a/pkg/probo/trust_center_access_service.go b/pkg/probo/trust_center_access_service.go index 288f1d050..90b4f1504 100644 --- a/pkg/probo/trust_center_access_service.go +++ b/pkg/probo/trust_center_access_service.go @@ -250,12 +250,8 @@ func (s TrustCenterAccessService) Create( UpdatedAt: now, } - if err := access.Insert(ctx, tx, s.svc.scope); err != nil { - return fmt.Errorf("cannot insert trust center access: %w", err) - } - if trustCenter.NonDisclosureAgreementFileID != nil && s.svc.esign != nil { - _, err := s.svc.esign.CreateSignature( + sig, err := s.svc.esign.CreateSignature( ctx, tx, &esign.CreateSignatureRequest{ @@ -265,10 +261,14 @@ func (s TrustCenterAccessService) Create( SignerEmail: access.Email, }, ) - if err != nil { return fmt.Errorf("cannot create pending signature: %w", err) } + access.ElectronicSignatureID = &sig.ID + } + + if err := access.Insert(ctx, tx, s.svc.scope); err != nil { + return fmt.Errorf("cannot insert trust center access: %w", err) } return nil diff --git a/pkg/probo/trust_center_service.go b/pkg/probo/trust_center_service.go index 994068aaf..515bca891 100644 --- a/pkg/probo/trust_center_service.go +++ b/pkg/probo/trust_center_service.go @@ -107,9 +107,8 @@ func (req *UpdateTrustCenterBrandRequest) Validate() error { func (s TrustCenterService) Get( ctx context.Context, trustCenterID gid.GID, -) (*coredata.TrustCenter, *coredata.File, error) { +) (*coredata.TrustCenter, error) { var trustCenter *coredata.TrustCenter - var file *coredata.File err := s.svc.pg.WithConn( ctx, @@ -119,30 +118,22 @@ func (s TrustCenterService) Get( return fmt.Errorf("cannot load trust center: %w", err) } - if trustCenter.NonDisclosureAgreementFileID != nil { - file = &coredata.File{} - if err := file.LoadByID(ctx, conn, s.svc.scope, *trustCenter.NonDisclosureAgreementFileID); err != nil { - return fmt.Errorf("cannot load file: %w", err) - } - } - return nil }, ) if err != nil { - return nil, nil, fmt.Errorf("cannot load trust center: %w", err) + return nil, fmt.Errorf("cannot load trust center: %w", err) } - return trustCenter, file, nil + return trustCenter, nil } func (s TrustCenterService) GetByOrganizationID( ctx context.Context, organizationID gid.GID, -) (*coredata.TrustCenter, *coredata.File, error) { +) (*coredata.TrustCenter, error) { var trustCenter *coredata.TrustCenter - var file *coredata.File err := s.svc.pg.WithConn( ctx, @@ -152,22 +143,15 @@ func (s TrustCenterService) GetByOrganizationID( return fmt.Errorf("cannot load trust center: %w", err) } - if trustCenter.NonDisclosureAgreementFileID != nil { - file = &coredata.File{} - if err := file.LoadByID(ctx, conn, s.svc.scope, *trustCenter.NonDisclosureAgreementFileID); err != nil { - return fmt.Errorf("cannot load file: %w", err) - } - } - return nil }, ) if err != nil { - return nil, nil, err + return nil, err } - return trustCenter, file, nil + return trustCenter, nil } func (s TrustCenterService) Update( diff --git a/pkg/server/api/console/v1/v1_resolver.go b/pkg/server/api/console/v1/v1_resolver.go index d5806000f..d89b0c7a6 100644 --- a/pkg/server/api/console/v1/v1_resolver.go +++ b/pkg/server/api/console/v1/v1_resolver.go @@ -1243,7 +1243,7 @@ func (r *documentVersionSignatureConnectionResolver) TotalCount(ctx context.Cont // CertificateFileURL is the resolver for the certificateFileUrl field. func (r *electronicSignatureResolver) CertificateFileURL(ctx context.Context, obj *types.ElectronicSignature) (*string, error) { - sig, err := r.esign.LoadSignatureByID(ctx, obj.ID) + sig, err := r.esign.GetSignatureByID(ctx, obj.ID) if err != nil { return nil, fmt.Errorf("cannot load signature: %w", err) } @@ -1262,7 +1262,7 @@ func (r *electronicSignatureResolver) CertificateFileURL(ctx context.Context, ob // Events is the resolver for the events field. func (r *electronicSignatureResolver) Events(ctx context.Context, obj *types.ElectronicSignature) ([]*types.ElectronicSignatureEvent, error) { - events, err := r.esign.LoadEventsBySignatureID(ctx, obj.ID) + events, err := r.esign.GetEventsBySignatureID(ctx, obj.ID) if err != nil { return nil, fmt.Errorf("cannot load signature events: %w", err) } @@ -6394,13 +6394,13 @@ func (r *organizationResolver) TrustCenter(ctx context.Context, obj *types.Organ prb := r.ProboService(ctx, obj.ID.TenantID()) - trustCenter, file, err := prb.TrustCenters.GetByOrganizationID(ctx, obj.ID) + trustCenter, err := prb.TrustCenters.GetByOrganizationID(ctx, obj.ID) if err != nil { // TODO no panic use gqlutils.InternalError panic(fmt.Errorf("cannot get trust center: %w", err)) } - return types.NewTrustCenter(trustCenter, file), nil + return types.NewTrustCenter(trustCenter, nil), nil } // CustomDomain is the resolver for the customDomain field. @@ -6874,11 +6874,11 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error case coredata.TrustCenterEntityType: action = probo.ActionTrustCenterGet loadNode = func(ctx context.Context, id gid.GID) (types.Node, error) { - trustCenter, file, err := prb.TrustCenters.Get(ctx, id) + trustCenter, err := prb.TrustCenters.Get(ctx, id) if err != nil { return nil, err } - return types.NewTrustCenter(trustCenter, file), nil + return types.NewTrustCenter(trustCenter, nil), nil } case coredata.TrustCenterAccessEntityType: action = probo.ActionTrustCenterAccessGet @@ -7739,7 +7739,7 @@ func (r *trustCenterResolver) Organization(ctx context.Context, obj *types.Trust prb := r.ProboService(ctx, obj.ID.TenantID()) - trustCenter, _, err := prb.TrustCenters.Get(ctx, obj.ID) + trustCenter, err := prb.TrustCenters.Get(ctx, obj.ID) if err != nil { panic(fmt.Errorf("cannot get trust center: %w", err)) } @@ -7832,24 +7832,13 @@ func (r *trustCenterAccessResolver) NdaSignature(ctx context.Context, obj *types return nil, fmt.Errorf("cannot load trust center access: %w", err) } - trustCenter, _, err := prb.TrustCenters.Get(ctx, access.TrustCenterID) - if err != nil { - return nil, fmt.Errorf("cannot load trust center: %w", err) - } - - if trustCenter.NonDisclosureAgreementFileID == nil { + if access.ElectronicSignatureID == nil { return nil, nil } - sig, err := r.esign.LoadSignatureByOrgEmailAndDocType( - ctx, - access.OrganizationID, - string(access.Email), - coredata.ElectronicSignatureDocumentTypeNDA, - *trustCenter.NonDisclosureAgreementFileID, - ) + sig, err := r.esign.GetSignatureByID(ctx, *access.ElectronicSignatureID) if err != nil { - return nil, nil // No signature row — pre-existing access + return nil, nil } return types.NewElectronicSignature(sig), nil diff --git a/pkg/server/api/trust/v1/schema.graphql b/pkg/server/api/trust/v1/schema.graphql index 70904cca0..25c1dd709 100644 --- a/pkg/server/api/trust/v1/schema.graphql +++ b/pkg/server/api/trust/v1/schema.graphql @@ -488,18 +488,23 @@ type TrustCenterFileEdge { node: TrustCenterFile! } +type NonDisclosureAgreement { + fileName: String! + fileUrl: String! @goField(forceResolver: true) + viewerSignature: ElectronicSignature @goField(forceResolver: true) +} + type TrustCenter implements Node { id: ID! active: Boolean! slug: String! logoFileUrl: String @goField(forceResolver: true) darkLogoFileUrl: String @goField(forceResolver: true) - ndaFileName: String - ndaFileUrl: String @goField(forceResolver: true) - ndaSignature: ElectronicSignature @goField(forceResolver: true) - organization: Organization! @goField(forceResolver: true) + + nonDisclosureAgreement: NonDisclosureAgreement @goField(forceResolver: true) + isViewerMember: Boolean! @goField(forceResolver: true) - hasAcceptedNonDisclosureAgreement: Boolean! @goField(forceResolver: true) + organization: Organization! @goField(forceResolver: true) documents( first: Int @@ -601,14 +606,6 @@ type ExportTrustCenterFilePayload { data: String! } -input AcceptNonDisclosureAgreementInput { - fullName: String! -} - -type AcceptNonDisclosureAgreementPayload { - success: Boolean! -} - # Electronic Signature enum ElectronicSignatureStatus @@ -770,11 +767,7 @@ type Mutation { input: ExportTrustCenterFileInput! ): ExportTrustCenterFilePayload! @session(required: OPTIONAL) - acceptNonDisclosureAgreement( - input: AcceptNonDisclosureAgreementInput! - ): AcceptNonDisclosureAgreementPayload @session(required: PRESENT) - - requestDocumentAccess( + requestDocumentAccess( input: RequestDocumentAccessInput! ): RequestAccessesPayload! @session(required: PRESENT) diff --git a/pkg/server/api/trust/v1/schema/schema.go b/pkg/server/api/trust/v1/schema/schema.go index bd9f590c6..c362d43e9 100644 --- a/pkg/server/api/trust/v1/schema/schema.go +++ b/pkg/server/api/trust/v1/schema/schema.go @@ -51,6 +51,7 @@ type ResolverRoot interface { Document() DocumentResolver Framework() FrameworkResolver Mutation() MutationResolver + NonDisclosureAgreement() NonDisclosureAgreementResolver Organization() OrganizationResolver Query() QueryResolver Report() ReportResolver @@ -69,10 +70,6 @@ type ComplexityRoot struct { Signature func(childComplexity int) int } - AcceptNonDisclosureAgreementPayload struct { - Success func(childComplexity int) int - } - Audit struct { Framework func(childComplexity int) int ID func(childComplexity int) int @@ -148,7 +145,6 @@ type ComplexityRoot struct { Mutation struct { AcceptElectronicSignature func(childComplexity int, input types.AcceptElectronicSignatureInput) int - AcceptNonDisclosureAgreement func(childComplexity int, input types.AcceptNonDisclosureAgreementInput) int ExportDocumentPDF func(childComplexity int, input types.ExportDocumentPDFInput) int ExportReportPDF func(childComplexity int, input types.ExportReportPDFInput) int ExportTrustCenterFile func(childComplexity int, input types.ExportTrustCenterFileInput) int @@ -161,6 +157,12 @@ type ComplexityRoot struct { VerifyMagicLink func(childComplexity int, input types.VerifyMagicLinkInput) int } + NonDisclosureAgreement struct { + FileName func(childComplexity int) int + FileURL func(childComplexity int) int + ViewerSignature func(childComplexity int) int + } + Organization struct { Description func(childComplexity int) int Email func(childComplexity int) int @@ -204,22 +206,19 @@ type ComplexityRoot struct { } TrustCenter struct { - Active func(childComplexity int) int - Audits func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey) int - DarkLogoFileURL func(childComplexity int) int - Documents func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey) int - HasAcceptedNonDisclosureAgreement func(childComplexity int) int - ID func(childComplexity int) int - IsViewerMember func(childComplexity int) int - LogoFileURL func(childComplexity int) int - NdaFileName func(childComplexity int) int - NdaFileURL func(childComplexity int) int - NdaSignature func(childComplexity int) int - Organization func(childComplexity int) int - References func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey) int - Slug func(childComplexity int) int - TrustCenterFiles func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey) int - Vendors func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey) int + Active func(childComplexity int) int + Audits func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey) int + DarkLogoFileURL func(childComplexity int) int + Documents func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey) int + ID func(childComplexity int) int + IsViewerMember func(childComplexity int) int + LogoFileURL func(childComplexity int) int + NonDisclosureAgreement func(childComplexity int) int + Organization func(childComplexity int) int + References func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey) int + Slug func(childComplexity int) int + TrustCenterFiles func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey) int + Vendors func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey) int } TrustCenterAccess struct { @@ -311,13 +310,16 @@ type MutationResolver interface { ExportDocumentPDF(ctx context.Context, input types.ExportDocumentPDFInput) (*types.ExportDocumentPDFPayload, error) ExportReportPDF(ctx context.Context, input types.ExportReportPDFInput) (*types.ExportReportPDFPayload, error) ExportTrustCenterFile(ctx context.Context, input types.ExportTrustCenterFileInput) (*types.ExportTrustCenterFilePayload, error) - AcceptNonDisclosureAgreement(ctx context.Context, input types.AcceptNonDisclosureAgreementInput) (*types.AcceptNonDisclosureAgreementPayload, error) RequestDocumentAccess(ctx context.Context, input types.RequestDocumentAccessInput) (*types.RequestAccessesPayload, error) RequestReportAccess(ctx context.Context, input types.RequestReportAccessInput) (*types.RequestAccessesPayload, error) RequestTrustCenterFileAccess(ctx context.Context, input types.RequestTrustCenterFileAccessInput) (*types.RequestAccessesPayload, error) AcceptElectronicSignature(ctx context.Context, input types.AcceptElectronicSignatureInput) (*types.AcceptElectronicSignaturePayload, error) RecordSigningEvent(ctx context.Context, input types.RecordSigningEventInput) (*types.RecordSigningEventPayload, error) } +type NonDisclosureAgreementResolver interface { + FileURL(ctx context.Context, obj *types.NonDisclosureAgreement) (string, error) + ViewerSignature(ctx context.Context, obj *types.NonDisclosureAgreement) (*types.ElectronicSignature, error) +} type OrganizationResolver interface { LogoURL(ctx context.Context, obj *types.Organization) (*string, error) } @@ -333,12 +335,9 @@ type ReportResolver interface { type TrustCenterResolver interface { LogoFileURL(ctx context.Context, obj *types.TrustCenter) (*string, error) DarkLogoFileURL(ctx context.Context, obj *types.TrustCenter) (*string, error) - - NdaFileURL(ctx context.Context, obj *types.TrustCenter) (*string, error) - NdaSignature(ctx context.Context, obj *types.TrustCenter) (*types.ElectronicSignature, error) - Organization(ctx context.Context, obj *types.TrustCenter) (*types.Organization, error) + NonDisclosureAgreement(ctx context.Context, obj *types.TrustCenter) (*types.NonDisclosureAgreement, error) IsViewerMember(ctx context.Context, obj *types.TrustCenter) (bool, error) - HasAcceptedNonDisclosureAgreement(ctx context.Context, obj *types.TrustCenter) (bool, error) + Organization(ctx context.Context, obj *types.TrustCenter) (*types.Organization, error) Documents(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.DocumentConnection, error) Audits(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.AuditConnection, error) Vendors(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.VendorConnection, error) @@ -382,13 +381,6 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin return e.complexity.AcceptElectronicSignaturePayload.Signature(childComplexity), true - case "AcceptNonDisclosureAgreementPayload.success": - if e.complexity.AcceptNonDisclosureAgreementPayload.Success == nil { - break - } - - return e.complexity.AcceptNonDisclosureAgreementPayload.Success(childComplexity), true - case "Audit.framework": if e.complexity.Audit.Framework == nil { break @@ -634,17 +626,6 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin } return e.complexity.Mutation.AcceptElectronicSignature(childComplexity, args["input"].(types.AcceptElectronicSignatureInput)), true - case "Mutation.acceptNonDisclosureAgreement": - if e.complexity.Mutation.AcceptNonDisclosureAgreement == nil { - break - } - - args, err := ec.field_Mutation_acceptNonDisclosureAgreement_args(ctx, rawArgs) - if err != nil { - return 0, false - } - - return e.complexity.Mutation.AcceptNonDisclosureAgreement(childComplexity, args["input"].(types.AcceptNonDisclosureAgreementInput)), true case "Mutation.exportDocumentPDF": if e.complexity.Mutation.ExportDocumentPDF == nil { break @@ -751,6 +732,25 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin return e.complexity.Mutation.VerifyMagicLink(childComplexity, args["input"].(types.VerifyMagicLinkInput)), true + case "NonDisclosureAgreement.fileName": + if e.complexity.NonDisclosureAgreement.FileName == nil { + break + } + + return e.complexity.NonDisclosureAgreement.FileName(childComplexity), true + case "NonDisclosureAgreement.fileUrl": + if e.complexity.NonDisclosureAgreement.FileURL == nil { + break + } + + return e.complexity.NonDisclosureAgreement.FileURL(childComplexity), true + case "NonDisclosureAgreement.viewerSignature": + if e.complexity.NonDisclosureAgreement.ViewerSignature == nil { + break + } + + return e.complexity.NonDisclosureAgreement.ViewerSignature(childComplexity), true + case "Organization.description": if e.complexity.Organization.Description == nil { break @@ -923,12 +923,6 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin } return e.complexity.TrustCenter.Documents(childComplexity, args["first"].(*int), args["after"].(*page.CursorKey), args["last"].(*int), args["before"].(*page.CursorKey)), true - case "TrustCenter.hasAcceptedNonDisclosureAgreement": - if e.complexity.TrustCenter.HasAcceptedNonDisclosureAgreement == nil { - break - } - - return e.complexity.TrustCenter.HasAcceptedNonDisclosureAgreement(childComplexity), true case "TrustCenter.id": if e.complexity.TrustCenter.ID == nil { break @@ -947,24 +941,12 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin } return e.complexity.TrustCenter.LogoFileURL(childComplexity), true - case "TrustCenter.ndaFileName": - if e.complexity.TrustCenter.NdaFileName == nil { + case "TrustCenter.nonDisclosureAgreement": + if e.complexity.TrustCenter.NonDisclosureAgreement == nil { break } - return e.complexity.TrustCenter.NdaFileName(childComplexity), true - case "TrustCenter.ndaFileUrl": - if e.complexity.TrustCenter.NdaFileURL == nil { - break - } - - return e.complexity.TrustCenter.NdaFileURL(childComplexity), true - case "TrustCenter.ndaSignature": - if e.complexity.TrustCenter.NdaSignature == nil { - break - } - - return e.complexity.TrustCenter.NdaSignature(childComplexity), true + return e.complexity.TrustCenter.NonDisclosureAgreement(childComplexity), true case "TrustCenter.organization": if e.complexity.TrustCenter.Organization == nil { break @@ -1247,7 +1229,6 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { ec := executionContext{opCtx, e, 0, 0, make(chan graphql.DeferredResult)} inputUnmarshalMap := graphql.BuildUnmarshalerMap( ec.unmarshalInputAcceptElectronicSignatureInput, - ec.unmarshalInputAcceptNonDisclosureAgreementInput, ec.unmarshalInputExportDocumentPDFInput, ec.unmarshalInputExportReportPDFInput, ec.unmarshalInputExportTrustCenterFileInput, @@ -1844,18 +1825,23 @@ type TrustCenterFileEdge { node: TrustCenterFile! } +type NonDisclosureAgreement { + fileName: String! + fileUrl: String! @goField(forceResolver: true) + viewerSignature: ElectronicSignature @goField(forceResolver: true) +} + type TrustCenter implements Node { id: ID! active: Boolean! slug: String! logoFileUrl: String @goField(forceResolver: true) darkLogoFileUrl: String @goField(forceResolver: true) - ndaFileName: String - ndaFileUrl: String @goField(forceResolver: true) - ndaSignature: ElectronicSignature @goField(forceResolver: true) - organization: Organization! @goField(forceResolver: true) + + nonDisclosureAgreement: NonDisclosureAgreement @goField(forceResolver: true) + isViewerMember: Boolean! @goField(forceResolver: true) - hasAcceptedNonDisclosureAgreement: Boolean! @goField(forceResolver: true) + organization: Organization! @goField(forceResolver: true) documents( first: Int @@ -1957,14 +1943,6 @@ type ExportTrustCenterFilePayload { data: String! } -input AcceptNonDisclosureAgreementInput { - fullName: String! -} - -type AcceptNonDisclosureAgreementPayload { - success: Boolean! -} - # Electronic Signature enum ElectronicSignatureStatus @@ -2126,11 +2104,7 @@ type Mutation { input: ExportTrustCenterFileInput! ): ExportTrustCenterFilePayload! @session(required: OPTIONAL) - acceptNonDisclosureAgreement( - input: AcceptNonDisclosureAgreementInput! - ): AcceptNonDisclosureAgreementPayload @session(required: PRESENT) - - requestDocumentAccess( + requestDocumentAccess( input: RequestDocumentAccessInput! ): RequestAccessesPayload! @session(required: PRESENT) @@ -2219,17 +2193,6 @@ func (ec *executionContext) field_Mutation_acceptElectronicSignature_args(ctx co return args, nil } -func (ec *executionContext) field_Mutation_acceptNonDisclosureAgreement_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { - var err error - args := map[string]any{} - arg0, err := graphql.ProcessArgField(ctx, rawArgs, "input", ec.unmarshalNAcceptNonDisclosureAgreementInput2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐAcceptNonDisclosureAgreementInput) - if err != nil { - return nil, err - } - args["input"] = arg0 - return args, nil -} - func (ec *executionContext) field_Mutation_exportDocumentPDF_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} @@ -2580,35 +2543,6 @@ func (ec *executionContext) fieldContext_AcceptElectronicSignaturePayload_signat return fc, nil } -func (ec *executionContext) _AcceptNonDisclosureAgreementPayload_success(ctx context.Context, field graphql.CollectedField, obj *types.AcceptNonDisclosureAgreementPayload) (ret graphql.Marshaler) { - return graphql.ResolveField( - ctx, - ec.OperationContext, - field, - ec.fieldContext_AcceptNonDisclosureAgreementPayload_success, - func(ctx context.Context) (any, error) { - return obj.Success, nil - }, - nil, - ec.marshalNBoolean2bool, - true, - true, - ) -} - -func (ec *executionContext) fieldContext_AcceptNonDisclosureAgreementPayload_success(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "AcceptNonDisclosureAgreementPayload", - Field: field, - IsMethod: false, - IsResolver: false, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Boolean does not have child fields") - }, - } - return fc, nil -} - func (ec *executionContext) _Audit_id(ctx context.Context, field graphql.CollectedField, obj *types.Audit) (ret graphql.Marshaler) { return graphql.ResolveField( ctx, @@ -4120,69 +4054,6 @@ func (ec *executionContext) fieldContext_Mutation_exportTrustCenterFile(ctx cont return fc, nil } -func (ec *executionContext) _Mutation_acceptNonDisclosureAgreement(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - return graphql.ResolveField( - ctx, - ec.OperationContext, - field, - ec.fieldContext_Mutation_acceptNonDisclosureAgreement, - func(ctx context.Context) (any, error) { - fc := graphql.GetFieldContext(ctx) - return ec.resolvers.Mutation().AcceptNonDisclosureAgreement(ctx, fc.Args["input"].(types.AcceptNonDisclosureAgreementInput)) - }, - func(ctx context.Context, next graphql.Resolver) graphql.Resolver { - directive0 := next - - directive1 := func(ctx context.Context) (any, error) { - required, err := ec.unmarshalNSessionRequirement2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋgqlutilsᚋdirectivesᚋsessionᚐSessionRequirement(ctx, "PRESENT") - if err != nil { - var zeroVal *types.AcceptNonDisclosureAgreementPayload - return zeroVal, err - } - if ec.directives.Session == nil { - var zeroVal *types.AcceptNonDisclosureAgreementPayload - return zeroVal, errors.New("directive session is not implemented") - } - return ec.directives.Session(ctx, nil, directive0, required) - } - - next = directive1 - return next - }, - ec.marshalOAcceptNonDisclosureAgreementPayload2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐAcceptNonDisclosureAgreementPayload, - true, - false, - ) -} - -func (ec *executionContext) fieldContext_Mutation_acceptNonDisclosureAgreement(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "Mutation", - Field: field, - IsMethod: true, - IsResolver: true, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "success": - return ec.fieldContext_AcceptNonDisclosureAgreementPayload_success(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type AcceptNonDisclosureAgreementPayload", field.Name) - }, - } - defer func() { - if r := recover(); r != nil { - err = ec.Recover(ctx, r) - ec.Error(ctx, err) - } - }() - ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Mutation_acceptNonDisclosureAgreement_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { - ec.Error(ctx, err) - return fc, err - } - return fc, nil -} - func (ec *executionContext) _Mutation_requestDocumentAccess(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { return graphql.ResolveField( ctx, @@ -4498,6 +4369,111 @@ func (ec *executionContext) fieldContext_Mutation_recordSigningEvent(ctx context return fc, nil } +func (ec *executionContext) _NonDisclosureAgreement_fileName(ctx context.Context, field graphql.CollectedField, obj *types.NonDisclosureAgreement) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + ec.fieldContext_NonDisclosureAgreement_fileName, + func(ctx context.Context) (any, error) { + return obj.FileName, nil + }, + nil, + ec.marshalNString2string, + true, + true, + ) +} + +func (ec *executionContext) fieldContext_NonDisclosureAgreement_fileName(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "NonDisclosureAgreement", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _NonDisclosureAgreement_fileUrl(ctx context.Context, field graphql.CollectedField, obj *types.NonDisclosureAgreement) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + ec.fieldContext_NonDisclosureAgreement_fileUrl, + func(ctx context.Context) (any, error) { + return ec.resolvers.NonDisclosureAgreement().FileURL(ctx, obj) + }, + nil, + ec.marshalNString2string, + true, + true, + ) +} + +func (ec *executionContext) fieldContext_NonDisclosureAgreement_fileUrl(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "NonDisclosureAgreement", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _NonDisclosureAgreement_viewerSignature(ctx context.Context, field graphql.CollectedField, obj *types.NonDisclosureAgreement) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + ec.fieldContext_NonDisclosureAgreement_viewerSignature, + func(ctx context.Context) (any, error) { + return ec.resolvers.NonDisclosureAgreement().ViewerSignature(ctx, obj) + }, + nil, + ec.marshalOElectronicSignature2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐElectronicSignature, + true, + false, + ) +} + +func (ec *executionContext) fieldContext_NonDisclosureAgreement_viewerSignature(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "NonDisclosureAgreement", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "id": + return ec.fieldContext_ElectronicSignature_id(ctx, field) + case "status": + return ec.fieldContext_ElectronicSignature_status(ctx, field) + case "documentType": + return ec.fieldContext_ElectronicSignature_documentType(ctx, field) + case "consentText": + return ec.fieldContext_ElectronicSignature_consentText(ctx, field) + case "lastError": + return ec.fieldContext_ElectronicSignature_lastError(ctx, field) + case "signedAt": + return ec.fieldContext_ElectronicSignature_signedAt(ctx, field) + case "createdAt": + return ec.fieldContext_ElectronicSignature_createdAt(ctx, field) + case "updatedAt": + return ec.fieldContext_ElectronicSignature_updatedAt(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type ElectronicSignature", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _Organization_id(ctx context.Context, field graphql.CollectedField, obj *types.Organization) (ret graphql.Marshaler) { return graphql.ResolveField( ctx, @@ -4935,18 +4911,12 @@ func (ec *executionContext) fieldContext_Query_currentTrustCenter(_ context.Cont return ec.fieldContext_TrustCenter_logoFileUrl(ctx, field) case "darkLogoFileUrl": return ec.fieldContext_TrustCenter_darkLogoFileUrl(ctx, field) - case "ndaFileName": - return ec.fieldContext_TrustCenter_ndaFileName(ctx, field) - case "ndaFileUrl": - return ec.fieldContext_TrustCenter_ndaFileUrl(ctx, field) - case "ndaSignature": - return ec.fieldContext_TrustCenter_ndaSignature(ctx, field) - case "organization": - return ec.fieldContext_TrustCenter_organization(ctx, field) + case "nonDisclosureAgreement": + return ec.fieldContext_TrustCenter_nonDisclosureAgreement(ctx, field) case "isViewerMember": return ec.fieldContext_TrustCenter_isViewerMember(ctx, field) - case "hasAcceptedNonDisclosureAgreement": - return ec.fieldContext_TrustCenter_hasAcceptedNonDisclosureAgreement(ctx, field) + case "organization": + return ec.fieldContext_TrustCenter_organization(ctx, field) case "documents": return ec.fieldContext_TrustCenter_documents(ctx, field) case "audits": @@ -5432,81 +5402,23 @@ func (ec *executionContext) fieldContext_TrustCenter_darkLogoFileUrl(_ context.C return fc, nil } -func (ec *executionContext) _TrustCenter_ndaFileName(ctx context.Context, field graphql.CollectedField, obj *types.TrustCenter) (ret graphql.Marshaler) { +func (ec *executionContext) _TrustCenter_nonDisclosureAgreement(ctx context.Context, field graphql.CollectedField, obj *types.TrustCenter) (ret graphql.Marshaler) { return graphql.ResolveField( ctx, ec.OperationContext, field, - ec.fieldContext_TrustCenter_ndaFileName, + ec.fieldContext_TrustCenter_nonDisclosureAgreement, func(ctx context.Context) (any, error) { - return obj.NdaFileName, nil + return ec.resolvers.TrustCenter().NonDisclosureAgreement(ctx, obj) }, nil, - ec.marshalOString2ᚖstring, + ec.marshalONonDisclosureAgreement2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐNonDisclosureAgreement, true, false, ) } -func (ec *executionContext) fieldContext_TrustCenter_ndaFileName(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "TrustCenter", - Field: field, - IsMethod: false, - IsResolver: false, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") - }, - } - return fc, nil -} - -func (ec *executionContext) _TrustCenter_ndaFileUrl(ctx context.Context, field graphql.CollectedField, obj *types.TrustCenter) (ret graphql.Marshaler) { - return graphql.ResolveField( - ctx, - ec.OperationContext, - field, - ec.fieldContext_TrustCenter_ndaFileUrl, - func(ctx context.Context) (any, error) { - return ec.resolvers.TrustCenter().NdaFileURL(ctx, obj) - }, - nil, - ec.marshalOString2ᚖstring, - true, - false, - ) -} - -func (ec *executionContext) fieldContext_TrustCenter_ndaFileUrl(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "TrustCenter", - Field: field, - IsMethod: true, - IsResolver: true, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") - }, - } - return fc, nil -} - -func (ec *executionContext) _TrustCenter_ndaSignature(ctx context.Context, field graphql.CollectedField, obj *types.TrustCenter) (ret graphql.Marshaler) { - return graphql.ResolveField( - ctx, - ec.OperationContext, - field, - ec.fieldContext_TrustCenter_ndaSignature, - func(ctx context.Context) (any, error) { - return ec.resolvers.TrustCenter().NdaSignature(ctx, obj) - }, - nil, - ec.marshalOElectronicSignature2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐElectronicSignature, - true, - false, - ) -} - -func (ec *executionContext) fieldContext_TrustCenter_ndaSignature(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_TrustCenter_nonDisclosureAgreement(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "TrustCenter", Field: field, @@ -5514,24 +5426,43 @@ func (ec *executionContext) fieldContext_TrustCenter_ndaSignature(_ context.Cont IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "id": - return ec.fieldContext_ElectronicSignature_id(ctx, field) - case "status": - return ec.fieldContext_ElectronicSignature_status(ctx, field) - case "documentType": - return ec.fieldContext_ElectronicSignature_documentType(ctx, field) - case "consentText": - return ec.fieldContext_ElectronicSignature_consentText(ctx, field) - case "lastError": - return ec.fieldContext_ElectronicSignature_lastError(ctx, field) - case "signedAt": - return ec.fieldContext_ElectronicSignature_signedAt(ctx, field) - case "createdAt": - return ec.fieldContext_ElectronicSignature_createdAt(ctx, field) - case "updatedAt": - return ec.fieldContext_ElectronicSignature_updatedAt(ctx, field) + case "fileName": + return ec.fieldContext_NonDisclosureAgreement_fileName(ctx, field) + case "fileUrl": + return ec.fieldContext_NonDisclosureAgreement_fileUrl(ctx, field) + case "viewerSignature": + return ec.fieldContext_NonDisclosureAgreement_viewerSignature(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type ElectronicSignature", field.Name) + return nil, fmt.Errorf("no field named %q was found under type NonDisclosureAgreement", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _TrustCenter_isViewerMember(ctx context.Context, field graphql.CollectedField, obj *types.TrustCenter) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + ec.fieldContext_TrustCenter_isViewerMember, + func(ctx context.Context) (any, error) { + return ec.resolvers.TrustCenter().IsViewerMember(ctx, obj) + }, + nil, + ec.marshalNBoolean2bool, + true, + true, + ) +} + +func (ec *executionContext) fieldContext_TrustCenter_isViewerMember(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "TrustCenter", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") }, } return fc, nil @@ -5582,64 +5513,6 @@ func (ec *executionContext) fieldContext_TrustCenter_organization(_ context.Cont return fc, nil } -func (ec *executionContext) _TrustCenter_isViewerMember(ctx context.Context, field graphql.CollectedField, obj *types.TrustCenter) (ret graphql.Marshaler) { - return graphql.ResolveField( - ctx, - ec.OperationContext, - field, - ec.fieldContext_TrustCenter_isViewerMember, - func(ctx context.Context) (any, error) { - return ec.resolvers.TrustCenter().IsViewerMember(ctx, obj) - }, - nil, - ec.marshalNBoolean2bool, - true, - true, - ) -} - -func (ec *executionContext) fieldContext_TrustCenter_isViewerMember(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "TrustCenter", - Field: field, - IsMethod: true, - IsResolver: true, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Boolean does not have child fields") - }, - } - return fc, nil -} - -func (ec *executionContext) _TrustCenter_hasAcceptedNonDisclosureAgreement(ctx context.Context, field graphql.CollectedField, obj *types.TrustCenter) (ret graphql.Marshaler) { - return graphql.ResolveField( - ctx, - ec.OperationContext, - field, - ec.fieldContext_TrustCenter_hasAcceptedNonDisclosureAgreement, - func(ctx context.Context) (any, error) { - return ec.resolvers.TrustCenter().HasAcceptedNonDisclosureAgreement(ctx, obj) - }, - nil, - ec.marshalNBoolean2bool, - true, - true, - ) -} - -func (ec *executionContext) fieldContext_TrustCenter_hasAcceptedNonDisclosureAgreement(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "TrustCenter", - Field: field, - IsMethod: true, - IsResolver: true, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Boolean does not have child fields") - }, - } - return fc, nil -} - func (ec *executionContext) _TrustCenter_documents(ctx context.Context, field graphql.CollectedField, obj *types.TrustCenter) (ret graphql.Marshaler) { return graphql.ResolveField( ctx, @@ -8489,33 +8362,6 @@ func (ec *executionContext) unmarshalInputAcceptElectronicSignatureInput(ctx con return it, nil } -func (ec *executionContext) unmarshalInputAcceptNonDisclosureAgreementInput(ctx context.Context, obj any) (types.AcceptNonDisclosureAgreementInput, error) { - var it types.AcceptNonDisclosureAgreementInput - asMap := map[string]any{} - for k, v := range obj.(map[string]any) { - asMap[k] = v - } - - fieldsInOrder := [...]string{"fullName"} - for _, k := range fieldsInOrder { - v, ok := asMap[k] - if !ok { - continue - } - switch k { - case "fullName": - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("fullName")) - data, err := ec.unmarshalNString2string(ctx, v) - if err != nil { - return it, err - } - it.FullName = data - } - } - - return it, nil -} - func (ec *executionContext) unmarshalInputExportDocumentPDFInput(ctx context.Context, obj any) (types.ExportDocumentPDFInput, error) { var it types.ExportDocumentPDFInput asMap := map[string]any{} @@ -8910,45 +8756,6 @@ func (ec *executionContext) _AcceptElectronicSignaturePayload(ctx context.Contex return out } -var acceptNonDisclosureAgreementPayloadImplementors = []string{"AcceptNonDisclosureAgreementPayload"} - -func (ec *executionContext) _AcceptNonDisclosureAgreementPayload(ctx context.Context, sel ast.SelectionSet, obj *types.AcceptNonDisclosureAgreementPayload) graphql.Marshaler { - fields := graphql.CollectFields(ec.OperationContext, sel, acceptNonDisclosureAgreementPayloadImplementors) - - out := graphql.NewFieldSet(fields) - deferred := make(map[string]*graphql.FieldSet) - for i, field := range fields { - switch field.Name { - case "__typename": - out.Values[i] = graphql.MarshalString("AcceptNonDisclosureAgreementPayload") - case "success": - out.Values[i] = ec._AcceptNonDisclosureAgreementPayload_success(ctx, field, obj) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - default: - panic("unknown field " + strconv.Quote(field.Name)) - } - } - out.Dispatch(ctx) - if out.Invalids > 0 { - return graphql.Null - } - - atomic.AddInt32(&ec.deferred, int32(len(deferred))) - - for label, dfs := range deferred { - ec.processDeferredGroup(graphql.DeferredGroup{ - Label: label, - Path: graphql.GetPath(ctx), - FieldSet: dfs, - Context: ctx, - }) - } - - return out -} - var auditImplementors = []string{"Audit", "Node"} func (ec *executionContext) _Audit(ctx context.Context, sel ast.SelectionSet, obj *types.Audit) graphql.Marshaler { @@ -9768,10 +9575,6 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) if out.Values[i] == graphql.Null { out.Invalids++ } - case "acceptNonDisclosureAgreement": - out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { - return ec._Mutation_acceptNonDisclosureAgreement(ctx, field) - }) case "requestDocumentAccess": out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { return ec._Mutation_requestDocumentAccess(ctx, field) @@ -9824,6 +9627,114 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) return out } +var nonDisclosureAgreementImplementors = []string{"NonDisclosureAgreement"} + +func (ec *executionContext) _NonDisclosureAgreement(ctx context.Context, sel ast.SelectionSet, obj *types.NonDisclosureAgreement) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, nonDisclosureAgreementImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("NonDisclosureAgreement") + case "fileName": + out.Values[i] = ec._NonDisclosureAgreement_fileName(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "fileUrl": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._NonDisclosureAgreement_fileUrl(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + case "viewerSignature": + field := field + + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._NonDisclosureAgreement_viewerSignature(ctx, field, obj) + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + var organizationImplementors = []string{"Organization", "Node"} func (ec *executionContext) _Organization(ctx context.Context, sel ast.SelectionSet, obj *types.Organization) graphql.Marshaler { @@ -10392,9 +10303,7 @@ func (ec *executionContext) _TrustCenter(ctx context.Context, sel ast.SelectionS } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) - case "ndaFileName": - out.Values[i] = ec._TrustCenter_ndaFileName(ctx, field, obj) - case "ndaFileUrl": + case "nonDisclosureAgreement": field := field innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { @@ -10403,76 +10312,7 @@ func (ec *executionContext) _TrustCenter(ctx context.Context, sel ast.SelectionS ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._TrustCenter_ndaFileUrl(ctx, field, obj) - return res - } - - if field.Deferrable != nil { - dfs, ok := deferred[field.Deferrable.Label] - di := 0 - if ok { - dfs.AddField(field) - di = len(dfs.Values) - 1 - } else { - dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) - deferred[field.Deferrable.Label] = dfs - } - dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { - return innerFunc(ctx, dfs) - }) - - // don't run the out.Concurrently() call below - out.Values[i] = graphql.Null - continue - } - - out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) - case "ndaSignature": - field := field - - innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._TrustCenter_ndaSignature(ctx, field, obj) - return res - } - - if field.Deferrable != nil { - dfs, ok := deferred[field.Deferrable.Label] - di := 0 - if ok { - dfs.AddField(field) - di = len(dfs.Values) - 1 - } else { - dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) - deferred[field.Deferrable.Label] = dfs - } - dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { - return innerFunc(ctx, dfs) - }) - - // don't run the out.Concurrently() call below - out.Values[i] = graphql.Null - continue - } - - out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) - case "organization": - field := field - - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._TrustCenter_organization(ctx, field, obj) - if res == graphql.Null { - atomic.AddUint32(&fs.Invalids, 1) - } + res = ec._TrustCenter_nonDisclosureAgreement(ctx, field, obj) return res } @@ -10532,7 +10372,7 @@ func (ec *executionContext) _TrustCenter(ctx context.Context, sel ast.SelectionS } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) - case "hasAcceptedNonDisclosureAgreement": + case "organization": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -10541,7 +10381,7 @@ func (ec *executionContext) _TrustCenter(ctx context.Context, sel ast.SelectionS ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._TrustCenter_hasAcceptedNonDisclosureAgreement(ctx, field, obj) + res = ec._TrustCenter_organization(ctx, field, obj) if res == graphql.Null { atomic.AddUint32(&fs.Invalids, 1) } @@ -11777,11 +11617,6 @@ func (ec *executionContext) unmarshalNAcceptElectronicSignatureInput2goᚗprobo return res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) unmarshalNAcceptNonDisclosureAgreementInput2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐAcceptNonDisclosureAgreementInput(ctx context.Context, v any) (types.AcceptNonDisclosureAgreementInput, error) { - res, err := ec.unmarshalInputAcceptNonDisclosureAgreementInput(ctx, v) - return res, graphql.ErrorOnPath(ctx, err) -} - func (ec *executionContext) marshalNAudit2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐAudit(ctx context.Context, sel ast.SelectionSet, v *types.Audit) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { @@ -13544,13 +13379,6 @@ func (ec *executionContext) marshalOAcceptElectronicSignaturePayload2ᚖgoᚗpro return ec._AcceptElectronicSignaturePayload(ctx, sel, v) } -func (ec *executionContext) marshalOAcceptNonDisclosureAgreementPayload2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐAcceptNonDisclosureAgreementPayload(ctx context.Context, sel ast.SelectionSet, v *types.AcceptNonDisclosureAgreementPayload) graphql.Marshaler { - if v == nil { - return graphql.Null - } - return ec._AcceptNonDisclosureAgreementPayload(ctx, sel, v) -} - func (ec *executionContext) unmarshalOBoolean2bool(ctx context.Context, v any) (bool, error) { res, err := graphql.UnmarshalBoolean(v) return res, graphql.ErrorOnPath(ctx, err) @@ -13649,6 +13477,13 @@ func (ec *executionContext) marshalOInt2ᚖint(ctx context.Context, sel ast.Sele return res } +func (ec *executionContext) marshalONonDisclosureAgreement2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐNonDisclosureAgreement(ctx context.Context, sel ast.SelectionSet, v *types.NonDisclosureAgreement) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._NonDisclosureAgreement(ctx, sel, v) +} + func (ec *executionContext) marshalORecordSigningEventPayload2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐRecordSigningEventPayload(ctx context.Context, sel ast.SelectionSet, v *types.RecordSigningEventPayload) graphql.Marshaler { if v == nil { return graphql.Null diff --git a/pkg/server/api/trust/v1/types/trust_center.go b/pkg/server/api/trust/v1/types/trust_center.go index bab1c07ca..ee9a882e5 100644 --- a/pkg/server/api/trust/v1/types/trust_center.go +++ b/pkg/server/api/trust/v1/types/trust_center.go @@ -18,16 +18,16 @@ import ( "go.probo.inc/probo/pkg/coredata" ) -func NewTrustCenter(tc *coredata.TrustCenter, file *coredata.File) *TrustCenter { - var ndaFileName *string - if file != nil { - ndaFileName = &file.FileName - } - +func NewTrustCenter(tc *coredata.TrustCenter) *TrustCenter { return &TrustCenter{ - ID: tc.ID, - Active: tc.Active, - Slug: tc.Slug, - NdaFileName: ndaFileName, + ID: tc.ID, + Active: tc.Active, + Slug: tc.Slug, + } +} + +func NewNonDisclosureAgreement(file *coredata.File) *NonDisclosureAgreement { + return &NonDisclosureAgreement{ + FileName: file.FileName, } } diff --git a/pkg/server/api/trust/v1/types/types.go b/pkg/server/api/trust/v1/types/types.go index f0ad66e50..47c8ec2e2 100644 --- a/pkg/server/api/trust/v1/types/types.go +++ b/pkg/server/api/trust/v1/types/types.go @@ -25,14 +25,6 @@ type AcceptElectronicSignaturePayload struct { Signature *ElectronicSignature `json:"signature"` } -type AcceptNonDisclosureAgreementInput struct { - FullName string `json:"fullName"` -} - -type AcceptNonDisclosureAgreementPayload struct { - Success bool `json:"success"` -} - type Audit struct { ID gid.GID `json:"id"` Framework *Framework `json:"framework"` @@ -136,6 +128,12 @@ func (this Identity) GetID() gid.GID { return this.ID } type Mutation struct { } +type NonDisclosureAgreement struct { + FileName string `json:"fileName"` + FileURL string `json:"fileUrl"` + ViewerSignature *ElectronicSignature `json:"viewerSignature,omitempty"` +} + type Organization struct { ID gid.GID `json:"id"` Name string `json:"name"` @@ -203,22 +201,19 @@ type SendMagicLinkPayload struct { } type TrustCenter struct { - ID gid.GID `json:"id"` - Active bool `json:"active"` - Slug string `json:"slug"` - LogoFileURL *string `json:"logoFileUrl,omitempty"` - DarkLogoFileURL *string `json:"darkLogoFileUrl,omitempty"` - NdaFileName *string `json:"ndaFileName,omitempty"` - NdaFileURL *string `json:"ndaFileUrl,omitempty"` - NdaSignature *ElectronicSignature `json:"ndaSignature,omitempty"` - Organization *Organization `json:"organization"` - IsViewerMember bool `json:"isViewerMember"` - HasAcceptedNonDisclosureAgreement bool `json:"hasAcceptedNonDisclosureAgreement"` - Documents *DocumentConnection `json:"documents"` - Audits *AuditConnection `json:"audits"` - Vendors *VendorConnection `json:"vendors"` - References *TrustCenterReferenceConnection `json:"references"` - TrustCenterFiles *TrustCenterFileConnection `json:"trustCenterFiles"` + ID gid.GID `json:"id"` + Active bool `json:"active"` + Slug string `json:"slug"` + LogoFileURL *string `json:"logoFileUrl,omitempty"` + DarkLogoFileURL *string `json:"darkLogoFileUrl,omitempty"` + NonDisclosureAgreement *NonDisclosureAgreement `json:"nonDisclosureAgreement,omitempty"` + IsViewerMember bool `json:"isViewerMember"` + Organization *Organization `json:"organization"` + Documents *DocumentConnection `json:"documents"` + Audits *AuditConnection `json:"audits"` + Vendors *VendorConnection `json:"vendors"` + References *TrustCenterReferenceConnection `json:"references"` + TrustCenterFiles *TrustCenterFileConnection `json:"trustCenterFiles"` } func (TrustCenter) IsNode() {} diff --git a/pkg/server/api/trust/v1/v1_resolver.go b/pkg/server/api/trust/v1/v1_resolver.go index e0d725cbd..ca855a70c 100644 --- a/pkg/server/api/trust/v1/v1_resolver.go +++ b/pkg/server/api/trust/v1/v1_resolver.go @@ -88,7 +88,7 @@ func (r *documentResolver) IsUserAuthorized(ctx context.Context, obj *types.Docu return false, nil } - documentAccess, err := trustService.TrustCenterAccesses.LoadDocumentAccess( + documentAccess, err := trustService.TrustCenterAccesses.GetDocumentAccess( ctx, trustCenter.ID, identity.EmailAddress, @@ -123,7 +123,7 @@ func (r *documentResolver) HasUserRequestedAccess(ctx context.Context, obj *type } // Try to load document access - if it exists (regardless of active status), user has requested it - _, err := trustService.TrustCenterAccesses.LoadDocumentAccess( + _, err := trustService.TrustCenterAccesses.GetDocumentAccess( ctx, trustCenter.ID, identity.EmailAddress, @@ -228,6 +228,41 @@ func (r *mutationResolver) RequestAllAccesses(ctx context.Context) (*types.Reque }, nil } +func (r *mutationResolver) checkNDASignature( + ctx context.Context, + trustCenter *coredata.TrustCenter, + identity *coredata.Identity, +) error { + if trustCenter.NonDisclosureAgreementFileID == nil { + return nil + } + + trustService := r.TrustService(ctx, trustCenter.ID.TenantID()) + + access, err := trustService.TrustCenterAccesses.GetAccess(ctx, trustCenter.ID, identity.EmailAddress) + if err != nil { + return gqlutils.Forbiddenf(ctx, "user has not signed the NDA") + } + + if access.ElectronicSignatureID == nil { + return gqlutils.Forbiddenf(ctx, "user has not signed the NDA") + } + + sig, err := r.esign.GetSignatureByID(ctx, *access.ElectronicSignatureID) + if err != nil { + return gqlutils.Forbiddenf(ctx, "user has not signed the NDA") + } + + switch sig.Status { + case coredata.ElectronicSignatureStatusAccepted, + coredata.ElectronicSignatureStatusProcessing, + coredata.ElectronicSignatureStatusCompleted: + return nil + default: + return gqlutils.Forbiddenf(ctx, "user has not signed the NDA") + } +} + // ExportDocumentPDF is the resolver for the exportDocumentPDF field. func (r *mutationResolver) ExportDocumentPDF(ctx context.Context, input types.ExportDocumentPDFInput) (*types.ExportDocumentPDFPayload, error) { trustService := r.TrustService(ctx, input.DocumentID.TenantID()) @@ -256,35 +291,13 @@ func (r *mutationResolver) ExportDocumentPDF(ctx context.Context, input types.Ex return nil, gqlutils.Unauthenticated(ctx, errors.New("unauthenticated")) } - ndaExists := true - hasAcceptedNDA := false - - if trustCenter.NonDisclosureAgreementFileID == nil { - ndaExists = false - } - - if ndaExists { - hasAcceptedNDA, err = trustService.TrustCenterAccesses.HasAcceptedNonDisclosureAgreement( - ctx, - trustCenter.ID, - identity.EmailAddress, - ) - if err != nil { - r.logger.ErrorCtx(ctx, "cannot check if user has accepted NDA", log.Error(err)) - return nil, gqlutils.Internal(ctx) - } - } - - documentAccess, err := trustService.TrustCenterAccesses.LoadDocumentAccess( + documentAccess, err := trustService.TrustCenterAccesses.GetDocumentAccess( ctx, trustCenter.ID, identity.EmailAddress, input.DocumentID, ) if err != nil { - // FIXME check for not found and return without error in this case - // r.logger.ErrorCtx(ctx, "cannot check document access", log.Error(err)) - // return false, gqlutils.Internal(ctx) return nil, nil } @@ -292,8 +305,8 @@ func (r *mutationResolver) ExportDocumentPDF(ctx context.Context, input types.Ex return nil, gqlutils.Forbiddenf(ctx, "access denied: no permission to access this document") } - if ndaExists && !hasAcceptedNDA { - return nil, gqlutils.Forbiddenf(ctx, "user has not accepted NDA") + if err := r.checkNDASignature(ctx, trustCenter, identity); err != nil { + return nil, err } pdf, err := trustService.Documents.ExportPDF(ctx, input.DocumentID, identity.EmailAddress) @@ -336,35 +349,13 @@ func (r *mutationResolver) ExportReportPDF(ctx context.Context, input types.Expo return nil, gqlutils.Unauthenticatedf(ctx, "unauthenticated") } - ndaExists := true - hasAcceptedNDA := false - - if trustCenter.NonDisclosureAgreementFileID == nil { - ndaExists = false - } - - if ndaExists { - hasAcceptedNDA, err = trustService.TrustCenterAccesses.HasAcceptedNonDisclosureAgreement( - ctx, - trustCenter.ID, - identity.EmailAddress, - ) - if err != nil { - r.logger.ErrorCtx(ctx, "cannot check if user has accepted NDA", log.Error(err)) - return nil, gqlutils.Internal(ctx) - } - } - - reportAccess, err := trustService.TrustCenterAccesses.LoadReportAccess( + reportAccess, err := trustService.TrustCenterAccesses.GetReportAccess( ctx, trustCenter.ID, identity.EmailAddress, input.ReportID, ) if err != nil { - // FIXME check for not found and return without error in this case - // r.logger.ErrorCtx(ctx, "cannot check report access", log.Error(err)) - // return false, gqlutils.Internal(ctx) return nil, nil } @@ -372,8 +363,8 @@ func (r *mutationResolver) ExportReportPDF(ctx context.Context, input types.Expo return nil, gqlutils.Forbiddenf(ctx, "access denied: no permission to access this report") } - if ndaExists && !hasAcceptedNDA { - return nil, gqlutils.Forbiddenf(ctx, "user has not accepted NDA") + if err := r.checkNDASignature(ctx, trustCenter, identity); err != nil { + return nil, err } pdf, err := trustService.Reports.ExportPDF(ctx, input.ReportID, identity.EmailAddress) @@ -415,33 +406,12 @@ func (r *mutationResolver) ExportTrustCenterFile(ctx context.Context, input type return nil, gqlutils.Unauthenticatedf(ctx, "unauthenticated") } - ndaExists := true - hasAcceptedNDA := false - - if trustCenter.NonDisclosureAgreementFileID == nil { - ndaExists = false - } - - if ndaExists { - hasAcceptedNDA, err = trustService.TrustCenterAccesses.HasAcceptedNonDisclosureAgreement(ctx, - trustCenter.ID, - identity.EmailAddress, - ) - if err != nil { - r.logger.ErrorCtx(ctx, "cannot check if user has accepted NDA", log.Error(err)) - return nil, gqlutils.Internal(ctx) - } - } - - fileAccess, err := trustService.TrustCenterAccesses.LoadTrustCenterFileAccess(ctx, + fileAccess, err := trustService.TrustCenterAccesses.GetTrustCenterFileAccess(ctx, trustCenter.ID, identity.EmailAddress, input.TrustCenterFileID, ) if err != nil { - // FIXME check for not found and return without error in this case - // r.logger.ErrorCtx(ctx, "cannot check trust center file access", log.Error(err)) - // return false, gqlutils.Internal(ctx) return nil, nil } @@ -449,8 +419,8 @@ func (r *mutationResolver) ExportTrustCenterFile(ctx context.Context, input type return nil, gqlutils.Forbiddenf(ctx, "access denied: no permission to access this file") } - if ndaExists && !hasAcceptedNDA { - return nil, gqlutils.Forbiddenf(ctx, "user has not accepted NDA") + if err := r.checkNDASignature(ctx, trustCenter, identity); err != nil { + return nil, err } fileData, err := trustService.TrustCenterFiles.ExportFile(ctx, input.TrustCenterFileID, identity.EmailAddress) @@ -464,42 +434,6 @@ func (r *mutationResolver) ExportTrustCenterFile(ctx context.Context, input type }, nil } -// AcceptNonDisclosureAgreement is the resolver for the acceptNonDisclosureAgreement field. -func (r *mutationResolver) AcceptNonDisclosureAgreement(ctx context.Context, input types.AcceptNonDisclosureAgreementInput) (*types.AcceptNonDisclosureAgreementPayload, error) { - identity := authn.IdentityFromContext(ctx) - if identity == nil { - return nil, gqlutils.Unauthenticatedf(ctx, "unauthenticated") - } - trustCenter := compliancepage.CompliancePageFromContext(ctx) - trustService := r.TrustService(ctx, trustCenter.ID.TenantID()) - - httpReq := gqlutils.HTTPRequestFromContext(ctx) - - if _, err := r.iam.AuthService.UpdateIdentity(ctx, identity.ID, input.FullName); err != nil { - var errNotFound *iam.ErrIdentityNotFound - if errors.As(err, &errNotFound) { - return nil, gqlutils.NotFound(ctx, err) - } - - r.logger.ErrorCtx(ctx, "cannot update identity", log.Error(err)) - return nil, gqlutils.Internal(ctx) - } - - if err := trustService.TrustCenterAccesses.AcceptNonDisclosureAgreement( - ctx, - &trust.AcceptNDARequest{ - TrustCenterID: trustCenter.ID, - Email: identity.EmailAddress, - IPAddr: httpReq.RemoteAddr, - }, - ); err != nil { - r.logger.ErrorCtx(ctx, "cannot accept NDA", log.Error(err)) - return nil, gqlutils.Internal(ctx) - } - - return &types.AcceptNonDisclosureAgreementPayload{Success: true}, nil -} - // RequestDocumentAccess is the resolver for the requestDocumentAccess field. func (r *mutationResolver) RequestDocumentAccess(ctx context.Context, input types.RequestDocumentAccessInput) (*types.RequestAccessesPayload, error) { trustCenter := compliancepage.CompliancePageFromContext(ctx) @@ -651,12 +585,10 @@ func (r *mutationResolver) RequestTrustCenterFileAccess(ctx context.Context, inp // AcceptElectronicSignature is the resolver for the acceptElectronicSignature field. func (r *mutationResolver) AcceptElectronicSignature(ctx context.Context, input types.AcceptElectronicSignatureInput) (*types.AcceptElectronicSignaturePayload, error) { - identity := authn.IdentityFromContext(ctx) - if identity == nil { - return nil, gqlutils.Unauthenticatedf(ctx, "unauthenticated") - } - - httpReq := gqlutils.HTTPRequestFromContext(ctx) + var ( + identity = authn.IdentityFromContext(ctx) + httpReq = gqlutils.HTTPRequestFromContext(ctx) + ) if _, err := r.iam.AuthService.UpdateIdentity(ctx, identity.ID, input.FullName); err != nil { var errNotFound *iam.ErrIdentityNotFound @@ -668,45 +600,44 @@ func (r *mutationResolver) AcceptElectronicSignature(ctx context.Context, input return nil, gqlutils.Internal(ctx) } - if err := r.esign.AcceptSignature(ctx, &esign.AcceptSignatureRequest{ - SignatureID: input.SignatureID, - SignerFullName: input.FullName, - SignerEmail: identity.EmailAddress, - SignerIPAddr: httpReq.RemoteAddr, - SignerUA: httpReq.UserAgent(), - }); err != nil { + signature, err := r.esign.AcceptSignature( + ctx, + &esign.AcceptSignatureRequest{ + SignatureID: input.SignatureID, + SignerFullName: input.FullName, + SignerEmail: identity.EmailAddress, + SignerIPAddr: httpReq.RemoteAddr, + SignerUA: httpReq.UserAgent(), + }, + ) + if err != nil { r.logger.ErrorCtx(ctx, "cannot accept electronic signature", log.Error(err)) return nil, gqlutils.Internal(ctx) } - sig, err := r.esign.LoadSignatureByID(ctx, input.SignatureID) - if err != nil { - r.logger.ErrorCtx(ctx, "cannot load electronic signature", log.Error(err)) - return nil, gqlutils.Internal(ctx) - } - return &types.AcceptElectronicSignaturePayload{ - Signature: types.NewElectronicSignature(sig), + Signature: types.NewElectronicSignature(signature), }, nil } // RecordSigningEvent is the resolver for the recordSigningEvent field. func (r *mutationResolver) RecordSigningEvent(ctx context.Context, input types.RecordSigningEventInput) (*types.RecordSigningEventPayload, error) { - identity := authn.IdentityFromContext(ctx) - if identity == nil { - return nil, gqlutils.Unauthenticatedf(ctx, "unauthenticated") - } + var ( + identity = authn.IdentityFromContext(ctx) + httpReq = gqlutils.HTTPRequestFromContext(ctx) + ) - httpReq := gqlutils.HTTPRequestFromContext(ctx) - - if err := r.esign.RecordEvent(ctx, &esign.RecordEventRequest{ - SignatureID: input.SignatureID, - EventType: input.EventType, - EventSource: coredata.ElectronicSignatureEventSourceClient, - ActorEmail: identity.EmailAddress, - ActorIPAddr: httpReq.RemoteAddr, - ActorUA: httpReq.UserAgent(), - }); err != nil { + if err := r.esign.RecordEvent( + ctx, + &esign.RecordEventRequest{ + SignatureID: input.SignatureID, + EventType: input.EventType, + EventSource: coredata.ElectronicSignatureEventSourceClient, + ActorEmail: identity.EmailAddress, + ActorIPAddr: httpReq.RemoteAddr, + ActorUA: httpReq.UserAgent(), + }, + ); err != nil { r.logger.ErrorCtx(ctx, "cannot record signing event", log.Error(err)) return nil, gqlutils.Internal(ctx) } @@ -714,6 +645,46 @@ func (r *mutationResolver) RecordSigningEvent(ctx context.Context, input types.R return &types.RecordSigningEventPayload{Success: true}, nil } +// FileURL is the resolver for the fileUrl field. +func (r *nonDisclosureAgreementResolver) FileURL(ctx context.Context, obj *types.NonDisclosureAgreement) (string, error) { + trustCenter := compliancepage.CompliancePageFromContext(ctx) + trustService := r.TrustService(ctx, trustCenter.ID.TenantID()) + + fileURL, err := trustService.TrustCenters.GenerateNDAFileURL(ctx, trustCenter.ID, 15*time.Minute) + if err != nil { + return "", gqlutils.Internal(ctx) + } + + return fileURL, nil +} + +// ViewerSignature is the resolver for the viewerSignature field. +func (r *nonDisclosureAgreementResolver) ViewerSignature(ctx context.Context, obj *types.NonDisclosureAgreement) (*types.ElectronicSignature, error) { + identity := authn.IdentityFromContext(ctx) + if identity == nil { + return nil, nil + } + + trustCenter := compliancepage.CompliancePageFromContext(ctx) + trustService := r.TrustService(ctx, trustCenter.ID.TenantID()) + + access, err := trustService.TrustCenterAccesses.GetAccess(ctx, trustCenter.ID, identity.EmailAddress) + if err != nil { + return nil, nil + } + + if access.ElectronicSignatureID == nil { + return nil, nil + } + + sig, err := r.esign.GetSignatureByID(ctx, *access.ElectronicSignatureID) + if err != nil { + return nil, nil + } + + return types.NewElectronicSignature(sig), nil +} + // LogoURL is the resolver for the logoUrl field. func (r *organizationResolver) LogoURL(ctx context.Context, obj *types.Organization) (*string, error) { trustService := r.TrustService(ctx, obj.ID.TenantID()) @@ -793,12 +764,12 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error return types.NewVendor(vendor), nil case coredata.TrustCenterEntityType: - trustCenter, file, err := trustService.TrustCenters.Get(ctx, id) + trustCenter, err := trustService.TrustCenters.Get(ctx, id) if err != nil { r.logger.ErrorCtx(ctx, "cannot get trust center", log.Error(err)) return nil, gqlutils.Internal(ctx) } - return types.NewTrustCenter(trustCenter, file), nil + return types.NewTrustCenter(trustCenter), nil case coredata.TrustCenterReferenceEntityType: reference, err := trustService.TrustCenterReferences.Get(ctx, id) @@ -824,12 +795,12 @@ func (r *queryResolver) CurrentTrustCenter(ctx context.Context) (*types.TrustCen panic(fmt.Errorf("cannot get organization: %w", err)) } - trustCenter, file, err := trustService.TrustCenters.Get(ctx, trustCenter.ID) + trustCenter, err = trustService.TrustCenters.Get(ctx, trustCenter.ID) if err != nil { panic(fmt.Errorf("cannot get trust center: %w", err)) } - response := types.NewTrustCenter(trustCenter, file) + response := types.NewTrustCenter(trustCenter) response.Organization = types.NewOrganization(org) return response, nil @@ -856,7 +827,7 @@ func (r *reportResolver) IsUserAuthorized(ctx context.Context, obj *types.Report return false, nil } - reportAccess, err := trustService.TrustCenterAccesses.LoadReportAccess(ctx, + reportAccess, err := trustService.TrustCenterAccesses.GetReportAccess(ctx, trustCenter.ID, identity.EmailAddress, obj.ID, @@ -890,7 +861,7 @@ func (r *reportResolver) HasUserRequestedAccess(ctx context.Context, obj *types. return false, nil // User is not authenticated, so no access requested } - _, err := trustService.TrustCenterAccesses.LoadReportAccess(ctx, + _, err := trustService.TrustCenterAccesses.GetReportAccess(ctx, trustCenter.ID, identity.EmailAddress, obj.ID, @@ -919,50 +890,25 @@ func (r *trustCenterResolver) DarkLogoFileURL(ctx context.Context, obj *types.Tr return trustService.TrustCenters.GenerateDarkLogoURL(ctx, obj.ID, 1*time.Hour) } -// NdaFileURL is the resolver for the ndaFileUrl field. -func (r *trustCenterResolver) NdaFileURL(ctx context.Context, obj *types.TrustCenter) (*string, error) { +// NonDisclosureAgreement is the resolver for the nonDisclosureAgreement field. +func (r *trustCenterResolver) NonDisclosureAgreement(ctx context.Context, obj *types.TrustCenter) (*types.NonDisclosureAgreement, error) { + trustCenter := compliancepage.CompliancePageFromContext(ctx) + if trustCenter.NonDisclosureAgreementFileID == nil { + return nil, nil + } + trustService := r.TrustService(ctx, obj.ID.TenantID()) - fileURL, err := trustService.TrustCenters.GenerateNDAFileURL(ctx, obj.ID, 15*time.Minute) + file, err := trustService.TrustCenters.GetNDAFile(ctx, obj.ID) if err != nil { - // FIXME: add error not found check etc - // r.logger.ErrorCtx(ctx, "cannot generate NDA file URL", log.Error(err)) - // return nil, gqlutils.Internal(ctx) + r.logger.ErrorCtx(ctx, "cannot load NDA file", log.Error(err)) + return nil, gqlutils.Internal(ctx) + } + if file == nil { return nil, nil } - return &fileURL, nil -} - -// NdaSignature is the resolver for the ndaSignature field. -func (r *trustCenterResolver) NdaSignature(ctx context.Context, obj *types.TrustCenter) (*types.ElectronicSignature, error) { - identity := authn.IdentityFromContext(ctx) - if identity == nil { - return nil, nil - } - - trustCenter := compliancepage.CompliancePageFromContext(ctx) - if trustCenter == nil || trustCenter.NonDisclosureAgreementFileID == nil { - return nil, nil - } - - sig, err := r.esign.LoadSignatureByOrgEmailAndDocType( - ctx, - trustCenter.OrganizationID, - identity.EmailAddress.String(), - coredata.ElectronicSignatureDocumentTypeNDA, - *trustCenter.NonDisclosureAgreementFileID, - ) - if err != nil { - return nil, nil - } - - return types.NewElectronicSignature(sig), nil -} - -// Organization is the resolver for the organization field. -func (r *trustCenterResolver) Organization(ctx context.Context, obj *types.TrustCenter) (*types.Organization, error) { - return obj.Organization, nil + return types.NewNonDisclosureAgreement(file), nil } // IsViewerMember is the resolver for the isViewerMember field. @@ -972,22 +918,9 @@ func (r *trustCenterResolver) IsViewerMember(ctx context.Context, obj *types.Tru return membership != nil, nil } -// HasAcceptedNonDisclosureAgreement is the resolver for the hasAcceptedNonDisclosureAgreement field. -func (r *trustCenterResolver) HasAcceptedNonDisclosureAgreement(ctx context.Context, obj *types.TrustCenter) (bool, error) { - trustService := r.TrustService(ctx, obj.ID.TenantID()) - - identity := authn.IdentityFromContext(ctx) - if identity == nil { - return false, nil // User is not authenticated, so no NDA accepted - } - - hasAcceptedNDA, err := trustService.TrustCenterAccesses.HasAcceptedNonDisclosureAgreement(ctx, obj.ID, identity.EmailAddress) - if err != nil { - r.logger.ErrorCtx(ctx, "cannot check if user has accepted NDA", log.Error(err)) - return false, gqlutils.Internal(ctx) - } - - return hasAcceptedNDA, nil +// Organization is the resolver for the organization field. +func (r *trustCenterResolver) Organization(ctx context.Context, obj *types.TrustCenter) (*types.Organization, error) { + return obj.Organization, nil } // Documents is the resolver for the documents field. @@ -1112,7 +1045,7 @@ func (r *trustCenterFileResolver) IsUserAuthorized(ctx context.Context, obj *typ return false, nil } - fileAccess, err := trustService.TrustCenterAccesses.LoadTrustCenterFileAccess(ctx, + fileAccess, err := trustService.TrustCenterAccesses.GetTrustCenterFileAccess(ctx, trustCenter.ID, identity.EmailAddress, obj.ID, @@ -1146,7 +1079,7 @@ func (r *trustCenterFileResolver) HasUserRequestedAccess(ctx context.Context, ob return false, nil // User is not authenticated, so no access requested } - _, err := trustService.TrustCenterAccesses.LoadTrustCenterFileAccess(ctx, + _, err := trustService.TrustCenterAccesses.GetTrustCenterFileAccess(ctx, trustCenter.ID, identity.EmailAddress, obj.ID, @@ -1201,6 +1134,11 @@ func (r *Resolver) Framework() schema.FrameworkResolver { return &frameworkResol // Mutation returns schema.MutationResolver implementation. func (r *Resolver) Mutation() schema.MutationResolver { return &mutationResolver{r} } +// NonDisclosureAgreement returns schema.NonDisclosureAgreementResolver implementation. +func (r *Resolver) NonDisclosureAgreement() schema.NonDisclosureAgreementResolver { + return &nonDisclosureAgreementResolver{r} +} + // Organization returns schema.OrganizationResolver implementation. func (r *Resolver) Organization() schema.OrganizationResolver { return &organizationResolver{r} } @@ -1232,6 +1170,7 @@ type auditResolver struct{ *Resolver } type documentResolver struct{ *Resolver } type frameworkResolver struct{ *Resolver } type mutationResolver struct{ *Resolver } +type nonDisclosureAgreementResolver struct{ *Resolver } type organizationResolver struct{ *Resolver } type queryResolver struct{ *Resolver } type reportResolver struct{ *Resolver } diff --git a/pkg/trust/trust_center_access_service.go b/pkg/trust/trust_center_access_service.go index c168956f1..0db27e036 100644 --- a/pkg/trust/trust_center_access_service.go +++ b/pkg/trust/trust_center_access_service.go @@ -16,7 +16,6 @@ package trust import ( "context" - "encoding/json" "errors" "fmt" "time" @@ -155,13 +154,8 @@ func (s TrustCenterAccessService) Request( UpdatedAt: now, } - if err := access.Insert(ctx, tx, s.svc.scope); err != nil { - return fmt.Errorf("cannot insert trust center access: %w", err) - } - - // Create PENDING electronic signature when NDA is configured. if trustCenter.NonDisclosureAgreementFileID != nil && s.svc.esign != nil { - _, err := s.svc.esign.CreateSignature( + sig, err := s.svc.esign.CreateSignature( ctx, tx, &esign.CreateSignatureRequest{ @@ -174,6 +168,11 @@ func (s TrustCenterAccessService) Request( if err != nil { return fmt.Errorf("cannot create pending signature: %w", err) } + access.ElectronicSignatureID = &sig.ID + } + + if err := access.Insert(ctx, tx, s.svc.scope); err != nil { + return fmt.Errorf("cannot insert trust center access: %w", err) } } @@ -243,93 +242,21 @@ func (s TrustCenterAccessService) Request( return access, nil } -func (s TrustCenterAccessService) HasAcceptedNonDisclosureAgreement(ctx context.Context, trustCenterID gid.GID, email mail.Addr) (bool, error) { +func (s TrustCenterAccessService) GetAccess( + ctx context.Context, + trustCenterID gid.GID, + email mail.Addr, +) (coredata.TrustCenterAccess, error) { var access coredata.TrustCenterAccess + err := s.svc.pg.WithConn(ctx, func(conn pg.Conn) error { return access.LoadByTrustCenterIDAndEmail(ctx, conn, s.svc.scope, trustCenterID, email) }) - if err != nil { - return false, nil - } - - // Legacy path: check the old boolean field. - if access.HasAcceptedNonDisclosureAgreement { - return true, nil - } - - // New path: check for an electronic signature in ACCEPTED or later status. - if s.svc.esign != nil { - trustCenter := &coredata.TrustCenter{} - err := s.svc.pg.WithConn(ctx, func(conn pg.Conn) error { - return trustCenter.LoadByID(ctx, conn, s.svc.scope, trustCenterID) - }) - if err != nil { - return false, nil - } - - if trustCenter.NonDisclosureAgreementFileID != nil { - sig, err := s.svc.esign.LoadSignatureByOrgEmailAndDocType( - ctx, - trustCenter.OrganizationID, - email.String(), - coredata.ElectronicSignatureDocumentTypeNDA, - *trustCenter.NonDisclosureAgreementFileID, - ) - if err == nil { - switch sig.Status { - case coredata.ElectronicSignatureStatusAccepted, - coredata.ElectronicSignatureStatusProcessing, - coredata.ElectronicSignatureStatusCompleted: - return true, nil - } - } - } - } - - return false, nil + return access, err } -type AcceptNDARequest struct { - TrustCenterID gid.GID - Email mail.Addr - IPAddr string -} - -func (s TrustCenterAccessService) AcceptNonDisclosureAgreement(ctx context.Context, req *AcceptNDARequest) error { - return s.svc.pg.WithTx(ctx, func(tx pg.Conn) error { - access := &coredata.TrustCenterAccess{} - if err := access.LoadByTrustCenterIDAndEmail(ctx, tx, s.svc.scope, req.TrustCenterID, req.Email); err != nil { - return fmt.Errorf("cannot load trust center access: %w", err) - } - - trustCenter := &coredata.TrustCenter{} - if err := trustCenter.LoadByID(ctx, tx, s.svc.scope, req.TrustCenterID); err != nil { - return fmt.Errorf("cannot load trust center: %w", err) - } - - acceptationLogs, err := json.Marshal(map[string]string{ - "email": req.Email.String(), - "timestamp": time.Now().Format(time.RFC3339), - "ip": req.IPAddr, - }) - if err != nil { - return fmt.Errorf("cannot marshal non disclosure agreement acceptation logs: %w", err) - } - - access.HasAcceptedNonDisclosureAgreement = true - access.UpdatedAt = time.Now() - access.HasAcceptedNonDisclosureAgreementMetadata = acceptationLogs - access.NDAFileID = trustCenter.NonDisclosureAgreementFileID - if err := access.Update(ctx, tx, s.svc.scope); err != nil { - return fmt.Errorf("cannot update trust center access: %w", err) - } - - return nil - }) -} - -func (s TrustCenterAccessService) LoadDocumentAccess( +func (s TrustCenterAccessService) GetDocumentAccess( ctx context.Context, trustCenterID gid.GID, email mail.Addr, @@ -372,7 +299,7 @@ func (s TrustCenterAccessService) LoadDocumentAccess( return documentAccess, nil } -func (s TrustCenterAccessService) LoadReportAccess( +func (s TrustCenterAccessService) GetReportAccess( ctx context.Context, trustCenterID gid.GID, email mail.Addr, @@ -415,7 +342,7 @@ func (s TrustCenterAccessService) LoadReportAccess( return reportAccess, nil } -func (s TrustCenterAccessService) LoadTrustCenterFileAccess( +func (s TrustCenterAccessService) GetTrustCenterFileAccess( ctx context.Context, trustCenterID gid.GID, email mail.Addr, diff --git a/pkg/trust/trust_center_service.go b/pkg/trust/trust_center_service.go index 924a7c602..8acfb7000 100644 --- a/pkg/trust/trust_center_service.go +++ b/pkg/trust/trust_center_service.go @@ -34,9 +34,8 @@ type TrustCenterService struct { func (s TrustCenterService) Get( ctx context.Context, trustCenterID gid.GID, -) (*coredata.TrustCenter, *coredata.File, error) { +) (*coredata.TrustCenter, error) { var trustCenter *coredata.TrustCenter - var file *coredata.File err := s.svc.pg.WithConn( ctx, @@ -46,22 +45,15 @@ func (s TrustCenterService) Get( return fmt.Errorf("cannot load trust center: %w", err) } - if trustCenter.NonDisclosureAgreementFileID != nil { - file = &coredata.File{} - if err := file.LoadByID(ctx, conn, s.svc.scope, *trustCenter.NonDisclosureAgreementFileID); err != nil { - return fmt.Errorf("cannot load file: %w", err) - } - } - return nil }, ) if err != nil { - return nil, nil, fmt.Errorf("cannot load trust center: %w", err) + return nil, fmt.Errorf("cannot load trust center: %w", err) } - return trustCenter, file, nil + return trustCenter, nil } func (s TrustCenterService) GetByOrganizationID( @@ -89,6 +81,39 @@ func (s TrustCenterService) GetByOrganizationID( return trustCenter, nil } +func (s TrustCenterService) GetNDAFile( + ctx context.Context, + trustCenterID gid.GID, +) (*coredata.File, error) { + var file *coredata.File + + err := s.svc.pg.WithConn( + ctx, + func(conn pg.Conn) error { + trustCenter := &coredata.TrustCenter{} + if err := trustCenter.LoadByID(ctx, conn, s.svc.scope, trustCenterID); err != nil { + return fmt.Errorf("cannot load trust center: %w", err) + } + + if trustCenter.NonDisclosureAgreementFileID == nil { + return nil + } + + file = &coredata.File{} + if err := file.LoadByID(ctx, conn, s.svc.scope, *trustCenter.NonDisclosureAgreementFileID); err != nil { + return fmt.Errorf("cannot load file: %w", err) + } + + return nil + }, + ) + if err != nil { + return nil, err + } + + return file, nil +} + func (s TrustCenterService) GenerateNDAFileURL( ctx context.Context, trustCenterID gid.GID, diff --git a/pkg/trust/vendor_service.go b/pkg/trust/vendor_service.go index d544f29d8..01bdc1c74 100644 --- a/pkg/trust/vendor_service.go +++ b/pkg/trust/vendor_service.go @@ -92,7 +92,7 @@ func (s VendorService) CountForTrustCenterId( err := s.svc.pg.WithConn( ctx, func(conn pg.Conn) (err error) { - trustCenter, _, err := s.svc.TrustCenters.Get(ctx, trustCenterID) + trustCenter, err := s.svc.TrustCenters.Get(ctx, trustCenterID) if err != nil { return fmt.Errorf("cannot load trust center: %w", err) }