diff --git a/apps/console/src/components/trustCenter/TrustCenterAuditsCard.tsx b/apps/console/src/components/trustCenter/TrustCenterAuditsCard.tsx index c60c49ae4..23ac375fc 100644 --- a/apps/console/src/components/trustCenter/TrustCenterAuditsCard.tsx +++ b/apps/console/src/components/trustCenter/TrustCenterAuditsCard.tsx @@ -1,6 +1,5 @@ import { graphql } from "relay-runtime"; import { - Card, Button, Tr, Td, @@ -18,7 +17,6 @@ import { useFragment } from "react-relay"; import { useMemo, useState, useCallback, useEffect } from "react"; import { sprintf, getAuditStateVariant, getAuditStateLabel, formatDate, getTrustCenterVisibilityOptions } from "@probo/helpers"; import { useOrganizationId } from "/hooks/useOrganizationId"; -import clsx from "clsx"; import type { TrustCenterAuditsCardFragment$key } from "./__generated__/TrustCenterAuditsCardFragment.graphql"; const trustCenterAuditFragment = graphql` @@ -50,17 +48,15 @@ type Props = { params: Params; disabled?: boolean; onChangeVisibility: Mutation; - variant?: "card" | "table"; }; export function TrustCenterAuditsCard(props: Props) { const { __ } = useTranslate(); - const [limit, setLimit] = useState(4); + const [limit, setLimit] = useState(100); const audits = useMemo(() => { return limit ? props.audits.slice(0, limit) : props.audits; }, [props.audits, limit]); const showMoreButton = limit !== null && props.audits.length > limit; - const variant = props.variant ?? "table"; const onChangeVisibility = (auditId: string, trustCenterVisibility: "NONE" | "PRIVATE" | "PUBLIC") => { props.onChangeVisibility({ @@ -74,11 +70,9 @@ export function TrustCenterAuditsCard(props: Props) { }); }; - const Wrapper = variant === "card" ? Card : "div"; - return ( - - +
+
@@ -116,7 +110,7 @@ export function TrustCenterAuditsCard(props: Props) { {sprintf(__("Show %s more"), props.audits.length - limit)} )} - + ); } diff --git a/apps/console/src/components/trustCenter/TrustCenterDocumentsCard.tsx b/apps/console/src/components/trustCenter/TrustCenterDocumentsCard.tsx index 7a21115a4..0fa01b883 100644 --- a/apps/console/src/components/trustCenter/TrustCenterDocumentsCard.tsx +++ b/apps/console/src/components/trustCenter/TrustCenterDocumentsCard.tsx @@ -1,6 +1,5 @@ import { graphql } from "relay-runtime"; import { - Card, Button, Tr, Td, @@ -21,7 +20,6 @@ import { useFragment } from "react-relay"; import { useMemo, useState, useCallback, useEffect } from "react"; import { sprintf, getTrustCenterVisibilityOptions } from "@probo/helpers"; import { useOrganizationId } from "/hooks/useOrganizationId"; -import clsx from "clsx"; const trustCenterDocumentFragment = graphql` fragment TrustCenterDocumentsCardFragment on Document { @@ -55,17 +53,15 @@ type Props = { params: Params; disabled?: boolean; onChangeVisibility: Mutation; - variant?: "card" | "table"; }; export function TrustCenterDocumentsCard(props: Props) { const { __ } = useTranslate(); - const [limit, setLimit] = useState(4); + const [limit, setLimit] = useState(100); const documents = useMemo(() => { return limit ? props.documents.slice(0, limit) : props.documents; }, [props.documents, limit]); const showMoreButton = limit !== null && props.documents.length > limit; - const variant = props.variant ?? "table"; const onChangeVisibility = (documentId: string, trustCenterVisibility: "NONE" | "PRIVATE" | "PUBLIC") => { props.onChangeVisibility({ @@ -79,11 +75,9 @@ export function TrustCenterDocumentsCard(props: Props) { }); }; - const Wrapper = variant === "card" ? Card : "div"; - return ( - -
{__("Framework")}
+
+
@@ -121,7 +115,7 @@ export function TrustCenterDocumentsCard(props: Props) { {sprintf(__("Show %s more"), props.documents.length - limit)} )} - + ); } diff --git a/apps/console/src/components/trustCenter/TrustCenterFilesCard.tsx b/apps/console/src/components/trustCenter/TrustCenterFilesCard.tsx index 2b8c27f56..532671aa1 100644 --- a/apps/console/src/components/trustCenter/TrustCenterFilesCard.tsx +++ b/apps/console/src/components/trustCenter/TrustCenterFilesCard.tsx @@ -1,6 +1,5 @@ import { graphql } from "relay-runtime"; import { - Card, Button, Tr, Td, @@ -22,7 +21,6 @@ import { useFragment } from "react-relay"; import { useMemo, useState, useCallback, useEffect } from "react"; import { sprintf, getTrustCenterVisibilityOptions } from "@probo/helpers"; import { formatDate } from "@probo/helpers"; -import clsx from "clsx"; const trustCenterFileFragment = graphql` fragment TrustCenterFilesCardFragment on TrustCenterFile { @@ -52,17 +50,15 @@ type Props = { onChangeVisibility: Mutation; onEdit: (file: { id: string; name: string; category: string }) => void; onDelete: (id: string) => void; - variant?: "card" | "table"; }; export function TrustCenterFilesCard(props: Props) { const { __ } = useTranslate(); - const [limit, setLimit] = useState(4); + const [limit, setLimit] = useState(100); const files = useMemo(() => { return limit ? props.files.slice(0, limit) : props.files; }, [props.files, limit]); const showMoreButton = limit !== null && props.files.length > limit; - const variant = props.variant ?? "table"; const onChangeVisibility = (fileId: string, trustCenterVisibility: "NONE" | "PRIVATE" | "PUBLIC") => { props.onChangeVisibility({ @@ -76,11 +72,9 @@ export function TrustCenterFilesCard(props: Props) { }); }; - const Wrapper = variant === "card" ? Card : "div"; - return ( - -
{__("Name")}
+
+
@@ -120,7 +114,7 @@ export function TrustCenterFilesCard(props: Props) { {sprintf(__("Show %s more"), props.files.length - limit)} )} - + ); } @@ -215,7 +209,7 @@ function FileRow(props: { title={__("Edit")} /> - - {references.length === 0 ? ( -
-
- -
-

- {__("No references yet")} -

-

- {__("Add customer testimonials and partner references to build trust")} -

-
- ) : ( -
- {references.map((reference: Reference) => ( - handleEdit(reference)} - connectionId={referencesConnectionId} - onVisitWebsite={() => handleVisitWebsite(reference.websiteUrl)} - /> - ))} -
- )} -
+
{__("Name")}
+ + + + + + + + + {references.length === 0 && ( + + + + )} + {references.map((reference: Reference) => ( + handleEdit(reference)} + connectionId={referencesConnectionId} + onVisitWebsite={() => handleVisitWebsite(reference.websiteUrl)} + /> + ))} + +
{__("Name")}{__("Description")}
+ {__("No references available")} +
@@ -113,52 +118,47 @@ type ReferenceRowProps = { }; function ReferenceRow({ reference, onEdit, connectionId, onVisitWebsite }: ReferenceRowProps) { - return ( -
-
- - -
-
- -
- -

- {reference.description} -

-
-
- -
-
+ {reference.name} +
+ + + + {reference.description} + + + +
+
+ + ); } diff --git a/apps/console/src/components/trustCenter/TrustCenterVendorsCard.tsx b/apps/console/src/components/trustCenter/TrustCenterVendorsCard.tsx index 370fa9960..ef625aac3 100644 --- a/apps/console/src/components/trustCenter/TrustCenterVendorsCard.tsx +++ b/apps/console/src/components/trustCenter/TrustCenterVendorsCard.tsx @@ -1,6 +1,5 @@ import { graphql } from "relay-runtime"; import { - Card, Button, Tr, Td, @@ -18,7 +17,6 @@ import { useFragment } from "react-relay"; import { useMemo, useState } from "react"; import { sprintf } from "@probo/helpers"; import { useOrganizationId } from "/hooks/useOrganizationId"; -import clsx from "clsx"; import type { TrustCenterVendorsCardFragment$key } from "./__generated__/TrustCenterVendorsCardFragment.graphql"; const trustCenterVendorFragment = graphql` @@ -46,17 +44,15 @@ type Props = { params: Params; disabled?: boolean; onToggleVisibility: Mutation; - variant?: "card" | "table"; }; export function TrustCenterVendorsCard(props: Props) { const { __ } = useTranslate(); - const [limit, setLimit] = useState(4); + const [limit, setLimit] = useState(100); const vendors = useMemo(() => { return limit ? props.vendors.slice(0, limit) : props.vendors; }, [props.vendors, limit]); const showMoreButton = limit !== null && props.vendors.length > limit; - const variant = props.variant ?? "table"; const onToggleVisibility = (vendorId: string, showOnTrustCenter: boolean) => { props.onToggleVisibility({ @@ -70,11 +66,9 @@ export function TrustCenterVendorsCard(props: Props) { }); }; - const Wrapper = variant === "card" ? Card : "div"; - return ( - - +
+
@@ -111,7 +105,7 @@ export function TrustCenterVendorsCard(props: Props) { {sprintf(__("Show %s more"), props.vendors.length - limit)} )} - + ); } diff --git a/apps/console/src/hooks/graph/TrustCenterAccessGraph.ts b/apps/console/src/hooks/graph/TrustCenterAccessGraph.ts index 5d1e26d20..757367adc 100644 --- a/apps/console/src/hooks/graph/TrustCenterAccessGraph.ts +++ b/apps/console/src/hooks/graph/TrustCenterAccessGraph.ts @@ -25,36 +25,9 @@ export const trustCenterAccessesPaginationFragment = graphql` active hasAcceptedNonDisclosureAgreement createdAt - documentAccesses(first: 100, orderBy: { field: CREATED_AT, direction: DESC }) { - edges { - node { - id - active - createdAt - updatedAt - document { - id - title - documentType - } - report { - id - filename - audit { - id - framework { - name - } - } - } - trustCenterFile { - id - name - category - } - } - } - } + lastTokenExpiresAt + pendingRequestCount + activeCount } } } @@ -87,36 +60,9 @@ export const createTrustCenterAccessMutation = graphql` active hasAcceptedNonDisclosureAgreement createdAt - documentAccesses(first: 100, orderBy: { field: CREATED_AT, direction: DESC }) { - edges { - node { - id - active - createdAt - updatedAt - document { - id - title - documentType - } - report { - id - filename - audit { - id - framework { - name - } - } - } - trustCenterFile { - id - name - category - } - } - } - } + lastTokenExpiresAt + pendingRequestCount + activeCount } } } @@ -136,13 +82,35 @@ export const updateTrustCenterAccessMutation = graphql` hasAcceptedNonDisclosureAgreement createdAt updatedAt - documentAccesses(first: 100, orderBy: { field: CREATED_AT, direction: DESC }) { + lastTokenExpiresAt + pendingRequestCount + activeCount + } + } + } +`; + +export const deleteTrustCenterAccessMutation = graphql` + mutation TrustCenterAccessGraphDeleteMutation( + $input: DeleteTrustCenterAccessInput! + $connections: [ID!]! + ) { + deleteTrustCenterAccess(input: $input) { + deletedTrustCenterAccessId @deleteEdge(connections: $connections) + } + } +`; + +export const loadTrustCenterAccessDocumentAccessesQuery = graphql` + query TrustCenterAccessGraphLoadDocumentAccessesQuery($accessId: ID!) { + node(id: $accessId) { + ... on TrustCenterAccess { + id + availableDocumentAccesses(first: 100, orderBy: { field: CREATED_AT, direction: DESC }) { edges { node { - id active - createdAt - updatedAt + requested document { id title @@ -171,17 +139,6 @@ export const updateTrustCenterAccessMutation = graphql` } `; -export const deleteTrustCenterAccessMutation = graphql` - mutation TrustCenterAccessGraphDeleteMutation( - $input: DeleteTrustCenterAccessInput! - $connections: [ID!]! - ) { - deleteTrustCenterAccess(input: $input) { - deletedTrustCenterAccessId @deleteEdge(connections: $connections) - } - } -`; - interface PaginatedData { data: { node: any } | null; hasNext: boolean; @@ -197,7 +154,7 @@ export function useTrustCenterAccesses(trustCenterId: string): PaginatedData { count: 10, cursor: null }, - { fetchPolicy: 'network-only' } + { fetchPolicy: 'store-and-network' } ); if (!trustCenterId) { diff --git a/apps/console/src/hooks/graph/__generated__/TrustCenterAccessGraphCreateMutation.graphql.ts b/apps/console/src/hooks/graph/__generated__/TrustCenterAccessGraphCreateMutation.graphql.ts index cccd47c21..14f6c6f94 100644 --- a/apps/console/src/hooks/graph/__generated__/TrustCenterAccessGraphCreateMutation.graphql.ts +++ b/apps/console/src/hooks/graph/__generated__/TrustCenterAccessGraphCreateMutation.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<<271260153dc611541b234266fbdd0c74>> * @lightSyntaxTransform * @nogrep */ @@ -9,7 +9,6 @@ // @ts-nocheck import { ConcreteRequest } from 'relay-runtime'; -export type DocumentType = "ISMS" | "OTHER" | "POLICY" | "PROCEDURE"; export type CreateTrustCenterAccessInput = { active: boolean; email: string; @@ -26,41 +25,14 @@ export type TrustCenterAccessGraphCreateMutation$data = { readonly cursor: any; readonly node: { readonly active: boolean; + readonly activeCount: number; readonly createdAt: any; - readonly documentAccesses: { - readonly edges: ReadonlyArray<{ - readonly node: { - readonly active: boolean; - readonly createdAt: any; - readonly document: { - readonly documentType: DocumentType; - readonly id: string; - readonly title: string; - } | null | undefined; - readonly id: string; - readonly report: { - readonly audit: { - readonly framework: { - readonly name: string; - }; - readonly id: string; - } | null | undefined; - readonly filename: string; - readonly id: string; - } | null | undefined; - readonly trustCenterFile: { - readonly category: string; - readonly id: string; - readonly name: string; - } | null | undefined; - readonly updatedAt: any; - }; - }>; - }; readonly email: string; readonly hasAcceptedNonDisclosureAgreement: boolean; readonly id: string; + readonly lastTokenExpiresAt: any | null | undefined; readonly name: string; + readonly pendingRequestCount: number; }; }; }; @@ -91,122 +63,90 @@ v2 = [ v3 = { "alias": null, "args": null, - "kind": "ScalarField", - "name": "cursor", - "storageKey": null -}, -v4 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "id", - "storageKey": null -}, -v5 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "email", - "storageKey": null -}, -v6 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "name", - "storageKey": null -}, -v7 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "active", - "storageKey": null -}, -v8 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "hasAcceptedNonDisclosureAgreement", - "storageKey": null -}, -v9 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "createdAt", - "storageKey": null -}, -v10 = [ - { - "kind": "Literal", - "name": "first", - "value": 100 - }, - { - "kind": "Literal", - "name": "orderBy", - "value": { - "direction": "DESC", - "field": "CREATED_AT" - } - } -], -v11 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "updatedAt", - "storageKey": null -}, -v12 = { - "alias": null, - "args": null, - "concreteType": "Document", + "concreteType": "TrustCenterAccessEdge", "kind": "LinkedField", - "name": "document", + "name": "trustCenterAccessEdge", "plural": false, "selections": [ - (v4/*: any*/), { "alias": null, "args": null, "kind": "ScalarField", - "name": "title", + "name": "cursor", "storageKey": null }, { "alias": null, "args": null, - "kind": "ScalarField", - "name": "documentType", - "storageKey": null - } - ], - "storageKey": null -}, -v13 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "filename", - "storageKey": null -}, -v14 = { - "alias": null, - "args": null, - "concreteType": "TrustCenterFile", - "kind": "LinkedField", - "name": "trustCenterFile", - "plural": false, - "selections": [ - (v4/*: any*/), - (v6/*: any*/), - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "category", + "concreteType": "TrustCenterAccess", + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "id", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "email", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "name", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "active", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "hasAcceptedNonDisclosureAgreement", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "createdAt", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "lastTokenExpiresAt", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "pendingRequestCount", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "activeCount", + "storageKey": null + } + ], "storageKey": null } ], @@ -230,111 +170,7 @@ return { "name": "createTrustCenterAccess", "plural": false, "selections": [ - { - "alias": null, - "args": null, - "concreteType": "TrustCenterAccessEdge", - "kind": "LinkedField", - "name": "trustCenterAccessEdge", - "plural": false, - "selections": [ - (v3/*: any*/), - { - "alias": null, - "args": null, - "concreteType": "TrustCenterAccess", - "kind": "LinkedField", - "name": "node", - "plural": false, - "selections": [ - (v4/*: any*/), - (v5/*: any*/), - (v6/*: any*/), - (v7/*: any*/), - (v8/*: any*/), - (v9/*: any*/), - { - "alias": null, - "args": (v10/*: any*/), - "concreteType": "TrustCenterDocumentAccessConnection", - "kind": "LinkedField", - "name": "documentAccesses", - "plural": false, - "selections": [ - { - "alias": null, - "args": null, - "concreteType": "TrustCenterDocumentAccessEdge", - "kind": "LinkedField", - "name": "edges", - "plural": true, - "selections": [ - { - "alias": null, - "args": null, - "concreteType": "TrustCenterDocumentAccess", - "kind": "LinkedField", - "name": "node", - "plural": false, - "selections": [ - (v4/*: any*/), - (v7/*: any*/), - (v9/*: any*/), - (v11/*: any*/), - (v12/*: any*/), - { - "alias": null, - "args": null, - "concreteType": "Report", - "kind": "LinkedField", - "name": "report", - "plural": false, - "selections": [ - (v4/*: any*/), - (v13/*: any*/), - { - "alias": null, - "args": null, - "concreteType": "Audit", - "kind": "LinkedField", - "name": "audit", - "plural": false, - "selections": [ - (v4/*: any*/), - { - "alias": null, - "args": null, - "concreteType": "Framework", - "kind": "LinkedField", - "name": "framework", - "plural": false, - "selections": [ - (v6/*: any*/) - ], - "storageKey": null - } - ], - "storageKey": null - } - ], - "storageKey": null - }, - (v14/*: any*/) - ], - "storageKey": null - } - ], - "storageKey": null - } - ], - "storageKey": "documentAccesses(first:100,orderBy:{\"direction\":\"DESC\",\"field\":\"CREATED_AT\"})" - } - ], - "storageKey": null - } - ], - "storageKey": null - } + (v3/*: any*/) ], "storageKey": null } @@ -359,112 +195,7 @@ return { "name": "createTrustCenterAccess", "plural": false, "selections": [ - { - "alias": null, - "args": null, - "concreteType": "TrustCenterAccessEdge", - "kind": "LinkedField", - "name": "trustCenterAccessEdge", - "plural": false, - "selections": [ - (v3/*: any*/), - { - "alias": null, - "args": null, - "concreteType": "TrustCenterAccess", - "kind": "LinkedField", - "name": "node", - "plural": false, - "selections": [ - (v4/*: any*/), - (v5/*: any*/), - (v6/*: any*/), - (v7/*: any*/), - (v8/*: any*/), - (v9/*: any*/), - { - "alias": null, - "args": (v10/*: any*/), - "concreteType": "TrustCenterDocumentAccessConnection", - "kind": "LinkedField", - "name": "documentAccesses", - "plural": false, - "selections": [ - { - "alias": null, - "args": null, - "concreteType": "TrustCenterDocumentAccessEdge", - "kind": "LinkedField", - "name": "edges", - "plural": true, - "selections": [ - { - "alias": null, - "args": null, - "concreteType": "TrustCenterDocumentAccess", - "kind": "LinkedField", - "name": "node", - "plural": false, - "selections": [ - (v4/*: any*/), - (v7/*: any*/), - (v9/*: any*/), - (v11/*: any*/), - (v12/*: any*/), - { - "alias": null, - "args": null, - "concreteType": "Report", - "kind": "LinkedField", - "name": "report", - "plural": false, - "selections": [ - (v4/*: any*/), - (v13/*: any*/), - { - "alias": null, - "args": null, - "concreteType": "Audit", - "kind": "LinkedField", - "name": "audit", - "plural": false, - "selections": [ - (v4/*: any*/), - { - "alias": null, - "args": null, - "concreteType": "Framework", - "kind": "LinkedField", - "name": "framework", - "plural": false, - "selections": [ - (v6/*: any*/), - (v4/*: any*/) - ], - "storageKey": null - } - ], - "storageKey": null - } - ], - "storageKey": null - }, - (v14/*: any*/) - ], - "storageKey": null - } - ], - "storageKey": null - } - ], - "storageKey": "documentAccesses(first:100,orderBy:{\"direction\":\"DESC\",\"field\":\"CREATED_AT\"})" - } - ], - "storageKey": null - } - ], - "storageKey": null - }, + (v3/*: any*/), { "alias": null, "args": null, @@ -487,16 +218,16 @@ return { ] }, "params": { - "cacheID": "4422a02632b77f81f3b5048b5acbac98", + "cacheID": "501c3c38f8d44e41a178514443803ce2", "id": null, "metadata": {}, "name": "TrustCenterAccessGraphCreateMutation", "operationKind": "mutation", - "text": "mutation TrustCenterAccessGraphCreateMutation(\n $input: CreateTrustCenterAccessInput!\n) {\n createTrustCenterAccess(input: $input) {\n trustCenterAccessEdge {\n cursor\n node {\n id\n email\n name\n active\n hasAcceptedNonDisclosureAgreement\n createdAt\n documentAccesses(first: 100, orderBy: {field: CREATED_AT, direction: DESC}) {\n edges {\n node {\n id\n active\n createdAt\n updatedAt\n document {\n id\n title\n documentType\n }\n report {\n id\n filename\n audit {\n id\n framework {\n name\n id\n }\n }\n }\n trustCenterFile {\n id\n name\n category\n }\n }\n }\n }\n }\n }\n }\n}\n" + "text": "mutation TrustCenterAccessGraphCreateMutation(\n $input: CreateTrustCenterAccessInput!\n) {\n createTrustCenterAccess(input: $input) {\n trustCenterAccessEdge {\n cursor\n node {\n id\n email\n name\n active\n hasAcceptedNonDisclosureAgreement\n createdAt\n lastTokenExpiresAt\n pendingRequestCount\n activeCount\n }\n }\n }\n}\n" } }; })(); -(node as any).hash = "c09c8a22a45226949a08f2262ddd0b1c"; +(node as any).hash = "bfe1841f269ba04a77e9b3ecf73665d2"; export default node; diff --git a/apps/console/src/hooks/graph/__generated__/TrustCenterAccessGraphLoadDocumentAccessesQuery.graphql.ts b/apps/console/src/hooks/graph/__generated__/TrustCenterAccessGraphLoadDocumentAccessesQuery.graphql.ts new file mode 100644 index 000000000..b44e82334 --- /dev/null +++ b/apps/console/src/hooks/graph/__generated__/TrustCenterAccessGraphLoadDocumentAccessesQuery.graphql.ts @@ -0,0 +1,391 @@ +/** + * @generated SignedSource<> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck + +import { ConcreteRequest } from 'relay-runtime'; +export type DocumentType = "ISMS" | "OTHER" | "POLICY" | "PROCEDURE"; +export type TrustCenterAccessGraphLoadDocumentAccessesQuery$variables = { + accessId: string; +}; +export type TrustCenterAccessGraphLoadDocumentAccessesQuery$data = { + readonly node: { + readonly availableDocumentAccesses?: { + readonly edges: ReadonlyArray<{ + readonly node: { + readonly active: boolean; + readonly document: { + readonly documentType: DocumentType; + readonly id: string; + readonly title: string; + } | null | undefined; + readonly report: { + readonly audit: { + readonly framework: { + readonly name: string; + }; + readonly id: string; + } | null | undefined; + readonly filename: string; + readonly id: string; + } | null | undefined; + readonly requested: boolean; + readonly trustCenterFile: { + readonly category: string; + readonly id: string; + readonly name: string; + } | null | undefined; + }; + }>; + }; + readonly id?: string; + }; +}; +export type TrustCenterAccessGraphLoadDocumentAccessesQuery = { + response: TrustCenterAccessGraphLoadDocumentAccessesQuery$data; + variables: TrustCenterAccessGraphLoadDocumentAccessesQuery$variables; +}; + +const node: ConcreteRequest = (function(){ +var v0 = [ + { + "defaultValue": null, + "kind": "LocalArgument", + "name": "accessId" + } +], +v1 = [ + { + "kind": "Variable", + "name": "id", + "variableName": "accessId" + } +], +v2 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "id", + "storageKey": null +}, +v3 = [ + { + "kind": "Literal", + "name": "first", + "value": 100 + }, + { + "kind": "Literal", + "name": "orderBy", + "value": { + "direction": "DESC", + "field": "CREATED_AT" + } + } +], +v4 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "active", + "storageKey": null +}, +v5 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "requested", + "storageKey": null +}, +v6 = { + "alias": null, + "args": null, + "concreteType": "Document", + "kind": "LinkedField", + "name": "document", + "plural": false, + "selections": [ + (v2/*: any*/), + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "title", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "documentType", + "storageKey": null + } + ], + "storageKey": null +}, +v7 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "filename", + "storageKey": null +}, +v8 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "name", + "storageKey": null +}, +v9 = { + "alias": null, + "args": null, + "concreteType": "TrustCenterFile", + "kind": "LinkedField", + "name": "trustCenterFile", + "plural": false, + "selections": [ + (v2/*: any*/), + (v8/*: any*/), + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "category", + "storageKey": null + } + ], + "storageKey": null +}; +return { + "fragment": { + "argumentDefinitions": (v0/*: any*/), + "kind": "Fragment", + "metadata": null, + "name": "TrustCenterAccessGraphLoadDocumentAccessesQuery", + "selections": [ + { + "alias": null, + "args": (v1/*: any*/), + "concreteType": null, + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + { + "kind": "InlineFragment", + "selections": [ + (v2/*: any*/), + { + "alias": null, + "args": (v3/*: any*/), + "concreteType": "TrustCenterDocumentAccessConnection", + "kind": "LinkedField", + "name": "availableDocumentAccesses", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "TrustCenterDocumentAccessEdge", + "kind": "LinkedField", + "name": "edges", + "plural": true, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "TrustCenterDocumentAccess", + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + (v4/*: any*/), + (v5/*: any*/), + (v6/*: any*/), + { + "alias": null, + "args": null, + "concreteType": "Report", + "kind": "LinkedField", + "name": "report", + "plural": false, + "selections": [ + (v2/*: any*/), + (v7/*: any*/), + { + "alias": null, + "args": null, + "concreteType": "Audit", + "kind": "LinkedField", + "name": "audit", + "plural": false, + "selections": [ + (v2/*: any*/), + { + "alias": null, + "args": null, + "concreteType": "Framework", + "kind": "LinkedField", + "name": "framework", + "plural": false, + "selections": [ + (v8/*: any*/) + ], + "storageKey": null + } + ], + "storageKey": null + } + ], + "storageKey": null + }, + (v9/*: any*/) + ], + "storageKey": null + } + ], + "storageKey": null + } + ], + "storageKey": "availableDocumentAccesses(first:100,orderBy:{\"direction\":\"DESC\",\"field\":\"CREATED_AT\"})" + } + ], + "type": "TrustCenterAccess", + "abstractKey": null + } + ], + "storageKey": null + } + ], + "type": "Query", + "abstractKey": null + }, + "kind": "Request", + "operation": { + "argumentDefinitions": (v0/*: any*/), + "kind": "Operation", + "name": "TrustCenterAccessGraphLoadDocumentAccessesQuery", + "selections": [ + { + "alias": null, + "args": (v1/*: any*/), + "concreteType": null, + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "__typename", + "storageKey": null + }, + (v2/*: any*/), + { + "kind": "InlineFragment", + "selections": [ + { + "alias": null, + "args": (v3/*: any*/), + "concreteType": "TrustCenterDocumentAccessConnection", + "kind": "LinkedField", + "name": "availableDocumentAccesses", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "TrustCenterDocumentAccessEdge", + "kind": "LinkedField", + "name": "edges", + "plural": true, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "TrustCenterDocumentAccess", + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + (v4/*: any*/), + (v5/*: any*/), + (v6/*: any*/), + { + "alias": null, + "args": null, + "concreteType": "Report", + "kind": "LinkedField", + "name": "report", + "plural": false, + "selections": [ + (v2/*: any*/), + (v7/*: any*/), + { + "alias": null, + "args": null, + "concreteType": "Audit", + "kind": "LinkedField", + "name": "audit", + "plural": false, + "selections": [ + (v2/*: any*/), + { + "alias": null, + "args": null, + "concreteType": "Framework", + "kind": "LinkedField", + "name": "framework", + "plural": false, + "selections": [ + (v8/*: any*/), + (v2/*: any*/) + ], + "storageKey": null + } + ], + "storageKey": null + } + ], + "storageKey": null + }, + (v9/*: any*/) + ], + "storageKey": null + } + ], + "storageKey": null + } + ], + "storageKey": "availableDocumentAccesses(first:100,orderBy:{\"direction\":\"DESC\",\"field\":\"CREATED_AT\"})" + } + ], + "type": "TrustCenterAccess", + "abstractKey": null + } + ], + "storageKey": null + } + ] + }, + "params": { + "cacheID": "50de5f19f1c13ee4d4a0b125231b989f", + "id": null, + "metadata": {}, + "name": "TrustCenterAccessGraphLoadDocumentAccessesQuery", + "operationKind": "query", + "text": "query TrustCenterAccessGraphLoadDocumentAccessesQuery(\n $accessId: ID!\n) {\n node(id: $accessId) {\n __typename\n ... on TrustCenterAccess {\n id\n availableDocumentAccesses(first: 100, orderBy: {field: CREATED_AT, direction: DESC}) {\n edges {\n node {\n active\n requested\n document {\n id\n title\n documentType\n }\n report {\n id\n filename\n audit {\n id\n framework {\n name\n id\n }\n }\n }\n trustCenterFile {\n id\n name\n category\n }\n }\n }\n }\n }\n id\n }\n}\n" + } +}; +})(); + +(node as any).hash = "64c69558e335d4cecb14192d8c5b66b8"; + +export default node; diff --git a/apps/console/src/hooks/graph/__generated__/TrustCenterAccessGraphPaginationQuery.graphql.ts b/apps/console/src/hooks/graph/__generated__/TrustCenterAccessGraphPaginationQuery.graphql.ts index c90e4f7b6..df0716ac4 100644 --- a/apps/console/src/hooks/graph/__generated__/TrustCenterAccessGraphPaginationQuery.graphql.ts +++ b/apps/console/src/hooks/graph/__generated__/TrustCenterAccessGraphPaginationQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<8c2482b7d32c42396e4645bd309e7cc2>> + * @generated SignedSource<> * @lightSyntaxTransform * @nogrep */ @@ -64,15 +64,7 @@ v3 = { "name": "id", "storageKey": null }, -v4 = { - "kind": "Literal", - "name": "orderBy", - "value": { - "direction": "DESC", - "field": "CREATED_AT" - } -}, -v5 = [ +v4 = [ { "kind": "Variable", "name": "after", @@ -83,29 +75,15 @@ v5 = [ "name": "first", "variableName": "count" }, - (v4/*: any*/) -], -v6 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "name", - "storageKey": null -}, -v7 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "active", - "storageKey": null -}, -v8 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "createdAt", - "storageKey": null -}; + { + "kind": "Literal", + "name": "orderBy", + "value": { + "direction": "DESC", + "field": "CREATED_AT" + } + } +]; return { "fragment": { "argumentDefinitions": (v0/*: any*/), @@ -154,7 +132,7 @@ return { "selections": [ { "alias": null, - "args": (v5/*: any*/), + "args": (v4/*: any*/), "concreteType": "TrustCenterAccessConnection", "kind": "LinkedField", "name": "accesses", @@ -230,8 +208,20 @@ return { "name": "email", "storageKey": null }, - (v6/*: any*/), - (v7/*: any*/), + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "name", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "active", + "storageKey": null + }, { "alias": null, "args": null, @@ -239,146 +229,33 @@ return { "name": "hasAcceptedNonDisclosureAgreement", "storageKey": null }, - (v8/*: any*/), { "alias": null, - "args": [ - { - "kind": "Literal", - "name": "first", - "value": 100 - }, - (v4/*: any*/) - ], - "concreteType": "TrustCenterDocumentAccessConnection", - "kind": "LinkedField", - "name": "documentAccesses", - "plural": false, - "selections": [ - { - "alias": null, - "args": null, - "concreteType": "TrustCenterDocumentAccessEdge", - "kind": "LinkedField", - "name": "edges", - "plural": true, - "selections": [ - { - "alias": null, - "args": null, - "concreteType": "TrustCenterDocumentAccess", - "kind": "LinkedField", - "name": "node", - "plural": false, - "selections": [ - (v3/*: any*/), - (v7/*: any*/), - (v8/*: any*/), - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "updatedAt", - "storageKey": null - }, - { - "alias": null, - "args": null, - "concreteType": "Document", - "kind": "LinkedField", - "name": "document", - "plural": false, - "selections": [ - (v3/*: any*/), - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "title", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "documentType", - "storageKey": null - } - ], - "storageKey": null - }, - { - "alias": null, - "args": null, - "concreteType": "Report", - "kind": "LinkedField", - "name": "report", - "plural": false, - "selections": [ - (v3/*: any*/), - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "filename", - "storageKey": null - }, - { - "alias": null, - "args": null, - "concreteType": "Audit", - "kind": "LinkedField", - "name": "audit", - "plural": false, - "selections": [ - (v3/*: any*/), - { - "alias": null, - "args": null, - "concreteType": "Framework", - "kind": "LinkedField", - "name": "framework", - "plural": false, - "selections": [ - (v6/*: any*/), - (v3/*: any*/) - ], - "storageKey": null - } - ], - "storageKey": null - } - ], - "storageKey": null - }, - { - "alias": null, - "args": null, - "concreteType": "TrustCenterFile", - "kind": "LinkedField", - "name": "trustCenterFile", - "plural": false, - "selections": [ - (v3/*: any*/), - (v6/*: any*/), - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "category", - "storageKey": null - } - ], - "storageKey": null - } - ], - "storageKey": null - } - ], - "storageKey": null - } - ], - "storageKey": "documentAccesses(first:100,orderBy:{\"direction\":\"DESC\",\"field\":\"CREATED_AT\"})" + "args": null, + "kind": "ScalarField", + "name": "createdAt", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "lastTokenExpiresAt", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "pendingRequestCount", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "activeCount", + "storageKey": null }, (v2/*: any*/) ], @@ -404,7 +281,7 @@ return { }, { "alias": null, - "args": (v5/*: any*/), + "args": (v4/*: any*/), "filters": [ "orderBy" ], @@ -423,16 +300,16 @@ return { ] }, "params": { - "cacheID": "12322ab403d03a821d2228ff68c3d191", + "cacheID": "98a87a363a8a26e30506346db052e11a", "id": null, "metadata": {}, "name": "TrustCenterAccessGraphPaginationQuery", "operationKind": "query", - "text": "query TrustCenterAccessGraphPaginationQuery(\n $count: Int\n $cursor: CursorKey\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...TrustCenterAccessGraph_accesses\n id\n }\n}\n\nfragment TrustCenterAccessGraph_accesses on TrustCenter {\n accesses(first: $count, after: $cursor, orderBy: {field: CREATED_AT, direction: DESC}) {\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n edges {\n cursor\n node {\n id\n email\n name\n active\n hasAcceptedNonDisclosureAgreement\n createdAt\n documentAccesses(first: 100, orderBy: {field: CREATED_AT, direction: DESC}) {\n edges {\n node {\n id\n active\n createdAt\n updatedAt\n document {\n id\n title\n documentType\n }\n report {\n id\n filename\n audit {\n id\n framework {\n name\n id\n }\n }\n }\n trustCenterFile {\n id\n name\n category\n }\n }\n }\n }\n __typename\n }\n }\n }\n id\n}\n" + "text": "query TrustCenterAccessGraphPaginationQuery(\n $count: Int\n $cursor: CursorKey\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...TrustCenterAccessGraph_accesses\n id\n }\n}\n\nfragment TrustCenterAccessGraph_accesses on TrustCenter {\n accesses(first: $count, after: $cursor, orderBy: {field: CREATED_AT, direction: DESC}) {\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n edges {\n cursor\n node {\n id\n email\n name\n active\n hasAcceptedNonDisclosureAgreement\n createdAt\n lastTokenExpiresAt\n pendingRequestCount\n activeCount\n __typename\n }\n }\n }\n id\n}\n" } }; })(); -(node as any).hash = "9c7f3e866e2593c169b1f98d0e637667"; +(node as any).hash = "10bb084980182a1e2334be77c29cf1ec"; export default node; diff --git a/apps/console/src/hooks/graph/__generated__/TrustCenterAccessGraphQuery.graphql.ts b/apps/console/src/hooks/graph/__generated__/TrustCenterAccessGraphQuery.graphql.ts index 6bd04066f..30aebcf5c 100644 --- a/apps/console/src/hooks/graph/__generated__/TrustCenterAccessGraphQuery.graphql.ts +++ b/apps/console/src/hooks/graph/__generated__/TrustCenterAccessGraphQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<> * @lightSyntaxTransform * @nogrep */ @@ -63,15 +63,7 @@ v5 = { "name": "__typename", "storageKey": null }, -v6 = { - "kind": "Literal", - "name": "orderBy", - "value": { - "direction": "DESC", - "field": "CREATED_AT" - } -}, -v7 = [ +v6 = [ { "kind": "Variable", "name": "after", @@ -82,29 +74,15 @@ v7 = [ "name": "first", "variableName": "count" }, - (v6/*: any*/) -], -v8 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "name", - "storageKey": null -}, -v9 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "active", - "storageKey": null -}, -v10 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "createdAt", - "storageKey": null -}; + { + "kind": "Literal", + "name": "orderBy", + "value": { + "direction": "DESC", + "field": "CREATED_AT" + } + } +]; return { "fragment": { "argumentDefinitions": [ @@ -169,7 +147,7 @@ return { "selections": [ { "alias": null, - "args": (v7/*: any*/), + "args": (v6/*: any*/), "concreteType": "TrustCenterAccessConnection", "kind": "LinkedField", "name": "accesses", @@ -245,8 +223,20 @@ return { "name": "email", "storageKey": null }, - (v8/*: any*/), - (v9/*: any*/), + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "name", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "active", + "storageKey": null + }, { "alias": null, "args": null, @@ -254,146 +244,33 @@ return { "name": "hasAcceptedNonDisclosureAgreement", "storageKey": null }, - (v10/*: any*/), { "alias": null, - "args": [ - { - "kind": "Literal", - "name": "first", - "value": 100 - }, - (v6/*: any*/) - ], - "concreteType": "TrustCenterDocumentAccessConnection", - "kind": "LinkedField", - "name": "documentAccesses", - "plural": false, - "selections": [ - { - "alias": null, - "args": null, - "concreteType": "TrustCenterDocumentAccessEdge", - "kind": "LinkedField", - "name": "edges", - "plural": true, - "selections": [ - { - "alias": null, - "args": null, - "concreteType": "TrustCenterDocumentAccess", - "kind": "LinkedField", - "name": "node", - "plural": false, - "selections": [ - (v4/*: any*/), - (v9/*: any*/), - (v10/*: any*/), - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "updatedAt", - "storageKey": null - }, - { - "alias": null, - "args": null, - "concreteType": "Document", - "kind": "LinkedField", - "name": "document", - "plural": false, - "selections": [ - (v4/*: any*/), - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "title", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "documentType", - "storageKey": null - } - ], - "storageKey": null - }, - { - "alias": null, - "args": null, - "concreteType": "Report", - "kind": "LinkedField", - "name": "report", - "plural": false, - "selections": [ - (v4/*: any*/), - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "filename", - "storageKey": null - }, - { - "alias": null, - "args": null, - "concreteType": "Audit", - "kind": "LinkedField", - "name": "audit", - "plural": false, - "selections": [ - (v4/*: any*/), - { - "alias": null, - "args": null, - "concreteType": "Framework", - "kind": "LinkedField", - "name": "framework", - "plural": false, - "selections": [ - (v8/*: any*/), - (v4/*: any*/) - ], - "storageKey": null - } - ], - "storageKey": null - } - ], - "storageKey": null - }, - { - "alias": null, - "args": null, - "concreteType": "TrustCenterFile", - "kind": "LinkedField", - "name": "trustCenterFile", - "plural": false, - "selections": [ - (v4/*: any*/), - (v8/*: any*/), - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "category", - "storageKey": null - } - ], - "storageKey": null - } - ], - "storageKey": null - } - ], - "storageKey": null - } - ], - "storageKey": "documentAccesses(first:100,orderBy:{\"direction\":\"DESC\",\"field\":\"CREATED_AT\"})" + "args": null, + "kind": "ScalarField", + "name": "createdAt", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "lastTokenExpiresAt", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "pendingRequestCount", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "activeCount", + "storageKey": null }, (v5/*: any*/) ], @@ -419,7 +296,7 @@ return { }, { "alias": null, - "args": (v7/*: any*/), + "args": (v6/*: any*/), "filters": [ "orderBy" ], @@ -438,12 +315,12 @@ return { ] }, "params": { - "cacheID": "37deb80fc3ff8892d2e68f7588da4e55", + "cacheID": "703f94692a1696b15e0c92b282866673", "id": null, "metadata": {}, "name": "TrustCenterAccessGraphQuery", "operationKind": "query", - "text": "query TrustCenterAccessGraphQuery(\n $trustCenterId: ID!\n $count: Int!\n $cursor: CursorKey\n) {\n node(id: $trustCenterId) {\n __typename\n ... on TrustCenter {\n id\n ...TrustCenterAccessGraph_accesses\n }\n id\n }\n}\n\nfragment TrustCenterAccessGraph_accesses on TrustCenter {\n accesses(first: $count, after: $cursor, orderBy: {field: CREATED_AT, direction: DESC}) {\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n edges {\n cursor\n node {\n id\n email\n name\n active\n hasAcceptedNonDisclosureAgreement\n createdAt\n documentAccesses(first: 100, orderBy: {field: CREATED_AT, direction: DESC}) {\n edges {\n node {\n id\n active\n createdAt\n updatedAt\n document {\n id\n title\n documentType\n }\n report {\n id\n filename\n audit {\n id\n framework {\n name\n id\n }\n }\n }\n trustCenterFile {\n id\n name\n category\n }\n }\n }\n }\n __typename\n }\n }\n }\n id\n}\n" + "text": "query TrustCenterAccessGraphQuery(\n $trustCenterId: ID!\n $count: Int!\n $cursor: CursorKey\n) {\n node(id: $trustCenterId) {\n __typename\n ... on TrustCenter {\n id\n ...TrustCenterAccessGraph_accesses\n }\n id\n }\n}\n\nfragment TrustCenterAccessGraph_accesses on TrustCenter {\n accesses(first: $count, after: $cursor, orderBy: {field: CREATED_AT, direction: DESC}) {\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n edges {\n cursor\n node {\n id\n email\n name\n active\n hasAcceptedNonDisclosureAgreement\n createdAt\n lastTokenExpiresAt\n pendingRequestCount\n activeCount\n __typename\n }\n }\n }\n id\n}\n" } }; })(); diff --git a/apps/console/src/hooks/graph/__generated__/TrustCenterAccessGraphUpdateMutation.graphql.ts b/apps/console/src/hooks/graph/__generated__/TrustCenterAccessGraphUpdateMutation.graphql.ts index 6e0b70bb2..bd6b41e4d 100644 --- a/apps/console/src/hooks/graph/__generated__/TrustCenterAccessGraphUpdateMutation.graphql.ts +++ b/apps/console/src/hooks/graph/__generated__/TrustCenterAccessGraphUpdateMutation.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<8ecf71138aa0165738506f5e589d3181>> + * @generated SignedSource<<25b79c235754d47097b2ca28f1f3e9a0>> * @lightSyntaxTransform * @nogrep */ @@ -9,7 +9,6 @@ // @ts-nocheck import { ConcreteRequest } from 'relay-runtime'; -export type DocumentType = "ISMS" | "OTHER" | "POLICY" | "PROCEDURE"; export type UpdateTrustCenterAccessInput = { active?: boolean | null | undefined; documentIds?: ReadonlyArray | null | undefined; @@ -25,41 +24,14 @@ export type TrustCenterAccessGraphUpdateMutation$data = { readonly updateTrustCenterAccess: { readonly trustCenterAccess: { readonly active: boolean; + readonly activeCount: number; readonly createdAt: any; - readonly documentAccesses: { - readonly edges: ReadonlyArray<{ - readonly node: { - readonly active: boolean; - readonly createdAt: any; - readonly document: { - readonly documentType: DocumentType; - readonly id: string; - readonly title: string; - } | null | undefined; - readonly id: string; - readonly report: { - readonly audit: { - readonly framework: { - readonly name: string; - }; - readonly id: string; - } | null | undefined; - readonly filename: string; - readonly id: string; - } | null | undefined; - readonly trustCenterFile: { - readonly category: string; - readonly id: string; - readonly name: string; - } | null | undefined; - readonly updatedAt: any; - }; - }>; - }; readonly email: string; readonly hasAcceptedNonDisclosureAgreement: boolean; readonly id: string; + readonly lastTokenExpiresAt: any | null | undefined; readonly name: string; + readonly pendingRequestCount: number; readonly updatedAt: any; }; }; @@ -79,241 +51,111 @@ var v0 = [ ], v1 = [ { - "kind": "Variable", - "name": "input", - "variableName": "input" - } -], -v2 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "id", - "storageKey": null -}, -v3 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "email", - "storageKey": null -}, -v4 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "name", - "storageKey": null -}, -v5 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "active", - "storageKey": null -}, -v6 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "hasAcceptedNonDisclosureAgreement", - "storageKey": null -}, -v7 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "createdAt", - "storageKey": null -}, -v8 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "updatedAt", - "storageKey": null -}, -v9 = [ - { - "kind": "Literal", - "name": "first", - "value": 100 - }, - { - "kind": "Literal", - "name": "orderBy", - "value": { - "direction": "DESC", - "field": "CREATED_AT" - } - } -], -v10 = { - "alias": null, - "args": null, - "concreteType": "Document", - "kind": "LinkedField", - "name": "document", - "plural": false, - "selections": [ - (v2/*: any*/), - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "title", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "documentType", - "storageKey": null - } - ], - "storageKey": null -}, -v11 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "filename", - "storageKey": null -}, -v12 = { - "alias": null, - "args": null, - "concreteType": "TrustCenterFile", - "kind": "LinkedField", - "name": "trustCenterFile", - "plural": false, - "selections": [ - (v2/*: any*/), - (v4/*: any*/), - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "category", - "storageKey": null - } - ], - "storageKey": null -}; -return { - "fragment": { - "argumentDefinitions": (v0/*: any*/), - "kind": "Fragment", - "metadata": null, - "name": "TrustCenterAccessGraphUpdateMutation", + "alias": null, + "args": [ + { + "kind": "Variable", + "name": "input", + "variableName": "input" + } + ], + "concreteType": "UpdateTrustCenterAccessPayload", + "kind": "LinkedField", + "name": "updateTrustCenterAccess", + "plural": false, "selections": [ { "alias": null, - "args": (v1/*: any*/), - "concreteType": "UpdateTrustCenterAccessPayload", + "args": null, + "concreteType": "TrustCenterAccess", "kind": "LinkedField", - "name": "updateTrustCenterAccess", + "name": "trustCenterAccess", "plural": false, "selections": [ { "alias": null, "args": null, - "concreteType": "TrustCenterAccess", - "kind": "LinkedField", - "name": "trustCenterAccess", - "plural": false, - "selections": [ - (v2/*: any*/), - (v3/*: any*/), - (v4/*: any*/), - (v5/*: any*/), - (v6/*: any*/), - (v7/*: any*/), - (v8/*: any*/), - { - "alias": null, - "args": (v9/*: any*/), - "concreteType": "TrustCenterDocumentAccessConnection", - "kind": "LinkedField", - "name": "documentAccesses", - "plural": false, - "selections": [ - { - "alias": null, - "args": null, - "concreteType": "TrustCenterDocumentAccessEdge", - "kind": "LinkedField", - "name": "edges", - "plural": true, - "selections": [ - { - "alias": null, - "args": null, - "concreteType": "TrustCenterDocumentAccess", - "kind": "LinkedField", - "name": "node", - "plural": false, - "selections": [ - (v2/*: any*/), - (v5/*: any*/), - (v7/*: any*/), - (v8/*: any*/), - (v10/*: any*/), - { - "alias": null, - "args": null, - "concreteType": "Report", - "kind": "LinkedField", - "name": "report", - "plural": false, - "selections": [ - (v2/*: any*/), - (v11/*: any*/), - { - "alias": null, - "args": null, - "concreteType": "Audit", - "kind": "LinkedField", - "name": "audit", - "plural": false, - "selections": [ - (v2/*: any*/), - { - "alias": null, - "args": null, - "concreteType": "Framework", - "kind": "LinkedField", - "name": "framework", - "plural": false, - "selections": [ - (v4/*: any*/) - ], - "storageKey": null - } - ], - "storageKey": null - } - ], - "storageKey": null - }, - (v12/*: any*/) - ], - "storageKey": null - } - ], - "storageKey": null - } - ], - "storageKey": "documentAccesses(first:100,orderBy:{\"direction\":\"DESC\",\"field\":\"CREATED_AT\"})" - } - ], + "kind": "ScalarField", + "name": "id", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "email", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "name", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "active", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "hasAcceptedNonDisclosureAgreement", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "createdAt", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "updatedAt", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "lastTokenExpiresAt", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "pendingRequestCount", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "activeCount", "storageKey": null } ], "storageKey": null } ], + "storageKey": null + } +]; +return { + "fragment": { + "argumentDefinitions": (v0/*: any*/), + "kind": "Fragment", + "metadata": null, + "name": "TrustCenterAccessGraphUpdateMutation", + "selections": (v1/*: any*/), "type": "Mutation", "abstractKey": null }, @@ -322,126 +164,19 @@ return { "argumentDefinitions": (v0/*: any*/), "kind": "Operation", "name": "TrustCenterAccessGraphUpdateMutation", - "selections": [ - { - "alias": null, - "args": (v1/*: any*/), - "concreteType": "UpdateTrustCenterAccessPayload", - "kind": "LinkedField", - "name": "updateTrustCenterAccess", - "plural": false, - "selections": [ - { - "alias": null, - "args": null, - "concreteType": "TrustCenterAccess", - "kind": "LinkedField", - "name": "trustCenterAccess", - "plural": false, - "selections": [ - (v2/*: any*/), - (v3/*: any*/), - (v4/*: any*/), - (v5/*: any*/), - (v6/*: any*/), - (v7/*: any*/), - (v8/*: any*/), - { - "alias": null, - "args": (v9/*: any*/), - "concreteType": "TrustCenterDocumentAccessConnection", - "kind": "LinkedField", - "name": "documentAccesses", - "plural": false, - "selections": [ - { - "alias": null, - "args": null, - "concreteType": "TrustCenterDocumentAccessEdge", - "kind": "LinkedField", - "name": "edges", - "plural": true, - "selections": [ - { - "alias": null, - "args": null, - "concreteType": "TrustCenterDocumentAccess", - "kind": "LinkedField", - "name": "node", - "plural": false, - "selections": [ - (v2/*: any*/), - (v5/*: any*/), - (v7/*: any*/), - (v8/*: any*/), - (v10/*: any*/), - { - "alias": null, - "args": null, - "concreteType": "Report", - "kind": "LinkedField", - "name": "report", - "plural": false, - "selections": [ - (v2/*: any*/), - (v11/*: any*/), - { - "alias": null, - "args": null, - "concreteType": "Audit", - "kind": "LinkedField", - "name": "audit", - "plural": false, - "selections": [ - (v2/*: any*/), - { - "alias": null, - "args": null, - "concreteType": "Framework", - "kind": "LinkedField", - "name": "framework", - "plural": false, - "selections": [ - (v4/*: any*/), - (v2/*: any*/) - ], - "storageKey": null - } - ], - "storageKey": null - } - ], - "storageKey": null - }, - (v12/*: any*/) - ], - "storageKey": null - } - ], - "storageKey": null - } - ], - "storageKey": "documentAccesses(first:100,orderBy:{\"direction\":\"DESC\",\"field\":\"CREATED_AT\"})" - } - ], - "storageKey": null - } - ], - "storageKey": null - } - ] + "selections": (v1/*: any*/) }, "params": { - "cacheID": "b66da9236d9f81563608b3aa5f730908", + "cacheID": "8b330240bc19bbebb3244a49dc0a6db0", "id": null, "metadata": {}, "name": "TrustCenterAccessGraphUpdateMutation", "operationKind": "mutation", - "text": "mutation TrustCenterAccessGraphUpdateMutation(\n $input: UpdateTrustCenterAccessInput!\n) {\n updateTrustCenterAccess(input: $input) {\n trustCenterAccess {\n id\n email\n name\n active\n hasAcceptedNonDisclosureAgreement\n createdAt\n updatedAt\n documentAccesses(first: 100, orderBy: {field: CREATED_AT, direction: DESC}) {\n edges {\n node {\n id\n active\n createdAt\n updatedAt\n document {\n id\n title\n documentType\n }\n report {\n id\n filename\n audit {\n id\n framework {\n name\n id\n }\n }\n }\n trustCenterFile {\n id\n name\n category\n }\n }\n }\n }\n }\n }\n}\n" + "text": "mutation TrustCenterAccessGraphUpdateMutation(\n $input: UpdateTrustCenterAccessInput!\n) {\n updateTrustCenterAccess(input: $input) {\n trustCenterAccess {\n id\n email\n name\n active\n hasAcceptedNonDisclosureAgreement\n createdAt\n updatedAt\n lastTokenExpiresAt\n pendingRequestCount\n activeCount\n }\n }\n}\n" } }; })(); -(node as any).hash = "43e73cc9d80e898f1ba2a92eaf4646f5"; +(node as any).hash = "f78b4d25b0977a14269491db951a1d9d"; export default node; diff --git a/apps/console/src/hooks/graph/__generated__/TrustCenterAccessGraph_accesses.graphql.ts b/apps/console/src/hooks/graph/__generated__/TrustCenterAccessGraph_accesses.graphql.ts index ec3ae8f6d..231e5a134 100644 --- a/apps/console/src/hooks/graph/__generated__/TrustCenterAccessGraph_accesses.graphql.ts +++ b/apps/console/src/hooks/graph/__generated__/TrustCenterAccessGraph_accesses.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<> * @lightSyntaxTransform * @nogrep */ @@ -9,7 +9,6 @@ // @ts-nocheck import { ReaderFragment } from 'relay-runtime'; -export type DocumentType = "ISMS" | "OTHER" | "POLICY" | "PROCEDURE"; import { FragmentRefs } from "relay-runtime"; export type TrustCenterAccessGraph_accesses$data = { readonly accesses: { @@ -18,41 +17,14 @@ export type TrustCenterAccessGraph_accesses$data = { readonly cursor: any; readonly node: { readonly active: boolean; + readonly activeCount: number; readonly createdAt: any; - readonly documentAccesses: { - readonly edges: ReadonlyArray<{ - readonly node: { - readonly active: boolean; - readonly createdAt: any; - readonly document: { - readonly documentType: DocumentType; - readonly id: string; - readonly title: string; - } | null | undefined; - readonly id: string; - readonly report: { - readonly audit: { - readonly framework: { - readonly name: string; - }; - readonly id: string; - } | null | undefined; - readonly filename: string; - readonly id: string; - } | null | undefined; - readonly trustCenterFile: { - readonly category: string; - readonly id: string; - readonly name: string; - } | null | undefined; - readonly updatedAt: any; - }; - }>; - }; readonly email: string; readonly hasAcceptedNonDisclosureAgreement: boolean; readonly id: string; + readonly lastTokenExpiresAt: any | null | undefined; readonly name: string; + readonly pendingRequestCount: number; }; }>; readonly pageInfo: { @@ -77,40 +49,11 @@ var v0 = [ "accesses" ], v1 = { - "kind": "Literal", - "name": "orderBy", - "value": { - "direction": "DESC", - "field": "CREATED_AT" - } -}, -v2 = { "alias": null, "args": null, "kind": "ScalarField", "name": "id", "storageKey": null -}, -v3 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "name", - "storageKey": null -}, -v4 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "active", - "storageKey": null -}, -v5 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "createdAt", - "storageKey": null }; return { "argumentDefinitions": [ @@ -157,7 +100,14 @@ return { { "alias": "accesses", "args": [ - (v1/*: any*/) + { + "kind": "Literal", + "name": "orderBy", + "value": { + "direction": "DESC", + "field": "CREATED_AT" + } + } ], "concreteType": "TrustCenterAccessConnection", "kind": "LinkedField", @@ -226,7 +176,7 @@ return { "name": "node", "plural": false, "selections": [ - (v2/*: any*/), + (v1/*: any*/), { "alias": null, "args": null, @@ -234,8 +184,20 @@ return { "name": "email", "storageKey": null }, - (v3/*: any*/), - (v4/*: any*/), + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "name", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "active", + "storageKey": null + }, { "alias": null, "args": null, @@ -243,145 +205,33 @@ return { "name": "hasAcceptedNonDisclosureAgreement", "storageKey": null }, - (v5/*: any*/), { "alias": null, - "args": [ - { - "kind": "Literal", - "name": "first", - "value": 100 - }, - (v1/*: any*/) - ], - "concreteType": "TrustCenterDocumentAccessConnection", - "kind": "LinkedField", - "name": "documentAccesses", - "plural": false, - "selections": [ - { - "alias": null, - "args": null, - "concreteType": "TrustCenterDocumentAccessEdge", - "kind": "LinkedField", - "name": "edges", - "plural": true, - "selections": [ - { - "alias": null, - "args": null, - "concreteType": "TrustCenterDocumentAccess", - "kind": "LinkedField", - "name": "node", - "plural": false, - "selections": [ - (v2/*: any*/), - (v4/*: any*/), - (v5/*: any*/), - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "updatedAt", - "storageKey": null - }, - { - "alias": null, - "args": null, - "concreteType": "Document", - "kind": "LinkedField", - "name": "document", - "plural": false, - "selections": [ - (v2/*: any*/), - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "title", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "documentType", - "storageKey": null - } - ], - "storageKey": null - }, - { - "alias": null, - "args": null, - "concreteType": "Report", - "kind": "LinkedField", - "name": "report", - "plural": false, - "selections": [ - (v2/*: any*/), - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "filename", - "storageKey": null - }, - { - "alias": null, - "args": null, - "concreteType": "Audit", - "kind": "LinkedField", - "name": "audit", - "plural": false, - "selections": [ - (v2/*: any*/), - { - "alias": null, - "args": null, - "concreteType": "Framework", - "kind": "LinkedField", - "name": "framework", - "plural": false, - "selections": [ - (v3/*: any*/) - ], - "storageKey": null - } - ], - "storageKey": null - } - ], - "storageKey": null - }, - { - "alias": null, - "args": null, - "concreteType": "TrustCenterFile", - "kind": "LinkedField", - "name": "trustCenterFile", - "plural": false, - "selections": [ - (v2/*: any*/), - (v3/*: any*/), - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "category", - "storageKey": null - } - ], - "storageKey": null - } - ], - "storageKey": null - } - ], - "storageKey": null - } - ], - "storageKey": "documentAccesses(first:100,orderBy:{\"direction\":\"DESC\",\"field\":\"CREATED_AT\"})" + "args": null, + "kind": "ScalarField", + "name": "createdAt", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "lastTokenExpiresAt", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "pendingRequestCount", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "activeCount", + "storageKey": null }, { "alias": null, @@ -411,13 +261,13 @@ return { ], "storageKey": "__TrustCenterAccessGraph_accesses_connection(orderBy:{\"direction\":\"DESC\",\"field\":\"CREATED_AT\"})" }, - (v2/*: any*/) + (v1/*: any*/) ], "type": "TrustCenter", "abstractKey": null }; })(); -(node as any).hash = "9c7f3e866e2593c169b1f98d0e637667"; +(node as any).hash = "10bb084980182a1e2334be77c29cf1ec"; export default node; diff --git a/apps/console/src/layouts/MainLayout.tsx b/apps/console/src/layouts/MainLayout.tsx index 7b8aaeaed..8afa8ed16 100644 --- a/apps/console/src/layouts/MainLayout.tsx +++ b/apps/console/src/layouts/MainLayout.tsx @@ -12,7 +12,6 @@ import { IconInboxEmpty, IconPageTextLine, IconSettingsGear2, - IconCheckmark1, IconStore, IconTodo, IconListStack, @@ -20,6 +19,7 @@ import { IconShield, IconRotateCw, IconCircleProgress, + IconMedal, Layout, SidebarItem, UserDropdown as UserDropdownRoot, @@ -169,7 +169,7 @@ export function MainLayout() { /> ; + }; + audits?: { + edges: Array<{ + node: { + id: string; + filename: string; + trustCenterVisibility: string; + framework: { + name: string; + }; + }; + }>; + }; + trustCenterFiles?: { + edges: Array<{ + node: { + id: string; + name: string; + category: string; + trustCenterVisibility: string; + }; + }>; + }; }; }; +type DocumentAccessInfo = { + id: string; + active: boolean; + requested: boolean; + document?: { + id: string; + title: string; + documentType: string; + } | null; + report?: { + id: string; + filename: string; + audit: { + id: string; + framework: { + name: string; + }; + }; + } | null; + trustCenterFile?: { + id: string; + name: string; + category: string; + } | null; +}; + +function DocumentAccessesLoader({ + queryReference, + onDataLoaded +}: { + queryReference: any; + onDataLoaded: (documentAccesses: DocumentAccessInfo[]) => void; +}) { + const data = usePreloadedQuery(loadTrustCenterAccessDocumentAccessesQuery, queryReference); + + useEffect(() => { + if (data && typeof data === 'object' && 'node' in data) { + const node = (data as any).node; + if (node?.availableDocumentAccesses?.edges) { + const documentAccesses = node.availableDocumentAccesses.edges.map((edge: any) => edge.node); + onDataLoaded(documentAccesses); + } + } + }, [data, onDataLoaded]); + + return null; +} + export default function TrustCenterAccessTab() { const { __ } = useTranslate(); const { organization } = useOutletContext(); @@ -75,10 +156,35 @@ export default function TrustCenterAccessTab() { const dialogRef = useDialogRef(); const editDialogRef = useDialogRef(); const [editingAccess, setEditingAccess] = useState(null); + const [editingDocumentAccesses, setEditingDocumentAccesses] = useState([]); const [selectedDocumentAccesses, setSelectedDocumentAccesses] = useState>(new Set()); const [pendingEditEmail, setPendingEditEmail] = useState(null); + const [documentAccessesQueryReference, loadDocumentAccessesQuery] = useQueryLoader(loadTrustCenterAccessDocumentAccessesQuery); + const loadedAccessIdRef = useRef(null); + const [isLoadingDocumentAccesses, setIsLoadingDocumentAccesses] = useState(false); - const formattedDocumentAccesses = editingAccess?.documentAccesses + useEffect(() => { + if (editingAccess?.id && loadedAccessIdRef.current !== editingAccess.id) { + loadedAccessIdRef.current = editingAccess.id; + setIsLoadingDocumentAccesses(true); + loadDocumentAccessesQuery({ accessId: editingAccess.id }, { fetchPolicy: 'network-only' }); + } + }, [editingAccess?.id, loadDocumentAccessesQuery]); + + const handleDocumentAccessesLoaded = useCallback((documentAccesses: DocumentAccessInfo[]) => { + setEditingDocumentAccesses(documentAccesses); + + const activeIds = new Set( + documentAccesses + .filter((docAccess) => docAccess.active) + .map((docAccess) => docAccess.document?.id || docAccess.report?.id || docAccess.trustCenterFile?.id) + .filter((id: unknown): id is string => typeof id === 'string') + ); + setSelectedDocumentAccesses(activeIds); + setIsLoadingDocumentAccesses(false); + }, []); + + const formattedDocumentAccesses = editingDocumentAccesses ?.map((docAccess) => getDocumentAccessInfo(docAccess, __)) ?.filter((info) => info !== null) ?? []; @@ -93,6 +199,7 @@ export default function TrustCenterAccessTab() { type DocumentAccessType = { id: string; active: boolean; + requested: boolean; document?: { id: string; title: string; @@ -126,6 +233,8 @@ export default function TrustCenterAccessTab() { type: __("Document"), category: docAccess.document?.documentType, id: docAccess.document?.id, + requested: docAccess.requested, + active: docAccess.active, }; } if (!!docAccess.report) { @@ -135,6 +244,8 @@ export default function TrustCenterAccessTab() { type: __("Report"), category: docAccess.report?.audit?.framework?.name, id: docAccess.report?.id, + requested: docAccess.requested, + active: docAccess.active, }; } if (!!docAccess.trustCenterFile) { @@ -144,6 +255,8 @@ export default function TrustCenterAccessTab() { type: __("File"), category: docAccess.trustCenterFile?.category, id: docAccess.trustCenterFile?.id, + requested: docAccess.requested, + active: docAccess.active, }; } @@ -157,28 +270,24 @@ export default function TrustCenterAccessTab() { active: boolean; hasAcceptedNonDisclosureAgreement: boolean; createdAt: string; - documentAccesses: DocumentAccessType[]; + lastTokenExpiresAt: string | null; + pendingRequestCount: number; + activeCount: number; + documentAccesses?: DocumentAccessType[]; }; const { data: trustCenterData, loadMore, hasNext, isLoadingNext } = useTrustCenterAccesses(organization.trustCenter?.id || ""); - type AccessEdge = NonNullable['edges']>[number]; - type DocumentAccessEdge = NonNullable['node']['documentAccesses']>['edges']>[number]; - - const accesses: AccessType[] = trustCenterData?.node?.accesses?.edges?.map((edge: AccessEdge) => ({ + const accesses: AccessType[] = trustCenterData?.node?.accesses?.edges?.map((edge: any) => ({ id: edge.node.id, email: edge.node.email, name: edge.node.name, active: edge.node.active, hasAcceptedNonDisclosureAgreement: edge.node.hasAcceptedNonDisclosureAgreement, createdAt: edge.node.createdAt, - documentAccesses: edge.node.documentAccesses?.edges?.map((docEdge: DocumentAccessEdge) => ({ - id: docEdge.node.id, - active: docEdge.node.active, - document: docEdge.node.document, - report: docEdge.node.report, - trustCenterFile: docEdge.node.trustCenterFile - })) ?? [] + lastTokenExpiresAt: edge.node.lastTokenExpiresAt, + pendingRequestCount: edge.node.pendingRequestCount || 0, + activeCount: edge.node.activeCount || 0, })) ?? []; @@ -201,8 +310,6 @@ export default function TrustCenterAccessTab() { connections: connectionId ? [connectionId] : [], }, onSuccess: () => { - dialogRef.current?.close(); - inviteForm.reset(); setPendingEditEmail(email); }, }); @@ -220,32 +327,37 @@ export default function TrustCenterAccessTab() { }, [deleteInvitation, trustCenterData]); - const getActiveDocumentIds = useCallback((access: AccessType) => { - return access.documentAccesses - .filter(docAccess => docAccess.active) - .map(docAccess => docAccess.document?.id || docAccess.report?.id || docAccess.trustCenterFile?.id) - .filter((id): id is string => id !== undefined); - }, []); const handleEditAccess = useCallback((access: AccessType) => { + loadedAccessIdRef.current = null; setEditingAccess(access); + setEditingDocumentAccesses([]); + setSelectedDocumentAccesses(new Set()); + setIsLoadingDocumentAccesses(false); editForm.reset({ name: access.name, active: access.active }); - setSelectedDocumentAccesses(new Set(getActiveDocumentIds(access))); editDialogRef.current?.open(); - }, [editDialogRef, editForm, getActiveDocumentIds]); + }, [editDialogRef, editForm]); useEffect(() => { if (pendingEditEmail && accesses.length > 0) { const newAccess = accesses.find(access => access.email === pendingEditEmail); if (newAccess) { setPendingEditEmail(null); + loadedAccessIdRef.current = null; setEditingAccess(newAccess); editForm.reset({ name: newAccess.name, active: true }); - setSelectedDocumentAccesses(new Set(getActiveDocumentIds(newAccess))); + setEditingDocumentAccesses([]); + setSelectedDocumentAccesses(new Set()); editDialogRef.current?.open(); + setTimeout(() => { + dialogRef.current?.close(); + }, 50); + setTimeout(() => { + inviteForm.reset(); + }, 300); } } - }, [accesses, pendingEditEmail, editForm, editDialogRef, getActiveDocumentIds]); + }, [accesses, pendingEditEmail, editForm, dialogRef, editDialogRef, inviteForm]); const handleToggleDocumentAccess = useCallback((documentId: string, active: boolean) => { setSelectedDocumentAccesses(prev => { @@ -262,7 +374,7 @@ export default function TrustCenterAccessTab() { const handleUpdateName = editForm.handleSubmit(async (data) => { if (!editingAccess) return; - const { documentIds, reportIds, trustCenterFileIds } = editingAccess.documentAccesses.reduce( + const { documentIds, reportIds, trustCenterFileIds } = editingDocumentAccesses.reduce( (acc, docAccess) => { const id = docAccess.document?.id || docAccess.report?.id || docAccess.trustCenterFile?.id; if (id && selectedDocumentAccesses.has(id)) { @@ -294,6 +406,7 @@ export default function TrustCenterAccessTab() { editDialogRef.current?.close(); setEditingAccess(null); editForm.reset(); + setEditingDocumentAccesses([]); setSelectedDocumentAccesses(new Set()); }, }); @@ -309,7 +422,7 @@ export default function TrustCenterAccessTab() {

{organization.trustCenter?.id && ( -
{__("Name")}
- - - - - - - - - - - - - {accesses.map((access) => { - const activeDocuments = access.documentAccesses.filter(doc => doc.active).length; - const totalDocuments = access.documentAccesses.length; + {!organization.trustCenter?.id ? ( +
{__("Name")}{__("Email")}{__("Date")}{__("Active")}{__("Documents")}{__("NDA")}
+ + + + + +
+ +
+ ) : accesses.length === 0 ? ( + + + + + + +
+ {__("No external access granted yet")} +
+ ) : ( + <> + + + + + + + + + + + + + + + + {accesses.map((access) => { + const isExpired = access.lastTokenExpiresAt ? new Date(access.lastTokenExpiresAt) < new Date() : false; - return ( - handleEditAccess(access)} - className="cursor-pointer hover:bg-bg-secondary transition-colors" - > - - - - handleEditAccess(access)} + className="cursor-pointer hover:bg-bg-secondary transition-colors" + > + + + + + - - + + + - - - ); - })} - -
{__("Name")}{__("Email")}{__("Date")}{__("Expires")}{__("Active")}{__("Access")}{__("Requests")}{__("NDA")}
{access.name}{access.email} - {formatDate(access.createdAt)} - + return ( +
{access.name}{access.email} + {formatDate(access.createdAt)} + + {access.lastTokenExpiresAt ? formatDate(access.lastTokenExpiresAt) : "-"} + +
{access.active ? ( ) : ( )} -
- {totalDocuments > 0 ? `${activeDocuments}/${totalDocuments}` : '0/0'} - + + + {access.activeCount} + + {access.pendingRequestCount > 0 ? access.pendingRequestCount : ""} + +
{access.hasAcceptedNonDisclosureAgreement && ( )} -
-
e.stopPropagation()} - > -
- {hasNext && ( - - )} - - )} - + +
e.stopPropagation()} + > +
+ + + ); + })} + + + {hasNext && ( + + )} + + )}
- -

- {__("Send a 7-day access token to an external person to view your trust center")} -

+ +
+

+ {__("Send a 30-day access token to an external person to view your trust center")} +

- + - +
+ +
+
@@ -453,6 +591,12 @@ export default function TrustCenterAccessTab() { ref={editDialogRef} title={__("Edit Access")} > + {documentAccessesQueryReference && ( + + )}
@@ -484,11 +628,37 @@ export default function TrustCenterAccessTab() {
- {formattedDocumentAccesses.length > 0 && ( -
-

+
+
+

{__("Document Access Permissions")}

+ {!isLoadingDocumentAccesses && formattedDocumentAccesses.length > 0 && ( + + )} +
+ + {isLoadingDocumentAccesses ? ( +
+ +
+ ) : formattedDocumentAccesses.length > 0 ? (
@@ -496,6 +666,7 @@ export default function TrustCenterAccessTab() { + {formattedDocumentAccesses.map((info) => { - const { variant, name, type, category, id } = info; + const { variant, name, type, category, id, requested } = info; return ( @@ -524,6 +695,13 @@ export default function TrustCenterAccessTab() { {category || "-"} +
{__("Name")} {__("Type")} {__("Category")}
{__("Access")} @@ -505,7 +676,7 @@ export default function TrustCenterAccessTab() {
+ {requested && ( + + {__("Requested")} + + )} +
-
- )} + ) : ( +
+ {__("No documents available")} +
+ )} +

- diff --git a/apps/console/src/pages/organizations/trustCenter/TrustCenterAuditsTab.tsx b/apps/console/src/pages/organizations/trustCenter/TrustCenterAuditsTab.tsx index 859102007..068fd9bd6 100644 --- a/apps/console/src/pages/organizations/trustCenter/TrustCenterAuditsTab.tsx +++ b/apps/console/src/pages/organizations/trustCenter/TrustCenterAuditsTab.tsx @@ -1,4 +1,5 @@ -import { Card, Spinner } from "@probo/ui"; +import { Spinner } from "@probo/ui"; +import { useTranslate } from "@probo/i18n"; import { useOutletContext } from "react-router"; import { TrustCenterAuditsCard } from "/components/trustCenter/TrustCenterAuditsCard"; import { useTrustCenterAuditUpdate } from "/hooks/graph/TrustCenterAuditGraph"; @@ -15,6 +16,7 @@ type ContextType = { }; export default function TrustCenterAuditsTab() { + const { __ } = useTranslate(); const { organization } = useOutletContext(); const [updateAuditVisibility, isUpdatingAudits] = useTrustCenterAuditUpdate(); @@ -23,17 +25,20 @@ export default function TrustCenterAuditsTab() { return (
+
+

{__("Audits")}

+

+ {__("Manage audit reports and compliance certifications")} +

+
{isUpdatingAudits && }
- - - +
); } diff --git a/apps/console/src/pages/organizations/trustCenter/TrustCenterDocumentsTab.tsx b/apps/console/src/pages/organizations/trustCenter/TrustCenterDocumentsTab.tsx index e8ff14490..241d4fa8a 100644 --- a/apps/console/src/pages/organizations/trustCenter/TrustCenterDocumentsTab.tsx +++ b/apps/console/src/pages/organizations/trustCenter/TrustCenterDocumentsTab.tsx @@ -1,4 +1,5 @@ -import { Card, Spinner } from "@probo/ui"; +import { Spinner } from "@probo/ui"; +import { useTranslate } from "@probo/i18n"; import { useOutletContext } from "react-router"; import { TrustCenterDocumentsCard } from "/components/trustCenter/TrustCenterDocumentsCard"; import { useUpdateDocumentVisibilityMutation } from "/hooks/graph/TrustCenterDocumentGraph"; @@ -15,6 +16,7 @@ type ContextType = { }; export default function TrustCenterDocumentsTab() { + const { __ } = useTranslate(); const { organization } = useOutletContext(); const [updateDocumentVisibility, isUpdatingDocuments] = useUpdateDocumentVisibilityMutation(); @@ -23,17 +25,20 @@ export default function TrustCenterDocumentsTab() { return (
+
+

{__("Documents")}

+

+ {__("Manage policies, procedures and compliance documents")} +

+
{isUpdatingDocuments && }
- - - +
); } diff --git a/apps/console/src/pages/organizations/trustCenter/TrustCenterFilesTab.tsx b/apps/console/src/pages/organizations/trustCenter/TrustCenterFilesTab.tsx index bcac38469..a9640af0d 100644 --- a/apps/console/src/pages/organizations/trustCenter/TrustCenterFilesTab.tsx +++ b/apps/console/src/pages/organizations/trustCenter/TrustCenterFilesTab.tsx @@ -1,6 +1,5 @@ import { Button, - Card, Dialog, DialogContent, DialogFooter, @@ -10,6 +9,7 @@ import { Dropzone, Option, Badge, + IconPlusLarge, } from "@probo/ui"; import { useTranslate } from "@probo/i18n"; import { useOutletContext } from "react-router"; @@ -200,7 +200,7 @@ export default function TrustCenterFilesTab() { {__("Upload and manage files for your trust center")}

- @@ -209,17 +209,14 @@ export default function TrustCenterFilesTab() { )} - - - + diff --git a/apps/console/src/pages/organizations/trustCenter/TrustCenterOverviewTab.tsx b/apps/console/src/pages/organizations/trustCenter/TrustCenterOverviewTab.tsx new file mode 100644 index 000000000..f8468b525 --- /dev/null +++ b/apps/console/src/pages/organizations/trustCenter/TrustCenterOverviewTab.tsx @@ -0,0 +1,248 @@ +import { useTranslate } from "@probo/i18n"; +import { + Button, + Card, + Checkbox, + Dropzone, + Spinner, + useToast, + IconTrashCan, +} from "@probo/ui"; +import { useOutletContext } from "react-router"; +import { useUpdateTrustCenterMutation, useUploadTrustCenterNDAMutation, useDeleteTrustCenterNDAMutation } from "/hooks/graph/TrustCenterGraph"; +import type { TrustCenterGraphQuery$data } from "/hooks/graph/__generated__/TrustCenterGraphQuery.graphql"; +import { useState } from "react"; +import { SlackConnections } from "../../../components/organizations/SlackConnection"; + +type ContextType = { + organization: TrustCenterGraphQuery$data["organization"]; +}; + +export default function TrustCenterOverviewTab() { + const { __ } = useTranslate(); + const { toast } = useToast(); + const { organization } = useOutletContext(); + + const [updateTrustCenter, isUpdating] = useUpdateTrustCenterMutation(); + const [uploadNDA, isUploadingNDA] = useUploadTrustCenterNDAMutation(); + const [deleteNDA, isDeletingNDA] = useDeleteTrustCenterNDAMutation(); + const [isActive, setIsActive] = useState(organization.trustCenter?.active || false); + + const handleToggleActive = async (active: boolean) => { + if (!organization.trustCenter?.id) { + toast({ + title: __("Error"), + description: __("Trust center not found"), + variant: "error", + }); + return; + } + + setIsActive(active); + + updateTrustCenter({ + variables: { + input: { + trustCenterId: organization.trustCenter.id, + active, + }, + }, + onError: () => { + setIsActive(!active); + }, + }); + }; + + const handleNDAUpload = async (files: File[]) => { + if (!organization.trustCenter?.id) { + toast({ + title: __("Error"), + description: __("Trust center not found"), + variant: "error", + }); + return; + } + + if (files.length === 0) return; + + const file = files[0]; + + await uploadNDA({ + variables: { + input: { + trustCenterId: organization.trustCenter.id, + fileName: file.name, + file: null, + }, + }, + uploadables: { + "input.file": file, + }, + }); + }; + + const handleNDADelete = async () => { + if (!organization.trustCenter?.id) { + toast({ + title: __("Error"), + description: __("Trust center not found"), + variant: "error", + }); + return; + } + + if (!confirm(__("Are you sure you want to delete the NDA file?"))) { + return; + } + + await deleteNDA({ + variables: { + input: { + trustCenterId: organization.trustCenter.id, + }, + }, + }); + }; + + const trustCenterUrl = organization.trustCenter?.id + ? organization.customDomain?.domain + ? `https://${organization.customDomain.domain}` + : `${window.location.origin}/trust/${organization.trustCenter.id}` + : null; + + return ( +
+
+
+

