Fix trust center audist documents files tabs permissions handling

Signed-off-by: Émile Ré <nemile.re@gmail.com>
This commit is contained in:
Émile Ré
2025-12-31 12:26:28 +01:00
committed by Bryan Frimin
parent 8d51888895
commit 0103f90918
15 changed files with 438 additions and 223 deletions

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<0defaaf1ce3544420e8fbd9c9f3af139>> * @generated SignedSource<<d98ea0f9e8ca507260465079e6073838>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -12,6 +12,8 @@ import { ReaderFragment } from 'relay-runtime';
export type TrustCenterVisibility = "NONE" | "PRIVATE" | "PUBLIC"; export type TrustCenterVisibility = "NONE" | "PRIVATE" | "PUBLIC";
import { FragmentRefs } from "relay-runtime"; import { FragmentRefs } from "relay-runtime";
export type TrustCenterFilesCardFragment$data = { export type TrustCenterFilesCardFragment$data = {
readonly canDelete: boolean;
readonly canUpdate: boolean;
readonly category: string; readonly category: string;
readonly createdAt: any; readonly createdAt: any;
readonly fileUrl: string; readonly fileUrl: string;
@@ -80,12 +82,38 @@ const node: ReaderFragment = {
"kind": "ScalarField", "kind": "ScalarField",
"name": "updatedAt", "name": "updatedAt",
"storageKey": null "storageKey": null
},
{
"alias": "canUpdate",
"args": [
{
"kind": "Literal",
"name": "action",
"value": "core:trust-center-file:update"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:trust-center-file:update\")"
},
{
"alias": "canDelete",
"args": [
{
"kind": "Literal",
"name": "action",
"value": "core:trust-center-file:delete"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:trust-center-file:delete\")"
} }
], ],
"type": "TrustCenterFile", "type": "TrustCenterFile",
"abstractKey": null "abstractKey": null
}; };
(node as any).hash = "33cb01782ca37fc776cd8e5dfde20f76"; (node as any).hash = "7b9e482868fc5d815923fbefdbafc8bb";
export default node; export default node;

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<f52778bf4020037a3a76f29c2a7c6b39>> * @generated SignedSource<<e67073eb7045d7e1b44337df273de6e0>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -23,6 +23,7 @@ export type TrustCenterGraphQuery$data = {
}; };
}>; }>;
}; };
readonly canCreateTrustCenterFile?: boolean;
readonly customDomain?: { readonly customDomain?: {
readonly domain: string; readonly domain: string;
readonly id: string; readonly id: string;
@@ -50,7 +51,10 @@ export type TrustCenterGraphQuery$data = {
}; };
readonly trustCenter?: { readonly trustCenter?: {
readonly active: boolean; readonly active: boolean;
readonly canDeleteNDA: boolean;
readonly canGetNDA: boolean;
readonly canUpdate: boolean; readonly canUpdate: boolean;
readonly canUploadNDA: boolean;
readonly createdAt: any; readonly createdAt: any;
readonly id: string; readonly id: string;
readonly ndaFileName: string | null | undefined; readonly ndaFileName: string | null | undefined;
@@ -124,6 +128,19 @@ v3 = {
"storageKey": null "storageKey": null
}, },
v4 = { v4 = {
"alias": "canCreateTrustCenterFile",
"args": [
{
"kind": "Literal",
"name": "action",
"value": "core:trust-center-file:create"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:trust-center-file:create\")"
},
v5 = {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "CustomDomain", "concreteType": "CustomDomain",
@@ -142,33 +159,33 @@ v4 = {
], ],
"storageKey": null "storageKey": null
}, },
v5 = { v6 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "createdAt", "name": "createdAt",
"storageKey": null "storageKey": null
}, },
v6 = { v7 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "updatedAt", "name": "updatedAt",
"storageKey": null "storageKey": null
}, },
v7 = { v8 = {
"kind": "Literal", "kind": "Literal",
"name": "first", "name": "first",
"value": 100 "value": 100
}, },
v8 = { v9 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "description", "name": "description",
"storageKey": null "storageKey": null
}, },
v9 = { v10 = {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "TrustCenter", "concreteType": "TrustCenter",
@@ -198,8 +215,8 @@ v9 = {
"name": "ndaFileUrl", "name": "ndaFileUrl",
"storageKey": null "storageKey": null
}, },
(v5/*: any*/),
(v6/*: any*/), (v6/*: any*/),
(v7/*: any*/),
{ {
"alias": "canUpdate", "alias": "canUpdate",
"args": [ "args": [
@@ -213,10 +230,49 @@ v9 = {
"name": "permission", "name": "permission",
"storageKey": "permission(action:\"core:trust-center:update\")" "storageKey": "permission(action:\"core:trust-center:update\")"
}, },
{
"alias": "canGetNDA",
"args": [
{
"kind": "Literal",
"name": "action",
"value": "core:trust-center:get-nda"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:trust-center:get-nda\")"
},
{
"alias": "canUploadNDA",
"args": [
{
"kind": "Literal",
"name": "action",
"value": "core:trust-center:upload-nda"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:trust-center:upload-nda\")"
},
{
"alias": "canDeleteNDA",
"args": [
{
"kind": "Literal",
"name": "action",
"value": "core:trust-center:delete-nda"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:trust-center:delete-nda\")"
},
{ {
"alias": null, "alias": null,
"args": [ "args": [
(v7/*: any*/), (v8/*: any*/),
{ {
"kind": "Literal", "kind": "Literal",
"name": "orderBy", "name": "orderBy",
@@ -249,7 +305,7 @@ v9 = {
"selections": [ "selections": [
(v2/*: any*/), (v2/*: any*/),
(v3/*: any*/), (v3/*: any*/),
(v8/*: any*/), (v9/*: any*/),
{ {
"alias": null, "alias": null,
"args": null, "args": null,
@@ -264,8 +320,8 @@ v9 = {
"name": "logoUrl", "name": "logoUrl",
"storageKey": null "storageKey": null
}, },
(v5/*: any*/), (v6/*: any*/),
(v6/*: any*/) (v7/*: any*/)
], ],
"storageKey": null "storageKey": null
} }
@@ -278,24 +334,24 @@ v9 = {
], ],
"storageKey": null "storageKey": null
}, },
v10 = [ v11 = [
(v7/*: any*/) (v8/*: any*/)
], ],
v11 = { v12 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "__typename", "name": "__typename",
"storageKey": null "storageKey": null
}, },
v12 = { v13 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "cursor", "name": "cursor",
"storageKey": null "storageKey": null
}, },
v13 = { v14 = {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PageInfo", "concreteType": "PageInfo",
@@ -320,7 +376,7 @@ v13 = {
], ],
"storageKey": null "storageKey": null
}, },
v14 = { v15 = {
"kind": "ClientExtension", "kind": "ClientExtension",
"selections": [ "selections": [
{ {
@@ -332,9 +388,9 @@ v14 = {
} }
] ]
}, },
v15 = { v16 = {
"alias": null, "alias": null,
"args": (v10/*: any*/), "args": (v11/*: any*/),
"concreteType": "SlackConnectionConnection", "concreteType": "SlackConnectionConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "slackConnections", "name": "slackConnections",
@@ -371,8 +427,8 @@ v15 = {
"name": "channelId", "name": "channelId",
"storageKey": null "storageKey": null
}, },
(v5/*: any*/), (v6/*: any*/),
(v6/*: any*/) (v7/*: any*/)
], ],
"storageKey": null "storageKey": null
} }
@@ -382,14 +438,14 @@ v15 = {
], ],
"storageKey": "slackConnections(first:100)" "storageKey": "slackConnections(first:100)"
}, },
v16 = { v17 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "trustCenterVisibility", "name": "trustCenterVisibility",
"storageKey": null "storageKey": null
}, },
v17 = { v18 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
@@ -417,10 +473,11 @@ return {
(v2/*: any*/), (v2/*: any*/),
(v3/*: any*/), (v3/*: any*/),
(v4/*: any*/), (v4/*: any*/),
(v9/*: any*/), (v5/*: any*/),
(v10/*: any*/),
{ {
"alias": null, "alias": null,
"args": (v10/*: any*/), "args": (v11/*: any*/),
"concreteType": "DocumentConnection", "concreteType": "DocumentConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "documents", "name": "documents",
@@ -459,7 +516,7 @@ return {
}, },
{ {
"alias": null, "alias": null,
"args": (v10/*: any*/), "args": (v11/*: any*/),
"concreteType": "AuditConnection", "concreteType": "AuditConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "audits", "name": "audits",
@@ -498,7 +555,7 @@ return {
}, },
{ {
"alias": null, "alias": null,
"args": (v10/*: any*/), "args": (v11/*: any*/),
"concreteType": "VendorConnection", "concreteType": "VendorConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "vendors", "name": "vendors",
@@ -565,20 +622,20 @@ return {
"kind": "FragmentSpread", "kind": "FragmentSpread",
"name": "TrustCenterFilesCardFragment" "name": "TrustCenterFilesCardFragment"
}, },
(v11/*: any*/) (v12/*: any*/)
], ],
"storageKey": null "storageKey": null
}, },
(v12/*: any*/) (v13/*: any*/)
], ],
"storageKey": null "storageKey": null
}, },
(v13/*: any*/), (v14/*: any*/),
(v14/*: any*/) (v15/*: any*/)
], ],
"storageKey": null "storageKey": null
}, },
(v15/*: any*/) (v16/*: any*/)
], ],
"type": "Organization", "type": "Organization",
"abstractKey": null "abstractKey": null
@@ -604,17 +661,18 @@ return {
"name": "node", "name": "node",
"plural": false, "plural": false,
"selections": [ "selections": [
(v11/*: any*/), (v12/*: any*/),
(v2/*: any*/), (v2/*: any*/),
{ {
"kind": "InlineFragment", "kind": "InlineFragment",
"selections": [ "selections": [
(v3/*: any*/), (v3/*: any*/),
(v4/*: any*/), (v4/*: any*/),
(v9/*: any*/), (v5/*: any*/),
(v10/*: any*/),
{ {
"alias": null, "alias": null,
"args": (v10/*: any*/), "args": (v11/*: any*/),
"concreteType": "DocumentConnection", "concreteType": "DocumentConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "documents", "name": "documents",
@@ -644,7 +702,7 @@ return {
"name": "title", "name": "title",
"storageKey": null "storageKey": null
}, },
(v5/*: any*/), (v6/*: any*/),
{ {
"alias": null, "alias": null,
"args": null, "args": null,
@@ -652,7 +710,7 @@ return {
"name": "documentType", "name": "documentType",
"storageKey": null "storageKey": null
}, },
(v16/*: any*/), (v17/*: any*/),
{ {
"alias": null, "alias": null,
"args": [ "args": [
@@ -711,7 +769,7 @@ return {
}, },
{ {
"alias": null, "alias": null,
"args": (v10/*: any*/), "args": (v11/*: any*/),
"concreteType": "AuditConnection", "concreteType": "AuditConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "audits", "name": "audits",
@@ -769,8 +827,8 @@ return {
"name": "state", "name": "state",
"storageKey": null "storageKey": null
}, },
(v16/*: any*/), (v17/*: any*/),
(v5/*: any*/) (v6/*: any*/)
], ],
"storageKey": null "storageKey": null
} }
@@ -782,7 +840,7 @@ return {
}, },
{ {
"alias": null, "alias": null,
"args": (v10/*: any*/), "args": (v11/*: any*/),
"concreteType": "VendorConnection", "concreteType": "VendorConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "vendors", "name": "vendors",
@@ -806,8 +864,8 @@ return {
"selections": [ "selections": [
(v2/*: any*/), (v2/*: any*/),
(v3/*: any*/), (v3/*: any*/),
(v17/*: any*/), (v18/*: any*/),
(v8/*: any*/), (v9/*: any*/),
{ {
"alias": null, "alias": null,
"args": null, "args": null,
@@ -815,7 +873,7 @@ return {
"name": "showOnTrustCenter", "name": "showOnTrustCenter",
"storageKey": null "storageKey": null
}, },
(v5/*: any*/) (v6/*: any*/)
], ],
"storageKey": null "storageKey": null
} }
@@ -827,7 +885,7 @@ return {
}, },
{ {
"alias": null, "alias": null,
"args": (v10/*: any*/), "args": (v11/*: any*/),
"concreteType": "TrustCenterFileConnection", "concreteType": "TrustCenterFileConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "trustCenterFiles", "name": "trustCenterFiles",
@@ -851,7 +909,7 @@ return {
"selections": [ "selections": [
(v2/*: any*/), (v2/*: any*/),
(v3/*: any*/), (v3/*: any*/),
(v17/*: any*/), (v18/*: any*/),
{ {
"alias": null, "alias": null,
"args": null, "args": null,
@@ -859,32 +917,58 @@ return {
"name": "fileUrl", "name": "fileUrl",
"storageKey": null "storageKey": null
}, },
(v16/*: any*/), (v17/*: any*/),
(v5/*: any*/),
(v6/*: any*/), (v6/*: any*/),
(v11/*: any*/) (v7/*: any*/),
{
"alias": "canUpdate",
"args": [
{
"kind": "Literal",
"name": "action",
"value": "core:trust-center-file:update"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:trust-center-file:update\")"
},
{
"alias": "canDelete",
"args": [
{
"kind": "Literal",
"name": "action",
"value": "core:trust-center-file:delete"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:trust-center-file:delete\")"
},
(v12/*: any*/)
], ],
"storageKey": null "storageKey": null
}, },
(v12/*: any*/) (v13/*: any*/)
], ],
"storageKey": null "storageKey": null
}, },
(v13/*: any*/), (v14/*: any*/),
(v14/*: any*/) (v15/*: any*/)
], ],
"storageKey": "trustCenterFiles(first:100)" "storageKey": "trustCenterFiles(first:100)"
}, },
{ {
"alias": null, "alias": null,
"args": (v10/*: any*/), "args": (v11/*: any*/),
"filters": null, "filters": null,
"handle": "connection", "handle": "connection",
"key": "TrustCenterPage_trustCenterFiles", "key": "TrustCenterPage_trustCenterFiles",
"kind": "LinkedHandle", "kind": "LinkedHandle",
"name": "trustCenterFiles" "name": "trustCenterFiles"
}, },
(v15/*: any*/) (v16/*: any*/)
], ],
"type": "Organization", "type": "Organization",
"abstractKey": null "abstractKey": null
@@ -895,7 +979,7 @@ return {
] ]
}, },
"params": { "params": {
"cacheID": "77cfcb8a51459702b07cd2295688ad07", "cacheID": "0fbd1275d4051e236a6f9711cf21c23b",
"id": null, "id": null,
"metadata": { "metadata": {
"connection": [ "connection": [
@@ -912,11 +996,11 @@ return {
}, },
"name": "TrustCenterGraphQuery", "name": "TrustCenterGraphQuery",
"operationKind": "query", "operationKind": "query",
"text": "query TrustCenterGraphQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n ... on Organization {\n id\n name\n customDomain {\n id\n domain\n }\n trustCenter {\n id\n active\n ndaFileName\n ndaFileUrl\n createdAt\n updatedAt\n canUpdate: permission(action: \"core:trust-center:update\")\n references(first: 100, orderBy: {field: CREATED_AT, direction: DESC}) {\n edges {\n node {\n id\n name\n description\n websiteUrl\n logoUrl\n createdAt\n updatedAt\n }\n }\n }\n }\n documents(first: 100) {\n edges {\n node {\n id\n ...TrustCenterDocumentsCardFragment\n }\n }\n }\n audits(first: 100) {\n edges {\n node {\n id\n ...TrustCenterAuditsCardFragment\n }\n }\n }\n vendors(first: 100) {\n edges {\n node {\n id\n ...TrustCenterVendorsCardFragment\n }\n }\n }\n trustCenterFiles(first: 100) {\n edges {\n node {\n id\n ...TrustCenterFilesCardFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n slackConnections(first: 100) {\n edges {\n node {\n id\n channel\n channelId\n createdAt\n updatedAt\n }\n }\n }\n }\n id\n }\n}\n\nfragment TrustCenterAuditsCardFragment on Audit {\n id\n name\n framework {\n name\n id\n }\n validFrom\n validUntil\n state\n trustCenterVisibility\n createdAt\n}\n\nfragment TrustCenterDocumentsCardFragment on Document {\n id\n title\n createdAt\n documentType\n trustCenterVisibility\n versions(first: 1) {\n edges {\n node {\n id\n status\n }\n }\n }\n}\n\nfragment TrustCenterFilesCardFragment on TrustCenterFile {\n id\n name\n category\n fileUrl\n trustCenterVisibility\n createdAt\n updatedAt\n}\n\nfragment TrustCenterVendorsCardFragment on Vendor {\n id\n name\n category\n description\n showOnTrustCenter\n createdAt\n}\n" "text": "query TrustCenterGraphQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n ... on Organization {\n id\n name\n canCreateTrustCenterFile: permission(action: \"core:trust-center-file:create\")\n customDomain {\n id\n domain\n }\n trustCenter {\n id\n active\n ndaFileName\n ndaFileUrl\n createdAt\n updatedAt\n canUpdate: permission(action: \"core:trust-center:update\")\n canGetNDA: permission(action: \"core:trust-center:get-nda\")\n canUploadNDA: permission(action: \"core:trust-center:upload-nda\")\n canDeleteNDA: permission(action: \"core:trust-center:delete-nda\")\n references(first: 100, orderBy: {field: CREATED_AT, direction: DESC}) {\n edges {\n node {\n id\n name\n description\n websiteUrl\n logoUrl\n createdAt\n updatedAt\n }\n }\n }\n }\n documents(first: 100) {\n edges {\n node {\n id\n ...TrustCenterDocumentsCardFragment\n }\n }\n }\n audits(first: 100) {\n edges {\n node {\n id\n ...TrustCenterAuditsCardFragment\n }\n }\n }\n vendors(first: 100) {\n edges {\n node {\n id\n ...TrustCenterVendorsCardFragment\n }\n }\n }\n trustCenterFiles(first: 100) {\n edges {\n node {\n id\n ...TrustCenterFilesCardFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n slackConnections(first: 100) {\n edges {\n node {\n id\n channel\n channelId\n createdAt\n updatedAt\n }\n }\n }\n }\n id\n }\n}\n\nfragment TrustCenterAuditsCardFragment on Audit {\n id\n name\n framework {\n name\n id\n }\n validFrom\n validUntil\n state\n trustCenterVisibility\n createdAt\n}\n\nfragment TrustCenterDocumentsCardFragment on Document {\n id\n title\n createdAt\n documentType\n trustCenterVisibility\n versions(first: 1) {\n edges {\n node {\n id\n status\n }\n }\n }\n}\n\nfragment TrustCenterFilesCardFragment on TrustCenterFile {\n id\n name\n category\n fileUrl\n trustCenterVisibility\n createdAt\n updatedAt\n canUpdate: permission(action: \"core:trust-center-file:update\")\n canDelete: permission(action: \"core:trust-center-file:delete\")\n}\n\nfragment TrustCenterVendorsCardFragment on Vendor {\n id\n name\n category\n description\n showOnTrustCenter\n createdAt\n}\n"
} }
}; };
})(); })();
(node as any).hash = "8c59eb08a0ec74662a01a3b8bb8ab56f"; (node as any).hash = "2c169dd5176d4dedd98ff82210335a86";
export default node; export default node;

