diff --git a/apps/console/src/components/organizations/__generated__/InviteUserDialogMutation.graphql.ts b/apps/console/src/components/organizations/__generated__/InviteUserDialogMutation.graphql.ts index 46bd0a77c..4a444ae50 100644 --- a/apps/console/src/components/organizations/__generated__/InviteUserDialogMutation.graphql.ts +++ b/apps/console/src/components/organizations/__generated__/InviteUserDialogMutation.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<<4dda94f89f726842762d68c28d8180b6>> * @lightSyntaxTransform * @nogrep */ @@ -9,7 +9,7 @@ // @ts-nocheck import { ConcreteRequest } from 'relay-runtime'; -export type MembershipRole = "ADMIN" | "OWNER" | "VIEWER"; +export type MembershipRole = "ADMIN" | "EMPLOYEE" | "OWNER" | "VIEWER"; export type InviteUserInput = { createPeople: boolean; email: string; diff --git a/apps/console/src/layouts/EmployeeLayout.tsx b/apps/console/src/layouts/EmployeeLayout.tsx new file mode 100644 index 000000000..fdb65ac8e --- /dev/null +++ b/apps/console/src/layouts/EmployeeLayout.tsx @@ -0,0 +1,377 @@ +import { Link, Navigate, Outlet, useParams } from "react-router"; +import { + DropdownSeparator, + IconArrowBoxLeft, + IconCircleQuestionmark, + UserDropdown as UserDropdownRoot, + UserDropdownItem, + Skeleton, + Dropdown, + Button, + DropdownItem, + IconChevronGrabberVertical, + IconLock, + IconKey, + IconPeopleAdd, + IconPlusLarge, + IconCheckmark1, + IconClock, + useToast, + Logo, + Toasts, + ConfirmDialog, + Avatar, + Badge, +} from "@probo/ui"; +import { useTranslate } from "@probo/i18n"; +import { graphql } from "relay-runtime"; +import { useLazyLoadQuery } from "react-relay"; +import type { EmployeeLayoutQuery as EmployeeLayoutQueryType } from "./__generated__/EmployeeLayoutQuery.graphql"; +import { Suspense, useState, useEffect, use } from "react"; +import { ErrorBoundary } from "react-error-boundary"; +import { PageError } from "/components/PageError"; +import { buildEndpoint } from "/providers/RelayProviders"; +import { PermissionsProvider } from "/providers/PermissionsProvider"; +import { PermissionsContext } from "/providers/PermissionsContext"; + +const EmployeeLayoutQuery = graphql` + query EmployeeLayoutQuery($organizationId: ID!) { + viewer { + id + user { + fullName + email + } + } + organization: node(id: $organizationId) { + ... on Organization { + id + name + logoUrl + } + } + } +`; + +export function EmployeeLayout() { + const { organizationId } = useParams(); + + if (!organizationId) { + return ; + } + + return ( + }> + + + + + ); +} + +function EmployeeLayoutContent({ + organizationId, +}: { + organizationId: string; +}) { + const data = useLazyLoadQuery(EmployeeLayoutQuery, { + organizationId, + }); + + return ( +
+
+ + + + +
+ +
+ }> + + +
+
+
+ + + +
+
+ + +
+ ); +} + +interface Organization { + id: string; + name: string; + logoUrl?: string | null; + authenticationMethod: string; + authStatus: "authenticated" | "unauthenticated" | "expired"; + loginUrl: string; +} + +interface OrganizationsResponse { + organizations: Organization[]; +} + +interface Invitation { + id: string; + email: string; + fullName: string; + role: string; + expiresAt: string; + acceptedAt?: string | null; + createdAt: string; + organization: { + id: string; + name: string; + }; +} + +interface InvitationsResponse { + invitations: Invitation[]; +} + +function OrganizationSelector({ + currentOrganization, +}: { + currentOrganization: EmployeeLayoutQueryType["response"]["organization"]; +}) { + const [organizations, setOrganizations] = useState([]); + const [pendingInvitationsCount, setPendingInvitationsCount] = useState(0); + const [isLoading, setIsLoading] = useState(true); + const [error, setError] = useState(null); + const { __ } = useTranslate(); + + useEffect(() => { + const fetchData = async () => { + try { + setIsLoading(true); + + const [orgsResponse, invitationsResponse] = await Promise.all([ + fetch("/connect/organizations", { credentials: "include" }), + fetch("/connect/invitations", { credentials: "include" }), + ]); + + if (!orgsResponse.ok) { + throw new Error("Failed to fetch organizations"); + } + + if (!invitationsResponse.ok) { + throw new Error("Failed to fetch invitations"); + } + + const orgsData: OrganizationsResponse = await orgsResponse.json(); + const invitationsData: InvitationsResponse = + await invitationsResponse.json(); + + const pendingCount = invitationsData.invitations.filter( + (inv) => !inv.acceptedAt + ).length; + + setOrganizations(orgsData.organizations); + setPendingInvitationsCount(pendingCount); + setError(null); + } catch (err) { + setError(err instanceof Error ? err.message : "Unknown error"); + console.error("Failed to fetch data:", err); + } finally { + setIsLoading(false); + } + }; + + fetchData(); + }, []); + + if (error) { + return ( +
+ +
+ ); + } + + return ( +
+ + {isLoading ? __("Loading...") : currentOrganization?.name || ""} + + } + > +
+ {isLoading ? ( +
+ {__("Loading organizations...")} +
+ ) : organizations.length === 0 ? ( +
+ {__("No organizations found")} +
+ ) : ( + organizations.map((organization) => { + const isAuthenticated = + organization.authStatus === "authenticated"; + const isExpired = organization.authStatus === "expired"; + const needsAuth = organization.authStatus === "unauthenticated"; + + const targetUrl = isAuthenticated + ? `/organizations/${organization.id}` + : organization.loginUrl; + + const isSAMLUrl = targetUrl.includes("/connect/saml/"); + + const logoUrl = organization.logoUrl; + + return ( + + {isSAMLUrl ? ( + + + {organization.name} + {isAuthenticated && ( + + )} + {isExpired && ( + + )} + {needsAuth && ( + + )} + + ) : ( + + + {organization.name} + {isAuthenticated && ( + + )} + {isExpired && ( + + )} + {needsAuth && ( + + )} + + )} + + ); + }) + )} +
+ + {pendingInvitationsCount > 0 && ( + + + + {__("Invitations")} + + {pendingInvitationsCount} + + + + )} + + + + {__("Add organization")} + + +
+ {pendingInvitationsCount > 0 && ( + +
+ ); +} + +function UserDropdown({ organizationId }: { organizationId: string }) { + const { __ } = useTranslate(); + const { toast } = useToast(); + const { isAuthorized } = use(PermissionsContext); + const user = useLazyLoadQuery(EmployeeLayoutQuery, { + organizationId, + }).viewer.user; + + const handleLogout: React.MouseEventHandler = async ( + e + ) => { + e.preventDefault(); + + fetch(buildEndpoint("/connect/logout"), { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({}), + }) + .then(async (res) => { + if (!res.ok) { + const error = await res.json(); + throw new Error(error.message || __("Failed to login")); + } + + window.location.reload(); + }) + .catch((e) => { + toast({ + title: __("Error"), + description: e.message as string, + variant: "error", + }); + }); + }; + + return ( + + {isAuthorized("Organization", "deleteOrganization") && ( + + )} + + + + + ); +} diff --git a/apps/console/src/layouts/MainLayout.tsx b/apps/console/src/layouts/MainLayout.tsx index ebca8c065..816de3049 100644 --- a/apps/console/src/layouts/MainLayout.tsx +++ b/apps/console/src/layouts/MainLayout.tsx @@ -299,6 +299,13 @@ function UserDropdown({ organizationId }: { organizationId: string }) { label={__("API Keys")} /> )} + {isAuthorized("Organization", "listSignableDocuments") && ( + + )} > + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck + +import { ConcreteRequest } from 'relay-runtime'; +export type EmployeeLayoutQuery$variables = { + organizationId: string; +}; +export type EmployeeLayoutQuery$data = { + readonly organization: { + readonly id?: string; + readonly logoUrl?: string | null | undefined; + readonly name?: string; + }; + readonly viewer: { + readonly id: string; + readonly user: { + readonly email: string; + readonly fullName: string; + }; + }; +}; +export type EmployeeLayoutQuery = { + response: EmployeeLayoutQuery$data; + variables: EmployeeLayoutQuery$variables; +}; + +const node: ConcreteRequest = (function(){ +var v0 = [ + { + "defaultValue": null, + "kind": "LocalArgument", + "name": "organizationId" + } +], +v1 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "id", + "storageKey": null +}, +v2 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "fullName", + "storageKey": null +}, +v3 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "email", + "storageKey": null +}, +v4 = [ + { + "kind": "Variable", + "name": "id", + "variableName": "organizationId" + } +], +v5 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "name", + "storageKey": null +}, +v6 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "logoUrl", + "storageKey": null +}; +return { + "fragment": { + "argumentDefinitions": (v0/*: any*/), + "kind": "Fragment", + "metadata": null, + "name": "EmployeeLayoutQuery", + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "Viewer", + "kind": "LinkedField", + "name": "viewer", + "plural": false, + "selections": [ + (v1/*: any*/), + { + "alias": null, + "args": null, + "concreteType": "User", + "kind": "LinkedField", + "name": "user", + "plural": false, + "selections": [ + (v2/*: any*/), + (v3/*: any*/) + ], + "storageKey": null + } + ], + "storageKey": null + }, + { + "alias": "organization", + "args": (v4/*: any*/), + "concreteType": null, + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + { + "kind": "InlineFragment", + "selections": [ + (v1/*: any*/), + (v5/*: any*/), + (v6/*: any*/) + ], + "type": "Organization", + "abstractKey": null + } + ], + "storageKey": null + } + ], + "type": "Query", + "abstractKey": null + }, + "kind": "Request", + "operation": { + "argumentDefinitions": (v0/*: any*/), + "kind": "Operation", + "name": "EmployeeLayoutQuery", + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "Viewer", + "kind": "LinkedField", + "name": "viewer", + "plural": false, + "selections": [ + (v1/*: any*/), + { + "alias": null, + "args": null, + "concreteType": "User", + "kind": "LinkedField", + "name": "user", + "plural": false, + "selections": [ + (v2/*: any*/), + (v3/*: any*/), + (v1/*: any*/) + ], + "storageKey": null + } + ], + "storageKey": null + }, + { + "alias": "organization", + "args": (v4/*: any*/), + "concreteType": null, + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "__typename", + "storageKey": null + }, + (v1/*: any*/), + { + "kind": "InlineFragment", + "selections": [ + (v5/*: any*/), + (v6/*: any*/) + ], + "type": "Organization", + "abstractKey": null + } + ], + "storageKey": null + } + ] + }, + "params": { + "cacheID": "64e05cc4b0940458c50a111f2ca42f1a", + "id": null, + "metadata": {}, + "name": "EmployeeLayoutQuery", + "operationKind": "query", + "text": "query EmployeeLayoutQuery(\n $organizationId: ID!\n) {\n viewer {\n id\n user {\n fullName\n email\n id\n }\n }\n organization: node(id: $organizationId) {\n __typename\n ... on Organization {\n id\n name\n logoUrl\n }\n id\n }\n}\n" + } +}; +})(); + +(node as any).hash = "1d30db1e236d19d63e2edcbaf172c34d"; + +export default node; diff --git a/apps/console/src/pages/organizations/continualImprovements/__generated__/ContinualImprovementsPageQuery.graphql.ts b/apps/console/src/pages/organizations/continualImprovements/__generated__/ContinualImprovementsPageQuery.graphql.ts deleted file mode 100644 index c1a8ed780..000000000 --- a/apps/console/src/pages/organizations/continualImprovements/__generated__/ContinualImprovementsPageQuery.graphql.ts +++ /dev/null @@ -1,341 +0,0 @@ -/** - * @generated SignedSource<> - * @lightSyntaxTransform - * @nogrep - */ - -/* tslint:disable */ -/* eslint-disable */ -// @ts-nocheck - -import { ConcreteRequest } from 'relay-runtime'; -import { FragmentRefs } from "relay-runtime"; -export type ContinualImprovementsPageQuery$variables = { - organizationId: string; - snapshotId?: string | null | undefined; -}; -export type ContinualImprovementsPageQuery$data = { - readonly node: { - readonly " $fragmentSpreads": FragmentRefs<"ContinualImprovementsPageFragment">; - }; -}; -export type ContinualImprovementsPageQuery = { - response: ContinualImprovementsPageQuery$data; - variables: ContinualImprovementsPageQuery$variables; -}; - -const node: ConcreteRequest = (function(){ -var v0 = [ - { - "defaultValue": null, - "kind": "LocalArgument", - "name": "organizationId" - }, - { - "defaultValue": null, - "kind": "LocalArgument", - "name": "snapshotId" - } -], -v1 = [ - { - "kind": "Variable", - "name": "id", - "variableName": "organizationId" - } -], -v2 = [ - { - "kind": "Variable", - "name": "snapshotId", - "variableName": "snapshotId" - } -], -v3 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "__typename", - "storageKey": null -}, -v4 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "id", - "storageKey": null -}, -v5 = [ - { - "fields": (v2/*: any*/), - "kind": "ObjectValue", - "name": "filter" - }, - { - "kind": "Literal", - "name": "first", - "value": 10 - } -]; -return { - "fragment": { - "argumentDefinitions": (v0/*: any*/), - "kind": "Fragment", - "metadata": null, - "name": "ContinualImprovementsPageQuery", - "selections": [ - { - "alias": null, - "args": (v1/*: any*/), - "concreteType": null, - "kind": "LinkedField", - "name": "node", - "plural": false, - "selections": [ - { - "kind": "InlineFragment", - "selections": [ - { - "args": (v2/*: any*/), - "kind": "FragmentSpread", - "name": "ContinualImprovementsPageFragment" - } - ], - "type": "Organization", - "abstractKey": null - } - ], - "storageKey": null - } - ], - "type": "Query", - "abstractKey": null - }, - "kind": "Request", - "operation": { - "argumentDefinitions": (v0/*: any*/), - "kind": "Operation", - "name": "ContinualImprovementsPageQuery", - "selections": [ - { - "alias": null, - "args": (v1/*: any*/), - "concreteType": null, - "kind": "LinkedField", - "name": "node", - "plural": false, - "selections": [ - (v3/*: any*/), - (v4/*: any*/), - { - "kind": "InlineFragment", - "selections": [ - { - "alias": null, - "args": (v5/*: any*/), - "concreteType": "ContinualImprovementConnection", - "kind": "LinkedField", - "name": "continualImprovements", - "plural": false, - "selections": [ - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "totalCount", - "storageKey": null - }, - { - "alias": null, - "args": null, - "concreteType": "ContinualImprovementEdge", - "kind": "LinkedField", - "name": "edges", - "plural": true, - "selections": [ - { - "alias": null, - "args": null, - "concreteType": "ContinualImprovement", - "kind": "LinkedField", - "name": "node", - "plural": false, - "selections": [ - (v4/*: any*/), - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "snapshotId", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "sourceId", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "referenceId", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "description", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "source", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "targetDate", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "status", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "priority", - "storageKey": null - }, - { - "alias": null, - "args": null, - "concreteType": "People", - "kind": "LinkedField", - "name": "owner", - "plural": false, - "selections": [ - (v4/*: any*/), - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "fullName", - "storageKey": null - } - ], - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "createdAt", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "updatedAt", - "storageKey": null - }, - (v3/*: any*/) - ], - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "cursor", - "storageKey": null - } - ], - "storageKey": null - }, - { - "alias": null, - "args": null, - "concreteType": "PageInfo", - "kind": "LinkedField", - "name": "pageInfo", - "plural": false, - "selections": [ - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "hasNextPage", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "endCursor", - "storageKey": null - } - ], - "storageKey": null - }, - { - "kind": "ClientExtension", - "selections": [ - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "__id", - "storageKey": null - } - ] - } - ], - "storageKey": null - }, - { - "alias": null, - "args": (v5/*: any*/), - "filters": [ - "filter" - ], - "handle": "connection", - "key": "ContinualImprovementsPage_continualImprovements", - "kind": "LinkedHandle", - "name": "continualImprovements" - } - ], - "type": "Organization", - "abstractKey": null - } - ], - "storageKey": null - } - ] - }, - "params": { - "cacheID": "7213a2ee3776522282ddbc3c46b4002b", - "id": null, - "metadata": {}, - "name": "ContinualImprovementsPageQuery", - "operationKind": "query", - "text": "query ContinualImprovementsPageQuery(\n $organizationId: ID!\n $snapshotId: ID\n) {\n node(id: $organizationId) {\n __typename\n ... on Organization {\n ...ContinualImprovementsPageFragment_3iomuz\n }\n id\n }\n}\n\nfragment ContinualImprovementsPageFragment_3iomuz on Organization {\n id\n continualImprovements(first: 10, filter: {snapshotId: $snapshotId}) {\n totalCount\n edges {\n node {\n id\n snapshotId\n sourceId\n referenceId\n description\n source\n targetDate\n status\n priority\n owner {\n id\n fullName\n }\n createdAt\n updatedAt\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n}\n" - } -}; -})(); - -(node as any).hash = "7baadd4791b1c26eb7315a7755e28a08"; - -export default node; diff --git a/apps/console/src/pages/organizations/employee/EmployeeDocumentSignaturePage.tsx b/apps/console/src/pages/organizations/employee/EmployeeDocumentSignaturePage.tsx new file mode 100644 index 000000000..92704789c --- /dev/null +++ b/apps/console/src/pages/organizations/employee/EmployeeDocumentSignaturePage.tsx @@ -0,0 +1,399 @@ +import { useTranslate } from "@probo/i18n"; +import { + Button, + Card, + Spinner, + IconCircleCheck, + IconRadioUnchecked, +} from "@probo/ui"; +import clsx from "clsx"; +import { + usePreloadedQuery, + useFragment, + useMutation, + type PreloadedQuery, +} from "react-relay"; +import { graphql } from "relay-runtime"; +import type { EmployeeDocumentSignaturePageQuery } from "./__generated__/EmployeeDocumentSignaturePageQuery.graphql"; +import { usePageTitle } from "@probo/hooks"; +import { useMutationWithToasts } from "/hooks/useMutationWithToasts"; +import type { EmployeeDocumentSignaturePageSignMutation } from "./__generated__/EmployeeDocumentSignaturePageSignMutation.graphql"; +import type { EmployeeDocumentSignaturePageExportSignablePDFMutation } from "./__generated__/EmployeeDocumentSignaturePageExportSignablePDFMutation.graphql"; +import { useNavigate } from "react-router"; +import { useOrganizationId } from "/hooks/useOrganizationId"; +import { PDFPreview } from "/components/documents/PDFPreview"; +import { useWindowSize } from "usehooks-ts"; +import { useState, useEffect, useRef, useMemo } from "react"; +import type { EmployeeDocumentSignaturePageDocumentFragment$key } from "./__generated__/EmployeeDocumentSignaturePageDocumentFragment.graphql"; +import type { EmployeeDocumentSignaturePageVersionFragment$key } from "./__generated__/EmployeeDocumentSignaturePageVersionFragment.graphql"; +import { useToast } from "@probo/ui"; +import { formatError, type GraphQLError } from "@probo/helpers"; + +export const employeeDocumentSignatureQuery = graphql` + query EmployeeDocumentSignaturePageQuery($documentId: ID!) { + viewer { + id + signableDocument(id: $documentId) { + id + ...EmployeeDocumentSignaturePageDocumentFragment + } + } + } +`; + +const documentFragment = graphql` + fragment EmployeeDocumentSignaturePageDocumentFragment on SignableDocument { + id + title + signed + versions(first: 100, orderBy: { field: CREATED_AT, direction: DESC }) { + edges { + node { + id + ...EmployeeDocumentSignaturePageVersionFragment + } + } + } + } +`; + +const versionFragment = graphql` + fragment EmployeeDocumentSignaturePageVersionFragment on DocumentVersion { + id + version + signed + publishedAt + } +`; + +const signDocumentMutation = graphql` + mutation EmployeeDocumentSignaturePageSignMutation($input: SignDocumentInput!) { + signDocument(input: $input) { + documentVersionSignature { + id + state + } + } + } +`; + +const exportSignableVersionDocumentPDFMutation = graphql` + mutation EmployeeDocumentSignaturePageExportSignablePDFMutation( + $input: ExportSignableDocumentVersionPDFInput! + ) { + exportSignableVersionDocumentPDF(input: $input) { + data + } + } +`; + +type Props = { + queryRef: PreloadedQuery; +}; + +export default function EmployeeDocumentSignaturePage(props: Props) { + const data = usePreloadedQuery(employeeDocumentSignatureQuery, props.queryRef); + const document = data.viewer.signableDocument; + + if (!document) { + return ( +
+ +
+ ); + } + + return ; +} + +function DocumentSignatureContent({ + document, +}: { + document: EmployeeDocumentSignaturePageDocumentFragment$key; +}) { + const { __ } = useTranslate(); + const navigate = useNavigate(); + const { width } = useWindowSize(); + const isMobile = width < 1100; + const isDesktop = !isMobile; + const organizationId = useOrganizationId(); + + const documentData = useFragment( + documentFragment, + document + ); + + const versions = useMemo(() => { + return documentData.versions?.edges + ?.map((edge) => edge?.node) + .filter(Boolean) || []; + }, [documentData.versions?.edges]); + + const [selectedVersionId, setSelectedVersionId] = useState( + () => versions[0]?.id + ); + + const selectedVersion = useMemo(() => { + return versions.find((v) => v?.id === selectedVersionId); + }, [versions, selectedVersionId]); + + usePageTitle(__("Sign Document")); + const { toast } = useToast(); + + const [signDocument, isSigning] = useMutationWithToasts( + signDocumentMutation, + { + successMessage: __("Document signed successfully"), + errorMessage: __("Failed to sign document"), + } + ); + + const [exportSignableVersionDocumentPDF] = useMutation( + exportSignableVersionDocumentPDFMutation + ); + + const [pdfUrl, setPdfUrl] = useState(null); + const pdfUrlRef = useRef(null); + + const handleSign = async (versionId: string) => { + await signDocument({ + variables: { + input: { + documentVersionId: versionId, + }, + }, + updater: (store) => { + const signableDoc = store.get(documentData.id); + if (signableDoc) { + signableDoc.setValue(true, "signed"); + } + store.invalidateStore(); + }, + onCompleted: () => { + navigate(`/organizations/${organizationId}/employee`); + }, + onError: (error) => { + console.error("Error signing document:", error); + }, + }); + }; + + useEffect(() => { + if (!selectedVersion?.id) return; + + exportSignableVersionDocumentPDF({ + variables: { + input: { + documentVersionId: selectedVersion.id, + }, + }, + onCompleted: (data, errors): void => { + if (errors) { + toast({ + title: __("Error"), + description: formatError(__("Failed to load PDF"), errors as GraphQLError[]), + variant: "error", + }); + return; + } + if (data.exportSignableVersionDocumentPDF?.data) { + const dataUrl = data.exportSignableVersionDocumentPDF.data; + pdfUrlRef.current = dataUrl; + setPdfUrl(dataUrl); + } + }, + onError: (error) => { + toast({ + title: __("Error"), + description: formatError(__("Failed to load PDF"), error as GraphQLError), + variant: "error", + }); + }, + }); + + return () => { + pdfUrlRef.current = null; + }; + }, [selectedVersion?.id, exportSignableVersionDocumentPDF, toast, __]); + + return ( +
+
+
+

+ {documentData.title || ""} +

+ + +
+ {versions.map((version) => { + return ( + setSelectedVersionId(version.id)} + /> + ); + })} +
+
+ +

+ {__("Please review the document carefully before signing.")} +

+ +
+ {selectedVersion ? ( + navigate(`/organizations/${organizationId}/employee`)} + /> + ) : null} +
+
+ + {isDesktop && ( +
+ {pdfUrl && } +
+ )} +
+
+ ); +} + +function VersionActions({ + version, + isSigning, + onSign, + onBack, +}: { + version: EmployeeDocumentSignaturePageVersionFragment$key; + isSigning: boolean; + onSign: (versionId: string) => void; + onBack: () => void; +}) { + const { __ } = useTranslate(); + const versionData = useFragment( + versionFragment, + version + ); + const isSigned = versionData.signed; + + if (isSigned) { + return ( + <> + +

+ + ); + } + + return ( + <> + +

+ {__( + "By clicking 'I acknowledge and agree', your digital signature will be recorded." + )} +

+ + ); +} + +function VersionRow({ + version, + isSelected, + onSelect, +}: { + version: EmployeeDocumentSignaturePageVersionFragment$key; + isSelected: boolean; + onSelect: () => void; +}) { + const { __ } = useTranslate(); + const versionData = useFragment( + versionFragment, + version + ); + const isVersionSigned = versionData.signed; + + return ( +
+
+ {isVersionSigned ? ( + + ) : ( + + )} +
+
+

+ {versionData.publishedAt + ? `v${versionData.version} - ${(() => { + const date = new Date(versionData.publishedAt); + const day = String(date.getDate()).padStart(2, '0'); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const year = date.getFullYear(); + return `${day}/${month}/${year}`; + })()}` + : `v${versionData.version}`} +

+
+
+ + {isVersionSigned + ? __("Signed") + : isSelected + ? __("In review") + : __("Waiting signature")} + +
+
+ ); +} diff --git a/apps/console/src/pages/organizations/employee/EmployeeDocumentsPage.tsx b/apps/console/src/pages/organizations/employee/EmployeeDocumentsPage.tsx new file mode 100644 index 000000000..d36ffc1e5 --- /dev/null +++ b/apps/console/src/pages/organizations/employee/EmployeeDocumentsPage.tsx @@ -0,0 +1,180 @@ +import { useTranslate } from "@probo/i18n"; +import { + PageHeader, + Tbody, + Thead, + Tr, + Th, + Td, + Badge, + Card, +} from "@probo/ui"; +import { SortableTable } from "/components/SortableTable"; +import { + useFragment, + usePaginationFragment, + usePreloadedQuery, + type PreloadedQuery, +} from "react-relay"; +import { graphql } from "relay-runtime"; +import type { EmployeeDocumentsPageListQuery } from "./__generated__/EmployeeDocumentsPageListQuery.graphql"; +import type { EmployeeDocumentsPageListFragment$key } from "./__generated__/EmployeeDocumentsPageListFragment.graphql"; +import { usePageTitle } from "@probo/hooks"; +import { getDocumentClassificationLabel, getDocumentTypeLabel, formatDate } from "@probo/helpers"; +import type { EmployeeDocumentsPageRowFragment$key } from "./__generated__/EmployeeDocumentsPageRowFragment.graphql"; +import { useEffect } from "react"; +import { useParams } from "react-router"; + +export const employeeDocumentsQuery = graphql` + query EmployeeDocumentsPageListQuery($organizationId: ID!) { + viewer { + id + ...EmployeeDocumentsPageListFragment @arguments(organizationId: $organizationId) + } + } +`; + +const employeeDocumentsFragment = graphql` + fragment EmployeeDocumentsPageListFragment on Viewer + @refetchable(queryName: "EmployeeDocumentsListQuery") + @argumentDefinitions( + organizationId: { type: "ID!" } + first: { type: "Int", defaultValue: 50 } + order: { + type: "DocumentOrder" + defaultValue: { field: CREATED_AT, direction: DESC } + } + after: { type: "CursorKey", defaultValue: null } + before: { type: "CursorKey", defaultValue: null } + last: { type: "Int", defaultValue: null } + ) { + signableDocuments( + organizationId: $organizationId + first: $first + after: $after + last: $last + before: $before + orderBy: $order + ) @connection(key: "EmployeeDocumentsListQuery_signableDocuments") { + __id + edges { + node { + id + ...EmployeeDocumentsPageRowFragment + } + } + } + } +`; + +type Props = { + queryRef: PreloadedQuery; +}; + +export default function EmployeeDocumentsPage(props: Props) { + const { __ } = useTranslate(); + const params = useParams<{ organizationId: string }>(); + const organizationId = params.organizationId!; + + const data = usePreloadedQuery( + employeeDocumentsQuery, + props.queryRef + ); + + const pagination = usePaginationFragment( + employeeDocumentsFragment, + data.viewer as EmployeeDocumentsPageListFragment$key + ); + + const { refetch } = pagination; + + useEffect(() => { + refetch({ organizationId }, { fetchPolicy: 'network-only' }); + }, [organizationId, refetch]); + + const documents = pagination.data.signableDocuments?.edges + ?.map((edge) => edge?.node) + .filter(Boolean) || []; + + usePageTitle(__("Documents")); + + return ( +
+ + {documents.length > 0 ? ( + + + + {__("Name")} + {__("Type")} + {__("Classification")} + {__("Last update")} + {__("Signed")} + + + + {documents.map((document) => ( + + ))} + + + ) : ( + +
+

+ {__("No documents yet")} +

+

+ {__("No documents have been requested for your signature.")} +

+
+
+ )} +
+ ); +} + +const rowFragment = graphql` + fragment EmployeeDocumentsPageRowFragment on SignableDocument { + id + title + documentType + classification + signed + updatedAt + } +`; + +function DocumentRow({ + document: documentKey, + organizationId, +}: { + document: EmployeeDocumentsPageRowFragment$key; + organizationId: string; +}) { + const document = useFragment( + rowFragment, + documentKey + ); + const { __ } = useTranslate(); + + return ( + + {document.title} + {getDocumentTypeLabel(__, document.documentType)} + + + {getDocumentClassificationLabel(__, document.classification)} + + + {formatDate(document.updatedAt)} + + + {document.signed ? __("Yes") : __("No")} + + + + ); +} diff --git a/apps/console/src/pages/organizations/employee/__generated__/EmployeeDocumentSignaturePageDocumentFragment.graphql.ts b/apps/console/src/pages/organizations/employee/__generated__/EmployeeDocumentSignaturePageDocumentFragment.graphql.ts new file mode 100644 index 000000000..a3d7634bf --- /dev/null +++ b/apps/console/src/pages/organizations/employee/__generated__/EmployeeDocumentSignaturePageDocumentFragment.graphql.ts @@ -0,0 +1,122 @@ +/** + * @generated SignedSource<<29c63d1f06c36d3670b5a4757b725b95>> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck + +import { ReaderFragment } from 'relay-runtime'; +import { FragmentRefs } from "relay-runtime"; +export type EmployeeDocumentSignaturePageDocumentFragment$data = { + readonly id: string; + readonly signed: boolean; + readonly title: string; + readonly versions: { + readonly edges: ReadonlyArray<{ + readonly node: { + readonly id: string; + readonly " $fragmentSpreads": FragmentRefs<"EmployeeDocumentSignaturePageVersionFragment">; + }; + }>; + }; + readonly " $fragmentType": "EmployeeDocumentSignaturePageDocumentFragment"; +}; +export type EmployeeDocumentSignaturePageDocumentFragment$key = { + readonly " $data"?: EmployeeDocumentSignaturePageDocumentFragment$data; + readonly " $fragmentSpreads": FragmentRefs<"EmployeeDocumentSignaturePageDocumentFragment">; +}; + +const node: ReaderFragment = (function(){ +var v0 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "id", + "storageKey": null +}; +return { + "argumentDefinitions": [], + "kind": "Fragment", + "metadata": null, + "name": "EmployeeDocumentSignaturePageDocumentFragment", + "selections": [ + (v0/*: any*/), + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "title", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "signed", + "storageKey": null + }, + { + "alias": null, + "args": [ + { + "kind": "Literal", + "name": "first", + "value": 100 + }, + { + "kind": "Literal", + "name": "orderBy", + "value": { + "direction": "DESC", + "field": "CREATED_AT" + } + } + ], + "concreteType": "DocumentVersionConnection", + "kind": "LinkedField", + "name": "versions", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "DocumentVersionEdge", + "kind": "LinkedField", + "name": "edges", + "plural": true, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "DocumentVersion", + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + (v0/*: any*/), + { + "args": null, + "kind": "FragmentSpread", + "name": "EmployeeDocumentSignaturePageVersionFragment" + } + ], + "storageKey": null + } + ], + "storageKey": null + } + ], + "storageKey": "versions(first:100,orderBy:{\"direction\":\"DESC\",\"field\":\"CREATED_AT\"})" + } + ], + "type": "SignableDocument", + "abstractKey": null +}; +})(); + +(node as any).hash = "a516f97725320f4fe0282d70cef83a62"; + +export default node; diff --git a/apps/console/src/pages/organizations/employee/__generated__/EmployeeDocumentSignaturePageExportSignablePDFMutation.graphql.ts b/apps/console/src/pages/organizations/employee/__generated__/EmployeeDocumentSignaturePageExportSignablePDFMutation.graphql.ts new file mode 100644 index 000000000..214d581bb --- /dev/null +++ b/apps/console/src/pages/organizations/employee/__generated__/EmployeeDocumentSignaturePageExportSignablePDFMutation.graphql.ts @@ -0,0 +1,92 @@ +/** + * @generated SignedSource<> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck + +import { ConcreteRequest } from 'relay-runtime'; +export type ExportSignableDocumentVersionPDFInput = { + documentVersionId: string; +}; +export type EmployeeDocumentSignaturePageExportSignablePDFMutation$variables = { + input: ExportSignableDocumentVersionPDFInput; +}; +export type EmployeeDocumentSignaturePageExportSignablePDFMutation$data = { + readonly exportSignableVersionDocumentPDF: { + readonly data: string; + }; +}; +export type EmployeeDocumentSignaturePageExportSignablePDFMutation = { + response: EmployeeDocumentSignaturePageExportSignablePDFMutation$data; + variables: EmployeeDocumentSignaturePageExportSignablePDFMutation$variables; +}; + +const node: ConcreteRequest = (function(){ +var v0 = [ + { + "defaultValue": null, + "kind": "LocalArgument", + "name": "input" + } +], +v1 = [ + { + "alias": null, + "args": [ + { + "kind": "Variable", + "name": "input", + "variableName": "input" + } + ], + "concreteType": "ExportSignableDocumentVersionPDFPayload", + "kind": "LinkedField", + "name": "exportSignableVersionDocumentPDF", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "data", + "storageKey": null + } + ], + "storageKey": null + } +]; +return { + "fragment": { + "argumentDefinitions": (v0/*: any*/), + "kind": "Fragment", + "metadata": null, + "name": "EmployeeDocumentSignaturePageExportSignablePDFMutation", + "selections": (v1/*: any*/), + "type": "Mutation", + "abstractKey": null + }, + "kind": "Request", + "operation": { + "argumentDefinitions": (v0/*: any*/), + "kind": "Operation", + "name": "EmployeeDocumentSignaturePageExportSignablePDFMutation", + "selections": (v1/*: any*/) + }, + "params": { + "cacheID": "1bbeaaac843ecd06e9f7ee662aa11fc2", + "id": null, + "metadata": {}, + "name": "EmployeeDocumentSignaturePageExportSignablePDFMutation", + "operationKind": "mutation", + "text": "mutation EmployeeDocumentSignaturePageExportSignablePDFMutation(\n $input: ExportSignableDocumentVersionPDFInput!\n) {\n exportSignableVersionDocumentPDF(input: $input) {\n data\n }\n}\n" + } +}; +})(); + +(node as any).hash = "39a1e34d4b4f8c98d262dd3a737ebb7c"; + +export default node; diff --git a/apps/console/src/pages/organizations/employee/__generated__/EmployeeDocumentSignaturePageQuery.graphql.ts b/apps/console/src/pages/organizations/employee/__generated__/EmployeeDocumentSignaturePageQuery.graphql.ts new file mode 100644 index 000000000..a6004841c --- /dev/null +++ b/apps/console/src/pages/organizations/employee/__generated__/EmployeeDocumentSignaturePageQuery.graphql.ts @@ -0,0 +1,215 @@ +/** + * @generated SignedSource<<9e8c0459987993bb4b217618a46fdbf5>> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck + +import { ConcreteRequest } from 'relay-runtime'; +import { FragmentRefs } from "relay-runtime"; +export type EmployeeDocumentSignaturePageQuery$variables = { + documentId: string; +}; +export type EmployeeDocumentSignaturePageQuery$data = { + readonly viewer: { + readonly id: string; + readonly signableDocument: { + readonly id: string; + readonly " $fragmentSpreads": FragmentRefs<"EmployeeDocumentSignaturePageDocumentFragment">; + } | null | undefined; + }; +}; +export type EmployeeDocumentSignaturePageQuery = { + response: EmployeeDocumentSignaturePageQuery$data; + variables: EmployeeDocumentSignaturePageQuery$variables; +}; + +const node: ConcreteRequest = (function(){ +var v0 = [ + { + "defaultValue": null, + "kind": "LocalArgument", + "name": "documentId" + } +], +v1 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "id", + "storageKey": null +}, +v2 = [ + { + "kind": "Variable", + "name": "id", + "variableName": "documentId" + } +], +v3 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "signed", + "storageKey": null +}; +return { + "fragment": { + "argumentDefinitions": (v0/*: any*/), + "kind": "Fragment", + "metadata": null, + "name": "EmployeeDocumentSignaturePageQuery", + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "Viewer", + "kind": "LinkedField", + "name": "viewer", + "plural": false, + "selections": [ + (v1/*: any*/), + { + "alias": null, + "args": (v2/*: any*/), + "concreteType": "SignableDocument", + "kind": "LinkedField", + "name": "signableDocument", + "plural": false, + "selections": [ + (v1/*: any*/), + { + "args": null, + "kind": "FragmentSpread", + "name": "EmployeeDocumentSignaturePageDocumentFragment" + } + ], + "storageKey": null + } + ], + "storageKey": null + } + ], + "type": "Query", + "abstractKey": null + }, + "kind": "Request", + "operation": { + "argumentDefinitions": (v0/*: any*/), + "kind": "Operation", + "name": "EmployeeDocumentSignaturePageQuery", + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "Viewer", + "kind": "LinkedField", + "name": "viewer", + "plural": false, + "selections": [ + (v1/*: any*/), + { + "alias": null, + "args": (v2/*: any*/), + "concreteType": "SignableDocument", + "kind": "LinkedField", + "name": "signableDocument", + "plural": false, + "selections": [ + (v1/*: any*/), + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "title", + "storageKey": null + }, + (v3/*: any*/), + { + "alias": null, + "args": [ + { + "kind": "Literal", + "name": "first", + "value": 100 + }, + { + "kind": "Literal", + "name": "orderBy", + "value": { + "direction": "DESC", + "field": "CREATED_AT" + } + } + ], + "concreteType": "DocumentVersionConnection", + "kind": "LinkedField", + "name": "versions", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "DocumentVersionEdge", + "kind": "LinkedField", + "name": "edges", + "plural": true, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "DocumentVersion", + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + (v1/*: any*/), + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "version", + "storageKey": null + }, + (v3/*: any*/), + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "publishedAt", + "storageKey": null + } + ], + "storageKey": null + } + ], + "storageKey": null + } + ], + "storageKey": "versions(first:100,orderBy:{\"direction\":\"DESC\",\"field\":\"CREATED_AT\"})" + } + ], + "storageKey": null + } + ], + "storageKey": null + } + ] + }, + "params": { + "cacheID": "a4866db288e1bf46e6562aa06bff4231", + "id": null, + "metadata": {}, + "name": "EmployeeDocumentSignaturePageQuery", + "operationKind": "query", + "text": "query EmployeeDocumentSignaturePageQuery(\n $documentId: ID!\n) {\n viewer {\n id\n signableDocument(id: $documentId) {\n id\n ...EmployeeDocumentSignaturePageDocumentFragment\n }\n }\n}\n\nfragment EmployeeDocumentSignaturePageDocumentFragment on SignableDocument {\n id\n title\n signed\n versions(first: 100, orderBy: {field: CREATED_AT, direction: DESC}) {\n edges {\n node {\n id\n ...EmployeeDocumentSignaturePageVersionFragment\n }\n }\n }\n}\n\nfragment EmployeeDocumentSignaturePageVersionFragment on DocumentVersion {\n id\n version\n signed\n publishedAt\n}\n" + } +}; +})(); + +(node as any).hash = "a2ac190853e8f078ff90213605a66e29"; + +export default node; diff --git a/apps/console/src/pages/organizations/employee/__generated__/EmployeeDocumentSignaturePageSignMutation.graphql.ts b/apps/console/src/pages/organizations/employee/__generated__/EmployeeDocumentSignaturePageSignMutation.graphql.ts new file mode 100644 index 000000000..84f2d8090 --- /dev/null +++ b/apps/console/src/pages/organizations/employee/__generated__/EmployeeDocumentSignaturePageSignMutation.graphql.ts @@ -0,0 +1,114 @@ +/** + * @generated SignedSource<> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck + +import { ConcreteRequest } from 'relay-runtime'; +export type DocumentVersionSignatureState = "REQUESTED" | "SIGNED"; +export type SignDocumentInput = { + documentVersionId: string; +}; +export type EmployeeDocumentSignaturePageSignMutation$variables = { + input: SignDocumentInput; +}; +export type EmployeeDocumentSignaturePageSignMutation$data = { + readonly signDocument: { + readonly documentVersionSignature: { + readonly id: string; + readonly state: DocumentVersionSignatureState; + }; + }; +}; +export type EmployeeDocumentSignaturePageSignMutation = { + response: EmployeeDocumentSignaturePageSignMutation$data; + variables: EmployeeDocumentSignaturePageSignMutation$variables; +}; + +const node: ConcreteRequest = (function(){ +var v0 = [ + { + "defaultValue": null, + "kind": "LocalArgument", + "name": "input" + } +], +v1 = [ + { + "alias": null, + "args": [ + { + "kind": "Variable", + "name": "input", + "variableName": "input" + } + ], + "concreteType": "SignDocumentPayload", + "kind": "LinkedField", + "name": "signDocument", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "DocumentVersionSignature", + "kind": "LinkedField", + "name": "documentVersionSignature", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "id", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "state", + "storageKey": null + } + ], + "storageKey": null + } + ], + "storageKey": null + } +]; +return { + "fragment": { + "argumentDefinitions": (v0/*: any*/), + "kind": "Fragment", + "metadata": null, + "name": "EmployeeDocumentSignaturePageSignMutation", + "selections": (v1/*: any*/), + "type": "Mutation", + "abstractKey": null + }, + "kind": "Request", + "operation": { + "argumentDefinitions": (v0/*: any*/), + "kind": "Operation", + "name": "EmployeeDocumentSignaturePageSignMutation", + "selections": (v1/*: any*/) + }, + "params": { + "cacheID": "dfdd778fc4b0cfc9c007e4c29258ea96", + "id": null, + "metadata": {}, + "name": "EmployeeDocumentSignaturePageSignMutation", + "operationKind": "mutation", + "text": "mutation EmployeeDocumentSignaturePageSignMutation(\n $input: SignDocumentInput!\n) {\n signDocument(input: $input) {\n documentVersionSignature {\n id\n state\n }\n }\n}\n" + } +}; +})(); + +(node as any).hash = "b91674332a1914e270e4fb811ccfd479"; + +export default node; diff --git a/apps/console/src/pages/organizations/employee/__generated__/EmployeeDocumentSignaturePageVersionFragment.graphql.ts b/apps/console/src/pages/organizations/employee/__generated__/EmployeeDocumentSignaturePageVersionFragment.graphql.ts new file mode 100644 index 000000000..679b90768 --- /dev/null +++ b/apps/console/src/pages/organizations/employee/__generated__/EmployeeDocumentSignaturePageVersionFragment.graphql.ts @@ -0,0 +1,66 @@ +/** + * @generated SignedSource<> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck + +import { ReaderFragment } from 'relay-runtime'; +import { FragmentRefs } from "relay-runtime"; +export type EmployeeDocumentSignaturePageVersionFragment$data = { + readonly id: string; + readonly publishedAt: any | null | undefined; + readonly signed: boolean; + readonly version: number; + readonly " $fragmentType": "EmployeeDocumentSignaturePageVersionFragment"; +}; +export type EmployeeDocumentSignaturePageVersionFragment$key = { + readonly " $data"?: EmployeeDocumentSignaturePageVersionFragment$data; + readonly " $fragmentSpreads": FragmentRefs<"EmployeeDocumentSignaturePageVersionFragment">; +}; + +const node: ReaderFragment = { + "argumentDefinitions": [], + "kind": "Fragment", + "metadata": null, + "name": "EmployeeDocumentSignaturePageVersionFragment", + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "id", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "version", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "signed", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "publishedAt", + "storageKey": null + } + ], + "type": "DocumentVersion", + "abstractKey": null +}; + +(node as any).hash = "4a85fbbc1bf8b2610f554aa439fd0e95"; + +export default node; diff --git a/apps/console/src/pages/organizations/employee/__generated__/EmployeeDocumentsListQuery.graphql.ts b/apps/console/src/pages/organizations/employee/__generated__/EmployeeDocumentsListQuery.graphql.ts new file mode 100644 index 000000000..5ee3df321 --- /dev/null +++ b/apps/console/src/pages/organizations/employee/__generated__/EmployeeDocumentsListQuery.graphql.ts @@ -0,0 +1,334 @@ +/** + * @generated SignedSource<<6caec1429cd03b026975c0e9ef7c76f6>> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck + +import { ConcreteRequest } from 'relay-runtime'; +import { FragmentRefs } from "relay-runtime"; +export type DocumentOrderField = "CREATED_AT" | "DOCUMENT_TYPE" | "TITLE"; +export type OrderDirection = "ASC" | "DESC"; +export type DocumentOrder = { + direction: OrderDirection; + field: DocumentOrderField; +}; +export type EmployeeDocumentsListQuery$variables = { + after?: any | null | undefined; + before?: any | null | undefined; + first?: number | null | undefined; + last?: number | null | undefined; + order?: DocumentOrder | null | undefined; + organizationId: string; +}; +export type EmployeeDocumentsListQuery$data = { + readonly viewer: { + readonly " $fragmentSpreads": FragmentRefs<"EmployeeDocumentsPageListFragment">; + }; +}; +export type EmployeeDocumentsListQuery = { + response: EmployeeDocumentsListQuery$data; + variables: EmployeeDocumentsListQuery$variables; +}; + +const node: ConcreteRequest = (function(){ +var v0 = [ + { + "defaultValue": null, + "kind": "LocalArgument", + "name": "after" + }, + { + "defaultValue": null, + "kind": "LocalArgument", + "name": "before" + }, + { + "defaultValue": 50, + "kind": "LocalArgument", + "name": "first" + }, + { + "defaultValue": null, + "kind": "LocalArgument", + "name": "last" + }, + { + "defaultValue": { + "direction": "DESC", + "field": "CREATED_AT" + }, + "kind": "LocalArgument", + "name": "order" + }, + { + "defaultValue": null, + "kind": "LocalArgument", + "name": "organizationId" + } +], +v1 = { + "kind": "Variable", + "name": "after", + "variableName": "after" +}, +v2 = { + "kind": "Variable", + "name": "before", + "variableName": "before" +}, +v3 = { + "kind": "Variable", + "name": "first", + "variableName": "first" +}, +v4 = { + "kind": "Variable", + "name": "last", + "variableName": "last" +}, +v5 = { + "kind": "Variable", + "name": "organizationId", + "variableName": "organizationId" +}, +v6 = [ + (v1/*: any*/), + (v2/*: any*/), + (v3/*: any*/), + (v4/*: any*/), + { + "kind": "Variable", + "name": "orderBy", + "variableName": "order" + }, + (v5/*: any*/) +], +v7 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "id", + "storageKey": null +}; +return { + "fragment": { + "argumentDefinitions": (v0/*: any*/), + "kind": "Fragment", + "metadata": null, + "name": "EmployeeDocumentsListQuery", + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "Viewer", + "kind": "LinkedField", + "name": "viewer", + "plural": false, + "selections": [ + { + "args": [ + (v1/*: any*/), + (v2/*: any*/), + (v3/*: any*/), + (v4/*: any*/), + { + "kind": "Variable", + "name": "order", + "variableName": "order" + }, + (v5/*: any*/) + ], + "kind": "FragmentSpread", + "name": "EmployeeDocumentsPageListFragment" + } + ], + "storageKey": null + } + ], + "type": "Query", + "abstractKey": null + }, + "kind": "Request", + "operation": { + "argumentDefinitions": (v0/*: any*/), + "kind": "Operation", + "name": "EmployeeDocumentsListQuery", + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "Viewer", + "kind": "LinkedField", + "name": "viewer", + "plural": false, + "selections": [ + { + "alias": null, + "args": (v6/*: any*/), + "concreteType": "SignableDocumentConnection", + "kind": "LinkedField", + "name": "signableDocuments", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "SignableDocumentEdge", + "kind": "LinkedField", + "name": "edges", + "plural": true, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "SignableDocument", + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + (v7/*: any*/), + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "title", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "documentType", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "classification", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "signed", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "updatedAt", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "__typename", + "storageKey": null + } + ], + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "cursor", + "storageKey": null + } + ], + "storageKey": null + }, + { + "alias": null, + "args": null, + "concreteType": "PageInfo", + "kind": "LinkedField", + "name": "pageInfo", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "endCursor", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "hasNextPage", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "hasPreviousPage", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "startCursor", + "storageKey": null + } + ], + "storageKey": null + }, + { + "kind": "ClientExtension", + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "__id", + "storageKey": null + } + ] + } + ], + "storageKey": null + }, + { + "alias": null, + "args": (v6/*: any*/), + "filters": [ + "organizationId", + "orderBy" + ], + "handle": "connection", + "key": "EmployeeDocumentsListQuery_signableDocuments", + "kind": "LinkedHandle", + "name": "signableDocuments" + }, + (v7/*: any*/) + ], + "storageKey": null + } + ] + }, + "params": { + "cacheID": "32e793fba0e3d2e46857cd1b8c436ba2", + "id": null, + "metadata": {}, + "name": "EmployeeDocumentsListQuery", + "operationKind": "query", + "text": "query EmployeeDocumentsListQuery(\n $after: CursorKey = null\n $before: CursorKey = null\n $first: Int = 50\n $last: Int = null\n $order: DocumentOrder = {field: CREATED_AT, direction: DESC}\n $organizationId: ID!\n) {\n viewer {\n ...EmployeeDocumentsPageListFragment_KjvVI\n id\n }\n}\n\nfragment EmployeeDocumentsPageListFragment_KjvVI on Viewer {\n signableDocuments(organizationId: $organizationId, first: $first, after: $after, last: $last, before: $before, orderBy: $order) {\n edges {\n node {\n id\n ...EmployeeDocumentsPageRowFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n}\n\nfragment EmployeeDocumentsPageRowFragment on SignableDocument {\n id\n title\n documentType\n classification\n signed\n updatedAt\n}\n" + } +}; +})(); + +(node as any).hash = "ebd2703f79cdf6900b5e42fc3b28932a"; + +export default node; diff --git a/apps/console/src/pages/organizations/employee/__generated__/EmployeeDocumentsPageListFragment.graphql.ts b/apps/console/src/pages/organizations/employee/__generated__/EmployeeDocumentsPageListFragment.graphql.ts new file mode 100644 index 000000000..3ef47c1ca --- /dev/null +++ b/apps/console/src/pages/organizations/employee/__generated__/EmployeeDocumentsPageListFragment.graphql.ts @@ -0,0 +1,231 @@ +/** + * @generated SignedSource<<47bb54b1ca3acc8736d619a74455a9c3>> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck + +import { ReaderFragment } from 'relay-runtime'; +import { FragmentRefs } from "relay-runtime"; +export type EmployeeDocumentsPageListFragment$data = { + readonly signableDocuments: { + readonly __id: string; + readonly edges: ReadonlyArray<{ + readonly node: { + readonly id: string; + readonly " $fragmentSpreads": FragmentRefs<"EmployeeDocumentsPageRowFragment">; + }; + }>; + }; + readonly " $fragmentType": "EmployeeDocumentsPageListFragment"; +}; +export type EmployeeDocumentsPageListFragment$key = { + readonly " $data"?: EmployeeDocumentsPageListFragment$data; + readonly " $fragmentSpreads": FragmentRefs<"EmployeeDocumentsPageListFragment">; +}; + +import EmployeeDocumentsListQuery_graphql from './EmployeeDocumentsListQuery.graphql'; + +const node: ReaderFragment = (function(){ +var v0 = [ + "signableDocuments" +]; +return { + "argumentDefinitions": [ + { + "defaultValue": null, + "kind": "LocalArgument", + "name": "after" + }, + { + "defaultValue": null, + "kind": "LocalArgument", + "name": "before" + }, + { + "defaultValue": 50, + "kind": "LocalArgument", + "name": "first" + }, + { + "defaultValue": null, + "kind": "LocalArgument", + "name": "last" + }, + { + "defaultValue": { + "direction": "DESC", + "field": "CREATED_AT" + }, + "kind": "LocalArgument", + "name": "order" + }, + { + "defaultValue": null, + "kind": "LocalArgument", + "name": "organizationId" + } + ], + "kind": "Fragment", + "metadata": { + "connection": [ + { + "count": null, + "cursor": null, + "direction": "bidirectional", + "path": (v0/*: any*/) + } + ], + "refetch": { + "connection": { + "forward": { + "count": "first", + "cursor": "after" + }, + "backward": { + "count": "last", + "cursor": "before" + }, + "path": (v0/*: any*/) + }, + "fragmentPathInResult": [ + "viewer" + ], + "operation": EmployeeDocumentsListQuery_graphql + } + }, + "name": "EmployeeDocumentsPageListFragment", + "selections": [ + { + "alias": "signableDocuments", + "args": [ + { + "kind": "Variable", + "name": "orderBy", + "variableName": "order" + }, + { + "kind": "Variable", + "name": "organizationId", + "variableName": "organizationId" + } + ], + "concreteType": "SignableDocumentConnection", + "kind": "LinkedField", + "name": "__EmployeeDocumentsListQuery_signableDocuments_connection", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "SignableDocumentEdge", + "kind": "LinkedField", + "name": "edges", + "plural": true, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "SignableDocument", + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "id", + "storageKey": null + }, + { + "args": null, + "kind": "FragmentSpread", + "name": "EmployeeDocumentsPageRowFragment" + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "__typename", + "storageKey": null + } + ], + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "cursor", + "storageKey": null + } + ], + "storageKey": null + }, + { + "alias": null, + "args": null, + "concreteType": "PageInfo", + "kind": "LinkedField", + "name": "pageInfo", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "endCursor", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "hasNextPage", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "hasPreviousPage", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "startCursor", + "storageKey": null + } + ], + "storageKey": null + }, + { + "kind": "ClientExtension", + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "__id", + "storageKey": null + } + ] + } + ], + "storageKey": null + } + ], + "type": "Viewer", + "abstractKey": null +}; +})(); + +(node as any).hash = "ebd2703f79cdf6900b5e42fc3b28932a"; + +export default node; diff --git a/apps/console/src/pages/organizations/employee/__generated__/EmployeeDocumentsPageListQuery.graphql.ts b/apps/console/src/pages/organizations/employee/__generated__/EmployeeDocumentsPageListQuery.graphql.ts new file mode 100644 index 000000000..9858b3db2 --- /dev/null +++ b/apps/console/src/pages/organizations/employee/__generated__/EmployeeDocumentsPageListQuery.graphql.ts @@ -0,0 +1,272 @@ +/** + * @generated SignedSource<> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck + +import { ConcreteRequest } from 'relay-runtime'; +import { FragmentRefs } from "relay-runtime"; +export type EmployeeDocumentsPageListQuery$variables = { + organizationId: string; +}; +export type EmployeeDocumentsPageListQuery$data = { + readonly viewer: { + readonly id: string; + readonly " $fragmentSpreads": FragmentRefs<"EmployeeDocumentsPageListFragment">; + }; +}; +export type EmployeeDocumentsPageListQuery = { + response: EmployeeDocumentsPageListQuery$data; + variables: EmployeeDocumentsPageListQuery$variables; +}; + +const node: ConcreteRequest = (function(){ +var v0 = [ + { + "defaultValue": null, + "kind": "LocalArgument", + "name": "organizationId" + } +], +v1 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "id", + "storageKey": null +}, +v2 = { + "kind": "Variable", + "name": "organizationId", + "variableName": "organizationId" +}, +v3 = [ + { + "kind": "Literal", + "name": "first", + "value": 50 + }, + { + "kind": "Literal", + "name": "orderBy", + "value": { + "direction": "DESC", + "field": "CREATED_AT" + } + }, + (v2/*: any*/) +]; +return { + "fragment": { + "argumentDefinitions": (v0/*: any*/), + "kind": "Fragment", + "metadata": null, + "name": "EmployeeDocumentsPageListQuery", + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "Viewer", + "kind": "LinkedField", + "name": "viewer", + "plural": false, + "selections": [ + (v1/*: any*/), + { + "args": [ + (v2/*: any*/) + ], + "kind": "FragmentSpread", + "name": "EmployeeDocumentsPageListFragment" + } + ], + "storageKey": null + } + ], + "type": "Query", + "abstractKey": null + }, + "kind": "Request", + "operation": { + "argumentDefinitions": (v0/*: any*/), + "kind": "Operation", + "name": "EmployeeDocumentsPageListQuery", + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "Viewer", + "kind": "LinkedField", + "name": "viewer", + "plural": false, + "selections": [ + (v1/*: any*/), + { + "alias": null, + "args": (v3/*: any*/), + "concreteType": "SignableDocumentConnection", + "kind": "LinkedField", + "name": "signableDocuments", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "SignableDocumentEdge", + "kind": "LinkedField", + "name": "edges", + "plural": true, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "SignableDocument", + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + (v1/*: any*/), + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "title", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "documentType", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "classification", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "signed", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "updatedAt", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "__typename", + "storageKey": null + } + ], + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "cursor", + "storageKey": null + } + ], + "storageKey": null + }, + { + "alias": null, + "args": null, + "concreteType": "PageInfo", + "kind": "LinkedField", + "name": "pageInfo", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "endCursor", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "hasNextPage", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "hasPreviousPage", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "startCursor", + "storageKey": null + } + ], + "storageKey": null + }, + { + "kind": "ClientExtension", + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "__id", + "storageKey": null + } + ] + } + ], + "storageKey": null + }, + { + "alias": null, + "args": (v3/*: any*/), + "filters": [ + "organizationId", + "orderBy" + ], + "handle": "connection", + "key": "EmployeeDocumentsListQuery_signableDocuments", + "kind": "LinkedHandle", + "name": "signableDocuments" + } + ], + "storageKey": null + } + ] + }, + "params": { + "cacheID": "e0d165b36ce3e65b6c3e7a4d3620ba7e", + "id": null, + "metadata": {}, + "name": "EmployeeDocumentsPageListQuery", + "operationKind": "query", + "text": "query EmployeeDocumentsPageListQuery(\n $organizationId: ID!\n) {\n viewer {\n id\n ...EmployeeDocumentsPageListFragment_4xMPKw\n }\n}\n\nfragment EmployeeDocumentsPageListFragment_4xMPKw on Viewer {\n signableDocuments(organizationId: $organizationId, first: 50, orderBy: {field: CREATED_AT, direction: DESC}) {\n edges {\n node {\n id\n ...EmployeeDocumentsPageRowFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n}\n\nfragment EmployeeDocumentsPageRowFragment on SignableDocument {\n id\n title\n documentType\n classification\n signed\n updatedAt\n}\n" + } +}; +})(); + +(node as any).hash = "8c281fd3823eb1894c0b46807e04e370"; + +export default node; diff --git a/apps/console/src/pages/organizations/employee/__generated__/EmployeeDocumentsPageRowFragment.graphql.ts b/apps/console/src/pages/organizations/employee/__generated__/EmployeeDocumentsPageRowFragment.graphql.ts new file mode 100644 index 000000000..9f18a5e29 --- /dev/null +++ b/apps/console/src/pages/organizations/employee/__generated__/EmployeeDocumentsPageRowFragment.graphql.ts @@ -0,0 +1,84 @@ +/** + * @generated SignedSource<> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck + +import { ReaderFragment } from 'relay-runtime'; +export type DocumentClassification = "CONFIDENTIAL" | "INTERNAL" | "PUBLIC" | "SECRET"; +export type DocumentType = "ISMS" | "OTHER" | "POLICY" | "PROCEDURE"; +import { FragmentRefs } from "relay-runtime"; +export type EmployeeDocumentsPageRowFragment$data = { + readonly classification: DocumentClassification; + readonly documentType: DocumentType; + readonly id: string; + readonly signed: boolean; + readonly title: string; + readonly updatedAt: any; + readonly " $fragmentType": "EmployeeDocumentsPageRowFragment"; +}; +export type EmployeeDocumentsPageRowFragment$key = { + readonly " $data"?: EmployeeDocumentsPageRowFragment$data; + readonly " $fragmentSpreads": FragmentRefs<"EmployeeDocumentsPageRowFragment">; +}; + +const node: ReaderFragment = { + "argumentDefinitions": [], + "kind": "Fragment", + "metadata": null, + "name": "EmployeeDocumentsPageRowFragment", + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "id", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "title", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "documentType", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "classification", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "signed", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "updatedAt", + "storageKey": null + } + ], + "type": "SignableDocument", + "abstractKey": null +}; + +(node as any).hash = "929301e6f6216fb0678b32061b70dd17"; + +export default node; diff --git a/apps/console/src/pages/organizations/nonconformities/__generated__/NonconformitiesPageQuery.graphql.ts b/apps/console/src/pages/organizations/nonconformities/__generated__/NonconformitiesPageQuery.graphql.ts deleted file mode 100644 index db43ed5ee..000000000 --- a/apps/console/src/pages/organizations/nonconformities/__generated__/NonconformitiesPageQuery.graphql.ts +++ /dev/null @@ -1,381 +0,0 @@ -/** - * @generated SignedSource<<3292b0059f82a3a5c1316f9312379621>> - * @lightSyntaxTransform - * @nogrep - */ - -/* tslint:disable */ -/* eslint-disable */ -// @ts-nocheck - -import { ConcreteRequest } from 'relay-runtime'; -import { FragmentRefs } from "relay-runtime"; -export type NonconformitiesPageQuery$variables = { - organizationId: string; - snapshotId?: string | null | undefined; -}; -export type NonconformitiesPageQuery$data = { - readonly node: { - readonly " $fragmentSpreads": FragmentRefs<"NonconformitiesPageFragment">; - }; -}; -export type NonconformitiesPageQuery = { - response: NonconformitiesPageQuery$data; - variables: NonconformitiesPageQuery$variables; -}; - -const node: ConcreteRequest = (function(){ -var v0 = [ - { - "defaultValue": null, - "kind": "LocalArgument", - "name": "organizationId" - }, - { - "defaultValue": null, - "kind": "LocalArgument", - "name": "snapshotId" - } -], -v1 = [ - { - "kind": "Variable", - "name": "id", - "variableName": "organizationId" - } -], -v2 = [ - { - "kind": "Variable", - "name": "snapshotId", - "variableName": "snapshotId" - } -], -v3 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "__typename", - "storageKey": null -}, -v4 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "id", - "storageKey": null -}, -v5 = [ - { - "fields": (v2/*: any*/), - "kind": "ObjectValue", - "name": "filter" - }, - { - "kind": "Literal", - "name": "first", - "value": 10 - } -], -v6 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "name", - "storageKey": null -}; -return { - "fragment": { - "argumentDefinitions": (v0/*: any*/), - "kind": "Fragment", - "metadata": null, - "name": "NonconformitiesPageQuery", - "selections": [ - { - "alias": null, - "args": (v1/*: any*/), - "concreteType": null, - "kind": "LinkedField", - "name": "node", - "plural": false, - "selections": [ - { - "kind": "InlineFragment", - "selections": [ - { - "args": (v2/*: any*/), - "kind": "FragmentSpread", - "name": "NonconformitiesPageFragment" - } - ], - "type": "Organization", - "abstractKey": null - } - ], - "storageKey": null - } - ], - "type": "Query", - "abstractKey": null - }, - "kind": "Request", - "operation": { - "argumentDefinitions": (v0/*: any*/), - "kind": "Operation", - "name": "NonconformitiesPageQuery", - "selections": [ - { - "alias": null, - "args": (v1/*: any*/), - "concreteType": null, - "kind": "LinkedField", - "name": "node", - "plural": false, - "selections": [ - (v3/*: any*/), - (v4/*: any*/), - { - "kind": "InlineFragment", - "selections": [ - { - "alias": null, - "args": (v5/*: any*/), - "concreteType": "NonconformityConnection", - "kind": "LinkedField", - "name": "nonconformities", - "plural": false, - "selections": [ - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "totalCount", - "storageKey": null - }, - { - "alias": null, - "args": null, - "concreteType": "NonconformityEdge", - "kind": "LinkedField", - "name": "edges", - "plural": true, - "selections": [ - { - "alias": null, - "args": null, - "concreteType": "Nonconformity", - "kind": "LinkedField", - "name": "node", - "plural": false, - "selections": [ - (v4/*: any*/), - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "referenceId", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "snapshotId", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "description", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "status", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "dateIdentified", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "dueDate", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "rootCause", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "correctiveAction", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "effectivenessCheck", - "storageKey": null - }, - { - "alias": null, - "args": null, - "concreteType": "Audit", - "kind": "LinkedField", - "name": "audit", - "plural": false, - "selections": [ - (v4/*: any*/), - (v6/*: any*/), - { - "alias": null, - "args": null, - "concreteType": "Framework", - "kind": "LinkedField", - "name": "framework", - "plural": false, - "selections": [ - (v4/*: any*/), - (v6/*: any*/) - ], - "storageKey": null - } - ], - "storageKey": null - }, - { - "alias": null, - "args": null, - "concreteType": "People", - "kind": "LinkedField", - "name": "owner", - "plural": false, - "selections": [ - (v4/*: any*/), - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "fullName", - "storageKey": null - } - ], - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "createdAt", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "updatedAt", - "storageKey": null - }, - (v3/*: any*/) - ], - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "cursor", - "storageKey": null - } - ], - "storageKey": null - }, - { - "alias": null, - "args": null, - "concreteType": "PageInfo", - "kind": "LinkedField", - "name": "pageInfo", - "plural": false, - "selections": [ - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "hasNextPage", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "endCursor", - "storageKey": null - } - ], - "storageKey": null - }, - { - "kind": "ClientExtension", - "selections": [ - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "__id", - "storageKey": null - } - ] - } - ], - "storageKey": null - }, - { - "alias": null, - "args": (v5/*: any*/), - "filters": [ - "filter" - ], - "handle": "connection", - "key": "NonconformitiesPage_nonconformities", - "kind": "LinkedHandle", - "name": "nonconformities" - } - ], - "type": "Organization", - "abstractKey": null - } - ], - "storageKey": null - } - ] - }, - "params": { - "cacheID": "b4f53542e4ea747099f28629d5e8a0bb", - "id": null, - "metadata": {}, - "name": "NonconformitiesPageQuery", - "operationKind": "query", - "text": "query NonconformitiesPageQuery(\n $organizationId: ID!\n $snapshotId: ID\n) {\n node(id: $organizationId) {\n __typename\n ... on Organization {\n ...NonconformitiesPageFragment_3iomuz\n }\n id\n }\n}\n\nfragment NonconformitiesPageFragment_3iomuz on Organization {\n id\n nonconformities(first: 10, filter: {snapshotId: $snapshotId}) {\n totalCount\n edges {\n node {\n id\n referenceId\n snapshotId\n description\n status\n dateIdentified\n dueDate\n rootCause\n correctiveAction\n effectivenessCheck\n audit {\n id\n name\n framework {\n id\n name\n }\n }\n owner {\n id\n fullName\n }\n createdAt\n updatedAt\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n}\n" - } -}; -})(); - -(node as any).hash = "af4a93239b6065756759b4958980b846"; - -export default node; diff --git a/apps/console/src/pages/organizations/obligations/__generated__/ObligationsPageQuery.graphql.ts b/apps/console/src/pages/organizations/obligations/__generated__/ObligationsPageQuery.graphql.ts deleted file mode 100644 index 985c7dd35..000000000 --- a/apps/console/src/pages/organizations/obligations/__generated__/ObligationsPageQuery.graphql.ts +++ /dev/null @@ -1,355 +0,0 @@ -/** - * @generated SignedSource<<445c6cc243eadbe9e5eacdec0161ee62>> - * @lightSyntaxTransform - * @nogrep - */ - -/* tslint:disable */ -/* eslint-disable */ -// @ts-nocheck - -import { ConcreteRequest } from 'relay-runtime'; -import { FragmentRefs } from "relay-runtime"; -export type ObligationsPageQuery$variables = { - organizationId: string; - snapshotId?: string | null | undefined; -}; -export type ObligationsPageQuery$data = { - readonly node: { - readonly " $fragmentSpreads": FragmentRefs<"ObligationsPageFragment">; - }; -}; -export type ObligationsPageQuery = { - response: ObligationsPageQuery$data; - variables: ObligationsPageQuery$variables; -}; - -const node: ConcreteRequest = (function(){ -var v0 = [ - { - "defaultValue": null, - "kind": "LocalArgument", - "name": "organizationId" - }, - { - "defaultValue": null, - "kind": "LocalArgument", - "name": "snapshotId" - } -], -v1 = [ - { - "kind": "Variable", - "name": "id", - "variableName": "organizationId" - } -], -v2 = [ - { - "kind": "Variable", - "name": "snapshotId", - "variableName": "snapshotId" - } -], -v3 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "__typename", - "storageKey": null -}, -v4 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "id", - "storageKey": null -}, -v5 = [ - { - "fields": (v2/*: any*/), - "kind": "ObjectValue", - "name": "filter" - }, - { - "kind": "Literal", - "name": "first", - "value": 10 - } -]; -return { - "fragment": { - "argumentDefinitions": (v0/*: any*/), - "kind": "Fragment", - "metadata": null, - "name": "ObligationsPageQuery", - "selections": [ - { - "alias": null, - "args": (v1/*: any*/), - "concreteType": null, - "kind": "LinkedField", - "name": "node", - "plural": false, - "selections": [ - { - "kind": "InlineFragment", - "selections": [ - { - "args": (v2/*: any*/), - "kind": "FragmentSpread", - "name": "ObligationsPageFragment" - } - ], - "type": "Organization", - "abstractKey": null - } - ], - "storageKey": null - } - ], - "type": "Query", - "abstractKey": null - }, - "kind": "Request", - "operation": { - "argumentDefinitions": (v0/*: any*/), - "kind": "Operation", - "name": "ObligationsPageQuery", - "selections": [ - { - "alias": null, - "args": (v1/*: any*/), - "concreteType": null, - "kind": "LinkedField", - "name": "node", - "plural": false, - "selections": [ - (v3/*: any*/), - (v4/*: any*/), - { - "kind": "InlineFragment", - "selections": [ - { - "alias": null, - "args": (v5/*: any*/), - "concreteType": "ObligationConnection", - "kind": "LinkedField", - "name": "obligations", - "plural": false, - "selections": [ - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "totalCount", - "storageKey": null - }, - { - "alias": null, - "args": null, - "concreteType": "ObligationEdge", - "kind": "LinkedField", - "name": "edges", - "plural": true, - "selections": [ - { - "alias": null, - "args": null, - "concreteType": "Obligation", - "kind": "LinkedField", - "name": "node", - "plural": false, - "selections": [ - (v4/*: any*/), - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "snapshotId", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "sourceId", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "area", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "source", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "requirement", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "status", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "lastReviewDate", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "dueDate", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "actionsToBeImplemented", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "regulator", - "storageKey": null - }, - { - "alias": null, - "args": null, - "concreteType": "People", - "kind": "LinkedField", - "name": "owner", - "plural": false, - "selections": [ - (v4/*: any*/), - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "fullName", - "storageKey": null - } - ], - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "createdAt", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "updatedAt", - "storageKey": null - }, - (v3/*: any*/) - ], - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "cursor", - "storageKey": null - } - ], - "storageKey": null - }, - { - "alias": null, - "args": null, - "concreteType": "PageInfo", - "kind": "LinkedField", - "name": "pageInfo", - "plural": false, - "selections": [ - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "hasNextPage", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "endCursor", - "storageKey": null - } - ], - "storageKey": null - }, - { - "kind": "ClientExtension", - "selections": [ - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "__id", - "storageKey": null - } - ] - } - ], - "storageKey": null - }, - { - "alias": null, - "args": (v5/*: any*/), - "filters": [ - "filter" - ], - "handle": "connection", - "key": "ObligationsPage_obligations", - "kind": "LinkedHandle", - "name": "obligations" - } - ], - "type": "Organization", - "abstractKey": null - } - ], - "storageKey": null - } - ] - }, - "params": { - "cacheID": "9a4d2f4ac3be91001f8c9bb602cd599f", - "id": null, - "metadata": {}, - "name": "ObligationsPageQuery", - "operationKind": "query", - "text": "query ObligationsPageQuery(\n $organizationId: ID!\n $snapshotId: ID\n) {\n node(id: $organizationId) {\n __typename\n ... on Organization {\n ...ObligationsPageFragment_3iomuz\n }\n id\n }\n}\n\nfragment ObligationsPageFragment_3iomuz on Organization {\n id\n obligations(first: 10, filter: {snapshotId: $snapshotId}) {\n totalCount\n edges {\n node {\n id\n snapshotId\n sourceId\n area\n source\n requirement\n status\n lastReviewDate\n dueDate\n actionsToBeImplemented\n regulator\n owner {\n id\n fullName\n }\n createdAt\n updatedAt\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n}\n" - } -}; -})(); - -(node as any).hash = "720209ab225ef7a42f1edb96e5d58aa1"; - -export default node; diff --git a/apps/console/src/pages/organizations/processingActivities/__generated__/ProcessingActivitiesPageQuery.graphql.ts b/apps/console/src/pages/organizations/processingActivities/__generated__/ProcessingActivitiesPageQuery.graphql.ts deleted file mode 100644 index 4b8a5dd50..000000000 --- a/apps/console/src/pages/organizations/processingActivities/__generated__/ProcessingActivitiesPageQuery.graphql.ts +++ /dev/null @@ -1,329 +0,0 @@ -/** - * @generated SignedSource<> - * @lightSyntaxTransform - * @nogrep - */ - -/* tslint:disable */ -/* eslint-disable */ -// @ts-nocheck - -import { ConcreteRequest } from 'relay-runtime'; -import { FragmentRefs } from "relay-runtime"; -export type ProcessingActivitiesPageQuery$variables = { - organizationId: string; - snapshotId?: string | null | undefined; -}; -export type ProcessingActivitiesPageQuery$data = { - readonly node: { - readonly " $fragmentSpreads": FragmentRefs<"ProcessingActivitiesPageFragment">; - }; -}; -export type ProcessingActivitiesPageQuery = { - response: ProcessingActivitiesPageQuery$data; - variables: ProcessingActivitiesPageQuery$variables; -}; - -const node: ConcreteRequest = (function(){ -var v0 = [ - { - "defaultValue": null, - "kind": "LocalArgument", - "name": "organizationId" - }, - { - "defaultValue": null, - "kind": "LocalArgument", - "name": "snapshotId" - } -], -v1 = [ - { - "kind": "Variable", - "name": "id", - "variableName": "organizationId" - } -], -v2 = [ - { - "kind": "Variable", - "name": "snapshotId", - "variableName": "snapshotId" - } -], -v3 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "__typename", - "storageKey": null -}, -v4 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "id", - "storageKey": null -}, -v5 = [ - { - "fields": (v2/*: any*/), - "kind": "ObjectValue", - "name": "filter" - }, - { - "kind": "Literal", - "name": "first", - "value": 10 - } -]; -return { - "fragment": { - "argumentDefinitions": (v0/*: any*/), - "kind": "Fragment", - "metadata": null, - "name": "ProcessingActivitiesPageQuery", - "selections": [ - { - "alias": null, - "args": (v1/*: any*/), - "concreteType": null, - "kind": "LinkedField", - "name": "node", - "plural": false, - "selections": [ - { - "kind": "InlineFragment", - "selections": [ - { - "args": (v2/*: any*/), - "kind": "FragmentSpread", - "name": "ProcessingActivitiesPageFragment" - } - ], - "type": "Organization", - "abstractKey": null - } - ], - "storageKey": null - } - ], - "type": "Query", - "abstractKey": null - }, - "kind": "Request", - "operation": { - "argumentDefinitions": (v0/*: any*/), - "kind": "Operation", - "name": "ProcessingActivitiesPageQuery", - "selections": [ - { - "alias": null, - "args": (v1/*: any*/), - "concreteType": null, - "kind": "LinkedField", - "name": "node", - "plural": false, - "selections": [ - (v3/*: any*/), - (v4/*: any*/), - { - "kind": "InlineFragment", - "selections": [ - { - "alias": null, - "args": (v5/*: any*/), - "concreteType": "ProcessingActivityConnection", - "kind": "LinkedField", - "name": "processingActivities", - "plural": false, - "selections": [ - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "totalCount", - "storageKey": null - }, - { - "alias": null, - "args": null, - "concreteType": "ProcessingActivityEdge", - "kind": "LinkedField", - "name": "edges", - "plural": true, - "selections": [ - { - "alias": null, - "args": null, - "concreteType": "ProcessingActivity", - "kind": "LinkedField", - "name": "node", - "plural": false, - "selections": [ - (v4/*: any*/), - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "snapshotId", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "sourceId", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "name", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "purpose", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "dataSubjectCategory", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "personalDataCategory", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "lawfulBasis", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "location", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "internationalTransfers", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "createdAt", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "updatedAt", - "storageKey": null - }, - (v3/*: any*/) - ], - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "cursor", - "storageKey": null - } - ], - "storageKey": null - }, - { - "alias": null, - "args": null, - "concreteType": "PageInfo", - "kind": "LinkedField", - "name": "pageInfo", - "plural": false, - "selections": [ - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "hasNextPage", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "endCursor", - "storageKey": null - } - ], - "storageKey": null - }, - { - "kind": "ClientExtension", - "selections": [ - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "__id", - "storageKey": null - } - ] - } - ], - "storageKey": null - }, - { - "alias": null, - "args": (v5/*: any*/), - "filters": [ - "filter" - ], - "handle": "connection", - "key": "ProcessingActivitiesPage_processingActivities", - "kind": "LinkedHandle", - "name": "processingActivities" - } - ], - "type": "Organization", - "abstractKey": null - } - ], - "storageKey": null - } - ] - }, - "params": { - "cacheID": "dfb1835056b3e318e7d1b8a9e351dcaf", - "id": null, - "metadata": {}, - "name": "ProcessingActivitiesPageQuery", - "operationKind": "query", - "text": "query ProcessingActivitiesPageQuery(\n $organizationId: ID!\n $snapshotId: ID\n) {\n node(id: $organizationId) {\n __typename\n ... on Organization {\n ...ProcessingActivitiesPageFragment_3iomuz\n }\n id\n }\n}\n\nfragment ProcessingActivitiesPageFragment_3iomuz on Organization {\n id\n processingActivities(first: 10, filter: {snapshotId: $snapshotId}) {\n totalCount\n edges {\n node {\n id\n snapshotId\n sourceId\n name\n purpose\n dataSubjectCategory\n personalDataCategory\n lawfulBasis\n location\n internationalTransfers\n createdAt\n updatedAt\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n}\n" - } -}; -})(); - -(node as any).hash = "68aa1223c7d37dec18879900c126bd42"; - -export default node; diff --git a/apps/console/src/pages/organizations/settings/__generated__/MembersSettingsTabInvitationsFragment.graphql.ts b/apps/console/src/pages/organizations/settings/__generated__/MembersSettingsTabInvitationsFragment.graphql.ts index f68f7999d..268773ae8 100644 --- a/apps/console/src/pages/organizations/settings/__generated__/MembersSettingsTabInvitationsFragment.graphql.ts +++ b/apps/console/src/pages/organizations/settings/__generated__/MembersSettingsTabInvitationsFragment.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<0a1a073bbc42108dd13e235594c27457>> + * @generated SignedSource<<0bd95d20e79294c530610625c86e88d7>> * @lightSyntaxTransform * @nogrep */ @@ -10,7 +10,7 @@ import { ReaderFragment } from 'relay-runtime'; export type InvitationStatus = "ACCEPTED" | "EXPIRED" | "PENDING"; -export type MembershipRole = "ADMIN" | "OWNER" | "VIEWER"; +export type MembershipRole = "ADMIN" | "EMPLOYEE" | "OWNER" | "VIEWER"; import { FragmentRefs } from "relay-runtime"; export type MembersSettingsTabInvitationsFragment$data = { readonly id: string; diff --git a/apps/console/src/pages/organizations/settings/__generated__/MembersSettingsTabMembershipsFragment.graphql.ts b/apps/console/src/pages/organizations/settings/__generated__/MembersSettingsTabMembershipsFragment.graphql.ts index e9970b1d0..011bdb503 100644 --- a/apps/console/src/pages/organizations/settings/__generated__/MembersSettingsTabMembershipsFragment.graphql.ts +++ b/apps/console/src/pages/organizations/settings/__generated__/MembersSettingsTabMembershipsFragment.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<752dcbc2d152883fa2ac09b52039f01c>> + * @generated SignedSource<<8fcd99714c4bf7dba138fcb0de398a3a>> * @lightSyntaxTransform * @nogrep */ @@ -9,7 +9,7 @@ // @ts-nocheck import { ReaderFragment } from 'relay-runtime'; -export type MembershipRole = "ADMIN" | "OWNER" | "VIEWER"; +export type MembershipRole = "ADMIN" | "EMPLOYEE" | "OWNER" | "VIEWER"; export type UserAuthMethod = "PASSWORD" | "SAML"; import { FragmentRefs } from "relay-runtime"; export type MembersSettingsTabMembershipsFragment$data = { diff --git a/apps/console/src/pages/organizations/settings/__generated__/MembersSettingsTab_UpdateMembershipMutation.graphql.ts b/apps/console/src/pages/organizations/settings/__generated__/MembersSettingsTab_UpdateMembershipMutation.graphql.ts index 2927ada90..988ed6bbf 100644 --- a/apps/console/src/pages/organizations/settings/__generated__/MembersSettingsTab_UpdateMembershipMutation.graphql.ts +++ b/apps/console/src/pages/organizations/settings/__generated__/MembersSettingsTab_UpdateMembershipMutation.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<562744e07bdb502c26aebe267b181b0e>> + * @generated SignedSource<<9aaf763355340403cfd0c9666b61be19>> * @lightSyntaxTransform * @nogrep */ @@ -9,7 +9,7 @@ // @ts-nocheck import { ConcreteRequest } from 'relay-runtime'; -export type MembershipRole = "ADMIN" | "OWNER" | "VIEWER"; +export type MembershipRole = "ADMIN" | "EMPLOYEE" | "OWNER" | "VIEWER"; export type UpdateMembershipInput = { memberId: string; organizationId: string; diff --git a/apps/console/src/routes.tsx b/apps/console/src/routes.tsx index f7d15b129..b38d4fb4f 100644 --- a/apps/console/src/routes.tsx +++ b/apps/console/src/routes.tsx @@ -5,8 +5,8 @@ import { useRouteError, } from "react-router"; import { MainLayout } from "./layouts/MainLayout"; +import { EmployeeLayout } from "./layouts/EmployeeLayout"; import { AuthLayout, CenteredLayout, CenteredLayoutSkeleton } from "@probo/ui"; -import { Fragment } from "react"; import { relayEnvironment, UnAuthenticatedError, @@ -36,6 +36,11 @@ import { continualImprovementRoutes } from "./routes/continualImprovementRoutes. import { processingActivityRoutes } from "./routes/processingActivityRoutes.ts"; import { lazy } from "@probo/react-lazy"; import { loaderFromQueryLoader, routeFromAppRoute, withQueryRef, type AppRoute } from "@probo/routes"; +import { employeeDocumentsQuery } from "./pages/organizations/employee/EmployeeDocumentsPage"; +import { employeeDocumentSignatureQuery } from "./pages/organizations/employee/EmployeeDocumentSignaturePage"; +import { Role } from "@probo/helpers"; +import { PermissionsContext } from "./providers/PermissionsContext"; +import { use } from "react"; /** * Top level error boundary @@ -117,6 +122,40 @@ const routes = [ }, ], }, + { + path: "/organizations/:organizationId/employee", + Component: EmployeeLayout, + ErrorBoundary: ErrorBoundary, + children: [ + { + path: "", + Fallback: PageSkeleton, + loader: loaderFromQueryLoader( + ({ organizationId }) => + loadQuery(relayEnvironment, employeeDocumentsQuery, { + organizationId: organizationId!, + }) + ), + Component: withQueryRef(lazy( + () => import("./pages/organizations/employee/EmployeeDocumentsPage") + )), + }, + { + path: ":documentId", + Fallback: PageSkeleton, + ErrorBoundary: ErrorBoundary, + loader: loaderFromQueryLoader( + ({ documentId }) => + loadQuery(relayEnvironment, employeeDocumentSignatureQuery, { + documentId: documentId!, + }) + ), + Component: withQueryRef(lazy( + () => import("./pages/organizations/employee/EmployeeDocumentSignaturePage") + )), + }, + ], + }, { path: "/organizations/:organizationId", Component: MainLayout, @@ -124,10 +163,13 @@ const routes = [ children: [ { path: "", - loader: () => { - throw redirect(`tasks`); + Component: () => { + const { role } = use(PermissionsContext); + if (role === Role.EMPLOYEE) { + return ; + } + return ; }, - Component: Fragment, }, { path: "settings", diff --git a/packages/helpers/src/roles.ts b/packages/helpers/src/roles.ts index 95a5aab2b..e67ce6fcc 100644 --- a/packages/helpers/src/roles.ts +++ b/packages/helpers/src/roles.ts @@ -2,6 +2,7 @@ export const Role = { OWNER: "OWNER", ADMIN: "ADMIN", VIEWER: "VIEWER", + EMPLOYEE: "EMPLOYEE", } as const export type Role = (typeof Role)[keyof typeof Role]; @@ -16,4 +17,4 @@ export function getAssignableRoles(currentRole: Role): Role[] { } return []; -} \ No newline at end of file +} diff --git a/pkg/auth/saml_mapper.go b/pkg/auth/saml_mapper.go index 99388d9d2..9fa2fd130 100644 --- a/pkg/auth/saml_mapper.go +++ b/pkg/auth/saml_mapper.go @@ -88,7 +88,7 @@ func MapSAMLRoleToSystemRole(samlRole string) *coredata.MembershipRole { func isValidRole(role string) bool { switch role { - case "OWNER", "ADMIN", "VIEWER": + case "OWNER", "ADMIN", "EMPLOYEE", "VIEWER": return true default: return false diff --git a/pkg/authz/permissions.go b/pkg/authz/permissions.go index de9e4555d..ed34e90e0 100644 --- a/pkg/authz/permissions.go +++ b/pkg/authz/permissions.go @@ -27,10 +27,11 @@ type ( ) const ( - RoleOwner Role = "OWNER" - RoleAdmin Role = "ADMIN" - RoleViewer Role = "VIEWER" - RoleFull Role = "FULL" + RoleOwner Role = "OWNER" + RoleAdmin Role = "ADMIN" + RoleEmployee Role = "EMPLOYEE" + RoleViewer Role = "VIEWER" + RoleFull Role = "FULL" ) const ( @@ -43,6 +44,7 @@ const ( ActionGetBusinessOwner Action = "getBusinessOwner" ActionGetCustomDomain Action = "getCustomDomain" ActionGetDataPrivacyAgreement Action = "getDataPrivacyAgreement" + ActionGetDocument Action = "getDocument" ActionGetFile Action = "getFile" ActionGetFileUrl Action = "getFileUrl" ActionGetFramework Action = "getFramework" @@ -53,6 +55,8 @@ const ( ActionGetOrganization Action = "getOrganization" ActionGetOwner Action = "getOwner" ActionGetSecurityOwner Action = "getSecurityOwner" + ActionGetSigned Action = "getSigned" + ActionGetSignableDocument Action = "getSignableDocument" ActionGetSnapshot Action = "getSnapshot" ActionGetTask Action = "getTask" ActionGetTrustCenter Action = "getTrustCenter" @@ -62,7 +66,6 @@ const ( ActionActiveCount Action = "activeCount" ActionAudit Action = "audit" ActionAvailableDocumentAccesses Action = "availableDocumentAccesses" - ActionDocument Action = "document" ActionDocumentVersion Action = "documentVersion" ActionDownloadUrl Action = "downloadUrl" ActionMemberships Action = "memberships" @@ -77,36 +80,38 @@ const ( ActionTotalCount Action = "totalCount" ActionTrustCenterFile Action = "trustCenterFile" - ActionListAccesses Action = "listAccesses" - ActionListAssets Action = "listAssets" - ActionListAudits Action = "listAudits" - ActionListComplianceReports Action = "listComplianceReports" - ActionListContacts Action = "listContacts" - ActionListContinualImprovements Action = "listContinualImprovements" - ActionListControls Action = "listControls" - ActionListData Action = "listData" - ActionListDocuments Action = "listDocuments" - ActionListEvidences Action = "listEvidences" - ActionListFrameworks Action = "listFrameworks" - ActionListInvitations Action = "listInvitations" - ActionListMeasures Action = "listMeasures" - ActionListMeetings Action = "listMeetings" - ActionListMembers Action = "listMembers" - ActionListNonconformities Action = "listNonconformities" - ActionListObligations Action = "listObligations" - ActionListPeople Action = "listPeople" - ActionListProcessingActivities Action = "listProcessingActivities" - ActionListReferences Action = "listReferences" - ActionListRiskAssessments Action = "listRiskAssessments" - ActionListRisks Action = "listRisks" - ActionListSAMLConfigurations Action = "listSAMLConfigurations" - ActionListServices Action = "listServices" - ActionListSlackConnections Action = "listSlackConnections" - ActionListSnapshots Action = "listSnapshots" - ActionListTasks Action = "listTasks" - ActionListTrustCenterFiles Action = "listTrustCenterFiles" - ActionListVendors Action = "listVendors" - ActionListVersions Action = "listVersions" + ActionListAccesses Action = "listAccesses" + ActionListAssets Action = "listAssets" + ActionListAudits Action = "listAudits" + ActionListComplianceReports Action = "listComplianceReports" + ActionListContacts Action = "listContacts" + ActionListContinualImprovements Action = "listContinualImprovements" + ActionListControls Action = "listControls" + ActionListData Action = "listData" + ActionListDocuments Action = "listDocuments" + ActionListEvidences Action = "listEvidences" + ActionListFrameworks Action = "listFrameworks" + ActionListInvitations Action = "listInvitations" + ActionListMeasures Action = "listMeasures" + ActionListMeetings Action = "listMeetings" + ActionListMembers Action = "listMembers" + ActionListNonconformities Action = "listNonconformities" + ActionListObligations Action = "listObligations" + ActionListPeople Action = "listPeople" + ActionListProcessingActivities Action = "listProcessingActivities" + ActionListReferences Action = "listReferences" + ActionListRiskAssessments Action = "listRiskAssessments" + ActionListRisks Action = "listRisks" + ActionListSAMLConfigurations Action = "listSAMLConfigurations" + ActionListServices Action = "listServices" + ActionListSlackConnections Action = "listSlackConnections" + ActionListSnapshots Action = "listSnapshots" + ActionListTasks Action = "listTasks" + ActionListTrustCenterFiles Action = "listTrustCenterFiles" + ActionListVendors Action = "listVendors" + ActionListVersions Action = "listVersions" + ActionListSignableDocuments Action = "listSignableDocuments" + ActionListSignableDocumentVersion Action = "listSignableDocumentVersion" ActionCreateAsset Action = "createAsset" ActionCreateAudit Action = "createAudit" @@ -222,10 +227,12 @@ const ( ActionBulkPublishDocumentVersions Action = "bulkPublishDocumentVersions" ActionBulkRequestSignatures Action = "bulkRequestSignatures" ActionCancelSignatureRequest Action = "cancelSignatureRequest" + ActionSignDocument Action = "signDocument" ActionConfirmEmail Action = "confirmEmail" ActionDisableSAML Action = "disableSAML" ActionEnableSAML Action = "enableSAML" ActionExportDocumentVersionPDF Action = "exportDocumentVersionPDF" + ActionExportSignableVersionDocumentPDF Action = "exportSignableVersionDocumentPDF" ActionExportFramework Action = "exportFramework" ActionGenerateDocumentChangelog Action = "generateDocumentChangelog" ActionGenerateFrameworkStateOfApplicability Action = "generateFrameworkStateOfApplicability" @@ -248,45 +255,47 @@ const ( ) var ( - AllRoles = []Role{RoleOwner, RoleAdmin, RoleViewer, RoleFull} - EditRoles = []Role{RoleOwner, RoleAdmin, RoleFull} + AllRoles = []Role{RoleOwner, RoleAdmin, RoleEmployee, RoleViewer, RoleFull} + NonEmployeeRoles = []Role{RoleOwner, RoleAdmin, RoleViewer, RoleFull} + EditRoles = []Role{RoleOwner, RoleAdmin, RoleFull} ) var Permissions = map[uint16]map[Action][]Role{ coredata.OrganizationEntityType: { - ActionGet: AllRoles, - ActionGetLogoUrl: AllRoles, - ActionGetHorizontalLogoUrl: AllRoles, - ActionMemberships: AllRoles, - ActionPeoples: AllRoles, - ActionTotalCount: AllRoles, - ActionListMembers: AllRoles, - ActionListInvitations: AllRoles, - ActionListSlackConnections: AllRoles, - ActionListFrameworks: AllRoles, - ActionListControls: AllRoles, - ActionListVendors: AllRoles, - ActionListPeople: AllRoles, - ActionListDocuments: AllRoles, - ActionListMeetings: AllRoles, - ActionListMeasures: AllRoles, - ActionListRisks: AllRoles, - ActionListTasks: AllRoles, - ActionListAssets: AllRoles, - ActionListData: AllRoles, - ActionListAudits: AllRoles, - ActionListNonconformities: AllRoles, - ActionListObligations: AllRoles, - ActionListContinualImprovements: AllRoles, - ActionListProcessingActivities: AllRoles, - ActionListSnapshots: AllRoles, - ActionListTrustCenterFiles: AllRoles, - ActionGetTrustCenter: AllRoles, - ActionAudit: AllRoles, - ActionGetCustomDomain: AllRoles, - ActionListSAMLConfigurations: AllRoles, - ActionConfirmEmail: AllRoles, - ActionAcceptInvitation: AllRoles, + ActionGet: AllRoles, + ActionListSignableDocuments: AllRoles, + ActionGetLogoUrl: AllRoles, + + ActionListDocuments: NonEmployeeRoles, + ActionGetHorizontalLogoUrl: NonEmployeeRoles, + ActionMemberships: NonEmployeeRoles, + ActionPeoples: NonEmployeeRoles, + ActionTotalCount: NonEmployeeRoles, + ActionListMembers: NonEmployeeRoles, + ActionListInvitations: NonEmployeeRoles, + ActionListSlackConnections: NonEmployeeRoles, + ActionListFrameworks: NonEmployeeRoles, + ActionListControls: NonEmployeeRoles, + ActionListVendors: NonEmployeeRoles, + ActionListPeople: NonEmployeeRoles, + ActionListMeetings: NonEmployeeRoles, + ActionListMeasures: NonEmployeeRoles, + ActionListRisks: NonEmployeeRoles, + ActionListTasks: NonEmployeeRoles, + ActionListAssets: NonEmployeeRoles, + ActionListData: NonEmployeeRoles, + ActionListAudits: NonEmployeeRoles, + ActionListNonconformities: NonEmployeeRoles, + ActionListObligations: NonEmployeeRoles, + ActionListContinualImprovements: NonEmployeeRoles, + ActionListProcessingActivities: NonEmployeeRoles, + ActionListSnapshots: NonEmployeeRoles, + ActionListTrustCenterFiles: NonEmployeeRoles, + ActionGetTrustCenter: NonEmployeeRoles, + ActionGetCustomDomain: NonEmployeeRoles, + ActionListSAMLConfigurations: NonEmployeeRoles, + ActionConfirmEmail: NonEmployeeRoles, + ActionAcceptInvitation: NonEmployeeRoles, ActionUpdateOrganization: EditRoles, ActionDeleteOrganizationHorizontalLogo: EditRoles, @@ -325,11 +334,11 @@ var Permissions = map[uint16]map[Action][]Role{ ActionDeleteOrganization: {RoleOwner}, }, coredata.TrustCenterEntityType: { - ActionGet: AllRoles, - ActionGetNdaFileUrl: AllRoles, - ActionGetOrganization: AllRoles, - ActionListAccesses: AllRoles, - ActionListReferences: AllRoles, + ActionGet: NonEmployeeRoles, + ActionGetNdaFileUrl: NonEmployeeRoles, + ActionGetOrganization: NonEmployeeRoles, + ActionListAccesses: NonEmployeeRoles, + ActionListReferences: NonEmployeeRoles, ActionUpdateTrustCenter: EditRoles, ActionUploadTrustCenterNDA: EditRoles, @@ -338,62 +347,59 @@ var Permissions = map[uint16]map[Action][]Role{ ActionCreateTrustCenterReference: EditRoles, }, coredata.TrustCenterAccessEntityType: { - ActionGet: AllRoles, - ActionActiveCount: AllRoles, - ActionPendingRequestCount: AllRoles, - ActionAvailableDocumentAccesses: AllRoles, - ActionDocument: AllRoles, - ActionReport: AllRoles, - ActionTrustCenterFile: AllRoles, + ActionGet: NonEmployeeRoles, + ActionActiveCount: NonEmployeeRoles, + ActionPendingRequestCount: NonEmployeeRoles, + ActionAvailableDocumentAccesses: NonEmployeeRoles, ActionUpdateTrustCenterAccess: EditRoles, ActionDeleteTrustCenterAccess: EditRoles, }, coredata.TrustCenterReferenceEntityType: { - ActionGet: AllRoles, - ActionGetLogoUrl: AllRoles, + ActionGet: NonEmployeeRoles, + ActionGetLogoUrl: NonEmployeeRoles, ActionUpdateTrustCenterReference: EditRoles, ActionDeleteTrustCenterReference: EditRoles, }, coredata.TrustCenterFileEntityType: { - ActionGet: AllRoles, - ActionGetFileUrl: AllRoles, + ActionGet: NonEmployeeRoles, + ActionGetFileUrl: NonEmployeeRoles, ActionUpdateTrustCenterFile: EditRoles, ActionGetTrustCenterFile: EditRoles, ActionDeleteTrustCenterFile: EditRoles, }, coredata.UserEntityType: { - ActionGet: AllRoles, + ActionGet: NonEmployeeRoles, }, coredata.MembershipEntityType: { - ActionGet: AllRoles, - ActionGetAuthMethod: AllRoles, + ActionGet: NonEmployeeRoles, + ActionGetAuthMethod: NonEmployeeRoles, }, coredata.InvitationEntityType: { - ActionGet: AllRoles, - ActionGetOrganization: AllRoles, + ActionGet: NonEmployeeRoles, + ActionGetOrganization: NonEmployeeRoles, ActionDeleteInvitation: EditRoles, }, coredata.PeopleEntityType: { - ActionGet: AllRoles, + ActionGet: NonEmployeeRoles, ActionUpdatePeople: EditRoles, ActionDeletePeople: EditRoles, }, coredata.VendorEntityType: { - ActionGet: AllRoles, - ActionGetOrganization: AllRoles, - ActionListComplianceReports: AllRoles, - ActionGetBusinessAssociateAgreement: AllRoles, - ActionGetDataPrivacyAgreement: AllRoles, - ActionListContacts: AllRoles, - ActionListServices: AllRoles, - ActionListRiskAssessments: AllRoles, - ActionGetBusinessOwner: AllRoles, - ActionGetSecurityOwner: AllRoles, + ActionGet: NonEmployeeRoles, + ActionGetOrganization: NonEmployeeRoles, + ActionListComplianceReports: NonEmployeeRoles, + ActionGetBusinessAssociateAgreement: NonEmployeeRoles, + ActionGetDataPrivacyAgreement: NonEmployeeRoles, + ActionListContacts: NonEmployeeRoles, + ActionListServices: NonEmployeeRoles, + ActionListRiskAssessments: NonEmployeeRoles, + ActionGetBusinessOwner: NonEmployeeRoles, + ActionGetSecurityOwner: NonEmployeeRoles, ActionUpdateVendor: EditRoles, ActionDeleteVendor: EditRoles, @@ -407,49 +413,49 @@ var Permissions = map[uint16]map[Action][]Role{ ActionAssessVendor: EditRoles, }, coredata.VendorComplianceReportEntityType: { - ActionGet: AllRoles, - ActionGetVendor: AllRoles, - ActionGetFile: AllRoles, + ActionGet: NonEmployeeRoles, + ActionGetVendor: NonEmployeeRoles, + ActionGetFile: NonEmployeeRoles, ActionDeleteVendorComplianceReport: EditRoles, }, coredata.VendorBusinessAssociateAgreementEntityType: { - ActionGet: AllRoles, - ActionGetVendor: AllRoles, - ActionGetFileUrl: AllRoles, + ActionGet: NonEmployeeRoles, + ActionGetVendor: NonEmployeeRoles, + ActionGetFileUrl: NonEmployeeRoles, ActionUpdateVendorBusinessAssociateAgreement: EditRoles, ActionDeleteVendorBusinessAssociateAgreement: EditRoles, }, coredata.VendorContactEntityType: { - ActionGet: AllRoles, - ActionGetVendor: AllRoles, + ActionGet: NonEmployeeRoles, + ActionGetVendor: NonEmployeeRoles, ActionUpdateVendorContact: EditRoles, ActionDeleteVendorContact: EditRoles, }, coredata.VendorServiceEntityType: { - ActionGet: AllRoles, - ActionGetVendor: AllRoles, + ActionGet: NonEmployeeRoles, + ActionGetVendor: NonEmployeeRoles, ActionUpdateVendorService: EditRoles, ActionDeleteVendorService: EditRoles, }, coredata.VendorDataPrivacyAgreementEntityType: { - ActionGet: AllRoles, - ActionGetVendor: AllRoles, - ActionGetFileUrl: AllRoles, + ActionGet: NonEmployeeRoles, + ActionGetVendor: NonEmployeeRoles, + ActionGetFileUrl: NonEmployeeRoles, ActionUpdateVendorDataPrivacyAgreement: EditRoles, ActionDeleteVendorDataPrivacyAgreement: EditRoles, }, coredata.VendorRiskAssessmentEntityType: { - ActionGet: AllRoles, + ActionGet: NonEmployeeRoles, }, coredata.FrameworkEntityType: { - ActionGet: AllRoles, - ActionGetOrganization: AllRoles, - ActionListControls: AllRoles, + ActionGet: NonEmployeeRoles, + ActionGetOrganization: NonEmployeeRoles, + ActionListControls: NonEmployeeRoles, ActionCreateControl: EditRoles, ActionUpdateFramework: EditRoles, @@ -458,12 +464,12 @@ var Permissions = map[uint16]map[Action][]Role{ ActionExportFramework: EditRoles, }, coredata.ControlEntityType: { - ActionGet: AllRoles, - ActionGetFramework: AllRoles, - ActionListMeasures: AllRoles, - ActionListDocuments: AllRoles, - ActionListAudits: AllRoles, - ActionListSnapshots: AllRoles, + ActionGet: NonEmployeeRoles, + ActionGetFramework: NonEmployeeRoles, + ActionListMeasures: NonEmployeeRoles, + ActionListDocuments: NonEmployeeRoles, + ActionListAudits: NonEmployeeRoles, + ActionListSnapshots: NonEmployeeRoles, ActionUpdateControl: EditRoles, ActionDeleteControl: EditRoles, @@ -477,23 +483,23 @@ var Permissions = map[uint16]map[Action][]Role{ ActionDeleteControlSnapshotMapping: EditRoles, }, coredata.MeasureEntityType: { - ActionGet: AllRoles, - ActionListEvidences: AllRoles, - ActionListTasks: AllRoles, - ActionListRisks: AllRoles, - ActionListControls: AllRoles, - ActionTotalCount: AllRoles, + ActionGet: NonEmployeeRoles, + ActionListEvidences: NonEmployeeRoles, + ActionListTasks: NonEmployeeRoles, + ActionListRisks: NonEmployeeRoles, + ActionListControls: NonEmployeeRoles, + ActionTotalCount: NonEmployeeRoles, ActionUpdateMeasure: EditRoles, ActionDeleteMeasure: EditRoles, ActionUploadMeasureEvidence: EditRoles, }, coredata.TaskEntityType: { - ActionGet: AllRoles, - ActionGetAssignedTo: AllRoles, - ActionGetOrganization: AllRoles, - ActionGetMeasure: AllRoles, - ActionListEvidences: AllRoles, + ActionGet: NonEmployeeRoles, + ActionGetAssignedTo: NonEmployeeRoles, + ActionGetOrganization: NonEmployeeRoles, + ActionGetMeasure: NonEmployeeRoles, + ActionListEvidences: NonEmployeeRoles, ActionUpdateTask: EditRoles, ActionDeleteTask: EditRoles, @@ -501,28 +507,31 @@ var Permissions = map[uint16]map[Action][]Role{ ActionUnassignTask: EditRoles, }, coredata.EvidenceEntityType: { - ActionGet: AllRoles, - ActionGetFile: AllRoles, - ActionGetTask: AllRoles, - ActionGetMeasure: AllRoles, + ActionGet: NonEmployeeRoles, + ActionGetFile: NonEmployeeRoles, + ActionGetTask: NonEmployeeRoles, + ActionGetMeasure: NonEmployeeRoles, ActionDeleteEvidence: EditRoles, }, coredata.DocumentEntityType: { - ActionGet: AllRoles, - ActionExportDocumentVersionPDF: AllRoles, - ActionGetOwner: AllRoles, - ActionGetOrganization: AllRoles, - ActionListVersions: AllRoles, - ActionListControls: AllRoles, - ActionTotalCount: AllRoles, + ActionListSignableDocumentVersion: AllRoles, + ActionGetSigned: AllRoles, + ActionGetSignableDocument: AllRoles, + + ActionGet: NonEmployeeRoles, + ActionGetOwner: NonEmployeeRoles, + ActionGetOrganization: NonEmployeeRoles, + ActionBulkExportDocuments: NonEmployeeRoles, + ActionTotalCount: NonEmployeeRoles, + ActionListControls: NonEmployeeRoles, + ActionListVersions: NonEmployeeRoles, ActionUpdateDocument: EditRoles, ActionDeleteDocument: EditRoles, ActionPublishDocumentVersion: EditRoles, ActionBulkPublishDocumentVersions: EditRoles, ActionBulkDeleteDocuments: EditRoles, - ActionBulkExportDocuments: EditRoles, ActionGenerateDocumentChangelog: EditRoles, ActionCreateDraftDocumentVersion: EditRoles, ActionDeleteDraftDocumentVersion: EditRoles, @@ -533,33 +542,35 @@ var Permissions = map[uint16]map[Action][]Role{ ActionCancelSignatureRequest: EditRoles, }, coredata.DocumentVersionEntityType: { - ActionGet: AllRoles, - ActionGetFile: AllRoles, - ActionGetOwner: AllRoles, - ActionDocument: AllRoles, - ActionSignatures: AllRoles, - ActionExportDocumentVersionPDF: AllRoles, + ActionSignDocument: AllRoles, - ActionUpdateDocumentVersion: EditRoles, - ActionRequestSignature: EditRoles, - ActionBulkRequestSignatures: EditRoles, - ActionSendSigningNotifications: EditRoles, - ActionCancelSignatureRequest: EditRoles, + ActionExportSignableVersionDocumentPDF: AllRoles, + ActionGetSigned: AllRoles, + + ActionGet: NonEmployeeRoles, + ActionGetFile: NonEmployeeRoles, + ActionGetOwner: NonEmployeeRoles, + ActionGetDocument: NonEmployeeRoles, + ActionSignatures: NonEmployeeRoles, + ActionExportDocumentVersionPDF: NonEmployeeRoles, + + ActionUpdateDocumentVersion: EditRoles, + ActionRequestSignature: EditRoles, }, coredata.DocumentVersionSignatureEntityType: { - ActionGet: AllRoles, - ActionDocumentVersion: AllRoles, - ActionSignedBy: AllRoles, + ActionGet: NonEmployeeRoles, + ActionDocumentVersion: NonEmployeeRoles, + ActionSignedBy: NonEmployeeRoles, }, coredata.RiskEntityType: { - ActionGet: AllRoles, - ActionGetOwner: AllRoles, - ActionGetOrganization: AllRoles, - ActionTotalCount: AllRoles, - ActionListControls: AllRoles, - ActionListMeasures: AllRoles, - ActionListDocuments: AllRoles, - ActionListObligations: AllRoles, + ActionGet: NonEmployeeRoles, + ActionGetOwner: NonEmployeeRoles, + ActionGetOrganization: NonEmployeeRoles, + ActionTotalCount: NonEmployeeRoles, + ActionListControls: NonEmployeeRoles, + ActionListMeasures: NonEmployeeRoles, + ActionListDocuments: NonEmployeeRoles, + ActionListObligations: NonEmployeeRoles, ActionUpdateRisk: EditRoles, ActionDeleteRisk: EditRoles, @@ -571,32 +582,32 @@ var Permissions = map[uint16]map[Action][]Role{ ActionDeleteRiskObligationMapping: EditRoles, }, coredata.AssetEntityType: { - ActionGet: AllRoles, - ActionGetOwner: AllRoles, - ActionListVendors: AllRoles, - ActionGetAssetType: AllRoles, - ActionGetOrganization: AllRoles, + ActionGet: NonEmployeeRoles, + ActionGetOwner: NonEmployeeRoles, + ActionListVendors: NonEmployeeRoles, + ActionGetAssetType: NonEmployeeRoles, + ActionGetOrganization: NonEmployeeRoles, ActionUpdateAsset: EditRoles, ActionDeleteAsset: EditRoles, }, coredata.DatumEntityType: { - ActionGet: AllRoles, - ActionGetOwner: AllRoles, - ActionGetOrganization: AllRoles, - ActionListVendors: AllRoles, + ActionGet: NonEmployeeRoles, + ActionGetOwner: NonEmployeeRoles, + ActionGetOrganization: NonEmployeeRoles, + ActionListVendors: NonEmployeeRoles, ActionUpdateDatum: EditRoles, ActionDeleteDatum: EditRoles, }, coredata.AuditEntityType: { - ActionGet: AllRoles, - ActionGetFile: AllRoles, - ActionGetFramework: AllRoles, - ActionGetOrganization: AllRoles, - ActionReport: AllRoles, - ActionReportUrl: AllRoles, - ActionListControls: AllRoles, + ActionGet: NonEmployeeRoles, + ActionGetFile: NonEmployeeRoles, + ActionGetFramework: NonEmployeeRoles, + ActionGetOrganization: NonEmployeeRoles, + ActionReport: NonEmployeeRoles, + ActionReportUrl: NonEmployeeRoles, + ActionListControls: NonEmployeeRoles, ActionUpdateAudit: EditRoles, ActionDeleteAudit: EditRoles, @@ -604,51 +615,50 @@ var Permissions = map[uint16]map[Action][]Role{ ActionDeleteAuditReport: EditRoles, }, coredata.ReportEntityType: { - ActionGet: AllRoles, - ActionGetFile: AllRoles, - ActionGetOrganization: AllRoles, - ActionGetSnapshot: AllRoles, - ActionDownloadUrl: AllRoles, - ActionAudit: AllRoles, + ActionGet: NonEmployeeRoles, + ActionGetFile: NonEmployeeRoles, + ActionGetOrganization: NonEmployeeRoles, + ActionGetSnapshot: NonEmployeeRoles, + ActionDownloadUrl: NonEmployeeRoles, }, coredata.NonconformityEntityType: { - ActionGet: AllRoles, - ActionGetOwner: AllRoles, - ActionGetOrganization: AllRoles, - ActionAudit: AllRoles, + ActionGet: NonEmployeeRoles, + ActionGetOwner: NonEmployeeRoles, + ActionGetOrganization: NonEmployeeRoles, + ActionAudit: NonEmployeeRoles, ActionUpdateNonconformity: EditRoles, ActionDeleteNonconformity: EditRoles, }, coredata.ObligationEntityType: { - ActionGet: AllRoles, - ActionGetOrganization: AllRoles, - ActionGetOwner: AllRoles, - ActionListRisks: AllRoles, + ActionGet: NonEmployeeRoles, + ActionGetOrganization: NonEmployeeRoles, + ActionGetOwner: NonEmployeeRoles, + ActionListRisks: NonEmployeeRoles, ActionUpdateObligation: EditRoles, ActionDeleteObligation: EditRoles, }, coredata.ContinualImprovementEntityType: { - ActionGet: AllRoles, - ActionGetOwner: AllRoles, - ActionGetOrganization: AllRoles, + ActionGet: NonEmployeeRoles, + ActionGetOwner: NonEmployeeRoles, + ActionGetOrganization: NonEmployeeRoles, ActionUpdateContinualImprovement: EditRoles, ActionDeleteContinualImprovement: EditRoles, }, coredata.ProcessingActivityEntityType: { - ActionGet: AllRoles, - ActionGetOrganization: AllRoles, - ActionListVendors: AllRoles, + ActionGet: NonEmployeeRoles, + ActionGetOrganization: NonEmployeeRoles, + ActionListVendors: NonEmployeeRoles, ActionUpdateProcessingActivity: EditRoles, ActionDeleteProcessingActivity: EditRoles, }, coredata.SnapshotEntityType: { - ActionGet: AllRoles, - ActionGetOrganization: AllRoles, - ActionListControls: AllRoles, + ActionGet: NonEmployeeRoles, + ActionGetOrganization: NonEmployeeRoles, + ActionListControls: NonEmployeeRoles, ActionDeleteSnapshot: EditRoles, }, @@ -669,19 +679,18 @@ var Permissions = map[uint16]map[Action][]Role{ ActionVerifyDomain: {RoleOwner}, }, coredata.FileEntityType: { - ActionGet: AllRoles, - ActionDownloadUrl: AllRoles, + ActionGet: NonEmployeeRoles, + ActionDownloadUrl: NonEmployeeRoles, }, coredata.TrustCenterDocumentAccessEntityType: { - ActionGet: AllRoles, - ActionDocument: {RoleOwner, RoleAdmin}, - ActionReport: {RoleOwner, RoleAdmin}, - ActionTrustCenterFile: {RoleOwner, RoleAdmin}, + ActionGet: NonEmployeeRoles, + ActionReport: NonEmployeeRoles, + ActionTrustCenterFile: NonEmployeeRoles, }, coredata.MeetingEntityType: { - ActionGet: AllRoles, - ActionGetOrganization: AllRoles, - ActionTotalCount: AllRoles, + ActionGet: NonEmployeeRoles, + ActionGetOrganization: NonEmployeeRoles, + ActionTotalCount: NonEmployeeRoles, ActionUpdateMeeting: EditRoles, ActionDeleteMeeting: EditRoles, diff --git a/pkg/coredata/document.go b/pkg/coredata/document.go index 28fb27656..4c5b2873c 100644 --- a/pkg/coredata/document.go +++ b/pkg/coredata/document.go @@ -124,6 +124,60 @@ LIMIT 1; return nil } +func (p *Document) LoadByIDWithFilter( + ctx context.Context, + conn pg.Conn, + scope Scoper, + documentID gid.GID, + filter *DocumentFilter, +) error { + q := ` +SELECT + id, + organization_id, + owner_id, + title, + document_type, + classification, + current_published_version, + trust_center_visibility, + created_at, + updated_at +FROM + documents +WHERE + %s + AND deleted_at IS NULL + AND id = @document_id + AND %s +LIMIT 1; +` + + q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment()) + + args := pgx.StrictNamedArgs{"document_id": documentID} + maps.Copy(args, scope.SQLArguments()) + maps.Copy(args, filter.SQLArguments()) + + rows, err := conn.Query(ctx, q, args) + if err != nil { + return fmt.Errorf("cannot query documents: %w", err) + } + + document, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[Document]) + if err != nil { + if errors.Is(err, pgx.ErrNoRows) { + return &ErrDocumentNotFound{Identifier: documentID.String()} + } + + return fmt.Errorf("cannot collect document: %w", err) + } + + *p = document + + return nil +} + func (p *Documents) CountByOrganizationID( ctx context.Context, conn pg.Conn, @@ -400,28 +454,17 @@ func (p *Documents) CountByControlID( filter *DocumentFilter, ) (int, error) { q := ` -WITH plcs AS ( - SELECT - p.id, - p.tenant_id, - p.search_vector, - p.trust_center_visibility, - p.deleted_at - FROM - documents p - INNER JOIN - controls_documents cp ON p.id = cp.document_id - WHERE - cp.control_id = @control_id +WITH scoped_documents AS ( + SELECT * + FROM documents + WHERE %s + AND deleted_at IS NULL + AND %s ) -SELECT - COUNT(id) -FROM - plcs -WHERE - %s - AND deleted_at IS NULL - AND %s +SELECT COUNT(scoped_documents.id) +FROM scoped_documents +INNER JOIN controls_documents cp ON scoped_documents.id = cp.document_id +WHERE cp.control_id = @control_id ` q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment()) @@ -448,46 +491,28 @@ func (p *Documents) LoadByControlID( filter *DocumentFilter, ) error { q := ` -WITH plcs AS ( - SELECT - p.id, - p.tenant_id, - p.search_vector, - p.organization_id, - p.owner_id, - p.title, - p.document_type, - p.classification, - p.current_published_version, - p.trust_center_visibility, - p.created_at, - p.updated_at, - p.deleted_at - FROM - documents p - INNER JOIN - controls_documents cp ON p.id = cp.document_id - WHERE - cp.control_id = @control_id +WITH scoped_documents AS ( + SELECT * + FROM documents + WHERE %s + AND deleted_at IS NULL + AND %s + AND %s ) SELECT - id, - organization_id, - owner_id, - title, - document_type, - classification, - current_published_version, - trust_center_visibility, - created_at, - updated_at -FROM - plcs -WHERE - %s - AND deleted_at IS NULL - AND %s - AND %s + scoped_documents.id, + scoped_documents.organization_id, + scoped_documents.owner_id, + scoped_documents.title, + scoped_documents.document_type, + scoped_documents.classification, + scoped_documents.current_published_version, + scoped_documents.trust_center_visibility, + scoped_documents.created_at, + scoped_documents.updated_at +FROM scoped_documents +INNER JOIN controls_documents cp ON scoped_documents.id = cp.document_id +WHERE cp.control_id = @control_id ` q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment(), cursor.SQLFragment()) @@ -519,28 +544,17 @@ func (p *Documents) CountByRiskID( filter *DocumentFilter, ) (int, error) { q := ` -WITH plcs AS ( - SELECT - p.id, - p.tenant_id, - p.search_vector, - p.trust_center_visibility, - p.deleted_at - FROM - documents p - INNER JOIN - risks_documents rp ON p.id = rp.document_id - WHERE - rp.risk_id = @risk_id +WITH scoped_documents AS ( + SELECT * + FROM documents + WHERE %s + AND deleted_at IS NULL + AND %s ) -SELECT - COUNT(id) -FROM - plcs -WHERE - %s - AND deleted_at IS NULL - AND %s +SELECT COUNT(scoped_documents.id) +FROM scoped_documents +INNER JOIN risks_documents rp ON scoped_documents.id = rp.document_id +WHERE rp.risk_id = @risk_id ` q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment()) @@ -567,46 +581,28 @@ func (p *Documents) LoadByRiskID( filter *DocumentFilter, ) error { q := ` -WITH plcs AS ( - SELECT - p.id, - p.tenant_id, - p.organization_id, - p.owner_id, - p.title, - p.document_type, - p.classification, - p.current_published_version, - p.trust_center_visibility, - p.created_at, - p.updated_at, - p.search_vector, - p.deleted_at - FROM - documents p - INNER JOIN - risks_documents rp ON p.id = rp.document_id - WHERE - rp.risk_id = @risk_id +WITH scoped_documents AS ( + SELECT * + FROM documents + WHERE %s + AND deleted_at IS NULL + AND %s + AND %s ) SELECT - id, - organization_id, - owner_id, - title, - document_type, - classification, - current_published_version, - trust_center_visibility, - created_at, - updated_at -FROM - plcs -WHERE - %s - AND deleted_at IS NULL - AND %s - AND %s + scoped_documents.id, + scoped_documents.organization_id, + scoped_documents.owner_id, + scoped_documents.title, + scoped_documents.document_type, + scoped_documents.classification, + scoped_documents.current_published_version, + scoped_documents.trust_center_visibility, + scoped_documents.created_at, + scoped_documents.updated_at +FROM scoped_documents +INNER JOIN risks_documents rp ON scoped_documents.id = rp.document_id +WHERE rp.risk_id = @risk_id ` q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment(), cursor.SQLFragment()) @@ -653,3 +649,61 @@ UPDATE documents SET deleted_at = @deleted_at WHERE %s AND id = ANY(@document_id _, err := conn.Exec(ctx, q, args) return err } + +func (p *Document) IsLastSignableVersionSignedByUserEmail( + ctx context.Context, + conn pg.Conn, + scope Scoper, + documentID gid.GID, + userEmail string, +) (bool, error) { + q := ` +WITH last_signable_version AS ( + SELECT + d.id AS document_id, + d.tenant_id, + dv.version_number, + dvs.state + FROM documents d + INNER JOIN document_versions dv ON dv.document_id = d.id + INNER JOIN document_version_signatures dvs ON dvs.document_version_id = dv.id + INNER JOIN peoples p ON dvs.signed_by = p.id + WHERE d.id = @document_id + AND p.primary_email_address = @user_email + AND dv.version_number = ( + SELECT MAX(dv2.version_number) + FROM document_versions dv2 + INNER JOIN document_version_signatures dvs2 ON dvs2.document_version_id = dv2.id + INNER JOIN peoples p2 ON dvs2.signed_by = p2.id + WHERE dv2.document_id = d.id + AND p2.primary_email_address = @user_email + ) +) +SELECT EXISTS ( + SELECT 1 + FROM last_signable_version + WHERE %s + AND state = 'SIGNED' +) AS signed +` + + q = fmt.Sprintf(q, scope.SQLFragment()) + + args := pgx.StrictNamedArgs{ + "document_id": documentID, + "user_email": userEmail, + } + maps.Copy(args, scope.SQLArguments()) + + rows, err := conn.Query(ctx, q, args) + if err != nil { + return false, fmt.Errorf("cannot query document signed status: %w", err) + } + + signed, err := pgx.CollectOneRow(rows, pgx.RowTo[bool]) + if err != nil { + return false, fmt.Errorf("cannot collect signed status: %w", err) + } + + return signed, nil +} diff --git a/pkg/coredata/document_filter.go b/pkg/coredata/document_filter.go index 103d98323..1e6d60487 100644 --- a/pkg/coredata/document_filter.go +++ b/pkg/coredata/document_filter.go @@ -22,6 +22,8 @@ type ( DocumentFilter struct { query *string trustCenterVisibilities []TrustCenterVisibility + published *bool + userEmail *string } ) @@ -40,7 +42,17 @@ func NewDocumentTrustCenterFilter() *DocumentFilter { } } -func (f *DocumentFilter) SQLArguments() pgx.StrictNamedArgs { +func (f *DocumentFilter) WithPublished(published *bool) *DocumentFilter { + f.published = published + return f +} + +func (f *DocumentFilter) WithUserEmail(userEmail *string) *DocumentFilter { + f.userEmail = userEmail + return f +} + +func (f *DocumentFilter) SQLArguments() pgx.NamedArgs { var visibilities []string if f.trustCenterVisibilities != nil { visibilities = make([]string, len(f.trustCenterVisibilities)) @@ -48,9 +60,11 @@ func (f *DocumentFilter) SQLArguments() pgx.StrictNamedArgs { visibilities[i] = v.String() } } - return pgx.StrictNamedArgs{ + return pgx.NamedArgs{ "query": f.query, "trust_center_visibilities": visibilities, + "published": f.published, + "user_email": f.userEmail, } } @@ -71,5 +85,25 @@ func (f *DocumentFilter) SQLFragment() string { trust_center_visibility = ANY(@trust_center_visibilities::trust_center_visibility[]) ELSE TRUE END + AND + CASE + WHEN @published::boolean IS NULL THEN TRUE + WHEN @published::boolean IS TRUE THEN current_published_version IS NOT NULL + WHEN @published::boolean IS FALSE THEN current_published_version IS NULL + END + AND + CASE + WHEN @user_email::text IS NULL THEN TRUE + ELSE EXISTS ( + SELECT 1 + FROM document_versions dv + INNER JOIN document_version_signatures dvs ON dv.id = dvs.document_version_id + INNER JOIN peoples p ON dvs.signed_by = p.id + WHERE dv.document_id = documents.id + AND dv.status = 'PUBLISHED' + AND p.primary_email_address = @user_email::text + AND dvs.state IN ('REQUESTED', 'SIGNED') + ) + END )` } diff --git a/pkg/coredata/document_version.go b/pkg/coredata/document_version.go index 993198564..164211bcd 100644 --- a/pkg/coredata/document_version.go +++ b/pkg/coredata/document_version.go @@ -78,6 +78,7 @@ func (p *DocumentVersions) LoadByDocumentID( scope Scoper, documentID gid.GID, cursor *page.Cursor[DocumentVersionOrderField], + filter *DocumentVersionFilter, ) error { q := ` SELECT @@ -100,14 +101,16 @@ WHERE %s AND document_id = @document_id AND %s + AND %s ` - q = fmt.Sprintf(q, scope.SQLFragment(), cursor.SQLFragment()) + q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment(), cursor.SQLFragment()) args := pgx.StrictNamedArgs{ "document_id": documentID, } maps.Copy(args, scope.SQLArguments()) maps.Copy(args, cursor.SQLArguments()) + maps.Copy(args, filter.SQLArguments()) rows, err := conn.Query(ctx, q, args) if err != nil { diff --git a/pkg/coredata/document_version_filter.go b/pkg/coredata/document_version_filter.go new file mode 100644 index 000000000..7a2aaad7f --- /dev/null +++ b/pkg/coredata/document_version_filter.go @@ -0,0 +1,55 @@ +// Copyright (c) 2025 Probo Inc . +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +package coredata + +import ( + "github.com/jackc/pgx/v5" +) + +type ( + DocumentVersionFilter struct { + userEmail *string + } +) + +func NewDocumentVersionFilter() *DocumentVersionFilter { + return &DocumentVersionFilter{} +} + +func (f *DocumentVersionFilter) WithUserEmail(userEmail *string) *DocumentVersionFilter { + f.userEmail = userEmail + return f +} + +func (f *DocumentVersionFilter) SQLArguments() pgx.StrictNamedArgs { + return pgx.StrictNamedArgs{ + "user_email": f.userEmail, + } +} + +func (f *DocumentVersionFilter) SQLFragment() string { + return ` +( + @user_email::text IS NULL + OR EXISTS ( + SELECT 1 + FROM document_version_signatures dvs + INNER JOIN peoples p ON dvs.signed_by = p.id + WHERE dvs.document_version_id = document_versions.id + AND p.primary_email_address = @user_email::text + AND dvs.state IN ('REQUESTED', 'SIGNED') + ) +)` +} diff --git a/pkg/coredata/document_version_order_field.go b/pkg/coredata/document_version_order_field.go index 15b092315..845af70e2 100644 --- a/pkg/coredata/document_version_order_field.go +++ b/pkg/coredata/document_version_order_field.go @@ -20,7 +20,6 @@ type ( const ( DocumentVersionOrderFieldCreatedAt DocumentVersionOrderField = "CREATED_AT" - DocumentVersionOrderFieldVersion DocumentVersionOrderField = "VERSION" ) func (p DocumentVersionOrderField) Column() string { diff --git a/pkg/coredata/document_version_signature.go b/pkg/coredata/document_version_signature.go index 844493cc1..0b4fa9ee1 100644 --- a/pkg/coredata/document_version_signature.go +++ b/pkg/coredata/document_version_signature.go @@ -57,6 +57,8 @@ type ( ErrDocumentVersionSignatureAlreadyExists struct { message string } + + ErrDocumentVersionSignatureAlreadySigned struct{} ) func (e ErrDocumentVersionSignatureNotFound) Error() string { @@ -67,6 +69,10 @@ func (e ErrDocumentVersionSignatureAlreadyExists) Error() string { return e.message } +func (e ErrDocumentVersionSignatureAlreadySigned) Error() string { + return "document version already signed" +} + func (pvs DocumentVersionSignature) CursorKey(orderBy DocumentVersionSignatureOrderField) page.CursorKey { switch orderBy { case DocumentVersionSignatureOrderFieldCreatedAt: @@ -412,3 +418,41 @@ WHERE return nil } + +func (pvs *DocumentVersionSignature) IsSignedByUserEmail( + ctx context.Context, + conn pg.Conn, + scope Scoper, + documentVersionID gid.GID, + userEmail string, +) (bool, error) { + q := ` +SELECT EXISTS ( + SELECT 1 + FROM document_version_signatures dvs + INNER JOIN peoples p ON dvs.signed_by = p.id + WHERE dvs.document_version_id = @document_version_id + AND p.primary_email_address = @user_email + AND dvs.state = 'SIGNED' + AND dvs.tenant_id = @tenant_id +) AS signed +` + + args := pgx.StrictNamedArgs{ + "document_version_id": documentVersionID, + "user_email": userEmail, + } + maps.Copy(args, scope.SQLArguments()) + + rows, err := conn.Query(ctx, q, args) + if err != nil { + return false, fmt.Errorf("cannot query document version signature: %w", err) + } + + signed, err := pgx.CollectOneRow(rows, pgx.RowTo[bool]) + if err != nil { + return false, fmt.Errorf("cannot collect signed status: %w", err) + } + + return signed, nil +} diff --git a/pkg/coredata/member_role.go b/pkg/coredata/member_role.go index d4495d0a8..a03cb5bd1 100644 --- a/pkg/coredata/member_role.go +++ b/pkg/coredata/member_role.go @@ -22,9 +22,10 @@ import ( type MembershipRole string const ( - MembershipRoleOwner MembershipRole = "OWNER" - MembershipRoleAdmin MembershipRole = "ADMIN" - MembershipRoleViewer MembershipRole = "VIEWER" + MembershipRoleOwner MembershipRole = "OWNER" + MembershipRoleAdmin MembershipRole = "ADMIN" + MembershipRoleEmployee MembershipRole = "EMPLOYEE" + MembershipRoleViewer MembershipRole = "VIEWER" ) func (r MembershipRole) String() string { @@ -47,6 +48,8 @@ func (r *MembershipRole) Scan(value any) error { *r = MembershipRoleOwner case "ADMIN": *r = MembershipRoleAdmin + case "EMPLOYEE": + *r = MembershipRoleEmployee case "VIEWER": *r = MembershipRoleViewer default: diff --git a/pkg/coredata/migrations/20251113T000000Z.sql b/pkg/coredata/migrations/20251113T000000Z.sql new file mode 100644 index 000000000..5bd9d4a79 --- /dev/null +++ b/pkg/coredata/migrations/20251113T000000Z.sql @@ -0,0 +1 @@ +ALTER TYPE authz_role RENAME VALUE 'MEMBER' TO 'EMPLOYEE'; diff --git a/pkg/coredata/people.go b/pkg/coredata/people.go index 3fd5a1b4c..e4cd8d658 100644 --- a/pkg/coredata/people.go +++ b/pkg/coredata/people.go @@ -132,24 +132,24 @@ func (p *People) LoadByEmail( primaryEmailAddress string, ) error { q := ` - SELECT - id, - organization_id, - kind, - full_name, - primary_email_address, - additional_email_addresses, - position, - contract_start_date, - contract_end_date, - created_at, - updated_at - FROM - peoples - WHERE - %s - AND primary_email_address = @primary_email_address - LIMIT 1; +SELECT + id, + organization_id, + kind, + full_name, + primary_email_address, + additional_email_addresses, + position, + contract_start_date, + contract_end_date, + created_at, + updated_at +FROM + peoples +WHERE + %s + AND primary_email_address = @primary_email_address +LIMIT 1; ` q = fmt.Sprintf(q, scope.SQLFragment()) @@ -176,6 +176,62 @@ func (p *People) LoadByEmail( return nil } +func (p *People) LoadByEmailAndOrganizationID( + ctx context.Context, + conn pg.Conn, + scope Scoper, + primaryEmailAddress string, + organizationID gid.GID, +) error { + q := ` +SELECT + id, + organization_id, + kind, + full_name, + primary_email_address, + additional_email_addresses, + position, + contract_start_date, + contract_end_date, + created_at, + updated_at +FROM + peoples +WHERE + %s + AND primary_email_address = @primary_email_address + AND organization_id = @organization_id +LIMIT 1; + ` + + q = fmt.Sprintf(q, scope.SQLFragment()) + + args := pgx.StrictNamedArgs{ + "primary_email_address": primaryEmailAddress, + "organization_id": organizationID, + } + maps.Copy(args, scope.SQLArguments()) + + rows, err := conn.Query(ctx, q, args) + if err != nil { + return fmt.Errorf("cannot query people: %w", err) + } + + people, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[People]) + if err != nil { + if errors.Is(err, pgx.ErrNoRows) { + return &ErrPeopleNotFound{Identifier: primaryEmailAddress} + } + + return fmt.Errorf("cannot collect people: %w", err) + } + + *p = people + + return nil +} + func (p *Peoples) LoadByIDs( ctx context.Context, conn pg.Conn, diff --git a/pkg/probo/document_service.go b/pkg/probo/document_service.go index a4f233b6d..e3cc6c2cf 100644 --- a/pkg/probo/document_service.go +++ b/pkg/probo/document_service.go @@ -164,6 +164,32 @@ func (s *DocumentService) Get( return document, nil } +func (s *DocumentService) GetWithFilter( + ctx context.Context, + documentID gid.GID, + filter *coredata.DocumentFilter, +) (*coredata.Document, error) { + document := &coredata.Document{} + + err := s.svc.pg.WithConn( + ctx, + func(conn pg.Conn) error { + err := document.LoadByIDWithFilter(ctx, conn, s.svc.scope, documentID, filter) + if err != nil { + return fmt.Errorf("cannot load document: %w", err) + } + + return nil + }, + ) + + if err != nil { + return nil, err + } + + return document, nil +} + func (s DocumentService) GenerateChangelog( ctx context.Context, documentID gid.GID, @@ -559,39 +585,13 @@ func (s *DocumentService) SignDocumentVersion( documentVersionID gid.GID, signatory gid.GID, ) error { - documentVersion := &coredata.DocumentVersion{} - documentVersionSignature := &coredata.DocumentVersionSignature{} - now := time.Now() - err := s.svc.pg.WithTx( ctx, func(conn pg.Conn) error { - if err := documentVersion.LoadByID(ctx, conn, s.svc.scope, documentVersionID); err != nil { - return fmt.Errorf("cannot load document version %q: %w", documentVersionID, err) - } - - if documentVersion.Status != coredata.DocumentStatusPublished { - return fmt.Errorf("cannot sign unpublished version") - } - - if err := documentVersionSignature.LoadByDocumentVersionIDAndSignatory(ctx, conn, s.svc.scope, documentVersionID, signatory); err != nil { - return fmt.Errorf("cannot load document version signature: %w", err) - } - - if documentVersionSignature.State == coredata.DocumentVersionSignatureStateSigned { - return fmt.Errorf("document version already signed") - } - - documentVersionSignature.State = coredata.DocumentVersionSignatureStateSigned - documentVersionSignature.SignedAt = &now - documentVersionSignature.UpdatedAt = now - - if err := documentVersion.Update(ctx, conn, s.svc.scope); err != nil { - return fmt.Errorf("cannot update document version: %w", err) - } - - if err := documentVersionSignature.Update(ctx, conn, s.svc.scope); err != nil { - return fmt.Errorf("cannot update document version signature: %w", err) + var err error + _, err = s.signDocumentVersionInTx(ctx, conn, documentVersionID, signatory) + if err != nil { + return fmt.Errorf("cannot sign document version: %w", err) } return nil @@ -605,6 +605,80 @@ func (s *DocumentService) SignDocumentVersion( return nil } +func (s *DocumentService) SignDocumentVersionByEmail( + ctx context.Context, + documentVersionID gid.GID, + userEmail string, +) (*coredata.DocumentVersionSignature, error) { + var documentVersionSignature *coredata.DocumentVersionSignature + + err := s.svc.pg.WithTx( + ctx, + func(conn pg.Conn) error { + documentVersion := &coredata.DocumentVersion{} + if err := documentVersion.LoadByID(ctx, conn, s.svc.scope, documentVersionID); err != nil { + return fmt.Errorf("cannot get document version: %w", err) + } + + people := &coredata.People{} + if err := people.LoadByEmailAndOrganizationID(ctx, conn, s.svc.scope, userEmail, documentVersion.OrganizationID); err != nil { + return fmt.Errorf("cannot find people record for user email in organization %q: %w", documentVersion.OrganizationID, err) + } + + var signErr error + documentVersionSignature, signErr = s.signDocumentVersionInTx(ctx, conn, documentVersionID, people.ID) + return signErr + }, + ) + + if err != nil { + return nil, fmt.Errorf("cannot sign document version: %w", err) + } + + return documentVersionSignature, nil +} + +func (s *DocumentService) signDocumentVersionInTx( + ctx context.Context, + conn pg.Conn, + documentVersionID gid.GID, + signatory gid.GID, +) (*coredata.DocumentVersionSignature, error) { + documentVersion := &coredata.DocumentVersion{} + documentVersionSignature := &coredata.DocumentVersionSignature{} + now := time.Now() + + if err := documentVersion.LoadByID(ctx, conn, s.svc.scope, documentVersionID); err != nil { + return nil, fmt.Errorf("cannot load document version %q: %w", documentVersionID, err) + } + + if documentVersion.Status != coredata.DocumentStatusPublished { + return nil, fmt.Errorf("cannot sign unpublished version") + } + + if err := documentVersionSignature.LoadByDocumentVersionIDAndSignatory(ctx, conn, s.svc.scope, documentVersionID, signatory); err != nil { + return nil, fmt.Errorf("cannot load document version signature: %w", err) + } + + if documentVersionSignature.State == coredata.DocumentVersionSignatureStateSigned { + return nil, &coredata.ErrDocumentVersionSignatureAlreadySigned{} + } + + documentVersionSignature.State = coredata.DocumentVersionSignatureStateSigned + documentVersionSignature.SignedAt = &now + documentVersionSignature.UpdatedAt = now + + if err := documentVersion.Update(ctx, conn, s.svc.scope); err != nil { + return nil, fmt.Errorf("cannot update document version: %w", err) + } + + if err := documentVersionSignature.Update(ctx, conn, s.svc.scope); err != nil { + return nil, fmt.Errorf("cannot update document version signature: %w", err) + } + + return documentVersionSignature, nil +} + func (s *DocumentService) UpdateVersion( ctx context.Context, req UpdateDocumentVersionRequest, @@ -810,6 +884,36 @@ func (s *DocumentService) ListSignatures( return page.NewPage(documentVersionSignatures, cursor), nil } +func (s *DocumentService) IsVersionSignedByUserEmail( + ctx context.Context, + documentVersionID gid.GID, + userEmail string, +) (bool, error) { + documentVersionSignature := &coredata.DocumentVersionSignature{} + + var signed bool + err := s.svc.pg.WithConn( + ctx, + func(conn pg.Conn) error { + var err error + signed, err = documentVersionSignature.IsSignedByUserEmail( + ctx, + conn, + s.svc.scope, + documentVersionID, + userEmail, + ) + return err + }, + ) + + if err != nil { + return false, fmt.Errorf("cannot check if document version is signed: %w", err) + } + + return signed, nil +} + func (s *DocumentService) CreateDraft( ctx context.Context, documentID gid.GID, @@ -998,13 +1102,20 @@ func (s *DocumentService) ListVersions( ctx context.Context, documentID gid.GID, cursor *page.Cursor[coredata.DocumentVersionOrderField], + filter *coredata.DocumentVersionFilter, ) (*page.Page[*coredata.DocumentVersion, coredata.DocumentVersionOrderField], error) { var documentVersions coredata.DocumentVersions err := s.svc.pg.WithConn( ctx, func(conn pg.Conn) error { - return documentVersions.LoadByDocumentID(ctx, conn, s.svc.scope, documentID, cursor) + + err := documentVersions.LoadByDocumentID(ctx, conn, s.svc.scope, documentID, cursor, filter) + if err != nil { + return fmt.Errorf("cannot load document versions: %w", err) + } + + return nil }, ) @@ -1035,6 +1146,36 @@ func (s *DocumentService) GetVersion( return documentVersion, nil } +func (s *DocumentService) IsSigned( + ctx context.Context, + documentID gid.GID, + userEmail string, +) (bool, error) { + document := &coredata.Document{} + + var signed bool + err := s.svc.pg.WithConn( + ctx, + func(conn pg.Conn) error { + var err error + signed, err = document.IsLastSignableVersionSignedByUserEmail( + ctx, + conn, + s.svc.scope, + documentID, + userEmail, + ) + return err + }, + ) + + if err != nil { + return false, fmt.Errorf("cannot check if document is signed: %w", err) + } + + return signed, nil +} + func (s *DocumentService) CountForOrganizationID( ctx context.Context, organizationID gid.GID, diff --git a/pkg/probo/people_service.go b/pkg/probo/people_service.go index 76bbb5d99..3cb6b7a10 100644 --- a/pkg/probo/people_service.go +++ b/pkg/probo/people_service.go @@ -108,6 +108,31 @@ func (s PeopleService) Get( return people, nil } +func (s PeopleService) GetByEmailAndOrganizationID( + ctx context.Context, + primaryEmailAddress string, + organizationID gid.GID, +) (*coredata.People, error) { + people := &coredata.People{} + + err := s.svc.pg.WithConn( + ctx, + func(conn pg.Conn) error { + err := people.LoadByEmailAndOrganizationID(ctx, conn, s.svc.scope, primaryEmailAddress, organizationID) + if err != nil { + return fmt.Errorf("cannot load people by email and organization ID: %w", err) + } + + return nil + }, + ) + if err != nil { + return nil, err + } + + return people, nil +} + func (s PeopleService) CountForOrganizationID( ctx context.Context, organizationID gid.GID, diff --git a/pkg/server/api/console/v1/schema.graphql b/pkg/server/api/console/v1/schema.graphql index 90361167c..b9498f1da 100644 --- a/pkg/server/api/console/v1/schema.graphql +++ b/pkg/server/api/console/v1/schema.graphql @@ -94,6 +94,7 @@ enum InvitationStatus enum MembershipRole @goModel(model: "go.probo.inc/probo/pkg/coredata.MembershipRole") { OWNER @goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipRoleOwner") ADMIN @goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipRoleAdmin") + EMPLOYEE @goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipRoleEmployee") VIEWER @goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipRoleViewer") } @@ -522,10 +523,6 @@ enum BusinessImpact enum DocumentVersionOrderField @goModel(model: "go.probo.inc/probo/pkg/coredata.DocumentVersionOrderField") { - VERSION - @goEnum( - value: "go.probo.inc/probo/pkg/coredata.DocumentVersionOrderFieldVersion" - ) CREATED_AT @goEnum( value: "go.probo.inc/probo/pkg/coredata.DocumentVersionOrderFieldCreatedAt" @@ -2035,6 +2032,29 @@ type Document implements Node { updatedAt: Datetime! } +type SignableDocument @goModel( + model: "go.probo.inc/probo/pkg/server/api/console/v1/types.SignableDocument" + ){ + id: ID! + title: String! + description: String + documentType: DocumentType! + classification: DocumentClassification! + signed: Boolean! @goField(forceResolver: true) + + versions( + first: Int + after: CursorKey + last: Int + before: CursorKey + orderBy: DocumentVersionOrder + filter: DocumentVersionFilter + ): DocumentVersionConnection! @goField(forceResolver: true) + + createdAt: Datetime! + updatedAt: Datetime! +} + type Meeting implements Node { id: ID! name: String! @@ -2259,6 +2279,17 @@ type Viewer { before: CursorKey orderBy: OrganizationOrder ): OrganizationConnection! @goField(forceResolver: true) + + signableDocuments( + organizationId: ID! + first: Int + after: CursorKey + last: Int + before: CursorKey + orderBy: DocumentOrder + ): SignableDocumentConnection! @goField(forceResolver: true) + + signableDocument(id: ID!): SignableDocument @goField(forceResolver: true) } # Connection Types @@ -2514,6 +2545,22 @@ type EvidenceEdge { node: Evidence! } +type SignableDocumentConnection + @goModel( + model: "go.probo.inc/probo/pkg/server/api/console/v1/types.SignableDocumentConnection" + ) { + edges: [SignableDocumentEdge!]! + pageInfo: PageInfo! +} + +type SignableDocumentEdge + @goModel( + model: "go.probo.inc/probo/pkg/server/api/console/v1/types.SignableDocumentEdge" + ) { + cursor: CursorKey! + node: SignableDocument! +} + type DocumentConnection @goModel( model: "go.probo.inc/probo/pkg/server/api/console/v1/types.DocumentConnection" @@ -2914,9 +2961,16 @@ type Mutation { input: SendSigningNotificationsInput! ): SendSigningNotificationsPayload! cancelSignatureRequest( input: CancelSignatureRequestInput! - ): CancelSignatureRequestPayload! exportDocumentVersionPDF( + ): CancelSignatureRequestPayload! + signDocument( + input: SignDocumentInput! + ): SignDocumentPayload! + exportDocumentVersionPDF( input: ExportDocumentVersionPDFInput! ): ExportDocumentVersionPDFPayload! + exportSignableVersionDocumentPDF( + input: ExportSignableDocumentVersionPDFInput! + ): ExportSignableDocumentVersionPDFPayload! createVendorRiskAssessment( input: CreateVendorRiskAssessmentInput! ): CreateVendorRiskAssessmentPayload! @@ -3488,6 +3542,10 @@ input ExportDocumentVersionPDFInput { withSignatures: Boolean! } +input ExportSignableDocumentVersionPDFInput { + documentVersionId: ID! +} + input DeleteDocumentInput { documentId: ID! } @@ -4072,6 +4130,10 @@ type ExportDocumentVersionPDFPayload { data: String! } +type ExportSignableDocumentVersionPDFPayload { + data: String! +} + type UpdateDocumentPayload { document: Document! } @@ -4186,6 +4248,8 @@ type DocumentVersion implements Node @goModel(model: "go.probo.inc/probo/pkg/ser filter: DocumentVersionSignatureFilter ): DocumentVersionSignatureConnection! @goField(forceResolver: true) + signed: Boolean! @goField(forceResolver: true) + publishedAt: Datetime createdAt: Datetime! updatedAt: Datetime! @@ -4347,6 +4411,14 @@ type CancelSignatureRequestPayload { deletedDocumentVersionSignatureId: ID! } +input SignDocumentInput { + documentVersionId: ID! +} + +type SignDocumentPayload { + documentVersionSignature: DocumentVersionSignature! +} + type UploadMeasureEvidencePayload { evidenceEdge: EvidenceEdge! } diff --git a/pkg/server/api/console/v1/schema/schema.go b/pkg/server/api/console/v1/schema/schema.go index 958b28aa4..edd8532fa 100644 --- a/pkg/server/api/console/v1/schema/schema.go +++ b/pkg/server/api/console/v1/schema/schema.go @@ -86,6 +86,7 @@ type ResolverRoot interface { Risk() RiskResolver RiskConnection() RiskConnectionResolver SAMLConfiguration() SAMLConfigurationResolver + SignableDocument() SignableDocumentResolver Snapshot() SnapshotResolver SnapshotConnection() SnapshotConnectionResolver Task() TaskResolver @@ -659,6 +660,7 @@ type ComplexityRoot struct { Owner func(childComplexity int) int PublishedAt func(childComplexity int) int Signatures func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentVersionSignatureOrder, filter *types.DocumentVersionSignatureFilter) int + Signed func(childComplexity int) int Status func(childComplexity int) int Title func(childComplexity int) int UpdatedAt func(childComplexity int) int @@ -733,6 +735,10 @@ type ComplexityRoot struct { ExportJobID func(childComplexity int) int } + ExportSignableDocumentVersionPDFPayload struct { + Data func(childComplexity int) int + } + File struct { CreatedAt func(childComplexity int) int DownloadURL func(childComplexity int) int @@ -979,6 +985,7 @@ type ComplexityRoot struct { EnableSaml func(childComplexity int, input types.EnableSAMLInput) int ExportDocumentVersionPDF func(childComplexity int, input types.ExportDocumentVersionPDFInput) int ExportFramework func(childComplexity int, input types.ExportFrameworkInput) int + ExportSignableVersionDocumentPDF func(childComplexity int, input types.ExportSignableDocumentVersionPDFInput) int GenerateDocumentChangelog func(childComplexity int, input types.GenerateDocumentChangelogInput) int GenerateFrameworkStateOfApplicability func(childComplexity int, input types.GenerateFrameworkStateOfApplicabilityInput) int GetTrustCenterFile func(childComplexity int, input types.GetTrustCenterFileInput) int @@ -990,6 +997,7 @@ type ComplexityRoot struct { RemoveMember func(childComplexity int, input types.RemoveMemberInput) int RequestSignature func(childComplexity int, input types.RequestSignatureInput) int SendSigningNotifications func(childComplexity int, input types.SendSigningNotificationsInput) int + SignDocument func(childComplexity int, input types.SignDocumentInput) int UnassignTask func(childComplexity int, input types.UnassignTaskInput) int UpdateAsset func(childComplexity int, input types.UpdateAssetInput) int UpdateAudit func(childComplexity int, input types.UpdateAuditInput) int @@ -1311,6 +1319,32 @@ type ComplexityRoot struct { ID func(childComplexity int) int } + SignDocumentPayload struct { + DocumentVersionSignature func(childComplexity int) int + } + + SignableDocument struct { + Classification func(childComplexity int) int + CreatedAt func(childComplexity int) int + Description func(childComplexity int) int + DocumentType func(childComplexity int) int + ID func(childComplexity int) int + Signed func(childComplexity int) int + Title func(childComplexity int) int + UpdatedAt func(childComplexity int) int + Versions func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentVersionOrderBy, filter *types.DocumentVersionFilter) int + } + + SignableDocumentConnection struct { + Edges func(childComplexity int) int + PageInfo func(childComplexity int) int + } + + SignableDocumentEdge struct { + Cursor func(childComplexity int) int + Node func(childComplexity int) int + } + SlackConnection struct { Channel func(childComplexity int) int ChannelID func(childComplexity int) int @@ -1805,9 +1839,11 @@ type ComplexityRoot struct { } Viewer struct { - ID func(childComplexity int) int - Organizations func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrganizationOrder) int - User func(childComplexity int) int + ID func(childComplexity int) int + Organizations func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrganizationOrder) int + SignableDocument func(childComplexity int, id gid.GID) int + SignableDocuments func(childComplexity int, organizationID gid.GID, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentOrderBy) int + User func(childComplexity int) int } } @@ -1873,6 +1909,7 @@ type DocumentVersionResolver interface { Owner(ctx context.Context, obj *types.DocumentVersion) (*types.People, error) Signatures(ctx context.Context, obj *types.DocumentVersion, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentVersionSignatureOrder, filter *types.DocumentVersionSignatureFilter) (*types.DocumentVersionSignatureConnection, error) + Signed(ctx context.Context, obj *types.DocumentVersion) (bool, error) } type DocumentVersionSignatureResolver interface { DocumentVersion(ctx context.Context, obj *types.DocumentVersionSignature) (*types.DocumentVersion, error) @@ -2026,7 +2063,9 @@ type MutationResolver interface { BulkRequestSignatures(ctx context.Context, input types.BulkRequestSignaturesInput) (*types.BulkRequestSignaturesPayload, error) SendSigningNotifications(ctx context.Context, input types.SendSigningNotificationsInput) (*types.SendSigningNotificationsPayload, error) CancelSignatureRequest(ctx context.Context, input types.CancelSignatureRequestInput) (*types.CancelSignatureRequestPayload, error) + SignDocument(ctx context.Context, input types.SignDocumentInput) (*types.SignDocumentPayload, error) ExportDocumentVersionPDF(ctx context.Context, input types.ExportDocumentVersionPDFInput) (*types.ExportDocumentVersionPDFPayload, error) + ExportSignableVersionDocumentPDF(ctx context.Context, input types.ExportSignableDocumentVersionPDFInput) (*types.ExportSignableDocumentVersionPDFPayload, error) CreateVendorRiskAssessment(ctx context.Context, input types.CreateVendorRiskAssessmentInput) (*types.CreateVendorRiskAssessmentPayload, error) AssessVendor(ctx context.Context, input types.AssessVendorInput) (*types.AssessVendorPayload, error) CreateAsset(ctx context.Context, input types.CreateAssetInput) (*types.CreateAssetPayload, error) @@ -2150,6 +2189,10 @@ type SAMLConfigurationResolver interface { TestLoginURL(ctx context.Context, obj *types.SAMLConfiguration) (string, error) } +type SignableDocumentResolver interface { + Signed(ctx context.Context, obj *types.SignableDocument) (bool, error) + Versions(ctx context.Context, obj *types.SignableDocument, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentVersionOrderBy, filter *types.DocumentVersionFilter) (*types.DocumentVersionConnection, error) +} type SnapshotResolver interface { Organization(ctx context.Context, obj *types.Snapshot) (*types.Organization, error) @@ -2244,6 +2287,8 @@ type VendorServiceResolver interface { } type ViewerResolver interface { Organizations(ctx context.Context, obj *types.Viewer, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrganizationOrder) (*types.OrganizationConnection, error) + SignableDocuments(ctx context.Context, obj *types.Viewer, organizationID gid.GID, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentOrderBy) (*types.SignableDocumentConnection, error) + SignableDocument(ctx context.Context, obj *types.Viewer, id gid.GID) (*types.SignableDocument, error) } type executableSchema struct { @@ -3777,6 +3822,12 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin } return e.complexity.DocumentVersion.Signatures(childComplexity, args["first"].(*int), args["after"].(*page.CursorKey), args["last"].(*int), args["before"].(*page.CursorKey), args["orderBy"].(*types.DocumentVersionSignatureOrder), args["filter"].(*types.DocumentVersionSignatureFilter)), true + case "DocumentVersion.signed": + if e.complexity.DocumentVersion.Signed == nil { + break + } + + return e.complexity.DocumentVersion.Signed(childComplexity), true case "DocumentVersion.status": if e.complexity.DocumentVersion.Status == nil { break @@ -4023,6 +4074,13 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin return e.complexity.ExportFrameworkPayload.ExportJobID(childComplexity), true + case "ExportSignableDocumentVersionPDFPayload.data": + if e.complexity.ExportSignableDocumentVersionPDFPayload.Data == nil { + break + } + + return e.complexity.ExportSignableDocumentVersionPDFPayload.Data(childComplexity), true + case "File.createdAt": if e.complexity.File.CreatedAt == nil { break @@ -5550,6 +5608,17 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin } return e.complexity.Mutation.ExportFramework(childComplexity, args["input"].(types.ExportFrameworkInput)), true + case "Mutation.exportSignableVersionDocumentPDF": + if e.complexity.Mutation.ExportSignableVersionDocumentPDF == nil { + break + } + + args, err := ec.field_Mutation_exportSignableVersionDocumentPDF_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.ExportSignableVersionDocumentPDF(childComplexity, args["input"].(types.ExportSignableDocumentVersionPDFInput)), true case "Mutation.generateDocumentChangelog": if e.complexity.Mutation.GenerateDocumentChangelog == nil { break @@ -5671,6 +5740,17 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin } return e.complexity.Mutation.SendSigningNotifications(childComplexity, args["input"].(types.SendSigningNotificationsInput)), true + case "Mutation.signDocument": + if e.complexity.Mutation.SignDocument == nil { + break + } + + args, err := ec.field_Mutation_signDocument_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.SignDocument(childComplexity, args["input"].(types.SignDocumentInput)), true case "Mutation.unassignTask": if e.complexity.Mutation.UnassignTask == nil { break @@ -7413,6 +7493,99 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin return e.complexity.Session.ID(childComplexity), true + case "SignDocumentPayload.documentVersionSignature": + if e.complexity.SignDocumentPayload.DocumentVersionSignature == nil { + break + } + + return e.complexity.SignDocumentPayload.DocumentVersionSignature(childComplexity), true + + case "SignableDocument.classification": + if e.complexity.SignableDocument.Classification == nil { + break + } + + return e.complexity.SignableDocument.Classification(childComplexity), true + case "SignableDocument.createdAt": + if e.complexity.SignableDocument.CreatedAt == nil { + break + } + + return e.complexity.SignableDocument.CreatedAt(childComplexity), true + case "SignableDocument.description": + if e.complexity.SignableDocument.Description == nil { + break + } + + return e.complexity.SignableDocument.Description(childComplexity), true + case "SignableDocument.documentType": + if e.complexity.SignableDocument.DocumentType == nil { + break + } + + return e.complexity.SignableDocument.DocumentType(childComplexity), true + case "SignableDocument.id": + if e.complexity.SignableDocument.ID == nil { + break + } + + return e.complexity.SignableDocument.ID(childComplexity), true + case "SignableDocument.signed": + if e.complexity.SignableDocument.Signed == nil { + break + } + + return e.complexity.SignableDocument.Signed(childComplexity), true + case "SignableDocument.title": + if e.complexity.SignableDocument.Title == nil { + break + } + + return e.complexity.SignableDocument.Title(childComplexity), true + case "SignableDocument.updatedAt": + if e.complexity.SignableDocument.UpdatedAt == nil { + break + } + + return e.complexity.SignableDocument.UpdatedAt(childComplexity), true + case "SignableDocument.versions": + if e.complexity.SignableDocument.Versions == nil { + break + } + + args, err := ec.field_SignableDocument_versions_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.SignableDocument.Versions(childComplexity, args["first"].(*int), args["after"].(*page.CursorKey), args["last"].(*int), args["before"].(*page.CursorKey), args["orderBy"].(*types.DocumentVersionOrderBy), args["filter"].(*types.DocumentVersionFilter)), true + + case "SignableDocumentConnection.edges": + if e.complexity.SignableDocumentConnection.Edges == nil { + break + } + + return e.complexity.SignableDocumentConnection.Edges(childComplexity), true + case "SignableDocumentConnection.pageInfo": + if e.complexity.SignableDocumentConnection.PageInfo == nil { + break + } + + return e.complexity.SignableDocumentConnection.PageInfo(childComplexity), true + + case "SignableDocumentEdge.cursor": + if e.complexity.SignableDocumentEdge.Cursor == nil { + break + } + + return e.complexity.SignableDocumentEdge.Cursor(childComplexity), true + case "SignableDocumentEdge.node": + if e.complexity.SignableDocumentEdge.Node == nil { + break + } + + return e.complexity.SignableDocumentEdge.Node(childComplexity), true + case "SlackConnection.channel": if e.complexity.SlackConnection.Channel == nil { break @@ -9056,6 +9229,28 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin } return e.complexity.Viewer.Organizations(childComplexity, args["first"].(*int), args["after"].(*page.CursorKey), args["last"].(*int), args["before"].(*page.CursorKey), args["orderBy"].(*types.OrganizationOrder)), true + case "Viewer.signableDocument": + if e.complexity.Viewer.SignableDocument == nil { + break + } + + args, err := ec.field_Viewer_signableDocument_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Viewer.SignableDocument(childComplexity, args["id"].(gid.GID)), true + case "Viewer.signableDocuments": + if e.complexity.Viewer.SignableDocuments == nil { + break + } + + args, err := ec.field_Viewer_signableDocuments_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Viewer.SignableDocuments(childComplexity, args["organizationId"].(gid.GID), args["first"].(*int), args["after"].(*page.CursorKey), args["last"].(*int), args["before"].(*page.CursorKey), args["orderBy"].(*types.DocumentOrderBy)), true case "Viewer.user": if e.complexity.Viewer.User == nil { break @@ -9176,6 +9371,7 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { ec.unmarshalInputEvidenceOrder, ec.unmarshalInputExportDocumentVersionPDFInput, ec.unmarshalInputExportFrameworkInput, + ec.unmarshalInputExportSignableDocumentVersionPDFInput, ec.unmarshalInputFrameworkOrder, ec.unmarshalInputFulfillEvidenceInput, ec.unmarshalInputGenerateDocumentChangelogInput, @@ -9207,6 +9403,7 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { ec.unmarshalInputRiskFilter, ec.unmarshalInputRiskOrder, ec.unmarshalInputSendSigningNotificationsInput, + ec.unmarshalInputSignDocumentInput, ec.unmarshalInputSnapshotOrder, ec.unmarshalInputTaskOrder, ec.unmarshalInputTrustCenterAccessOrder, @@ -9450,6 +9647,7 @@ enum InvitationStatus enum MembershipRole @goModel(model: "go.probo.inc/probo/pkg/coredata.MembershipRole") { OWNER @goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipRoleOwner") ADMIN @goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipRoleAdmin") + EMPLOYEE @goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipRoleEmployee") VIEWER @goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipRoleViewer") } @@ -9878,10 +10076,6 @@ enum BusinessImpact enum DocumentVersionOrderField @goModel(model: "go.probo.inc/probo/pkg/coredata.DocumentVersionOrderField") { - VERSION - @goEnum( - value: "go.probo.inc/probo/pkg/coredata.DocumentVersionOrderFieldVersion" - ) CREATED_AT @goEnum( value: "go.probo.inc/probo/pkg/coredata.DocumentVersionOrderFieldCreatedAt" @@ -11391,6 +11585,29 @@ type Document implements Node { updatedAt: Datetime! } +type SignableDocument @goModel( + model: "go.probo.inc/probo/pkg/server/api/console/v1/types.SignableDocument" + ){ + id: ID! + title: String! + description: String + documentType: DocumentType! + classification: DocumentClassification! + signed: Boolean! @goField(forceResolver: true) + + versions( + first: Int + after: CursorKey + last: Int + before: CursorKey + orderBy: DocumentVersionOrder + filter: DocumentVersionFilter + ): DocumentVersionConnection! @goField(forceResolver: true) + + createdAt: Datetime! + updatedAt: Datetime! +} + type Meeting implements Node { id: ID! name: String! @@ -11615,6 +11832,17 @@ type Viewer { before: CursorKey orderBy: OrganizationOrder ): OrganizationConnection! @goField(forceResolver: true) + + signableDocuments( + organizationId: ID! + first: Int + after: CursorKey + last: Int + before: CursorKey + orderBy: DocumentOrder + ): SignableDocumentConnection! @goField(forceResolver: true) + + signableDocument(id: ID!): SignableDocument @goField(forceResolver: true) } # Connection Types @@ -11870,6 +12098,22 @@ type EvidenceEdge { node: Evidence! } +type SignableDocumentConnection + @goModel( + model: "go.probo.inc/probo/pkg/server/api/console/v1/types.SignableDocumentConnection" + ) { + edges: [SignableDocumentEdge!]! + pageInfo: PageInfo! +} + +type SignableDocumentEdge + @goModel( + model: "go.probo.inc/probo/pkg/server/api/console/v1/types.SignableDocumentEdge" + ) { + cursor: CursorKey! + node: SignableDocument! +} + type DocumentConnection @goModel( model: "go.probo.inc/probo/pkg/server/api/console/v1/types.DocumentConnection" @@ -12270,9 +12514,16 @@ type Mutation { input: SendSigningNotificationsInput! ): SendSigningNotificationsPayload! cancelSignatureRequest( input: CancelSignatureRequestInput! - ): CancelSignatureRequestPayload! exportDocumentVersionPDF( + ): CancelSignatureRequestPayload! + signDocument( + input: SignDocumentInput! + ): SignDocumentPayload! + exportDocumentVersionPDF( input: ExportDocumentVersionPDFInput! ): ExportDocumentVersionPDFPayload! + exportSignableVersionDocumentPDF( + input: ExportSignableDocumentVersionPDFInput! + ): ExportSignableDocumentVersionPDFPayload! createVendorRiskAssessment( input: CreateVendorRiskAssessmentInput! ): CreateVendorRiskAssessmentPayload! @@ -12844,6 +13095,10 @@ input ExportDocumentVersionPDFInput { withSignatures: Boolean! } +input ExportSignableDocumentVersionPDFInput { + documentVersionId: ID! +} + input DeleteDocumentInput { documentId: ID! } @@ -13428,6 +13683,10 @@ type ExportDocumentVersionPDFPayload { data: String! } +type ExportSignableDocumentVersionPDFPayload { + data: String! +} + type UpdateDocumentPayload { document: Document! } @@ -13542,6 +13801,8 @@ type DocumentVersion implements Node @goModel(model: "go.probo.inc/probo/pkg/ser filter: DocumentVersionSignatureFilter ): DocumentVersionSignatureConnection! @goField(forceResolver: true) + signed: Boolean! @goField(forceResolver: true) + publishedAt: Datetime createdAt: Datetime! updatedAt: Datetime! @@ -13703,6 +13964,14 @@ type CancelSignatureRequestPayload { deletedDocumentVersionSignatureId: ID! } +input SignDocumentInput { + documentVersionId: ID! +} + +type SignDocumentPayload { + documentVersionSignature: DocumentVersionSignature! +} + type UploadMeasureEvidencePayload { evidenceEdge: EvidenceEdge! } @@ -15650,6 +15919,17 @@ func (ec *executionContext) field_Mutation_exportFramework_args(ctx context.Cont return args, nil } +func (ec *executionContext) field_Mutation_exportSignableVersionDocumentPDF_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.unmarshalNExportSignableDocumentVersionPDFInput2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐExportSignableDocumentVersionPDFInput) + if err != nil { + return nil, err + } + args["input"] = arg0 + return args, nil +} + func (ec *executionContext) field_Mutation_generateDocumentChangelog_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} @@ -15771,6 +16051,17 @@ func (ec *executionContext) field_Mutation_sendSigningNotifications_args(ctx con return args, nil } +func (ec *executionContext) field_Mutation_signDocument_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.unmarshalNSignDocumentInput2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐSignDocumentInput) + if err != nil { + return nil, err + } + args["input"] = arg0 + return args, nil +} + func (ec *executionContext) field_Mutation_unassignTask_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} @@ -17086,6 +17377,42 @@ func (ec *executionContext) field_Risk_obligations_args(ctx context.Context, raw return args, nil } +func (ec *executionContext) field_SignableDocument_versions_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, "first", ec.unmarshalOInt2ᚖint) + if err != nil { + return nil, err + } + args["first"] = arg0 + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "after", ec.unmarshalOCursorKey2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋpageᚐCursorKey) + if err != nil { + return nil, err + } + args["after"] = arg1 + arg2, err := graphql.ProcessArgField(ctx, rawArgs, "last", ec.unmarshalOInt2ᚖint) + if err != nil { + return nil, err + } + args["last"] = arg2 + arg3, err := graphql.ProcessArgField(ctx, rawArgs, "before", ec.unmarshalOCursorKey2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋpageᚐCursorKey) + if err != nil { + return nil, err + } + args["before"] = arg3 + arg4, err := graphql.ProcessArgField(ctx, rawArgs, "orderBy", ec.unmarshalODocumentVersionOrder2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐDocumentVersionOrderBy) + if err != nil { + return nil, err + } + args["orderBy"] = arg4 + arg5, err := graphql.ProcessArgField(ctx, rawArgs, "filter", ec.unmarshalODocumentVersionFilter2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐDocumentVersionFilter) + if err != nil { + return nil, err + } + args["filter"] = arg5 + return args, nil +} + func (ec *executionContext) field_Snapshot_controls_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} @@ -17401,6 +17728,53 @@ func (ec *executionContext) field_Viewer_organizations_args(ctx context.Context, return args, nil } +func (ec *executionContext) field_Viewer_signableDocument_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, "id", ec.unmarshalNID2goᚗproboᚗincᚋproboᚋpkgᚋgidᚐGID) + if err != nil { + return nil, err + } + args["id"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Viewer_signableDocuments_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, "organizationId", ec.unmarshalNID2goᚗproboᚗincᚋproboᚋpkgᚋgidᚐGID) + if err != nil { + return nil, err + } + args["organizationId"] = arg0 + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "first", ec.unmarshalOInt2ᚖint) + if err != nil { + return nil, err + } + args["first"] = arg1 + arg2, err := graphql.ProcessArgField(ctx, rawArgs, "after", ec.unmarshalOCursorKey2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋpageᚐCursorKey) + if err != nil { + return nil, err + } + args["after"] = arg2 + arg3, err := graphql.ProcessArgField(ctx, rawArgs, "last", ec.unmarshalOInt2ᚖint) + if err != nil { + return nil, err + } + args["last"] = arg3 + arg4, err := graphql.ProcessArgField(ctx, rawArgs, "before", ec.unmarshalOCursorKey2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋpageᚐCursorKey) + if err != nil { + return nil, err + } + args["before"] = arg4 + arg5, err := graphql.ProcessArgField(ctx, rawArgs, "orderBy", ec.unmarshalODocumentOrder2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐDocumentOrderBy) + if err != nil { + return nil, err + } + args["orderBy"] = arg5 + return args, nil +} + func (ec *executionContext) field___Directive_args_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} @@ -25726,6 +26100,35 @@ func (ec *executionContext) fieldContext_DocumentVersion_signatures(ctx context. return fc, nil } +func (ec *executionContext) _DocumentVersion_signed(ctx context.Context, field graphql.CollectedField, obj *types.DocumentVersion) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + ec.fieldContext_DocumentVersion_signed, + func(ctx context.Context) (any, error) { + return ec.resolvers.DocumentVersion().Signed(ctx, obj) + }, + nil, + ec.marshalNBoolean2bool, + true, + true, + ) +} + +func (ec *executionContext) fieldContext_DocumentVersion_signed(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DocumentVersion", + 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) _DocumentVersion_publishedAt(ctx context.Context, field graphql.CollectedField, obj *types.DocumentVersion) (ret graphql.Marshaler) { return graphql.ResolveField( ctx, @@ -25960,6 +26363,8 @@ func (ec *executionContext) fieldContext_DocumentVersionEdge_node(_ context.Cont return ec.fieldContext_DocumentVersion_owner(ctx, field) case "signatures": return ec.fieldContext_DocumentVersion_signatures(ctx, field) + case "signed": + return ec.fieldContext_DocumentVersion_signed(ctx, field) case "publishedAt": return ec.fieldContext_DocumentVersion_publishedAt(ctx, field) case "createdAt": @@ -26046,6 +26451,8 @@ func (ec *executionContext) fieldContext_DocumentVersionSignature_documentVersio return ec.fieldContext_DocumentVersion_owner(ctx, field) case "signatures": return ec.fieldContext_DocumentVersion_signatures(ctx, field) + case "signed": + return ec.fieldContext_DocumentVersion_signed(ctx, field) case "publishedAt": return ec.fieldContext_DocumentVersion_publishedAt(ctx, field) case "createdAt": @@ -27110,6 +27517,35 @@ func (ec *executionContext) fieldContext_ExportFrameworkPayload_exportJobId(_ co return fc, nil } +func (ec *executionContext) _ExportSignableDocumentVersionPDFPayload_data(ctx context.Context, field graphql.CollectedField, obj *types.ExportSignableDocumentVersionPDFPayload) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + ec.fieldContext_ExportSignableDocumentVersionPDFPayload_data, + func(ctx context.Context) (any, error) { + return obj.Data, nil + }, + nil, + ec.marshalNString2string, + true, + true, + ) +} + +func (ec *executionContext) fieldContext_ExportSignableDocumentVersionPDFPayload_data(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "ExportSignableDocumentVersionPDFPayload", + 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) _File_id(ctx context.Context, field graphql.CollectedField, obj *types.File) (ret graphql.Marshaler) { return graphql.ResolveField( ctx, @@ -34670,6 +35106,51 @@ func (ec *executionContext) fieldContext_Mutation_cancelSignatureRequest(ctx con return fc, nil } +func (ec *executionContext) _Mutation_signDocument(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + ec.fieldContext_Mutation_signDocument, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.resolvers.Mutation().SignDocument(ctx, fc.Args["input"].(types.SignDocumentInput)) + }, + nil, + ec.marshalNSignDocumentPayload2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐSignDocumentPayload, + true, + true, + ) +} + +func (ec *executionContext) fieldContext_Mutation_signDocument(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 "documentVersionSignature": + return ec.fieldContext_SignDocumentPayload_documentVersionSignature(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type SignDocumentPayload", 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_signDocument_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + func (ec *executionContext) _Mutation_exportDocumentVersionPDF(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { return graphql.ResolveField( ctx, @@ -34715,6 +35196,51 @@ func (ec *executionContext) fieldContext_Mutation_exportDocumentVersionPDF(ctx c return fc, nil } +func (ec *executionContext) _Mutation_exportSignableVersionDocumentPDF(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + ec.fieldContext_Mutation_exportSignableVersionDocumentPDF, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.resolvers.Mutation().ExportSignableVersionDocumentPDF(ctx, fc.Args["input"].(types.ExportSignableDocumentVersionPDFInput)) + }, + nil, + ec.marshalNExportSignableDocumentVersionPDFPayload2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐExportSignableDocumentVersionPDFPayload, + true, + true, + ) +} + +func (ec *executionContext) fieldContext_Mutation_exportSignableVersionDocumentPDF(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 "data": + return ec.fieldContext_ExportSignableDocumentVersionPDFPayload_data(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type ExportSignableDocumentVersionPDFPayload", 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_exportSignableVersionDocumentPDF_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + func (ec *executionContext) _Mutation_createVendorRiskAssessment(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { return graphql.ResolveField( ctx, @@ -41168,6 +41694,8 @@ func (ec *executionContext) fieldContext_PublishDocumentVersionPayload_documentV return ec.fieldContext_DocumentVersion_owner(ctx, field) case "signatures": return ec.fieldContext_DocumentVersion_signatures(ctx, field) + case "signed": + return ec.fieldContext_DocumentVersion_signed(ctx, field) case "publishedAt": return ec.fieldContext_DocumentVersion_publishedAt(ctx, field) case "createdAt": @@ -41309,6 +41837,10 @@ func (ec *executionContext) fieldContext_Query_viewer(_ context.Context, field g return ec.fieldContext_Viewer_user(ctx, field) case "organizations": return ec.fieldContext_Viewer_organizations(ctx, field) + case "signableDocuments": + return ec.fieldContext_Viewer_signableDocuments(ctx, field) + case "signableDocument": + return ec.fieldContext_Viewer_signableDocument(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Viewer", field.Name) }, @@ -43626,6 +44158,484 @@ func (ec *executionContext) fieldContext_Session_expiresAt(_ context.Context, fi return fc, nil } +func (ec *executionContext) _SignDocumentPayload_documentVersionSignature(ctx context.Context, field graphql.CollectedField, obj *types.SignDocumentPayload) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + ec.fieldContext_SignDocumentPayload_documentVersionSignature, + func(ctx context.Context) (any, error) { + return obj.DocumentVersionSignature, nil + }, + nil, + ec.marshalNDocumentVersionSignature2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐDocumentVersionSignature, + true, + true, + ) +} + +func (ec *executionContext) fieldContext_SignDocumentPayload_documentVersionSignature(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "SignDocumentPayload", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "id": + return ec.fieldContext_DocumentVersionSignature_id(ctx, field) + case "documentVersion": + return ec.fieldContext_DocumentVersionSignature_documentVersion(ctx, field) + case "state": + return ec.fieldContext_DocumentVersionSignature_state(ctx, field) + case "signedBy": + return ec.fieldContext_DocumentVersionSignature_signedBy(ctx, field) + case "signedAt": + return ec.fieldContext_DocumentVersionSignature_signedAt(ctx, field) + case "requestedAt": + return ec.fieldContext_DocumentVersionSignature_requestedAt(ctx, field) + case "createdAt": + return ec.fieldContext_DocumentVersionSignature_createdAt(ctx, field) + case "updatedAt": + return ec.fieldContext_DocumentVersionSignature_updatedAt(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type DocumentVersionSignature", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _SignableDocument_id(ctx context.Context, field graphql.CollectedField, obj *types.SignableDocument) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + ec.fieldContext_SignableDocument_id, + func(ctx context.Context) (any, error) { + return obj.ID, nil + }, + nil, + ec.marshalNID2goᚗproboᚗincᚋproboᚋpkgᚋgidᚐGID, + true, + true, + ) +} + +func (ec *executionContext) fieldContext_SignableDocument_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "SignableDocument", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type ID does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _SignableDocument_title(ctx context.Context, field graphql.CollectedField, obj *types.SignableDocument) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + ec.fieldContext_SignableDocument_title, + func(ctx context.Context) (any, error) { + return obj.Title, nil + }, + nil, + ec.marshalNString2string, + true, + true, + ) +} + +func (ec *executionContext) fieldContext_SignableDocument_title(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "SignableDocument", + 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) _SignableDocument_description(ctx context.Context, field graphql.CollectedField, obj *types.SignableDocument) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + ec.fieldContext_SignableDocument_description, + func(ctx context.Context) (any, error) { + return obj.Description, nil + }, + nil, + ec.marshalOString2ᚖstring, + true, + false, + ) +} + +func (ec *executionContext) fieldContext_SignableDocument_description(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "SignableDocument", + 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) _SignableDocument_documentType(ctx context.Context, field graphql.CollectedField, obj *types.SignableDocument) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + ec.fieldContext_SignableDocument_documentType, + func(ctx context.Context) (any, error) { + return obj.DocumentType, nil + }, + nil, + ec.marshalNDocumentType2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐDocumentType, + true, + true, + ) +} + +func (ec *executionContext) fieldContext_SignableDocument_documentType(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "SignableDocument", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type DocumentType does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _SignableDocument_classification(ctx context.Context, field graphql.CollectedField, obj *types.SignableDocument) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + ec.fieldContext_SignableDocument_classification, + func(ctx context.Context) (any, error) { + return obj.Classification, nil + }, + nil, + ec.marshalNDocumentClassification2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐDocumentClassification, + true, + true, + ) +} + +func (ec *executionContext) fieldContext_SignableDocument_classification(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "SignableDocument", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type DocumentClassification does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _SignableDocument_signed(ctx context.Context, field graphql.CollectedField, obj *types.SignableDocument) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + ec.fieldContext_SignableDocument_signed, + func(ctx context.Context) (any, error) { + return ec.resolvers.SignableDocument().Signed(ctx, obj) + }, + nil, + ec.marshalNBoolean2bool, + true, + true, + ) +} + +func (ec *executionContext) fieldContext_SignableDocument_signed(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "SignableDocument", + 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) _SignableDocument_versions(ctx context.Context, field graphql.CollectedField, obj *types.SignableDocument) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + ec.fieldContext_SignableDocument_versions, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.resolvers.SignableDocument().Versions(ctx, obj, fc.Args["first"].(*int), fc.Args["after"].(*page.CursorKey), fc.Args["last"].(*int), fc.Args["before"].(*page.CursorKey), fc.Args["orderBy"].(*types.DocumentVersionOrderBy), fc.Args["filter"].(*types.DocumentVersionFilter)) + }, + nil, + ec.marshalNDocumentVersionConnection2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐDocumentVersionConnection, + true, + true, + ) +} + +func (ec *executionContext) fieldContext_SignableDocument_versions(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "SignableDocument", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "edges": + return ec.fieldContext_DocumentVersionConnection_edges(ctx, field) + case "pageInfo": + return ec.fieldContext_DocumentVersionConnection_pageInfo(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type DocumentVersionConnection", 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_SignableDocument_versions_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _SignableDocument_createdAt(ctx context.Context, field graphql.CollectedField, obj *types.SignableDocument) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + ec.fieldContext_SignableDocument_createdAt, + func(ctx context.Context) (any, error) { + return obj.CreatedAt, nil + }, + nil, + ec.marshalNDatetime2timeᚐTime, + true, + true, + ) +} + +func (ec *executionContext) fieldContext_SignableDocument_createdAt(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "SignableDocument", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Datetime does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _SignableDocument_updatedAt(ctx context.Context, field graphql.CollectedField, obj *types.SignableDocument) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + ec.fieldContext_SignableDocument_updatedAt, + func(ctx context.Context) (any, error) { + return obj.UpdatedAt, nil + }, + nil, + ec.marshalNDatetime2timeᚐTime, + true, + true, + ) +} + +func (ec *executionContext) fieldContext_SignableDocument_updatedAt(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "SignableDocument", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Datetime does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _SignableDocumentConnection_edges(ctx context.Context, field graphql.CollectedField, obj *types.SignableDocumentConnection) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + ec.fieldContext_SignableDocumentConnection_edges, + func(ctx context.Context) (any, error) { + return obj.Edges, nil + }, + nil, + ec.marshalNSignableDocumentEdge2ᚕᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐSignableDocumentEdgeᚄ, + true, + true, + ) +} + +func (ec *executionContext) fieldContext_SignableDocumentConnection_edges(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "SignableDocumentConnection", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "cursor": + return ec.fieldContext_SignableDocumentEdge_cursor(ctx, field) + case "node": + return ec.fieldContext_SignableDocumentEdge_node(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type SignableDocumentEdge", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _SignableDocumentConnection_pageInfo(ctx context.Context, field graphql.CollectedField, obj *types.SignableDocumentConnection) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + ec.fieldContext_SignableDocumentConnection_pageInfo, + func(ctx context.Context) (any, error) { + return obj.PageInfo, nil + }, + nil, + ec.marshalNPageInfo2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐPageInfo, + true, + true, + ) +} + +func (ec *executionContext) fieldContext_SignableDocumentConnection_pageInfo(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "SignableDocumentConnection", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "hasNextPage": + return ec.fieldContext_PageInfo_hasNextPage(ctx, field) + case "hasPreviousPage": + return ec.fieldContext_PageInfo_hasPreviousPage(ctx, field) + case "startCursor": + return ec.fieldContext_PageInfo_startCursor(ctx, field) + case "endCursor": + return ec.fieldContext_PageInfo_endCursor(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type PageInfo", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _SignableDocumentEdge_cursor(ctx context.Context, field graphql.CollectedField, obj *types.SignableDocumentEdge) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + ec.fieldContext_SignableDocumentEdge_cursor, + func(ctx context.Context) (any, error) { + return obj.Cursor, nil + }, + nil, + ec.marshalNCursorKey2goᚗproboᚗincᚋproboᚋpkgᚋpageᚐCursorKey, + true, + true, + ) +} + +func (ec *executionContext) fieldContext_SignableDocumentEdge_cursor(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "SignableDocumentEdge", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type CursorKey does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _SignableDocumentEdge_node(ctx context.Context, field graphql.CollectedField, obj *types.SignableDocumentEdge) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + ec.fieldContext_SignableDocumentEdge_node, + func(ctx context.Context) (any, error) { + return obj.Node, nil + }, + nil, + ec.marshalNSignableDocument2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐSignableDocument, + true, + true, + ) +} + +func (ec *executionContext) fieldContext_SignableDocumentEdge_node(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "SignableDocumentEdge", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "id": + return ec.fieldContext_SignableDocument_id(ctx, field) + case "title": + return ec.fieldContext_SignableDocument_title(ctx, field) + case "description": + return ec.fieldContext_SignableDocument_description(ctx, field) + case "documentType": + return ec.fieldContext_SignableDocument_documentType(ctx, field) + case "classification": + return ec.fieldContext_SignableDocument_classification(ctx, field) + case "signed": + return ec.fieldContext_SignableDocument_signed(ctx, field) + case "versions": + return ec.fieldContext_SignableDocument_versions(ctx, field) + case "createdAt": + return ec.fieldContext_SignableDocument_createdAt(ctx, field) + case "updatedAt": + return ec.fieldContext_SignableDocument_updatedAt(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type SignableDocument", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _SlackConnection_id(ctx context.Context, field graphql.CollectedField, obj *types.SlackConnection) (ret graphql.Marshaler) { return graphql.ResolveField( ctx, @@ -47785,6 +48795,8 @@ func (ec *executionContext) fieldContext_UpdateDocumentVersionPayload_documentVe return ec.fieldContext_DocumentVersion_owner(ctx, field) case "signatures": return ec.fieldContext_DocumentVersion_signatures(ctx, field) + case "signed": + return ec.fieldContext_DocumentVersion_signed(ctx, field) case "publishedAt": return ec.fieldContext_DocumentVersion_publishedAt(ctx, field) case "createdAt": @@ -53613,6 +54625,114 @@ func (ec *executionContext) fieldContext_Viewer_organizations(ctx context.Contex return fc, nil } +func (ec *executionContext) _Viewer_signableDocuments(ctx context.Context, field graphql.CollectedField, obj *types.Viewer) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + ec.fieldContext_Viewer_signableDocuments, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.resolvers.Viewer().SignableDocuments(ctx, obj, fc.Args["organizationId"].(gid.GID), fc.Args["first"].(*int), fc.Args["after"].(*page.CursorKey), fc.Args["last"].(*int), fc.Args["before"].(*page.CursorKey), fc.Args["orderBy"].(*types.DocumentOrderBy)) + }, + nil, + ec.marshalNSignableDocumentConnection2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐSignableDocumentConnection, + true, + true, + ) +} + +func (ec *executionContext) fieldContext_Viewer_signableDocuments(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Viewer", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "edges": + return ec.fieldContext_SignableDocumentConnection_edges(ctx, field) + case "pageInfo": + return ec.fieldContext_SignableDocumentConnection_pageInfo(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type SignableDocumentConnection", 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_Viewer_signableDocuments_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Viewer_signableDocument(ctx context.Context, field graphql.CollectedField, obj *types.Viewer) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + ec.fieldContext_Viewer_signableDocument, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.resolvers.Viewer().SignableDocument(ctx, obj, fc.Args["id"].(gid.GID)) + }, + nil, + ec.marshalOSignableDocument2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐSignableDocument, + true, + false, + ) +} + +func (ec *executionContext) fieldContext_Viewer_signableDocument(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Viewer", + 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_SignableDocument_id(ctx, field) + case "title": + return ec.fieldContext_SignableDocument_title(ctx, field) + case "description": + return ec.fieldContext_SignableDocument_description(ctx, field) + case "documentType": + return ec.fieldContext_SignableDocument_documentType(ctx, field) + case "classification": + return ec.fieldContext_SignableDocument_classification(ctx, field) + case "signed": + return ec.fieldContext_SignableDocument_signed(ctx, field) + case "versions": + return ec.fieldContext_SignableDocument_versions(ctx, field) + case "createdAt": + return ec.fieldContext_SignableDocument_createdAt(ctx, field) + case "updatedAt": + return ec.fieldContext_SignableDocument_updatedAt(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type SignableDocument", 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_Viewer_signableDocument_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + func (ec *executionContext) ___Directive_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { return graphql.ResolveField( ctx, @@ -59287,6 +60407,33 @@ func (ec *executionContext) unmarshalInputExportFrameworkInput(ctx context.Conte return it, nil } +func (ec *executionContext) unmarshalInputExportSignableDocumentVersionPDFInput(ctx context.Context, obj any) (types.ExportSignableDocumentVersionPDFInput, error) { + var it types.ExportSignableDocumentVersionPDFInput + asMap := map[string]any{} + for k, v := range obj.(map[string]any) { + asMap[k] = v + } + + fieldsInOrder := [...]string{"documentVersionId"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "documentVersionId": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("documentVersionId")) + data, err := ec.unmarshalNID2goᚗproboᚗincᚋproboᚋpkgᚋgidᚐGID(ctx, v) + if err != nil { + return it, err + } + it.DocumentVersionID = data + } + } + + return it, nil +} + func (ec *executionContext) unmarshalInputFrameworkOrder(ctx context.Context, obj any) (types.FrameworkOrderBy, error) { var it types.FrameworkOrderBy asMap := map[string]any{} @@ -60327,6 +61474,33 @@ func (ec *executionContext) unmarshalInputSendSigningNotificationsInput(ctx cont return it, nil } +func (ec *executionContext) unmarshalInputSignDocumentInput(ctx context.Context, obj any) (types.SignDocumentInput, error) { + var it types.SignDocumentInput + asMap := map[string]any{} + for k, v := range obj.(map[string]any) { + asMap[k] = v + } + + fieldsInOrder := [...]string{"documentVersionId"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "documentVersionId": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("documentVersionId")) + data, err := ec.unmarshalNID2goᚗproboᚗincᚋproboᚋpkgᚋgidᚐGID(ctx, v) + if err != nil { + return it, err + } + it.DocumentVersionID = data + } + } + + return it, nil +} + func (ec *executionContext) unmarshalInputSnapshotOrder(ctx context.Context, obj any) (types.SnapshotOrderBy, error) { var it types.SnapshotOrderBy asMap := map[string]any{} @@ -69022,6 +70196,42 @@ func (ec *executionContext) _DocumentVersion(ctx context.Context, sel ast.Select continue } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + case "signed": + 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._DocumentVersion_signed(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 "publishedAt": out.Values[i] = ec._DocumentVersion_publishedAt(ctx, field, obj) @@ -69778,6 +70988,45 @@ func (ec *executionContext) _ExportFrameworkPayload(ctx context.Context, sel ast return out } +var exportSignableDocumentVersionPDFPayloadImplementors = []string{"ExportSignableDocumentVersionPDFPayload"} + +func (ec *executionContext) _ExportSignableDocumentVersionPDFPayload(ctx context.Context, sel ast.SelectionSet, obj *types.ExportSignableDocumentVersionPDFPayload) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, exportSignableDocumentVersionPDFPayloadImplementors) + + 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("ExportSignableDocumentVersionPDFPayload") + case "data": + out.Values[i] = ec._ExportSignableDocumentVersionPDFPayload_data(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 fileImplementors = []string{"File"} func (ec *executionContext) _File(ctx context.Context, sel ast.SelectionSet, obj *types.File) graphql.Marshaler { @@ -72215,6 +73464,13 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) if out.Values[i] == graphql.Null { out.Invalids++ } + case "signDocument": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_signDocument(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } case "exportDocumentVersionPDF": out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { return ec._Mutation_exportDocumentVersionPDF(ctx, field) @@ -72222,6 +73478,13 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) if out.Values[i] == graphql.Null { out.Invalids++ } + case "exportSignableVersionDocumentPDF": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_exportSignableVersionDocumentPDF(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } case "createVendorRiskAssessment": out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { return ec._Mutation_createVendorRiskAssessment(ctx, field) @@ -75911,6 +77174,271 @@ func (ec *executionContext) _Session(ctx context.Context, sel ast.SelectionSet, return out } +var signDocumentPayloadImplementors = []string{"SignDocumentPayload"} + +func (ec *executionContext) _SignDocumentPayload(ctx context.Context, sel ast.SelectionSet, obj *types.SignDocumentPayload) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, signDocumentPayloadImplementors) + + 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("SignDocumentPayload") + case "documentVersionSignature": + out.Values[i] = ec._SignDocumentPayload_documentVersionSignature(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 signableDocumentImplementors = []string{"SignableDocument"} + +func (ec *executionContext) _SignableDocument(ctx context.Context, sel ast.SelectionSet, obj *types.SignableDocument) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, signableDocumentImplementors) + + 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("SignableDocument") + case "id": + out.Values[i] = ec._SignableDocument_id(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "title": + out.Values[i] = ec._SignableDocument_title(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "description": + out.Values[i] = ec._SignableDocument_description(ctx, field, obj) + case "documentType": + out.Values[i] = ec._SignableDocument_documentType(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "classification": + out.Values[i] = ec._SignableDocument_classification(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "signed": + 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._SignableDocument_signed(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 "versions": + 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._SignableDocument_versions(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 "createdAt": + out.Values[i] = ec._SignableDocument_createdAt(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "updatedAt": + out.Values[i] = ec._SignableDocument_updatedAt(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + 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 signableDocumentConnectionImplementors = []string{"SignableDocumentConnection"} + +func (ec *executionContext) _SignableDocumentConnection(ctx context.Context, sel ast.SelectionSet, obj *types.SignableDocumentConnection) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, signableDocumentConnectionImplementors) + + 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("SignableDocumentConnection") + case "edges": + out.Values[i] = ec._SignableDocumentConnection_edges(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "pageInfo": + out.Values[i] = ec._SignableDocumentConnection_pageInfo(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 signableDocumentEdgeImplementors = []string{"SignableDocumentEdge"} + +func (ec *executionContext) _SignableDocumentEdge(ctx context.Context, sel ast.SelectionSet, obj *types.SignableDocumentEdge) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, signableDocumentEdgeImplementors) + + 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("SignableDocumentEdge") + case "cursor": + out.Values[i] = ec._SignableDocumentEdge_cursor(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "node": + out.Values[i] = ec._SignableDocumentEdge_node(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 slackConnectionImplementors = []string{"SlackConnection"} func (ec *executionContext) _SlackConnection(ctx context.Context, sel ast.SelectionSet, obj *types.SlackConnection) graphql.Marshaler { @@ -81200,6 +82728,75 @@ func (ec *executionContext) _Viewer(ctx context.Context, sel ast.SelectionSet, o continue } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + case "signableDocuments": + 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._Viewer_signableDocuments(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 "signableDocument": + 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._Viewer_signableDocument(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)) @@ -84982,11 +86579,9 @@ func (ec *executionContext) marshalNDocumentVersionOrderField2goᚗproboᚗinc var ( unmarshalNDocumentVersionOrderField2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐDocumentVersionOrderField = map[string]coredata.DocumentVersionOrderField{ - "VERSION": coredata.DocumentVersionOrderFieldVersion, "CREATED_AT": coredata.DocumentVersionOrderFieldCreatedAt, } marshalNDocumentVersionOrderField2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐDocumentVersionOrderField = map[coredata.DocumentVersionOrderField]string{ - coredata.DocumentVersionOrderFieldVersion: "VERSION", coredata.DocumentVersionOrderFieldCreatedAt: "CREATED_AT", } ) @@ -85333,6 +86928,25 @@ func (ec *executionContext) marshalNExportFrameworkPayload2ᚖgoᚗproboᚗinc return ec._ExportFrameworkPayload(ctx, sel, v) } +func (ec *executionContext) unmarshalNExportSignableDocumentVersionPDFInput2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐExportSignableDocumentVersionPDFInput(ctx context.Context, v any) (types.ExportSignableDocumentVersionPDFInput, error) { + res, err := ec.unmarshalInputExportSignableDocumentVersionPDFInput(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNExportSignableDocumentVersionPDFPayload2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐExportSignableDocumentVersionPDFPayload(ctx context.Context, sel ast.SelectionSet, v types.ExportSignableDocumentVersionPDFPayload) graphql.Marshaler { + return ec._ExportSignableDocumentVersionPDFPayload(ctx, sel, &v) +} + +func (ec *executionContext) marshalNExportSignableDocumentVersionPDFPayload2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐExportSignableDocumentVersionPDFPayload(ctx context.Context, sel ast.SelectionSet, v *types.ExportSignableDocumentVersionPDFPayload) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._ExportSignableDocumentVersionPDFPayload(ctx, sel, v) +} + func (ec *executionContext) marshalNFramework2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐFramework(ctx context.Context, sel ast.SelectionSet, v types.Framework) graphql.Marshaler { return ec._Framework(ctx, sel, &v) } @@ -86159,14 +87773,16 @@ func (ec *executionContext) marshalNMembershipRole2goᚗproboᚗincᚋproboᚋpk var ( unmarshalNMembershipRole2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐMembershipRole = map[string]coredata.MembershipRole{ - "OWNER": coredata.MembershipRoleOwner, - "ADMIN": coredata.MembershipRoleAdmin, - "VIEWER": coredata.MembershipRoleViewer, + "OWNER": coredata.MembershipRoleOwner, + "ADMIN": coredata.MembershipRoleAdmin, + "EMPLOYEE": coredata.MembershipRoleEmployee, + "VIEWER": coredata.MembershipRoleViewer, } marshalNMembershipRole2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐMembershipRole = map[coredata.MembershipRole]string{ - coredata.MembershipRoleOwner: "OWNER", - coredata.MembershipRoleAdmin: "ADMIN", - coredata.MembershipRoleViewer: "VIEWER", + coredata.MembershipRoleOwner: "OWNER", + coredata.MembershipRoleAdmin: "ADMIN", + coredata.MembershipRoleEmployee: "EMPLOYEE", + coredata.MembershipRoleViewer: "VIEWER", } ) @@ -87386,6 +89002,103 @@ func (ec *executionContext) marshalNSendSigningNotificationsPayload2ᚖgoᚗprob return ec._SendSigningNotificationsPayload(ctx, sel, v) } +func (ec *executionContext) unmarshalNSignDocumentInput2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐSignDocumentInput(ctx context.Context, v any) (types.SignDocumentInput, error) { + res, err := ec.unmarshalInputSignDocumentInput(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNSignDocumentPayload2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐSignDocumentPayload(ctx context.Context, sel ast.SelectionSet, v types.SignDocumentPayload) graphql.Marshaler { + return ec._SignDocumentPayload(ctx, sel, &v) +} + +func (ec *executionContext) marshalNSignDocumentPayload2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐSignDocumentPayload(ctx context.Context, sel ast.SelectionSet, v *types.SignDocumentPayload) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._SignDocumentPayload(ctx, sel, v) +} + +func (ec *executionContext) marshalNSignableDocument2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐSignableDocument(ctx context.Context, sel ast.SelectionSet, v *types.SignableDocument) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._SignableDocument(ctx, sel, v) +} + +func (ec *executionContext) marshalNSignableDocumentConnection2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐSignableDocumentConnection(ctx context.Context, sel ast.SelectionSet, v types.SignableDocumentConnection) graphql.Marshaler { + return ec._SignableDocumentConnection(ctx, sel, &v) +} + +func (ec *executionContext) marshalNSignableDocumentConnection2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐSignableDocumentConnection(ctx context.Context, sel ast.SelectionSet, v *types.SignableDocumentConnection) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._SignableDocumentConnection(ctx, sel, v) +} + +func (ec *executionContext) marshalNSignableDocumentEdge2ᚕᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐSignableDocumentEdgeᚄ(ctx context.Context, sel ast.SelectionSet, v []*types.SignableDocumentEdge) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNSignableDocumentEdge2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐSignableDocumentEdge(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalNSignableDocumentEdge2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐSignableDocumentEdge(ctx context.Context, sel ast.SelectionSet, v *types.SignableDocumentEdge) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._SignableDocumentEdge(ctx, sel, v) +} + func (ec *executionContext) marshalNSlackConnection2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐSlackConnection(ctx context.Context, sel ast.SelectionSet, v *types.SlackConnection) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { @@ -91366,6 +93079,13 @@ var ( } ) +func (ec *executionContext) marshalOSignableDocument2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐSignableDocument(ctx context.Context, sel ast.SelectionSet, v *types.SignableDocument) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._SignableDocument(ctx, sel, v) +} + func (ec *executionContext) unmarshalOSnapshotOrder2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐSnapshotOrderBy(ctx context.Context, v any) (*types.SnapshotOrderBy, error) { if v == nil { return nil, nil diff --git a/pkg/server/api/console/v1/types/signable_document.go b/pkg/server/api/console/v1/types/signable_document.go new file mode 100644 index 000000000..63ee889c3 --- /dev/null +++ b/pkg/server/api/console/v1/types/signable_document.go @@ -0,0 +1,83 @@ +// Copyright (c) 2025 Probo Inc . +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +package types + +import ( + "time" + + "go.probo.inc/probo/pkg/coredata" + "go.probo.inc/probo/pkg/gid" + "go.probo.inc/probo/pkg/page" +) + +type ( + SignableDocumentConnection struct { + Edges []*SignableDocumentEdge + PageInfo *PageInfo + } + + SignableDocumentEdge struct { + Cursor page.CursorKey + Node *SignableDocument + } + + SignableDocument struct { + ID gid.GID + Title string + Description *string + DocumentType coredata.DocumentType + Classification coredata.DocumentClassification + CreatedAt time.Time + UpdatedAt time.Time + } +) + +func (SignableDocument) IsNode() {} +func (this SignableDocument) GetID() gid.GID { return this.ID } + +func NewSignableDocumentConnection( + p *page.Page[*SignableDocument, coredata.DocumentOrderField], +) *SignableDocumentConnection { + var edges = make([]*SignableDocumentEdge, len(p.Data)) + + for i := range edges { + edges[i] = NewSignableDocumentEdge(p.Data[i], p.Cursor.OrderBy.Field) + } + + return &SignableDocumentConnection{ + Edges: edges, + PageInfo: NewPageInfo(p), + } +} + +func NewSignableDocumentEdge(document *SignableDocument, orderBy coredata.DocumentOrderField) *SignableDocumentEdge { + return &SignableDocumentEdge{ + Cursor: document.CursorKey(orderBy), + Node: document, + } +} + +func (d SignableDocument) CursorKey(orderBy coredata.DocumentOrderField) page.CursorKey { + switch orderBy { + case coredata.DocumentOrderFieldCreatedAt: + return page.NewCursorKey(d.ID, d.CreatedAt) + case coredata.DocumentOrderFieldTitle: + return page.NewCursorKey(d.ID, d.Title) + case coredata.DocumentOrderFieldDocumentType: + return page.NewCursorKey(d.ID, d.DocumentType) + } + + panic("unsupported order by") +} diff --git a/pkg/server/api/console/v1/types/types.go b/pkg/server/api/console/v1/types/types.go index e65b4096c..220a92441 100644 --- a/pkg/server/api/console/v1/types/types.go +++ b/pkg/server/api/console/v1/types/types.go @@ -1153,6 +1153,14 @@ type ExportFrameworkPayload struct { ExportJobID gid.GID `json:"exportJobId"` } +type ExportSignableDocumentVersionPDFInput struct { + DocumentVersionID gid.GID `json:"documentVersionId"` +} + +type ExportSignableDocumentVersionPDFPayload struct { + Data string `json:"data"` +} + type File struct { ID gid.GID `json:"id"` MimeType string `json:"mimeType"` @@ -1680,6 +1688,14 @@ type Session struct { ExpiresAt time.Time `json:"expiresAt"` } +type SignDocumentInput struct { + DocumentVersionID gid.GID `json:"documentVersionId"` +} + +type SignDocumentPayload struct { + DocumentVersionSignature *DocumentVersionSignature `json:"documentVersionSignature"` +} + type SlackConnection struct { ID gid.GID `json:"id"` Channel *string `json:"channel,omitempty"` @@ -2506,9 +2522,11 @@ type VerifyDomainPayload struct { } type Viewer struct { - ID gid.GID `json:"id"` - User *User `json:"user"` - Organizations *OrganizationConnection `json:"organizations"` + ID gid.GID `json:"id"` + User *User `json:"user"` + Organizations *OrganizationConnection `json:"organizations"` + SignableDocuments *SignableDocumentConnection `json:"signableDocuments"` + SignableDocument *SignableDocument `json:"signableDocument,omitempty"` } type Role string diff --git a/pkg/server/api/console/v1/v1_resolver.go b/pkg/server/api/console/v1/v1_resolver.go index 5989adb67..3fec7e917 100644 --- a/pkg/server/api/console/v1/v1_resolver.go +++ b/pkg/server/api/console/v1/v1_resolver.go @@ -714,7 +714,9 @@ func (r *documentResolver) Versions(ctx context.Context, obj *types.Document, fi cursor := types.NewCursor(first, after, last, before, pageOrderBy) - page, err := prb.Documents.ListVersions(ctx, obj.ID, cursor) + versionFilter := coredata.NewDocumentVersionFilter() + + page, err := prb.Documents.ListVersions(ctx, obj.ID, cursor, versionFilter) if err != nil { panic(fmt.Errorf("cannot list document versions: %w", err)) } @@ -785,7 +787,7 @@ func (r *documentConnectionResolver) TotalCount(ctx context.Context, obj *types. // Document is the resolver for the document field. func (r *documentVersionResolver) Document(ctx context.Context, obj *types.DocumentVersion) (*types.Document, error) { - r.MustBeAuthorized(ctx, obj.ID, authz.ActionDocument) + r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetDocument) prb := r.ProboService(ctx, obj.ID.TenantID()) @@ -862,6 +864,24 @@ func (r *documentVersionResolver) Signatures(ctx context.Context, obj *types.Doc return types.NewDocumentVersionSignatureConnection(page), nil } +// Signed is the resolver for the signed field. +func (r *documentVersionResolver) Signed(ctx context.Context, obj *types.DocumentVersion) (bool, error) { + r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetSigned) + + user := UserFromContext(ctx) + if user == nil { + panic(fmt.Errorf("user not found in context")) + } + + prb := r.ProboService(ctx, obj.ID.TenantID()) + signed, err := prb.Documents.IsVersionSignedByUserEmail(ctx, obj.ID, user.EmailAddress) + if err != nil { + panic(fmt.Errorf("cannot check if document version is signed: %w", err)) + } + + return signed, nil +} + // DocumentVersion is the resolver for the documentVersion field. func (r *documentVersionSignatureResolver) DocumentVersion(ctx context.Context, obj *types.DocumentVersionSignature) (*types.DocumentVersion, error) { r.MustBeAuthorized(ctx, obj.ID, authz.ActionDocumentVersion) @@ -3551,6 +3571,31 @@ func (r *mutationResolver) CancelSignatureRequest(ctx context.Context, input typ }, nil } +// SignDocument is the resolver for the signDocument field. +func (r *mutationResolver) SignDocument(ctx context.Context, input types.SignDocumentInput) (*types.SignDocumentPayload, error) { + r.MustBeAuthorized(ctx, input.DocumentVersionID, authz.ActionSignDocument) + + user := UserFromContext(ctx) + if user == nil { + panic(fmt.Errorf("user not found in context")) + } + + prb := r.ProboService(ctx, input.DocumentVersionID.TenantID()) + + documentVersionSignature, err := prb.Documents.SignDocumentVersionByEmail(ctx, input.DocumentVersionID, user.EmailAddress) + if err != nil { + var errAlreadySigned *coredata.ErrDocumentVersionSignatureAlreadySigned + if errors.As(err, &errAlreadySigned) { + return nil, gqlutils.Conflict(errAlreadySigned) + } + panic(fmt.Errorf("cannot sign document: %w", err)) + } + + return &types.SignDocumentPayload{ + DocumentVersionSignature: types.NewDocumentVersionSignature(documentVersionSignature), + }, nil +} + // ExportDocumentVersionPDF is the resolver for the exportDocumentVersionPDF field. func (r *mutationResolver) ExportDocumentVersionPDF(ctx context.Context, input types.ExportDocumentVersionPDFInput) (*types.ExportDocumentVersionPDFPayload, error) { r.MustBeAuthorized(ctx, input.DocumentVersionID, authz.ActionExportDocumentVersionPDF) @@ -3573,6 +3618,49 @@ func (r *mutationResolver) ExportDocumentVersionPDF(ctx context.Context, input t }, nil } +// ExportSignableVersionDocumentPDF is the resolver for the exportSignableVersionDocumentPDF field. +func (r *mutationResolver) ExportSignableVersionDocumentPDF(ctx context.Context, input types.ExportSignableDocumentVersionPDFInput) (*types.ExportSignableDocumentVersionPDFPayload, error) { + r.MustBeAuthorized(ctx, input.DocumentVersionID, authz.ActionExportSignableVersionDocumentPDF) + + prb := r.ProboService(ctx, input.DocumentVersionID.TenantID()) + + documentVersion, err := prb.Documents.GetVersion(ctx, input.DocumentVersionID) + if err != nil { + panic(fmt.Errorf("cannot get document version: %w", err)) + } + + user := UserFromContext(ctx) + if user == nil { + panic(fmt.Errorf("user not found in context")) + } + + documentFilter := coredata.NewDocumentFilter(nil).WithUserEmail(&user.EmailAddress) + + _, err = prb.Documents.GetWithFilter(ctx, documentVersion.DocumentID, documentFilter) + if err != nil { + var errNotFound *coredata.ErrDocumentNotFound + if errors.As(err, &errNotFound) { + return nil, gqlutils.NotFound(errNotFound) + } + panic(fmt.Errorf("cannot get signable document: %w", err)) + } + + options := probo.ExportPDFOptions{ + WithSignatures: false, + WithWatermark: true, + WatermarkEmail: &user.EmailAddress, + } + + pdf, err := prb.Documents.ExportPDF(ctx, input.DocumentVersionID, options) + if err != nil { + panic(fmt.Errorf("cannot export signable document PDF: %w", err)) + } + + return &types.ExportSignableDocumentVersionPDFPayload{ + Data: fmt.Sprintf("data:application/pdf;base64,%s", base64.StdEncoding.EncodeToString(pdf)), + }, nil +} + // CreateVendorRiskAssessment is the resolver for the createVendorRiskAssessment field. func (r *mutationResolver) CreateVendorRiskAssessment(ctx context.Context, input types.CreateVendorRiskAssessmentInput) (*types.CreateVendorRiskAssessmentPayload, error) { r.MustBeAuthorized(ctx, input.VendorID, authz.ActionCreateVendorRiskAssessment) @@ -5994,6 +6082,59 @@ func (r *sAMLConfigurationResolver) TestLoginURL(ctx context.Context, obj *types return fmt.Sprintf("%s/connect/saml/login/%s", parts[0], obj.ID), nil } +// Signed is the resolver for the signed field. +func (r *signableDocumentResolver) Signed(ctx context.Context, obj *types.SignableDocument) (bool, error) { + r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetSigned) + + user := UserFromContext(ctx) + if user == nil { + panic(fmt.Errorf("user not found in context")) + } + + prb := r.ProboService(ctx, obj.ID.TenantID()) + + signed, err := prb.Documents.IsSigned(ctx, obj.ID, user.EmailAddress) + if err != nil { + panic(fmt.Errorf("cannot check if document is signed: %w", err)) + } + + return signed, nil +} + +// Versions is the resolver for the versions field. +func (r *signableDocumentResolver) Versions(ctx context.Context, obj *types.SignableDocument, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentVersionOrderBy, filter *types.DocumentVersionFilter) (*types.DocumentVersionConnection, error) { + r.MustBeAuthorized(ctx, obj.ID, authz.ActionListSignableDocumentVersion) + + prb := r.ProboService(ctx, obj.ID.TenantID()) + + pageOrderBy := page.OrderBy[coredata.DocumentVersionOrderField]{ + Field: coredata.DocumentVersionOrderFieldCreatedAt, + Direction: page.OrderDirectionDesc, + } + if orderBy != nil { + pageOrderBy = page.OrderBy[coredata.DocumentVersionOrderField]{ + Field: orderBy.Field, + Direction: orderBy.Direction, + } + } + + cursor := types.NewCursor(first, after, last, before, pageOrderBy) + + user := UserFromContext(ctx) + if user == nil { + panic(fmt.Errorf("user not found in context")) + } + + versionFilter := coredata.NewDocumentVersionFilter().WithUserEmail(&user.EmailAddress) + + page, err := prb.Documents.ListVersions(ctx, obj.ID, cursor, versionFilter) + if err != nil { + panic(fmt.Errorf("cannot list signable document versions: %w", err)) + } + + return types.NewDocumentVersionConnection(page), nil +} + // Organization is the resolver for the organization field. func (r *snapshotResolver) Organization(ctx context.Context, obj *types.Snapshot) (*types.Organization, error) { r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetOrganization) @@ -6349,7 +6490,7 @@ func (r *trustCenterAccessResolver) AvailableDocumentAccesses(ctx context.Contex // Document is the resolver for the document field. func (r *trustCenterDocumentAccessResolver) Document(ctx context.Context, obj *types.TrustCenterDocumentAccess) (*types.Document, error) { - r.MustBeAuthorized(ctx, obj.TrustCenterAccessID, authz.ActionDocument) + r.MustBeAuthorized(ctx, obj.ID, authz.ActionGet) if obj.DocumentID == nil { return nil, nil @@ -6979,6 +7120,85 @@ func (r *viewerResolver) Organizations(ctx context.Context, obj *types.Viewer, f return types.NewOrganizationConnection(page), nil } +// SignableDocuments is the resolver for the signableDocuments field. +func (r *viewerResolver) SignableDocuments(ctx context.Context, obj *types.Viewer, organizationID gid.GID, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentOrderBy) (*types.SignableDocumentConnection, error) { + r.MustBeAuthorized(ctx, organizationID, authz.ActionListSignableDocuments) + + prb := r.ProboService(ctx, organizationID.TenantID()) + + pageOrderBy := page.OrderBy[coredata.DocumentOrderField]{ + Field: coredata.DocumentOrderFieldCreatedAt, + Direction: page.OrderDirectionDesc, + } + if orderBy != nil { + pageOrderBy = page.OrderBy[coredata.DocumentOrderField]{ + Field: orderBy.Field, + Direction: orderBy.Direction, + } + } + + cursor := types.NewCursor(first, after, last, before, pageOrderBy) + + user := UserFromContext(ctx) + if user == nil { + panic(fmt.Errorf("user not found in context")) + } + + documentFilter := coredata.NewDocumentFilter(nil).WithUserEmail(&user.EmailAddress) + + documentsPage, err := prb.Documents.ListByOrganizationID(ctx, organizationID, cursor, documentFilter) + if err != nil { + panic(fmt.Errorf("cannot list organization signable documents: %w", err)) + } + + signableDocuments := make([]*types.SignableDocument, len(documentsPage.Data)) + for i, doc := range documentsPage.Data { + signableDocuments[i] = &types.SignableDocument{ + ID: doc.ID, + Title: doc.Title, + DocumentType: doc.DocumentType, + Classification: doc.Classification, + CreatedAt: doc.CreatedAt, + UpdatedAt: doc.UpdatedAt, + } + } + + page := page.NewPage(signableDocuments, documentsPage.Cursor) + + return types.NewSignableDocumentConnection(page), nil +} + +// SignableDocument is the resolver for the signableDocument field. +func (r *viewerResolver) SignableDocument(ctx context.Context, obj *types.Viewer, id gid.GID) (*types.SignableDocument, error) { + r.MustBeAuthorized(ctx, id, authz.ActionGetSignableDocument) + + prb := r.ProboService(ctx, id.TenantID()) + + user := UserFromContext(ctx) + if user == nil { + panic(fmt.Errorf("user not found in context")) + } + + documentFilter := coredata.NewDocumentFilter(nil).WithUserEmail(&user.EmailAddress) + document, err := prb.Documents.GetWithFilter(ctx, id, documentFilter) + if err != nil { + var errNotFound *coredata.ErrDocumentNotFound + if errors.As(err, &errNotFound) { + return nil, gqlutils.NotFound(errNotFound) + } + panic(fmt.Errorf("cannot get signable document: %w", err)) + } + + return &types.SignableDocument{ + ID: document.ID, + Title: document.Title, + DocumentType: document.DocumentType, + Classification: document.Classification, + CreatedAt: document.CreatedAt, + UpdatedAt: document.UpdatedAt, + }, nil +} + // Asset returns schema.AssetResolver implementation. func (r *Resolver) Asset() schema.AssetResolver { return &assetResolver{r} } @@ -7144,6 +7364,11 @@ func (r *Resolver) SAMLConfiguration() schema.SAMLConfigurationResolver { return &sAMLConfigurationResolver{r} } +// SignableDocument returns schema.SignableDocumentResolver implementation. +func (r *Resolver) SignableDocument() schema.SignableDocumentResolver { + return &signableDocumentResolver{r} +} + // Snapshot returns schema.SnapshotResolver implementation. func (r *Resolver) Snapshot() schema.SnapshotResolver { return &snapshotResolver{r} } @@ -7277,6 +7502,7 @@ type reportResolver struct{ *Resolver } type riskResolver struct{ *Resolver } type riskConnectionResolver struct{ *Resolver } type sAMLConfigurationResolver struct{ *Resolver } +type signableDocumentResolver struct{ *Resolver } type snapshotResolver struct{ *Resolver } type snapshotConnectionResolver struct{ *Resolver } type taskResolver struct{ *Resolver } diff --git a/pkg/server/api/mcp/v1/schema.resolvers.go b/pkg/server/api/mcp/v1/schema.resolvers.go index f06694bd4..f8beb85a1 100644 --- a/pkg/server/api/mcp/v1/schema.resolvers.go +++ b/pkg/server/api/mcp/v1/schema.resolvers.go @@ -1595,7 +1595,7 @@ func (r *Resolver) ListDocumentVersionsTool(ctx context.Context, req *mcp.CallTo cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy) svc := r.ProboService(ctx, input.DocumentID) - page, err := svc.Documents.ListVersions(ctx, input.DocumentID, cursor) + page, err := svc.Documents.ListVersions(ctx, input.DocumentID, cursor, coredata.NewDocumentVersionFilter()) if err != nil { panic(fmt.Errorf("cannot list document versions: %w", err)) } diff --git a/pkg/trust/document_service.go b/pkg/trust/document_service.go index 218d51548..d93099038 100644 --- a/pkg/trust/document_service.go +++ b/pkg/trust/document_service.go @@ -46,7 +46,8 @@ func (s *DocumentService) ListVersions( err := s.svc.pg.WithConn( ctx, func(conn pg.Conn) error { - return documentVersions.LoadByDocumentID(ctx, conn, s.svc.scope, documentID, cursor) + filter := coredata.NewDocumentVersionFilter() + return documentVersions.LoadByDocumentID(ctx, conn, s.svc.scope, documentID, cursor, filter) }, )