Redesign trust center console

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
Sacha Al Himdani
2025-10-28 13:44:41 +01:00
parent abeaaec734
commit 1f0a5dff5c
39 changed files with 2308 additions and 2423 deletions

View File

@@ -1,6 +1,5 @@
import { graphql } from "relay-runtime"; import { graphql } from "relay-runtime";
import { import {
Card,
Button, Button,
Tr, Tr,
Td, Td,
@@ -18,7 +17,6 @@ import { useFragment } from "react-relay";
import { useMemo, useState, useCallback, useEffect } from "react"; import { useMemo, useState, useCallback, useEffect } from "react";
import { sprintf, getAuditStateVariant, getAuditStateLabel, formatDate, getTrustCenterVisibilityOptions } from "@probo/helpers"; import { sprintf, getAuditStateVariant, getAuditStateLabel, formatDate, getTrustCenterVisibilityOptions } from "@probo/helpers";
import { useOrganizationId } from "/hooks/useOrganizationId"; import { useOrganizationId } from "/hooks/useOrganizationId";
import clsx from "clsx";
import type { TrustCenterAuditsCardFragment$key } from "./__generated__/TrustCenterAuditsCardFragment.graphql"; import type { TrustCenterAuditsCardFragment$key } from "./__generated__/TrustCenterAuditsCardFragment.graphql";
const trustCenterAuditFragment = graphql` const trustCenterAuditFragment = graphql`
@@ -50,17 +48,15 @@ type Props<Params> = {
params: Params; params: Params;
disabled?: boolean; disabled?: boolean;
onChangeVisibility: Mutation<Params>; onChangeVisibility: Mutation<Params>;
variant?: "card" | "table";
}; };
export function TrustCenterAuditsCard<Params>(props: Props<Params>) { export function TrustCenterAuditsCard<Params>(props: Props<Params>) {
const { __ } = useTranslate(); const { __ } = useTranslate();
const [limit, setLimit] = useState<number | null>(4); const [limit, setLimit] = useState<number | null>(100);
const audits = useMemo(() => { const audits = useMemo(() => {
return limit ? props.audits.slice(0, limit) : props.audits; return limit ? props.audits.slice(0, limit) : props.audits;
}, [props.audits, limit]); }, [props.audits, limit]);
const showMoreButton = limit !== null && props.audits.length > limit; const showMoreButton = limit !== null && props.audits.length > limit;
const variant = props.variant ?? "table";
const onChangeVisibility = (auditId: string, trustCenterVisibility: "NONE" | "PRIVATE" | "PUBLIC") => { const onChangeVisibility = (auditId: string, trustCenterVisibility: "NONE" | "PRIVATE" | "PUBLIC") => {
props.onChangeVisibility({ props.onChangeVisibility({
@@ -74,11 +70,9 @@ export function TrustCenterAuditsCard<Params>(props: Props<Params>) {
}); });
}; };
const Wrapper = variant === "card" ? Card : "div";
return ( return (
<Wrapper {...(variant === "card" ? { padded: true } : {})} className="space-y-[10px]"> <div className="space-y-[10px]">
<Table className={clsx(variant === "card" && "bg-invert")}> <Table>
<Thead> <Thead>
<Tr> <Tr>
<Th>{__("Framework")}</Th> <Th>{__("Framework")}</Th>
@@ -116,7 +110,7 @@ export function TrustCenterAuditsCard<Params>(props: Props<Params>) {
{sprintf(__("Show %s more"), props.audits.length - limit)} {sprintf(__("Show %s more"), props.audits.length - limit)}
</Button> </Button>
)} )}
</Wrapper> </div>
); );
} }

View File