View File

@@ -14,7 +14,7 @@ import {
} from "@probo/ui"; } from "@probo/ui";
import { useTranslate } from "@probo/i18n"; import { useTranslate } from "@probo/i18n";
import { useFragment } from "react-relay"; import { useFragment } from "react-relay";
import { useMemo, useState, useCallback, useEffect, use } from "react"; import { useMemo, useState, useCallback, useEffect } from "react";
import { import {
sprintf, sprintf,
getAuditStateVariant, getAuditStateVariant,
@@ -24,7 +24,6 @@ import {
} from "@probo/helpers"; } from "@probo/helpers";
import { useOrganizationId } from "/hooks/useOrganizationId"; import { useOrganizationId } from "/hooks/useOrganizationId";
import type { TrustCenterAuditsCardFragment$key } from "/__generated__/core/TrustCenterAuditsCardFragment.graphql"; import type { TrustCenterAuditsCardFragment$key } from "/__generated__/core/TrustCenterAuditsCardFragment.graphql";
import { PermissionsContext } from "/providers/PermissionsContext";
const trustCenterAuditFragment = graphql` const trustCenterAuditFragment = graphql`
fragment TrustCenterAuditsCardFragment on Audit { fragment TrustCenterAuditsCardFragment on Audit {
@@ -55,6 +54,7 @@ type Props<Params> = {
params: Params; params: Params;
disabled?: boolean; disabled?: boolean;
onChangeVisibility: Mutation<Params>; onChangeVisibility: Mutation<Params>;
canUpdate: boolean;
}; };
export function TrustCenterAuditsCard<Params>(props: Props<Params>) { export function TrustCenterAuditsCard<Params>(props: Props<Params>) {
@@ -104,6 +104,7 @@ export function TrustCenterAuditsCard<Params>(props: Props<Params>) {
<AuditRow <AuditRow
key={index} key={index}
auditFragmentRef={audit} auditFragmentRef={audit}
canUpdate={props.canUpdate}
onChangeVisibility={onChangeVisibility} onChangeVisibility={onChangeVisibility}
disabled={props.disabled} disabled={props.disabled}
/> />
@@ -131,16 +132,13 @@ function AuditRow(props: {
trustCenterVisibility: "NONE" | "PRIVATE" | "PUBLIC", trustCenterVisibility: "NONE" | "PRIVATE" | "PUBLIC",
) => void; ) => void;
disabled?: boolean; disabled?: boolean;
canUpdate: boolean;
}) { }) {
const { auditFragmentRef, onChangeVisibility, disabled } = props; const { auditFragmentRef, onChangeVisibility, disabled, canUpdate } = props;
const audit = useFragment(trustCenterAuditFragment, auditFragmentRef); const audit = useFragment(trustCenterAuditFragment, auditFragmentRef);
const organizationId = useOrganizationId(); const organizationId = useOrganizationId();
const { __ } = useTranslate(); const { __ } = useTranslate();
const [optimisticValue, setOptimisticValue] = useState<string | null>(null); const [optimisticValue, setOptimisticValue] = useState<string | null>(null);
const { isAuthorized } = use(PermissionsContext);
const canUpdate = organizationId
? isAuthorized("TrustCenter", "updateTrustCenter")
: false;
const handleValueChange = useCallback( const handleValueChange = useCallback(
(value: string) => { (value: string) => {

View File

@@ -17,10 +17,9 @@ import {
import { useTranslate } from "@probo/i18n"; import { useTranslate } from "@probo/i18n";
import type { TrustCenterDocumentsCardFragment$key } from "/__generated__/core/TrustCenterDocumentsCardFragment.graphql"; import type { TrustCenterDocumentsCardFragment$key } from "/__generated__/core/TrustCenterDocumentsCardFragment.graphql";
import { useFragment } from "react-relay"; import { useFragment } from "react-relay";
import { useMemo, useState, useCallback, useEffect, use } 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 { PermissionsContext } from "/providers/PermissionsContext";
const trustCenterDocumentFragment = graphql` const trustCenterDocumentFragment = graphql`
fragment TrustCenterDocumentsCardFragment on Document { fragment TrustCenterDocumentsCardFragment on Document {
@@ -54,6 +53,7 @@ type Props<Params> = {
params: Params; params: Params;
disabled?: boolean; disabled?: boolean;
onChangeVisibility: Mutation<Params>; onChangeVisibility: Mutation<Params>;
canUpdate: boolean;
}; };
export function TrustCenterDocumentsCard<Params>(props: Props<Params>) { export function TrustCenterDocumentsCard<Params>(props: Props<Params>) {
@@ -104,6 +104,7 @@ export function TrustCenterDocumentsCard<Params>(props: Props<Params>) {
documentFragmentRef={document} documentFragmentRef={document}
onChangeVisibility={onChangeVisibility} onChangeVisibility={onChangeVisibility}
disabled={props.disabled} disabled={props.disabled}
canUpdate={props.canUpdate}
/> />
))} ))}
</Tbody> </Tbody>
@@ -129,8 +130,10 @@ function DocumentRow(props: {
trustCenterVisibility: "NONE" | "PRIVATE" | "PUBLIC", trustCenterVisibility: "NONE" | "PRIVATE" | "PUBLIC",
) => void; ) => void;
disabled?: boolean; disabled?: boolean;
canUpdate: boolean;
}) { }) {
const { documentFragmentRef, onChangeVisibility, disabled } = props; const { documentFragmentRef, onChangeVisibility, disabled, canUpdate } =
props;
const document = useFragment( const document = useFragment(
trustCenterDocumentFragment, trustCenterDocumentFragment,
documentFragmentRef, documentFragmentRef,
@@ -138,8 +141,6 @@ function DocumentRow(props: {
const organizationId = useOrganizationId(); const organizationId = useOrganizationId();
const { __ } = useTranslate(); const { __ } = useTranslate();
const [optimisticValue, setOptimisticValue] = useState<string | null>(null); const [optimisticValue, setOptimisticValue] = useState<string | null>(null);
const { isAuthorized } = use(PermissionsContext);
const canUpdate = isAuthorized("TrustCenter", "updateTrustCenter");
const handleValueChange = useCallback( const handleValueChange = useCallback(
(value: string) => { (value: string) => {

View File

@@ -21,10 +21,9 @@ import type {
TrustCenterFilesCardFragment$data, TrustCenterFilesCardFragment$data,
} from "/__generated__/core/TrustCenterFilesCardFragment.graphql"; } from "/__generated__/core/TrustCenterFilesCardFragment.graphql";
import { useFragment } from "react-relay"; import { useFragment } from "react-relay";
import { useMemo, useState, useCallback, useEffect, use } 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 { PermissionsContext } from "/providers/PermissionsContext";
const trustCenterFileFragment = graphql` const trustCenterFileFragment = graphql`
fragment TrustCenterFilesCardFragment on TrustCenterFile { fragment TrustCenterFilesCardFragment on TrustCenterFile {
@@ -35,6 +34,8 @@ const trustCenterFileFragment = graphql`
trustCenterVisibility trustCenterVisibility
createdAt createdAt
updatedAt updatedAt
canUpdate: permission(action: "core:trust-center-file:update")
canDelete: permission(action: "core:trust-center-file:delete")
} }
`; `;
@@ -54,6 +55,7 @@ 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;
canUpdate: boolean;
}; };
export function TrustCenterFilesCard<Params>(props: Props<Params>) { export function TrustCenterFilesCard<Params>(props: Props<Params>) {
@@ -107,6 +109,7 @@ export function TrustCenterFilesCard<Params>(props: Props<Params>) {
onEdit={props.onEdit} onEdit={props.onEdit}
onDelete={props.onDelete} onDelete={props.onDelete}
disabled={props.disabled} disabled={props.disabled}
canUpdate={props.canUpdate}
/> />
))} ))}
</Tbody> </Tbody>
@@ -134,6 +137,7 @@ function FileRowWrapper(props: {
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;
disabled?: boolean; disabled?: boolean;
canUpdate: boolean;
}) { }) {
const file = useFragment(trustCenterFileFragment, props.fileFragmentRef); const file = useFragment(trustCenterFileFragment, props.fileFragmentRef);
return ( return (
@@ -143,6 +147,7 @@ function FileRowWrapper(props: {
onEdit={props.onEdit} onEdit={props.onEdit}
onDelete={props.onDelete} onDelete={props.onDelete}
disabled={props.disabled} disabled={props.disabled}
canUpdate={props.canUpdate}
/> />
); );
} }
@@ -156,12 +161,12 @@ function FileRow(props: {
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;
disabled?: boolean; disabled?: boolean;
canUpdate: boolean;
}) { }) {
const { file, onChangeVisibility, onEdit, onDelete, disabled } = props; const { file, onChangeVisibility, onEdit, onDelete, disabled, canUpdate } =
props;
const { __ } = useTranslate(); const { __ } = useTranslate();
const [optimisticValue, setOptimisticValue] = useState<string | null>(null); const [optimisticValue, setOptimisticValue] = useState<string | null>(null);
const { isAuthorized } = use(PermissionsContext);
const canUpdate = isAuthorized("TrustCenter", "updateTrustCenter");
const handleValueChange = useCallback( const handleValueChange = useCallback(
(value: string) => { (value: string) => {
@@ -217,7 +222,7 @@ function FileRow(props: {
} }
title={__("Download")} title={__("Download")}
/> />
{isAuthorized("TrustCenterFile", "updateTrustCenterFile") && ( {file.canUpdate && (
<Button <Button
variant="secondary" variant="secondary"
icon={IconPencil} icon={IconPencil}
@@ -232,7 +237,7 @@ function FileRow(props: {
title={__("Edit")} title={__("Edit")}
/> />
)} )}
{isAuthorized("TrustCenterFile", "deleteTrustCenterFile") && ( {file.canDelete && (
<Button <Button
variant="danger" variant="danger"
icon={IconTrashCan} icon={IconTrashCan}

View File

@@ -8,6 +8,9 @@ export const trustCenterQuery = graphql`
... on Organization { ... on Organization {
id id
name name
canCreateTrustCenterFile: permission(
action: "core:trust-center-file:create"
)
customDomain { customDomain {
id id
domain domain
@@ -20,6 +23,9 @@ export const trustCenterQuery = graphql`
createdAt createdAt
updatedAt updatedAt
canUpdate: permission(action: "core:trust-center:update") canUpdate: permission(action: "core:trust-center:update")
canGetNDA: permission(action: "core:trust-center:get-nda")
canUploadNDA: permission(action: "core:trust-center:upload-nda")
canDeleteNDA: permission(action: "core:trust-center:delete-nda")
references( references(
first: 100 first: 100
orderBy: { field: CREATED_AT, direction: DESC } orderBy: { field: CREATED_AT, direction: DESC }

View File

@@ -3,21 +3,11 @@ 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";
import type { TrustCenterAuditsCardFragment$key } from "/__generated__/core/TrustCenterAuditsCardFragment.graphql"; import type { TrustCenterGraphQuery$data } from "/__generated__/core/TrustCenterGraphQuery.graphql";
type ContextType = {
organization: {
audits?: {
edges: Array<{
node: TrustCenterAuditsCardFragment$key;
}>;
};
};
};
export default function TrustCenterAuditsTab() { export default function TrustCenterAuditsTab() {
const { __ } = useTranslate(); const { __ } = useTranslate();
const { organization } = useOutletContext<ContextType>(); const { organization } = useOutletContext<TrustCenterGraphQuery$data>();
const [updateAuditVisibility, isUpdatingAudits] = useTrustCenterAuditUpdate(); const [updateAuditVisibility, isUpdatingAudits] = useTrustCenterAuditUpdate();
const audits = (organization.audits?.edges ?? []).map((edge) => edge.node); const audits = (organization.audits?.edges ?? []).map((edge) => edge.node);
@@ -38,6 +28,7 @@ export default function TrustCenterAuditsTab() {
params={{}} params={{}}
disabled={isUpdatingAudits} disabled={isUpdatingAudits}
onChangeVisibility={updateAuditVisibility} onChangeVisibility={updateAuditVisibility}
canUpdate={!!organization.trustCenter?.canUpdate}
/> />
</div> </div>
); );

View File

@@ -3,21 +3,11 @@ 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";
import type { TrustCenterDocumentsCardFragment$key } from "/__generated__/core/TrustCenterDocumentsCardFragment.graphql"; import type { TrustCenterGraphQuery$data } from "/__generated__/core/TrustCenterGraphQuery.graphql";
type ContextType = {
organization: {
documents?: {
edges: Array<{
node: TrustCenterDocumentsCardFragment$key;
}>;
};
};
};
export default function TrustCenterDocumentsTab() { export default function TrustCenterDocumentsTab() {
const { __ } = useTranslate(); const { __ } = useTranslate();
const { organization } = useOutletContext<ContextType>(); const { organization } = useOutletContext<TrustCenterGraphQuery$data>();
const [updateDocumentVisibility, isUpdatingDocuments] = const [updateDocumentVisibility, isUpdatingDocuments] =
useUpdateDocumentVisibilityMutation(); useUpdateDocumentVisibilityMutation();
@@ -40,6 +30,7 @@ export default function TrustCenterDocumentsTab() {
params={{}} params={{}}
disabled={isUpdatingDocuments} disabled={isUpdatingDocuments}
onChangeVisibility={updateDocumentVisibility} onChangeVisibility={updateDocumentVisibility}
canUpdate={!!organization.trustCenter?.canUpdate}
/> />
</div> </div>
); );

View File

@@ -13,7 +13,7 @@ import {
} 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";
import { useState, useCallback, use } from "react"; import { useState, useCallback } from "react";
import z from "zod"; import z from "zod";
import { getTrustCenterVisibilityOptions } from "@probo/helpers"; import { getTrustCenterVisibilityOptions } from "@probo/helpers";
import { import {
@@ -23,20 +23,7 @@ import {
} from "/hooks/graph/TrustCenterFileGraph"; } from "/hooks/graph/TrustCenterFileGraph";
import { useFormWithSchema } from "/hooks/useFormWithSchema"; import { useFormWithSchema } from "/hooks/useFormWithSchema";
import { TrustCenterFilesCard } from "/components/trustCenter/TrustCenterFilesCard"; import { TrustCenterFilesCard } from "/components/trustCenter/TrustCenterFilesCard";
import type { TrustCenterFilesCardFragment$key } from "/__generated__/core/TrustCenterFilesCardFragment.graphql"; import type { TrustCenterGraphQuery$data } from "/__generated__/core/TrustCenterGraphQuery.graphql";
import { PermissionsContext } from "/providers/PermissionsContext";
type ContextType = {
organization: {
id: string;
trustCenterFiles?: {
__id?: string;
edges: Array<{
node: TrustCenterFilesCardFragment$key;
}>;
};
};
};
const acceptedFileTypes = { const acceptedFileTypes = {
"application/csv": [".csv"], "application/csv": [".csv"],
@@ -75,8 +62,7 @@ const acceptedFileTypes = {
export default function TrustCenterFilesTab() { export default function TrustCenterFilesTab() {
const { __ } = useTranslate(); const { __ } = useTranslate();
const { organization } = useOutletContext<ContextType>(); const { organization } = useOutletContext<TrustCenterGraphQuery$data>();
const { isAuthorized } = use(PermissionsContext);
const createSchema = z.object({ const createSchema = z.object({
name: z.string().min(1, __("Name is required")), name: z.string().min(1, __("Name is required")),
category: z.string().min(1, __("Category is required")), category: z.string().min(1, __("Category is required")),
@@ -258,7 +244,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>
{isAuthorized("Organization", "createTrustCenterFile") && ( {organization.canCreateTrustCenterFile && (
<Button <Button
icon={IconPlusLarge} icon={IconPlusLarge}
onClick={() => createDialogRef.current?.open()} onClick={() => createDialogRef.current?.open()}
@@ -279,6 +265,7 @@ export default function TrustCenterFilesTab() {
onChangeVisibility={handleChangeVisibility} onChangeVisibility={handleChangeVisibility}
onEdit={handleEdit} onEdit={handleEdit}
onDelete={handleDeleteClick} onDelete={handleDeleteClick}
canUpdate={!!organization.trustCenter?.canUpdate}
/> />
<Dialog ref={createDialogRef} title={__("Add File")}> <Dialog ref={createDialogRef} title={__("Add File")}>

View File

@@ -15,19 +15,13 @@ import {
useDeleteTrustCenterNDAMutation, useDeleteTrustCenterNDAMutation,
} from "/hooks/graph/TrustCenterGraph"; } from "/hooks/graph/TrustCenterGraph";
import type { TrustCenterGraphQuery$data } from "/__generated__/core/TrustCenterGraphQuery.graphql"; import type { TrustCenterGraphQuery$data } from "/__generated__/core/TrustCenterGraphQuery.graphql";
import { use, useState } from "react"; import { useState } from "react";
import { SlackConnections } from "../../../components/organizations/SlackConnection"; import { SlackConnections } from "../../../components/organizations/SlackConnection";
import { PermissionsContext } from "/providers/PermissionsContext";
type ContextType = {
organization: TrustCenterGraphQuery$data["organization"];
};
export default function TrustCenterOverviewTab() { export default function TrustCenterOverviewTab() {
const { __ } = useTranslate(); const { __ } = useTranslate();
const { toast } = useToast(); const { toast } = useToast();
const { organization } = useOutletContext<ContextType>(); const { organization } = useOutletContext<TrustCenterGraphQuery$data>();
const { isAuthorized } = use(PermissionsContext);
const [updateTrustCenter, isUpdating] = useUpdateTrustCenterMutation(); const [updateTrustCenter, isUpdating] = useUpdateTrustCenterMutation();
const [uploadNDA, isUploadingNDA] = useUploadTrustCenterNDAMutation(); const [uploadNDA, isUploadingNDA] = useUploadTrustCenterNDAMutation();
@@ -36,7 +30,7 @@ export default function TrustCenterOverviewTab() {
organization.trustCenter?.active || false, organization.trustCenter?.active || false,
); );
const canUpdateTrustCenter = isAuthorized("TrustCenter", "updateTrustCenter"); const canUpdateTrustCenter = organization.trustCenter?.canUpdate;
const handleToggleActive = async (active: boolean) => { const handleToggleActive = async (active: boolean) => {
if (!organization.trustCenter?.id) { if (!organization.trustCenter?.id) {
@@ -189,89 +183,91 @@ export default function TrustCenterOverviewTab() {
)} )}
</Card> </Card>
</div> </div>
{organization.trustCenter?.canGetNDA && (
<div className="space-y-4"> <div className="space-y-4">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<h2 className="text-base font-medium"> <h2 className="text-base font-medium">
{__("Non-Disclosure Agreement")} {__("Non-Disclosure Agreement")}
</h2> </h2>
{(isUploadingNDA || isDeletingNDA) && <Spinner />} {(isUploadingNDA || isDeletingNDA) && <Spinner />}
</div> </div>
<Card padded className="space-y-4"> <Card padded className="space-y-4">
<div className="space-y-2"> <div className="space-y-2">
{!organization.trustCenter?.ndaFileName ? ( {!organization.trustCenter?.ndaFileName &&
<p className="text-sm text-txt-tertiary"> organization.trustCenter.canUploadNDA ? (
{__( <p className="text-sm text-txt-tertiary">
"Upload a Non-Disclosure Agreement that visitors must accept before accessing your trust center", {__(
)} "Upload a Non-Disclosure Agreement that visitors must accept before accessing your trust center",
</p> )}
) : ( </p>
<></> ) : (
)} <></>
{organization.trustCenter?.ndaFileName ? ( )}
<div className="space-y-3"> {organization.trustCenter?.ndaFileName ? (
<div className="flex items-center justify-between"> <div className="space-y-3">
<div className="space-y-1"> <div className="flex items-center justify-between">
<div className="flex items-center gap-2"> <div className="space-y-1">
<p className="text-sm font-medium"> <div className="flex items-center gap-2">
{organization.trustCenter.ndaFileName || <p className="text-sm font-medium">
__("Non-Disclosure Agreement")} {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> </p>
</div> </div>
<p className="text-xs text-txt-tertiary"> <div className="flex items-center gap-2">
{__(
"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>
{canUpdateTrustCenter && (
<Button <Button
variant="quaternary" type="button"
icon={IconTrashCan} variant="secondary"
onClick={handleNDADelete} onClick={() => {
disabled={isDeletingNDA} if (organization.trustCenter?.ndaFileUrl) {
/> window.open(
)} organization.trustCenter.ndaFileUrl,
"_blank",
);
}
}}
>
{__("Download PDF")}
</Button>
{organization.trustCenter?.canDeleteNDA && (
<Button
variant="quaternary"
icon={IconTrashCan}
onClick={handleNDADelete}
disabled={isDeletingNDA}
/>
)}
</div>
</div> </div>
</div> </div>
</div> ) : (
) : ( <>
<> {canUpdateTrustCenter ? (
{canUpdateTrustCenter ? ( <Dropzone
<Dropzone description={__("Upload PDF files up to 10MB")}
description={__("Upload PDF files up to 10MB")} isUploading={isUploadingNDA}
isUploading={isUploadingNDA} onDrop={handleNDAUpload}
onDrop={handleNDAUpload} accept={{
accept={{ "application/pdf": [".pdf"],
"application/pdf": [".pdf"], }}
}} maxSize={10}
maxSize={10} />
/> ) : (
) : ( <p className="text-sm text-txt-tertiary">
<p className="text-sm text-txt-tertiary"> {__("No NDA file uploaded")}
{__("No NDA file uploaded")} </p>
</p> )}
)} </>
</> )}
)} </div>
</div> </Card>
</Card> </div>
</div> )}
<div className="space-y-4"> <div className="space-y-4">
<h2 className="text-base font-medium">{__("Integrations")}</h2> <h2 className="text-base font-medium">{__("Integrations")}</h2>

View File

@@ -1409,15 +1409,3 @@ type sAMLConfigurationResolver struct{ *Resolver }
type sAMLConfigurationConnectionResolver struct{ *Resolver } type sAMLConfigurationConnectionResolver struct{ *Resolver }
type sessionResolver struct{ *Resolver } type sessionResolver struct{ *Resolver }
type sessionConnectionResolver struct{ *Resolver } type sessionConnectionResolver struct{ *Resolver }
// !!! WARNING !!!
// The code below was going to be deleted when updating resolvers. It has been copied here so you have
// one last chance to move it out of harms way if you want. There are two reasons this happens:
// - When renaming or deleting a resolver the old code will be put in here. You can safely delete
// it when you're done.
// - You have helper methods in this file. Move them out to keep these resolver files clean.
/*
func (r *membershipResolver) Permissions(ctx context.Context, obj *types.Membership) ([]*types.Permission, error) {
panic("not implemented")
}
*/

View File

@@ -2543,7 +2543,7 @@ type TrustCenterReferenceEdge {
node: TrustCenterReference! node: TrustCenterReference!
} }
type TrustCenterFile { type TrustCenterFile implements Node {
id: ID! id: ID!
name: String! name: String!
category: String! category: String!
@@ -2552,6 +2552,8 @@ type TrustCenterFile {
createdAt: Datetime! createdAt: Datetime!
updatedAt: Datetime! updatedAt: Datetime!
organization: Organization! @goField(forceResolver: true) organization: Organization! @goField(forceResolver: true)
permission(action: String!): Boolean! @goField(forceResolver: true)
} }
type TrustCenterFileConnection type TrustCenterFileConnection

View File

@@ -1590,6 +1590,7 @@ type ComplexityRoot struct {
ID func(childComplexity int) int ID func(childComplexity int) int
Name func(childComplexity int) int Name func(childComplexity int) int
Organization func(childComplexity int) int Organization func(childComplexity int) int
Permission func(childComplexity int, action string) int
TrustCenterVisibility func(childComplexity int) int TrustCenterVisibility func(childComplexity int) int
UpdatedAt func(childComplexity int) int UpdatedAt func(childComplexity int) int
} }
@@ -2394,6 +2395,7 @@ type TrustCenterFileResolver interface {
FileURL(ctx context.Context, obj *types.TrustCenterFile) (string, error) FileURL(ctx context.Context, obj *types.TrustCenterFile) (string, error)
Organization(ctx context.Context, obj *types.TrustCenterFile) (*types.Organization, error) Organization(ctx context.Context, obj *types.TrustCenterFile) (*types.Organization, error)
Permission(ctx context.Context, obj *types.TrustCenterFile, action string) (bool, error)
} }
type TrustCenterFileConnectionResolver interface { type TrustCenterFileConnectionResolver interface {
TotalCount(ctx context.Context, obj *types.TrustCenterFileConnection) (int, error) TotalCount(ctx context.Context, obj *types.TrustCenterFileConnection) (int, error)
@@ -8896,6 +8898,17 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
} }
return e.complexity.TrustCenterFile.Organization(childComplexity), true return e.complexity.TrustCenterFile.Organization(childComplexity), true
case "TrustCenterFile.permission":
if e.complexity.TrustCenterFile.Permission == nil {
break
}
args, err := ec.field_TrustCenterFile_permission_args(ctx, rawArgs)
if err != nil {
return 0, false
}
return e.complexity.TrustCenterFile.Permission(childComplexity, args["action"].(string)), true
case "TrustCenterFile.trustCenterVisibility": case "TrustCenterFile.trustCenterVisibility":
if e.complexity.TrustCenterFile.TrustCenterVisibility == nil { if e.complexity.TrustCenterFile.TrustCenterVisibility == nil {
break break
@@ -12872,7 +12885,7 @@ type TrustCenterReferenceEdge {
node: TrustCenterReference! node: TrustCenterReference!
} }
type TrustCenterFile { type TrustCenterFile implements Node {
id: ID! id: ID!
name: String! name: String!
category: String! category: String!
@@ -12881,6 +12894,8 @@ type TrustCenterFile {
createdAt: Datetime! createdAt: Datetime!
updatedAt: Datetime! updatedAt: Datetime!
organization: Organization! @goField(forceResolver: true) organization: Organization! @goField(forceResolver: true)
permission(action: String!): Boolean! @goField(forceResolver: true)
} }
type TrustCenterFileConnection type TrustCenterFileConnection
@@ -19036,6 +19051,17 @@ func (ec *executionContext) field_TrustCenterAccess_permission_args(ctx context.
return args, nil return args, nil
} }
func (ec *executionContext) field_TrustCenterFile_permission_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
var err error
args := map[string]any{}
arg0, err := graphql.ProcessArgField(ctx, rawArgs, "action", ec.unmarshalNString2string)
if err != nil {
return nil, err
}
args["action"] = arg0
return args, nil
}
func (ec *executionContext) field_TrustCenterReference_permission_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { func (ec *executionContext) field_TrustCenterReference_permission_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{}
@@ -31802,6 +31828,8 @@ func (ec *executionContext) fieldContext_GetTrustCenterFilePayload_trustCenterFi
return ec.fieldContext_TrustCenterFile_updatedAt(ctx, field) return ec.fieldContext_TrustCenterFile_updatedAt(ctx, field)
case "organization": case "organization":
return ec.fieldContext_TrustCenterFile_organization(ctx, field) return ec.fieldContext_TrustCenterFile_organization(ctx, field)
case "permission":
return ec.fieldContext_TrustCenterFile_permission(ctx, field)
} }
return nil, fmt.Errorf("no field named %q was found under type TrustCenterFile", field.Name) return nil, fmt.Errorf("no field named %q was found under type TrustCenterFile", field.Name)
}, },
@@ -51785,6 +51813,8 @@ func (ec *executionContext) fieldContext_TrustCenterDocumentAccess_trustCenterFi
return ec.fieldContext_TrustCenterFile_updatedAt(ctx, field) return ec.fieldContext_TrustCenterFile_updatedAt(ctx, field)
case "organization": case "organization":
return ec.fieldContext_TrustCenterFile_organization(ctx, field) return ec.fieldContext_TrustCenterFile_organization(ctx, field)
case "permission":
return ec.fieldContext_TrustCenterFile_permission(ctx, field)
} }
return nil, fmt.Errorf("no field named %q was found under type TrustCenterFile", field.Name) return nil, fmt.Errorf("no field named %q was found under type TrustCenterFile", field.Name)
}, },
@@ -52353,6 +52383,47 @@ func (ec *executionContext) fieldContext_TrustCenterFile_organization(_ context.
return fc, nil return fc, nil
} }
func (ec *executionContext) _TrustCenterFile_permission(ctx context.Context, field graphql.CollectedField, obj *types.TrustCenterFile) (ret graphql.Marshaler) {
return graphql.ResolveField(
ctx,
ec.OperationContext,
field,
ec.fieldContext_TrustCenterFile_permission,
func(ctx context.Context) (any, error) {
fc := graphql.GetFieldContext(ctx)
return ec.resolvers.TrustCenterFile().Permission(ctx, obj, fc.Args["action"].(string))
},
nil,
ec.marshalNBoolean2bool,
true,
true,
)
}
func (ec *executionContext) fieldContext_TrustCenterFile_permission(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "TrustCenterFile",
Field: field,
IsMethod: true,
IsResolver: true,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
return nil, errors.New("field of type Boolean does not have child fields")
},
}
defer func() {
if r := recover(); r != nil {
err = ec.Recover(ctx, r)
ec.Error(ctx, err)
}
}()
ctx = graphql.WithFieldContext(ctx, fc)
if fc.Args, err = ec.field_TrustCenterFile_permission_args(ctx, field.ArgumentMap(ec.Variables)); err != nil {
ec.Error(ctx, err)
return fc, err
}
return fc, nil
}
func (ec *executionContext) _TrustCenterFileConnection_totalCount(ctx context.Context, field graphql.CollectedField, obj *types.TrustCenterFileConnection) (ret graphql.Marshaler) { func (ec *executionContext) _TrustCenterFileConnection_totalCount(ctx context.Context, field graphql.CollectedField, obj *types.TrustCenterFileConnection) (ret graphql.Marshaler) {
return graphql.ResolveField( return graphql.ResolveField(
ctx, ctx,
@@ -52525,6 +52596,8 @@ func (ec *executionContext) fieldContext_TrustCenterFileEdge_node(_ context.Cont
return ec.fieldContext_TrustCenterFile_updatedAt(ctx, field) return ec.fieldContext_TrustCenterFile_updatedAt(ctx, field)
case "organization": case "organization":
return ec.fieldContext_TrustCenterFile_organization(ctx, field) return ec.fieldContext_TrustCenterFile_organization(ctx, field)
case "permission":
return ec.fieldContext_TrustCenterFile_permission(ctx, field)
} }
return nil, fmt.Errorf("no field named %q was found under type TrustCenterFile", field.Name) return nil, fmt.Errorf("no field named %q was found under type TrustCenterFile", field.Name)
}, },
@@ -54290,6 +54363,8 @@ func (ec *executionContext) fieldContext_UpdateTrustCenterFilePayload_trustCente
return ec.fieldContext_TrustCenterFile_updatedAt(ctx, field) return ec.fieldContext_TrustCenterFile_updatedAt(ctx, field)
case "organization": case "organization":
return ec.fieldContext_TrustCenterFile_organization(ctx, field) return ec.fieldContext_TrustCenterFile_organization(ctx, field)
case "permission":
return ec.fieldContext_TrustCenterFile_permission(ctx, field)
} }
return nil, fmt.Errorf("no field named %q was found under type TrustCenterFile", field.Name) return nil, fmt.Errorf("no field named %q was found under type TrustCenterFile", field.Name)
}, },
@@ -69052,6 +69127,13 @@ func (ec *executionContext) _Node(ctx context.Context, sel ast.SelectionSet, obj
return graphql.Null return graphql.Null
} }
return ec._TrustCenterReference(ctx, sel, obj) return ec._TrustCenterReference(ctx, sel, obj)
case types.TrustCenterFile:
return ec._TrustCenterFile(ctx, sel, &obj)
case *types.TrustCenterFile:
if obj == nil {
return graphql.Null
}
return ec._TrustCenterFile(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:
@@ -85535,7 +85617,7 @@ func (ec *executionContext) _TrustCenterEdge(ctx context.Context, sel ast.Select
return out return out
} }
var trustCenterFileImplementors = []string{"TrustCenterFile"} var trustCenterFileImplementors = []string{"TrustCenterFile", "Node"}
func (ec *executionContext) _TrustCenterFile(ctx context.Context, sel ast.SelectionSet, obj *types.TrustCenterFile) graphql.Marshaler { func (ec *executionContext) _TrustCenterFile(ctx context.Context, sel ast.SelectionSet, obj *types.TrustCenterFile) graphql.Marshaler {
fields := graphql.CollectFields(ec.OperationContext, sel, trustCenterFileImplementors) fields := graphql.CollectFields(ec.OperationContext, sel, trustCenterFileImplementors)
@@ -85647,6 +85729,42 @@ func (ec *executionContext) _TrustCenterFile(ctx context.Context, sel ast.Select
continue continue
} }
out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) })
case "permission":
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._TrustCenterFile_permission(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) }) out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) })
default: default:
panic("unknown field " + strconv.Quote(field.Name)) panic("unknown field " + strconv.Quote(field.Name))

View File

@@ -1952,8 +1952,12 @@ type TrustCenterFile struct {
CreatedAt time.Time `json:"createdAt"` CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"` UpdatedAt time.Time `json:"updatedAt"`
Organization *Organization `json:"organization"` Organization *Organization `json:"organization"`
Permission bool `json:"permission"`
} }
func (TrustCenterFile) IsNode() {}
func (this TrustCenterFile) GetID() gid.GID { return this.ID }
type TrustCenterFileEdge struct { type TrustCenterFileEdge struct {
Cursor page.CursorKey `json:"cursor"` Cursor page.CursorKey `json:"cursor"`
Node *TrustCenterFile `json:"node"` Node *TrustCenterFile `json:"node"`

View File

@@ -6917,7 +6917,18 @@ func (r *transferImpactAssessmentConnectionResolver) TotalCount(ctx context.Cont
// NdaFileURL is the resolver for the ndaFileUrl field. // NdaFileURL is the resolver for the ndaFileUrl field.
func (r *trustCenterResolver) NdaFileURL(ctx context.Context, obj *types.TrustCenter) (*string, error) { func (r *trustCenterResolver) NdaFileURL(ctx context.Context, obj *types.TrustCenter) (*string, error) {
r.MustAuthorize(ctx, obj.ID, probo.ActionTrustCenterGetNda) if err := r.iam.Authorizer.Authorize(ctx, iam.AuthorizeParams{
Principal: connect_v1.IdentityFromContext(ctx).ID,
Resource: obj.ID,
Action: "core:trust-center:get-nda-file-url",
}); err != nil {
var errInsufficientPermissions *iam.ErrInsufficientPermissions
if errors.As(err, &errInsufficientPermissions) {
return nil, nil
}
panic(fmt.Errorf("cannot authorize: %w", err))
}
prb := r.ProboService(ctx, obj.ID.TenantID()) prb := r.ProboService(ctx, obj.ID.TenantID())
@@ -7179,6 +7190,11 @@ func (r *trustCenterFileResolver) Organization(ctx context.Context, obj *types.T
return types.NewOrganization(organization), nil return types.NewOrganization(organization), nil
} }
// Permission is the resolver for the permission field.
func (r *trustCenterFileResolver) Permission(ctx context.Context, obj *types.TrustCenterFile, action string) (bool, error) {
return r.Resolver.Permission(ctx, obj, action)
}
// TotalCount is the resolver for the totalCount field. // TotalCount is the resolver for the totalCount field.
func (r *trustCenterFileConnectionResolver) TotalCount(ctx context.Context, obj *types.TrustCenterFileConnection) (int, error) { func (r *trustCenterFileConnectionResolver) TotalCount(ctx context.Context, obj *types.TrustCenterFileConnection) (int, error) {
r.MustAuthorize(ctx, obj.ParentID, probo.ActionTrustCenterFileList) r.MustAuthorize(ctx, obj.ParentID, probo.ActionTrustCenterFileList)