{__("Trust Center Status")}

+ {isUpdating && } +
+ +
+
+

{__("Activate Trust Center")}

+

+ {__("Make your trust center publicly accessible to build customer confidence")} +

+
+ +
+ + {isActive && trustCenterUrl && ( +
+
+
+

+ {__("Your Trust Center is Live!")} +

+

+ {__("Your customers can now access your trust center at:")} +

+ + {trustCenterUrl} + +
+ +
+
+ )} + + {!isActive && ( +
+

+ {__("Trust Center is Inactive")} +

+

+ {__("Your trust center is currently not accessible to the public. Enable it to start sharing your compliance status.")} +

+
+ )} +
+
+ +
+
+

{__("Non-Disclosure Agreement")}

+ {(isUploadingNDA || isDeletingNDA) && } +
+ +
+ {!organization.trustCenter?.ndaFileName ? ( +

+ {__("Upload a Non-Disclosure Agreement that visitors must accept before accessing your trust center")} +

+ ) : (<>)} + {organization.trustCenter?.ndaFileName ? ( +
+
+
+
+

+ {organization.trustCenter.ndaFileName || __("Non-Disclosure Agreement")} +

+
+

+ {__("Visitors will need to accept this NDA before accessing your trust center")} +

+
+
+ +
+
+
+ ) : ( + + )} +
+
+
+ +
+

