Add nda to trust center
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
@@ -26,6 +26,7 @@ export const trustCenterAccessesQuery = graphql`
|
||||
email
|
||||
name
|
||||
active
|
||||
hasAcceptedNonDisclosureAgreement
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
@@ -48,6 +49,7 @@ export const createTrustCenterAccessMutation = graphql`
|
||||
email
|
||||
name
|
||||
active
|
||||
hasAcceptedNonDisclosureAgreement
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
@@ -65,6 +67,7 @@ export const updateTrustCenterAccessMutation = graphql`
|
||||
email
|
||||
name
|
||||
active
|
||||
hasAcceptedNonDisclosureAgreement
|
||||
createdAt
|
||||
updatedAt
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@ export const trustCenterQuery = graphql`
|
||||
id
|
||||
active
|
||||
slug
|
||||
ndaFileName
|
||||
ndaFileUrl
|
||||
createdAt
|
||||
updatedAt
|
||||
}
|
||||
@@ -66,3 +68,48 @@ export function useUpdateTrustCenterMutation() {
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export const uploadTrustCenterNDAMutation = graphql`
|
||||
mutation TrustCenterGraphUploadNDAMutation($input: UploadTrustCenterNDAInput!) {
|
||||
uploadTrustCenterNDA(input: $input) {
|
||||
trustCenter {
|
||||
id
|
||||
ndaFileName
|
||||
updatedAt
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export function useUploadTrustCenterNDAMutation() {
|
||||
return useMutationWithToasts(
|
||||
uploadTrustCenterNDAMutation,
|
||||
{
|
||||
successMessage: "NDA uploaded successfully",
|
||||
errorMessage: "Failed to upload NDA",
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export const deleteTrustCenterNDAMutation = graphql`
|
||||
mutation TrustCenterGraphDeleteNDAMutation($input: DeleteTrustCenterNDAInput!) {
|
||||
deleteTrustCenterNDA(input: $input) {
|
||||
trustCenter {
|
||||
id
|
||||
ndaFileName
|
||||
updatedAt
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export function useDeleteTrustCenterNDAMutation() {
|
||||
return useMutationWithToasts(
|
||||
deleteTrustCenterNDAMutation,
|
||||
{
|
||||
successMessage: "NDA deleted successfully",
|
||||
errorMessage: "Failed to delete NDA",
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<ae95aed7bc22c95f8cc2ab591039c810>>
|
||||
* @generated SignedSource<<5ccaab70e4cb8c4b5bee7fbe6ba2c0b6>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -27,6 +27,7 @@ export type TrustCenterAccessGraphCreateMutation$data = {
|
||||
readonly active: boolean;
|
||||
readonly createdAt: any;
|
||||
readonly email: string;
|
||||
readonly hasAcceptedNonDisclosureAgreement: boolean;
|
||||
readonly id: string;
|
||||
readonly name: string;
|
||||
};
|
||||
@@ -107,6 +108,13 @@ v3 = {
|
||||
"name": "active",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "hasAcceptedNonDisclosureAgreement",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
@@ -186,16 +194,16 @@ return {
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "eafddcd0263963235d3249c22eb50593",
|
||||
"cacheID": "fa88b100be7598cf46159cf79199c398",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "TrustCenterAccessGraphCreateMutation",
|
||||
"operationKind": "mutation",
|
||||
"text": "mutation TrustCenterAccessGraphCreateMutation(\n $input: CreateTrustCenterAccessInput!\n) {\n createTrustCenterAccess(input: $input) {\n trustCenterAccessEdge {\n cursor\n node {\n id\n email\n name\n active\n createdAt\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 }\n }\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "99676fee0b2de06a92cdad66c577eee7";
|
||||
(node as any).hash = "6c6c1344730e7d908a5c6392f578ca81";
|
||||
|
||||
export default node;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<2333a6a7d5415f1a08a5612dcaceee8f>>
|
||||
* @generated SignedSource<<e9cdda9f586cee5ffe66f238216060f6>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -22,6 +22,7 @@ export type TrustCenterAccessGraphQuery$data = {
|
||||
readonly active: boolean;
|
||||
readonly createdAt: any;
|
||||
readonly email: string;
|
||||
readonly hasAcceptedNonDisclosureAgreement: boolean;
|
||||
readonly id: string;
|
||||
readonly name: string;
|
||||
};
|
||||
@@ -163,6 +164,13 @@ v5 = [
|
||||
"name": "active",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "hasAcceptedNonDisclosureAgreement",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
@@ -290,7 +298,7 @@ return {
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "5b83cd4ae2434ce2e00de7230d264432",
|
||||
"cacheID": "0286ec03fb4ae012ada7bae8a2234152",
|
||||
"id": null,
|
||||
"metadata": {
|
||||
"connection": [
|
||||
@@ -307,11 +315,11 @@ return {
|
||||
},
|
||||
"name": "TrustCenterAccessGraphQuery",
|
||||
"operationKind": "query",
|
||||
"text": "query TrustCenterAccessGraphQuery(\n $trustCenterId: ID!\n) {\n node(id: $trustCenterId) {\n __typename\n ... on TrustCenter {\n id\n accesses(first: 100, 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 createdAt\n __typename\n }\n }\n }\n }\n id\n }\n}\n"
|
||||
"text": "query TrustCenterAccessGraphQuery(\n $trustCenterId: ID!\n) {\n node(id: $trustCenterId) {\n __typename\n ... on TrustCenter {\n id\n accesses(first: 100, 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 __typename\n }\n }\n }\n }\n id\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "af598fd2af198e63ed84fd618857a985";
|
||||
(node as any).hash = "f837b96937f1397ac1a3065f58386e4d";
|
||||
|
||||
export default node;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<6de2ecb63a58c88c3008368061943b49>>
|
||||
* @generated SignedSource<<d2f40d8fc2bd9c7627d308660dedb1e5>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -23,6 +23,7 @@ export type TrustCenterAccessGraphUpdateMutation$data = {
|
||||
readonly active: boolean;
|
||||
readonly createdAt: any;
|
||||
readonly email: string;
|
||||
readonly hasAcceptedNonDisclosureAgreement: boolean;
|
||||
readonly id: string;
|
||||
readonly name: string;
|
||||
readonly updatedAt: any;
|
||||
@@ -93,6 +94,13 @@ v1 = [
|
||||
"name": "active",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "hasAcceptedNonDisclosureAgreement",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
@@ -132,16 +140,16 @@ return {
|
||||
"selections": (v1/*: any*/)
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "683ee01fb5173b49b0a7f3c2d99cf002",
|
||||
"cacheID": "223169ee8a4f65008047097ecff68fc5",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "TrustCenterAccessGraphUpdateMutation",
|
||||
"operationKind": "mutation",
|
||||
"text": "mutation TrustCenterAccessGraphUpdateMutation(\n $input: UpdateTrustCenterAccessInput!\n) {\n updateTrustCenterAccess(input: $input) {\n trustCenterAccess {\n id\n email\n name\n active\n createdAt\n updatedAt\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 }\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "cccd083b0047f6bc7b504b7494205e9d";
|
||||
(node as any).hash = "0da1f737e6ea1db7a1b9930c4b6cc545";
|
||||
|
||||
export default node;
|
||||
|
||||
121
apps/console/src/hooks/graph/__generated__/TrustCenterGraphDeleteNDAMutation.graphql.ts
generated
Normal file
121
apps/console/src/hooks/graph/__generated__/TrustCenterGraphDeleteNDAMutation.graphql.ts
generated
Normal file
@@ -0,0 +1,121 @@
|
||||
/**
|
||||
* @generated SignedSource<<43a8665719f251c1bae028ff7821b14a>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
export type DeleteTrustCenterNDAInput = {
|
||||
trustCenterId: string;
|
||||
};
|
||||
export type TrustCenterGraphDeleteNDAMutation$variables = {
|
||||
input: DeleteTrustCenterNDAInput;
|
||||
};
|
||||
export type TrustCenterGraphDeleteNDAMutation$data = {
|
||||
readonly deleteTrustCenterNDA: {
|
||||
readonly trustCenter: {
|
||||
readonly id: string;
|
||||
readonly ndaFileName: string | null | undefined;
|
||||
readonly updatedAt: any;
|
||||
};
|
||||
};
|
||||
};
|
||||
export type TrustCenterGraphDeleteNDAMutation = {
|
||||
response: TrustCenterGraphDeleteNDAMutation$data;
|
||||
variables: TrustCenterGraphDeleteNDAMutation$variables;
|
||||
};
|
||||
|
||||
const node: ConcreteRequest = (function(){
|
||||
var v0 = [
|
||||
{
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "input"
|
||||
}
|
||||
],
|
||||
v1 = [
|
||||
{
|
||||
"alias": null,
|
||||
"args": [
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "input",
|
||||
"variableName": "input"
|
||||
}
|
||||
],
|
||||
"concreteType": "DeleteTrustCenterNDAPayload",
|
||||
"kind": "LinkedField",
|
||||
"name": "deleteTrustCenterNDA",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "TrustCenter",
|
||||
"kind": "LinkedField",
|
||||
"name": "trustCenter",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "id",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "ndaFileName",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "updatedAt",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
];
|
||||
return {
|
||||
"fragment": {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "TrustCenterGraphDeleteNDAMutation",
|
||||
"selections": (v1/*: any*/),
|
||||
"type": "Mutation",
|
||||
"abstractKey": null
|
||||
},
|
||||
"kind": "Request",
|
||||
"operation": {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Operation",
|
||||
"name": "TrustCenterGraphDeleteNDAMutation",
|
||||
"selections": (v1/*: any*/)
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "fa3ebf3593c396bf05819d357d9f909f",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "TrustCenterGraphDeleteNDAMutation",
|
||||
"operationKind": "mutation",
|
||||
"text": "mutation TrustCenterGraphDeleteNDAMutation(\n $input: DeleteTrustCenterNDAInput!\n) {\n deleteTrustCenterNDA(input: $input) {\n trustCenter {\n id\n ndaFileName\n updatedAt\n }\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "9c055069b9e2e7432fed7509f6578a07";
|
||||
|
||||
export default node;
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<25550a93c5459c3b405c782be19ac888>>
|
||||
* @generated SignedSource<<9dbea87f398ce8189cb2431d7c03912c>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -37,6 +37,8 @@ export type TrustCenterGraphQuery$data = {
|
||||
readonly active: boolean;
|
||||
readonly createdAt: any;
|
||||
readonly id: string;
|
||||
readonly ndaFileName: string | null | undefined;
|
||||
readonly ndaFileUrl: string | null | undefined;
|
||||
readonly slug: string;
|
||||
readonly updatedAt: any;
|
||||
} | null | undefined;
|
||||
@@ -114,6 +116,20 @@ v5 = {
|
||||
"name": "slug",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "ndaFileName",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "ndaFileUrl",
|
||||
"storageKey": null
|
||||
},
|
||||
(v4/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
@@ -544,16 +560,16 @@ return {
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "28c1a32327e2fee9320fd091100ec800",
|
||||
"cacheID": "8dff30a639470418ba7151cb5743d3cc",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "TrustCenterGraphQuery",
|
||||
"operationKind": "query",
|
||||
"text": "query TrustCenterGraphQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n ... on Organization {\n id\n name\n trustCenter {\n id\n active\n slug\n createdAt\n updatedAt\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 }\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 showOnTrustCenter\n createdAt\n}\n\nfragment TrustCenterDocumentsCardFragment on Document {\n id\n title\n createdAt\n documentType\n showOnTrustCenter\n versions(first: 1) {\n edges {\n node {\n id\n status\n }\n }\n }\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 trustCenter {\n id\n active\n slug\n ndaFileName\n ndaFileUrl\n createdAt\n updatedAt\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 }\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 showOnTrustCenter\n createdAt\n}\n\nfragment TrustCenterDocumentsCardFragment on Document {\n id\n title\n createdAt\n documentType\n showOnTrustCenter\n versions(first: 1) {\n edges {\n node {\n id\n status\n }\n }\n }\n}\n\nfragment TrustCenterVendorsCardFragment on Vendor {\n id\n name\n category\n description\n showOnTrustCenter\n createdAt\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "260529b3ca03240b07989f278bb7a539";
|
||||
(node as any).hash = "21b2915ae5002dd54c990013e94adf5d";
|
||||
|
||||
export default node;
|
||||
|
||||
123
apps/console/src/hooks/graph/__generated__/TrustCenterGraphUploadNDAMutation.graphql.ts
generated
Normal file
123
apps/console/src/hooks/graph/__generated__/TrustCenterGraphUploadNDAMutation.graphql.ts
generated
Normal file
@@ -0,0 +1,123 @@
|
||||
/**
|
||||
* @generated SignedSource<<966d4aa638042469c717ddc96e5c5d78>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
export type UploadTrustCenterNDAInput = {
|
||||
file: any;
|
||||
fileName: string;
|
||||
trustCenterId: string;
|
||||
};
|
||||
export type TrustCenterGraphUploadNDAMutation$variables = {
|
||||
input: UploadTrustCenterNDAInput;
|
||||
};
|
||||
export type TrustCenterGraphUploadNDAMutation$data = {
|
||||
readonly uploadTrustCenterNDA: {
|
||||
readonly trustCenter: {
|
||||
readonly id: string;
|
||||
readonly ndaFileName: string | null | undefined;
|
||||
readonly updatedAt: any;
|
||||
};
|
||||
};
|
||||
};
|
||||
export type TrustCenterGraphUploadNDAMutation = {
|
||||
response: TrustCenterGraphUploadNDAMutation$data;
|
||||
variables: TrustCenterGraphUploadNDAMutation$variables;
|
||||
};
|
||||
|
||||
const node: ConcreteRequest = (function(){
|
||||
var v0 = [
|
||||
{
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "input"
|
||||
}
|
||||
],
|
||||
v1 = [
|
||||
{
|
||||
"alias": null,
|
||||
"args": [
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "input",
|
||||
"variableName": "input"
|
||||
}
|
||||
],
|
||||
"concreteType": "UploadTrustCenterNDAPayload",
|
||||
"kind": "LinkedField",
|
||||
"name": "uploadTrustCenterNDA",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "TrustCenter",
|
||||
"kind": "LinkedField",
|
||||
"name": "trustCenter",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "id",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "ndaFileName",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "updatedAt",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
];
|
||||
return {
|
||||
"fragment": {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "TrustCenterGraphUploadNDAMutation",
|
||||
"selections": (v1/*: any*/),
|
||||
"type": "Mutation",
|
||||
"abstractKey": null
|
||||
},
|
||||
"kind": "Request",
|
||||
"operation": {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Operation",
|
||||
"name": "TrustCenterGraphUploadNDAMutation",
|
||||
"selections": (v1/*: any*/)
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "09a5dbf73f3e279173691b235f9da2e2",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "TrustCenterGraphUploadNDAMutation",
|
||||
"operationKind": "mutation",
|
||||
"text": "mutation TrustCenterGraphUploadNDAMutation(\n $input: UploadTrustCenterNDAInput!\n) {\n uploadTrustCenterNDA(input: $input) {\n trustCenter {\n id\n ndaFileName\n updatedAt\n }\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "b9877f8a5b9c2c12addeb939360719f1";
|
||||
|
||||
export default node;
|
||||
@@ -34,6 +34,9 @@ interface TrustCenterQueryData {
|
||||
active: boolean;
|
||||
slug: string;
|
||||
isUserAuthenticated: boolean;
|
||||
hasAcceptedNonDisclosureAgreement: boolean;
|
||||
ndaFileName: string | null;
|
||||
ndaFileUrl: string | null;
|
||||
organization: {
|
||||
id: string;
|
||||
name: string;
|
||||
@@ -96,7 +99,19 @@ interface CreateTrustCenterAccessVariables {
|
||||
};
|
||||
}
|
||||
|
||||
type GraphQLVariables = TrustCenterQueryVariables | ExportDocumentPDFVariables | CreateTrustCenterAccessVariables | Record<string, never>;
|
||||
interface AcceptNonDisclosureAgreementData {
|
||||
acceptNonDisclosureAgreement: {
|
||||
success: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
interface AcceptNonDisclosureAgreementVariables {
|
||||
input: {
|
||||
trustCenterId: string;
|
||||
};
|
||||
}
|
||||
|
||||
type GraphQLVariables = TrustCenterQueryVariables | ExportDocumentPDFVariables | CreateTrustCenterAccessVariables | AcceptNonDisclosureAgreementVariables | Record<string, never>;
|
||||
|
||||
async function trustCenterGraphQLRequest<T = unknown>(
|
||||
operationName: string,
|
||||
@@ -127,12 +142,14 @@ async function trustCenterGraphQLRequest<T = unknown>(
|
||||
|
||||
function isCriticalError(error: GraphQLError): boolean {
|
||||
const message = error.message?.toLowerCase() || '';
|
||||
const path = error.path || [];
|
||||
|
||||
if (message.includes('access denied') || message.includes('authentication required')) {
|
||||
if (path.length > 2) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
message.includes('access denied') ||
|
||||
message.includes('authentication required') ||
|
||||
message.includes('user has not accepted nda') ||
|
||||
message.includes('no nda file found')
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -145,6 +162,9 @@ const TRUST_CENTER_QUERY = `
|
||||
active
|
||||
slug
|
||||
isUserAuthenticated
|
||||
hasAcceptedNonDisclosureAgreement
|
||||
ndaFileName
|
||||
ndaFileUrl
|
||||
organization {
|
||||
id
|
||||
name
|
||||
@@ -213,6 +233,16 @@ const CREATE_TRUST_CENTER_ACCESS_MUTATION = `
|
||||
}
|
||||
`;
|
||||
|
||||
const ACCEPT_NDA_MUTATION = `
|
||||
mutation AcceptNonDisclosureAgreementMutation(
|
||||
$input: AcceptNonDisclosureAgreementInput!
|
||||
) {
|
||||
acceptNonDisclosureAgreement(input: $input) {
|
||||
success
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export function useTrustCenterQuery(slug: string) {
|
||||
return useQuery<TrustCenterQueryData>({
|
||||
queryKey: ["trust-center", slug],
|
||||
@@ -297,3 +327,27 @@ export function useCreateTrustCenterAccess() {
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useAcceptNonDisclosureAgreement() {
|
||||
return useMutation<AcceptNonDisclosureAgreementData, Error, { trustCenterId: string }>({
|
||||
mutationFn: async (input: { trustCenterId: string }) => {
|
||||
const result = await trustCenterGraphQLRequest<AcceptNonDisclosureAgreementData>(
|
||||
"AcceptNonDisclosureAgreementMutation",
|
||||
ACCEPT_NDA_MUTATION,
|
||||
{ input }
|
||||
);
|
||||
|
||||
if (result.errors && result.errors.length > 0) {
|
||||
throw new Error(
|
||||
`GraphQL error: ${result.errors.map((e) => e.message).join(", ")}`
|
||||
);
|
||||
}
|
||||
|
||||
if (!result.data) {
|
||||
throw new Error("No data returned from mutation");
|
||||
}
|
||||
|
||||
return result.data;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -127,7 +127,9 @@ export default function TrustCenterAccessPage() {
|
||||
if (error) {
|
||||
const isTokenError = error.toLowerCase().includes('token') ||
|
||||
error.toLowerCase().includes('expired') ||
|
||||
error.toLowerCase().includes('invalid');
|
||||
error.toLowerCase().includes('invalid') ||
|
||||
error.toLowerCase().includes('401') ||
|
||||
error.toLowerCase().includes('unauthorized');
|
||||
|
||||
if (isTokenError) {
|
||||
return <TokenErrorPage error={error} />;
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
useDialogRef,
|
||||
IconTrashCan,
|
||||
IconPencil,
|
||||
IconCheckmark1,
|
||||
} from "@probo/ui";
|
||||
import { useTranslate } from "@probo/i18n";
|
||||
import { useOutletContext } from "react-router";
|
||||
@@ -85,6 +86,7 @@ export default function TrustCenterAccessTab() {
|
||||
email: string;
|
||||
name: string;
|
||||
active: boolean;
|
||||
hasAcceptedNonDisclosureAgreement: boolean;
|
||||
createdAt: Date;
|
||||
};
|
||||
|
||||
@@ -95,6 +97,7 @@ export default function TrustCenterAccessTab() {
|
||||
email: edge.node.email,
|
||||
name: edge.node.name,
|
||||
active: edge.node.active,
|
||||
hasAcceptedNonDisclosureAgreement: edge.node.hasAcceptedNonDisclosureAgreement,
|
||||
createdAt: new Date(edge.node.createdAt)
|
||||
})) ?? [];
|
||||
|
||||
@@ -203,6 +206,7 @@ export default function TrustCenterAccessTab() {
|
||||
<Th>{__("Email")}</Th>
|
||||
<Th>{__("Date")}</Th>
|
||||
<Th>{__("Active")}</Th>
|
||||
<Th>{__("NDA")}</Th>
|
||||
<Th></Th>
|
||||
</Tr>
|
||||
</Thead>
|
||||
@@ -220,6 +224,11 @@ export default function TrustCenterAccessTab() {
|
||||
onChange={(active) => handleToggleActive(access.id, active)}
|
||||
/>
|
||||
</Td>
|
||||
<Td>
|
||||
{access.hasAcceptedNonDisclosureAgreement && (
|
||||
<IconCheckmark1 size={16} className="text-txt-success" />
|
||||
)}
|
||||
</Td>
|
||||
<Td noLink width={160} className="text-end">
|
||||
<div className="flex gap-2 justify-end">
|
||||
<Button
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
Button,
|
||||
Card,
|
||||
Checkbox,
|
||||
Dropzone,
|
||||
Field,
|
||||
Input,
|
||||
PageHeader,
|
||||
@@ -12,9 +13,10 @@ import {
|
||||
Tabs,
|
||||
TabLink,
|
||||
TabItem,
|
||||
IconTrashCan,
|
||||
} from "@probo/ui";
|
||||
import { usePreloadedQuery, type PreloadedQuery } from "react-relay";
|
||||
import { trustCenterQuery, useUpdateTrustCenterMutation } from "/hooks/graph/TrustCenterGraph";
|
||||
import { trustCenterQuery, useUpdateTrustCenterMutation, useUploadTrustCenterNDAMutation, useDeleteTrustCenterNDAMutation } from "/hooks/graph/TrustCenterGraph";
|
||||
import type { TrustCenterGraphQuery } from "/hooks/graph/__generated__/TrustCenterGraphQuery.graphql";
|
||||
import { useState } from "react";
|
||||
import { useOrganizationId } from "/hooks/useOrganizationId";
|
||||
@@ -32,6 +34,8 @@ export default function TrustCenterPage({ queryRef }: Props) {
|
||||
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);
|
||||
const [slug, setSlug] = useState(organization.trustCenter?.slug || "");
|
||||
const [isUpdatingSlug, setIsUpdatingSlug] = useState(false);
|
||||
@@ -101,6 +105,57 @@ export default function TrustCenterPage({ queryRef }: Props) {
|
||||
});
|
||||
};
|
||||
|
||||
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?.slug
|
||||
? `${window.location.origin}/trust/${organization.trustCenter.slug}`
|
||||
: null;
|
||||
@@ -211,6 +266,68 @@ export default function TrustCenterPage({ queryRef }: Props) {
|
||||
</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">
|
||||
<Tabs>
|
||||
<TabItem
|
||||
|
||||
187
apps/console/src/trust/components/NDAAcceptanceDialog.tsx
Normal file
187
apps/console/src/trust/components/NDAAcceptanceDialog.tsx
Normal file
@@ -0,0 +1,187 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogFooter,
|
||||
Button,
|
||||
Checkbox,
|
||||
IconLock,
|
||||
IconArrowDown,
|
||||
useToast,
|
||||
useDialogRef
|
||||
} from "@probo/ui";
|
||||
import { useTranslate } from "@probo/i18n";
|
||||
import { useAcceptNonDisclosureAgreement } from "/hooks/useTrustCenterQueries";
|
||||
import { buildEndpoint } from "/providers/RelayProviders";
|
||||
import { sprintf } from "@probo/helpers";
|
||||
|
||||
type Props = {
|
||||
trustCenterId: string;
|
||||
organizationName: string;
|
||||
ndaFileName?: string | null;
|
||||
ndaFileUrl?: string | null;
|
||||
};
|
||||
|
||||
export function NDAAcceptanceDialog({ trustCenterId, organizationName, ndaFileName, ndaFileUrl }: Props) {
|
||||
const { __ } = useTranslate();
|
||||
const { toast } = useToast();
|
||||
const [isChecked, setIsChecked] = useState(false);
|
||||
const dialogRef = useDialogRef();
|
||||
const acceptNdaMutation = useAcceptNonDisclosureAgreement();
|
||||
|
||||
useEffect(() => {
|
||||
dialogRef.current?.open();
|
||||
}, []);
|
||||
|
||||
const handleLogout = async () => {
|
||||
try {
|
||||
const response = await fetch(buildEndpoint('/api/trust/v1/auth/logout'), {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
credentials: 'include',
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error("Logout failed");
|
||||
}
|
||||
|
||||
window.location.reload();
|
||||
} catch (error) {
|
||||
toast({
|
||||
title: __("Error"),
|
||||
description: __("Logout failed"),
|
||||
variant: "error",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleAccept = () => {
|
||||
if (!isChecked) {
|
||||
toast({
|
||||
title: __("Agreement Required"),
|
||||
description: __("Please check the box to confirm your agreement"),
|
||||
variant: "error",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
acceptNdaMutation.mutate(
|
||||
{ trustCenterId },
|
||||
{
|
||||
onSuccess: () => {
|
||||
window.location.reload();
|
||||
},
|
||||
onError: () => {
|
||||
toast({
|
||||
title: __("Error"),
|
||||
description: __("Failed to accept the Non-Disclosure Agreement"),
|
||||
variant: "error",
|
||||
});
|
||||
},
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
handleLogout();
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
ref={dialogRef}
|
||||
closable={false}
|
||||
onClose={handleCancel}
|
||||
>
|
||||
<DialogContent>
|
||||
<div className="space-y-3 p-4">
|
||||
<div className="text-center">
|
||||
<div className="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-amber-50 border border-amber-200 mb-3">
|
||||
<IconLock className="h-6 w-6 text-amber-600" />
|
||||
</div>
|
||||
<h2 className="text-lg font-semibold text-txt-primary mb-2">
|
||||
{__("Non-Disclosure Agreement")}
|
||||
</h2>
|
||||
<p className="text-sm text-txt-secondary">
|
||||
{sprintf(__("To access %s's trust center, you must accept the Non-Disclosure Agreement."), organizationName)}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-level-1 p-3 rounded-lg border border-border-subtle">
|
||||
{ndaFileName && ndaFileUrl ? (
|
||||
<div className="text-center">
|
||||
<p className="text-sm font-medium text-txt-primary mb-3">
|
||||
{__("Please review and download the Non-Disclosure Agreement:")}
|
||||
</p>
|
||||
<div className="flex justify-center">
|
||||
<Button
|
||||
variant="secondary"
|
||||
icon={IconArrowDown}
|
||||
onClick={() => {
|
||||
const link = document.createElement('a');
|
||||
link.href = ndaFileUrl;
|
||||
link.download = ndaFileName || 'NDA.pdf';
|
||||
link.target = '_blank';
|
||||
link.rel = 'noopener noreferrer';
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
}}
|
||||
>
|
||||
{sprintf(__("Download %s"), ndaFileName)}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<p className="text-sm font-medium text-txt-primary mb-2">
|
||||
{__("By accepting this agreement, you commit to:")}
|
||||
</p>
|
||||
<ul className="text-sm text-txt-secondary space-y-0.5">
|
||||
<li className="flex items-start">
|
||||
<span className="inline-block w-2 h-2 rounded-full bg-txt-tertiary mt-1.5 mr-2 flex-shrink-0"></span>
|
||||
{__("Keep confidential information secure")}
|
||||
</li>
|
||||
<li className="flex items-start">
|
||||
<span className="inline-block w-2 h-2 rounded-full bg-txt-tertiary mt-1.5 mr-2 flex-shrink-0"></span>
|
||||
{__("Not share or disclose sensitive data")}
|
||||
</li>
|
||||
<li className="flex items-start">
|
||||
<span className="inline-block w-2 h-2 rounded-full bg-txt-tertiary mt-1.5 mr-2 flex-shrink-0"></span>
|
||||
{__("Use information only for authorized purposes")}
|
||||
</li>
|
||||
</ul>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex items-start space-x-2 p-3 bg-level-0 rounded-lg border border-border-subtle">
|
||||
<div className="mt-0.5">
|
||||
<Checkbox
|
||||
checked={isChecked}
|
||||
onChange={setIsChecked}
|
||||
/>
|
||||
</div>
|
||||
<label
|
||||
className="text-sm text-txt-primary cursor-pointer flex-1"
|
||||
onClick={() => setIsChecked(!isChecked)}
|
||||
>
|
||||
{__("I agree to the terms of the Non-Disclosure Agreement and will handle all information accordingly.")}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</DialogContent>
|
||||
|
||||
<DialogFooter exitLabel={__("Disconnect")}>
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={handleAccept}
|
||||
disabled={!isChecked || acceptNdaMutation.isPending}
|
||||
>
|
||||
{acceptNdaMutation.isPending ? __("Accepting...") : __("Accept & Continue")}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import { PublicTrustCenterLayout } from "/layouts/PublicTrustCenterLayout";
|
||||
import { PublicTrustCenterAudits } from "../components/PublicTrustCenterAudits";
|
||||
import { PublicTrustCenterVendors } from "../components/PublicTrustCenterVendors";
|
||||
import { PublicTrustCenterDocuments } from "../components/PublicTrustCenterDocuments";
|
||||
import { NDAAcceptanceDialog } from "../components/NDAAcceptanceDialog";
|
||||
import { Spinner } from "@probo/ui";
|
||||
import { useTrustCenterQuery, type TrustCenterDocument, type TrustCenterAudit, type TrustCenterVendor } from "/hooks/useTrustCenterQueries";
|
||||
|
||||
@@ -66,36 +67,49 @@ export default function PublicTrustCenterPage() {
|
||||
}
|
||||
|
||||
const { trustCenterBySlug } = data;
|
||||
const { documents, audits, vendors, isUserAuthenticated } = trustCenterBySlug;
|
||||
const { documents, audits, vendors, isUserAuthenticated, hasAcceptedNonDisclosureAgreement } = trustCenterBySlug;
|
||||
|
||||
const trustCenterDocuments = documents.edges.map((edge) => edge.node) as TrustCenterDocument[];
|
||||
const trustCenterAudits = audits.edges.map((edge) => edge.node) as TrustCenterAudit[];
|
||||
const trustCenterVendors = vendors.edges.map((edge) => edge.node) as TrustCenterVendor[];
|
||||
|
||||
const showNdaDialog = isUserAuthenticated && !hasAcceptedNonDisclosureAgreement;
|
||||
|
||||
return (
|
||||
<PublicTrustCenterLayout
|
||||
organizationName={organizationName}
|
||||
organizationLogo={organization?.logoUrl}
|
||||
isAuthenticated={isUserAuthenticated}
|
||||
>
|
||||
<div className="space-y-12">
|
||||
<PublicTrustCenterAudits
|
||||
audits={trustCenterAudits}
|
||||
organizationName={organizationName}
|
||||
isAuthenticated={isUserAuthenticated}
|
||||
<>
|
||||
{showNdaDialog && (
|
||||
<NDAAcceptanceDialog
|
||||
trustCenterId={trustCenterBySlug.id}
|
||||
/>
|
||||
<PublicTrustCenterDocuments
|
||||
documents={trustCenterDocuments}
|
||||
organizationName={organizationName}
|
||||
isAuthenticated={isUserAuthenticated}
|
||||
trustCenterId={trustCenterBySlug.id}
|
||||
ndaFileName={trustCenterBySlug.ndaFileName}
|
||||
ndaFileUrl={trustCenterBySlug.ndaFileUrl}
|
||||
/>
|
||||
<PublicTrustCenterVendors
|
||||
vendors={trustCenterVendors}
|
||||
organizationName={organizationName}
|
||||
/>
|
||||
</div>
|
||||
</PublicTrustCenterLayout>
|
||||
)}
|
||||
|
||||
<PublicTrustCenterLayout
|
||||
organizationName={organizationName}
|
||||
organizationLogo={organization?.logoUrl}
|
||||
isAuthenticated={isUserAuthenticated}
|
||||
>
|
||||
<div className="space-y-12">
|
||||
<PublicTrustCenterAudits
|
||||
audits={trustCenterAudits}
|
||||
organizationName={organizationName}
|
||||
isAuthenticated={isUserAuthenticated}
|
||||
trustCenterId={trustCenterBySlug.id}
|
||||
/>
|
||||
<PublicTrustCenterDocuments
|
||||
documents={trustCenterDocuments}
|
||||
organizationName={organizationName}
|
||||
isAuthenticated={isUserAuthenticated}
|
||||
trustCenterId={trustCenterBySlug.id}
|
||||
/>
|
||||
<PublicTrustCenterVendors
|
||||
vendors={trustCenterVendors}
|
||||
organizationName={organizationName}
|
||||
/>
|
||||
</div>
|
||||
</PublicTrustCenterLayout>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ type Props = {
|
||||
className?: string;
|
||||
ref?: DialogRef;
|
||||
onClose?: () => void;
|
||||
closable?: boolean;
|
||||
};
|
||||
|
||||
export const useDialogRef = (): DialogRef => {
|
||||
@@ -64,6 +65,7 @@ export function Dialog({
|
||||
ref,
|
||||
defaultOpen,
|
||||
onClose,
|
||||
closable = true,
|
||||
}: Props) {
|
||||
const { overlay, content, header, title: titleClassname } = dialog();
|
||||
const [open, setOpen] = useState(!!defaultOpen);
|
||||
@@ -80,41 +82,55 @@ export function Dialog({
|
||||
}
|
||||
|
||||
const onOpenChange = (open: boolean) => {
|
||||
if (!open && !closable) {
|
||||
return;
|
||||
}
|
||||
setOpen(open);
|
||||
if (!open) {
|
||||
onClose?.();
|
||||
}
|
||||
};
|
||||
|
||||
const contentProps = closable ? {} : {
|
||||
onEscapeKeyDown: (e: Event) => e.preventDefault(),
|
||||
onPointerDownOutside: (e: Event) => e.preventDefault(),
|
||||
onInteractOutside: (e: Event) => e.preventDefault(),
|
||||
};
|
||||
|
||||
return (
|
||||
<Root open={open} onOpenChange={onOpenChange}>
|
||||
<Root open={open} onOpenChange={closable ? onOpenChange : undefined}>
|
||||
{trigger && <Trigger asChild>{trigger}</Trigger>}
|
||||
<Portal>
|
||||
<Overlay className={overlay()} />
|
||||
<Content
|
||||
aria-describedby={undefined}
|
||||
className={content({ className })}
|
||||
{...contentProps}
|
||||
>
|
||||
{title ? (
|
||||
<div className={header()}>
|
||||
<Title className={titleClassname()}> {title}</Title>
|
||||
{closable && (
|
||||
<Close asChild>
|
||||
<Button
|
||||
tabIndex={-1}
|
||||
variant="tertiary"
|
||||
icon={IconCrossLargeX}
|
||||
/>
|
||||
</Close>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
closable && (
|
||||
<Close asChild>
|
||||
<Button
|
||||
tabIndex={-1}
|
||||
variant="tertiary"
|
||||
className="absolute top-4 right-4"
|
||||
icon={IconCrossLargeX}
|
||||
/>
|
||||
</Close>
|
||||
</div>
|
||||
) : (
|
||||
<Close asChild>
|
||||
<Button
|
||||
tabIndex={-1}
|
||||
variant="tertiary"
|
||||
className="absolute top-4 right-4"
|
||||
icon={IconCrossLargeX}
|
||||
/>
|
||||
</Close>
|
||||
)
|
||||
)}
|
||||
{children}
|
||||
</Content>
|
||||
|
||||
@@ -14,6 +14,12 @@
|
||||
|
||||
package coredata
|
||||
|
||||
type ctxKey struct{ name string }
|
||||
|
||||
var (
|
||||
ContextKeyIPAddress = &ctxKey{name: "ip_address"}
|
||||
)
|
||||
|
||||
const (
|
||||
OrganizationEntityType uint16 = iota
|
||||
FrameworkEntityType
|
||||
|
||||
10
pkg/coredata/migrations/20250909T114034Z.sql
Normal file
10
pkg/coredata/migrations/20250909T114034Z.sql
Normal file
@@ -0,0 +1,10 @@
|
||||
ALTER TABLE trust_center_accesses ADD COLUMN has_accepted_non_disclosure_agreement BOOLEAN NOT NULL DEFAULT FALSE;
|
||||
ALTER TABLE trust_center_accesses ALTER COLUMN has_accepted_non_disclosure_agreement DROP DEFAULT;
|
||||
ALTER TABLE trust_center_accesses ADD COLUMN has_accepted_non_disclosure_agreement_metadata JSONB;
|
||||
|
||||
ALTER TABLE trust_centers ADD COLUMN non_disclosure_agreement_file_id TEXT;
|
||||
ALTER TABLE trust_centers ADD CONSTRAINT trust_centers_non_disclosure_agreement_file_id_fkey
|
||||
FOREIGN KEY (non_disclosure_agreement_file_id)
|
||||
REFERENCES files(id)
|
||||
ON UPDATE CASCADE
|
||||
ON DELETE RESTRICT;
|
||||
@@ -28,13 +28,14 @@ import (
|
||||
|
||||
type (
|
||||
TrustCenter struct {
|
||||
ID gid.GID `db:"id"`
|
||||
OrganizationID gid.GID `db:"organization_id"`
|
||||
TenantID gid.TenantID `db:"tenant_id"`
|
||||
Active bool `db:"active"`
|
||||
Slug string `db:"slug"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
ID gid.GID `db:"id"`
|
||||
OrganizationID gid.GID `db:"organization_id"`
|
||||
TenantID gid.TenantID `db:"tenant_id"`
|
||||
Active bool `db:"active"`
|
||||
Slug string `db:"slug"`
|
||||
NonDisclosureAgreementFileID *gid.GID `db:"non_disclosure_agreement_file_id"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
}
|
||||
|
||||
TrustCenters []*TrustCenter
|
||||
@@ -62,6 +63,7 @@ SELECT
|
||||
tenant_id,
|
||||
active,
|
||||
slug,
|
||||
non_disclosure_agreement_file_id,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
@@ -105,6 +107,7 @@ SELECT
|
||||
tenant_id,
|
||||
active,
|
||||
slug,
|
||||
non_disclosure_agreement_file_id,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
@@ -147,6 +150,7 @@ SELECT
|
||||
tenant_id,
|
||||
active,
|
||||
slug,
|
||||
non_disclosure_agreement_file_id,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
@@ -185,6 +189,7 @@ INSERT INTO trust_centers (
|
||||
tenant_id,
|
||||
active,
|
||||
slug,
|
||||
non_disclosure_agreement_file_id,
|
||||
created_at,
|
||||
updated_at
|
||||
) VALUES (
|
||||
@@ -193,19 +198,21 @@ INSERT INTO trust_centers (
|
||||
@tenant_id,
|
||||
@active,
|
||||
@slug,
|
||||
@non_disclosure_agreement_file_id,
|
||||
@created_at,
|
||||
@updated_at
|
||||
)
|
||||
`
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"id": tc.ID,
|
||||
"organization_id": tc.OrganizationID,
|
||||
"tenant_id": tc.TenantID,
|
||||
"active": tc.Active,
|
||||
"slug": tc.Slug,
|
||||
"created_at": tc.CreatedAt,
|
||||
"updated_at": tc.UpdatedAt,
|
||||
"id": tc.ID,
|
||||
"organization_id": tc.OrganizationID,
|
||||
"tenant_id": tc.TenantID,
|
||||
"active": tc.Active,
|
||||
"slug": tc.Slug,
|
||||
"non_disclosure_agreement_file_id": tc.NonDisclosureAgreementFileID,
|
||||
"created_at": tc.CreatedAt,
|
||||
"updated_at": tc.UpdatedAt,
|
||||
}
|
||||
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
@@ -226,6 +233,7 @@ UPDATE trust_centers
|
||||
SET
|
||||
active = @active,
|
||||
slug = @slug,
|
||||
non_disclosure_agreement_file_id = @non_disclosure_agreement_file_id,
|
||||
updated_at = @updated_at
|
||||
WHERE
|
||||
%s
|
||||
@@ -235,10 +243,11 @@ WHERE
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"id": tc.ID,
|
||||
"active": tc.Active,
|
||||
"slug": tc.Slug,
|
||||
"updated_at": tc.UpdatedAt,
|
||||
"id": tc.ID,
|
||||
"active": tc.Active,
|
||||
"slug": tc.Slug,
|
||||
"non_disclosure_agreement_file_id": tc.NonDisclosureAgreementFileID,
|
||||
"updated_at": tc.UpdatedAt,
|
||||
}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ package coredata
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"maps"
|
||||
@@ -29,14 +30,16 @@ import (
|
||||
|
||||
type (
|
||||
TrustCenterAccess struct {
|
||||
ID gid.GID `db:"id"`
|
||||
TenantID gid.TenantID `db:"tenant_id"`
|
||||
TrustCenterID gid.GID `db:"trust_center_id"`
|
||||
Email string `db:"email"`
|
||||
Name string `db:"name"`
|
||||
Active bool `db:"active"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
ID gid.GID `db:"id"`
|
||||
TenantID gid.TenantID `db:"tenant_id"`
|
||||
TrustCenterID gid.GID `db:"trust_center_id"`
|
||||
Email string `db:"email"`
|
||||
Name string `db:"name"`
|
||||
Active bool `db:"active"`
|
||||
HasAcceptedNonDisclosureAgreement bool `db:"has_accepted_non_disclosure_agreement"`
|
||||
HasAcceptedNonDisclosureAgreementMetadata json.RawMessage `db:"has_accepted_non_disclosure_agreement_metadata"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
}
|
||||
|
||||
TrustCenterAccesses []*TrustCenterAccess
|
||||
@@ -73,6 +76,8 @@ SELECT
|
||||
email,
|
||||
name,
|
||||
active,
|
||||
has_accepted_non_disclosure_agreement,
|
||||
has_accepted_non_disclosure_agreement_metadata,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
@@ -122,6 +127,8 @@ SELECT
|
||||
email,
|
||||
name,
|
||||
active,
|
||||
has_accepted_non_disclosure_agreement,
|
||||
has_accepted_non_disclosure_agreement_metadata,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
@@ -173,6 +180,7 @@ INSERT INTO trust_center_accesses (
|
||||
email,
|
||||
name,
|
||||
active,
|
||||
has_accepted_non_disclosure_agreement,
|
||||
created_at,
|
||||
updated_at
|
||||
) VALUES (
|
||||
@@ -182,20 +190,22 @@ INSERT INTO trust_center_accesses (
|
||||
@email,
|
||||
@name,
|
||||
@active,
|
||||
@has_accepted_non_disclosure_agreement,
|
||||
@created_at,
|
||||
@updated_at
|
||||
)
|
||||
`
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"id": tca.ID,
|
||||
"tenant_id": tca.TenantID,
|
||||
"trust_center_id": tca.TrustCenterID,
|
||||
"email": tca.Email,
|
||||
"name": tca.Name,
|
||||
"active": tca.Active,
|
||||
"created_at": tca.CreatedAt,
|
||||
"updated_at": tca.UpdatedAt,
|
||||
"id": tca.ID,
|
||||
"tenant_id": tca.TenantID,
|
||||
"trust_center_id": tca.TrustCenterID,
|
||||
"email": tca.Email,
|
||||
"name": tca.Name,
|
||||
"active": tca.Active,
|
||||
"has_accepted_non_disclosure_agreement": tca.HasAcceptedNonDisclosureAgreement,
|
||||
"created_at": tca.CreatedAt,
|
||||
"updated_at": tca.UpdatedAt,
|
||||
}
|
||||
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
@@ -215,7 +225,9 @@ func (tca *TrustCenterAccess) Update(
|
||||
UPDATE trust_center_accesses SET
|
||||
name = @name,
|
||||
active = @active,
|
||||
updated_at = @updated_at
|
||||
updated_at = @updated_at,
|
||||
has_accepted_non_disclosure_agreement = @has_accepted_non_disclosure_agreement,
|
||||
has_accepted_non_disclosure_agreement_metadata = @has_accepted_non_disclosure_agreement_metadata
|
||||
WHERE
|
||||
%s
|
||||
AND id = @id
|
||||
@@ -224,10 +236,12 @@ WHERE
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"id": tca.ID,
|
||||
"name": tca.Name,
|
||||
"active": tca.Active,
|
||||
"updated_at": tca.UpdatedAt,
|
||||
"id": tca.ID,
|
||||
"name": tca.Name,
|
||||
"active": tca.Active,
|
||||
"updated_at": tca.UpdatedAt,
|
||||
"has_accepted_non_disclosure_agreement": tca.HasAcceptedNonDisclosureAgreement,
|
||||
"has_accepted_non_disclosure_agreement_metadata": tca.HasAcceptedNonDisclosureAgreementMetadata,
|
||||
}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
@@ -281,6 +295,8 @@ SELECT
|
||||
email,
|
||||
name,
|
||||
active,
|
||||
has_accepted_non_disclosure_agreement,
|
||||
has_accepted_non_disclosure_agreement_metadata,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
|
||||
@@ -149,14 +149,15 @@ func (s TrustCenterAccessService) Create(
|
||||
}
|
||||
|
||||
access = &coredata.TrustCenterAccess{
|
||||
ID: gid.New(s.svc.scope.GetTenantID(), coredata.TrustCenterAccessEntityType),
|
||||
TenantID: s.svc.scope.GetTenantID(),
|
||||
TrustCenterID: req.TrustCenterID,
|
||||
Email: req.Email,
|
||||
Name: req.Name,
|
||||
Active: req.Active,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
ID: gid.New(s.svc.scope.GetTenantID(), coredata.TrustCenterAccessEntityType),
|
||||
TenantID: s.svc.scope.GetTenantID(),
|
||||
TrustCenterID: req.TrustCenterID,
|
||||
Email: req.Email,
|
||||
Name: req.Name,
|
||||
Active: req.Active,
|
||||
HasAcceptedNonDisclosureAgreement: false,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
|
||||
if err := access.Insert(ctx, tx, s.svc.scope); err != nil {
|
||||
|
||||
@@ -17,10 +17,17 @@ package probo
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime"
|
||||
"net/url"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||
"github.com/getprobo/probo/pkg/coredata"
|
||||
"github.com/getprobo/probo/pkg/gid"
|
||||
"go.gearno.de/crypto/uuid"
|
||||
"go.gearno.de/kit/pg"
|
||||
)
|
||||
|
||||
@@ -30,71 +37,100 @@ type (
|
||||
}
|
||||
|
||||
UpdateTrustCenterRequest struct {
|
||||
ID gid.GID
|
||||
Active *bool
|
||||
Slug *string
|
||||
ID gid.GID
|
||||
Active *bool
|
||||
Slug *string
|
||||
NonDisclosureAgreementFileID *gid.GID
|
||||
}
|
||||
|
||||
UploadTrustCenterNDARequest struct {
|
||||
TrustCenterID gid.GID
|
||||
File io.Reader
|
||||
FileName string
|
||||
}
|
||||
|
||||
DeleteTrustCenterNDARequest struct {
|
||||
TrustCenterID gid.GID
|
||||
}
|
||||
)
|
||||
|
||||
func (s TrustCenterService) Get(
|
||||
ctx context.Context,
|
||||
trustCenterID gid.GID,
|
||||
) (*coredata.TrustCenter, error) {
|
||||
trustCenter := &coredata.TrustCenter{}
|
||||
) (*coredata.TrustCenter, *coredata.File, error) {
|
||||
var trustCenter *coredata.TrustCenter
|
||||
var file *coredata.File
|
||||
|
||||
err := s.svc.pg.WithConn(
|
||||
ctx,
|
||||
func(conn pg.Conn) error {
|
||||
err := trustCenter.LoadByID(ctx, conn, s.svc.scope, trustCenterID)
|
||||
if err != nil {
|
||||
trustCenter = &coredata.TrustCenter{}
|
||||
if err := trustCenter.LoadByID(ctx, conn, s.svc.scope, trustCenterID); err != nil {
|
||||
return fmt.Errorf("cannot load trust center: %w", err)
|
||||
}
|
||||
|
||||
if trustCenter.NonDisclosureAgreementFileID != nil {
|
||||
file = &coredata.File{}
|
||||
if err := file.LoadByID(ctx, conn, s.svc.scope, *trustCenter.NonDisclosureAgreementFileID); err != nil {
|
||||
return fmt.Errorf("cannot load file: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, fmt.Errorf("cannot load trust center: %w", err)
|
||||
}
|
||||
|
||||
return trustCenter, nil
|
||||
return trustCenter, file, nil
|
||||
}
|
||||
|
||||
func (s TrustCenterService) GetByOrganizationID(
|
||||
ctx context.Context,
|
||||
organizationID gid.GID,
|
||||
) (*coredata.TrustCenter, error) {
|
||||
trustCenter := &coredata.TrustCenter{}
|
||||
) (*coredata.TrustCenter, *coredata.File, error) {
|
||||
var trustCenter *coredata.TrustCenter
|
||||
var file *coredata.File
|
||||
|
||||
err := s.svc.pg.WithConn(
|
||||
ctx,
|
||||
func(conn pg.Conn) error {
|
||||
err := trustCenter.LoadByOrganizationID(ctx, conn, s.svc.scope, organizationID)
|
||||
if err != nil {
|
||||
trustCenter = &coredata.TrustCenter{}
|
||||
if err := trustCenter.LoadByOrganizationID(ctx, conn, s.svc.scope, organizationID); err != nil {
|
||||
return fmt.Errorf("cannot load trust center: %w", err)
|
||||
}
|
||||
|
||||
if trustCenter.NonDisclosureAgreementFileID != nil {
|
||||
file = &coredata.File{}
|
||||
if err := file.LoadByID(ctx, conn, s.svc.scope, *trustCenter.NonDisclosureAgreementFileID); err != nil {
|
||||
return fmt.Errorf("cannot load file: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return trustCenter, nil
|
||||
return trustCenter, file, nil
|
||||
}
|
||||
|
||||
func (s TrustCenterService) Update(
|
||||
ctx context.Context,
|
||||
req *UpdateTrustCenterRequest,
|
||||
) (*coredata.TrustCenter, error) {
|
||||
trustCenter := &coredata.TrustCenter{}
|
||||
) (*coredata.TrustCenter, *coredata.File, error) {
|
||||
var trustCenter *coredata.TrustCenter
|
||||
var file *coredata.File
|
||||
|
||||
err := s.svc.pg.WithTx(
|
||||
ctx,
|
||||
func(conn pg.Conn) error {
|
||||
trustCenter = &coredata.TrustCenter{}
|
||||
if err := trustCenter.LoadByID(ctx, conn, s.svc.scope, req.ID); err != nil {
|
||||
return fmt.Errorf("cannot load trust center: %w", err)
|
||||
}
|
||||
@@ -112,13 +148,189 @@ func (s TrustCenterService) Update(
|
||||
return fmt.Errorf("cannot update trust center: %w", err)
|
||||
}
|
||||
|
||||
if trustCenter.NonDisclosureAgreementFileID != nil {
|
||||
file = &coredata.File{}
|
||||
if err := file.LoadByID(ctx, conn, s.svc.scope, *trustCenter.NonDisclosureAgreementFileID); err != nil {
|
||||
return fmt.Errorf("cannot load file: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return trustCenter, file, nil
|
||||
}
|
||||
|
||||
func (s TrustCenterService) UploadNDA(
|
||||
ctx context.Context,
|
||||
req *UploadTrustCenterNDARequest,
|
||||
) (*coredata.TrustCenter, *coredata.File, error) {
|
||||
objectKey, err := uuid.NewV7()
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("cannot generate object key: %w", err)
|
||||
}
|
||||
|
||||
mimeType := mime.TypeByExtension(filepath.Ext(req.FileName))
|
||||
|
||||
_, err = s.svc.s3.PutObject(ctx, &s3.PutObjectInput{
|
||||
Bucket: &s.svc.bucket,
|
||||
Key: aws.String(objectKey.String()),
|
||||
Body: req.File,
|
||||
ContentType: &mimeType,
|
||||
Metadata: map[string]string{
|
||||
"type": "trust-center-nda",
|
||||
"trust-center-id": req.TrustCenterID.String(),
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("cannot upload file to S3: %w", err)
|
||||
}
|
||||
|
||||
headOutput, err := s.svc.s3.HeadObject(ctx, &s3.HeadObjectInput{
|
||||
Bucket: aws.String(s.svc.bucket),
|
||||
Key: aws.String(objectKey.String()),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("cannot get object metadata: %w", err)
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
|
||||
fileID := gid.New(s.svc.scope.GetTenantID(), coredata.FileEntityType)
|
||||
|
||||
var trustCenter *coredata.TrustCenter
|
||||
var file *coredata.File
|
||||
|
||||
err = s.svc.pg.WithTx(
|
||||
ctx,
|
||||
func(conn pg.Conn) error {
|
||||
trustCenter = &coredata.TrustCenter{}
|
||||
if err := trustCenter.LoadByID(ctx, conn, s.svc.scope, req.TrustCenterID); err != nil {
|
||||
return fmt.Errorf("cannot load trust center: %w", err)
|
||||
}
|
||||
|
||||
file = &coredata.File{
|
||||
ID: fileID,
|
||||
BucketName: s.svc.bucket,
|
||||
MimeType: mimeType,
|
||||
FileName: req.FileName,
|
||||
FileKey: objectKey.String(),
|
||||
FileSize: int(*headOutput.ContentLength),
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
|
||||
if err := file.Insert(ctx, conn, s.svc.scope); err != nil {
|
||||
return fmt.Errorf("cannot insert file: %w", err)
|
||||
}
|
||||
|
||||
trustCenter.NonDisclosureAgreementFileID = &fileID
|
||||
trustCenter.UpdatedAt = now
|
||||
|
||||
if err := trustCenter.Update(ctx, conn, s.svc.scope); err != nil {
|
||||
return fmt.Errorf("cannot update trust center: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return trustCenter, file, nil
|
||||
}
|
||||
|
||||
func (s TrustCenterService) DeleteNDA(
|
||||
ctx context.Context,
|
||||
req *DeleteTrustCenterNDARequest,
|
||||
) (*coredata.TrustCenter, *coredata.File, error) {
|
||||
var trustCenter *coredata.TrustCenter
|
||||
|
||||
err := s.svc.pg.WithTx(
|
||||
ctx,
|
||||
func(conn pg.Conn) error {
|
||||
trustCenter = &coredata.TrustCenter{}
|
||||
if err := trustCenter.LoadByID(ctx, conn, s.svc.scope, req.TrustCenterID); err != nil {
|
||||
return fmt.Errorf("cannot load trust center: %w", err)
|
||||
}
|
||||
|
||||
trustCenter.NonDisclosureAgreementFileID = nil
|
||||
trustCenter.UpdatedAt = time.Now()
|
||||
|
||||
if err := trustCenter.Update(ctx, conn, s.svc.scope); err != nil {
|
||||
return fmt.Errorf("cannot update trust center: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return trustCenter, nil, nil // File is nil after deletion
|
||||
}
|
||||
|
||||
func (s TrustCenterService) GenerateNDAFileURL(
|
||||
ctx context.Context,
|
||||
trustCenterID gid.GID,
|
||||
expiresIn time.Duration,
|
||||
) (*string, error) {
|
||||
var file *coredata.File
|
||||
trustCenter := &coredata.TrustCenter{}
|
||||
|
||||
err := s.svc.pg.WithConn(
|
||||
ctx,
|
||||
func(conn pg.Conn) error {
|
||||
if err := trustCenter.LoadByID(ctx, conn, s.svc.scope, trustCenterID); err != nil {
|
||||
return fmt.Errorf("cannot load trust center: %w", err)
|
||||
}
|
||||
|
||||
if trustCenter.NonDisclosureAgreementFileID == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
file = &coredata.File{}
|
||||
if err := file.LoadByID(ctx, conn, s.svc.scope, *trustCenter.NonDisclosureAgreementFileID); err != nil {
|
||||
return fmt.Errorf("cannot load file: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return trustCenter, nil
|
||||
if trustCenter.NonDisclosureAgreementFileID == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
presignClient := s3.NewPresignClient(s.svc.s3)
|
||||
|
||||
encodedFilename := url.QueryEscape(file.FileName)
|
||||
contentDisposition := fmt.Sprintf("attachment; filename=\"%s\"; filename*=UTF-8''%s",
|
||||
encodedFilename, encodedFilename)
|
||||
|
||||
presignedReq, err := presignClient.PresignGetObject(ctx, &s3.GetObjectInput{
|
||||
Bucket: aws.String(s.svc.bucket),
|
||||
Key: aws.String(file.FileKey),
|
||||
ResponseCacheControl: aws.String("max-age=3600, public"),
|
||||
ResponseContentDisposition: aws.String(contentDisposition),
|
||||
}, func(opts *s3.PresignOptions) {
|
||||
opts.Expires = expiresIn
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot presign GetObject request: %w", err)
|
||||
}
|
||||
|
||||
return &presignedReq.URL, nil
|
||||
}
|
||||
|
||||
@@ -1144,6 +1144,8 @@ type TrustCenter implements Node {
|
||||
id: ID!
|
||||
active: Boolean!
|
||||
slug: String!
|
||||
ndaFileName: String
|
||||
ndaFileUrl: String @goField(forceResolver: true)
|
||||
createdAt: Datetime!
|
||||
updatedAt: Datetime!
|
||||
organization: Organization! @goField(forceResolver: true)
|
||||
@@ -1889,6 +1891,7 @@ type TrustCenterAccess implements Node {
|
||||
email: String!
|
||||
name: String!
|
||||
active: Boolean!
|
||||
hasAcceptedNonDisclosureAgreement: Boolean!
|
||||
createdAt: Datetime!
|
||||
updatedAt: Datetime!
|
||||
}
|
||||
@@ -2218,6 +2221,14 @@ type Mutation {
|
||||
input: UpdateTrustCenterInput!
|
||||
): UpdateTrustCenterPayload!
|
||||
|
||||
uploadTrustCenterNDA(
|
||||
input: UploadTrustCenterNDAInput!
|
||||
): UploadTrustCenterNDAPayload!
|
||||
|
||||
deleteTrustCenterNDA(
|
||||
input: DeleteTrustCenterNDAInput!
|
||||
): DeleteTrustCenterNDAPayload!
|
||||
|
||||
# Trust Center Access CRUD mutations
|
||||
createTrustCenterAccess(
|
||||
input: CreateTrustCenterAccessInput!
|
||||
@@ -2503,6 +2514,16 @@ input UpdateTrustCenterInput {
|
||||
slug: String
|
||||
}
|
||||
|
||||
input UploadTrustCenterNDAInput {
|
||||
trustCenterId: ID!
|
||||
fileName: String!
|
||||
file: Upload!
|
||||
}
|
||||
|
||||
input DeleteTrustCenterNDAInput {
|
||||
trustCenterId: ID!
|
||||
}
|
||||
|
||||
input CreateTrustCenterAccessInput {
|
||||
trustCenterId: ID!
|
||||
email: String!
|
||||
@@ -3135,6 +3156,14 @@ type UpdateTrustCenterPayload {
|
||||
trustCenter: TrustCenter!
|
||||
}
|
||||
|
||||
type UploadTrustCenterNDAPayload {
|
||||
trustCenter: TrustCenter!
|
||||
}
|
||||
|
||||
type DeleteTrustCenterNDAPayload {
|
||||
trustCenter: TrustCenter!
|
||||
}
|
||||
|
||||
type CreateTrustCenterAccessPayload {
|
||||
trustCenterAccessEdge: TrustCenterAccessEdge!
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -18,12 +18,18 @@ import (
|
||||
"github.com/getprobo/probo/pkg/coredata"
|
||||
)
|
||||
|
||||
func NewTrustCenter(tc *coredata.TrustCenter) *TrustCenter {
|
||||
func NewTrustCenter(tc *coredata.TrustCenter, file *coredata.File) *TrustCenter {
|
||||
var ndaFileName *string
|
||||
if file != nil {
|
||||
ndaFileName = &file.FileName
|
||||
}
|
||||
|
||||
return &TrustCenter{
|
||||
ID: tc.ID,
|
||||
Active: tc.Active,
|
||||
Slug: tc.Slug,
|
||||
CreatedAt: tc.CreatedAt,
|
||||
UpdatedAt: tc.UpdatedAt,
|
||||
ID: tc.ID,
|
||||
Active: tc.Active,
|
||||
Slug: tc.Slug,
|
||||
NdaFileName: ndaFileName,
|
||||
CreatedAt: tc.CreatedAt,
|
||||
UpdatedAt: tc.UpdatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,12 +23,13 @@ type TrustCenterAccessOrderBy = OrderBy[coredata.TrustCenterAccessOrderField]
|
||||
|
||||
func NewTrustCenterAccess(tca *coredata.TrustCenterAccess) *TrustCenterAccess {
|
||||
return &TrustCenterAccess{
|
||||
ID: tca.ID,
|
||||
Email: tca.Email,
|
||||
Name: tca.Name,
|
||||
Active: tca.Active,
|
||||
CreatedAt: tca.CreatedAt,
|
||||
UpdatedAt: tca.UpdatedAt,
|
||||
ID: tca.ID,
|
||||
Email: tca.Email,
|
||||
Name: tca.Name,
|
||||
Active: tca.Active,
|
||||
HasAcceptedNonDisclosureAgreement: tca.HasAcceptedNonDisclosureAgreement,
|
||||
CreatedAt: tca.CreatedAt,
|
||||
UpdatedAt: tca.UpdatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -828,6 +828,14 @@ type DeleteTrustCenterAccessPayload struct {
|
||||
DeletedTrustCenterAccessID gid.GID `json:"deletedTrustCenterAccessId"`
|
||||
}
|
||||
|
||||
type DeleteTrustCenterNDAInput struct {
|
||||
TrustCenterID gid.GID `json:"trustCenterId"`
|
||||
}
|
||||
|
||||
type DeleteTrustCenterNDAPayload struct {
|
||||
TrustCenter *TrustCenter `json:"trustCenter"`
|
||||
}
|
||||
|
||||
type DeleteVendorBusinessAssociateAgreementInput struct {
|
||||
VendorID gid.GID `json:"vendorId"`
|
||||
}
|
||||
@@ -1436,6 +1444,8 @@ type TrustCenter struct {
|
||||
ID gid.GID `json:"id"`
|
||||
Active bool `json:"active"`
|
||||
Slug string `json:"slug"`
|
||||
NdaFileName *string `json:"ndaFileName,omitempty"`
|
||||
NdaFileURL *string `json:"ndaFileUrl,omitempty"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
Organization *Organization `json:"organization"`
|
||||
@@ -1446,12 +1456,13 @@ func (TrustCenter) IsNode() {}
|
||||
func (this TrustCenter) GetID() gid.GID { return this.ID }
|
||||
|
||||
type TrustCenterAccess struct {
|
||||
ID gid.GID `json:"id"`
|
||||
Email string `json:"email"`
|
||||
Name string `json:"name"`
|
||||
Active bool `json:"active"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
ID gid.GID `json:"id"`
|
||||
Email string `json:"email"`
|
||||
Name string `json:"name"`
|
||||
Active bool `json:"active"`
|
||||
HasAcceptedNonDisclosureAgreement bool `json:"hasAcceptedNonDisclosureAgreement"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
}
|
||||
|
||||
func (TrustCenterAccess) IsNode() {}
|
||||
@@ -1831,6 +1842,16 @@ type UploadTaskEvidencePayload struct {
|
||||
EvidenceEdge *EvidenceEdge `json:"evidenceEdge"`
|
||||
}
|
||||
|
||||
type UploadTrustCenterNDAInput struct {
|
||||
TrustCenterID gid.GID `json:"trustCenterId"`
|
||||
FileName string `json:"fileName"`
|
||||
File graphql.Upload `json:"file"`
|
||||
}
|
||||
|
||||
type UploadTrustCenterNDAPayload struct {
|
||||
TrustCenter *TrustCenter `json:"trustCenter"`
|
||||
}
|
||||
|
||||
type UploadVendorBusinessAssociateAgreementInput struct {
|
||||
VendorID gid.GID `json:"vendorId"`
|
||||
ValidFrom *time.Time `json:"validFrom,omitempty"`
|
||||
|
||||
@@ -1145,7 +1145,7 @@ func (r *mutationResolver) DeleteOrganization(ctx context.Context, input types.D
|
||||
func (r *mutationResolver) UpdateTrustCenter(ctx context.Context, input types.UpdateTrustCenterInput) (*types.UpdateTrustCenterPayload, error) {
|
||||
prb := r.ProboService(ctx, input.TrustCenterID.TenantID())
|
||||
|
||||
trustCenter, err := prb.TrustCenters.Update(ctx, &probo.UpdateTrustCenterRequest{
|
||||
trustCenter, file, err := prb.TrustCenters.Update(ctx, &probo.UpdateTrustCenterRequest{
|
||||
ID: input.TrustCenterID,
|
||||
Active: input.Active,
|
||||
Slug: input.Slug,
|
||||
@@ -1155,7 +1155,41 @@ func (r *mutationResolver) UpdateTrustCenter(ctx context.Context, input types.Up
|
||||
}
|
||||
|
||||
return &types.UpdateTrustCenterPayload{
|
||||
TrustCenter: types.NewTrustCenter(trustCenter),
|
||||
TrustCenter: types.NewTrustCenter(trustCenter, file),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UploadTrustCenterNda is the resolver for the uploadTrustCenterNDA field.
|
||||
func (r *mutationResolver) UploadTrustCenterNda(ctx context.Context, input types.UploadTrustCenterNDAInput) (*types.UploadTrustCenterNDAPayload, error) {
|
||||
prb := r.ProboService(ctx, input.TrustCenterID.TenantID())
|
||||
|
||||
trustCenter, file, err := prb.TrustCenters.UploadNDA(ctx, &probo.UploadTrustCenterNDARequest{
|
||||
TrustCenterID: input.TrustCenterID,
|
||||
File: input.File.File,
|
||||
FileName: input.FileName,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot upload trust center NDA: %w", err)
|
||||
}
|
||||
|
||||
return &types.UploadTrustCenterNDAPayload{
|
||||
TrustCenter: types.NewTrustCenter(trustCenter, file),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// DeleteTrustCenterNda is the resolver for the deleteTrustCenterNDA field.
|
||||
func (r *mutationResolver) DeleteTrustCenterNda(ctx context.Context, input types.DeleteTrustCenterNDAInput) (*types.DeleteTrustCenterNDAPayload, error) {
|
||||
prb := r.ProboService(ctx, input.TrustCenterID.TenantID())
|
||||
|
||||
trustCenter, file, err := prb.TrustCenters.DeleteNDA(ctx, &probo.DeleteTrustCenterNDARequest{
|
||||
TrustCenterID: input.TrustCenterID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot delete trust center NDA: %w", err)
|
||||
}
|
||||
|
||||
return &types.DeleteTrustCenterNDAPayload{
|
||||
TrustCenter: types.NewTrustCenter(trustCenter, file),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -3895,12 +3929,12 @@ func (r *organizationResolver) Snapshots(ctx context.Context, obj *types.Organiz
|
||||
func (r *organizationResolver) TrustCenter(ctx context.Context, obj *types.Organization) (*types.TrustCenter, error) {
|
||||
prb := r.ProboService(ctx, obj.ID.TenantID())
|
||||
|
||||
trustCenter, err := prb.TrustCenters.GetByOrganizationID(ctx, obj.ID)
|
||||
trustCenter, file, err := prb.TrustCenters.GetByOrganizationID(ctx, obj.ID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot get trust center: %w", err)
|
||||
}
|
||||
|
||||
return types.NewTrustCenter(trustCenter), nil
|
||||
return types.NewTrustCenter(trustCenter, file), nil
|
||||
}
|
||||
|
||||
// TotalCount is the resolver for the totalCount field.
|
||||
@@ -4115,11 +4149,12 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error
|
||||
}
|
||||
return types.NewSnapshot(snapshot), nil
|
||||
case coredata.TrustCenterEntityType:
|
||||
trustCenter, err := prb.TrustCenters.Get(ctx, id)
|
||||
trustCenter, file, err := prb.TrustCenters.Get(ctx, id)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot get trust center: %w", err))
|
||||
panic(fmt.Errorf("cannot get trust center with file: %w", err))
|
||||
}
|
||||
return types.NewTrustCenter(trustCenter), nil
|
||||
|
||||
return types.NewTrustCenter(trustCenter, file), nil
|
||||
default:
|
||||
}
|
||||
|
||||
@@ -4462,6 +4497,18 @@ func (r *taskConnectionResolver) TotalCount(ctx context.Context, obj *types.Task
|
||||
panic(fmt.Errorf("unsupported resolver: %T", obj.Resolver))
|
||||
}
|
||||
|
||||
// NdaFileURL is the resolver for the ndaFileUrl field.
|
||||
func (r *trustCenterResolver) NdaFileURL(ctx context.Context, obj *types.TrustCenter) (*string, error) {
|
||||
prb := r.ProboService(ctx, obj.ID.TenantID())
|
||||
|
||||
fileURL, err := prb.TrustCenters.GenerateNDAFileURL(ctx, obj.ID, 15*time.Minute)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("failed to generate NDA file URL: %w", err))
|
||||
}
|
||||
|
||||
return fileURL, nil
|
||||
}
|
||||
|
||||
// Organization is the resolver for the organization field.
|
||||
func (r *trustCenterResolver) Organization(ctx context.Context, obj *types.TrustCenter) (*types.Organization, error) {
|
||||
prb := r.ProboService(ctx, obj.ID.TenantID())
|
||||
|
||||
@@ -31,6 +31,10 @@ type TokenAccessData struct {
|
||||
Scope string
|
||||
}
|
||||
|
||||
func (t *TokenAccessData) GetEmail() string {
|
||||
return t.Email
|
||||
}
|
||||
|
||||
type ContextAccessor interface {
|
||||
UserFromContext(ctx context.Context) *coredata.User
|
||||
TokenAccessFromContext(ctx context.Context) *TokenAccessData
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/99designs/gqlgen/graphql/handler"
|
||||
@@ -138,20 +139,29 @@ func graphqlHandler(logger *log.Logger, usrmgrSvc *usrmgr.Service, trustSvc *tru
|
||||
return WithSession(usrmgrSvc, trustSvc, authCfg, trustAuthCfg, srv.ServeHTTP)
|
||||
}
|
||||
|
||||
// TrustService returns a trust service scoped to the given tenant
|
||||
func (r *Resolver) TrustService(ctx context.Context, tenantID gid.TenantID) *trust.TenantService {
|
||||
func (r *Resolver) RootTrustService(ctx context.Context) *trust.TenantService {
|
||||
return r.trustCenterSvc.WithTenant(gid.NewTenantID())
|
||||
}
|
||||
|
||||
func (r *Resolver) PublicTrustService(ctx context.Context, tenantID gid.TenantID) *trust.TenantService {
|
||||
return r.trustCenterSvc.WithTenant(tenantID)
|
||||
}
|
||||
|
||||
// GetTenantService returns a tenant service for the given tenant ID
|
||||
func (r *Resolver) GetTenantService(ctx context.Context, tenantID gid.TenantID) *trust.TenantService {
|
||||
return r.trustCenterSvc.WithTenant(tenantID)
|
||||
func (r *Resolver) PrivateTrustService(ctx context.Context, tenantID gid.TenantID) (*trust.TenantService, error) {
|
||||
if err := auth.ValidateTenantAccess(ctx, r, userTenantContextKey, tenantID); err != nil {
|
||||
return nil, fmt.Errorf("cannot access trust center: %w", err)
|
||||
}
|
||||
|
||||
return r.trustCenterSvc.WithTenant(tenantID), nil
|
||||
}
|
||||
|
||||
func WithSession(usrmgrSvc *usrmgr.Service, trustSvc *trust.Service, authCfg console_v1.AuthConfig, trustAuthCfg TrustAuthConfig, next http.HandlerFunc) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
|
||||
ip := extractIPAddress(r)
|
||||
ctx = context.WithValue(ctx, coredata.ContextKeyIPAddress, ip)
|
||||
|
||||
if authCtx := tryTokenAuth(ctx, w, r, trustSvc, trustAuthCfg); authCtx != nil {
|
||||
next(w, r.WithContext(authCtx))
|
||||
return
|
||||
@@ -219,15 +229,14 @@ func tryTokenAuth(ctx context.Context, w http.ResponseWriter, r *http.Request, t
|
||||
tenantID := basicPayload.Data.TrustCenterID.TenantID()
|
||||
|
||||
tenantSvc := trustSvc.WithTenant(tenantID)
|
||||
payload, err := tenantSvc.TrustCenterAccesses.ValidateToken(ctx, cookie.Value)
|
||||
if err != nil {
|
||||
if err := tenantSvc.TrustCenterAccesses.ValidateToken(ctx, basicPayload.Data.TrustCenterID, basicPayload.Data.Email); err != nil {
|
||||
clearTokenCookie(w, trustAuthCfg)
|
||||
return nil
|
||||
}
|
||||
|
||||
tokenAccess := &auth.TokenAccessData{
|
||||
TrustCenterID: payload.TrustCenterID,
|
||||
Email: payload.Email,
|
||||
TrustCenterID: basicPayload.Data.TrustCenterID,
|
||||
Email: basicPayload.Data.Email,
|
||||
TenantID: tenantID,
|
||||
Scope: trustAuthCfg.Scope,
|
||||
}
|
||||
@@ -256,3 +265,21 @@ func updateSessionIfNeeded(ctx context.Context, usrmgrSvc *usrmgr.Service) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func extractIPAddress(r *http.Request) string {
|
||||
if xff := r.Header.Get("X-Forwarded-For"); xff != "" {
|
||||
if ip := strings.Split(xff, ",")[0]; ip != "" {
|
||||
return strings.TrimSpace(ip)
|
||||
}
|
||||
}
|
||||
|
||||
if xri := r.Header.Get("X-Real-IP"); xri != "" {
|
||||
return strings.TrimSpace(xri)
|
||||
}
|
||||
|
||||
if ip := strings.Split(r.RemoteAddr, ":")[0]; ip != "" {
|
||||
return ip
|
||||
}
|
||||
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
@@ -199,8 +199,11 @@ type TrustCenter implements Node {
|
||||
id: ID!
|
||||
active: Boolean!
|
||||
slug: String!
|
||||
ndaFileName: String
|
||||
ndaFileUrl: String @goField(forceResolver: true)
|
||||
organization: Organization! @goField(forceResolver: true)
|
||||
isUserAuthenticated: Boolean! @goField(forceResolver: true)
|
||||
hasAcceptedNonDisclosureAgreement: Boolean! @goField(forceResolver: true)
|
||||
|
||||
documents(
|
||||
first: Int
|
||||
@@ -246,10 +249,18 @@ input ExportDocumentPDFInput {
|
||||
documentId: ID!
|
||||
}
|
||||
|
||||
input AcceptNonDisclosureAgreementInput {
|
||||
trustCenterId: ID!
|
||||
}
|
||||
|
||||
type ExportDocumentPDFPayload {
|
||||
data: String!
|
||||
}
|
||||
|
||||
type AcceptNonDisclosureAgreementPayload{
|
||||
success: Boolean!
|
||||
}
|
||||
|
||||
type Query {
|
||||
trustCenterBySlug(slug: String!): TrustCenter @mustBeAuthenticated(role: NONE)
|
||||
}
|
||||
@@ -262,4 +273,8 @@ type Mutation {
|
||||
exportDocumentPDF(
|
||||
input: ExportDocumentPDFInput!
|
||||
): ExportDocumentPDFPayload! @mustBeAuthenticated(role: USER)
|
||||
|
||||
acceptNonDisclosureAgreement(
|
||||
input: AcceptNonDisclosureAgreementInput!
|
||||
): AcceptNonDisclosureAgreementPayload! @mustBeAuthenticated(role: USER)
|
||||
}
|
||||
|
||||
@@ -57,6 +57,10 @@ type DirectiveRoot struct {
|
||||
}
|
||||
|
||||
type ComplexityRoot struct {
|
||||
AcceptNonDisclosureAgreementPayload struct {
|
||||
Success func(childComplexity int) int
|
||||
}
|
||||
|
||||
Audit struct {
|
||||
Framework func(childComplexity int) int
|
||||
ID func(childComplexity int) int
|
||||
@@ -103,8 +107,9 @@ type ComplexityRoot struct {
|
||||
}
|
||||
|
||||
Mutation struct {
|
||||
CreateTrustCenterAccess func(childComplexity int, input types.CreateTrustCenterAccessInput) int
|
||||
ExportDocumentPDF func(childComplexity int, input types.ExportDocumentPDFInput) int
|
||||
AcceptNonDisclosureAgreement func(childComplexity int, input types.AcceptNonDisclosureAgreementInput) int
|
||||
CreateTrustCenterAccess func(childComplexity int, input types.CreateTrustCenterAccessInput) int
|
||||
ExportDocumentPDF func(childComplexity int, input types.ExportDocumentPDFInput) int
|
||||
}
|
||||
|
||||
Organization struct {
|
||||
@@ -131,14 +136,17 @@ type ComplexityRoot struct {
|
||||
}
|
||||
|
||||
TrustCenter struct {
|
||||
Active func(childComplexity int) int
|
||||
Audits func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey) int
|
||||
Documents func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey) int
|
||||
ID func(childComplexity int) int
|
||||
IsUserAuthenticated func(childComplexity int) int
|
||||
Organization func(childComplexity int) int
|
||||
Slug func(childComplexity int) int
|
||||
Vendors func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey) int
|
||||
Active func(childComplexity int) int
|
||||
Audits func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey) int
|
||||
Documents func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey) int
|
||||
HasAcceptedNonDisclosureAgreement func(childComplexity int) int
|
||||
ID func(childComplexity int) int
|
||||
IsUserAuthenticated func(childComplexity int) int
|
||||
NdaFileName func(childComplexity int) int
|
||||
NdaFileURL func(childComplexity int) int
|
||||
Organization func(childComplexity int) int
|
||||
Slug func(childComplexity int) int
|
||||
Vendors func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey) int
|
||||
}
|
||||
|
||||
TrustCenterAccess struct {
|
||||
@@ -175,6 +183,7 @@ type AuditResolver interface {
|
||||
type MutationResolver interface {
|
||||
CreateTrustCenterAccess(ctx context.Context, input types.CreateTrustCenterAccessInput) (*types.CreateTrustCenterAccessPayload, error)
|
||||
ExportDocumentPDF(ctx context.Context, input types.ExportDocumentPDFInput) (*types.ExportDocumentPDFPayload, error)
|
||||
AcceptNonDisclosureAgreement(ctx context.Context, input types.AcceptNonDisclosureAgreementInput) (*types.AcceptNonDisclosureAgreementPayload, error)
|
||||
}
|
||||
type OrganizationResolver interface {
|
||||
LogoURL(ctx context.Context, obj *types.Organization) (*string, error)
|
||||
@@ -186,8 +195,10 @@ type ReportResolver interface {
|
||||
DownloadURL(ctx context.Context, obj *types.Report) (*string, error)
|
||||
}
|
||||
type TrustCenterResolver interface {
|
||||
NdaFileURL(ctx context.Context, obj *types.TrustCenter) (*string, error)
|
||||
Organization(ctx context.Context, obj *types.TrustCenter) (*types.Organization, error)
|
||||
IsUserAuthenticated(ctx context.Context, obj *types.TrustCenter) (bool, error)
|
||||
HasAcceptedNonDisclosureAgreement(ctx context.Context, obj *types.TrustCenter) (bool, error)
|
||||
Documents(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.DocumentConnection, error)
|
||||
Audits(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.AuditConnection, error)
|
||||
Vendors(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.VendorConnection, error)
|
||||
@@ -212,6 +223,13 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
|
||||
_ = ec
|
||||
switch typeName + "." + field {
|
||||
|
||||
case "AcceptNonDisclosureAgreementPayload.success":
|
||||
if e.complexity.AcceptNonDisclosureAgreementPayload.Success == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.AcceptNonDisclosureAgreementPayload.Success(childComplexity), true
|
||||
|
||||
case "Audit.framework":
|
||||
if e.complexity.Audit.Framework == nil {
|
||||
break
|
||||
@@ -338,6 +356,18 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
|
||||
|
||||
return e.complexity.Framework.Name(childComplexity), true
|
||||
|
||||
case "Mutation.acceptNonDisclosureAgreement":
|
||||
if e.complexity.Mutation.AcceptNonDisclosureAgreement == nil {
|
||||
break
|
||||
}
|
||||
|
||||
args, err := ec.field_Mutation_acceptNonDisclosureAgreement_args(ctx, rawArgs)
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
return e.complexity.Mutation.AcceptNonDisclosureAgreement(childComplexity, args["input"].(types.AcceptNonDisclosureAgreementInput)), true
|
||||
|
||||
case "Mutation.createTrustCenterAccess":
|
||||
if e.complexity.Mutation.CreateTrustCenterAccess == nil {
|
||||
break
|
||||
@@ -475,6 +505,13 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
|
||||
|
||||
return e.complexity.TrustCenter.Documents(childComplexity, args["first"].(*int), args["after"].(*page.CursorKey), args["last"].(*int), args["before"].(*page.CursorKey)), true
|
||||
|
||||
case "TrustCenter.hasAcceptedNonDisclosureAgreement":
|
||||
if e.complexity.TrustCenter.HasAcceptedNonDisclosureAgreement == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.TrustCenter.HasAcceptedNonDisclosureAgreement(childComplexity), true
|
||||
|
||||
case "TrustCenter.id":
|
||||
if e.complexity.TrustCenter.ID == nil {
|
||||
break
|
||||
@@ -489,6 +526,20 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
|
||||
|
||||
return e.complexity.TrustCenter.IsUserAuthenticated(childComplexity), true
|
||||
|
||||
case "TrustCenter.ndaFileName":
|
||||
if e.complexity.TrustCenter.NdaFileName == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.TrustCenter.NdaFileName(childComplexity), true
|
||||
|
||||
case "TrustCenter.ndaFileUrl":
|
||||
if e.complexity.TrustCenter.NdaFileURL == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.TrustCenter.NdaFileURL(childComplexity), true
|
||||
|
||||
case "TrustCenter.organization":
|
||||
if e.complexity.TrustCenter.Organization == nil {
|
||||
break
|
||||
@@ -621,6 +672,7 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler {
|
||||
opCtx := graphql.GetOperationContext(ctx)
|
||||
ec := executionContext{opCtx, e, 0, 0, make(chan graphql.DeferredResult)}
|
||||
inputUnmarshalMap := graphql.BuildUnmarshalerMap(
|
||||
ec.unmarshalInputAcceptNonDisclosureAgreementInput,
|
||||
ec.unmarshalInputCreateTrustCenterAccessInput,
|
||||
ec.unmarshalInputExportDocumentPDFInput,
|
||||
)
|
||||
@@ -921,8 +973,11 @@ type TrustCenter implements Node {
|
||||
id: ID!
|
||||
active: Boolean!
|
||||
slug: String!
|
||||
ndaFileName: String
|
||||
ndaFileUrl: String @goField(forceResolver: true)
|
||||
organization: Organization! @goField(forceResolver: true)
|
||||
isUserAuthenticated: Boolean! @goField(forceResolver: true)
|
||||
hasAcceptedNonDisclosureAgreement: Boolean! @goField(forceResolver: true)
|
||||
|
||||
documents(
|
||||
first: Int
|
||||
@@ -968,10 +1023,18 @@ input ExportDocumentPDFInput {
|
||||
documentId: ID!
|
||||
}
|
||||
|
||||
input AcceptNonDisclosureAgreementInput {
|
||||
trustCenterId: ID!
|
||||
}
|
||||
|
||||
type ExportDocumentPDFPayload {
|
||||
data: String!
|
||||
}
|
||||
|
||||
type AcceptNonDisclosureAgreementPayload{
|
||||
success: Boolean!
|
||||
}
|
||||
|
||||
type Query {
|
||||
trustCenterBySlug(slug: String!): TrustCenter @mustBeAuthenticated(role: NONE)
|
||||
}
|
||||
@@ -984,6 +1047,10 @@ type Mutation {
|
||||
exportDocumentPDF(
|
||||
input: ExportDocumentPDFInput!
|
||||
): ExportDocumentPDFPayload! @mustBeAuthenticated(role: USER)
|
||||
|
||||
acceptNonDisclosureAgreement(
|
||||
input: AcceptNonDisclosureAgreementInput!
|
||||
): AcceptNonDisclosureAgreementPayload! @mustBeAuthenticated(role: USER)
|
||||
}
|
||||
`, BuiltIn: false},
|
||||
}
|
||||
@@ -1021,6 +1088,29 @@ func (ec *executionContext) dir_mustBeAuthenticated_argsRole(
|
||||
return zeroVal, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) field_Mutation_acceptNonDisclosureAgreement_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
|
||||
var err error
|
||||
args := map[string]any{}
|
||||
arg0, err := ec.field_Mutation_acceptNonDisclosureAgreement_argsInput(ctx, rawArgs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
args["input"] = arg0
|
||||
return args, nil
|
||||
}
|
||||
func (ec *executionContext) field_Mutation_acceptNonDisclosureAgreement_argsInput(
|
||||
ctx context.Context,
|
||||
rawArgs map[string]any,
|
||||
) (types.AcceptNonDisclosureAgreementInput, error) {
|
||||
ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("input"))
|
||||
if tmp, ok := rawArgs["input"]; ok {
|
||||
return ec.unmarshalNAcceptNonDisclosureAgreementInput2githubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐAcceptNonDisclosureAgreementInput(ctx, tmp)
|
||||
}
|
||||
|
||||
var zeroVal types.AcceptNonDisclosureAgreementInput
|
||||
return zeroVal, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) field_Mutation_createTrustCenterAccess_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
|
||||
var err error
|
||||
args := map[string]any{}
|
||||
@@ -1444,6 +1534,50 @@ func (ec *executionContext) field___Type_fields_argsIncludeDeprecated(
|
||||
|
||||
// region **************************** field.gotpl *****************************
|
||||
|
||||
func (ec *executionContext) _AcceptNonDisclosureAgreementPayload_success(ctx context.Context, field graphql.CollectedField, obj *types.AcceptNonDisclosureAgreementPayload) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_AcceptNonDisclosureAgreementPayload_success(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.Success, 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.(bool)
|
||||
fc.Result = res
|
||||
return ec.marshalNBoolean2bool(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_AcceptNonDisclosureAgreementPayload_success(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "AcceptNonDisclosureAgreementPayload",
|
||||
Field: field,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
return nil, errors.New("field of type Boolean does not have child fields")
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Audit_id(ctx context.Context, field graphql.CollectedField, obj *types.Audit) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_Audit_id(ctx, field)
|
||||
if err != nil {
|
||||
@@ -2479,6 +2613,92 @@ func (ec *executionContext) fieldContext_Mutation_exportDocumentPDF(ctx context.
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Mutation_acceptNonDisclosureAgreement(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_Mutation_acceptNonDisclosureAgreement(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) {
|
||||
directive0 := func(rctx context.Context) (any, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return ec.resolvers.Mutation().AcceptNonDisclosureAgreement(rctx, fc.Args["input"].(types.AcceptNonDisclosureAgreementInput))
|
||||
}
|
||||
|
||||
directive1 := func(ctx context.Context) (any, error) {
|
||||
role, err := ec.unmarshalORole2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐRole(ctx, "USER")
|
||||
if err != nil {
|
||||
var zeroVal *types.AcceptNonDisclosureAgreementPayload
|
||||
return zeroVal, err
|
||||
}
|
||||
if ec.directives.MustBeAuthenticated == nil {
|
||||
var zeroVal *types.AcceptNonDisclosureAgreementPayload
|
||||
return zeroVal, errors.New("directive mustBeAuthenticated is not implemented")
|
||||
}
|
||||
return ec.directives.MustBeAuthenticated(ctx, nil, directive0, role)
|
||||
}
|
||||
|
||||
tmp, err := directive1(rctx)
|
||||
if err != nil {
|
||||
return nil, graphql.ErrorOnPath(ctx, err)
|
||||
}
|
||||
if tmp == nil {
|
||||
return nil, nil
|
||||
}
|
||||
if data, ok := tmp.(*types.AcceptNonDisclosureAgreementPayload); ok {
|
||||
return data, nil
|
||||
}
|
||||
return nil, fmt.Errorf(`unexpected type %T from directive, should be *github.com/getprobo/probo/pkg/server/api/trust/v1/types.AcceptNonDisclosureAgreementPayload`, tmp)
|
||||
})
|
||||
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.AcceptNonDisclosureAgreementPayload)
|
||||
fc.Result = res
|
||||
return ec.marshalNAcceptNonDisclosureAgreementPayload2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐAcceptNonDisclosureAgreementPayload(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_Mutation_acceptNonDisclosureAgreement(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "Mutation",
|
||||
Field: field,
|
||||
IsMethod: true,
|
||||
IsResolver: true,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
switch field.Name {
|
||||
case "success":
|
||||
return ec.fieldContext_AcceptNonDisclosureAgreementPayload_success(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type AcceptNonDisclosureAgreementPayload", field.Name)
|
||||
},
|
||||
}
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
err = ec.Recover(ctx, r)
|
||||
ec.Error(ctx, err)
|
||||
}
|
||||
}()
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
if fc.Args, err = ec.field_Mutation_acceptNonDisclosureAgreement_args(ctx, field.ArgumentMap(ec.Variables)); err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return fc, err
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Organization_id(ctx context.Context, field graphql.CollectedField, obj *types.Organization) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_Organization_id(ctx, field)
|
||||
if err != nil {
|
||||
@@ -2847,10 +3067,16 @@ func (ec *executionContext) fieldContext_Query_trustCenterBySlug(ctx context.Con
|
||||
return ec.fieldContext_TrustCenter_active(ctx, field)
|
||||
case "slug":
|
||||
return ec.fieldContext_TrustCenter_slug(ctx, field)
|
||||
case "ndaFileName":
|
||||
return ec.fieldContext_TrustCenter_ndaFileName(ctx, field)
|
||||
case "ndaFileUrl":
|
||||
return ec.fieldContext_TrustCenter_ndaFileUrl(ctx, field)
|
||||
case "organization":
|
||||
return ec.fieldContext_TrustCenter_organization(ctx, field)
|
||||
case "isUserAuthenticated":
|
||||
return ec.fieldContext_TrustCenter_isUserAuthenticated(ctx, field)
|
||||
case "hasAcceptedNonDisclosureAgreement":
|
||||
return ec.fieldContext_TrustCenter_hasAcceptedNonDisclosureAgreement(ctx, field)
|
||||
case "documents":
|
||||
return ec.fieldContext_TrustCenter_documents(ctx, field)
|
||||
case "audits":
|
||||
@@ -3294,6 +3520,88 @@ func (ec *executionContext) fieldContext_TrustCenter_slug(_ context.Context, fie
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _TrustCenter_ndaFileName(ctx context.Context, field graphql.CollectedField, obj *types.TrustCenter) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_TrustCenter_ndaFileName(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.NdaFileName, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*string)
|
||||
fc.Result = res
|
||||
return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_TrustCenter_ndaFileName(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "TrustCenter",
|
||||
Field: field,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
return nil, errors.New("field of type String does not have child fields")
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _TrustCenter_ndaFileUrl(ctx context.Context, field graphql.CollectedField, obj *types.TrustCenter) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_TrustCenter_ndaFileUrl(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.TrustCenter().NdaFileURL(rctx, obj)
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*string)
|
||||
fc.Result = res
|
||||
return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_TrustCenter_ndaFileUrl(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "TrustCenter",
|
||||
Field: field,
|
||||
IsMethod: true,
|
||||
IsResolver: true,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
return nil, errors.New("field of type String does not have child fields")
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _TrustCenter_organization(ctx context.Context, field graphql.CollectedField, obj *types.TrustCenter) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_TrustCenter_organization(ctx, field)
|
||||
if err != nil {
|
||||
@@ -3390,6 +3698,50 @@ func (ec *executionContext) fieldContext_TrustCenter_isUserAuthenticated(_ conte
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _TrustCenter_hasAcceptedNonDisclosureAgreement(ctx context.Context, field graphql.CollectedField, obj *types.TrustCenter) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_TrustCenter_hasAcceptedNonDisclosureAgreement(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.TrustCenter().HasAcceptedNonDisclosureAgreement(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.(bool)
|
||||
fc.Result = res
|
||||
return ec.marshalNBoolean2bool(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_TrustCenter_hasAcceptedNonDisclosureAgreement(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "TrustCenter",
|
||||
Field: field,
|
||||
IsMethod: true,
|
||||
IsResolver: true,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
return nil, errors.New("field of type Boolean does not have child fields")
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _TrustCenter_documents(ctx context.Context, field graphql.CollectedField, obj *types.TrustCenter) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_TrustCenter_documents(ctx, field)
|
||||
if err != nil {
|
||||
@@ -6162,6 +6514,33 @@ func (ec *executionContext) fieldContext___Type_isOneOf(_ context.Context, field
|
||||
|
||||
// region **************************** input.gotpl *****************************
|
||||
|
||||
func (ec *executionContext) unmarshalInputAcceptNonDisclosureAgreementInput(ctx context.Context, obj any) (types.AcceptNonDisclosureAgreementInput, error) {
|
||||
var it types.AcceptNonDisclosureAgreementInput
|
||||
asMap := map[string]any{}
|
||||
for k, v := range obj.(map[string]any) {
|
||||
asMap[k] = v
|
||||
}
|
||||
|
||||
fieldsInOrder := [...]string{"trustCenterId"}
|
||||
for _, k := range fieldsInOrder {
|
||||
v, ok := asMap[k]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
switch k {
|
||||
case "trustCenterId":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("trustCenterId"))
|
||||
data, err := ec.unmarshalNID2githubᚗcomᚋgetproboᚋproboᚋpkgᚋgidᚐGID(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
it.TrustCenterID = data
|
||||
}
|
||||
}
|
||||
|
||||
return it, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalInputCreateTrustCenterAccessInput(ctx context.Context, obj any) (types.CreateTrustCenterAccessInput, error) {
|
||||
var it types.CreateTrustCenterAccessInput
|
||||
asMap := map[string]any{}
|
||||
@@ -6303,6 +6682,45 @@ func (ec *executionContext) _Node(ctx context.Context, sel ast.SelectionSet, obj
|
||||
|
||||
// region **************************** object.gotpl ****************************
|
||||
|
||||
var acceptNonDisclosureAgreementPayloadImplementors = []string{"AcceptNonDisclosureAgreementPayload"}
|
||||
|
||||
func (ec *executionContext) _AcceptNonDisclosureAgreementPayload(ctx context.Context, sel ast.SelectionSet, obj *types.AcceptNonDisclosureAgreementPayload) graphql.Marshaler {
|
||||
fields := graphql.CollectFields(ec.OperationContext, sel, acceptNonDisclosureAgreementPayloadImplementors)
|
||||
|
||||
out := graphql.NewFieldSet(fields)
|
||||
deferred := make(map[string]*graphql.FieldSet)
|
||||
for i, field := range fields {
|
||||
switch field.Name {
|
||||
case "__typename":
|
||||
out.Values[i] = graphql.MarshalString("AcceptNonDisclosureAgreementPayload")
|
||||
case "success":
|
||||
out.Values[i] = ec._AcceptNonDisclosureAgreementPayload_success(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
out.Invalids++
|
||||
}
|
||||
default:
|
||||
panic("unknown field " + strconv.Quote(field.Name))
|
||||
}
|
||||
}
|
||||
out.Dispatch(ctx)
|
||||
if out.Invalids > 0 {
|
||||
return graphql.Null
|
||||
}
|
||||
|
||||
atomic.AddInt32(&ec.deferred, int32(len(deferred)))
|
||||
|
||||
for label, dfs := range deferred {
|
||||
ec.processDeferredGroup(graphql.DeferredGroup{
|
||||
Label: label,
|
||||
Path: graphql.GetPath(ctx),
|
||||
FieldSet: dfs,
|
||||
Context: ctx,
|
||||
})
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
var auditImplementors = []string{"Audit", "Node"}
|
||||
|
||||
func (ec *executionContext) _Audit(ctx context.Context, sel ast.SelectionSet, obj *types.Audit) graphql.Marshaler {
|
||||
@@ -6791,6 +7209,13 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet)
|
||||
if out.Values[i] == graphql.Null {
|
||||
out.Invalids++
|
||||
}
|
||||
case "acceptNonDisclosureAgreement":
|
||||
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
|
||||
return ec._Mutation_acceptNonDisclosureAgreement(ctx, field)
|
||||
})
|
||||
if out.Values[i] == graphql.Null {
|
||||
out.Invalids++
|
||||
}
|
||||
default:
|
||||
panic("unknown field " + strconv.Quote(field.Name))
|
||||
}
|
||||
@@ -7111,6 +7536,41 @@ func (ec *executionContext) _TrustCenter(ctx context.Context, sel ast.SelectionS
|
||||
if out.Values[i] == graphql.Null {
|
||||
atomic.AddUint32(&out.Invalids, 1)
|
||||
}
|
||||
case "ndaFileName":
|
||||
out.Values[i] = ec._TrustCenter_ndaFileName(ctx, field, obj)
|
||||
case "ndaFileUrl":
|
||||
field := field
|
||||
|
||||
innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
}
|
||||
}()
|
||||
res = ec._TrustCenter_ndaFileUrl(ctx, field, obj)
|
||||
return res
|
||||
}
|
||||
|
||||
if field.Deferrable != nil {
|
||||
dfs, ok := deferred[field.Deferrable.Label]
|
||||
di := 0
|
||||
if ok {
|
||||
dfs.AddField(field)
|
||||
di = len(dfs.Values) - 1
|
||||
} else {
|
||||
dfs = graphql.NewFieldSet([]graphql.CollectedField{field})
|
||||
deferred[field.Deferrable.Label] = dfs
|
||||
}
|
||||
dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler {
|
||||
return innerFunc(ctx, dfs)
|
||||
})
|
||||
|
||||
// don't run the out.Concurrently() call below
|
||||
out.Values[i] = graphql.Null
|
||||
continue
|
||||
}
|
||||
|
||||
out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) })
|
||||
case "organization":
|
||||
field := field
|
||||
|
||||
@@ -7182,6 +7642,42 @@ func (ec *executionContext) _TrustCenter(ctx context.Context, sel ast.SelectionS
|
||||
continue
|
||||
}
|
||||
|
||||
out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) })
|
||||
case "hasAcceptedNonDisclosureAgreement":
|
||||
field := field
|
||||
|
||||
innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
}
|
||||
}()
|
||||
res = ec._TrustCenter_hasAcceptedNonDisclosureAgreement(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 "documents":
|
||||
field := field
|
||||
@@ -7849,6 +8345,25 @@ func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, o
|
||||
|
||||
// region ***************************** type.gotpl *****************************
|
||||
|
||||
func (ec *executionContext) unmarshalNAcceptNonDisclosureAgreementInput2githubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐAcceptNonDisclosureAgreementInput(ctx context.Context, v any) (types.AcceptNonDisclosureAgreementInput, error) {
|
||||
res, err := ec.unmarshalInputAcceptNonDisclosureAgreementInput(ctx, v)
|
||||
return res, graphql.ErrorOnPath(ctx, err)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNAcceptNonDisclosureAgreementPayload2githubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐAcceptNonDisclosureAgreementPayload(ctx context.Context, sel ast.SelectionSet, v types.AcceptNonDisclosureAgreementPayload) graphql.Marshaler {
|
||||
return ec._AcceptNonDisclosureAgreementPayload(ctx, sel, &v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNAcceptNonDisclosureAgreementPayload2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐAcceptNonDisclosureAgreementPayload(ctx context.Context, sel ast.SelectionSet, v *types.AcceptNonDisclosureAgreementPayload) graphql.Marshaler {
|
||||
if v == nil {
|
||||
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
||||
ec.Errorf(ctx, "the requested element is null which the schema does not allow")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
return ec._AcceptNonDisclosureAgreementPayload(ctx, sel, v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNAudit2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐAudit(ctx context.Context, sel ast.SelectionSet, v *types.Audit) graphql.Marshaler {
|
||||
if v == nil {
|
||||
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
||||
|
||||
@@ -109,15 +109,12 @@ func validateTrustCenterAccessToken(ctx context.Context, trustSvc *trust.Service
|
||||
return nil, fmt.Errorf("cannot validate trust center access token: %w", err)
|
||||
}
|
||||
|
||||
tenantID := token.Data.TrustCenterID.TenantID()
|
||||
tenantSvc := trustSvc.WithTenant(tenantID)
|
||||
|
||||
accessData, err := tenantSvc.TrustCenterAccesses.ValidateToken(ctx, tokenString)
|
||||
if err != nil {
|
||||
tenantSvc := trustSvc.WithTenant(token.Data.TrustCenterID.TenantID())
|
||||
if err := tenantSvc.TrustCenterAccesses.ValidateToken(ctx, token.Data.TrustCenterID, token.Data.Email); err != nil {
|
||||
return nil, fmt.Errorf("cannot validate trust center access token: %w", err)
|
||||
}
|
||||
|
||||
return accessData, nil
|
||||
return &token.Data, nil
|
||||
}
|
||||
|
||||
func trustCenterLogoutHandler(authCfg console_v1.AuthConfig, trustAuthCfg TrustAuthConfig) http.HandlerFunc {
|
||||
|
||||
@@ -18,10 +18,16 @@ import (
|
||||
"github.com/getprobo/probo/pkg/coredata"
|
||||
)
|
||||
|
||||
func NewTrustCenter(tc *coredata.TrustCenter) *TrustCenter {
|
||||
func NewTrustCenter(tc *coredata.TrustCenter, file *coredata.File) *TrustCenter {
|
||||
var ndaFileName *string
|
||||
if file != nil {
|
||||
ndaFileName = &file.FileName
|
||||
}
|
||||
|
||||
return &TrustCenter{
|
||||
ID: tc.ID,
|
||||
Active: tc.Active,
|
||||
Slug: tc.Slug,
|
||||
ID: tc.ID,
|
||||
Active: tc.Active,
|
||||
Slug: tc.Slug,
|
||||
NdaFileName: ndaFileName,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,14 @@ type Node interface {
|
||||
GetID() gid.GID
|
||||
}
|
||||
|
||||
type AcceptNonDisclosureAgreementInput struct {
|
||||
TrustCenterID gid.GID `json:"trustCenterId"`
|
||||
}
|
||||
|
||||
type AcceptNonDisclosureAgreementPayload struct {
|
||||
Success bool `json:"success"`
|
||||
}
|
||||
|
||||
type Audit struct {
|
||||
ID gid.GID `json:"id"`
|
||||
Framework *Framework `json:"framework"`
|
||||
@@ -115,14 +123,17 @@ func (Report) IsNode() {}
|
||||
func (this Report) GetID() gid.GID { return this.ID }
|
||||
|
||||
type TrustCenter struct {
|
||||
ID gid.GID `json:"id"`
|
||||
Active bool `json:"active"`
|
||||
Slug string `json:"slug"`
|
||||
Organization *Organization `json:"organization"`
|
||||
IsUserAuthenticated bool `json:"isUserAuthenticated"`
|
||||
Documents *DocumentConnection `json:"documents"`
|
||||
Audits *AuditConnection `json:"audits"`
|
||||
Vendors *VendorConnection `json:"vendors"`
|
||||
ID gid.GID `json:"id"`
|
||||
Active bool `json:"active"`
|
||||
Slug string `json:"slug"`
|
||||
NdaFileName *string `json:"ndaFileName,omitempty"`
|
||||
NdaFileURL *string `json:"ndaFileUrl,omitempty"`
|
||||
Organization *Organization `json:"organization"`
|
||||
IsUserAuthenticated bool `json:"isUserAuthenticated"`
|
||||
HasAcceptedNonDisclosureAgreement bool `json:"hasAcceptedNonDisclosureAgreement"`
|
||||
Documents *DocumentConnection `json:"documents"`
|
||||
Audits *AuditConnection `json:"audits"`
|
||||
Vendors *VendorConnection `json:"vendors"`
|
||||
}
|
||||
|
||||
func (TrustCenter) IsNode() {}
|
||||
|
||||
@@ -11,9 +11,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/getprobo/probo/pkg/coredata"
|
||||
"github.com/getprobo/probo/pkg/gid"
|
||||
"github.com/getprobo/probo/pkg/page"
|
||||
"github.com/getprobo/probo/pkg/server/api/trust/v1/auth"
|
||||
"github.com/getprobo/probo/pkg/server/api/trust/v1/schema"
|
||||
"github.com/getprobo/probo/pkg/server/api/trust/v1/types"
|
||||
"github.com/getprobo/probo/pkg/trust"
|
||||
@@ -21,14 +19,14 @@ import (
|
||||
|
||||
// Framework is the resolver for the framework field.
|
||||
func (r *auditResolver) Framework(ctx context.Context, obj *types.Audit) (*types.Framework, error) {
|
||||
trust := r.TrustService(ctx, obj.ID.TenantID())
|
||||
publicTrustService := r.PublicTrustService(ctx, obj.ID.TenantID())
|
||||
|
||||
audit, err := trust.Audits.Get(ctx, obj.ID)
|
||||
audit, err := publicTrustService.Audits.Get(ctx, obj.ID)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot load audit: %w", err))
|
||||
}
|
||||
|
||||
framework, err := trust.Frameworks.Get(ctx, audit.FrameworkID)
|
||||
framework, err := publicTrustService.Frameworks.Get(ctx, audit.FrameworkID)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot load framework: %w", err))
|
||||
}
|
||||
@@ -38,9 +36,9 @@ func (r *auditResolver) Framework(ctx context.Context, obj *types.Audit) (*types
|
||||
|
||||
// Report is the resolver for the report field.
|
||||
func (r *auditResolver) Report(ctx context.Context, obj *types.Audit) (*types.Report, error) {
|
||||
trust := r.TrustService(ctx, obj.ID.TenantID())
|
||||
publicTrustService := r.PublicTrustService(ctx, obj.ID.TenantID())
|
||||
|
||||
audit, err := trust.Audits.Get(ctx, obj.ID)
|
||||
audit, err := publicTrustService.Audits.Get(ctx, obj.ID)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot load audit: %w", err))
|
||||
}
|
||||
@@ -49,7 +47,7 @@ func (r *auditResolver) Report(ctx context.Context, obj *types.Audit) (*types.Re
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
report, err := trust.Reports.Get(ctx, *audit.ReportID)
|
||||
report, err := publicTrustService.Reports.Get(ctx, *audit.ReportID)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot load report: %w", err))
|
||||
}
|
||||
@@ -59,9 +57,9 @@ func (r *auditResolver) Report(ctx context.Context, obj *types.Audit) (*types.Re
|
||||
|
||||
// CreateTrustCenterAccess is the resolver for the createTrustCenterAccess field.
|
||||
func (r *mutationResolver) CreateTrustCenterAccess(ctx context.Context, input types.CreateTrustCenterAccessInput) (*types.CreateTrustCenterAccessPayload, error) {
|
||||
trustSvc := r.trustCenterSvc.WithTenant(input.TrustCenterID.TenantID())
|
||||
publicTrustService := r.PublicTrustService(ctx, input.TrustCenterID.TenantID())
|
||||
|
||||
access, err := trustSvc.TrustCenterAccesses.Create(ctx, &trust.CreateTrustCenterAccessRequest{
|
||||
access, err := publicTrustService.TrustCenterAccesses.Create(ctx, &trust.CreateTrustCenterAccessRequest{
|
||||
TrustCenterID: input.TrustCenterID,
|
||||
Email: input.Email,
|
||||
Name: input.Name,
|
||||
@@ -83,34 +81,72 @@ func (r *mutationResolver) CreateTrustCenterAccess(ctx context.Context, input ty
|
||||
|
||||
// ExportDocumentPDF is the resolver for the exportDocumentPDF field.
|
||||
func (r *mutationResolver) ExportDocumentPDF(ctx context.Context, input types.ExportDocumentPDFInput) (*types.ExportDocumentPDFPayload, error) {
|
||||
if err := auth.ValidateTenantAccess(ctx, r, userTenantContextKey, input.DocumentID.TenantID()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
trust := r.trustCenterSvc.WithTenant(input.DocumentID.TenantID())
|
||||
|
||||
pdf, err := trust.Documents.ExportPDF(ctx, input.DocumentID)
|
||||
privateTrustService, err := r.PrivateTrustService(ctx, input.DocumentID.TenantID())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot export document PDF: %w", err)
|
||||
}
|
||||
|
||||
hasAcceptedNDA := false
|
||||
userData := UserFromContext(ctx)
|
||||
if userData != nil {
|
||||
hasAcceptedNDA = true
|
||||
}
|
||||
|
||||
tokenData := TokenAccessFromContext(ctx)
|
||||
if tokenData != nil {
|
||||
tokenData := TokenAccessFromContext(ctx)
|
||||
hasAcceptedNDA, err = privateTrustService.TrustCenterAccesses.HasAcceptedNonDisclosureAgreement(ctx, tokenData.TrustCenterID, tokenData.GetEmail())
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot check if user has accepted NDA: %w", err))
|
||||
}
|
||||
}
|
||||
|
||||
if !hasAcceptedNDA {
|
||||
return nil, fmt.Errorf("user has not accepted NDA")
|
||||
}
|
||||
|
||||
pdf, err := privateTrustService.Documents.ExportPDF(ctx, input.DocumentID)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot export document PDF: %w", err))
|
||||
}
|
||||
|
||||
return &types.ExportDocumentPDFPayload{
|
||||
Data: fmt.Sprintf("data:application/pdf;base64,%s", base64.StdEncoding.EncodeToString(pdf)),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// AcceptNonDisclosureAgreement is the resolver for the acceptNonDisclosureAgreement field.
|
||||
func (r *mutationResolver) AcceptNonDisclosureAgreement(ctx context.Context, input types.AcceptNonDisclosureAgreementInput) (*types.AcceptNonDisclosureAgreementPayload, error) {
|
||||
privateTrustService, err := r.PrivateTrustService(ctx, input.TrustCenterID.TenantID())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot accept NDA: %w", err)
|
||||
}
|
||||
|
||||
tokenData := TokenAccessFromContext(ctx)
|
||||
if tokenData == nil {
|
||||
return nil, fmt.Errorf("token not found")
|
||||
}
|
||||
|
||||
err = privateTrustService.TrustCenterAccesses.AcceptNonDisclosureAgreement(ctx, input.TrustCenterID, tokenData.GetEmail())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot accept NDA: %w", err)
|
||||
}
|
||||
|
||||
return &types.AcceptNonDisclosureAgreementPayload{Success: true}, nil
|
||||
}
|
||||
|
||||
// LogoURL is the resolver for the logoUrl field.
|
||||
func (r *organizationResolver) LogoURL(ctx context.Context, obj *types.Organization) (*string, error) {
|
||||
trust := r.TrustService(ctx, obj.ID.TenantID())
|
||||
publicTrustService := r.PublicTrustService(ctx, obj.ID.TenantID())
|
||||
|
||||
return trust.Organizations.GenerateLogoURL(ctx, obj.ID, 1*time.Hour)
|
||||
return publicTrustService.Organizations.GenerateLogoURL(ctx, obj.ID, 1*time.Hour)
|
||||
}
|
||||
|
||||
// TrustCenterBySlug is the resolver for the trustCenterBySlug field.
|
||||
func (r *queryResolver) TrustCenterBySlug(ctx context.Context, slug string) (*types.TrustCenter, error) {
|
||||
publicTrust := r.trustCenterSvc.WithTenant(gid.NewTenantID())
|
||||
rootTrustService := r.RootTrustService(ctx)
|
||||
|
||||
trustCenter, err := publicTrust.TrustCenters.GetBySlug(ctx, slug)
|
||||
trustCenter, err := rootTrustService.TrustCenters.GetBySlug(ctx, slug)
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -119,28 +155,48 @@ func (r *queryResolver) TrustCenterBySlug(ctx context.Context, slug string) (*ty
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
result := types.NewTrustCenter(trustCenter)
|
||||
publicTrustService := r.PublicTrustService(ctx, trustCenter.TenantID)
|
||||
trustCenter, file, err := publicTrustService.TrustCenters.Get(ctx, trustCenter.ID)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot get trust center: %w", err))
|
||||
}
|
||||
|
||||
orgTrust := r.trustCenterSvc.WithTenant(trustCenter.TenantID)
|
||||
org, err := orgTrust.Organizations.Get(ctx, trustCenter.OrganizationID)
|
||||
org, err := publicTrustService.Organizations.Get(ctx, trustCenter.OrganizationID)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot get organization: %w", err))
|
||||
}
|
||||
response := types.NewTrustCenter(trustCenter, file)
|
||||
response.Organization = types.NewOrganization(org)
|
||||
|
||||
result.Organization = types.NewOrganization(org)
|
||||
|
||||
return result, nil
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// DownloadURL is the resolver for the downloadUrl field.
|
||||
func (r *reportResolver) DownloadURL(ctx context.Context, obj *types.Report) (*string, error) {
|
||||
if err := auth.ValidateTenantAccess(ctx, r, userTenantContextKey, obj.ID.TenantID()); err != nil {
|
||||
return nil, err
|
||||
privateTrustService, err := r.PrivateTrustService(ctx, obj.ID.TenantID())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot generate download URL: %w", err)
|
||||
}
|
||||
|
||||
trust := r.TrustService(ctx, obj.ID.TenantID())
|
||||
hasAcceptedNDA := false
|
||||
userData := UserFromContext(ctx)
|
||||
if userData != nil {
|
||||
hasAcceptedNDA = true
|
||||
}
|
||||
|
||||
url, err := trust.Reports.GenerateDownloadURL(ctx, obj.ID, r.trustAuthCfg.ReportURLDuration)
|
||||
tokenData := TokenAccessFromContext(ctx)
|
||||
if tokenData != nil {
|
||||
hasAcceptedNDA, err = privateTrustService.TrustCenterAccesses.HasAcceptedNonDisclosureAgreement(ctx, tokenData.TrustCenterID, tokenData.GetEmail())
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot check if user has accepted NDA: %w", err))
|
||||
}
|
||||
}
|
||||
|
||||
if !hasAcceptedNDA {
|
||||
return nil, fmt.Errorf("user has not accepted NDA")
|
||||
}
|
||||
|
||||
url, err := privateTrustService.Reports.GenerateDownloadURL(ctx, obj.ID, r.trustAuthCfg.ReportURLDuration)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot generate download URL: %w", err))
|
||||
}
|
||||
@@ -148,6 +204,21 @@ func (r *reportResolver) DownloadURL(ctx context.Context, obj *types.Report) (*s
|
||||
return url, nil
|
||||
}
|
||||
|
||||
// NdaFileURL is the resolver for the ndaFileUrl field.
|
||||
func (r *trustCenterResolver) NdaFileURL(ctx context.Context, obj *types.TrustCenter) (*string, error) {
|
||||
privateTrustService, err := r.PrivateTrustService(ctx, obj.ID.TenantID())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get private trust service: %w", err)
|
||||
}
|
||||
|
||||
fileURL, err := privateTrustService.TrustCenters.GenerateNDAFileURL(ctx, obj.ID, 15*time.Minute)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to generate NDA file URL: %w", err)
|
||||
}
|
||||
|
||||
return &fileURL, nil
|
||||
}
|
||||
|
||||
// Organization is the resolver for the organization field.
|
||||
func (r *trustCenterResolver) Organization(ctx context.Context, obj *types.TrustCenter) (*types.Organization, error) {
|
||||
return obj.Organization, nil
|
||||
@@ -155,15 +226,41 @@ func (r *trustCenterResolver) Organization(ctx context.Context, obj *types.Trust
|
||||
|
||||
// IsUserAuthenticated is the resolver for the isUserAuthenticated field.
|
||||
func (r *trustCenterResolver) IsUserAuthenticated(ctx context.Context, obj *types.TrustCenter) (bool, error) {
|
||||
if err := auth.ValidateTenantAccess(ctx, r, userTenantContextKey, obj.Organization.ID.TenantID()); err != nil {
|
||||
_, err := r.PrivateTrustService(ctx, obj.ID.TenantID())
|
||||
if err != nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// HasAcceptedNonDisclosureAgreement is the resolver for the hasAcceptedNonDisclosureAgreement field.
|
||||
func (r *trustCenterResolver) HasAcceptedNonDisclosureAgreement(ctx context.Context, obj *types.TrustCenter) (bool, error) {
|
||||
privateTrustService, err := r.PrivateTrustService(ctx, obj.ID.TenantID())
|
||||
if err != nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
userData := UserFromContext(ctx)
|
||||
if userData != nil {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
tokenData := TokenAccessFromContext(ctx)
|
||||
if tokenData != nil {
|
||||
hasAcceptedNDA, err := privateTrustService.TrustCenterAccesses.HasAcceptedNonDisclosureAgreement(ctx, obj.ID, tokenData.GetEmail())
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot check if user has accepted NDA: %w", err))
|
||||
}
|
||||
return hasAcceptedNDA, nil
|
||||
}
|
||||
|
||||
panic(fmt.Errorf("no user or token data found"))
|
||||
}
|
||||
|
||||
// Documents is the resolver for the documents field.
|
||||
func (r *trustCenterResolver) Documents(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.DocumentConnection, error) {
|
||||
trust := r.trustCenterSvc.WithTenant(obj.Organization.ID.TenantID())
|
||||
publicTrustService := r.PublicTrustService(ctx, obj.ID.TenantID())
|
||||
|
||||
pageOrderBy := page.OrderBy[coredata.DocumentOrderField]{
|
||||
Field: coredata.DocumentOrderFieldTitle,
|
||||
@@ -171,7 +268,7 @@ func (r *trustCenterResolver) Documents(ctx context.Context, obj *types.TrustCen
|
||||
}
|
||||
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
|
||||
|
||||
documentPage, err := trust.Documents.ListForOrganizationId(ctx, obj.Organization.ID, cursor)
|
||||
documentPage, err := publicTrustService.Documents.ListForOrganizationId(ctx, obj.Organization.ID, cursor)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot list public documents: %w", err))
|
||||
}
|
||||
@@ -181,7 +278,7 @@ func (r *trustCenterResolver) Documents(ctx context.Context, obj *types.TrustCen
|
||||
|
||||
// Audits is the resolver for the audits field.
|
||||
func (r *trustCenterResolver) Audits(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.AuditConnection, error) {
|
||||
trust := r.trustCenterSvc.WithTenant(obj.Organization.ID.TenantID())
|
||||
publicTrustService := r.PublicTrustService(ctx, obj.ID.TenantID())
|
||||
|
||||
pageOrderBy := page.OrderBy[coredata.AuditOrderField]{
|
||||
Field: coredata.AuditOrderFieldValidFrom,
|
||||
@@ -189,7 +286,7 @@ func (r *trustCenterResolver) Audits(ctx context.Context, obj *types.TrustCenter
|
||||
}
|
||||
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
|
||||
|
||||
auditPage, err := trust.Audits.ListForOrganizationId(ctx, obj.Organization.ID, cursor)
|
||||
auditPage, err := publicTrustService.Audits.ListForOrganizationId(ctx, obj.Organization.ID, cursor)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot list public audits: %w", err))
|
||||
}
|
||||
@@ -199,7 +296,7 @@ func (r *trustCenterResolver) Audits(ctx context.Context, obj *types.TrustCenter
|
||||
|
||||
// Vendors is the resolver for the vendors field.
|
||||
func (r *trustCenterResolver) Vendors(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.VendorConnection, error) {
|
||||
trust := r.trustCenterSvc.WithTenant(obj.Organization.ID.TenantID())
|
||||
publicTrustService := r.PublicTrustService(ctx, obj.ID.TenantID())
|
||||
|
||||
pageOrderBy := page.OrderBy[coredata.VendorOrderField]{
|
||||
Field: coredata.VendorOrderFieldName,
|
||||
@@ -207,7 +304,7 @@ func (r *trustCenterResolver) Vendors(ctx context.Context, obj *types.TrustCente
|
||||
}
|
||||
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
|
||||
|
||||
vendorPage, err := trust.Vendors.ListForOrganizationId(ctx, obj.Organization.ID, cursor)
|
||||
vendorPage, err := publicTrustService.Vendors.ListForOrganizationId(ctx, obj.Organization.ID, cursor)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot list public vendors: %w", err))
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ package trust
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/mail"
|
||||
@@ -23,8 +24,6 @@ import (
|
||||
|
||||
"github.com/getprobo/probo/pkg/coredata"
|
||||
"github.com/getprobo/probo/pkg/gid"
|
||||
"github.com/getprobo/probo/pkg/probo"
|
||||
"github.com/getprobo/probo/pkg/statelesstoken"
|
||||
"github.com/getprobo/probo/pkg/usrmgr"
|
||||
"go.gearno.de/kit/pg"
|
||||
)
|
||||
@@ -48,20 +47,12 @@ const (
|
||||
|
||||
func (s TrustCenterAccessService) ValidateToken(
|
||||
ctx context.Context,
|
||||
tokenString string,
|
||||
) (*probo.TrustCenterAccessData, error) {
|
||||
token, err := statelesstoken.ValidateToken[probo.TrustCenterAccessData](
|
||||
s.svc.tokenSecret,
|
||||
TokenTypeTrustCenterAccess,
|
||||
tokenString,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot validate trust center access token: %w", err)
|
||||
}
|
||||
|
||||
access := &coredata.TrustCenterAccess{}
|
||||
err = s.svc.pg.WithConn(ctx, func(conn pg.Conn) error {
|
||||
err := access.LoadByTrustCenterIDAndEmail(ctx, conn, s.svc.scope, token.Data.TrustCenterID, token.Data.Email)
|
||||
trustCenterID gid.GID,
|
||||
email string,
|
||||
) error {
|
||||
return s.svc.pg.WithConn(ctx, func(conn pg.Conn) error {
|
||||
access := &coredata.TrustCenterAccess{}
|
||||
err := access.LoadByTrustCenterIDAndEmail(ctx, conn, s.svc.scope, trustCenterID, email)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot load trust center access: %w", err)
|
||||
}
|
||||
@@ -72,12 +63,6 @@ func (s TrustCenterAccessService) ValidateToken(
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &token.Data, nil
|
||||
}
|
||||
|
||||
func (s TrustCenterAccessService) Create(
|
||||
@@ -115,14 +100,15 @@ func (s TrustCenterAccessService) Create(
|
||||
}
|
||||
|
||||
access = &coredata.TrustCenterAccess{
|
||||
ID: gid.New(s.svc.scope.GetTenantID(), coredata.TrustCenterAccessEntityType),
|
||||
TenantID: s.svc.scope.GetTenantID(),
|
||||
TrustCenterID: req.TrustCenterID,
|
||||
Email: req.Email,
|
||||
Name: req.Name,
|
||||
Active: false,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
ID: gid.New(s.svc.scope.GetTenantID(), coredata.TrustCenterAccessEntityType),
|
||||
TenantID: s.svc.scope.GetTenantID(),
|
||||
TrustCenterID: req.TrustCenterID,
|
||||
Email: req.Email,
|
||||
Name: req.Name,
|
||||
Active: false,
|
||||
HasAcceptedNonDisclosureAgreement: false,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
|
||||
if err := access.Insert(ctx, tx, s.svc.scope); err != nil {
|
||||
@@ -137,3 +123,48 @@ func (s TrustCenterAccessService) Create(
|
||||
|
||||
return access, nil
|
||||
}
|
||||
|
||||
func (s TrustCenterAccessService) HasAcceptedNonDisclosureAgreement(ctx context.Context, trustCenterID gid.GID, email string) (bool, error) {
|
||||
access := &coredata.TrustCenterAccess{}
|
||||
err := s.svc.pg.WithConn(ctx, func(conn pg.Conn) error {
|
||||
err := access.LoadByTrustCenterIDAndEmail(ctx, conn, s.svc.scope, trustCenterID, email)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot load trust center access: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return access.HasAcceptedNonDisclosureAgreement, nil
|
||||
}
|
||||
|
||||
func (s TrustCenterAccessService) AcceptNonDisclosureAgreement(ctx context.Context, trustCenterID gid.GID, email string) error {
|
||||
return s.svc.pg.WithTx(ctx, func(tx pg.Conn) error {
|
||||
access := &coredata.TrustCenterAccess{}
|
||||
if err := access.LoadByTrustCenterIDAndEmail(ctx, tx, s.svc.scope, trustCenterID, email); err != nil {
|
||||
return fmt.Errorf("cannot load trust center access: %w", err)
|
||||
}
|
||||
|
||||
acceptationLogs, err := json.Marshal(map[string]string{
|
||||
"email": email,
|
||||
"timestamp": time.Now().Format(time.RFC3339),
|
||||
"ip": ctx.Value(coredata.ContextKeyIPAddress).(string),
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot marshal non disclosure agreement acceptation logs: %w", err)
|
||||
}
|
||||
|
||||
access.HasAcceptedNonDisclosureAgreement = true
|
||||
access.UpdatedAt = time.Now()
|
||||
access.HasAcceptedNonDisclosureAgreementMetadata = acceptationLogs
|
||||
if err := access.Update(ctx, tx, s.svc.scope); err != nil {
|
||||
return fmt.Errorf("cannot update trust center access: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -16,10 +16,14 @@ package trust
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"fmt"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||
"github.com/getprobo/probo/pkg/coredata"
|
||||
"github.com/getprobo/probo/pkg/gid"
|
||||
"go.gearno.de/kit/pg"
|
||||
)
|
||||
|
||||
@@ -51,3 +55,88 @@ func (s TrustCenterService) GetBySlug(
|
||||
|
||||
return trustCenter, nil
|
||||
}
|
||||
|
||||
func (s TrustCenterService) Get(
|
||||
ctx context.Context,
|
||||
trustCenterID gid.GID,
|
||||
) (*coredata.TrustCenter, *coredata.File, error) {
|
||||
var trustCenter *coredata.TrustCenter
|
||||
var file *coredata.File
|
||||
|
||||
err := s.svc.pg.WithConn(
|
||||
ctx,
|
||||
func(conn pg.Conn) error {
|
||||
trustCenter = &coredata.TrustCenter{}
|
||||
if err := trustCenter.LoadByID(ctx, conn, s.svc.scope, trustCenterID); err != nil {
|
||||
return fmt.Errorf("cannot load trust center: %w", err)
|
||||
}
|
||||
|
||||
if trustCenter.NonDisclosureAgreementFileID != nil {
|
||||
file = &coredata.File{}
|
||||
if err := file.LoadByID(ctx, conn, s.svc.scope, *trustCenter.NonDisclosureAgreementFileID); err != nil {
|
||||
return fmt.Errorf("cannot load file: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("cannot load trust center: %w", err)
|
||||
}
|
||||
|
||||
return trustCenter, file, nil
|
||||
}
|
||||
|
||||
func (s TrustCenterService) GenerateNDAFileURL(
|
||||
ctx context.Context,
|
||||
trustCenterID gid.GID,
|
||||
expiresIn time.Duration,
|
||||
) (string, error) {
|
||||
var file *coredata.File
|
||||
|
||||
err := s.svc.pg.WithConn(
|
||||
ctx,
|
||||
func(conn pg.Conn) error {
|
||||
trustCenter := &coredata.TrustCenter{}
|
||||
if err := trustCenter.LoadByID(ctx, conn, s.svc.scope, trustCenterID); err != nil {
|
||||
return fmt.Errorf("cannot load trust center: %w", err)
|
||||
}
|
||||
|
||||
if trustCenter.NonDisclosureAgreementFileID == nil {
|
||||
return fmt.Errorf("no NDA file found")
|
||||
}
|
||||
|
||||
file = &coredata.File{}
|
||||
if err := file.LoadByID(ctx, conn, s.svc.scope, *trustCenter.NonDisclosureAgreementFileID); err != nil {
|
||||
return fmt.Errorf("cannot load file: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
presignClient := s3.NewPresignClient(s.svc.s3)
|
||||
|
||||
encodedFilename := url.QueryEscape(file.FileName)
|
||||
contentDisposition := fmt.Sprintf("attachment; filename=\"%s\"; filename*=UTF-8''%s",
|
||||
encodedFilename, encodedFilename)
|
||||
|
||||
presignedReq, err := presignClient.PresignGetObject(ctx, &s3.GetObjectInput{
|
||||
Bucket: aws.String(s.svc.bucket),
|
||||
Key: aws.String(file.FileKey),
|
||||
ResponseCacheControl: aws.String("max-age=3600, public"),
|
||||
ResponseContentDisposition: aws.String(contentDisposition),
|
||||
}, func(opts *s3.PresignOptions) {
|
||||
opts.Expires = expiresIn
|
||||
})
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("cannot presign GetObject request: %w", err)
|
||||
}
|
||||
|
||||
return presignedReq.URL, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user