@@ -1,6 +1,5 @@
import { graphql } from "relay-runtime"; import { graphql } from "relay-runtime";
import { import {
Card,
Button, Button,
Tr, Tr,
Td, Td,
@@ -21,7 +20,6 @@ import { useFragment } from "react-relay";
import { useMemo, useState, useCallback, useEffect } from "react"; import { useMemo, useState, useCallback, useEffect } from "react";
import { sprintf, getTrustCenterVisibilityOptions } from "@probo/helpers"; import { sprintf, getTrustCenterVisibilityOptions } from "@probo/helpers";
import { useOrganizationId } from "/hooks/useOrganizationId"; import { useOrganizationId } from "/hooks/useOrganizationId";
import clsx from "clsx";
const trustCenterDocumentFragment = graphql` const trustCenterDocumentFragment = graphql`
fragment TrustCenterDocumentsCardFragment on Document { fragment TrustCenterDocumentsCardFragment on Document {
@@ -55,17 +53,15 @@ type Props<Params> = {
params: Params; params: Params;
disabled?: boolean; disabled?: boolean;
onChangeVisibility: Mutation<Params>; onChangeVisibility: Mutation<Params>;
variant?: "card" | "table";
}; };
export function TrustCenterDocumentsCard<Params>(props: Props<Params>) { export function TrustCenterDocumentsCard<Params>(props: Props<Params>) {
const { __ } = useTranslate(); const { __ } = useTranslate();
const [limit, setLimit] = useState<number | null>(4); const [limit, setLimit] = useState<number | null>(100);
const documents = useMemo(() => { const documents = useMemo(() => {
return limit ? props.documents.slice(0, limit) : props.documents; return limit ? props.documents.slice(0, limit) : props.documents;
}, [props.documents, limit]); }, [props.documents, limit]);
const showMoreButton = limit !== null && props.documents.length > limit; const showMoreButton = limit !== null && props.documents.length > limit;
const variant = props.variant ?? "table";
const onChangeVisibility = (documentId: string, trustCenterVisibility: "NONE" | "PRIVATE" | "PUBLIC") => { const onChangeVisibility = (documentId: string, trustCenterVisibility: "NONE" | "PRIVATE" | "PUBLIC") => {
props.onChangeVisibility({ props.onChangeVisibility({
@@ -79,11 +75,9 @@ export function TrustCenterDocumentsCard<Params>(props: Props<Params>) {
}); });
}; };
const Wrapper = variant === "card" ? Card : "div";
return ( return (
<Wrapper padded className="space-y-[10px]"> <div className="space-y-[10px]">
<Table className={clsx(variant === "card" && "bg-invert")}> <Table>
<Thead> <Thead>
<Tr> <Tr>
<Th>{__("Name")}</Th> <Th>{__("Name")}</Th>
@@ -121,7 +115,7 @@ export function TrustCenterDocumentsCard<Params>(props: Props<Params>) {
{sprintf(__("Show %s more"), props.documents.length - limit)} {sprintf(__("Show %s more"), props.documents.length - limit)}
</Button> </Button>
)} )}
</Wrapper> </div>
); );
} }

View File

@@ -1,6 +1,5 @@
import { graphql } from "relay-runtime"; import { graphql } from "relay-runtime";
import { import {
Card,
Button, Button,
Tr, Tr,
Td, Td,
@@ -22,7 +21,6 @@ import { useFragment } from "react-relay";
import { useMemo, useState, useCallback, useEffect } from "react"; import { useMemo, useState, useCallback, useEffect } from "react";
import { sprintf, getTrustCenterVisibilityOptions } from "@probo/helpers"; import { sprintf, getTrustCenterVisibilityOptions } from "@probo/helpers";
import { formatDate } from "@probo/helpers"; import { formatDate } from "@probo/helpers";
import clsx from "clsx";
const trustCenterFileFragment = graphql` const trustCenterFileFragment = graphql`
fragment TrustCenterFilesCardFragment on TrustCenterFile { fragment TrustCenterFilesCardFragment on TrustCenterFile {
@@ -52,17 +50,15 @@ type Props<Params> = {
onChangeVisibility: Mutation<Params>; onChangeVisibility: Mutation<Params>;
onEdit: (file: { id: string; name: string; category: string }) => void; onEdit: (file: { id: string; name: string; category: string }) => void;
onDelete: (id: string) => void; onDelete: (id: string) => void;
variant?: "card" | "table";
}; };
export function TrustCenterFilesCard<Params>(props: Props<Params>) { export function TrustCenterFilesCard<Params>(props: Props<Params>) {
const { __ } = useTranslate(); const { __ } = useTranslate();
const [limit, setLimit] = useState<number | null>(4); const [limit, setLimit] = useState<number | null>(100);
const files = useMemo(() => { const files = useMemo(() => {
return limit ? props.files.slice(0, limit) : props.files; return limit ? props.files.slice(0, limit) : props.files;
}, [props.files, limit]); }, [props.files, limit]);
const showMoreButton = limit !== null && props.files.length > limit; const showMoreButton = limit !== null && props.files.length > limit;
const variant = props.variant ?? "table";
const onChangeVisibility = (fileId: string, trustCenterVisibility: "NONE" | "PRIVATE" | "PUBLIC") => { const onChangeVisibility = (fileId: string, trustCenterVisibility: "NONE" | "PRIVATE" | "PUBLIC") => {
props.onChangeVisibility({ props.onChangeVisibility({
@@ -76,11 +72,9 @@ export function TrustCenterFilesCard<Params>(props: Props<Params>) {
}); });
}; };
const Wrapper = variant === "card" ? Card : "div";
return ( return (
<Wrapper padded className="space-y-[10px]"> <div className="space-y-[10px]">
<Table className={clsx(variant === "card" && "bg-invert")}> <Table>
<Thead> <Thead>
<Tr> <Tr>
<Th>{__("Name")}</Th> <Th>{__("Name")}</Th>
@@ -120,7 +114,7 @@ export function TrustCenterFilesCard<Params>(props: Props<Params>) {
{sprintf(__("Show %s more"), props.files.length - limit)} {sprintf(__("Show %s more"), props.files.length - limit)}
</Button> </Button>
)} )}
</Wrapper> </div>
); );
} }
@@ -215,7 +209,7 @@ function FileRow(props: {
title={__("Edit")} title={__("Edit")}
/> />
<Button <Button
variant="secondary" variant="danger"
icon={IconTrashCan} icon={IconTrashCan}
onClick={() => props.onDelete(file.id)} onClick={() => props.onDelete(file.id)}
disabled={props.disabled} disabled={props.disabled}

View File

@@ -3,10 +3,16 @@ import { safeOpenUrl } from "@probo/helpers";
import { import {
Avatar, Avatar,
Button, Button,
Card, Table,
Thead,
Tbody,
Tr,
Th,
Td,
IconPlusLarge, IconPlusLarge,
IconTrashCan, IconTrashCan,
IconPencil, IconPencil,
IconArrowLink,
} from "@probo/ui"; } from "@probo/ui";
import { type ReactNode, useRef } from "react"; import { type ReactNode, useRef } from "react";
import { import {
@@ -64,7 +70,6 @@ export function TrustCenterReferencesSection({ trustCenterId }: Props) {
</p> </p>
</div> </div>
<Button <Button
variant="secondary"
icon={IconPlusLarge} icon={IconPlusLarge}
onClick={handleCreate} onClick={handleCreate}
> >
@@ -72,33 +77,33 @@ export function TrustCenterReferencesSection({ trustCenterId }: Props) {
</Button> </Button>
</div> </div>
<Card padded> <Table>
{references.length === 0 ? ( <Thead>
<div className="text-center py-12"> <Tr>
<div className="mx-auto w-12 h-12 bg-tertiary rounded-lg flex items-center justify-center mb-4"> <Th>{__("Name")}</Th>
<IconPlusLarge size={24} className="text-txt-tertiary" /> <Th>{__("Description")}</Th>
</div> <Th></Th>
<h3 className="text-lg font-medium text-txt-primary mb-2"> </Tr>
{__("No references yet")} </Thead>
</h3> <Tbody>
<p className="text-txt-tertiary mb-4"> {references.length === 0 && (
{__("Add customer testimonials and partner references to build trust")} <Tr>
</p> <Td colSpan={3} className="text-center text-txt-secondary">
</div> {__("No references available")}
) : ( </Td>
<div className="space-y-4"> </Tr>
{references.map((reference: Reference) => ( )}
<ReferenceRow {references.map((reference: Reference) => (
key={reference.id} <ReferenceRow
reference={reference} key={reference.id}
onEdit={() => handleEdit(reference)} reference={reference}
connectionId={referencesConnectionId} onEdit={() => handleEdit(reference)}
onVisitWebsite={() => handleVisitWebsite(reference.websiteUrl)} connectionId={referencesConnectionId}
/> onVisitWebsite={() => handleVisitWebsite(reference.websiteUrl)}
))} />
</div> ))}
)} </Tbody>
</Card> </Table>
<TrustCenterReferenceDialog ref={dialogRef} /> <TrustCenterReferenceDialog ref={dialogRef} />
</div> </div>
@@ -113,52 +118,47 @@ type ReferenceRowProps = {
}; };
function ReferenceRow({ reference, onEdit, connectionId, onVisitWebsite }: ReferenceRowProps) { function ReferenceRow({ reference, onEdit, connectionId, onVisitWebsite }: ReferenceRowProps) {
return ( return (
<div className="flex items-center justify-between p-4 bg-level-1 rounded-lg"> <Tr>
<div className="flex items-center space-x-4 flex-1"> <Td>
<Avatar <div className="flex items-center gap-3">
src={reference.logoUrl} <Avatar
name={reference.name} src={reference.logoUrl}
size="l" name={reference.name}
/> size="m"
<div className="flex-1 min-w-0">
<div className="flex items-center space-x-2 mb-1">
<button
type="button"
onClick={onVisitWebsite}
className="font-medium text-txt-primary truncate hover:text-primary hover:underline text-left cursor-pointer"
>
{reference.name}
</button>
</div>
<p className="text-sm text-txt-secondary line-clamp-2 mb-2">
{reference.description}
</p>
</div>
</div>
<div className="flex items-center justify-center space-x-2 ml-4">
<Button
variant="tertiary"
icon={IconPencil}
onClick={onEdit}
aria-label="Edit reference"
/>
<DeleteTrustCenterReferenceDialog
referenceId={reference.id}
referenceName={reference.name}
connectionId={connectionId}
>
<Button
variant="danger"
icon={IconTrashCan}
aria-label="Delete reference"
/> />
</DeleteTrustCenterReferenceDialog> <span className="font-medium">{reference.name}</span>
</div> </div>
</div> </Td>
<Td>
<span className="text-txt-secondary line-clamp-2">
{reference.description}
</span>
</Td>
<Td noLink width={200} className="text-end">
<div className="flex gap-2 justify-end">
<Button
variant="secondary"
icon={IconArrowLink}
onClick={onVisitWebsite}
/>
<Button
variant="secondary"
icon={IconPencil}
onClick={onEdit}
/>
<DeleteTrustCenterReferenceDialog
referenceId={reference.id}
referenceName={reference.name}
connectionId={connectionId}
>
<Button
variant="danger"
icon={IconTrashCan}
/>
</DeleteTrustCenterReferenceDialog>
</div>
</Td>
</Tr>
); );
} }

View File

@@ -1,6 +1,5 @@
import { graphql } from "relay-runtime"; import { graphql } from "relay-runtime";
import { import {
Card,
Button, Button,
Tr, Tr,
Td, Td,
@@ -18,7 +17,6 @@ import { useFragment } from "react-relay";
import { useMemo, useState } from "react"; import { useMemo, useState } from "react";
import { sprintf } from "@probo/helpers"; import { sprintf } from "@probo/helpers";
import { useOrganizationId } from "/hooks/useOrganizationId"; import { useOrganizationId } from "/hooks/useOrganizationId";
import clsx from "clsx";
import type { TrustCenterVendorsCardFragment$key } from "./__generated__/TrustCenterVendorsCardFragment.graphql"; import type { TrustCenterVendorsCardFragment$key } from "./__generated__/TrustCenterVendorsCardFragment.graphql";
const trustCenterVendorFragment = graphql` const trustCenterVendorFragment = graphql`
@@ -46,17 +44,15 @@ type Props<Params> = {
params: Params; params: Params;
disabled?: boolean; disabled?: boolean;
onToggleVisibility: Mutation<Params>; onToggleVisibility: Mutation<Params>;
variant?: "card" | "table";
}; };
export function TrustCenterVendorsCard<Params>(props: Props<Params>) { export function TrustCenterVendorsCard<Params>(props: Props<Params>) {
const { __ } = useTranslate(); const { __ } = useTranslate();
const [limit, setLimit] = useState<number | null>(4); const [limit, setLimit] = useState<number | null>(100);
const vendors = useMemo(() => { const vendors = useMemo(() => {
return limit ? props.vendors.slice(0, limit) : props.vendors; return limit ? props.vendors.slice(0, limit) : props.vendors;
}, [props.vendors, limit]); }, [props.vendors, limit]);
const showMoreButton = limit !== null && props.vendors.length > limit; const showMoreButton = limit !== null && props.vendors.length > limit;
const variant = props.variant ?? "table";
const onToggleVisibility = (vendorId: string, showOnTrustCenter: boolean) => { const onToggleVisibility = (vendorId: string, showOnTrustCenter: boolean) => {
props.onToggleVisibility({ props.onToggleVisibility({
@@ -70,11 +66,9 @@ export function TrustCenterVendorsCard<Params>(props: Props<Params>) {
}); });
}; };
const Wrapper = variant === "card" ? Card : "div";
return ( return (
<Wrapper padded className="space-y-[10px]"> <div className="space-y-[10px]">
<Table className={clsx(variant === "card" && "bg-invert")}> <Table>
<Thead> <Thead>
<Tr> <Tr>
<Th>{__("Name")}</Th> <Th>{__("Name")}</Th>
@@ -111,7 +105,7 @@ export function TrustCenterVendorsCard<Params>(props: Props<Params>) {
{sprintf(__("Show %s more"), props.vendors.length - limit)} {sprintf(__("Show %s more"), props.vendors.length - limit)}
</Button> </Button>
)} )}
</Wrapper> </div>
); );
} }

View File

@@ -25,36 +25,9 @@ export const trustCenterAccessesPaginationFragment = graphql`
active active
hasAcceptedNonDisclosureAgreement hasAcceptedNonDisclosureAgreement
createdAt createdAt
documentAccesses(first: 100, orderBy: { field: CREATED_AT, direction: DESC }) { lastTokenExpiresAt
edges { pendingRequestCount
node { activeCount
id
active
createdAt
updatedAt
document {
id
title
documentType
}
report {
id
filename
audit {
id
framework {
name
}
}
}
trustCenterFile {
id
name
category
}
}
}
}
} }
} }
} }
@@ -87,36 +60,9 @@ export const createTrustCenterAccessMutation = graphql`
active active
hasAcceptedNonDisclosureAgreement hasAcceptedNonDisclosureAgreement
createdAt createdAt
documentAccesses(first: 100, orderBy: { field: CREATED_AT, direction: DESC }) { lastTokenExpiresAt
edges { pendingRequestCount
node { activeCount
id
active
createdAt
updatedAt
document {
id
title
documentType
}
report {
id
filename
audit {
id
framework {
name
}
}
}
trustCenterFile {
id
name
category
}
}
}
}
} }
} }
} }
@@ -136,13 +82,35 @@ export const updateTrustCenterAccessMutation = graphql`
hasAcceptedNonDisclosureAgreement hasAcceptedNonDisclosureAgreement
createdAt createdAt
updatedAt 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 { edges {
node { node {
id
active active
createdAt requested
updatedAt
document { document {
id id
title 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 { interface PaginatedData {
data: { node: any } | null; data: { node: any } | null;
hasNext: boolean; hasNext: boolean;
@@ -197,7 +154,7 @@ export function useTrustCenterAccesses(trustCenterId: string): PaginatedData {
count: 10, count: 10,
cursor: null cursor: null
}, },
{ fetchPolicy: 'network-only' } { fetchPolicy: 'store-and-network' }
); );
if (!trustCenterId) { if (!trustCenterId) {

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<d527603a814e765a1a2be0900d1c59e1>> * @generated SignedSource<<271260153dc611541b234266fbdd0c74>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -9,7 +9,6 @@
// @ts-nocheck // @ts-nocheck
import { ConcreteRequest } from 'relay-runtime'; import { ConcreteRequest } from 'relay-runtime';
export type DocumentType = "ISMS" | "OTHER" | "POLICY" | "PROCEDURE";
export type CreateTrustCenterAccessInput = { export type CreateTrustCenterAccessInput = {
active: boolean; active: boolean;
email: string; email: string;
@@ -26,41 +25,14 @@ export type TrustCenterAccessGraphCreateMutation$data = {
readonly cursor: any; readonly cursor: any;
readonly node: { readonly node: {
readonly active: boolean; readonly active: boolean;
readonly activeCount: number;
readonly createdAt: any; 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 email: string;
readonly hasAcceptedNonDisclosureAgreement: boolean; readonly hasAcceptedNonDisclosureAgreement: boolean;
readonly id: string; readonly id: string;
readonly lastTokenExpiresAt: any | null | undefined;
readonly name: string; readonly name: string;
readonly pendingRequestCount: number;
}; };
}; };
}; };
@@ -91,122 +63,90 @@ v2 = [
v3 = { v3 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "concreteType": "TrustCenterAccessEdge",
"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",
"kind": "LinkedField", "kind": "LinkedField",
"name": "document", "name": "trustCenterAccessEdge",
"plural": false, "plural": false,
"selections": [ "selections": [
(v4/*: any*/),
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "title", "name": "cursor",
"storageKey": null "storageKey": null
}, },
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "concreteType": "TrustCenterAccess",
"name": "documentType", "kind": "LinkedField",
"storageKey": null "name": "node",
} "plural": false,
], "selections": [
"storageKey": null {
}, "alias": null,
v13 = { "args": null,
"alias": null, "kind": "ScalarField",
"args": null, "name": "id",
"kind": "ScalarField", "storageKey": null
"name": "filename", },
"storageKey": null {
}, "alias": null,
v14 = { "args": null,
"alias": null, "kind": "ScalarField",
"args": null, "name": "email",
"concreteType": "TrustCenterFile", "storageKey": null
"kind": "LinkedField", },
"name": "trustCenterFile", {
"plural": false, "alias": null,
"selections": [ "args": null,
(v4/*: any*/), "kind": "ScalarField",
(v6/*: any*/), "name": "name",
{ "storageKey": null
"alias": null, },
"args": null, {
"kind": "ScalarField", "alias": null,
"name": "category", "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 "storageKey": null
} }
], ],
@@ -230,111 +170,7 @@ return {
"name": "createTrustCenterAccess", "name": "createTrustCenterAccess",
"plural": false, "plural": false,
"selections": [ "selections": [
{ (v3/*: any*/)
"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
}
], ],
"storageKey": null "storageKey": null
} }
@@ -359,112 +195,7 @@ return {
"name": "createTrustCenterAccess", "name": "createTrustCenterAccess",
"plural": false, "plural": false,
"selections": [ "selections": [
{ (v3/*: any*/),
"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
},
{ {
"alias": null, "alias": null,
"args": null, "args": null,
@@ -487,16 +218,16 @@ return {
] ]
}, },
"params": { "params": {
"cacheID": "4422a02632b77f81f3b5048b5acbac98", "cacheID": "501c3c38f8d44e41a178514443803ce2",
"id": null, "id": null,
"metadata": {}, "metadata": {},
"name": "TrustCenterAccessGraphCreateMutation", "name": "TrustCenterAccessGraphCreateMutation",
"operationKind": "mutation", "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; export default node;

View File

@@ -0,0 +1,391 @@
/**
* @generated SignedSource<<ef22c40e1c881ddd440a0468bae615f9>>
* @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;

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<8c2482b7d32c42396e4645bd309e7cc2>> * @generated SignedSource<<fedd4f94d88d48ba3152491a5c0101f4>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -64,15 +64,7 @@ v3 = {
"name": "id", "name": "id",
"storageKey": null "storageKey": null
}, },
v4 = { v4 = [
"kind": "Literal",
"name": "orderBy",
"value": {
"direction": "DESC",
"field": "CREATED_AT"
}
},
v5 = [
{ {
"kind": "Variable", "kind": "Variable",
"name": "after", "name": "after",
@@ -83,29 +75,15 @@ v5 = [
"name": "first", "name": "first",
"variableName": "count" "variableName": "count"
}, },
(v4/*: any*/) {
], "kind": "Literal",
v6 = { "name": "orderBy",
"alias": null, "value": {
"args": null, "direction": "DESC",
"kind": "ScalarField", "field": "CREATED_AT"
"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
};
return { return {
"fragment": { "fragment": {
"argumentDefinitions": (v0/*: any*/), "argumentDefinitions": (v0/*: any*/),
@@ -154,7 +132,7 @@ return {
"selections": [ "selections": [
{ {
"alias": null, "alias": null,
"args": (v5/*: any*/), "args": (v4/*: any*/),
"concreteType": "TrustCenterAccessConnection", "concreteType": "TrustCenterAccessConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "accesses", "name": "accesses",
@@ -230,8 +208,20 @@ return {
"name": "email", "name": "email",
"storageKey": null "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, "alias": null,
"args": null, "args": null,
@@ -239,146 +229,33 @@ return {
"name": "hasAcceptedNonDisclosureAgreement", "name": "hasAcceptedNonDisclosureAgreement",
"storageKey": null "storageKey": null
}, },
(v8/*: any*/),
{ {
"alias": null, "alias": null,
"args": [ "args": null,
{ "kind": "ScalarField",
"kind": "Literal", "name": "createdAt",
"name": "first", "storageKey": null
"value": 100 },
}, {
(v4/*: any*/) "alias": null,
], "args": null,
"concreteType": "TrustCenterDocumentAccessConnection", "kind": "ScalarField",
"kind": "LinkedField", "name": "lastTokenExpiresAt",
"name": "documentAccesses", "storageKey": null
"plural": false, },
"selections": [ {
{ "alias": null,
"alias": null, "args": null,
"args": null, "kind": "ScalarField",
"concreteType": "TrustCenterDocumentAccessEdge", "name": "pendingRequestCount",
"kind": "LinkedField", "storageKey": null
"name": "edges", },
"plural": true, {
"selections": [ "alias": null,
{ "args": null,
"alias": null, "kind": "ScalarField",
"args": null, "name": "activeCount",
"concreteType": "TrustCenterDocumentAccess", "storageKey": null
"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\"})"
}, },
(v2/*: any*/) (v2/*: any*/)
], ],
@@ -404,7 +281,7 @@ return {
}, },
{ {
"alias": null, "alias": null,
"args": (v5/*: any*/), "args": (v4/*: any*/),
"filters": [ "filters": [
"orderBy" "orderBy"
], ],
@@ -423,16 +300,16 @@ return {
] ]
}, },
"params": { "params": {
"cacheID": "12322ab403d03a821d2228ff68c3d191", "cacheID": "98a87a363a8a26e30506346db052e11a",
"id": null, "id": null,
"metadata": {}, "metadata": {},
"name": "TrustCenterAccessGraphPaginationQuery", "name": "TrustCenterAccessGraphPaginationQuery",
"operationKind": "query", "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; export default node;

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<e0c9c25c78bb6c8cf63eb9437947a013>> * @generated SignedSource<<d13da95487a7fd3dafa22397092b134c>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -63,15 +63,7 @@ v5 = {
"name": "__typename", "name": "__typename",
"storageKey": null "storageKey": null
}, },
v6 = { v6 = [
"kind": "Literal",
"name": "orderBy",
"value": {
"direction": "DESC",
"field": "CREATED_AT"
}
},
v7 = [
{ {
"kind": "Variable", "kind": "Variable",
"name": "after", "name": "after",
@@ -82,29 +74,15 @@ v7 = [
"name": "first", "name": "first",
"variableName": "count" "variableName": "count"
}, },
(v6/*: any*/) {
], "kind": "Literal",
v8 = { "name": "orderBy",
"alias": null, "value": {
"args": null, "direction": "DESC",
"kind": "ScalarField", "field": "CREATED_AT"
"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
};
return { return {
"fragment": { "fragment": {
"argumentDefinitions": [ "argumentDefinitions": [
@@ -169,7 +147,7 @@ return {
"selections": [ "selections": [
{ {
"alias": null, "alias": null,
"args": (v7/*: any*/), "args": (v6/*: any*/),
"concreteType": "TrustCenterAccessConnection", "concreteType": "TrustCenterAccessConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "accesses", "name": "accesses",
@@ -245,8 +223,20 @@ return {
"name": "email", "name": "email",
"storageKey": null "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, "alias": null,
"args": null, "args": null,
@@ -254,146 +244,33 @@ return {
"name": "hasAcceptedNonDisclosureAgreement", "name": "hasAcceptedNonDisclosureAgreement",
"storageKey": null "storageKey": null
}, },
(v10/*: any*/),
{ {
"alias": null, "alias": null,
"args": [ "args": null,
{ "kind": "ScalarField",
"kind": "Literal", "name": "createdAt",
"name": "first", "storageKey": null
"value": 100 },
}, {
(v6/*: any*/) "alias": null,
], "args": null,
"concreteType": "TrustCenterDocumentAccessConnection", "kind": "ScalarField",
"kind": "LinkedField", "name": "lastTokenExpiresAt",
"name": "documentAccesses", "storageKey": null
"plural": false, },
"selections": [ {
{ "alias": null,
"alias": null, "args": null,
"args": null, "kind": "ScalarField",
"concreteType": "TrustCenterDocumentAccessEdge", "name": "pendingRequestCount",
"kind": "LinkedField", "storageKey": null
"name": "edges", },
"plural": true, {
"selections": [ "alias": null,
{ "args": null,
"alias": null, "kind": "ScalarField",
"args": null, "name": "activeCount",
"concreteType": "TrustCenterDocumentAccess", "storageKey": null
"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\"})"
}, },
(v5/*: any*/) (v5/*: any*/)
], ],
@@ -419,7 +296,7 @@ return {
}, },
{ {
"alias": null, "alias": null,
"args": (v7/*: any*/), "args": (v6/*: any*/),
"filters": [ "filters": [
"orderBy" "orderBy"
], ],
@@ -438,12 +315,12 @@ return {
] ]
}, },
"params": { "params": {
"cacheID": "37deb80fc3ff8892d2e68f7588da4e55", "cacheID": "703f94692a1696b15e0c92b282866673",
"id": null, "id": null,
"metadata": {}, "metadata": {},
"name": "TrustCenterAccessGraphQuery", "name": "TrustCenterAccessGraphQuery",
"operationKind": "query", "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"
} }
}; };
})(); })();

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<8ecf71138aa0165738506f5e589d3181>> * @generated SignedSource<<25b79c235754d47097b2ca28f1f3e9a0>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -9,7 +9,6 @@
// @ts-nocheck // @ts-nocheck
import { ConcreteRequest } from 'relay-runtime'; import { ConcreteRequest } from 'relay-runtime';
export type DocumentType = "ISMS" | "OTHER" | "POLICY" | "PROCEDURE";
export type UpdateTrustCenterAccessInput = { export type UpdateTrustCenterAccessInput = {
active?: boolean | null | undefined; active?: boolean | null | undefined;
documentIds?: ReadonlyArray<string> | null | undefined; documentIds?: ReadonlyArray<string> | null | undefined;
@@ -25,41 +24,14 @@ export type TrustCenterAccessGraphUpdateMutation$data = {
readonly updateTrustCenterAccess: { readonly updateTrustCenterAccess: {
readonly trustCenterAccess: { readonly trustCenterAccess: {
readonly active: boolean; readonly active: boolean;
readonly activeCount: number;
readonly createdAt: any; 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 email: string;
readonly hasAcceptedNonDisclosureAgreement: boolean; readonly hasAcceptedNonDisclosureAgreement: boolean;
readonly id: string; readonly id: string;
readonly lastTokenExpiresAt: any | null | undefined;
readonly name: string; readonly name: string;
readonly pendingRequestCount: number;
readonly updatedAt: any; readonly updatedAt: any;
}; };
}; };
@@ -79,241 +51,111 @@ var v0 = [
], ],
v1 = [ v1 = [
{ {
"kind": "Variable", "alias": null,
"name": "input", "args": [
"variableName": "input" {
} "kind": "Variable",
], "name": "input",
v2 = { "variableName": "input"
"alias": null, }
"args": null, ],
"kind": "ScalarField", "concreteType": "UpdateTrustCenterAccessPayload",
"name": "id", "kind": "LinkedField",
"storageKey": null "name": "updateTrustCenterAccess",
}, "plural": false,
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",
"selections": [ "selections": [
{ {
"alias": null, "alias": null,
"args": (v1/*: any*/), "args": null,
"concreteType": "UpdateTrustCenterAccessPayload", "concreteType": "TrustCenterAccess",
"kind": "LinkedField", "kind": "LinkedField",
"name": "updateTrustCenterAccess", "name": "trustCenterAccess",
"plural": false, "plural": false,
"selections": [ "selections": [
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "TrustCenterAccess", "kind": "ScalarField",
"kind": "LinkedField", "name": "id",
"name": "trustCenterAccess", "storageKey": null
"plural": false, },
"selections": [ {
(v2/*: any*/), "alias": null,
(v3/*: any*/), "args": null,
(v4/*: any*/), "kind": "ScalarField",
(v5/*: any*/), "name": "email",
(v6/*: any*/), "storageKey": null
(v7/*: any*/), },
(v8/*: any*/), {
{ "alias": null,
"alias": null, "args": null,
"args": (v9/*: any*/), "kind": "ScalarField",
"concreteType": "TrustCenterDocumentAccessConnection", "name": "name",
"kind": "LinkedField", "storageKey": null
"name": "documentAccesses", },
"plural": false, {
"selections": [ "alias": null,
{ "args": null,
"alias": null, "kind": "ScalarField",
"args": null, "name": "active",
"concreteType": "TrustCenterDocumentAccessEdge", "storageKey": null
"kind": "LinkedField", },
"name": "edges", {
"plural": true, "alias": null,
"selections": [ "args": null,
{ "kind": "ScalarField",
"alias": null, "name": "hasAcceptedNonDisclosureAgreement",
"args": null, "storageKey": null
"concreteType": "TrustCenterDocumentAccess", },
"kind": "LinkedField", {
"name": "node", "alias": null,
"plural": false, "args": null,
"selections": [ "kind": "ScalarField",
(v2/*: any*/), "name": "createdAt",
(v5/*: any*/), "storageKey": null
(v7/*: any*/), },
(v8/*: any*/), {
(v10/*: any*/), "alias": null,
{ "args": null,
"alias": null, "kind": "ScalarField",
"args": null, "name": "updatedAt",
"concreteType": "Report", "storageKey": null
"kind": "LinkedField", },
"name": "report", {
"plural": false, "alias": null,
"selections": [ "args": null,
(v2/*: any*/), "kind": "ScalarField",
(v11/*: any*/), "name": "lastTokenExpiresAt",
{ "storageKey": null
"alias": null, },
"args": null, {
"concreteType": "Audit", "alias": null,
"kind": "LinkedField", "args": null,
"name": "audit", "kind": "ScalarField",
"plural": false, "name": "pendingRequestCount",
"selections": [ "storageKey": null
(v2/*: any*/), },
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "Framework", "kind": "ScalarField",
"kind": "LinkedField", "name": "activeCount",
"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\"})"
}
],
"storageKey": null "storageKey": null
} }
], ],
"storageKey": null "storageKey": null
} }
], ],
"storageKey": null
}
];
return {
"fragment": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "TrustCenterAccessGraphUpdateMutation",
"selections": (v1/*: any*/),
"type": "Mutation", "type": "Mutation",
"abstractKey": null "abstractKey": null
}, },
@@ -322,126 +164,19 @@ return {
"argumentDefinitions": (v0/*: any*/), "argumentDefinitions": (v0/*: any*/),
"kind": "Operation", "kind": "Operation",
"name": "TrustCenterAccessGraphUpdateMutation", "name": "TrustCenterAccessGraphUpdateMutation",
"selections": [ "selections": (v1/*: any*/)
{
"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
}
]
}, },
"params": { "params": {
"cacheID": "b66da9236d9f81563608b3aa5f730908", "cacheID": "8b330240bc19bbebb3244a49dc0a6db0",
"id": null, "id": null,
"metadata": {}, "metadata": {},
"name": "TrustCenterAccessGraphUpdateMutation", "name": "TrustCenterAccessGraphUpdateMutation",
"operationKind": "mutation", "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; export default node;

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<d572a906e6afd89e4a3f1dcffa5c0528>> * @generated SignedSource<<a3da155281753945ab0645a04f0b74fb>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -9,7 +9,6 @@
// @ts-nocheck // @ts-nocheck
import { ReaderFragment } from 'relay-runtime'; import { ReaderFragment } from 'relay-runtime';
export type DocumentType = "ISMS" | "OTHER" | "POLICY" | "PROCEDURE";
import { FragmentRefs } from "relay-runtime"; import { FragmentRefs } from "relay-runtime";
export type TrustCenterAccessGraph_accesses$data = { export type TrustCenterAccessGraph_accesses$data = {
readonly accesses: { readonly accesses: {
@@ -18,41 +17,14 @@ export type TrustCenterAccessGraph_accesses$data = {
readonly cursor: any; readonly cursor: any;
readonly node: { readonly node: {
readonly active: boolean; readonly active: boolean;
readonly activeCount: number;
readonly createdAt: any; 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 email: string;
readonly hasAcceptedNonDisclosureAgreement: boolean; readonly hasAcceptedNonDisclosureAgreement: boolean;
readonly id: string; readonly id: string;
readonly lastTokenExpiresAt: any | null | undefined;
readonly name: string; readonly name: string;
readonly pendingRequestCount: number;
}; };
}>; }>;
readonly pageInfo: { readonly pageInfo: {
@@ -77,40 +49,11 @@ var v0 = [
"accesses" "accesses"
], ],
v1 = { v1 = {
"kind": "Literal",
"name": "orderBy",
"value": {
"direction": "DESC",
"field": "CREATED_AT"
}
},
v2 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "id", "name": "id",
"storageKey": null "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 { return {
"argumentDefinitions": [ "argumentDefinitions": [
@@ -157,7 +100,14 @@ return {
{ {
"alias": "accesses", "alias": "accesses",
"args": [ "args": [
(v1/*: any*/) {
"kind": "Literal",
"name": "orderBy",
"value": {
"direction": "DESC",
"field": "CREATED_AT"
}
}
], ],
"concreteType": "TrustCenterAccessConnection", "concreteType": "TrustCenterAccessConnection",
"kind": "LinkedField", "kind": "LinkedField",
@@ -226,7 +176,7 @@ return {
"name": "node", "name": "node",
"plural": false, "plural": false,
"selections": [ "selections": [
(v2/*: any*/), (v1/*: any*/),
{ {
"alias": null, "alias": null,
"args": null, "args": null,
@@ -234,8 +184,20 @@ return {
"name": "email", "name": "email",
"storageKey": null "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, "alias": null,
"args": null, "args": null,
@@ -243,145 +205,33 @@ return {
"name": "hasAcceptedNonDisclosureAgreement", "name": "hasAcceptedNonDisclosureAgreement",
"storageKey": null "storageKey": null
}, },
(v5/*: any*/),
{ {
"alias": null, "alias": null,
"args": [ "args": null,
{ "kind": "ScalarField",
"kind": "Literal", "name": "createdAt",
"name": "first", "storageKey": null
"value": 100 },
}, {
(v1/*: any*/) "alias": null,
], "args": null,
"concreteType": "TrustCenterDocumentAccessConnection", "kind": "ScalarField",
"kind": "LinkedField", "name": "lastTokenExpiresAt",
"name": "documentAccesses", "storageKey": null
"plural": false, },
"selections": [ {
{ "alias": null,
"alias": null, "args": null,
"args": null, "kind": "ScalarField",
"concreteType": "TrustCenterDocumentAccessEdge", "name": "pendingRequestCount",
"kind": "LinkedField", "storageKey": null
"name": "edges", },
"plural": true, {
"selections": [ "alias": null,
{ "args": null,
"alias": null, "kind": "ScalarField",
"args": null, "name": "activeCount",
"concreteType": "TrustCenterDocumentAccess", "storageKey": null
"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\"})"
}, },
{ {
"alias": null, "alias": null,
@@ -411,13 +261,13 @@ return {
], ],
"storageKey": "__TrustCenterAccessGraph_accesses_connection(orderBy:{\"direction\":\"DESC\",\"field\":\"CREATED_AT\"})" "storageKey": "__TrustCenterAccessGraph_accesses_connection(orderBy:{\"direction\":\"DESC\",\"field\":\"CREATED_AT\"})"
}, },
(v2/*: any*/) (v1/*: any*/)
], ],
"type": "TrustCenter", "type": "TrustCenter",
"abstractKey": null "abstractKey": null
}; };
})(); })();
(node as any).hash = "9c7f3e866e2593c169b1f98d0e637667"; (node as any).hash = "10bb084980182a1e2334be77c29cf1ec";
export default node; export default node;

View File

@@ -12,7 +12,6 @@ import {
IconInboxEmpty, IconInboxEmpty,
IconPageTextLine, IconPageTextLine,
IconSettingsGear2, IconSettingsGear2,
IconCheckmark1,
IconStore, IconStore,
IconTodo, IconTodo,
IconListStack, IconListStack,
@@ -20,6 +19,7 @@ import {
IconShield, IconShield,
IconRotateCw, IconRotateCw,
IconCircleProgress, IconCircleProgress,
IconMedal,
Layout, Layout,
SidebarItem, SidebarItem,
UserDropdown as UserDropdownRoot, UserDropdown as UserDropdownRoot,
@@ -169,7 +169,7 @@ export function MainLayout() {
/> />
<SidebarItem <SidebarItem
label={__("Audits")} label={__("Audits")}
icon={IconCheckmark1} icon={IconMedal}
to={`${prefix}/audits`} to={`${prefix}/audits`}
/> />
<SidebarItem <SidebarItem

View File

@@ -1,7 +1,6 @@
import { import {
Badge, Badge,
Button, Button,
Card,
Checkbox, Checkbox,
Dialog, Dialog,
DialogContent, DialogContent,
@@ -20,19 +19,21 @@ import {
IconCheckmark1, IconCheckmark1,
IconCrossLargeX, IconCrossLargeX,
IconChevronDown, IconChevronDown,
IconPlusLarge,
} from "@probo/ui"; } from "@probo/ui";
import { useTranslate } from "@probo/i18n"; import { useTranslate } from "@probo/i18n";
import { formatDate } from "@probo/helpers"; import { formatDate } from "@probo/helpers";
import { useOutletContext } from "react-router"; import { useOutletContext } from "react-router";
import { useState, useCallback, useEffect } from "react"; import { useState, useCallback, useEffect, useRef } from "react";
import { useQueryLoader, usePreloadedQuery } from 'react-relay';
import z from "zod"; import z from "zod";
import { import {
useTrustCenterAccesses, useTrustCenterAccesses,
createTrustCenterAccessMutation, createTrustCenterAccessMutation,
updateTrustCenterAccessMutation, updateTrustCenterAccessMutation,
deleteTrustCenterAccessMutation deleteTrustCenterAccessMutation,
loadTrustCenterAccessDocumentAccessesQuery
} from "/hooks/graph/TrustCenterAccessGraph"; } from "/hooks/graph/TrustCenterAccessGraph";
import type { TrustCenterAccessGraph_accesses$data } from "/hooks/graph/__generated__/TrustCenterAccessGraph_accesses.graphql";
import { useFormWithSchema } from "/hooks/useFormWithSchema"; import { useFormWithSchema } from "/hooks/useFormWithSchema";
import { useMutationWithToasts } from "/hooks/useMutationWithToasts"; import { useMutationWithToasts } from "/hooks/useMutationWithToasts";
@@ -42,9 +43,89 @@ type ContextType = {
trustCenter?: { trustCenter?: {
id: string; id: string;
}; };
documents?: {
edges: Array<{
node: {
id: string;
title: string;
documentType: string;
trustCenterVisibility: string;
};
}>;
};
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() { export default function TrustCenterAccessTab() {
const { __ } = useTranslate(); const { __ } = useTranslate();
const { organization } = useOutletContext<ContextType>(); const { organization } = useOutletContext<ContextType>();
@@ -75,10 +156,35 @@ export default function TrustCenterAccessTab() {
const dialogRef = useDialogRef(); const dialogRef = useDialogRef();
const editDialogRef = useDialogRef(); const editDialogRef = useDialogRef();
const [editingAccess, setEditingAccess] = useState<AccessType | null>(null); const [editingAccess, setEditingAccess] = useState<AccessType | null>(null);
const [editingDocumentAccesses, setEditingDocumentAccesses] = useState<DocumentAccessType[]>([]);
const [selectedDocumentAccesses, setSelectedDocumentAccesses] = useState<Set<string>>(new Set()); const [selectedDocumentAccesses, setSelectedDocumentAccesses] = useState<Set<string>>(new Set());
const [pendingEditEmail, setPendingEditEmail] = useState<string | null>(null); const [pendingEditEmail, setPendingEditEmail] = useState<string | null>(null);
const [documentAccessesQueryReference, loadDocumentAccessesQuery] = useQueryLoader(loadTrustCenterAccessDocumentAccessesQuery);
const loadedAccessIdRef = useRef<string | null>(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<string>(
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, __)) ?.map((docAccess) => getDocumentAccessInfo(docAccess, __))
?.filter((info) => info !== null) ?? []; ?.filter((info) => info !== null) ?? [];
@@ -93,6 +199,7 @@ export default function TrustCenterAccessTab() {
type DocumentAccessType = { type DocumentAccessType = {
id: string; id: string;
active: boolean; active: boolean;
requested: boolean;
document?: { document?: {
id: string; id: string;
title: string; title: string;
@@ -126,6 +233,8 @@ export default function TrustCenterAccessTab() {
type: __("Document"), type: __("Document"),
category: docAccess.document?.documentType, category: docAccess.document?.documentType,
id: docAccess.document?.id, id: docAccess.document?.id,
requested: docAccess.requested,
active: docAccess.active,
}; };
} }
if (!!docAccess.report) { if (!!docAccess.report) {
@@ -135,6 +244,8 @@ export default function TrustCenterAccessTab() {
type: __("Report"), type: __("Report"),
category: docAccess.report?.audit?.framework?.name, category: docAccess.report?.audit?.framework?.name,
id: docAccess.report?.id, id: docAccess.report?.id,
requested: docAccess.requested,
active: docAccess.active,
}; };
} }
if (!!docAccess.trustCenterFile) { if (!!docAccess.trustCenterFile) {
@@ -144,6 +255,8 @@ export default function TrustCenterAccessTab() {
type: __("File"), type: __("File"),
category: docAccess.trustCenterFile?.category, category: docAccess.trustCenterFile?.category,
id: docAccess.trustCenterFile?.id, id: docAccess.trustCenterFile?.id,
requested: docAccess.requested,
active: docAccess.active,
}; };
} }
@@ -157,28 +270,24 @@ export default function TrustCenterAccessTab() {
active: boolean; active: boolean;
hasAcceptedNonDisclosureAgreement: boolean; hasAcceptedNonDisclosureAgreement: boolean;
createdAt: string; createdAt: string;
documentAccesses: DocumentAccessType[]; lastTokenExpiresAt: string | null;
pendingRequestCount: number;
activeCount: number;
documentAccesses?: DocumentAccessType[];
}; };
const { data: trustCenterData, loadMore, hasNext, isLoadingNext } = useTrustCenterAccesses(organization.trustCenter?.id || ""); const { data: trustCenterData, loadMore, hasNext, isLoadingNext } = useTrustCenterAccesses(organization.trustCenter?.id || "");
type AccessEdge = NonNullable<NonNullable<TrustCenterAccessGraph_accesses$data['accesses']>['edges']>[number]; const accesses: AccessType[] = trustCenterData?.node?.accesses?.edges?.map((edge: any) => ({
type DocumentAccessEdge = NonNullable<NonNullable<NonNullable<AccessEdge>['node']['documentAccesses']>['edges']>[number];
const accesses: AccessType[] = trustCenterData?.node?.accesses?.edges?.map((edge: AccessEdge) => ({
id: edge.node.id, id: edge.node.id,
email: edge.node.email, email: edge.node.email,
name: edge.node.name, name: edge.node.name,
active: edge.node.active, active: edge.node.active,
hasAcceptedNonDisclosureAgreement: edge.node.hasAcceptedNonDisclosureAgreement, hasAcceptedNonDisclosureAgreement: edge.node.hasAcceptedNonDisclosureAgreement,
createdAt: edge.node.createdAt, createdAt: edge.node.createdAt,
documentAccesses: edge.node.documentAccesses?.edges?.map((docEdge: DocumentAccessEdge) => ({ lastTokenExpiresAt: edge.node.lastTokenExpiresAt,
id: docEdge.node.id, pendingRequestCount: edge.node.pendingRequestCount || 0,
active: docEdge.node.active, activeCount: edge.node.activeCount || 0,
document: docEdge.node.document,
report: docEdge.node.report,
trustCenterFile: docEdge.node.trustCenterFile
})) ?? []
})) ?? []; })) ?? [];
@@ -201,8 +310,6 @@ export default function TrustCenterAccessTab() {
connections: connectionId ? [connectionId] : [], connections: connectionId ? [connectionId] : [],
}, },
onSuccess: () => { onSuccess: () => {
dialogRef.current?.close();
inviteForm.reset();
setPendingEditEmail(email); setPendingEditEmail(email);
}, },
}); });
@@ -220,32 +327,37 @@ export default function TrustCenterAccessTab() {
}, [deleteInvitation, trustCenterData]); }, [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) => { const handleEditAccess = useCallback((access: AccessType) => {
loadedAccessIdRef.current = null;
setEditingAccess(access); setEditingAccess(access);
setEditingDocumentAccesses([]);
setSelectedDocumentAccesses(new Set());
setIsLoadingDocumentAccesses(false);
editForm.reset({ name: access.name, active: access.active }); editForm.reset({ name: access.name, active: access.active });
setSelectedDocumentAccesses(new Set(getActiveDocumentIds(access)));
editDialogRef.current?.open(); editDialogRef.current?.open();
}, [editDialogRef, editForm, getActiveDocumentIds]); }, [editDialogRef, editForm]);
useEffect(() => { useEffect(() => {
if (pendingEditEmail && accesses.length > 0) { if (pendingEditEmail && accesses.length > 0) {
const newAccess = accesses.find(access => access.email === pendingEditEmail); const newAccess = accesses.find(access => access.email === pendingEditEmail);
if (newAccess) { if (newAccess) {
setPendingEditEmail(null); setPendingEditEmail(null);
loadedAccessIdRef.current = null;
setEditingAccess(newAccess); setEditingAccess(newAccess);
editForm.reset({ name: newAccess.name, active: true }); editForm.reset({ name: newAccess.name, active: true });
setSelectedDocumentAccesses(new Set(getActiveDocumentIds(newAccess))); setEditingDocumentAccesses([]);
setSelectedDocumentAccesses(new Set());
editDialogRef.current?.open(); 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) => { const handleToggleDocumentAccess = useCallback((documentId: string, active: boolean) => {
setSelectedDocumentAccesses(prev => { setSelectedDocumentAccesses(prev => {
@@ -262,7 +374,7 @@ export default function TrustCenterAccessTab() {
const handleUpdateName = editForm.handleSubmit(async (data) => { const handleUpdateName = editForm.handleSubmit(async (data) => {
if (!editingAccess) return; if (!editingAccess) return;
const { documentIds, reportIds, trustCenterFileIds } = editingAccess.documentAccesses.reduce( const { documentIds, reportIds, trustCenterFileIds } = editingDocumentAccesses.reduce(
(acc, docAccess) => { (acc, docAccess) => {
const id = docAccess.document?.id || docAccess.report?.id || docAccess.trustCenterFile?.id; const id = docAccess.document?.id || docAccess.report?.id || docAccess.trustCenterFile?.id;
if (id && selectedDocumentAccesses.has(id)) { if (id && selectedDocumentAccesses.has(id)) {
@@ -294,6 +406,7 @@ export default function TrustCenterAccessTab() {
editDialogRef.current?.close(); editDialogRef.current?.close();
setEditingAccess(null); setEditingAccess(null);
editForm.reset(); editForm.reset();
setEditingDocumentAccesses([]);
setSelectedDocumentAccesses(new Set()); setSelectedDocumentAccesses(new Set());
}, },
}); });
@@ -309,7 +422,7 @@ export default function TrustCenterAccessTab() {
</p> </p>
</div> </div>
{organization.trustCenter?.id && ( {organization.trustCenter?.id && (
<Button onClick={() => { <Button icon={IconPlusLarge} onClick={() => {
inviteForm.reset(); inviteForm.reset();
dialogRef.current?.open(); dialogRef.current?.open();
}}> }}>
@@ -318,126 +431,151 @@ export default function TrustCenterAccessTab() {
)} )}
</div> </div>
<Card padded> {!organization.trustCenter?.id ? (
{!organization.trustCenter?.id ? ( <Table>
<div className="text-center text-txt-tertiary py-8"> <Tbody>
<Spinner /> <Tr>
</div> <Td className="text-center text-txt-tertiary py-8">
) : accesses.length === 0 ? ( <Spinner />
<div className="text-center text-txt-tertiary py-8"> </Td>
{__("No external access granted yet")} </Tr>
</div> </Tbody>
) : ( </Table>
<> ) : accesses.length === 0 ? (
<Table> <Table>
<Thead> <Tbody>
<Tr> <Tr>
<Th>{__("Name")}</Th> <Td className="text-center text-txt-tertiary py-8">
<Th>{__("Email")}</Th> {__("No external access granted yet")}
<Th>{__("Date")}</Th> </Td>
<Th>{__("Active")}</Th> </Tr>
<Th>{__("Documents")}</Th> </Tbody>
<Th>{__("NDA")}</Th> </Table>
<Th></Th> ) : (
</Tr> <>
</Thead> <Table>
<Tbody> <Thead>
{accesses.map((access) => { <Tr>
const activeDocuments = access.documentAccesses.filter(doc => doc.active).length; <Th>{__("Name")}</Th>
const totalDocuments = access.documentAccesses.length; <Th>{__("Email")}</Th>
<Th>{__("Date")}</Th>
<Th>{__("Expires")}</Th>
<Th className="text-center">{__("Active")}</Th>
<Th className="text-center">{__("Access")}</Th>
<Th className="text-center">{__("Requests")}</Th>
<Th className="text-center">{__("NDA")}</Th>
<Th></Th>
</Tr>
</Thead>
<Tbody>
{accesses.map((access) => {
const isExpired = access.lastTokenExpiresAt ? new Date(access.lastTokenExpiresAt) < new Date() : false;
return ( return (
<Tr <Tr
key={access.id} key={access.id}
onClick={() => handleEditAccess(access)} onClick={() => handleEditAccess(access)}
className="cursor-pointer hover:bg-bg-secondary transition-colors" className="cursor-pointer hover:bg-bg-secondary transition-colors"
> >
<Td className="font-medium">{access.name}</Td> <Td className="font-medium">{access.name}</Td>
<Td>{access.email}</Td> <Td>{access.email}</Td>
<Td> <Td>
{formatDate(access.createdAt)} {formatDate(access.createdAt)}
</Td> </Td>
<Td> <Td className={isExpired ? "text-txt-danger" : ""}>
{access.lastTokenExpiresAt ? formatDate(access.lastTokenExpiresAt) : "-"}
</Td>
<Td>
<div className="flex justify-center">
{access.active ? ( {access.active ? (
<IconCheckmark1 size={16} className="text-txt-success" /> <IconCheckmark1 size={16} className="text-txt-success" />
) : ( ) : (
<IconCrossLargeX size={16} className="text-txt-danger" /> <IconCrossLargeX size={16} className="text-txt-danger" />
)} )}
</Td> </div>
<Td> </Td>
{totalDocuments > 0 ? `${activeDocuments}/${totalDocuments}` : '0/0'} <Td className="text-center">
</Td> {access.activeCount}
<Td> </Td>
<Td className="text-center">
{access.pendingRequestCount > 0 ? access.pendingRequestCount : ""}
</Td>
<Td>
<div className="flex justify-center">
{access.hasAcceptedNonDisclosureAgreement && ( {access.hasAcceptedNonDisclosureAgreement && (
<IconCheckmark1 size={16} className="text-txt-success" /> <IconCheckmark1 size={16} className="text-txt-success" />
)} )}
</Td>
<Td noLink width={160} className="text-end">
<div
className="flex gap-2 justify-end"
onClick={(e) => e.stopPropagation()}
>
<Button
variant="secondary"
onClick={() => handleEditAccess(access)}
disabled={isUpdating}
icon={IconPencil}
/>
<Button
variant="secondary"
onClick={() => handleDelete(access.id)}
disabled={isDeleting}
icon={IconTrashCan}
/>
</div> </div>
</Td> </Td>
</Tr> <Td noLink width={160} className="text-end">
); <div
})} className="flex gap-2 justify-end"
</Tbody> onClick={(e) => e.stopPropagation()}
</Table> >
{hasNext && ( <Button
<Button variant="secondary"
variant="tertiary" onClick={() => handleEditAccess(access)}
onClick={loadMore} disabled={isUpdating}
disabled={isLoadingNext} icon={IconPencil}
className="mt-3 mx-auto" />
icon={IconChevronDown} <Button
> variant="danger"
{isLoadingNext && <Spinner />} onClick={() => handleDelete(access.id)}
{__("Show More")} disabled={isDeleting}
</Button> icon={IconTrashCan}
)} />
</> </div>
)} </Td>
</Card> </Tr>
);
})}
</Tbody>
</Table>
{hasNext && (
<Button
variant="tertiary"
onClick={loadMore}
disabled={isLoadingNext}
className="mt-3 mx-auto"
icon={IconChevronDown}
>
{isLoadingNext && <Spinner />}
{__("Show More")}
</Button>
)}
</>
)}
<Dialog <Dialog
ref={dialogRef} ref={dialogRef}
title={__("Invite External Access")} title={__("Invite External Access")}
> >
<form onSubmit={handleInvite}> <form onSubmit={handleInvite}>
<DialogContent padded className="space-y-4"> <DialogContent padded className="space-y-6">
<p className="text-txt-secondary text-sm"> <div>
{__("Send a 7-day access token to an external person to view your trust center")} <p className="text-txt-secondary text-sm mb-4">
</p> {__("Send a 30-day access token to an external person to view your trust center")}
</p>
<Field <Field
label={__("Full Name")} label={__("Full Name")}
required required
error={inviteForm.formState.errors.name?.message} error={inviteForm.formState.errors.name?.message}
{...inviteForm.register("name")} {...inviteForm.register("name")}
placeholder={__("John Doe")} placeholder={__("John Doe")}
/> />
<Field <div className="mt-4">
label={__("Email Address")} <Field
required label={__("Email Address")}
error={inviteForm.formState.errors.email?.message} required
type="email" error={inviteForm.formState.errors.email?.message}
{...inviteForm.register("email")} type="email"
placeholder={__("john@example.com")} {...inviteForm.register("email")}
/> placeholder={__("john@example.com")}
/>
</div>
</div>
</DialogContent> </DialogContent>
<DialogFooter> <DialogFooter>
@@ -453,6 +591,12 @@ export default function TrustCenterAccessTab() {
ref={editDialogRef} ref={editDialogRef}
title={__("Edit Access")} title={__("Edit Access")}
> >
{documentAccessesQueryReference && (
<DocumentAccessesLoader
queryReference={documentAccessesQueryReference}
onDataLoaded={handleDocumentAccessesLoaded}
/>
)}
<form onSubmit={handleUpdateName}> <form onSubmit={handleUpdateName}>
<DialogContent padded className="space-y-6"> <DialogContent padded className="space-y-6">
<div> <div>
@@ -484,11 +628,37 @@ export default function TrustCenterAccessTab() {
</div> </div>
</div> </div>
{formattedDocumentAccesses.length > 0 && ( <div>
<div> <div className="flex justify-between items-center mb-4">
<h4 className="font-medium text-txt-primary mb-4"> <h4 className="font-medium text-txt-primary">
{__("Document Access Permissions")} {__("Document Access Permissions")}
</h4> </h4>
{!isLoadingDocumentAccesses && formattedDocumentAccesses.length > 0 && (
<Button
type="button"
variant="tertiary"
onClick={() => {
if (selectedDocumentAccesses.size === formattedDocumentAccesses.length) {
setSelectedDocumentAccesses(new Set());
} else {
const allIds = new Set(formattedDocumentAccesses.map(doc => doc.id).filter((id): id is string => !!id));
setSelectedDocumentAccesses(allIds);
}
}}
className="text-xs h-7 min-h-7"
>
{selectedDocumentAccesses.size === formattedDocumentAccesses.length
? __("Clear All")
: __("Select All")}
</Button>
)}
</div>
{isLoadingDocumentAccesses ? (
<div className="flex justify-center items-center py-12">
<Spinner />
</div>
) : formattedDocumentAccesses.length > 0 ? (
<div className="bg-bg-secondary rounded-lg overflow-hidden"> <div className="bg-bg-secondary rounded-lg overflow-hidden">
<Table> <Table>
<Thead> <Thead>
@@ -496,6 +666,7 @@ export default function TrustCenterAccessTab() {
<Th>{__("Name")}</Th> <Th>{__("Name")}</Th>
<Th>{__("Type")}</Th> <Th>{__("Type")}</Th>
<Th>{__("Category")}</Th> <Th>{__("Category")}</Th>
<Th></Th>
<Th> <Th>
<div className="flex justify-end"> <div className="flex justify-end">
{__("Access")} {__("Access")}
@@ -505,7 +676,7 @@ export default function TrustCenterAccessTab() {
</Thead> </Thead>
<Tbody> <Tbody>
{formattedDocumentAccesses.map((info) => { {formattedDocumentAccesses.map((info) => {
const { variant, name, type, category, id } = info; const { variant, name, type, category, id, requested } = info;
return ( return (
<Tr key={id}> <Tr key={id}>
@@ -524,6 +695,13 @@ export default function TrustCenterAccessTab() {
{category || "-"} {category || "-"}
</div> </div>
</Td> </Td>
<Td>
{requested && (
<Badge variant="warning">
{__("Requested")}
</Badge>
)}
</Td>
<Td> <Td>
<div className="flex justify-end"> <div className="flex justify-end">
<Checkbox <Checkbox
@@ -540,13 +718,17 @@ export default function TrustCenterAccessTab() {
</Tbody> </Tbody>
</Table> </Table>
</div> </div>
</div> ) : (
)} <div className="text-center text-txt-tertiary py-8">
{__("No documents available")}
</div>
)}
</div>
</DialogContent> </DialogContent>
<DialogFooter> <DialogFooter>
<Button type="submit" disabled={isUpdating}> <Button type="submit" disabled={isUpdating || isLoadingDocumentAccesses}>
{isUpdating && <Spinner />} {(isUpdating || isLoadingDocumentAccesses) && <Spinner />}
{__("Update Access")} {__("Update Access")}
</Button> </Button>
</DialogFooter> </DialogFooter>

View File

@@ -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 { useOutletContext } from "react-router";
import { TrustCenterAuditsCard } from "/components/trustCenter/TrustCenterAuditsCard"; import { TrustCenterAuditsCard } from "/components/trustCenter/TrustCenterAuditsCard";
import { useTrustCenterAuditUpdate } from "/hooks/graph/TrustCenterAuditGraph"; import { useTrustCenterAuditUpdate } from "/hooks/graph/TrustCenterAuditGraph";
@@ -15,6 +16,7 @@ type ContextType = {
}; };
export default function TrustCenterAuditsTab() { export default function TrustCenterAuditsTab() {
const { __ } = useTranslate();
const { organization } = useOutletContext<ContextType>(); const { organization } = useOutletContext<ContextType>();
const [updateAuditVisibility, isUpdatingAudits] = useTrustCenterAuditUpdate(); const [updateAuditVisibility, isUpdatingAudits] = useTrustCenterAuditUpdate();
@@ -23,17 +25,20 @@ export default function TrustCenterAuditsTab() {
return ( return (
<div className="space-y-4"> <div className="space-y-4">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div>
<h3 className="text-base font-medium">{__("Audits")}</h3>
<p className="text-sm text-txt-tertiary">
{__("Manage audit reports and compliance certifications")}
</p>
</div>
{isUpdatingAudits && <Spinner />} {isUpdatingAudits && <Spinner />}
</div> </div>
<Card padded> <TrustCenterAuditsCard
<TrustCenterAuditsCard audits={audits}
audits={audits} params={{}}
params={{}} disabled={isUpdatingAudits}
disabled={isUpdatingAudits} onChangeVisibility={updateAuditVisibility}
onChangeVisibility={updateAuditVisibility} />
variant="table"
/>
</Card>
</div> </div>
); );
} }

View File

@@ -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 { useOutletContext } from "react-router";
import { TrustCenterDocumentsCard } from "/components/trustCenter/TrustCenterDocumentsCard"; import { TrustCenterDocumentsCard } from "/components/trustCenter/TrustCenterDocumentsCard";
import { useUpdateDocumentVisibilityMutation } from "/hooks/graph/TrustCenterDocumentGraph"; import { useUpdateDocumentVisibilityMutation } from "/hooks/graph/TrustCenterDocumentGraph";
@@ -15,6 +16,7 @@ type ContextType = {
}; };
export default function TrustCenterDocumentsTab() { export default function TrustCenterDocumentsTab() {
const { __ } = useTranslate();
const { organization } = useOutletContext<ContextType>(); const { organization } = useOutletContext<ContextType>();
const [updateDocumentVisibility, isUpdatingDocuments] = useUpdateDocumentVisibilityMutation(); const [updateDocumentVisibility, isUpdatingDocuments] = useUpdateDocumentVisibilityMutation();
@@ -23,17 +25,20 @@ export default function TrustCenterDocumentsTab() {
return ( return (
<div className="space-y-4"> <div className="space-y-4">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div>
<h3 className="text-base font-medium">{__("Documents")}</h3>
<p className="text-sm text-txt-tertiary">
{__("Manage policies, procedures and compliance documents")}
</p>
</div>
{isUpdatingDocuments && <Spinner />} {isUpdatingDocuments && <Spinner />}
</div> </div>
<Card padded> <TrustCenterDocumentsCard
<TrustCenterDocumentsCard documents={documents}
documents={documents} params={{}}
params={{}} disabled={isUpdatingDocuments}
disabled={isUpdatingDocuments} onChangeVisibility={updateDocumentVisibility}
onChangeVisibility={updateDocumentVisibility} />
variant="table"
/>
</Card>
</div> </div>
); );
} }

View File

@@ -1,6 +1,5 @@
import { import {
Button, Button,
Card,
Dialog, Dialog,
DialogContent, DialogContent,
DialogFooter, DialogFooter,
@@ -10,6 +9,7 @@ import {
Dropzone, Dropzone,
Option, Option,
Badge, Badge,
IconPlusLarge,
} from "@probo/ui"; } from "@probo/ui";
import { useTranslate } from "@probo/i18n"; import { useTranslate } from "@probo/i18n";
import { useOutletContext } from "react-router"; import { useOutletContext } from "react-router";
@@ -200,7 +200,7 @@ export default function TrustCenterFilesTab() {
{__("Upload and manage files for your trust center")} {__("Upload and manage files for your trust center")}
</p> </p>
</div> </div>
<Button onClick={() => createDialogRef.current?.open()}> <Button icon={IconPlusLarge} onClick={() => createDialogRef.current?.open()}>
{__("Add File")} {__("Add File")}
</Button> </Button>
</div> </div>
@@ -209,17 +209,14 @@ export default function TrustCenterFilesTab() {
<Spinner /> <Spinner />
</div> </div>
)} )}
<Card padded> <TrustCenterFilesCard
<TrustCenterFilesCard files={files}
files={files} params={{}}
params={{}} disabled={isUpdating || isDeleting}
disabled={isUpdating || isDeleting} onChangeVisibility={handleChangeVisibility}
onChangeVisibility={handleChangeVisibility} onEdit={handleEdit}
onEdit={handleEdit} onDelete={handleDeleteClick}
onDelete={handleDeleteClick} />
variant="table"
/>
</Card>
<Dialog ref={createDialogRef} title={__("Add File")}> <Dialog ref={createDialogRef} title={__("Add File")}>
<form onSubmit={handleCreate}> <form onSubmit={handleCreate}>

View File

@@ -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<ContextType>();
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 (
<div className="space-y-6">
<div className="space-y-4">
<div className="flex items-center justify-between">
<h2 className="text-base font-medium">{__("Trust Center Status")}</h2>
{isUpdating && <Spinner />}
</div>
<Card padded className="space-y-4">
<div className="flex items-center justify-between">
<div className="space-y-1">
<h3 className="font-medium">{__("Activate Trust Center")}</h3>
<p className="text-sm text-txt-tertiary">
{__("Make your trust center publicly accessible to build customer confidence")}
</p>
</div>
<Checkbox
checked={isActive}
onChange={handleToggleActive}
/>
</div>
{isActive && trustCenterUrl && (
<div className="mt-4 p-4 bg-accent-light rounded-lg border border-accent">
<div className="flex items-center justify-between">
<div>
<h4 className="font-medium text-accent-dark">
{__("Your Trust Center is Live!")}
</h4>
<p className="text-sm text-accent-dark mt-1">
{__("Your customers can now access your trust center at:")}
</p>
<a
href={trustCenterUrl}
target="_blank"
rel="noopener noreferrer"
className="text-sm font-mono text-accent underline hover:no-underline"
>
{trustCenterUrl}
</a>
</div>
<Button
variant="secondary"
onClick={() => window.open(trustCenterUrl, '_blank', 'noopener,noreferrer')}
>
{__("View")}
</Button>
</div>
</div>
)}
{!isActive && (
<div className="mt-4 p-4 bg-tertiary rounded-lg border border-border-solid">
<h4 className="font-medium text-txt-secondary">
{__("Trust Center is Inactive")}
</h4>
<p className="text-sm text-txt-tertiary mt-1">
{__("Your trust center is currently not accessible to the public. Enable it to start sharing your compliance status.")}
</p>
</div>
)}
</Card>
</div>
<div className="space-y-4">
<div className="flex items-center justify-between">
<h2 className="text-base font-medium">{__("Non-Disclosure Agreement")}</h2>
{(isUploadingNDA || isDeletingNDA) && <Spinner />}
</div>
<Card padded className="space-y-4">
<div className="space-y-2">
{!organization.trustCenter?.ndaFileName ? (
<p className="text-sm text-txt-tertiary">
{__("Upload a Non-Disclosure Agreement that visitors must accept before accessing your trust center")}
</p>
) : (<></>)}
{organization.trustCenter?.ndaFileName ? (
<div className="space-y-3">
<div className="flex items-center justify-between">
<div className="space-y-1">
<div className="flex items-center gap-2">
<p className="text-sm font-medium">
{organization.trustCenter.ndaFileName || __("Non-Disclosure Agreement")}
</p>
</div>
<p className="text-xs text-txt-tertiary">
{__("Visitors will need to accept this NDA before accessing your trust center")}
</p>
</div>
<div className="flex items-center gap-2">
<Button
type="button"
variant="secondary"
onClick={() => {
if (organization.trustCenter?.ndaFileUrl) {
window.open(organization.trustCenter.ndaFileUrl, '_blank');
}
}}
>
{__("Download PDF")}
</Button>
<Button
variant="quaternary"
icon={IconTrashCan}
onClick={handleNDADelete}
disabled={isDeletingNDA}
/>
</div>
</div>
</div>
) : (
<Dropzone
description={__("Upload PDF files up to 10MB")}
isUploading={isUploadingNDA}
onDrop={handleNDAUpload}
accept={{
"application/pdf": [".pdf"],
}}
maxSize={10}
/>
)}
</div>
</Card>
</div>
<div className="space-y-4">
<h2 className="text-base font-medium">{__("Integrations")}</h2>
<Card padded>
<SlackConnections
organizationId={organization.id!}
slackConnections={organization.slackConnections?.edges?.map((edge) => edge.node) ?? []}
/>
</Card>
</div>
</div>
);
}

View File

@@ -1,26 +1,23 @@
import { useTranslate } from "@probo/i18n"; import { useTranslate } from "@probo/i18n";
import { usePageTitle } from "@probo/hooks"; import { usePageTitle } from "@probo/hooks";
import { import {
Button,
Card,
Checkbox,
Dropzone,
PageHeader, PageHeader,
Spinner,
useToast,
Tabs, Tabs,
TabLink, TabLink,
TabItem, Badge,
IconTrashCan, IconSettingsGear2,
IconMedal,
IconCheckmark1,
IconPageTextLine,
IconFolder2,
IconStore,
IconPeopleAdd,
} from "@probo/ui"; } from "@probo/ui";
import { usePreloadedQuery, type PreloadedQuery } from "react-relay"; 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 type { TrustCenterGraphQuery } from "/hooks/graph/__generated__/TrustCenterGraphQuery.graphql";
import { useState } from "react";
import { useOrganizationId } from "/hooks/useOrganizationId"; import { useOrganizationId } from "/hooks/useOrganizationId";
import { Outlet, useLocation, Link } from "react-router"; import { Outlet } from "react-router";
import { TrustCenterReferencesSection } from "/components/trustCenter/TrustCenterReferencesSection";
import { SlackConnections } from "../../../components/organizations/SlackConnection";
type Props = { type Props = {
queryRef: PreloadedQuery<TrustCenterGraphQuery>; queryRef: PreloadedQuery<TrustCenterGraphQuery>;
@@ -28,100 +25,12 @@ type Props = {
export default function TrustCenterPage({ queryRef }: Props) { export default function TrustCenterPage({ queryRef }: Props) {
const { __ } = useTranslate(); const { __ } = useTranslate();
const { toast } = useToast();
const organizationId = useOrganizationId(); const organizationId = useOrganizationId();
const location = useLocation();
const { organization } = usePreloadedQuery(trustCenterQuery, queryRef); 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")); usePageTitle(__("Trust Center"));
const handleToggleActive = async (active: boolean) => { const isActive = organization.trustCenter?.active || false;
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 ( return (
<div className="space-y-6"> <div className="space-y-6">
@@ -130,173 +39,44 @@ export default function TrustCenterPage({ queryRef }: Props) {
description={__( description={__(
"Configure your public trust center to showcase your security and compliance posture." "Configure your public trust center to showcase your security and compliance posture."
)} )}
/> >
<Badge variant={isActive ? "success" : "danger"}>
{isActive ? __("Active") : __("Inactive")}
</Badge>
</PageHeader>
<div className="space-y-4"> <Tabs>
<div className="flex items-center justify-between"> <TabLink to={`/organizations/${organizationId}/trust-center`} end>
<h2 className="text-base font-medium">{__("Trust Center Status")}</h2> <IconSettingsGear2 className="size-4" />
{isUpdating && <Spinner />} {__("Overview")}
</div> </TabLink>
<Card padded className="space-y-4"> <TabLink to={`/organizations/${organizationId}/trust-center/trust-by`}>
<div className="flex items-center justify-between"> <IconCheckmark1 className="size-4" />
<div className="space-y-1"> {__("Trusted by")}
<h3 className="font-medium">{__("Activate Trust Center")}</h3> </TabLink>
<p className="text-sm text-txt-tertiary"> <TabLink to={`/organizations/${organizationId}/trust-center/audits`}>
{__("Make your trust center publicly accessible to build customer confidence")} <IconMedal className="size-4" />
</p> {__("Audits")}
</div> </TabLink>
<Checkbox <TabLink to={`/organizations/${organizationId}/trust-center/documents`}>
checked={isActive} <IconPageTextLine className="size-4" />
onChange={handleToggleActive} {__("Documents")}
/> </TabLink>
</div> <TabLink to={`/organizations/${organizationId}/trust-center/files`}>
<IconFolder2 className="size-4" />
{__("Files")}
</TabLink>
<TabLink to={`/organizations/${organizationId}/trust-center/vendors`}>
<IconStore className="size-4" />
{__("Vendors")}
</TabLink>
<TabLink to={`/organizations/${organizationId}/trust-center/access`}>
<IconPeopleAdd className="size-4" />
{__("Access")}
</TabLink>
</Tabs>
{isActive && trustCenterUrl && ( <Outlet context={{ organization }} />
<div className="mt-4 p-4 bg-accent-light rounded-lg border border-accent">
<div className="flex items-center justify-between">
<div>
<h4 className="font-medium text-accent-dark">
{__("Your Trust Center is Live!")}
</h4>
<p className="text-sm text-accent-dark mt-1">
{__("Your customers can now access your trust center at:")}
</p>
<a
href={trustCenterUrl}
target="_blank"
rel="noopener noreferrer"
className="text-sm font-mono text-accent underline hover:no-underline"
>
{trustCenterUrl}
</a>
</div>
<Button
variant="secondary"
onClick={() => window.open(trustCenterUrl, '_blank', 'noopener,noreferrer')}
>
{__("View")}
</Button>
</div>
</div>
)}
{!isActive && (
<div className="mt-4 p-4 bg-tertiary rounded-lg border border-border-solid">
<h4 className="font-medium text-txt-secondary">
{__("Trust Center is Inactive")}
</h4>
<p className="text-sm text-txt-tertiary mt-1">
{__("Your trust center is currently not accessible to the public. Enable it to start sharing your compliance status.")}
</p>
</div>
)}
</Card>
</div>
<div className="space-y-4">
<div className="flex items-center justify-between">
<h2 className="text-base font-medium">{__("Non-Disclosure Agreement")}</h2>
{(isUploadingNDA || isDeletingNDA) && <Spinner />}
</div>
<Card padded className="space-y-4">
<div className="space-y-2">
{!organization.trustCenter?.ndaFileName ? (
<p className="text-sm text-txt-tertiary">
{__("Upload a Non-Disclosure Agreement that visitors must accept before accessing your trust center")}
</p>
) : (<></>)}
{organization.trustCenter?.ndaFileName ? (
<div className="space-y-3">
<div className="flex items-center justify-between">
<div className="space-y-1">
<div className="flex items-center gap-2">
<p className="text-sm font-medium">
{organization.trustCenter.ndaFileName || __("Non-Disclosure Agreement")}
</p>
</div>
<p className="text-xs text-txt-tertiary">
{__("Visitors will need to accept this NDA before accessing your trust center")}
</p>
</div>
<div className="flex items-center gap-2">
<Button
type="button"
variant="secondary"
onClick={() => {
if (organization.trustCenter?.ndaFileUrl) {
window.open(organization.trustCenter.ndaFileUrl, '_blank');
}
}}
>
{__("Download PDF")}
</Button>
<Button
variant="quaternary"
icon={IconTrashCan}
onClick={handleNDADelete}
disabled={isDeletingNDA}
/>
</div>
</div>
</div>
) : (
<Dropzone
description={__("Upload PDF files up to 10MB")}
isUploading={isUploadingNDA}
onDrop={handleNDAUpload}
accept={{
"application/pdf": [".pdf"],
}}
maxSize={10}
/>
)}
</div>
</Card>
</div>
{organization.trustCenter?.id && (
<TrustCenterReferencesSection trustCenterId={organization.trustCenter.id} />
)}
<div className="space-y-4">
<h2 className="text-base font-medium">{__("Integrations")}</h2>
<Card padded>
<SlackConnections
organizationId={organization.id!}
slackConnections={organization.slackConnections?.edges?.map((edge) => edge.node) ?? []}
/>
</Card>
</div>
<div className="space-y-4">
<Tabs>
<TabItem
asChild
active={
location.pathname === `/organizations/${organizationId}/trust-center` ||
location.pathname === `/organizations/${organizationId}/trust-center/audits`
}
>
<Link to={`/organizations/${organizationId}/trust-center/audits`}>
{__("Audits")}
</Link>
</TabItem>
<TabLink to={`/organizations/${organizationId}/trust-center/vendors`}>
{__("Vendors")}
</TabLink>
<TabLink to={`/organizations/${organizationId}/trust-center/documents`}>
{__("Documents")}
</TabLink>
<TabLink to={`/organizations/${organizationId}/trust-center/files`}>
{__("Files")}
</TabLink>
<TabLink to={`/organizations/${organizationId}/trust-center/access`}>
{__("Access")}
</TabLink>
</Tabs>
<Outlet context={{ organization }} />
</div>
</div> </div>
); );
} }

View File

@@ -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<ContextType>();
return (
<div className="space-y-4">
{organization.trustCenter?.id && (
<TrustCenterReferencesSection trustCenterId={organization.trustCenter.id} />
)}
</div>
);
}

View File

@@ -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 { useOutletContext } from "react-router";
import { TrustCenterVendorsCard } from "/components/trustCenter/TrustCenterVendorsCard"; import { TrustCenterVendorsCard } from "/components/trustCenter/TrustCenterVendorsCard";
import { useTrustCenterVendorUpdate } from "/hooks/graph/TrustCenterVendorGraph"; import { useTrustCenterVendorUpdate } from "/hooks/graph/TrustCenterVendorGraph";
@@ -15,6 +16,7 @@ type ContextType = {
}; };
export default function TrustCenterVendorsTab() { export default function TrustCenterVendorsTab() {
const { __ } = useTranslate();
const { organization } = useOutletContext<ContextType>(); const { organization } = useOutletContext<ContextType>();
const [updateVendorVisibility, isUpdatingVendors] = useTrustCenterVendorUpdate(); const [updateVendorVisibility, isUpdatingVendors] = useTrustCenterVendorUpdate();
@@ -23,17 +25,20 @@ export default function TrustCenterVendorsTab() {
return ( return (
<div className="space-y-4"> <div className="space-y-4">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div>
<h3 className="text-base font-medium">{__("Vendors")}</h3>
<p className="text-sm text-txt-tertiary">
{__("Manage vendor assessments and third-party risk information")}
</p>
</div>
{isUpdatingVendors && <Spinner />} {isUpdatingVendors && <Spinner />}
</div> </div>
<Card padded> <TrustCenterVendorsCard
<TrustCenterVendorsCard vendors={vendors}
vendors={vendors} params={{}}
params={{}} disabled={isUpdatingVendors}
disabled={isUpdatingVendors} onToggleVisibility={updateVendorVisibility}
onToggleVisibility={updateVendorVisibility} />
variant="table"
/>
</Card>
</div> </div>
); );
} }

View File

@@ -20,7 +20,14 @@ export const trustCenterRoutes = [
index: true, index: true,
fallback: LinkCardSkeleton, fallback: LinkCardSkeleton,
Component: lazy( 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") () => import("/pages/organizations/trustCenter/TrustCenterAuditsTab")
), ),
}, },
{
path: "vendors",
fallback: LinkCardSkeleton,
Component: lazy(
() => import("/pages/organizations/trustCenter/TrustCenterVendorsTab")
),
},
{ {
path: "documents", path: "documents",
fallback: LinkCardSkeleton, fallback: LinkCardSkeleton,
@@ -51,6 +51,13 @@ export const trustCenterRoutes = [
() => import("/pages/organizations/trustCenter/TrustCenterFilesTab") () => import("/pages/organizations/trustCenter/TrustCenterFilesTab")
), ),
}, },
{
path: "vendors",
fallback: LinkCardSkeleton,
Component: lazy(
() => import("/pages/organizations/trustCenter/TrustCenterVendorsTab")
),
},
{ {
path: "access", path: "access",
fallback: LinkCardSkeleton, fallback: LinkCardSkeleton,

View File

@@ -42,7 +42,7 @@ probod:
cookie-name: "TCT" cookie-name: "TCT"
cookie-domain: "localhost" cookie-domain: "localhost"
cookie-duration: 24 cookie-duration: 24
token-duration: 168 token-duration: 720
report-url-duration: 15 report-url-duration: 15
token-secret: "this-is-a-secure-secret-for-trust-token-signing-at-least-32-bytes" token-secret: "this-is-a-secure-secret-for-trust-token-signing-at-least-32-bytes"
scope: "trust_center_readonly" scope: "trust_center_readonly"

View File

@@ -61,7 +61,7 @@ probod:
cookie-name: "TCT" cookie-name: "TCT"
cookie-domain: "localhost" cookie-domain: "localhost"
cookie-duration: 24 cookie-duration: 24
token-duration: 168 token-duration: 720
report-url-duration: 15 report-url-duration: 15
token-secret: "trust-token-signing-secret" token-secret: "trust-token-signing-secret"
scope: "trust_center_readonly" scope: "trust_center_readonly"
@@ -397,7 +397,7 @@ Trust center cookie lifetime in hours.
#### `trust-auth.token-duration` (integer) #### `trust-auth.token-duration` (integer)
**Default**: `168` **Default**: `720`
Trust center access token lifetime in hours. Trust center access token lifetime in hours.

View File

@@ -19,7 +19,9 @@ import (
"embed" "embed"
"fmt" "fmt"
htmltemplate "html/template" htmltemplate "html/template"
"math"
texttemplate "text/template" texttemplate "text/template"
"time"
) )
//go:embed dist //go:embed dist
@@ -148,17 +150,21 @@ func RenderFrameworkExport(hostname, fullName, downloadUrl string) (subject stri
return subjectFrameworkExport, textBody, htmlBody, err 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 { data := struct {
FullName string FullName string
OrganizationName string OrganizationName string
AccessUrl string AccessUrl string
LogoURL string LogoURL string
DurationInDays int
}{ }{
FullName: fullName, FullName: fullName,
OrganizationName: organizationName, OrganizationName: organizationName,
AccessUrl: accessUrl, AccessUrl: accessUrl,
LogoURL: fmt.Sprintf(logoURLFormat, hostname), LogoURL: fmt.Sprintf(logoURLFormat, hostname),
DurationInDays: durationInDays,
} }
textBody, htmlBody, err = renderEmail(trustCenterAccessTextTemplate, trustCenterAccessHTMLTemplate, data) textBody, htmlBody, err = renderEmail(trustCenterAccessTextTemplate, trustCenterAccessHTMLTemplate, data)

View File

@@ -16,7 +16,7 @@ export const TrustCenterAccess = () => {
</Section> </Section>
<Text style={footerText}> <Text style={footerText}>
This link will expire in 7 days. This link will expire in {'{{.DurationInDays}}'} days.
</Text> </Text>
</EmailLayout> </EmailLayout>
); );

View File

@@ -6,6 +6,6 @@ You have been granted access to {{.OrganizationName}}'s Trust Center! Click the
{{.AccessUrl}} {{.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 Probo Inc, 490 Post St, STE 640, San Francisco, CA, 94102, US

View File

@@ -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;

View File

@@ -41,6 +41,7 @@ type (
NDAFileID *gid.GID `db:"nda_file_id"` NDAFileID *gid.GID `db:"nda_file_id"`
CreatedAt time.Time `db:"created_at"` CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"` UpdatedAt time.Time `db:"updated_at"`
LastTokenExpiresAt *time.Time `db:"last_token_expires_at"`
} }
TrustCenterAccesses []*TrustCenterAccess TrustCenterAccesses []*TrustCenterAccess
@@ -81,7 +82,8 @@ SELECT
has_accepted_non_disclosure_agreement_metadata, has_accepted_non_disclosure_agreement_metadata,
nda_file_id, nda_file_id,
created_at, created_at,
updated_at updated_at,
last_token_expires_at
FROM FROM
trust_center_accesses trust_center_accesses
WHERE WHERE
@@ -133,7 +135,8 @@ SELECT
has_accepted_non_disclosure_agreement_metadata, has_accepted_non_disclosure_agreement_metadata,
nda_file_id, nda_file_id,
created_at, created_at,
updated_at updated_at,
last_token_expires_at
FROM FROM
trust_center_accesses trust_center_accesses
WHERE WHERE
@@ -231,7 +234,8 @@ UPDATE trust_center_accesses SET
updated_at = @updated_at, updated_at = @updated_at,
has_accepted_non_disclosure_agreement = @has_accepted_non_disclosure_agreement, has_accepted_non_disclosure_agreement = @has_accepted_non_disclosure_agreement,
has_accepted_non_disclosure_agreement_metadata = @has_accepted_non_disclosure_agreement_metadata, 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 WHERE
%s %s
AND id = @id AND id = @id
@@ -246,7 +250,8 @@ WHERE
"updated_at": tca.UpdatedAt, "updated_at": tca.UpdatedAt,
"has_accepted_non_disclosure_agreement": tca.HasAcceptedNonDisclosureAgreement, "has_accepted_non_disclosure_agreement": tca.HasAcceptedNonDisclosureAgreement,
"has_accepted_non_disclosure_agreement_metadata": tca.HasAcceptedNonDisclosureAgreementMetadata, "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()) maps.Copy(args, scope.SQLArguments())
@@ -304,7 +309,8 @@ SELECT
has_accepted_non_disclosure_agreement_metadata, has_accepted_non_disclosure_agreement_metadata,
nda_file_id, nda_file_id,
created_at, created_at,
updated_at updated_at,
last_token_expires_at
FROM FROM
trust_center_accesses trust_center_accesses
WHERE WHERE