{__("Integrations")}

+ + edge.node) ?? []} + /> + +
+
+ ); +} diff --git a/apps/console/src/pages/organizations/trustCenter/TrustCenterPage.tsx b/apps/console/src/pages/organizations/trustCenter/TrustCenterPage.tsx index 351dc977d..a30063067 100644 --- a/apps/console/src/pages/organizations/trustCenter/TrustCenterPage.tsx +++ b/apps/console/src/pages/organizations/trustCenter/TrustCenterPage.tsx @@ -1,26 +1,23 @@ import { useTranslate } from "@probo/i18n"; import { usePageTitle } from "@probo/hooks"; import { - Button, - Card, - Checkbox, - Dropzone, PageHeader, - Spinner, - useToast, Tabs, TabLink, - TabItem, - IconTrashCan, + Badge, + IconSettingsGear2, + IconMedal, + IconCheckmark1, + IconPageTextLine, + IconFolder2, + IconStore, + IconPeopleAdd, } from "@probo/ui"; import { usePreloadedQuery, type PreloadedQuery } from "react-relay"; -import { trustCenterQuery, useUpdateTrustCenterMutation, useUploadTrustCenterNDAMutation, useDeleteTrustCenterNDAMutation } from "/hooks/graph/TrustCenterGraph"; +import { trustCenterQuery } from "/hooks/graph/TrustCenterGraph"; import type { TrustCenterGraphQuery } from "/hooks/graph/__generated__/TrustCenterGraphQuery.graphql"; -import { useState } from "react"; import { useOrganizationId } from "/hooks/useOrganizationId"; -import { Outlet, useLocation, Link } from "react-router"; -import { TrustCenterReferencesSection } from "/components/trustCenter/TrustCenterReferencesSection"; -import { SlackConnections } from "../../../components/organizations/SlackConnection"; +import { Outlet } from "react-router"; type Props = { queryRef: PreloadedQuery; @@ -28,100 +25,12 @@ type Props = { export default function TrustCenterPage({ queryRef }: Props) { const { __ } = useTranslate(); - const { toast } = useToast(); const organizationId = useOrganizationId(); - const location = useLocation(); const { organization } = usePreloadedQuery(trustCenterQuery, queryRef); - const [updateTrustCenter, isUpdating] = useUpdateTrustCenterMutation(); - const [uploadNDA, isUploadingNDA] = useUploadTrustCenterNDAMutation(); - const [deleteNDA, isDeletingNDA] = useDeleteTrustCenterNDAMutation(); - const [isActive, setIsActive] = useState(organization.trustCenter?.active || false); - usePageTitle(__("Trust Center")); - const handleToggleActive = async (active: boolean) => { - if (!organization.trustCenter?.id) { - toast({ - title: __("Error"), - description: __("Trust center not found"), - variant: "error", - }); - return; - } - - setIsActive(active); - - updateTrustCenter({ - variables: { - input: { - trustCenterId: organization.trustCenter.id, - active, - }, - }, - onError: () => { - setIsActive(!active); - }, - }); - }; - - const handleNDAUpload = async (files: File[]) => { - if (!organization.trustCenter?.id) { - toast({ - title: __("Error"), - description: __("Trust center not found"), - variant: "error", - }); - return; - } - - if (files.length === 0) return; - - const file = files[0]; - - await uploadNDA({ - variables: { - input: { - trustCenterId: organization.trustCenter.id, - fileName: file.name, - file: null, - }, - }, - uploadables: { - "input.file": file, - }, - }); - }; - - const handleNDADelete = async () => { - if (!organization.trustCenter?.id) { - toast({ - title: __("Error"), - description: __("Trust center not found"), - variant: "error", - }); - return; - } - - if (!confirm(__("Are you sure you want to delete the NDA file?"))) { - return; - } - - await deleteNDA({ - variables: { - input: { - trustCenterId: organization.trustCenter.id, - }, - }, - }); - }; - - const trustCenterUrl = organization.trustCenter?.id - ? organization.customDomain?.domain - ? `https://${organization.customDomain.domain}` - : `${window.location.origin}/trust/${organization.trustCenter.id}` - : null; - + const isActive = organization.trustCenter?.active || false; return (
@@ -130,173 +39,44 @@ export default function TrustCenterPage({ queryRef }: Props) { description={__( "Configure your public trust center to showcase your security and compliance posture." )} - /> + > + + {isActive ? __("Active") : __("Inactive")} + + -
-
-

{__("Trust Center Status")}

- {isUpdating && } -
- -
-
-

{__("Activate Trust Center")}

-

- {__("Make your trust center publicly accessible to build customer confidence")} -

-
- -
+ + + + {__("Overview")} + + + + {__("Trusted by")} + + + + {__("Audits")} + + + + {__("Documents")} + + + + {__("Files")} + + + + {__("Vendors")} + + + + {__("Access")} + + - {isActive && trustCenterUrl && ( -
-
-
-

- {__("Your Trust Center is Live!")} -

-

- {__("Your customers can now access your trust center at:")} -

- - {trustCenterUrl} - -
- -
-
- )} - - {!isActive && ( -
-

- {__("Trust Center is Inactive")} -

-

- {__("Your trust center is currently not accessible to the public. Enable it to start sharing your compliance status.")} -

-
- )} -
-
- -
-
-

{__("Non-Disclosure Agreement")}

- {(isUploadingNDA || isDeletingNDA) && } -
- -
- {!organization.trustCenter?.ndaFileName ? ( -

- {__("Upload a Non-Disclosure Agreement that visitors must accept before accessing your trust center")} -

- ) : (<>)} - {organization.trustCenter?.ndaFileName ? ( -
-
-
-
-

- {organization.trustCenter.ndaFileName || __("Non-Disclosure Agreement")} -

-
-

- {__("Visitors will need to accept this NDA before accessing your trust center")} -

-
-
- -
-
-
- ) : ( - - )} -
-
-
- - {organization.trustCenter?.id && ( - - )} - -
-

{__("Integrations")}

- - edge.node) ?? []} - /> - -
- -
- - - - {__("Audits")} - - - - {__("Vendors")} - - - {__("Documents")} - - - {__("Files")} - - - {__("Access")} - - - - -
+
); } diff --git a/apps/console/src/pages/organizations/trustCenter/TrustCenterReferencesTab.tsx b/apps/console/src/pages/organizations/trustCenter/TrustCenterReferencesTab.tsx new file mode 100644 index 000000000..df30f6c93 --- /dev/null +++ b/apps/console/src/pages/organizations/trustCenter/TrustCenterReferencesTab.tsx @@ -0,0 +1,22 @@ +import { useOutletContext } from "react-router"; +import { TrustCenterReferencesSection } from "/components/trustCenter/TrustCenterReferencesSection"; + +type ContextType = { + organization: { + trustCenter?: { + id: string; + } | null; + }; +}; + +export default function TrustCenterReferencesTab() { + const { organization } = useOutletContext(); + + return ( +
+ {organization.trustCenter?.id && ( + + )} +
+ ); +} diff --git a/apps/console/src/pages/organizations/trustCenter/TrustCenterVendorsTab.tsx b/apps/console/src/pages/organizations/trustCenter/TrustCenterVendorsTab.tsx index 2a1601553..6a57fad76 100644 --- a/apps/console/src/pages/organizations/trustCenter/TrustCenterVendorsTab.tsx +++ b/apps/console/src/pages/organizations/trustCenter/TrustCenterVendorsTab.tsx @@ -1,4 +1,5 @@ -import { Card, Spinner } from "@probo/ui"; +import { Spinner } from "@probo/ui"; +import { useTranslate } from "@probo/i18n"; import { useOutletContext } from "react-router"; import { TrustCenterVendorsCard } from "/components/trustCenter/TrustCenterVendorsCard"; import { useTrustCenterVendorUpdate } from "/hooks/graph/TrustCenterVendorGraph"; @@ -15,6 +16,7 @@ type ContextType = { }; export default function TrustCenterVendorsTab() { + const { __ } = useTranslate(); const { organization } = useOutletContext(); const [updateVendorVisibility, isUpdatingVendors] = useTrustCenterVendorUpdate(); @@ -23,17 +25,20 @@ export default function TrustCenterVendorsTab() { return (
+
+

{__("Vendors")}

+

+ {__("Manage vendor assessments and third-party risk information")} +

+
{isUpdatingVendors && }
- - - +
); } diff --git a/apps/console/src/routes/trustCenterRoutes.ts b/apps/console/src/routes/trustCenterRoutes.ts index d55f5de33..f5b765eb6 100644 --- a/apps/console/src/routes/trustCenterRoutes.ts +++ b/apps/console/src/routes/trustCenterRoutes.ts @@ -20,7 +20,14 @@ export const trustCenterRoutes = [ index: true, fallback: LinkCardSkeleton, Component: lazy( - () => import("/pages/organizations/trustCenter/TrustCenterAuditsTab") + () => import("/pages/organizations/trustCenter/TrustCenterOverviewTab") + ), + }, + { + path: "trust-by", + fallback: LinkCardSkeleton, + Component: lazy( + () => import("/pages/organizations/trustCenter/TrustCenterReferencesTab") ), }, { @@ -30,13 +37,6 @@ export const trustCenterRoutes = [ () => import("/pages/organizations/trustCenter/TrustCenterAuditsTab") ), }, - { - path: "vendors", - fallback: LinkCardSkeleton, - Component: lazy( - () => import("/pages/organizations/trustCenter/TrustCenterVendorsTab") - ), - }, { path: "documents", fallback: LinkCardSkeleton, @@ -51,6 +51,13 @@ export const trustCenterRoutes = [ () => import("/pages/organizations/trustCenter/TrustCenterFilesTab") ), }, + { + path: "vendors", + fallback: LinkCardSkeleton, + Component: lazy( + () => import("/pages/organizations/trustCenter/TrustCenterVendorsTab") + ), + }, { path: "access", fallback: LinkCardSkeleton, diff --git a/cfg/dev.yaml b/cfg/dev.yaml index 80f896cd0..132eaa2c2 100644 --- a/cfg/dev.yaml +++ b/cfg/dev.yaml @@ -42,7 +42,7 @@ probod: cookie-name: "TCT" cookie-domain: "localhost" cookie-duration: 24 - token-duration: 168 + token-duration: 720 report-url-duration: 15 token-secret: "this-is-a-secure-secret-for-trust-token-signing-at-least-32-bytes" scope: "trust_center_readonly" diff --git a/docs/CONFIGURATION.md b/docs/CONFIGURATION.md index cf4ad7a76..23a140640 100644 --- a/docs/CONFIGURATION.md +++ b/docs/CONFIGURATION.md @@ -61,7 +61,7 @@ probod: cookie-name: "TCT" cookie-domain: "localhost" cookie-duration: 24 - token-duration: 168 + token-duration: 720 report-url-duration: 15 token-secret: "trust-token-signing-secret" scope: "trust_center_readonly" @@ -397,7 +397,7 @@ Trust center cookie lifetime in hours. #### `trust-auth.token-duration` (integer) -**Default**: `168` +**Default**: `720` Trust center access token lifetime in hours. diff --git a/packages/emails/emails.go b/packages/emails/emails.go index 07c35f2e1..9544b3de2 100644 --- a/packages/emails/emails.go +++ b/packages/emails/emails.go @@ -19,7 +19,9 @@ import ( "embed" "fmt" htmltemplate "html/template" + "math" texttemplate "text/template" + "time" ) //go:embed dist @@ -148,17 +150,21 @@ func RenderFrameworkExport(hostname, fullName, downloadUrl string) (subject stri return subjectFrameworkExport, textBody, htmlBody, err } -func RenderTrustCenterAccess(hostname, fullName, organizationName, accessUrl string) (subject string, textBody string, htmlBody *string, err error) { +func RenderTrustCenterAccess(hostname, fullName, organizationName, accessUrl string, tokenDuration time.Duration) (subject string, textBody string, htmlBody *string, err error) { + durationInDays := int(math.Round(tokenDuration.Hours() / 24)) + data := struct { FullName string OrganizationName string AccessUrl string LogoURL string + DurationInDays int }{ FullName: fullName, OrganizationName: organizationName, AccessUrl: accessUrl, LogoURL: fmt.Sprintf(logoURLFormat, hostname), + DurationInDays: durationInDays, } textBody, htmlBody, err = renderEmail(trustCenterAccessTextTemplate, trustCenterAccessHTMLTemplate, data) diff --git a/packages/emails/src/TrustCenterAccess.tsx b/packages/emails/src/TrustCenterAccess.tsx index fc14764ef..02c392a0d 100644 --- a/packages/emails/src/TrustCenterAccess.tsx +++ b/packages/emails/src/TrustCenterAccess.tsx @@ -16,7 +16,7 @@ export const TrustCenterAccess = () => { - This link will expire in 7 days. + This link will expire in {'{{.DurationInDays}}'} days. ); diff --git a/packages/emails/templates/trust-center-access.txt b/packages/emails/templates/trust-center-access.txt index 0a1f6527e..dfb3c1974 100644 --- a/packages/emails/templates/trust-center-access.txt +++ b/packages/emails/templates/trust-center-access.txt @@ -6,6 +6,6 @@ You have been granted access to {{.OrganizationName}}'s Trust Center! Click the {{.AccessUrl}} -This link will expire in 7 days. +This link will expire in {{.DurationInDays}} days. Probo Inc, 490 Post St, STE 640, San Francisco, CA, 94102, US diff --git a/pkg/coredata/migrations/20251024T183816Z.sql b/pkg/coredata/migrations/20251024T183816Z.sql new file mode 100644 index 000000000..a813df0fa --- /dev/null +++ b/pkg/coredata/migrations/20251024T183816Z.sql @@ -0,0 +1,10 @@ +ALTER TABLE trust_center_accesses +ADD COLUMN last_token_expires_at TIMESTAMP WITH TIME ZONE; + +UPDATE trust_center_accesses +SET last_token_expires_at = created_at + INTERVAL '7 days' +WHERE active = true AND last_token_expires_at IS NULL; + +ALTER TABLE trust_center_document_accesses ADD COLUMN requested BOOLEAN NOT NULL DEFAULT false; +UPDATE trust_center_document_accesses SET requested = true WHERE active = false; +ALTER TABLE trust_center_document_accesses ALTER COLUMN requested DROP DEFAULT; diff --git a/pkg/coredata/trust_center_access.go b/pkg/coredata/trust_center_access.go index c0fd0bb5e..3c2a3bb2d 100644 --- a/pkg/coredata/trust_center_access.go +++ b/pkg/coredata/trust_center_access.go @@ -41,6 +41,7 @@ type ( NDAFileID *gid.GID `db:"nda_file_id"` CreatedAt time.Time `db:"created_at"` UpdatedAt time.Time `db:"updated_at"` + LastTokenExpiresAt *time.Time `db:"last_token_expires_at"` } TrustCenterAccesses []*TrustCenterAccess @@ -81,7 +82,8 @@ SELECT has_accepted_non_disclosure_agreement_metadata, nda_file_id, created_at, - updated_at + updated_at, + last_token_expires_at FROM trust_center_accesses WHERE @@ -133,7 +135,8 @@ SELECT has_accepted_non_disclosure_agreement_metadata, nda_file_id, created_at, - updated_at + updated_at, + last_token_expires_at FROM trust_center_accesses WHERE @@ -231,7 +234,8 @@ UPDATE trust_center_accesses SET updated_at = @updated_at, has_accepted_non_disclosure_agreement = @has_accepted_non_disclosure_agreement, has_accepted_non_disclosure_agreement_metadata = @has_accepted_non_disclosure_agreement_metadata, - nda_file_id = @nda_file_id + nda_file_id = @nda_file_id, + last_token_expires_at = @last_token_expires_at WHERE %s AND id = @id @@ -246,7 +250,8 @@ WHERE "updated_at": tca.UpdatedAt, "has_accepted_non_disclosure_agreement": tca.HasAcceptedNonDisclosureAgreement, "has_accepted_non_disclosure_agreement_metadata": tca.HasAcceptedNonDisclosureAgreementMetadata, - "nda_file_id": tca.NDAFileID, + "nda_file_id": tca.NDAFileID, + "last_token_expires_at": tca.LastTokenExpiresAt, } maps.Copy(args, scope.SQLArguments()) @@ -304,7 +309,8 @@ SELECT has_accepted_non_disclosure_agreement_metadata, nda_file_id, created_at, - updated_at + updated_at, + last_token_expires_at FROM trust_center_accesses WHERE diff --git a/pkg/coredata/trust_center_document_access.go b/pkg/coredata/trust_center_document_access.go index 5f048de81..39797d0c7 100644 --- a/pkg/coredata/trust_center_document_access.go +++ b/pkg/coredata/trust_center_document_access.go @@ -16,6 +16,7 @@ package coredata import ( "context" + "errors" "fmt" "maps" "time" @@ -34,13 +35,22 @@ type ( ReportID *gid.GID `db:"report_id"` TrustCenterFileID *gid.GID `db:"trust_center_file_id"` Active bool `db:"active"` + Requested bool `db:"requested"` CreatedAt time.Time `db:"created_at"` UpdatedAt time.Time `db:"updated_at"` } TrustCenterDocumentAccesses []*TrustCenterDocumentAccess + + ErrTrustCenterDocumentAccessNotFound struct { + Identifier string + } ) +func (e ErrTrustCenterDocumentAccessNotFound) Error() string { + return fmt.Sprintf("trust center document access not found: %s", e.Identifier) +} + func (tcda *TrustCenterDocumentAccess) CursorKey(orderBy TrustCenterDocumentAccessOrderField) page.CursorKey { switch orderBy { case TrustCenterDocumentAccessOrderFieldCreatedAt: @@ -64,6 +74,7 @@ SELECT report_id, trust_center_file_id, active, + requested, created_at, updated_at FROM @@ -86,6 +97,9 @@ LIMIT 1; access, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[TrustCenterDocumentAccess]) if err != nil { + if errors.Is(err, pgx.ErrNoRows) { + return &ErrTrustCenterDocumentAccessNotFound{Identifier: accessID.String()} + } return fmt.Errorf("cannot collect trust center document access: %w", err) } @@ -109,6 +123,7 @@ SELECT report_id, trust_center_file_id, active, + requested, created_at, updated_at FROM @@ -158,6 +173,7 @@ SELECT report_id, trust_center_file_id, active, + requested, created_at, updated_at FROM @@ -206,6 +222,7 @@ INSERT INTO trust_center_document_accesses ( report_id, trust_center_file_id, active, + requested, created_at, updated_at ) VALUES ( @@ -216,6 +233,7 @@ INSERT INTO trust_center_document_accesses ( @report_id, @trust_center_file_id, @active, + @requested, @created_at, @updated_at ) @@ -229,6 +247,7 @@ INSERT INTO trust_center_document_accesses ( "report_id": tcda.ReportID, "trust_center_file_id": tcda.TrustCenterFileID, "active": tcda.Active, + "requested": tcda.Requested, "created_at": tcda.CreatedAt, "updated_at": tcda.UpdatedAt, } @@ -332,7 +351,76 @@ WHERE return count, nil } -func (tcdas *TrustCenterDocumentAccesses) LoadByTrustCenterAccessID( +func (tcdas *TrustCenterDocumentAccesses) CountPendingRequestByTrustCenterAccessID( + ctx context.Context, + conn pg.Conn, + scope Scoper, + trustCenterAccessID gid.GID, +) (int, error) { + q := ` +SELECT + COUNT(id) +FROM + trust_center_document_accesses +WHERE + %s + AND trust_center_access_id = @trust_center_access_id + AND requested = true + AND active = false +` + + q = fmt.Sprintf(q, scope.SQLFragment()) + + args := pgx.StrictNamedArgs{ + "trust_center_access_id": trustCenterAccessID, + } + maps.Copy(args, scope.SQLArguments()) + + row := conn.QueryRow(ctx, q, args) + + var count int + if err := row.Scan(&count); err != nil { + return 0, fmt.Errorf("cannot scan count: %w", err) + } + + return count, nil +} + +func (tcdas *TrustCenterDocumentAccesses) CountActiveByTrustCenterAccessID( + ctx context.Context, + conn pg.Conn, + scope Scoper, + trustCenterAccessID gid.GID, +) (int, error) { + q := ` +SELECT + COUNT(id) +FROM + trust_center_document_accesses +WHERE + %s + AND trust_center_access_id = @trust_center_access_id + AND active = true +` + + q = fmt.Sprintf(q, scope.SQLFragment()) + + args := pgx.StrictNamedArgs{ + "trust_center_access_id": trustCenterAccessID, + } + maps.Copy(args, scope.SQLArguments()) + + row := conn.QueryRow(ctx, q, args) + + var count int + if err := row.Scan(&count); err != nil { + return 0, fmt.Errorf("cannot scan count: %w", err) + } + + return count, nil +} + +func (tcdas *TrustCenterDocumentAccesses) LoadAvailableByTrustCenterAccessID( ctx context.Context, conn pg.Conn, scope Scoper, @@ -340,6 +428,79 @@ func (tcdas *TrustCenterDocumentAccesses) LoadByTrustCenterAccessID( cursor *page.Cursor[TrustCenterDocumentAccessOrderField], ) error { q := ` +WITH organization AS ( + SELECT tc.organization_id + FROM trust_center_accesses tca + INNER JOIN trust_centers tc ON tca.trust_center_id = tc.id + WHERE tca.tenant_id = @tenant_id + AND tca.id = @trust_center_access_id +), +tenant_organization AS ( + SELECT o.id AS organization_id + FROM organizations o + WHERE %s +), +all_items AS ( + SELECT + d.id AS item_id, + d.id AS document_id, + NULL::text AS report_id, + NULL::text AS trust_center_file_id, + d.created_at AS item_created_at, + d.updated_at AS item_updated_at + FROM documents d, tenant_organization o + WHERE d.organization_id = o.organization_id + AND d.deleted_at IS NULL + AND d.trust_center_visibility = 'PRIVATE'::trust_center_visibility + + UNION ALL + + SELECT + r.id AS item_id, + NULL::text AS document_id, + r.id AS report_id, + NULL::text AS trust_center_file_id, + r.created_at AS item_created_at, + r.updated_at AS item_updated_at + FROM audits r, tenant_organization o + WHERE r.organization_id = o.organization_id + AND r.trust_center_visibility = 'PRIVATE'::trust_center_visibility + + UNION ALL + + SELECT + tcf.id AS item_id, + NULL::text AS document_id, + NULL::text AS report_id, + tcf.id AS trust_center_file_id, + tcf.created_at AS item_created_at, + tcf.updated_at AS item_updated_at + FROM trust_center_files tcf, tenant_organization o + WHERE tcf.organization_id = o.organization_id + AND tcf.trust_center_visibility = 'PRIVATE'::trust_center_visibility +), +final_items AS ( + SELECT + COALESCE(tcda.id, ai.item_id) AS id, + tcda.tenant_id, + @trust_center_access_id AS trust_center_access_id, + ai.document_id, + ai.report_id, + ai.trust_center_file_id, + COALESCE(tcda.active, false) AS active, + COALESCE(tcda.requested, false) AS requested, + COALESCE(tcda.created_at, ai.item_created_at) AS created_at, + COALESCE(tcda.updated_at, ai.item_updated_at) AS updated_at + FROM all_items ai + LEFT JOIN trust_center_document_accesses tcda ON ( + tcda.trust_center_access_id = @trust_center_access_id + AND ( + (tcda.document_id = ai.document_id AND ai.document_id IS NOT NULL) + OR (tcda.report_id = ai.report_id AND ai.report_id IS NOT NULL) + OR (tcda.trust_center_file_id = ai.trust_center_file_id AND ai.trust_center_file_id IS NOT NULL) + ) + ) +) SELECT id, trust_center_access_id, @@ -347,14 +508,11 @@ SELECT report_id, trust_center_file_id, active, + requested, created_at, updated_at -FROM - trust_center_document_accesses -WHERE - %s - AND trust_center_access_id = @trust_center_access_id - AND %s +FROM final_items +WHERE %s ` q = fmt.Sprintf(q, scope.SQLFragment(), cursor.SQLFragment()) @@ -394,6 +552,7 @@ SELECT report_id, trust_center_file_id, active, + requested, created_at, updated_at FROM @@ -464,10 +623,6 @@ func ActivateByDocumentIDs( documentIDs []gid.GID, updatedAt time.Time, ) error { - if len(documentIDs) == 0 { - return nil - } - q := ` UPDATE trust_center_document_accesses SET active = true, updated_at = @updated_at @@ -502,10 +657,6 @@ func ActivateByReportIDs( reportIDs []gid.GID, updatedAt time.Time, ) error { - if len(reportIDs) == 0 { - return nil - } - q := ` UPDATE trust_center_document_accesses SET active = true, updated_at = @updated_at @@ -538,6 +689,7 @@ func (tcdas TrustCenterDocumentAccesses) BulkInsertDocumentAccesses( scope Scoper, trustCenterAccessID gid.GID, documentIDs []gid.GID, + requested bool, createdAt time.Time, ) error { if len(documentIDs) == 0 { @@ -554,13 +706,15 @@ WITH document_access_data AS ( null::text AS report_id, null::text AS trust_center_file_id, false AS active, + @requested::boolean AS requested, @created_at::timestamptz AS created_at, @updated_at::timestamptz AS updated_at ) INSERT INTO trust_center_document_accesses ( - id, tenant_id, trust_center_access_id, document_id, report_id, trust_center_file_id, active, created_at, updated_at + id, tenant_id, trust_center_access_id, document_id, report_id, trust_center_file_id, active, requested, created_at, updated_at ) SELECT * FROM document_access_data +ON CONFLICT DO NOTHING ` args := pgx.StrictNamedArgs{ @@ -568,6 +722,7 @@ SELECT * FROM document_access_data "trust_center_access_id": trustCenterAccessID, "document_ids": documentIDs, "trust_center_document_access_entity_type": TrustCenterDocumentAccessEntityType, + "requested": requested, "created_at": createdAt, "updated_at": createdAt, } @@ -585,6 +740,7 @@ func (tcdas TrustCenterDocumentAccesses) BulkInsertReportAccesses( scope Scoper, trustCenterAccessID gid.GID, reportIDs []gid.GID, + requested bool, createdAt time.Time, ) error { if len(reportIDs) == 0 { @@ -601,13 +757,15 @@ WITH report_access_data AS ( unnest(@report_ids::text[]) AS report_id, null::text AS trust_center_file_id, false AS active, + @requested::boolean AS requested, @created_at::timestamptz AS created_at, @updated_at::timestamptz AS updated_at ) INSERT INTO trust_center_document_accesses ( - id, tenant_id, trust_center_access_id, document_id, report_id, trust_center_file_id, active, created_at, updated_at + id, tenant_id, trust_center_access_id, document_id, report_id, trust_center_file_id, active, requested, created_at, updated_at ) SELECT * FROM report_access_data +ON CONFLICT DO NOTHING ` args := pgx.StrictNamedArgs{ @@ -641,6 +799,7 @@ SELECT report_id, trust_center_file_id, active, + requested, created_at, updated_at FROM @@ -715,6 +874,7 @@ func (tcdas TrustCenterDocumentAccesses) BulkInsertTrustCenterFileAccesses( scope Scoper, trustCenterAccessID gid.GID, trustCenterFileIDs []gid.GID, + requested bool, createdAt time.Time, ) error { q := ` @@ -727,13 +887,15 @@ WITH trust_center_file_access_data AS ( null::text AS report_id, unnest(@trust_center_file_ids::text[]) AS trust_center_file_id, false AS active, + @requested::boolean AS requested, @created_at::timestamptz AS created_at, @updated_at::timestamptz AS updated_at ) INSERT INTO trust_center_document_accesses ( - id, tenant_id, trust_center_access_id, document_id, report_id, trust_center_file_id, active, created_at, updated_at + id, tenant_id, trust_center_access_id, document_id, report_id, trust_center_file_id, active, requested, created_at, updated_at ) SELECT * FROM trust_center_file_access_data +ON CONFLICT DO NOTHING ` args := pgx.StrictNamedArgs{ @@ -741,6 +903,7 @@ SELECT * FROM trust_center_file_access_data "trust_center_document_access_entity_type": TrustCenterDocumentAccessEntityType, "trust_center_access_id": trustCenterAccessID, "trust_center_file_ids": trustCenterFileIDs, + "requested": requested, "created_at": createdAt, "updated_at": createdAt, } diff --git a/pkg/probo/trust_center_access_service.go b/pkg/probo/trust_center_access_service.go index 56ac7db3d..35a41a566 100644 --- a/pkg/probo/trust_center_access_service.go +++ b/pkg/probo/trust_center_access_service.go @@ -80,7 +80,7 @@ func (s TrustCenterAccessService) ListForTrustCenterID( return page.NewPage(accesses, cursor), nil } -func (s TrustCenterAccessService) ListDocumentAccesses( +func (s TrustCenterAccessService) ListAvailableDocumentAccesses( ctx context.Context, trustCenterAccessID gid.GID, cursor *page.Cursor[coredata.TrustCenterDocumentAccessOrderField], @@ -90,7 +90,7 @@ func (s TrustCenterAccessService) ListDocumentAccesses( err := s.svc.pg.WithConn( ctx, func(conn pg.Conn) error { - return documentAccesses.LoadByTrustCenterAccessID(ctx, conn, s.svc.scope, trustCenterAccessID, cursor) + return documentAccesses.LoadAvailableByTrustCenterAccessID(ctx, conn, s.svc.scope, trustCenterAccessID, cursor) }, ) @@ -163,6 +163,50 @@ func (s TrustCenterAccessService) CountDocumentAccesses( return count, nil } +func (s TrustCenterAccessService) CountPendingRequestDocumentAccesses( + ctx context.Context, + trustCenterAccessID gid.GID, +) (int, error) { + var count int + err := s.svc.pg.WithConn( + ctx, + func(conn pg.Conn) error { + var documentAccesses coredata.TrustCenterDocumentAccesses + var err error + count, err = documentAccesses.CountPendingRequestByTrustCenterAccessID(ctx, conn, s.svc.scope, trustCenterAccessID) + return err + }, + ) + + if err != nil { + return 0, err + } + + return count, nil +} + +func (s TrustCenterAccessService) CountActiveDocumentAccesses( + ctx context.Context, + trustCenterAccessID gid.GID, +) (int, error) { + var count int + err := s.svc.pg.WithConn( + ctx, + func(conn pg.Conn) error { + var documentAccesses coredata.TrustCenterDocumentAccesses + var err error + count, err = documentAccesses.CountActiveByTrustCenterAccessID(ctx, conn, s.svc.scope, trustCenterAccessID) + return err + }, + ) + + if err != nil { + return 0, err + } + + return count, nil +} + func (s TrustCenterAccessService) ValidateToken( ctx context.Context, tokenString string, @@ -210,50 +254,6 @@ func (s TrustCenterAccessService) Create( err := s.svc.pg.WithTx( ctx, func(tx pg.Conn) error { - trustCenter := &coredata.TrustCenter{} - if err := trustCenter.LoadByID(ctx, tx, s.svc.scope, req.TrustCenterID); err != nil { - return fmt.Errorf("cannot load trust center: %w", err) - } - organizationID := trustCenter.OrganizationID - - documentIDs := []gid.GID{} - reportIDs := []gid.GID{} - trustCenterFileIDs := []gid.GID{} - - var allDocuments coredata.Documents - filter := coredata.NewDocumentTrustCenterFilter() - - if err := allDocuments.LoadAllByOrganizationID(ctx, tx, s.svc.scope, organizationID, filter); err != nil { - return fmt.Errorf("cannot list documents: %w", err) - } - - for _, doc := range allDocuments { - documentIDs = append(documentIDs, doc.ID) - } - - var allAudits coredata.Audits - auditFilter := coredata.NewAuditTrustCenterFilter() - - if err := allAudits.LoadAllByOrganizationID(ctx, tx, s.svc.scope, organizationID, auditFilter); err != nil { - return fmt.Errorf("cannot list audits: %w", err) - } - - for _, audit := range allAudits { - if audit.ReportID != nil { - reportIDs = append(reportIDs, *audit.ReportID) - } - } - - var allTrustCenterFiles coredata.TrustCenterFiles - - if err := allTrustCenterFiles.LoadAllByOrganizationID(ctx, tx, s.svc.scope, organizationID); err != nil { - return fmt.Errorf("cannot list trust center files: %w", err) - } - - for _, file := range allTrustCenterFiles { - trustCenterFileIDs = append(trustCenterFileIDs, file.ID) - } - access = &coredata.TrustCenterAccess{ ID: gid.New(s.svc.scope.GetTenantID(), coredata.TrustCenterAccessEntityType), TenantID: s.svc.scope.GetTenantID(), @@ -270,19 +270,6 @@ func (s TrustCenterAccessService) Create( return fmt.Errorf("cannot insert trust center access: %w", err) } - var documentAccesses coredata.TrustCenterDocumentAccesses - if err := documentAccesses.BulkInsertDocumentAccesses(ctx, tx, s.svc.scope, access.ID, documentIDs, now); err != nil { - return fmt.Errorf("cannot bulk insert trust center document accesses: %w", err) - } - - if err := documentAccesses.BulkInsertReportAccesses(ctx, tx, s.svc.scope, access.ID, reportIDs, now); err != nil { - return fmt.Errorf("cannot bulk insert trust center report accesses: %w", err) - } - - if err := documentAccesses.BulkInsertTrustCenterFileAccesses(ctx, tx, s.svc.scope, access.ID, trustCenterFileIDs, now); err != nil { - return fmt.Errorf("cannot bulk insert trust center file accesses: %w", err) - } - return nil }, ) @@ -328,28 +315,8 @@ func (s TrustCenterAccessService) Update( return fmt.Errorf("cannot update trust center access: %w", err) } - if req.DocumentIDs != nil || req.ReportIDs != nil || req.TrustCenterFileIDs != nil { - if err := coredata.DeactivateByTrustCenterAccessID(ctx, tx, s.svc.scope, access.ID, now); err != nil { - return fmt.Errorf("cannot deactivate existing document accesses: %w", err) - } - - if req.DocumentIDs != nil { - if err := coredata.ActivateByDocumentIDs(ctx, tx, s.svc.scope, access.ID, req.DocumentIDs, now); err != nil { - return fmt.Errorf("cannot activate document accesses: %w", err) - } - } - - if req.ReportIDs != nil { - if err := coredata.ActivateByReportIDs(ctx, tx, s.svc.scope, access.ID, req.ReportIDs, now); err != nil { - return fmt.Errorf("cannot activate report accesses: %w", err) - } - } - - if req.TrustCenterFileIDs != nil { - if err := coredata.ActivateByTrustCenterFileIDs(ctx, tx, s.svc.scope, access.ID, req.TrustCenterFileIDs, now); err != nil { - return fmt.Errorf("cannot activate trust center file accesses: %w", err) - } - } + if err := s.upsertDocumentAccesses(ctx, tx, access.ID, req.DocumentIDs, req.ReportIDs, req.TrustCenterFileIDs, now); err != nil { + return fmt.Errorf("cannot upsert document accesses: %w", err) } if shouldSendEmail { @@ -393,6 +360,56 @@ func (s TrustCenterAccessService) Delete( return err } +func (s TrustCenterAccessService) upsertDocumentAccesses( + ctx context.Context, + tx pg.Conn, + accessID gid.GID, + documentIDs []gid.GID, + reportIDs []gid.GID, + trustCenterFileIDs []gid.GID, + now time.Time, +) error { + if documentIDs == nil && reportIDs == nil && trustCenterFileIDs == nil { + return nil + } + + if err := coredata.DeactivateByTrustCenterAccessID(ctx, tx, s.svc.scope, accessID, now); err != nil { + return fmt.Errorf("cannot deactivate existing document accesses: %w", err) + } + + if documentIDs != nil { + var documentAccesses coredata.TrustCenterDocumentAccesses + if err := documentAccesses.BulkInsertDocumentAccesses(ctx, tx, s.svc.scope, accessID, documentIDs, false, now); err != nil { + return fmt.Errorf("cannot create document accesses: %w", err) + } + if err := coredata.ActivateByDocumentIDs(ctx, tx, s.svc.scope, accessID, documentIDs, now); err != nil { + return fmt.Errorf("cannot activate document accesses: %w", err) + } + } + + if reportIDs != nil { + var documentAccesses coredata.TrustCenterDocumentAccesses + if err := documentAccesses.BulkInsertReportAccesses(ctx, tx, s.svc.scope, accessID, reportIDs, false, now); err != nil { + return fmt.Errorf("cannot create report accesses: %w", err) + } + if err := coredata.ActivateByReportIDs(ctx, tx, s.svc.scope, accessID, reportIDs, now); err != nil { + return fmt.Errorf("cannot activate report accesses: %w", err) + } + } + + if trustCenterFileIDs != nil { + var documentAccesses coredata.TrustCenterDocumentAccesses + if err := documentAccesses.BulkInsertTrustCenterFileAccesses(ctx, tx, s.svc.scope, accessID, trustCenterFileIDs, false, now); err != nil { + return fmt.Errorf("cannot create trust center file accesses: %w", err) + } + if err := coredata.ActivateByTrustCenterFileIDs(ctx, tx, s.svc.scope, accessID, trustCenterFileIDs, now); err != nil { + return fmt.Errorf("cannot activate trust center file accesses: %w", err) + } + } + + return nil +} + func (s TrustCenterAccessService) sendAccessEmail(ctx context.Context, tx pg.Conn, access *coredata.TrustCenterAccess) error { accessToken, err := statelesstoken.NewToken( s.svc.trustConfig.TokenSecret, @@ -445,6 +462,15 @@ func (s TrustCenterAccessService) sendAccessEmail(ctx context.Context, tx pg.Con }.Encode(), } + now := time.Now() + expiresAt := now.Add(s.svc.trustConfig.TokenDuration) + access.LastTokenExpiresAt = &expiresAt + access.UpdatedAt = now + + if err := access.Update(ctx, tx, s.svc.scope); err != nil { + return fmt.Errorf("cannot update trust center access with expiration: %w", err) + } + return s.sendTrustCenterAccessEmail(ctx, tx, access.Name, access.Email, organization.Name, accessURL.String()) } @@ -461,6 +487,7 @@ func (s TrustCenterAccessService) sendTrustCenterAccessEmail( name, companyName, accessURL, + s.svc.trustConfig.TokenDuration, ) if err != nil { return fmt.Errorf("cannot render trust center access email: %w", err) diff --git a/pkg/probo/trust_center_file_service.go b/pkg/probo/trust_center_file_service.go index 4c13457f9..89cf327b2 100644 --- a/pkg/probo/trust_center_file_service.go +++ b/pkg/probo/trust_center_file_service.go @@ -54,10 +54,6 @@ type ( TrustCenterVisibility *coredata.TrustCenterVisibility } - GetTrustCenterFileRequest struct { - ID gid.GID - } - DeleteTrustCenterFileRequest struct { ID gid.GID } @@ -114,21 +110,18 @@ func (s TrustCenterFileService) CountForOrganizationID( func (s TrustCenterFileService) Get( ctx context.Context, - req *GetTrustCenterFileRequest, + id gid.GID, ) (*coredata.TrustCenterFile, error) { var file *coredata.TrustCenterFile - err := s.svc.pg.WithConn( - ctx, - func(conn pg.Conn) error { - file = &coredata.TrustCenterFile{} - if err := file.LoadByID(ctx, conn, s.svc.scope, req.ID); err != nil { - return fmt.Errorf("cannot load trust center file: %w", err) - } + err := s.svc.pg.WithConn(ctx, func(conn pg.Conn) error { + file = &coredata.TrustCenterFile{} + if err := file.LoadByID(ctx, conn, s.svc.scope, id); err != nil { + return fmt.Errorf("cannot load trust center file: %w", err) + } - return nil - }, - ) + return nil + }) if err != nil { return nil, err diff --git a/pkg/probod/probod.go b/pkg/probod/probod.go index 003e8805f..a4822a261 100644 --- a/pkg/probod/probod.go +++ b/pkg/probod/probod.go @@ -123,7 +123,7 @@ func New() *Implm { CookieName: "TCT", CookieDomain: "localhost", CookieDuration: 24, - TokenDuration: 168, + TokenDuration: 720, ReportURLDuration: 15, TokenSecret: "this-is-a-secure-secret-for-trust-token-signing-at-least-32-bytes", Scope: "trust_center_readonly", diff --git a/pkg/server/api/console/v1/schema.graphql b/pkg/server/api/console/v1/schema.graphql index 295461611..0453145ca 100644 --- a/pkg/server/api/console/v1/schema.graphql +++ b/pkg/server/api/console/v1/schema.graphql @@ -2407,8 +2407,11 @@ type TrustCenterAccess implements Node { hasAcceptedNonDisclosureAgreement: Boolean! createdAt: Datetime! updatedAt: Datetime! + lastTokenExpiresAt: Datetime + pendingRequestCount: Int! @goField(forceResolver: true) + activeCount: Int! @goField(forceResolver: true) - documentAccesses( + availableDocumentAccesses( first: Int after: CursorKey last: Int @@ -2417,12 +2420,12 @@ type TrustCenterAccess implements Node { ): TrustCenterDocumentAccessConnection! @goField(forceResolver: true) } -type TrustCenterDocumentAccess implements Node { - id: ID! +type TrustCenterDocumentAccess + @goModel( + model: "github.com/getprobo/probo/pkg/server/api/console/v1/types.TrustCenterDocumentAccess" + ) { active: Boolean! - createdAt: Datetime! - updatedAt: Datetime! - trustCenterAccess: TrustCenterAccess! @goField(forceResolver: true) + requested: Boolean! document: Document @goField(forceResolver: true) report: Report @goField(forceResolver: true) trustCenterFile: TrustCenterFile @goField(forceResolver: true) diff --git a/pkg/server/api/console/v1/schema/schema.go b/pkg/server/api/console/v1/schema/schema.go index 1f5da4d1d..1a8467ae7 100644 --- a/pkg/server/api/console/v1/schema/schema.go +++ b/pkg/server/api/console/v1/schema/schema.go @@ -1287,12 +1287,15 @@ type ComplexityRoot struct { TrustCenterAccess struct { Active func(childComplexity int) int + ActiveCount func(childComplexity int) int + AvailableDocumentAccesses func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrderBy[coredata.TrustCenterDocumentAccessOrderField]) int CreatedAt func(childComplexity int) int - DocumentAccesses func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrderBy[coredata.TrustCenterDocumentAccessOrderField]) int Email func(childComplexity int) int HasAcceptedNonDisclosureAgreement func(childComplexity int) int ID func(childComplexity int) int + LastTokenExpiresAt func(childComplexity int) int Name func(childComplexity int) int + PendingRequestCount func(childComplexity int) int UpdatedAt func(childComplexity int) int } @@ -1312,14 +1315,11 @@ type ComplexityRoot struct { } TrustCenterDocumentAccess struct { - Active func(childComplexity int) int - CreatedAt func(childComplexity int) int - Document func(childComplexity int) int - ID func(childComplexity int) int - Report func(childComplexity int) int - TrustCenterAccess func(childComplexity int) int - TrustCenterFile func(childComplexity int) int - UpdatedAt func(childComplexity int) int + Active func(childComplexity int) int + Document func(childComplexity int) int + Report func(childComplexity int) int + Requested func(childComplexity int) int + TrustCenterFile func(childComplexity int) int } TrustCenterDocumentAccessConnection struct { @@ -2017,10 +2017,11 @@ type TrustCenterResolver interface { References(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrderBy[coredata.TrustCenterReferenceOrderField]) (*types.TrustCenterReferenceConnection, error) } type TrustCenterAccessResolver interface { - DocumentAccesses(ctx context.Context, obj *types.TrustCenterAccess, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrderBy[coredata.TrustCenterDocumentAccessOrderField]) (*types.TrustCenterDocumentAccessConnection, error) + PendingRequestCount(ctx context.Context, obj *types.TrustCenterAccess) (int, error) + ActiveCount(ctx context.Context, obj *types.TrustCenterAccess) (int, error) + AvailableDocumentAccesses(ctx context.Context, obj *types.TrustCenterAccess, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrderBy[coredata.TrustCenterDocumentAccessOrderField]) (*types.TrustCenterDocumentAccessConnection, error) } type TrustCenterDocumentAccessResolver interface { - TrustCenterAccess(ctx context.Context, obj *types.TrustCenterDocumentAccess) (*types.TrustCenterAccess, error) Document(ctx context.Context, obj *types.TrustCenterDocumentAccess) (*types.Document, error) Report(ctx context.Context, obj *types.TrustCenterDocumentAccess) (*types.Report, error) TrustCenterFile(ctx context.Context, obj *types.TrustCenterDocumentAccess) (*types.TrustCenterFile, error) @@ -7609,6 +7610,25 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin return e.complexity.TrustCenterAccess.Active(childComplexity), true + case "TrustCenterAccess.activeCount": + if e.complexity.TrustCenterAccess.ActiveCount == nil { + break + } + + return e.complexity.TrustCenterAccess.ActiveCount(childComplexity), true + + case "TrustCenterAccess.availableDocumentAccesses": + if e.complexity.TrustCenterAccess.AvailableDocumentAccesses == nil { + break + } + + args, err := ec.field_TrustCenterAccess_availableDocumentAccesses_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.TrustCenterAccess.AvailableDocumentAccesses(childComplexity, args["first"].(*int), args["after"].(*page.CursorKey), args["last"].(*int), args["before"].(*page.CursorKey), args["orderBy"].(*types.OrderBy[coredata.TrustCenterDocumentAccessOrderField])), true + case "TrustCenterAccess.createdAt": if e.complexity.TrustCenterAccess.CreatedAt == nil { break @@ -7616,18 +7636,6 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin return e.complexity.TrustCenterAccess.CreatedAt(childComplexity), true - case "TrustCenterAccess.documentAccesses": - if e.complexity.TrustCenterAccess.DocumentAccesses == nil { - break - } - - args, err := ec.field_TrustCenterAccess_documentAccesses_args(ctx, rawArgs) - if err != nil { - return 0, false - } - - return e.complexity.TrustCenterAccess.DocumentAccesses(childComplexity, args["first"].(*int), args["after"].(*page.CursorKey), args["last"].(*int), args["before"].(*page.CursorKey), args["orderBy"].(*types.OrderBy[coredata.TrustCenterDocumentAccessOrderField])), true - case "TrustCenterAccess.email": if e.complexity.TrustCenterAccess.Email == nil { break @@ -7649,6 +7657,13 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin return e.complexity.TrustCenterAccess.ID(childComplexity), true + case "TrustCenterAccess.lastTokenExpiresAt": + if e.complexity.TrustCenterAccess.LastTokenExpiresAt == nil { + break + } + + return e.complexity.TrustCenterAccess.LastTokenExpiresAt(childComplexity), true + case "TrustCenterAccess.name": if e.complexity.TrustCenterAccess.Name == nil { break @@ -7656,6 +7671,13 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin return e.complexity.TrustCenterAccess.Name(childComplexity), true + case "TrustCenterAccess.pendingRequestCount": + if e.complexity.TrustCenterAccess.PendingRequestCount == nil { + break + } + + return e.complexity.TrustCenterAccess.PendingRequestCount(childComplexity), true + case "TrustCenterAccess.updatedAt": if e.complexity.TrustCenterAccess.UpdatedAt == nil { break @@ -7712,13 +7734,6 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin return e.complexity.TrustCenterDocumentAccess.Active(childComplexity), true - case "TrustCenterDocumentAccess.createdAt": - if e.complexity.TrustCenterDocumentAccess.CreatedAt == nil { - break - } - - return e.complexity.TrustCenterDocumentAccess.CreatedAt(childComplexity), true - case "TrustCenterDocumentAccess.document": if e.complexity.TrustCenterDocumentAccess.Document == nil { break @@ -7726,13 +7741,6 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin return e.complexity.TrustCenterDocumentAccess.Document(childComplexity), true - case "TrustCenterDocumentAccess.id": - if e.complexity.TrustCenterDocumentAccess.ID == nil { - break - } - - return e.complexity.TrustCenterDocumentAccess.ID(childComplexity), true - case "TrustCenterDocumentAccess.report": if e.complexity.TrustCenterDocumentAccess.Report == nil { break @@ -7740,12 +7748,12 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin return e.complexity.TrustCenterDocumentAccess.Report(childComplexity), true - case "TrustCenterDocumentAccess.trustCenterAccess": - if e.complexity.TrustCenterDocumentAccess.TrustCenterAccess == nil { + case "TrustCenterDocumentAccess.requested": + if e.complexity.TrustCenterDocumentAccess.Requested == nil { break } - return e.complexity.TrustCenterDocumentAccess.TrustCenterAccess(childComplexity), true + return e.complexity.TrustCenterDocumentAccess.Requested(childComplexity), true case "TrustCenterDocumentAccess.trustCenterFile": if e.complexity.TrustCenterDocumentAccess.TrustCenterFile == nil { @@ -7754,13 +7762,6 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin return e.complexity.TrustCenterDocumentAccess.TrustCenterFile(childComplexity), true - case "TrustCenterDocumentAccess.updatedAt": - if e.complexity.TrustCenterDocumentAccess.UpdatedAt == nil { - break - } - - return e.complexity.TrustCenterDocumentAccess.UpdatedAt(childComplexity), true - case "TrustCenterDocumentAccessConnection.edges": if e.complexity.TrustCenterDocumentAccessConnection.Edges == nil { break @@ -11724,8 +11725,11 @@ type TrustCenterAccess implements Node { hasAcceptedNonDisclosureAgreement: Boolean! createdAt: Datetime! updatedAt: Datetime! + lastTokenExpiresAt: Datetime + pendingRequestCount: Int! @goField(forceResolver: true) + activeCount: Int! @goField(forceResolver: true) - documentAccesses( + availableDocumentAccesses( first: Int after: CursorKey last: Int @@ -11734,12 +11738,12 @@ type TrustCenterAccess implements Node { ): TrustCenterDocumentAccessConnection! @goField(forceResolver: true) } -type TrustCenterDocumentAccess implements Node { - id: ID! +type TrustCenterDocumentAccess + @goModel( + model: "github.com/getprobo/probo/pkg/server/api/console/v1/types.TrustCenterDocumentAccess" + ) { active: Boolean! - createdAt: Datetime! - updatedAt: Datetime! - trustCenterAccess: TrustCenterAccess! @goField(forceResolver: true) + requested: Boolean! document: Document @goField(forceResolver: true) report: Report @goField(forceResolver: true) trustCenterFile: TrustCenterFile @goField(forceResolver: true) @@ -21371,37 +21375,37 @@ func (ec *executionContext) field_Task_evidences_argsOrderBy( return zeroVal, nil } -func (ec *executionContext) field_TrustCenterAccess_documentAccesses_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { +func (ec *executionContext) field_TrustCenterAccess_availableDocumentAccesses_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_TrustCenterAccess_documentAccesses_argsFirst(ctx, rawArgs) + arg0, err := ec.field_TrustCenterAccess_availableDocumentAccesses_argsFirst(ctx, rawArgs) if err != nil { return nil, err } args["first"] = arg0 - arg1, err := ec.field_TrustCenterAccess_documentAccesses_argsAfter(ctx, rawArgs) + arg1, err := ec.field_TrustCenterAccess_availableDocumentAccesses_argsAfter(ctx, rawArgs) if err != nil { return nil, err } args["after"] = arg1 - arg2, err := ec.field_TrustCenterAccess_documentAccesses_argsLast(ctx, rawArgs) + arg2, err := ec.field_TrustCenterAccess_availableDocumentAccesses_argsLast(ctx, rawArgs) if err != nil { return nil, err } args["last"] = arg2 - arg3, err := ec.field_TrustCenterAccess_documentAccesses_argsBefore(ctx, rawArgs) + arg3, err := ec.field_TrustCenterAccess_availableDocumentAccesses_argsBefore(ctx, rawArgs) if err != nil { return nil, err } args["before"] = arg3 - arg4, err := ec.field_TrustCenterAccess_documentAccesses_argsOrderBy(ctx, rawArgs) + arg4, err := ec.field_TrustCenterAccess_availableDocumentAccesses_argsOrderBy(ctx, rawArgs) if err != nil { return nil, err } args["orderBy"] = arg4 return args, nil } -func (ec *executionContext) field_TrustCenterAccess_documentAccesses_argsFirst( +func (ec *executionContext) field_TrustCenterAccess_availableDocumentAccesses_argsFirst( ctx context.Context, rawArgs map[string]any, ) (*int, error) { @@ -21414,7 +21418,7 @@ func (ec *executionContext) field_TrustCenterAccess_documentAccesses_argsFirst( return zeroVal, nil } -func (ec *executionContext) field_TrustCenterAccess_documentAccesses_argsAfter( +func (ec *executionContext) field_TrustCenterAccess_availableDocumentAccesses_argsAfter( ctx context.Context, rawArgs map[string]any, ) (*page.CursorKey, error) { @@ -21427,7 +21431,7 @@ func (ec *executionContext) field_TrustCenterAccess_documentAccesses_argsAfter( return zeroVal, nil } -func (ec *executionContext) field_TrustCenterAccess_documentAccesses_argsLast( +func (ec *executionContext) field_TrustCenterAccess_availableDocumentAccesses_argsLast( ctx context.Context, rawArgs map[string]any, ) (*int, error) { @@ -21440,7 +21444,7 @@ func (ec *executionContext) field_TrustCenterAccess_documentAccesses_argsLast( return zeroVal, nil } -func (ec *executionContext) field_TrustCenterAccess_documentAccesses_argsBefore( +func (ec *executionContext) field_TrustCenterAccess_availableDocumentAccesses_argsBefore( ctx context.Context, rawArgs map[string]any, ) (*page.CursorKey, error) { @@ -21453,7 +21457,7 @@ func (ec *executionContext) field_TrustCenterAccess_documentAccesses_argsBefore( return zeroVal, nil } -func (ec *executionContext) field_TrustCenterAccess_documentAccesses_argsOrderBy( +func (ec *executionContext) field_TrustCenterAccess_availableDocumentAccesses_argsOrderBy( ctx context.Context, rawArgs map[string]any, ) (*types.OrderBy[coredata.TrustCenterDocumentAccessOrderField], error) { @@ -57622,8 +57626,8 @@ func (ec *executionContext) fieldContext_TrustCenterAccess_updatedAt(_ context.C return fc, nil } -func (ec *executionContext) _TrustCenterAccess_documentAccesses(ctx context.Context, field graphql.CollectedField, obj *types.TrustCenterAccess) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_TrustCenterAccess_documentAccesses(ctx, field) +func (ec *executionContext) _TrustCenterAccess_lastTokenExpiresAt(ctx context.Context, field graphql.CollectedField, obj *types.TrustCenterAccess) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_TrustCenterAccess_lastTokenExpiresAt(ctx, field) if err != nil { return graphql.Null } @@ -57636,7 +57640,136 @@ func (ec *executionContext) _TrustCenterAccess_documentAccesses(ctx context.Cont }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.TrustCenterAccess().DocumentAccesses(rctx, obj, fc.Args["first"].(*int), fc.Args["after"].(*page.CursorKey), fc.Args["last"].(*int), fc.Args["before"].(*page.CursorKey), fc.Args["orderBy"].(*types.OrderBy[coredata.TrustCenterDocumentAccessOrderField])) + return obj.LastTokenExpiresAt, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*time.Time) + fc.Result = res + return ec.marshalODatetime2ᚖtimeᚐTime(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_TrustCenterAccess_lastTokenExpiresAt(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "TrustCenterAccess", + 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) _TrustCenterAccess_pendingRequestCount(ctx context.Context, field graphql.CollectedField, obj *types.TrustCenterAccess) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_TrustCenterAccess_pendingRequestCount(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.TrustCenterAccess().PendingRequestCount(rctx, obj) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_TrustCenterAccess_pendingRequestCount(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "TrustCenterAccess", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _TrustCenterAccess_activeCount(ctx context.Context, field graphql.CollectedField, obj *types.TrustCenterAccess) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_TrustCenterAccess_activeCount(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.TrustCenterAccess().ActiveCount(rctx, obj) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_TrustCenterAccess_activeCount(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "TrustCenterAccess", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _TrustCenterAccess_availableDocumentAccesses(ctx context.Context, field graphql.CollectedField, obj *types.TrustCenterAccess) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_TrustCenterAccess_availableDocumentAccesses(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.TrustCenterAccess().AvailableDocumentAccesses(rctx, obj, fc.Args["first"].(*int), fc.Args["after"].(*page.CursorKey), fc.Args["last"].(*int), fc.Args["before"].(*page.CursorKey), fc.Args["orderBy"].(*types.OrderBy[coredata.TrustCenterDocumentAccessOrderField])) }) if err != nil { ec.Error(ctx, err) @@ -57653,7 +57786,7 @@ func (ec *executionContext) _TrustCenterAccess_documentAccesses(ctx context.Cont return ec.marshalNTrustCenterDocumentAccessConnection2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐTrustCenterDocumentAccessConnection(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_TrustCenterAccess_documentAccesses(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_TrustCenterAccess_availableDocumentAccesses(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "TrustCenterAccess", Field: field, @@ -57678,7 +57811,7 @@ func (ec *executionContext) fieldContext_TrustCenterAccess_documentAccesses(ctx } }() ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_TrustCenterAccess_documentAccesses_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + if fc.Args, err = ec.field_TrustCenterAccess_availableDocumentAccesses_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { ec.Error(ctx, err) return fc, err } @@ -57886,8 +58019,14 @@ func (ec *executionContext) fieldContext_TrustCenterAccessEdge_node(_ context.Co return ec.fieldContext_TrustCenterAccess_createdAt(ctx, field) case "updatedAt": return ec.fieldContext_TrustCenterAccess_updatedAt(ctx, field) - case "documentAccesses": - return ec.fieldContext_TrustCenterAccess_documentAccesses(ctx, field) + case "lastTokenExpiresAt": + return ec.fieldContext_TrustCenterAccess_lastTokenExpiresAt(ctx, field) + case "pendingRequestCount": + return ec.fieldContext_TrustCenterAccess_pendingRequestCount(ctx, field) + case "activeCount": + return ec.fieldContext_TrustCenterAccess_activeCount(ctx, field) + case "availableDocumentAccesses": + return ec.fieldContext_TrustCenterAccess_availableDocumentAccesses(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type TrustCenterAccess", field.Name) }, @@ -57999,50 +58138,6 @@ func (ec *executionContext) fieldContext_TrustCenterConnection_pageInfo(_ contex return fc, nil } -func (ec *executionContext) _TrustCenterDocumentAccess_id(ctx context.Context, field graphql.CollectedField, obj *types.TrustCenterDocumentAccess) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_TrustCenterDocumentAccess_id(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { - ctx = rctx // use context from middleware stack in children - return obj.ID, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(gid.GID) - fc.Result = res - return ec.marshalNID2githubᚗcomᚋgetproboᚋproboᚋpkgᚋgidᚐGID(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_TrustCenterDocumentAccess_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "TrustCenterDocumentAccess", - 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) _TrustCenterDocumentAccess_active(ctx context.Context, field graphql.CollectedField, obj *types.TrustCenterDocumentAccess) (ret graphql.Marshaler) { fc, err := ec.fieldContext_TrustCenterDocumentAccess_active(ctx, field) if err != nil { @@ -58087,8 +58182,8 @@ func (ec *executionContext) fieldContext_TrustCenterDocumentAccess_active(_ cont return fc, nil } -func (ec *executionContext) _TrustCenterDocumentAccess_createdAt(ctx context.Context, field graphql.CollectedField, obj *types.TrustCenterDocumentAccess) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_TrustCenterDocumentAccess_createdAt(ctx, field) +func (ec *executionContext) _TrustCenterDocumentAccess_requested(ctx context.Context, field graphql.CollectedField, obj *types.TrustCenterDocumentAccess) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_TrustCenterDocumentAccess_requested(ctx, field) if err != nil { return graphql.Null } @@ -58101,7 +58196,7 @@ func (ec *executionContext) _TrustCenterDocumentAccess_createdAt(ctx context.Con }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.CreatedAt, nil + return obj.Requested, nil }) if err != nil { ec.Error(ctx, err) @@ -58113,125 +58208,19 @@ func (ec *executionContext) _TrustCenterDocumentAccess_createdAt(ctx context.Con } return graphql.Null } - res := resTmp.(time.Time) + res := resTmp.(bool) fc.Result = res - return ec.marshalNDatetime2timeᚐTime(ctx, field.Selections, res) + return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_TrustCenterDocumentAccess_createdAt(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_TrustCenterDocumentAccess_requested(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "TrustCenterDocumentAccess", 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) _TrustCenterDocumentAccess_updatedAt(ctx context.Context, field graphql.CollectedField, obj *types.TrustCenterDocumentAccess) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_TrustCenterDocumentAccess_updatedAt(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { - ctx = rctx // use context from middleware stack in children - return obj.UpdatedAt, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(time.Time) - fc.Result = res - return ec.marshalNDatetime2timeᚐTime(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_TrustCenterDocumentAccess_updatedAt(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "TrustCenterDocumentAccess", - 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) _TrustCenterDocumentAccess_trustCenterAccess(ctx context.Context, field graphql.CollectedField, obj *types.TrustCenterDocumentAccess) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_TrustCenterDocumentAccess_trustCenterAccess(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.TrustCenterDocumentAccess().TrustCenterAccess(rctx, obj) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(*types.TrustCenterAccess) - fc.Result = res - return ec.marshalNTrustCenterAccess2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐTrustCenterAccess(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_TrustCenterDocumentAccess_trustCenterAccess(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "TrustCenterDocumentAccess", - 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_TrustCenterAccess_id(ctx, field) - case "email": - return ec.fieldContext_TrustCenterAccess_email(ctx, field) - case "name": - return ec.fieldContext_TrustCenterAccess_name(ctx, field) - case "active": - return ec.fieldContext_TrustCenterAccess_active(ctx, field) - case "hasAcceptedNonDisclosureAgreement": - return ec.fieldContext_TrustCenterAccess_hasAcceptedNonDisclosureAgreement(ctx, field) - case "createdAt": - return ec.fieldContext_TrustCenterAccess_createdAt(ctx, field) - case "updatedAt": - return ec.fieldContext_TrustCenterAccess_updatedAt(ctx, field) - case "documentAccesses": - return ec.fieldContext_TrustCenterAccess_documentAccesses(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type TrustCenterAccess", field.Name) + return nil, errors.New("field of type Boolean does not have child fields") }, } return fc, nil @@ -58657,16 +58646,10 @@ func (ec *executionContext) fieldContext_TrustCenterDocumentAccessEdge_node(_ co IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "id": - return ec.fieldContext_TrustCenterDocumentAccess_id(ctx, field) case "active": return ec.fieldContext_TrustCenterDocumentAccess_active(ctx, field) - case "createdAt": - return ec.fieldContext_TrustCenterDocumentAccess_createdAt(ctx, field) - case "updatedAt": - return ec.fieldContext_TrustCenterDocumentAccess_updatedAt(ctx, field) - case "trustCenterAccess": - return ec.fieldContext_TrustCenterDocumentAccess_trustCenterAccess(ctx, field) + case "requested": + return ec.fieldContext_TrustCenterDocumentAccess_requested(ctx, field) case "document": return ec.fieldContext_TrustCenterDocumentAccess_document(ctx, field) case "report": @@ -61337,8 +61320,14 @@ func (ec *executionContext) fieldContext_UpdateTrustCenterAccessPayload_trustCen return ec.fieldContext_TrustCenterAccess_createdAt(ctx, field) case "updatedAt": return ec.fieldContext_TrustCenterAccess_updatedAt(ctx, field) - case "documentAccesses": - return ec.fieldContext_TrustCenterAccess_documentAccesses(ctx, field) + case "lastTokenExpiresAt": + return ec.fieldContext_TrustCenterAccess_lastTokenExpiresAt(ctx, field) + case "pendingRequestCount": + return ec.fieldContext_TrustCenterAccess_pendingRequestCount(ctx, field) + case "activeCount": + return ec.fieldContext_TrustCenterAccess_activeCount(ctx, field) + case "availableDocumentAccesses": + return ec.fieldContext_TrustCenterAccess_availableDocumentAccesses(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type TrustCenterAccess", field.Name) }, @@ -77458,13 +77447,6 @@ func (ec *executionContext) _Node(ctx context.Context, sel ast.SelectionSet, obj return graphql.Null } return ec._TrustCenterFile(ctx, sel, obj) - case types.TrustCenterDocumentAccess: - return ec._TrustCenterDocumentAccess(ctx, sel, &obj) - case *types.TrustCenterDocumentAccess: - if obj == nil { - return graphql.Null - } - return ec._TrustCenterDocumentAccess(ctx, sel, obj) case types.TrustCenterAccess: return ec._TrustCenterAccess(ctx, sel, &obj) case *types.TrustCenterAccess: @@ -90142,7 +90124,9 @@ func (ec *executionContext) _TrustCenterAccess(ctx context.Context, sel ast.Sele if out.Values[i] == graphql.Null { atomic.AddUint32(&out.Invalids, 1) } - case "documentAccesses": + case "lastTokenExpiresAt": + out.Values[i] = ec._TrustCenterAccess_lastTokenExpiresAt(ctx, field, obj) + case "pendingRequestCount": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -90151,7 +90135,79 @@ func (ec *executionContext) _TrustCenterAccess(ctx context.Context, sel ast.Sele ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._TrustCenterAccess_documentAccesses(ctx, field, obj) + res = ec._TrustCenterAccess_pendingRequestCount(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 "activeCount": + 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._TrustCenterAccess_activeCount(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 "availableDocumentAccesses": + 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._TrustCenterAccess_availableDocumentAccesses(ctx, field, obj) if res == graphql.Null { atomic.AddUint32(&fs.Invalids, 1) } @@ -90333,7 +90389,7 @@ func (ec *executionContext) _TrustCenterConnection(ctx context.Context, sel ast. return out } -var trustCenterDocumentAccessImplementors = []string{"TrustCenterDocumentAccess", "Node"} +var trustCenterDocumentAccessImplementors = []string{"TrustCenterDocumentAccess"} func (ec *executionContext) _TrustCenterDocumentAccess(ctx context.Context, sel ast.SelectionSet, obj *types.TrustCenterDocumentAccess) graphql.Marshaler { fields := graphql.CollectFields(ec.OperationContext, sel, trustCenterDocumentAccessImplementors) @@ -90344,62 +90400,16 @@ func (ec *executionContext) _TrustCenterDocumentAccess(ctx context.Context, sel switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("TrustCenterDocumentAccess") - case "id": - out.Values[i] = ec._TrustCenterDocumentAccess_id(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&out.Invalids, 1) - } case "active": out.Values[i] = ec._TrustCenterDocumentAccess_active(ctx, field, obj) if out.Values[i] == graphql.Null { atomic.AddUint32(&out.Invalids, 1) } - case "createdAt": - out.Values[i] = ec._TrustCenterDocumentAccess_createdAt(ctx, field, obj) + case "requested": + out.Values[i] = ec._TrustCenterDocumentAccess_requested(ctx, field, obj) if out.Values[i] == graphql.Null { atomic.AddUint32(&out.Invalids, 1) } - case "updatedAt": - out.Values[i] = ec._TrustCenterDocumentAccess_updatedAt(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&out.Invalids, 1) - } - case "trustCenterAccess": - 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._TrustCenterDocumentAccess_trustCenterAccess(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 "document": field := field @@ -100961,10 +100971,6 @@ func (ec *executionContext) marshalNTrustCenter2ᚖgithubᚗcomᚋgetproboᚋpro return ec._TrustCenter(ctx, sel, v) } -func (ec *executionContext) marshalNTrustCenterAccess2githubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐTrustCenterAccess(ctx context.Context, sel ast.SelectionSet, v types.TrustCenterAccess) graphql.Marshaler { - return ec._TrustCenterAccess(ctx, sel, &v) -} - func (ec *executionContext) marshalNTrustCenterAccess2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐTrustCenterAccess(ctx context.Context, sel ast.SelectionSet, v *types.TrustCenterAccess) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { diff --git a/pkg/server/api/console/v1/types/trust_center_document_access.go b/pkg/server/api/console/v1/types/trust_center_document_access.go index 9bddcc4a3..78f02a811 100644 --- a/pkg/server/api/console/v1/types/trust_center_document_access.go +++ b/pkg/server/api/console/v1/types/trust_center_document_access.go @@ -15,6 +15,8 @@ package types import ( + "time" + "github.com/getprobo/probo/pkg/coredata" "github.com/getprobo/probo/pkg/gid" "github.com/getprobo/probo/pkg/page" @@ -31,14 +33,35 @@ type ( Resolver any ParentID gid.GID } + + TrustCenterDocumentAccess struct { + ID gid.GID `json:"id"` + Active bool `json:"active"` + Requested bool `json:"requested"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` + TrustCenterAccess *TrustCenterAccess `json:"trustCenterAccess"` + Document *Document `json:"document,omitempty"` + Report *Report `json:"report,omitempty"` + TrustCenterFile *TrustCenterFile `json:"trustCenterFile,omitempty"` + + // Internal fields used by resolvers + DocumentID *gid.GID `json:"-"` + ReportID *gid.GID `json:"-"` + TrustCenterFileID *gid.GID `json:"-"` + } ) func NewTrustCenterDocumentAccess(tcda *coredata.TrustCenterDocumentAccess) *TrustCenterDocumentAccess { return &TrustCenterDocumentAccess{ - ID: tcda.ID, - Active: tcda.Active, - CreatedAt: tcda.CreatedAt, - UpdatedAt: tcda.UpdatedAt, + ID: tcda.ID, + Active: tcda.Active, + Requested: tcda.Requested, + CreatedAt: tcda.CreatedAt, + UpdatedAt: tcda.UpdatedAt, + DocumentID: tcda.DocumentID, + ReportID: tcda.ReportID, + TrustCenterFileID: tcda.TrustCenterFileID, } } diff --git a/pkg/server/api/console/v1/types/types.go b/pkg/server/api/console/v1/types/types.go index ddf2f94cd..fc5dde85f 100644 --- a/pkg/server/api/console/v1/types/types.go +++ b/pkg/server/api/console/v1/types/types.go @@ -1675,7 +1675,10 @@ type TrustCenterAccess struct { HasAcceptedNonDisclosureAgreement bool `json:"hasAcceptedNonDisclosureAgreement"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` - DocumentAccesses *TrustCenterDocumentAccessConnection `json:"documentAccesses"` + LastTokenExpiresAt *time.Time `json:"lastTokenExpiresAt,omitempty"` + PendingRequestCount int `json:"pendingRequestCount"` + ActiveCount int `json:"activeCount"` + AvailableDocumentAccesses *TrustCenterDocumentAccessConnection `json:"availableDocumentAccesses"` } func (TrustCenterAccess) IsNode() {} @@ -1696,20 +1699,6 @@ type TrustCenterConnection struct { PageInfo *PageInfo `json:"pageInfo"` } -type TrustCenterDocumentAccess struct { - ID gid.GID `json:"id"` - Active bool `json:"active"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` - TrustCenterAccess *TrustCenterAccess `json:"trustCenterAccess"` - Document *Document `json:"document,omitempty"` - Report *Report `json:"report,omitempty"` - TrustCenterFile *TrustCenterFile `json:"trustCenterFile,omitempty"` -} - -func (TrustCenterDocumentAccess) IsNode() {} -func (this TrustCenterDocumentAccess) GetID() gid.GID { return this.ID } - type TrustCenterDocumentAccessEdge struct { Cursor page.CursorKey `json:"cursor"` Node *TrustCenterDocumentAccess `json:"node"` diff --git a/pkg/server/api/console/v1/v1_resolver.go b/pkg/server/api/console/v1/v1_resolver.go index 1b62045b6..297c93343 100644 --- a/pkg/server/api/console/v1/v1_resolver.go +++ b/pkg/server/api/console/v1/v1_resolver.go @@ -1439,9 +1439,7 @@ func (r *mutationResolver) UpdateTrustCenterFile(ctx context.Context, input type func (r *mutationResolver) GetTrustCenterFile(ctx context.Context, input types.GetTrustCenterFileInput) (*types.GetTrustCenterFilePayload, error) { prb := r.ProboService(ctx, input.ID.TenantID()) - file, err := prb.TrustCenterFiles.Get(ctx, &probo.GetTrustCenterFileRequest{ - ID: input.ID, - }) + file, err := prb.TrustCenterFiles.Get(ctx, input.ID) if err != nil { return nil, fmt.Errorf("cannot get trust center file: %w", err) } @@ -4501,6 +4499,13 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error } return types.NewTrustCenter(trustCenter, file), nil + case coredata.TrustCenterAccessEntityType: + trustCenterAccess, err := prb.TrustCenterAccesses.Get(ctx, id) + if err != nil { + panic(fmt.Errorf("cannot get trust center access: %w", err)) + } + + return types.NewTrustCenterAccess(trustCenterAccess), nil default: } @@ -4959,8 +4964,32 @@ func (r *trustCenterResolver) References(ctx context.Context, obj *types.TrustCe return types.NewTrustCenterReferenceConnection(result, obj.ID), nil } -// DocumentAccesses is the resolver for the documentAccesses field. -func (r *trustCenterAccessResolver) DocumentAccesses(ctx context.Context, obj *types.TrustCenterAccess, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrderBy[coredata.TrustCenterDocumentAccessOrderField]) (*types.TrustCenterDocumentAccessConnection, error) { +// PendingRequestCount is the resolver for the pendingRequestCount field. +func (r *trustCenterAccessResolver) PendingRequestCount(ctx context.Context, obj *types.TrustCenterAccess) (int, error) { + prb := r.ProboService(ctx, obj.ID.TenantID()) + + count, err := prb.TrustCenterAccesses.CountPendingRequestDocumentAccesses(ctx, obj.ID) + if err != nil { + panic(fmt.Errorf("cannot count pending request document accesses: %w", err)) + } + + return count, nil +} + +// ActiveCount is the resolver for the activeCount field. +func (r *trustCenterAccessResolver) ActiveCount(ctx context.Context, obj *types.TrustCenterAccess) (int, error) { + prb := r.ProboService(ctx, obj.ID.TenantID()) + + count, err := prb.TrustCenterAccesses.CountActiveDocumentAccesses(ctx, obj.ID) + if err != nil { + panic(fmt.Errorf("cannot count active document accesses: %w", err)) + } + + return count, nil +} + +// AvailableDocumentAccesses is the resolver for the availableDocumentAccesses field. +func (r *trustCenterAccessResolver) AvailableDocumentAccesses(ctx context.Context, obj *types.TrustCenterAccess, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrderBy[coredata.TrustCenterDocumentAccessOrderField]) (*types.TrustCenterDocumentAccessConnection, error) { prb := r.ProboService(ctx, obj.ID.TenantID()) pageOrderBy := page.OrderBy[coredata.TrustCenterDocumentAccessOrderField]{ @@ -4976,7 +5005,7 @@ func (r *trustCenterAccessResolver) DocumentAccesses(ctx context.Context, obj *t cursor := types.NewCursor(first, after, last, before, pageOrderBy) - result, err := prb.TrustCenterAccesses.ListDocumentAccesses(ctx, obj.ID, cursor) + result, err := prb.TrustCenterAccesses.ListAvailableDocumentAccesses(ctx, obj.ID, cursor) if err != nil { panic(fmt.Errorf("cannot list trust center document accesses: %w", err)) } @@ -4984,26 +5013,15 @@ func (r *trustCenterAccessResolver) DocumentAccesses(ctx context.Context, obj *t return types.NewTrustCenterDocumentAccessConnection(result, obj, obj.ID), nil } -// TrustCenterAccess is the resolver for the trustCenterAccess field. -func (r *trustCenterDocumentAccessResolver) TrustCenterAccess(ctx context.Context, obj *types.TrustCenterDocumentAccess) (*types.TrustCenterAccess, error) { - // The TrustCenterAccess is already loaded from the connection resolver - return obj.TrustCenterAccess, nil -} - // Document is the resolver for the document field. func (r *trustCenterDocumentAccessResolver) Document(ctx context.Context, obj *types.TrustCenterDocumentAccess) (*types.Document, error) { - prb := r.ProboService(ctx, obj.ID.TenantID()) - - documentAccess, err := prb.TrustCenterAccesses.GetDocumentAccess(ctx, obj.ID) - if err != nil { - return nil, fmt.Errorf("cannot load trust center document access: %w", err) - } - - if documentAccess.DocumentID == nil { + if obj.DocumentID == nil { return nil, nil } - document, err := prb.Documents.Get(ctx, *documentAccess.DocumentID) + prb := r.ProboService(ctx, obj.ID.TenantID()) + + document, err := prb.Documents.Get(ctx, *obj.DocumentID) if err != nil { return nil, fmt.Errorf("cannot load document: %w", err) } @@ -5013,18 +5031,13 @@ func (r *trustCenterDocumentAccessResolver) Document(ctx context.Context, obj *t // Report is the resolver for the report field. func (r *trustCenterDocumentAccessResolver) Report(ctx context.Context, obj *types.TrustCenterDocumentAccess) (*types.Report, error) { - prb := r.ProboService(ctx, obj.ID.TenantID()) - - documentAccess, err := prb.TrustCenterAccesses.GetDocumentAccess(ctx, obj.ID) - if err != nil { - return nil, fmt.Errorf("cannot load trust center document access: %w", err) - } - - if documentAccess.ReportID == nil { + if obj.ReportID == nil { return nil, nil } - report, err := prb.Reports.Get(ctx, *documentAccess.ReportID) + prb := r.ProboService(ctx, obj.ID.TenantID()) + + report, err := prb.Reports.Get(ctx, *obj.ReportID) if err != nil { return nil, fmt.Errorf("cannot load report: %w", err) } @@ -5034,20 +5047,13 @@ func (r *trustCenterDocumentAccessResolver) Report(ctx context.Context, obj *typ // TrustCenterFile is the resolver for the trustCenterFile field. func (r *trustCenterDocumentAccessResolver) TrustCenterFile(ctx context.Context, obj *types.TrustCenterDocumentAccess) (*types.TrustCenterFile, error) { - prb := r.ProboService(ctx, obj.ID.TenantID()) - - documentAccess, err := prb.TrustCenterAccesses.GetDocumentAccess(ctx, obj.ID) - if err != nil { - return nil, fmt.Errorf("cannot load trust center document access: %w", err) - } - - if documentAccess.TrustCenterFileID == nil { + if obj.TrustCenterFileID == nil { return nil, nil } - trustCenterFile, err := prb.TrustCenterFiles.Get(ctx, &probo.GetTrustCenterFileRequest{ - ID: *documentAccess.TrustCenterFileID, - }) + prb := r.ProboService(ctx, obj.ID.TenantID()) + + trustCenterFile, err := prb.TrustCenterFiles.Get(ctx, *obj.TrustCenterFileID) if err != nil { return nil, fmt.Errorf("cannot load trust center file: %w", err) } @@ -5083,9 +5089,7 @@ func (r *trustCenterFileResolver) FileURL(ctx context.Context, obj *types.TrustC func (r *trustCenterFileResolver) Organization(ctx context.Context, obj *types.TrustCenterFile) (*types.Organization, error) { prb := r.ProboService(ctx, obj.ID.TenantID()) - file, err := prb.TrustCenterFiles.Get(ctx, &probo.GetTrustCenterFileRequest{ - ID: obj.ID, - }) + file, err := prb.TrustCenterFiles.Get(ctx, obj.ID) if err != nil { panic(fmt.Errorf("cannot get trust center file: %w", err)) } diff --git a/pkg/trust/trust_center_access_service.go b/pkg/trust/trust_center_access_service.go index d764efcc1..fd4c2c104 100644 --- a/pkg/trust/trust_center_access_service.go +++ b/pkg/trust/trust_center_access_service.go @@ -208,15 +208,15 @@ func (s TrustCenterAccessService) Request( var accesses coredata.TrustCenterDocumentAccesses - if err := accesses.BulkInsertDocumentAccesses(ctx, tx, s.svc.scope, access.ID, newDocumentIDs, now); err != nil { + if err := accesses.BulkInsertDocumentAccesses(ctx, tx, s.svc.scope, access.ID, newDocumentIDs, true, now); err != nil { return fmt.Errorf("cannot bulk insert trust center document accesses: %w", err) } - if err := accesses.BulkInsertReportAccesses(ctx, tx, s.svc.scope, access.ID, newReportIDs, now); err != nil { + if err := accesses.BulkInsertReportAccesses(ctx, tx, s.svc.scope, access.ID, newReportIDs, true, now); err != nil { return fmt.Errorf("cannot bulk insert trust center report accesses: %w", err) } - if err := accesses.BulkInsertTrustCenterFileAccesses(ctx, tx, s.svc.scope, access.ID, newTrustCenterFileIDs, now); err != nil { + if err := accesses.BulkInsertTrustCenterFileAccesses(ctx, tx, s.svc.scope, access.ID, newTrustCenterFileIDs, true, now); err != nil { return fmt.Errorf("cannot bulk insert trust center file accesses: %w", err) } @@ -409,7 +409,7 @@ func (s *TrustCenterAccessService) AcceptByIDs( return fmt.Errorf("cannot load trust center access: %w", err) } - wasInactive := !access.Active + shouldSendEmail := !access.Active now := time.Now() if len(documentIDs) > 0 { @@ -428,7 +428,7 @@ func (s *TrustCenterAccessService) AcceptByIDs( } } - if wasInactive { + if shouldSendEmail { access.Active = true access.UpdatedAt = now if err := access.Update(ctx, tx, s.svc.scope); err != nil { @@ -496,6 +496,15 @@ func (s *TrustCenterAccessService) sendAccessEmail(ctx context.Context, tx pg.Co }.Encode(), } + now := time.Now() + expiresAt := now.Add(s.svc.trustConfig.TokenDuration) + access.LastTokenExpiresAt = &expiresAt + access.UpdatedAt = now + + if err := access.Update(ctx, tx, s.svc.scope); err != nil { + return fmt.Errorf("cannot update trust center access with expiration: %w", err) + } + return s.sendTrustCenterAccessEmail(ctx, tx, access.Name, access.Email, organization.Name, accessURL.String()) } @@ -512,6 +521,7 @@ func (s *TrustCenterAccessService) sendTrustCenterAccessEmail( name, companyName, accessURL, + s.svc.trustConfig.TokenDuration, ) if err != nil { return fmt.Errorf("cannot render trust center access email: %w", err)