View File

@@ -16,6 +16,7 @@ package coredata
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"maps" "maps"
"time" "time"
@@ -34,13 +35,22 @@ type (
ReportID *gid.GID `db:"report_id"` ReportID *gid.GID `db:"report_id"`
TrustCenterFileID *gid.GID `db:"trust_center_file_id"` TrustCenterFileID *gid.GID `db:"trust_center_file_id"`
Active bool `db:"active"` Active bool `db:"active"`
Requested bool `db:"requested"`
CreatedAt time.Time `db:"created_at"` CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"` UpdatedAt time.Time `db:"updated_at"`
} }
TrustCenterDocumentAccesses []*TrustCenterDocumentAccess 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 { func (tcda *TrustCenterDocumentAccess) CursorKey(orderBy TrustCenterDocumentAccessOrderField) page.CursorKey {
switch orderBy { switch orderBy {
case TrustCenterDocumentAccessOrderFieldCreatedAt: case TrustCenterDocumentAccessOrderFieldCreatedAt:
@@ -64,6 +74,7 @@ SELECT
report_id, report_id,
trust_center_file_id, trust_center_file_id,
active, active,
requested,
created_at, created_at,
updated_at updated_at
FROM FROM
@@ -86,6 +97,9 @@ LIMIT 1;
access, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[TrustCenterDocumentAccess]) access, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[TrustCenterDocumentAccess])
if err != nil { 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) return fmt.Errorf("cannot collect trust center document access: %w", err)
} }
@@ -109,6 +123,7 @@ SELECT
report_id, report_id,
trust_center_file_id, trust_center_file_id,
active, active,
requested,
created_at, created_at,
updated_at updated_at
FROM FROM
@@ -158,6 +173,7 @@ SELECT
report_id, report_id,
trust_center_file_id, trust_center_file_id,
active, active,
requested,
created_at, created_at,
updated_at updated_at
FROM FROM
@@ -206,6 +222,7 @@ INSERT INTO trust_center_document_accesses (
report_id, report_id,
trust_center_file_id, trust_center_file_id,
active, active,
requested,
created_at, created_at,
updated_at updated_at
) VALUES ( ) VALUES (
@@ -216,6 +233,7 @@ INSERT INTO trust_center_document_accesses (
@report_id, @report_id,
@trust_center_file_id, @trust_center_file_id,
@active, @active,
@requested,
@created_at, @created_at,
@updated_at @updated_at
) )
@@ -229,6 +247,7 @@ INSERT INTO trust_center_document_accesses (
"report_id": tcda.ReportID, "report_id": tcda.ReportID,
"trust_center_file_id": tcda.TrustCenterFileID, "trust_center_file_id": tcda.TrustCenterFileID,
"active": tcda.Active, "active": tcda.Active,
"requested": tcda.Requested,
"created_at": tcda.CreatedAt, "created_at": tcda.CreatedAt,
"updated_at": tcda.UpdatedAt, "updated_at": tcda.UpdatedAt,
} }
@@ -332,7 +351,76 @@ WHERE
return count, nil 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, ctx context.Context,
conn pg.Conn, conn pg.Conn,
scope Scoper, scope Scoper,
@@ -340,6 +428,79 @@ func (tcdas *TrustCenterDocumentAccesses) LoadByTrustCenterAccessID(
cursor *page.Cursor[TrustCenterDocumentAccessOrderField], cursor *page.Cursor[TrustCenterDocumentAccessOrderField],
) error { ) error {
q := ` 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 SELECT
id, id,
trust_center_access_id, trust_center_access_id,
@@ -347,14 +508,11 @@ SELECT
report_id, report_id,
trust_center_file_id, trust_center_file_id,
active, active,
requested,
created_at, created_at,
updated_at updated_at
FROM FROM final_items
trust_center_document_accesses WHERE %s
WHERE
%s
AND trust_center_access_id = @trust_center_access_id
AND %s
` `
q = fmt.Sprintf(q, scope.SQLFragment(), cursor.SQLFragment()) q = fmt.Sprintf(q, scope.SQLFragment(), cursor.SQLFragment())
@@ -394,6 +552,7 @@ SELECT
report_id, report_id,
trust_center_file_id, trust_center_file_id,
active, active,
requested,
created_at, created_at,
updated_at updated_at
FROM FROM
@@ -464,10 +623,6 @@ func ActivateByDocumentIDs(
documentIDs []gid.GID, documentIDs []gid.GID,
updatedAt time.Time, updatedAt time.Time,
) error { ) error {
if len(documentIDs) == 0 {
return nil
}
q := ` q := `
UPDATE trust_center_document_accesses UPDATE trust_center_document_accesses
SET active = true, updated_at = @updated_at SET active = true, updated_at = @updated_at
@@ -502,10 +657,6 @@ func ActivateByReportIDs(
reportIDs []gid.GID, reportIDs []gid.GID,
updatedAt time.Time, updatedAt time.Time,
) error { ) error {
if len(reportIDs) == 0 {
return nil
}
q := ` q := `
UPDATE trust_center_document_accesses UPDATE trust_center_document_accesses
SET active = true, updated_at = @updated_at SET active = true, updated_at = @updated_at
@@ -538,6 +689,7 @@ func (tcdas TrustCenterDocumentAccesses) BulkInsertDocumentAccesses(
scope Scoper, scope Scoper,
trustCenterAccessID gid.GID, trustCenterAccessID gid.GID,
documentIDs []gid.GID, documentIDs []gid.GID,
requested bool,
createdAt time.Time, createdAt time.Time,
) error { ) error {
if len(documentIDs) == 0 { if len(documentIDs) == 0 {
@@ -554,13 +706,15 @@ WITH document_access_data AS (
null::text AS report_id, null::text AS report_id,
null::text AS trust_center_file_id, null::text AS trust_center_file_id,
false AS active, false AS active,
@requested::boolean AS requested,
@created_at::timestamptz AS created_at, @created_at::timestamptz AS created_at,
@updated_at::timestamptz AS updated_at @updated_at::timestamptz AS updated_at
) )
INSERT INTO trust_center_document_accesses ( 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 SELECT * FROM document_access_data
ON CONFLICT DO NOTHING
` `
args := pgx.StrictNamedArgs{ args := pgx.StrictNamedArgs{
@@ -568,6 +722,7 @@ SELECT * FROM document_access_data
"trust_center_access_id": trustCenterAccessID, "trust_center_access_id": trustCenterAccessID,
"document_ids": documentIDs, "document_ids": documentIDs,
"trust_center_document_access_entity_type": TrustCenterDocumentAccessEntityType, "trust_center_document_access_entity_type": TrustCenterDocumentAccessEntityType,
"requested": requested,
"created_at": createdAt, "created_at": createdAt,
"updated_at": createdAt, "updated_at": createdAt,
} }
@@ -585,6 +740,7 @@ func (tcdas TrustCenterDocumentAccesses) BulkInsertReportAccesses(
scope Scoper, scope Scoper,
trustCenterAccessID gid.GID, trustCenterAccessID gid.GID,
reportIDs []gid.GID, reportIDs []gid.GID,
requested bool,
createdAt time.Time, createdAt time.Time,
) error { ) error {
if len(reportIDs) == 0 { if len(reportIDs) == 0 {
@@ -601,13 +757,15 @@ WITH report_access_data AS (
unnest(@report_ids::text[]) AS report_id, unnest(@report_ids::text[]) AS report_id,
null::text AS trust_center_file_id, null::text AS trust_center_file_id,
false AS active, false AS active,
@requested::boolean AS requested,
@created_at::timestamptz AS created_at, @created_at::timestamptz AS created_at,
@updated_at::timestamptz AS updated_at @updated_at::timestamptz AS updated_at
) )
INSERT INTO trust_center_document_accesses ( 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 SELECT * FROM report_access_data
ON CONFLICT DO NOTHING
` `
args := pgx.StrictNamedArgs{ args := pgx.StrictNamedArgs{
@@ -641,6 +799,7 @@ SELECT
report_id, report_id,
trust_center_file_id, trust_center_file_id,
active, active,
requested,
created_at, created_at,
updated_at updated_at
FROM FROM
@@ -715,6 +874,7 @@ func (tcdas TrustCenterDocumentAccesses) BulkInsertTrustCenterFileAccesses(
scope Scoper, scope Scoper,
trustCenterAccessID gid.GID, trustCenterAccessID gid.GID,
trustCenterFileIDs []gid.GID, trustCenterFileIDs []gid.GID,
requested bool,
createdAt time.Time, createdAt time.Time,
) error { ) error {
q := ` q := `
@@ -727,13 +887,15 @@ WITH trust_center_file_access_data AS (
null::text AS report_id, null::text AS report_id,
unnest(@trust_center_file_ids::text[]) AS trust_center_file_id, unnest(@trust_center_file_ids::text[]) AS trust_center_file_id,
false AS active, false AS active,
@requested::boolean AS requested,
@created_at::timestamptz AS created_at, @created_at::timestamptz AS created_at,
@updated_at::timestamptz AS updated_at @updated_at::timestamptz AS updated_at
) )
INSERT INTO trust_center_document_accesses ( 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 SELECT * FROM trust_center_file_access_data
ON CONFLICT DO NOTHING
` `
args := pgx.StrictNamedArgs{ args := pgx.StrictNamedArgs{
@@ -741,6 +903,7 @@ SELECT * FROM trust_center_file_access_data
"trust_center_document_access_entity_type": TrustCenterDocumentAccessEntityType, "trust_center_document_access_entity_type": TrustCenterDocumentAccessEntityType,
"trust_center_access_id": trustCenterAccessID, "trust_center_access_id": trustCenterAccessID,
"trust_center_file_ids": trustCenterFileIDs, "trust_center_file_ids": trustCenterFileIDs,
"requested": requested,
"created_at": createdAt, "created_at": createdAt,
"updated_at": createdAt, "updated_at": createdAt,
} }

View File

@@ -80,7 +80,7 @@ func (s TrustCenterAccessService) ListForTrustCenterID(
return page.NewPage(accesses, cursor), nil return page.NewPage(accesses, cursor), nil
} }
func (s TrustCenterAccessService) ListDocumentAccesses( func (s TrustCenterAccessService) ListAvailableDocumentAccesses(
ctx context.Context, ctx context.Context,
trustCenterAccessID gid.GID, trustCenterAccessID gid.GID,
cursor *page.Cursor[coredata.TrustCenterDocumentAccessOrderField], cursor *page.Cursor[coredata.TrustCenterDocumentAccessOrderField],
@@ -90,7 +90,7 @@ func (s TrustCenterAccessService) ListDocumentAccesses(
err := s.svc.pg.WithConn( err := s.svc.pg.WithConn(
ctx, ctx,
func(conn pg.Conn) error { 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 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( func (s TrustCenterAccessService) ValidateToken(
ctx context.Context, ctx context.Context,
tokenString string, tokenString string,
@@ -210,50 +254,6 @@ func (s TrustCenterAccessService) Create(
err := s.svc.pg.WithTx( err := s.svc.pg.WithTx(
ctx, ctx,
func(tx pg.Conn) error { 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{ access = &coredata.TrustCenterAccess{
ID: gid.New(s.svc.scope.GetTenantID(), coredata.TrustCenterAccessEntityType), ID: gid.New(s.svc.scope.GetTenantID(), coredata.TrustCenterAccessEntityType),
TenantID: s.svc.scope.GetTenantID(), TenantID: s.svc.scope.GetTenantID(),
@@ -270,19 +270,6 @@ func (s TrustCenterAccessService) Create(
return fmt.Errorf("cannot insert trust center access: %w", err) 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 return nil
}, },
) )
@@ -328,28 +315,8 @@ func (s TrustCenterAccessService) Update(
return fmt.Errorf("cannot update trust center access: %w", err) return fmt.Errorf("cannot update trust center access: %w", err)
} }
if req.DocumentIDs != nil || req.ReportIDs != nil || req.TrustCenterFileIDs != nil { if err := s.upsertDocumentAccesses(ctx, tx, access.ID, req.DocumentIDs, req.ReportIDs, req.TrustCenterFileIDs, now); err != nil {
if err := coredata.DeactivateByTrustCenterAccessID(ctx, tx, s.svc.scope, access.ID, now); err != nil { return fmt.Errorf("cannot upsert document accesses: %w", err)
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 shouldSendEmail { if shouldSendEmail {
@@ -393,6 +360,56 @@ func (s TrustCenterAccessService) Delete(
return err 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 { func (s TrustCenterAccessService) sendAccessEmail(ctx context.Context, tx pg.Conn, access *coredata.TrustCenterAccess) error {
accessToken, err := statelesstoken.NewToken( accessToken, err := statelesstoken.NewToken(
s.svc.trustConfig.TokenSecret, s.svc.trustConfig.TokenSecret,
@@ -445,6 +462,15 @@ func (s TrustCenterAccessService) sendAccessEmail(ctx context.Context, tx pg.Con
}.Encode(), }.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()) return s.sendTrustCenterAccessEmail(ctx, tx, access.Name, access.Email, organization.Name, accessURL.String())
} }
@@ -461,6 +487,7 @@ func (s TrustCenterAccessService) sendTrustCenterAccessEmail(
name, name,
companyName, companyName,
accessURL, accessURL,
s.svc.trustConfig.TokenDuration,
) )
if err != nil { if err != nil {
return fmt.Errorf("cannot render trust center access email: %w", err) return fmt.Errorf("cannot render trust center access email: %w", err)

View File

@@ -54,10 +54,6 @@ type (
TrustCenterVisibility *coredata.TrustCenterVisibility TrustCenterVisibility *coredata.TrustCenterVisibility
} }
GetTrustCenterFileRequest struct {
ID gid.GID
}
DeleteTrustCenterFileRequest struct { DeleteTrustCenterFileRequest struct {
ID gid.GID ID gid.GID
} }
@@ -114,21 +110,18 @@ func (s TrustCenterFileService) CountForOrganizationID(
func (s TrustCenterFileService) Get( func (s TrustCenterFileService) Get(
ctx context.Context, ctx context.Context,
req *GetTrustCenterFileRequest, id gid.GID,
) (*coredata.TrustCenterFile, error) { ) (*coredata.TrustCenterFile, error) {
var file *coredata.TrustCenterFile var file *coredata.TrustCenterFile
err := s.svc.pg.WithConn( err := s.svc.pg.WithConn(ctx, func(conn pg.Conn) error {
ctx, file = &coredata.TrustCenterFile{}
func(conn pg.Conn) error { if err := file.LoadByID(ctx, conn, s.svc.scope, id); err != nil {
file = &coredata.TrustCenterFile{} return fmt.Errorf("cannot load trust center file: %w", err)
if err := file.LoadByID(ctx, conn, s.svc.scope, req.ID); err != nil { }
return fmt.Errorf("cannot load trust center file: %w", err)
}
return nil return nil
}, })
)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -123,7 +123,7 @@ func New() *Implm {
CookieName: "TCT", CookieName: "TCT",
CookieDomain: "localhost", CookieDomain: "localhost",
CookieDuration: 24, CookieDuration: 24,
TokenDuration: 168, TokenDuration: 720,
ReportURLDuration: 15, ReportURLDuration: 15,
TokenSecret: "this-is-a-secure-secret-for-trust-token-signing-at-least-32-bytes", TokenSecret: "this-is-a-secure-secret-for-trust-token-signing-at-least-32-bytes",
Scope: "trust_center_readonly", Scope: "trust_center_readonly",

View File

@@ -2407,8 +2407,11 @@ type TrustCenterAccess implements Node {
hasAcceptedNonDisclosureAgreement: Boolean! hasAcceptedNonDisclosureAgreement: Boolean!
createdAt: Datetime! createdAt: Datetime!
updatedAt: Datetime! updatedAt: Datetime!
lastTokenExpiresAt: Datetime
pendingRequestCount: Int! @goField(forceResolver: true)
activeCount: Int! @goField(forceResolver: true)
documentAccesses( availableDocumentAccesses(
first: Int first: Int
after: CursorKey after: CursorKey
last: Int last: Int
@@ -2417,12 +2420,12 @@ type TrustCenterAccess implements Node {
): TrustCenterDocumentAccessConnection! @goField(forceResolver: true) ): TrustCenterDocumentAccessConnection! @goField(forceResolver: true)
} }
type TrustCenterDocumentAccess implements Node { type TrustCenterDocumentAccess
id: ID! @goModel(
model: "github.com/getprobo/probo/pkg/server/api/console/v1/types.TrustCenterDocumentAccess"
) {
active: Boolean! active: Boolean!
createdAt: Datetime! requested: Boolean!
updatedAt: Datetime!
trustCenterAccess: TrustCenterAccess! @goField(forceResolver: true)
document: Document @goField(forceResolver: true) document: Document @goField(forceResolver: true)
report: Report @goField(forceResolver: true) report: Report @goField(forceResolver: true)
trustCenterFile: TrustCenterFile @goField(forceResolver: true) trustCenterFile: TrustCenterFile @goField(forceResolver: true)

View File

@@ -1287,12 +1287,15 @@ type ComplexityRoot struct {
TrustCenterAccess struct { TrustCenterAccess struct {
Active func(childComplexity int) int 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 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 Email func(childComplexity int) int
HasAcceptedNonDisclosureAgreement func(childComplexity int) int HasAcceptedNonDisclosureAgreement func(childComplexity int) int
ID func(childComplexity int) int ID func(childComplexity int) int
LastTokenExpiresAt func(childComplexity int) int
Name func(childComplexity int) int Name func(childComplexity int) int
PendingRequestCount func(childComplexity int) int
UpdatedAt func(childComplexity int) int UpdatedAt func(childComplexity int) int
} }
@@ -1312,14 +1315,11 @@ type ComplexityRoot struct {
} }
TrustCenterDocumentAccess struct { TrustCenterDocumentAccess struct {
Active func(childComplexity int) int Active func(childComplexity int) int
CreatedAt func(childComplexity int) int Document func(childComplexity int) int
Document func(childComplexity int) int Report func(childComplexity int) int
ID func(childComplexity int) int Requested func(childComplexity int) int
Report func(childComplexity int) int TrustCenterFile func(childComplexity int) int
TrustCenterAccess func(childComplexity int) int
TrustCenterFile func(childComplexity int) int
UpdatedAt func(childComplexity int) int
} }
TrustCenterDocumentAccessConnection struct { 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) 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 { 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 { type TrustCenterDocumentAccessResolver interface {
TrustCenterAccess(ctx context.Context, obj *types.TrustCenterDocumentAccess) (*types.TrustCenterAccess, error)
Document(ctx context.Context, obj *types.TrustCenterDocumentAccess) (*types.Document, error) Document(ctx context.Context, obj *types.TrustCenterDocumentAccess) (*types.Document, error)
Report(ctx context.Context, obj *types.TrustCenterDocumentAccess) (*types.Report, error) Report(ctx context.Context, obj *types.TrustCenterDocumentAccess) (*types.Report, error)
TrustCenterFile(ctx context.Context, obj *types.TrustCenterDocumentAccess) (*types.TrustCenterFile, 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 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": case "TrustCenterAccess.createdAt":
if e.complexity.TrustCenterAccess.CreatedAt == nil { if e.complexity.TrustCenterAccess.CreatedAt == nil {
break break
@@ -7616,18 +7636,6 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
return e.complexity.TrustCenterAccess.CreatedAt(childComplexity), true 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": case "TrustCenterAccess.email":
if e.complexity.TrustCenterAccess.Email == nil { if e.complexity.TrustCenterAccess.Email == nil {
break break
@@ -7649,6 +7657,13 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
return e.complexity.TrustCenterAccess.ID(childComplexity), true 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": case "TrustCenterAccess.name":
if e.complexity.TrustCenterAccess.Name == nil { if e.complexity.TrustCenterAccess.Name == nil {
break break
@@ -7656,6 +7671,13 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
return e.complexity.TrustCenterAccess.Name(childComplexity), true 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": case "TrustCenterAccess.updatedAt":
if e.complexity.TrustCenterAccess.UpdatedAt == nil { if e.complexity.TrustCenterAccess.UpdatedAt == nil {
break break
@@ -7712,13 +7734,6 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
return e.complexity.TrustCenterDocumentAccess.Active(childComplexity), true 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": case "TrustCenterDocumentAccess.document":
if e.complexity.TrustCenterDocumentAccess.Document == nil { if e.complexity.TrustCenterDocumentAccess.Document == nil {
break break
@@ -7726,13 +7741,6 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
return e.complexity.TrustCenterDocumentAccess.Document(childComplexity), true 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": case "TrustCenterDocumentAccess.report":
if e.complexity.TrustCenterDocumentAccess.Report == nil { if e.complexity.TrustCenterDocumentAccess.Report == nil {
break break
@@ -7740,12 +7748,12 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
return e.complexity.TrustCenterDocumentAccess.Report(childComplexity), true return e.complexity.TrustCenterDocumentAccess.Report(childComplexity), true
case "TrustCenterDocumentAccess.trustCenterAccess": case "TrustCenterDocumentAccess.requested":
if e.complexity.TrustCenterDocumentAccess.TrustCenterAccess == nil { if e.complexity.TrustCenterDocumentAccess.Requested == nil {
break break
} }
return e.complexity.TrustCenterDocumentAccess.TrustCenterAccess(childComplexity), true return e.complexity.TrustCenterDocumentAccess.Requested(childComplexity), true
case "TrustCenterDocumentAccess.trustCenterFile": case "TrustCenterDocumentAccess.trustCenterFile":
if e.complexity.TrustCenterDocumentAccess.TrustCenterFile == nil { 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 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": case "TrustCenterDocumentAccessConnection.edges":
if e.complexity.TrustCenterDocumentAccessConnection.Edges == nil { if e.complexity.TrustCenterDocumentAccessConnection.Edges == nil {
break break
@@ -11724,8 +11725,11 @@ type TrustCenterAccess implements Node {
hasAcceptedNonDisclosureAgreement: Boolean! hasAcceptedNonDisclosureAgreement: Boolean!
createdAt: Datetime! createdAt: Datetime!
updatedAt: Datetime! updatedAt: Datetime!
lastTokenExpiresAt: Datetime
pendingRequestCount: Int! @goField(forceResolver: true)
activeCount: Int! @goField(forceResolver: true)
documentAccesses( availableDocumentAccesses(
first: Int first: Int
after: CursorKey after: CursorKey
last: Int last: Int
@@ -11734,12 +11738,12 @@ type TrustCenterAccess implements Node {
): TrustCenterDocumentAccessConnection! @goField(forceResolver: true) ): TrustCenterDocumentAccessConnection! @goField(forceResolver: true)
} }
type TrustCenterDocumentAccess implements Node { type TrustCenterDocumentAccess
id: ID! @goModel(
model: "github.com/getprobo/probo/pkg/server/api/console/v1/types.TrustCenterDocumentAccess"
) {
active: Boolean! active: Boolean!
createdAt: Datetime! requested: Boolean!
updatedAt: Datetime!
trustCenterAccess: TrustCenterAccess! @goField(forceResolver: true)
document: Document @goField(forceResolver: true) document: Document @goField(forceResolver: true)
report: Report @goField(forceResolver: true) report: Report @goField(forceResolver: true)
trustCenterFile: TrustCenterFile @goField(forceResolver: true) trustCenterFile: TrustCenterFile @goField(forceResolver: true)
@@ -21371,37 +21375,37 @@ func (ec *executionContext) field_Task_evidences_argsOrderBy(
return zeroVal, nil 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 var err error
args := map[string]any{} 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 { if err != nil {
return nil, err return nil, err
} }
args["first"] = arg0 args["first"] = arg0
arg1, err := ec.field_TrustCenterAccess_documentAccesses_argsAfter(ctx, rawArgs) arg1, err := ec.field_TrustCenterAccess_availableDocumentAccesses_argsAfter(ctx, rawArgs)
if err != nil { if err != nil {
return nil, err return nil, err
} }
args["after"] = arg1 args["after"] = arg1
arg2, err := ec.field_TrustCenterAccess_documentAccesses_argsLast(ctx, rawArgs) arg2, err := ec.field_TrustCenterAccess_availableDocumentAccesses_argsLast(ctx, rawArgs)
if err != nil { if err != nil {
return nil, err return nil, err
} }
args["last"] = arg2 args["last"] = arg2
arg3, err := ec.field_TrustCenterAccess_documentAccesses_argsBefore(ctx, rawArgs) arg3, err := ec.field_TrustCenterAccess_availableDocumentAccesses_argsBefore(ctx, rawArgs)
if err != nil { if err != nil {
return nil, err return nil, err
} }
args["before"] = arg3 args["before"] = arg3
arg4, err := ec.field_TrustCenterAccess_documentAccesses_argsOrderBy(ctx, rawArgs) arg4, err := ec.field_TrustCenterAccess_availableDocumentAccesses_argsOrderBy(ctx, rawArgs)
if err != nil { if err != nil {
return nil, err return nil, err
} }
args["orderBy"] = arg4 args["orderBy"] = arg4
return args, nil return args, nil
} }
func (ec *executionContext) field_TrustCenterAccess_documentAccesses_argsFirst( func (ec *executionContext) field_TrustCenterAccess_availableDocumentAccesses_argsFirst(
ctx context.Context, ctx context.Context,
rawArgs map[string]any, rawArgs map[string]any,
) (*int, error) { ) (*int, error) {
@@ -21414,7 +21418,7 @@ func (ec *executionContext) field_TrustCenterAccess_documentAccesses_argsFirst(
return zeroVal, nil return zeroVal, nil
} }
func (ec *executionContext) field_TrustCenterAccess_documentAccesses_argsAfter( func (ec *executionContext) field_TrustCenterAccess_availableDocumentAccesses_argsAfter(
ctx context.Context, ctx context.Context,
rawArgs map[string]any, rawArgs map[string]any,
) (*page.CursorKey, error) { ) (*page.CursorKey, error) {
@@ -21427,7 +21431,7 @@ func (ec *executionContext) field_TrustCenterAccess_documentAccesses_argsAfter(
return zeroVal, nil return zeroVal, nil
} }
func (ec *executionContext) field_TrustCenterAccess_documentAccesses_argsLast( func (ec *executionContext) field_TrustCenterAccess_availableDocumentAccesses_argsLast(
ctx context.Context, ctx context.Context,
rawArgs map[string]any, rawArgs map[string]any,
) (*int, error) { ) (*int, error) {
@@ -21440,7 +21444,7 @@ func (ec *executionContext) field_TrustCenterAccess_documentAccesses_argsLast(
return zeroVal, nil return zeroVal, nil
} }
func (ec *executionContext) field_TrustCenterAccess_documentAccesses_argsBefore( func (ec *executionContext) field_TrustCenterAccess_availableDocumentAccesses_argsBefore(
ctx context.Context, ctx context.Context,
rawArgs map[string]any, rawArgs map[string]any,
) (*page.CursorKey, error) { ) (*page.CursorKey, error) {
@@ -21453,7 +21457,7 @@ func (ec *executionContext) field_TrustCenterAccess_documentAccesses_argsBefore(
return zeroVal, nil return zeroVal, nil
} }
func (ec *executionContext) field_TrustCenterAccess_documentAccesses_argsOrderBy( func (ec *executionContext) field_TrustCenterAccess_availableDocumentAccesses_argsOrderBy(
ctx context.Context, ctx context.Context,
rawArgs map[string]any, rawArgs map[string]any,
) (*types.OrderBy[coredata.TrustCenterDocumentAccessOrderField], error) { ) (*types.OrderBy[coredata.TrustCenterDocumentAccessOrderField], error) {
@@ -57622,8 +57626,8 @@ func (ec *executionContext) fieldContext_TrustCenterAccess_updatedAt(_ context.C
return fc, nil return fc, nil
} }
func (ec *executionContext) _TrustCenterAccess_documentAccesses(ctx context.Context, field graphql.CollectedField, obj *types.TrustCenterAccess) (ret graphql.Marshaler) { func (ec *executionContext) _TrustCenterAccess_lastTokenExpiresAt(ctx context.Context, field graphql.CollectedField, obj *types.TrustCenterAccess) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_TrustCenterAccess_documentAccesses(ctx, field) fc, err := ec.fieldContext_TrustCenterAccess_lastTokenExpiresAt(ctx, field)
if err != nil { if err != nil {
return graphql.Null 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) { resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
ctx = rctx // use context from middleware stack in children 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 { if err != nil {
ec.Error(ctx, err) 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) 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{ fc = &graphql.FieldContext{
Object: "TrustCenterAccess", Object: "TrustCenterAccess",
Field: field, Field: field,
@@ -57678,7 +57811,7 @@ func (ec *executionContext) fieldContext_TrustCenterAccess_documentAccesses(ctx
} }
}() }()
ctx = graphql.WithFieldContext(ctx, fc) 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) ec.Error(ctx, err)
return fc, err return fc, err
} }
@@ -57886,8 +58019,14 @@ func (ec *executionContext) fieldContext_TrustCenterAccessEdge_node(_ context.Co
return ec.fieldContext_TrustCenterAccess_createdAt(ctx, field) return ec.fieldContext_TrustCenterAccess_createdAt(ctx, field)
case "updatedAt": case "updatedAt":
return ec.fieldContext_TrustCenterAccess_updatedAt(ctx, field) return ec.fieldContext_TrustCenterAccess_updatedAt(ctx, field)
case "documentAccesses": case "lastTokenExpiresAt":
return ec.fieldContext_TrustCenterAccess_documentAccesses(ctx, field) 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) 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 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) { 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) fc, err := ec.fieldContext_TrustCenterDocumentAccess_active(ctx, field)
if err != nil { if err != nil {
@@ -58087,8 +58182,8 @@ func (ec *executionContext) fieldContext_TrustCenterDocumentAccess_active(_ cont
return fc, nil return fc, nil
} }
func (ec *executionContext) _TrustCenterDocumentAccess_createdAt(ctx context.Context, field graphql.CollectedField, obj *types.TrustCenterDocumentAccess) (ret graphql.Marshaler) { func (ec *executionContext) _TrustCenterDocumentAccess_requested(ctx context.Context, field graphql.CollectedField, obj *types.TrustCenterDocumentAccess) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_TrustCenterDocumentAccess_createdAt(ctx, field) fc, err := ec.fieldContext_TrustCenterDocumentAccess_requested(ctx, field)
if err != nil { if err != nil {
return graphql.Null 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) { resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
ctx = rctx // use context from middleware stack in children ctx = rctx // use context from middleware stack in children
return obj.CreatedAt, nil return obj.Requested, nil
}) })
if err != nil { if err != nil {
ec.Error(ctx, err) ec.Error(ctx, err)
@@ -58113,125 +58208,19 @@ func (ec *executionContext) _TrustCenterDocumentAccess_createdAt(ctx context.Con
} }
return graphql.Null return graphql.Null
} }
res := resTmp.(time.Time) res := resTmp.(bool)
fc.Result = res 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{ fc = &graphql.FieldContext{
Object: "TrustCenterDocumentAccess", Object: "TrustCenterDocumentAccess",
Field: field, Field: field,
IsMethod: false, IsMethod: false,
IsResolver: false, IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { 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 nil, errors.New("field of type Boolean 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 fc, nil return fc, nil
@@ -58657,16 +58646,10 @@ func (ec *executionContext) fieldContext_TrustCenterDocumentAccessEdge_node(_ co
IsResolver: false, IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
switch field.Name { switch field.Name {
case "id":
return ec.fieldContext_TrustCenterDocumentAccess_id(ctx, field)
case "active": case "active":
return ec.fieldContext_TrustCenterDocumentAccess_active(ctx, field) return ec.fieldContext_TrustCenterDocumentAccess_active(ctx, field)
case "createdAt": case "requested":
return ec.fieldContext_TrustCenterDocumentAccess_createdAt(ctx, field) return ec.fieldContext_TrustCenterDocumentAccess_requested(ctx, field)
case "updatedAt":
return ec.fieldContext_TrustCenterDocumentAccess_updatedAt(ctx, field)
case "trustCenterAccess":
return ec.fieldContext_TrustCenterDocumentAccess_trustCenterAccess(ctx, field)
case "document": case "document":
return ec.fieldContext_TrustCenterDocumentAccess_document(ctx, field) return ec.fieldContext_TrustCenterDocumentAccess_document(ctx, field)
case "report": case "report":
@@ -61337,8 +61320,14 @@ func (ec *executionContext) fieldContext_UpdateTrustCenterAccessPayload_trustCen
return ec.fieldContext_TrustCenterAccess_createdAt(ctx, field) return ec.fieldContext_TrustCenterAccess_createdAt(ctx, field)
case "updatedAt": case "updatedAt":
return ec.fieldContext_TrustCenterAccess_updatedAt(ctx, field) return ec.fieldContext_TrustCenterAccess_updatedAt(ctx, field)
case "documentAccesses": case "lastTokenExpiresAt":
return ec.fieldContext_TrustCenterAccess_documentAccesses(ctx, field) 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) 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 graphql.Null
} }
return ec._TrustCenterFile(ctx, sel, obj) 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: case types.TrustCenterAccess:
return ec._TrustCenterAccess(ctx, sel, &obj) return ec._TrustCenterAccess(ctx, sel, &obj)
case *types.TrustCenterAccess: case *types.TrustCenterAccess:
@@ -90142,7 +90124,9 @@ func (ec *executionContext) _TrustCenterAccess(ctx context.Context, sel ast.Sele
if out.Values[i] == graphql.Null { if out.Values[i] == graphql.Null {
atomic.AddUint32(&out.Invalids, 1) atomic.AddUint32(&out.Invalids, 1)
} }
case "documentAccesses": case "lastTokenExpiresAt":
out.Values[i] = ec._TrustCenterAccess_lastTokenExpiresAt(ctx, field, obj)
case "pendingRequestCount":
field := field field := field
innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { 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)) 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 { if res == graphql.Null {
atomic.AddUint32(&fs.Invalids, 1) atomic.AddUint32(&fs.Invalids, 1)
} }
@@ -90333,7 +90389,7 @@ func (ec *executionContext) _TrustCenterConnection(ctx context.Context, sel ast.
return out 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 { func (ec *executionContext) _TrustCenterDocumentAccess(ctx context.Context, sel ast.SelectionSet, obj *types.TrustCenterDocumentAccess) graphql.Marshaler {
fields := graphql.CollectFields(ec.OperationContext, sel, trustCenterDocumentAccessImplementors) fields := graphql.CollectFields(ec.OperationContext, sel, trustCenterDocumentAccessImplementors)
@@ -90344,62 +90400,16 @@ func (ec *executionContext) _TrustCenterDocumentAccess(ctx context.Context, sel
switch field.Name { switch field.Name {
case "__typename": case "__typename":
out.Values[i] = graphql.MarshalString("TrustCenterDocumentAccess") 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": case "active":
out.Values[i] = ec._TrustCenterDocumentAccess_active(ctx, field, obj) out.Values[i] = ec._TrustCenterDocumentAccess_active(ctx, field, obj)
if out.Values[i] == graphql.Null { if out.Values[i] == graphql.Null {
atomic.AddUint32(&out.Invalids, 1) atomic.AddUint32(&out.Invalids, 1)
} }
case "createdAt": case "requested":
out.Values[i] = ec._TrustCenterDocumentAccess_createdAt(ctx, field, obj) out.Values[i] = ec._TrustCenterDocumentAccess_requested(ctx, field, obj)
if out.Values[i] == graphql.Null { if out.Values[i] == graphql.Null {
atomic.AddUint32(&out.Invalids, 1) 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": case "document":
field := field field := field
@@ -100961,10 +100971,6 @@ func (ec *executionContext) marshalNTrustCenter2ᚖgithubᚗcomᚋgetproboᚋpro
return ec._TrustCenter(ctx, sel, v) 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 { 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 v == nil {
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {

View File

@@ -15,6 +15,8 @@
package types package types
import ( import (
"time"
"github.com/getprobo/probo/pkg/coredata" "github.com/getprobo/probo/pkg/coredata"
"github.com/getprobo/probo/pkg/gid" "github.com/getprobo/probo/pkg/gid"
"github.com/getprobo/probo/pkg/page" "github.com/getprobo/probo/pkg/page"
@@ -31,14 +33,35 @@ type (
Resolver any Resolver any
ParentID gid.GID 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 { func NewTrustCenterDocumentAccess(tcda *coredata.TrustCenterDocumentAccess) *TrustCenterDocumentAccess {
return &TrustCenterDocumentAccess{ return &TrustCenterDocumentAccess{
ID: tcda.ID, ID: tcda.ID,
Active: tcda.Active, Active: tcda.Active,
CreatedAt: tcda.CreatedAt, Requested: tcda.Requested,
UpdatedAt: tcda.UpdatedAt, CreatedAt: tcda.CreatedAt,
UpdatedAt: tcda.UpdatedAt,
DocumentID: tcda.DocumentID,
ReportID: tcda.ReportID,
TrustCenterFileID: tcda.TrustCenterFileID,
} }
} }

View File

@@ -1675,7 +1675,10 @@ type TrustCenterAccess struct {
HasAcceptedNonDisclosureAgreement bool `json:"hasAcceptedNonDisclosureAgreement"` HasAcceptedNonDisclosureAgreement bool `json:"hasAcceptedNonDisclosureAgreement"`
CreatedAt time.Time `json:"createdAt"` CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"` 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() {} func (TrustCenterAccess) IsNode() {}
@@ -1696,20 +1699,6 @@ type TrustCenterConnection struct {
PageInfo *PageInfo `json:"pageInfo"` 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 { type TrustCenterDocumentAccessEdge struct {
Cursor page.CursorKey `json:"cursor"` Cursor page.CursorKey `json:"cursor"`
Node *TrustCenterDocumentAccess `json:"node"` Node *TrustCenterDocumentAccess `json:"node"`

View File

@@ -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) { func (r *mutationResolver) GetTrustCenterFile(ctx context.Context, input types.GetTrustCenterFileInput) (*types.GetTrustCenterFilePayload, error) {
prb := r.ProboService(ctx, input.ID.TenantID()) prb := r.ProboService(ctx, input.ID.TenantID())
file, err := prb.TrustCenterFiles.Get(ctx, &probo.GetTrustCenterFileRequest{ file, err := prb.TrustCenterFiles.Get(ctx, input.ID)
ID: input.ID,
})
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot get trust center file: %w", err) 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 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: default:
} }
@@ -4959,8 +4964,32 @@ func (r *trustCenterResolver) References(ctx context.Context, obj *types.TrustCe
return types.NewTrustCenterReferenceConnection(result, obj.ID), nil return types.NewTrustCenterReferenceConnection(result, obj.ID), nil
} }
// DocumentAccesses is the resolver for the documentAccesses field. // PendingRequestCount is the resolver for the pendingRequestCount 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) { 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()) prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.TrustCenterDocumentAccessOrderField]{ 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) 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 { if err != nil {
panic(fmt.Errorf("cannot list trust center document accesses: %w", err)) 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 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. // Document is the resolver for the document field.
func (r *trustCenterDocumentAccessResolver) Document(ctx context.Context, obj *types.TrustCenterDocumentAccess) (*types.Document, error) { func (r *trustCenterDocumentAccessResolver) Document(ctx context.Context, obj *types.TrustCenterDocumentAccess) (*types.Document, error) {
prb := r.ProboService(ctx, obj.ID.TenantID()) if obj.DocumentID == nil {
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 {
return nil, 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 { if err != nil {
return nil, fmt.Errorf("cannot load document: %w", err) 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. // Report is the resolver for the report field.
func (r *trustCenterDocumentAccessResolver) Report(ctx context.Context, obj *types.TrustCenterDocumentAccess) (*types.Report, error) { func (r *trustCenterDocumentAccessResolver) Report(ctx context.Context, obj *types.TrustCenterDocumentAccess) (*types.Report, error) {
prb := r.ProboService(ctx, obj.ID.TenantID()) if obj.ReportID == nil {
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 {
return nil, 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 { if err != nil {
return nil, fmt.Errorf("cannot load report: %w", err) 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. // TrustCenterFile is the resolver for the trustCenterFile field.
func (r *trustCenterDocumentAccessResolver) TrustCenterFile(ctx context.Context, obj *types.TrustCenterDocumentAccess) (*types.TrustCenterFile, error) { func (r *trustCenterDocumentAccessResolver) TrustCenterFile(ctx context.Context, obj *types.TrustCenterDocumentAccess) (*types.TrustCenterFile, error) {
prb := r.ProboService(ctx, obj.ID.TenantID()) if obj.TrustCenterFileID == nil {
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 {
return nil, nil return nil, nil
} }
trustCenterFile, err := prb.TrustCenterFiles.Get(ctx, &probo.GetTrustCenterFileRequest{ prb := r.ProboService(ctx, obj.ID.TenantID())
ID: *documentAccess.TrustCenterFileID,
}) trustCenterFile, err := prb.TrustCenterFiles.Get(ctx, *obj.TrustCenterFileID)
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot load trust center file: %w", err) 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) { func (r *trustCenterFileResolver) Organization(ctx context.Context, obj *types.TrustCenterFile) (*types.Organization, error) {
prb := r.ProboService(ctx, obj.ID.TenantID()) prb := r.ProboService(ctx, obj.ID.TenantID())
file, err := prb.TrustCenterFiles.Get(ctx, &probo.GetTrustCenterFileRequest{ file, err := prb.TrustCenterFiles.Get(ctx, obj.ID)
ID: obj.ID,
})
if err != nil { if err != nil {
panic(fmt.Errorf("cannot get trust center file: %w", err)) panic(fmt.Errorf("cannot get trust center file: %w", err))
} }

View File

@@ -208,15 +208,15 @@ func (s TrustCenterAccessService) Request(
var accesses coredata.TrustCenterDocumentAccesses 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) 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) 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) 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) return fmt.Errorf("cannot load trust center access: %w", err)
} }
wasInactive := !access.Active shouldSendEmail := !access.Active
now := time.Now() now := time.Now()
if len(documentIDs) > 0 { if len(documentIDs) > 0 {
@@ -428,7 +428,7 @@ func (s *TrustCenterAccessService) AcceptByIDs(
} }
} }
if wasInactive { if shouldSendEmail {
access.Active = true access.Active = true
access.UpdatedAt = now access.UpdatedAt = now
if err := access.Update(ctx, tx, s.svc.scope); err != nil { 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(), }.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()) return s.sendTrustCenterAccessEmail(ctx, tx, access.Name, access.Email, organization.Name, accessURL.String())
} }
@@ -512,6 +521,7 @@ func (s *TrustCenterAccessService) sendTrustCenterAccessEmail(
name, name,
companyName, companyName,
accessURL, accessURL,
s.svc.trustConfig.TokenDuration,
) )
if err != nil { if err != nil {
return fmt.Errorf("cannot render trust center access email: %w", err) return fmt.Errorf("cannot render trust center access email: %w", err)