diff --git a/apps/console/src/pages/organizations/processingActivities/ProcessingActivitiesPage.tsx b/apps/console/src/pages/organizations/processingActivities/ProcessingActivitiesPage.tsx
index 8b4755a85..e04dc1f42 100644
--- a/apps/console/src/pages/organizations/processingActivities/ProcessingActivitiesPage.tsx
+++ b/apps/console/src/pages/organizations/processingActivities/ProcessingActivitiesPage.tsx
@@ -16,6 +16,10 @@ import {
useConfirm,
Tabs,
TabItem,
+ IconArrowDown,
+ IconChevronDown,
+ Spinner,
+ Dropdown,
} from "@probo/ui";
import { useTranslate } from "@probo/i18n";
import { usePageTitle } from "@probo/hooks";
@@ -32,7 +36,8 @@ import { useOrganizationId } from "/hooks/useOrganizationId";
import { useParams } from "react-router";
import { CreateProcessingActivityDialog } from "./dialogs/CreateProcessingActivityDialog";
import { deleteProcessingActivityMutation, ProcessingActivitiesConnectionKey, processingActivitiesQuery } from "../../../hooks/graph/ProcessingActivityGraph";
-import { sprintf, promisifyMutation } from "@probo/helpers";
+import { sprintf, promisifyMutation, downloadFile, toDateInput } from "@probo/helpers";
+import { useMutationWithToasts } from "/hooks/useMutationWithToasts";
import { SnapshotBanner } from "/components/SnapshotBanner";
import type { NodeOf } from "/types";
import type {
@@ -174,6 +179,36 @@ const tiaListPageFragment = graphql`
}
`;
+const exportProcessingActivitiesPDFMutation = graphql`
+ mutation ProcessingActivitiesPageExportPDFMutation(
+ $input: ExportProcessingActivitiesPDFInput!
+ ) {
+ exportProcessingActivitiesPDF(input: $input) {
+ data
+ }
+ }
+`;
+
+const exportDataProtectionImpactAssessmentsPDFMutation = graphql`
+ mutation ProcessingActivitiesPageExportDPIAPDFMutation(
+ $input: ExportDataProtectionImpactAssessmentsPDFInput!
+ ) {
+ exportDataProtectionImpactAssessmentsPDF(input: $input) {
+ data
+ }
+ }
+`;
+
+const exportTransferImpactAssessmentsPDFMutation = graphql`
+ mutation ProcessingActivitiesPageExportTIAPDFMutation(
+ $input: ExportTransferImpactAssessmentsPDFInput!
+ ) {
+ exportTransferImpactAssessmentsPDF(input: $input) {
+ data
+ }
+ }
+`;
+
export default function ProcessingActivitiesPage({ queryRef }: ProcessingActivitiesPageProps) {
const { __ } = useTranslate();
const organizationId = useOrganizationId();
@@ -233,12 +268,169 @@ export default function ProcessingActivitiesPage({ queryRef }: ProcessingActivit
isAuthorized("ProcessingActivity", "deleteProcessingActivity")
);
+ const canExportPDF = isAuthorized("ProcessingActivity", "exportProcessingActivitiesPDF");
+ const [exportPDF, isExportingPDF] = useMutationWithToasts<{
+ response: {
+ exportProcessingActivitiesPDF?: {
+ data: string;
+ };
+ };
+ variables: {
+ input: {
+ organizationId: string;
+ filter: { snapshotId: string } | null;
+ };
+ };
+ }>(
+ exportProcessingActivitiesPDFMutation,
+ {
+ successMessage: __("PDF download started."),
+ errorMessage: __("Failed to generate PDF"),
+ }
+ );
+
+ const handleExportPDF = () => {
+ exportPDF({
+ variables: {
+ input: {
+ organizationId: organizationId,
+ filter: snapshotId ? { snapshotId } : null,
+ },
+ },
+ onCompleted: (data) => {
+ if (data.exportProcessingActivitiesPDF?.data) {
+ downloadFile(
+ data.exportProcessingActivitiesPDF.data,
+ `processing-activities-${toDateInput(new Date().toISOString())}.pdf`
+ );
+ }
+ },
+ });
+ };
+
+ const canExportDPIAPDF = isAuthorized("Organization", "exportDataProtectionImpactAssessmentsPDF");
+ const [exportDPIAPDF, isExportingDPIAPDF] = useMutationWithToasts<{
+ response: {
+ exportDataProtectionImpactAssessmentsPDF?: {
+ data: string;
+ };
+ };
+ variables: {
+ input: {
+ organizationId: string;
+ filter: { snapshotId: string } | null;
+ };
+ };
+ }>(
+ exportDataProtectionImpactAssessmentsPDFMutation,
+ {
+ successMessage: __("PDF download started."),
+ errorMessage: __("Failed to generate PDF"),
+ }
+ );
+
+ const handleExportDPIAPDF = () => {
+ exportDPIAPDF({
+ variables: {
+ input: {
+ organizationId: organizationId,
+ filter: snapshotId ? { snapshotId } : null,
+ },
+ },
+ onCompleted: (data) => {
+ if (data.exportDataProtectionImpactAssessmentsPDF?.data) {
+ downloadFile(
+ data.exportDataProtectionImpactAssessmentsPDF.data,
+ `data-protection-impact-assessments-${toDateInput(new Date().toISOString())}.pdf`
+ );
+ }
+ },
+ });
+ };
+
+ const canExportTIAPDF = isAuthorized("Organization", "exportTransferImpactAssessmentsPDF");
+ const [exportTIAPDF, isExportingTIAPDF] = useMutationWithToasts<{
+ response: {
+ exportTransferImpactAssessmentsPDF?: {
+ data: string;
+ };
+ };
+ variables: {
+ input: {
+ organizationId: string;
+ filter: { snapshotId: string } | null;
+ };
+ };
+ }>(
+ exportTransferImpactAssessmentsPDFMutation,
+ {
+ successMessage: __("PDF download started."),
+ errorMessage: __("Failed to generate PDF"),
+ }
+ );
+
+ const handleExportTIAPDF = () => {
+ exportTIAPDF({
+ variables: {
+ input: {
+ organizationId: organizationId,
+ filter: snapshotId ? { snapshotId } : null,
+ },
+ },
+ onCompleted: (data) => {
+ if (data.exportTransferImpactAssessmentsPDF?.data) {
+ downloadFile(
+ data.exportTransferImpactAssessmentsPDF.data,
+ `transfer-impact-assessments-${toDateInput(new Date().toISOString())}.pdf`
+ );
+ }
+ },
+ });
+ };
+
return (
{isSnapshotMode && snapshotId && (
)}
+ {(canExportPDF || canExportDPIAPDF || canExportTIAPDF) && (
+
+ {__("Export")}
+
+ }
+ >
+ {canExportPDF && (
+
+ {__("Processing Activities")}
+
+ )}
+ {canExportDPIAPDF && (
+
+ {__("Data Protection Impact Assessments")}
+
+ )}
+ {canExportTIAPDF && (
+
+ {__("Transfer Impact Assessments")}
+
+ )}
+
+ )}
{!isSnapshotMode && activeTab === "activities" && (
isAuthorized("Organization", "createProcessingActivity") && (
- | {__("Name")} |
- {__("Purpose")} |
- {__("Data Subject")} |
- {__("Lawful Basis")} |
- {__("Location")} |
- {__("International Transfers")} |
- {hasAnyAction && {__("Actions")} | }
+ {__("Name")} |
+ {__("Purpose")} |
+ {__("Data Subject")} |
+ {__("Lawful Basis")} |
+ {__("Location")} |
+ {__("International Transfers")} |
+ {hasAnyAction && {__("Actions")} | }
diff --git a/apps/console/src/pages/organizations/processingActivities/__generated__/ProcessingActivitiesPageExportDPIAPDFMutation.graphql.ts b/apps/console/src/pages/organizations/processingActivities/__generated__/ProcessingActivitiesPageExportDPIAPDFMutation.graphql.ts
new file mode 100644
index 000000000..ce85042bb
--- /dev/null
+++ b/apps/console/src/pages/organizations/processingActivities/__generated__/ProcessingActivitiesPageExportDPIAPDFMutation.graphql.ts
@@ -0,0 +1,96 @@
+/**
+ * @generated SignedSource<<2f43f6874d8b6d515cf244934b7b19ea>>
+ * @lightSyntaxTransform
+ * @nogrep
+ */
+
+/* tslint:disable */
+/* eslint-disable */
+// @ts-nocheck
+
+import { ConcreteRequest } from 'relay-runtime';
+export type ExportDataProtectionImpactAssessmentsPDFInput = {
+ filter?: DataProtectionImpactAssessmentFilter | null | undefined;
+ organizationId: string;
+};
+export type DataProtectionImpactAssessmentFilter = {
+ snapshotId?: string | null | undefined;
+};
+export type ProcessingActivitiesPageExportDPIAPDFMutation$variables = {
+ input: ExportDataProtectionImpactAssessmentsPDFInput;
+};
+export type ProcessingActivitiesPageExportDPIAPDFMutation$data = {
+ readonly exportDataProtectionImpactAssessmentsPDF: {
+ readonly data: string;
+ };
+};
+export type ProcessingActivitiesPageExportDPIAPDFMutation = {
+ response: ProcessingActivitiesPageExportDPIAPDFMutation$data;
+ variables: ProcessingActivitiesPageExportDPIAPDFMutation$variables;
+};
+
+const node: ConcreteRequest = (function(){
+var v0 = [
+ {
+ "defaultValue": null,
+ "kind": "LocalArgument",
+ "name": "input"
+ }
+],
+v1 = [
+ {
+ "alias": null,
+ "args": [
+ {
+ "kind": "Variable",
+ "name": "input",
+ "variableName": "input"
+ }
+ ],
+ "concreteType": "ExportDataProtectionImpactAssessmentsPDFPayload",
+ "kind": "LinkedField",
+ "name": "exportDataProtectionImpactAssessmentsPDF",
+ "plural": false,
+ "selections": [
+ {
+ "alias": null,
+ "args": null,
+ "kind": "ScalarField",
+ "name": "data",
+ "storageKey": null
+ }
+ ],
+ "storageKey": null
+ }
+];
+return {
+ "fragment": {
+ "argumentDefinitions": (v0/*: any*/),
+ "kind": "Fragment",
+ "metadata": null,
+ "name": "ProcessingActivitiesPageExportDPIAPDFMutation",
+ "selections": (v1/*: any*/),
+ "type": "Mutation",
+ "abstractKey": null
+ },
+ "kind": "Request",
+ "operation": {
+ "argumentDefinitions": (v0/*: any*/),
+ "kind": "Operation",
+ "name": "ProcessingActivitiesPageExportDPIAPDFMutation",
+ "selections": (v1/*: any*/)
+ },
+ "params": {
+ "cacheID": "851a1c0def7719185cf3a67954696231",
+ "id": null,
+ "metadata": {},
+ "name": "ProcessingActivitiesPageExportDPIAPDFMutation",
+ "operationKind": "mutation",
+ "text": "mutation ProcessingActivitiesPageExportDPIAPDFMutation(\n $input: ExportDataProtectionImpactAssessmentsPDFInput!\n) {\n exportDataProtectionImpactAssessmentsPDF(input: $input) {\n data\n }\n}\n"
+ }
+};
+})();
+
+(node as any).hash = "3c2a96fb29c61791e7df39c7b8174c90";
+
+export default node;
diff --git a/apps/console/src/pages/organizations/processingActivities/__generated__/ProcessingActivitiesPageExportPDFMutation.graphql.ts b/apps/console/src/pages/organizations/processingActivities/__generated__/ProcessingActivitiesPageExportPDFMutation.graphql.ts
new file mode 100644
index 000000000..a29c6936a
--- /dev/null
+++ b/apps/console/src/pages/organizations/processingActivities/__generated__/ProcessingActivitiesPageExportPDFMutation.graphql.ts
@@ -0,0 +1,96 @@
+/**
+ * @generated SignedSource<<82ece1ab5e9585bfcce605e38fe9563a>>
+ * @lightSyntaxTransform
+ * @nogrep
+ */
+
+/* tslint:disable */
+/* eslint-disable */
+// @ts-nocheck
+
+import { ConcreteRequest } from 'relay-runtime';
+export type ExportProcessingActivitiesPDFInput = {
+ filter?: ProcessingActivityFilter | null | undefined;
+ organizationId: string;
+};
+export type ProcessingActivityFilter = {
+ snapshotId?: string | null | undefined;
+};
+export type ProcessingActivitiesPageExportPDFMutation$variables = {
+ input: ExportProcessingActivitiesPDFInput;
+};
+export type ProcessingActivitiesPageExportPDFMutation$data = {
+ readonly exportProcessingActivitiesPDF: {
+ readonly data: string;
+ };
+};
+export type ProcessingActivitiesPageExportPDFMutation = {
+ response: ProcessingActivitiesPageExportPDFMutation$data;
+ variables: ProcessingActivitiesPageExportPDFMutation$variables;
+};
+
+const node: ConcreteRequest = (function(){
+var v0 = [
+ {
+ "defaultValue": null,
+ "kind": "LocalArgument",
+ "name": "input"
+ }
+],
+v1 = [
+ {
+ "alias": null,
+ "args": [
+ {
+ "kind": "Variable",
+ "name": "input",
+ "variableName": "input"
+ }
+ ],
+ "concreteType": "ExportProcessingActivitiesPDFPayload",
+ "kind": "LinkedField",
+ "name": "exportProcessingActivitiesPDF",
+ "plural": false,
+ "selections": [
+ {
+ "alias": null,
+ "args": null,
+ "kind": "ScalarField",
+ "name": "data",
+ "storageKey": null
+ }
+ ],
+ "storageKey": null
+ }
+];
+return {
+ "fragment": {
+ "argumentDefinitions": (v0/*: any*/),
+ "kind": "Fragment",
+ "metadata": null,
+ "name": "ProcessingActivitiesPageExportPDFMutation",
+ "selections": (v1/*: any*/),
+ "type": "Mutation",
+ "abstractKey": null
+ },
+ "kind": "Request",
+ "operation": {
+ "argumentDefinitions": (v0/*: any*/),
+ "kind": "Operation",
+ "name": "ProcessingActivitiesPageExportPDFMutation",
+ "selections": (v1/*: any*/)
+ },
+ "params": {
+ "cacheID": "85140bef5e55c8ae4fdb139965375f13",
+ "id": null,
+ "metadata": {},
+ "name": "ProcessingActivitiesPageExportPDFMutation",
+ "operationKind": "mutation",
+ "text": "mutation ProcessingActivitiesPageExportPDFMutation(\n $input: ExportProcessingActivitiesPDFInput!\n) {\n exportProcessingActivitiesPDF(input: $input) {\n data\n }\n}\n"
+ }
+};
+})();
+
+(node as any).hash = "cc777bb4440f6aed36c2fb92c1bc7e0b";
+
+export default node;
diff --git a/apps/console/src/pages/organizations/processingActivities/__generated__/ProcessingActivitiesPageExportTIAPDFMutation.graphql.ts b/apps/console/src/pages/organizations/processingActivities/__generated__/ProcessingActivitiesPageExportTIAPDFMutation.graphql.ts
new file mode 100644
index 000000000..d40e9f622
--- /dev/null
+++ b/apps/console/src/pages/organizations/processingActivities/__generated__/ProcessingActivitiesPageExportTIAPDFMutation.graphql.ts
@@ -0,0 +1,96 @@
+/**
+ * @generated SignedSource<>
+ * @lightSyntaxTransform
+ * @nogrep
+ */
+
+/* tslint:disable */
+/* eslint-disable */
+// @ts-nocheck
+
+import { ConcreteRequest } from 'relay-runtime';
+export type ExportTransferImpactAssessmentsPDFInput = {
+ filter?: TransferImpactAssessmentFilter | null | undefined;
+ organizationId: string;
+};
+export type TransferImpactAssessmentFilter = {
+ snapshotId?: string | null | undefined;
+};
+export type ProcessingActivitiesPageExportTIAPDFMutation$variables = {
+ input: ExportTransferImpactAssessmentsPDFInput;
+};
+export type ProcessingActivitiesPageExportTIAPDFMutation$data = {
+ readonly exportTransferImpactAssessmentsPDF: {
+ readonly data: string;
+ };
+};
+export type ProcessingActivitiesPageExportTIAPDFMutation = {
+ response: ProcessingActivitiesPageExportTIAPDFMutation$data;
+ variables: ProcessingActivitiesPageExportTIAPDFMutation$variables;
+};
+
+const node: ConcreteRequest = (function(){
+var v0 = [
+ {
+ "defaultValue": null,
+ "kind": "LocalArgument",
+ "name": "input"
+ }
+],
+v1 = [
+ {
+ "alias": null,
+ "args": [
+ {
+ "kind": "Variable",
+ "name": "input",
+ "variableName": "input"
+ }
+ ],
+ "concreteType": "ExportTransferImpactAssessmentsPDFPayload",
+ "kind": "LinkedField",
+ "name": "exportTransferImpactAssessmentsPDF",
+ "plural": false,
+ "selections": [
+ {
+ "alias": null,
+ "args": null,
+ "kind": "ScalarField",
+ "name": "data",
+ "storageKey": null
+ }
+ ],
+ "storageKey": null
+ }
+];
+return {
+ "fragment": {
+ "argumentDefinitions": (v0/*: any*/),
+ "kind": "Fragment",
+ "metadata": null,
+ "name": "ProcessingActivitiesPageExportTIAPDFMutation",
+ "selections": (v1/*: any*/),
+ "type": "Mutation",
+ "abstractKey": null
+ },
+ "kind": "Request",
+ "operation": {
+ "argumentDefinitions": (v0/*: any*/),
+ "kind": "Operation",
+ "name": "ProcessingActivitiesPageExportTIAPDFMutation",
+ "selections": (v1/*: any*/)
+ },
+ "params": {
+ "cacheID": "b41ab5f56ee5dc4436069c4e2a97f8d8",
+ "id": null,
+ "metadata": {},
+ "name": "ProcessingActivitiesPageExportTIAPDFMutation",
+ "operationKind": "mutation",
+ "text": "mutation ProcessingActivitiesPageExportTIAPDFMutation(\n $input: ExportTransferImpactAssessmentsPDFInput!\n) {\n exportTransferImpactAssessmentsPDF(input: $input) {\n data\n }\n}\n"
+ }
+};
+})();
+
+(node as any).hash = "3fe289d5564d0617074825d8c58f88f8";
+
+export default node;
diff --git a/e2e/console/processing_activity_test.go b/e2e/console/processing_activity_test.go
index 23d248833..5dbe1f477 100644
--- a/e2e/console/processing_activity_test.go
+++ b/e2e/console/processing_activity_test.go
@@ -2596,3 +2596,392 @@ func TestProcessingActivity_Snapshot_DPIA_TIA(t *testing.T) {
}
})
}
+
+func TestProcessingActivity_ExportPDF(t *testing.T) {
+ t.Parallel()
+ owner := testutil.NewClient(t, testutil.RoleOwner)
+
+ t.Run("export processing activities PDF", func(t *testing.T) {
+ _ = factory.NewProcessingActivity(owner).
+ WithName("PA Export Test 1").
+ WithLawfulBasis("CONSENT").
+ Create()
+ _ = factory.NewProcessingActivity(owner).
+ WithName("PA Export Test 2").
+ WithLawfulBasis("LEGITIMATE_INTEREST").
+ Create()
+
+ query := `
+ mutation ExportProcessingActivitiesPDF($input: ExportProcessingActivitiesPDFInput!) {
+ exportProcessingActivitiesPDF(input: $input) {
+ data
+ }
+ }
+ `
+
+ var result struct {
+ ExportProcessingActivitiesPDF struct {
+ Data string `json:"data"`
+ } `json:"exportProcessingActivitiesPDF"`
+ }
+
+ err := owner.Execute(query, map[string]any{
+ "input": map[string]any{
+ "organizationId": owner.GetOrganizationID().String(),
+ "filter": nil,
+ },
+ }, &result)
+ require.NoError(t, err)
+ assert.NotEmpty(t, result.ExportProcessingActivitiesPDF.Data)
+ assert.Contains(t, result.ExportProcessingActivitiesPDF.Data, "data:application/pdf;base64,")
+ })
+
+ t.Run("export processing activities PDF with snapshot filter", func(t *testing.T) {
+ _ = factory.NewProcessingActivity(owner).
+ WithName("PA Snapshot Export Test").
+ Create()
+
+ // Create snapshot
+ var snapshotResult struct {
+ CreateSnapshot struct {
+ SnapshotEdge struct {
+ Node struct {
+ ID string `json:"id"`
+ } `json:"node"`
+ } `json:"snapshotEdge"`
+ } `json:"createSnapshot"`
+ }
+ err := owner.Execute(`
+ mutation($input: CreateSnapshotInput!) {
+ createSnapshot(input: $input) {
+ snapshotEdge {
+ node { id }
+ }
+ }
+ }
+ `, map[string]any{
+ "input": map[string]any{
+ "organizationId": owner.GetOrganizationID().String(),
+ "name": fmt.Sprintf("PA Export Snapshot Test %d", time.Now().UnixNano()),
+ "type": "PROCESSING_ACTIVITIES",
+ },
+ }, &snapshotResult)
+ require.NoError(t, err)
+ snapshotID := snapshotResult.CreateSnapshot.SnapshotEdge.Node.ID
+
+ query := `
+ mutation ExportProcessingActivitiesPDF($input: ExportProcessingActivitiesPDFInput!) {
+ exportProcessingActivitiesPDF(input: $input) {
+ data
+ }
+ }
+ `
+
+ var result struct {
+ ExportProcessingActivitiesPDF struct {
+ Data string `json:"data"`
+ } `json:"exportProcessingActivitiesPDF"`
+ }
+
+ err = owner.Execute(query, map[string]any{
+ "input": map[string]any{
+ "organizationId": owner.GetOrganizationID().String(),
+ "filter": map[string]any{
+ "snapshotId": snapshotID,
+ },
+ },
+ }, &result)
+ require.NoError(t, err)
+ assert.NotEmpty(t, result.ExportProcessingActivitiesPDF.Data)
+ assert.Contains(t, result.ExportProcessingActivitiesPDF.Data, "data:application/pdf;base64,")
+ })
+
+ t.Run("export fails with no processing activities", func(t *testing.T) {
+ newOwner := testutil.NewClient(t, testutil.RoleOwner)
+
+ query := `
+ mutation ExportProcessingActivitiesPDF($input: ExportProcessingActivitiesPDFInput!) {
+ exportProcessingActivitiesPDF(input: $input) {
+ data
+ }
+ }
+ `
+
+ _, err := newOwner.Do(query, map[string]any{
+ "input": map[string]any{
+ "organizationId": newOwner.GetOrganizationID().String(),
+ "filter": nil,
+ },
+ })
+ testutil.RequireErrorCode(t, err, "NOT_FOUND")
+ assert.Contains(t, err.Error(), "no processing activities found")
+ })
+}
+
+func TestDataProtectionImpactAssessment_ExportPDF(t *testing.T) {
+ t.Parallel()
+ owner := testutil.NewClient(t, testutil.RoleOwner)
+
+ t.Run("export DPIA PDF", func(t *testing.T) {
+ pa1ID := factory.NewProcessingActivity(owner).
+ WithName("DPIA Export Test PA 1").
+ Create()
+ pa2ID := factory.NewProcessingActivity(owner).
+ WithName("DPIA Export Test PA 2").
+ Create()
+
+ _, err := owner.Do(`
+ mutation($input: CreateDataProtectionImpactAssessmentInput!) {
+ createDataProtectionImpactAssessment(input: $input) {
+ dataProtectionImpactAssessment { id }
+ }
+ }
+ `, map[string]any{
+ "input": map[string]any{
+ "processingActivityId": pa1ID,
+ "description": "DPIA 1 description",
+ "residualRisk": "LOW",
+ },
+ })
+ require.NoError(t, err)
+
+ _, err = owner.Do(`
+ mutation($input: CreateDataProtectionImpactAssessmentInput!) {
+ createDataProtectionImpactAssessment(input: $input) {
+ dataProtectionImpactAssessment { id }
+ }
+ }
+ `, map[string]any{
+ "input": map[string]any{
+ "processingActivityId": pa2ID,
+ "description": "DPIA 2 description",
+ "residualRisk": "MEDIUM",
+ },
+ })
+ require.NoError(t, err)
+
+ query := `
+ mutation ExportDataProtectionImpactAssessmentsPDF($input: ExportDataProtectionImpactAssessmentsPDFInput!) {
+ exportDataProtectionImpactAssessmentsPDF(input: $input) {
+ data
+ }
+ }
+ `
+
+ var result struct {
+ ExportDataProtectionImpactAssessmentsPDF struct {
+ Data string `json:"data"`
+ } `json:"exportDataProtectionImpactAssessmentsPDF"`
+ }
+
+ err = owner.Execute(query, map[string]any{
+ "input": map[string]any{
+ "organizationId": owner.GetOrganizationID().String(),
+ "filter": nil,
+ },
+ }, &result)
+ require.NoError(t, err)
+ assert.NotEmpty(t, result.ExportDataProtectionImpactAssessmentsPDF.Data)
+ assert.Contains(t, result.ExportDataProtectionImpactAssessmentsPDF.Data, "data:application/pdf;base64,")
+ })
+
+ t.Run("export fails with no DPIAs", func(t *testing.T) {
+ newOwner := testutil.NewClient(t, testutil.RoleOwner)
+
+ query := `
+ mutation ExportDataProtectionImpactAssessmentsPDF($input: ExportDataProtectionImpactAssessmentsPDFInput!) {
+ exportDataProtectionImpactAssessmentsPDF(input: $input) {
+ data
+ }
+ }
+ `
+
+ _, err := newOwner.Do(query, map[string]any{
+ "input": map[string]any{
+ "organizationId": newOwner.GetOrganizationID().String(),
+ "filter": nil,
+ },
+ })
+ testutil.RequireErrorCode(t, err, "NOT_FOUND")
+ assert.Contains(t, err.Error(), "no data protection impact assessments found")
+ })
+}
+
+func TestTransferImpactAssessment_ExportPDF(t *testing.T) {
+ t.Parallel()
+ owner := testutil.NewClient(t, testutil.RoleOwner)
+
+ t.Run("export TIA PDF", func(t *testing.T) {
+ pa1ID := factory.NewProcessingActivity(owner).
+ WithName("TIA Export Test PA 1").
+ Create()
+ pa2ID := factory.NewProcessingActivity(owner).
+ WithName("TIA Export Test PA 2").
+ Create()
+
+ _, err := owner.Do(`
+ mutation($input: CreateTransferImpactAssessmentInput!) {
+ createTransferImpactAssessment(input: $input) {
+ transferImpactAssessment { id }
+ }
+ }
+ `, map[string]any{
+ "input": map[string]any{
+ "processingActivityId": pa1ID,
+ "dataSubjects": "TIA 1 subjects",
+ "transfer": "EU to US",
+ },
+ })
+ require.NoError(t, err)
+
+ _, err = owner.Do(`
+ mutation($input: CreateTransferImpactAssessmentInput!) {
+ createTransferImpactAssessment(input: $input) {
+ transferImpactAssessment { id }
+ }
+ }
+ `, map[string]any{
+ "input": map[string]any{
+ "processingActivityId": pa2ID,
+ "dataSubjects": "TIA 2 subjects",
+ "transfer": "EU to UK",
+ },
+ })
+ require.NoError(t, err)
+
+ query := `
+ mutation ExportTransferImpactAssessmentsPDF($input: ExportTransferImpactAssessmentsPDFInput!) {
+ exportTransferImpactAssessmentsPDF(input: $input) {
+ data
+ }
+ }
+ `
+
+ var result struct {
+ ExportTransferImpactAssessmentsPDF struct {
+ Data string `json:"data"`
+ } `json:"exportTransferImpactAssessmentsPDF"`
+ }
+
+ err = owner.Execute(query, map[string]any{
+ "input": map[string]any{
+ "organizationId": owner.GetOrganizationID().String(),
+ "filter": nil,
+ },
+ }, &result)
+ require.NoError(t, err)
+ assert.NotEmpty(t, result.ExportTransferImpactAssessmentsPDF.Data)
+ assert.Contains(t, result.ExportTransferImpactAssessmentsPDF.Data, "data:application/pdf;base64,")
+ })
+
+ t.Run("export fails with no TIAs", func(t *testing.T) {
+ newOwner := testutil.NewClient(t, testutil.RoleOwner)
+
+ query := `
+ mutation ExportTransferImpactAssessmentsPDF($input: ExportTransferImpactAssessmentsPDFInput!) {
+ exportTransferImpactAssessmentsPDF(input: $input) {
+ data
+ }
+ }
+ `
+
+ _, err := newOwner.Do(query, map[string]any{
+ "input": map[string]any{
+ "organizationId": newOwner.GetOrganizationID().String(),
+ "filter": nil,
+ },
+ })
+ testutil.RequireErrorCode(t, err, "NOT_FOUND")
+ assert.Contains(t, err.Error(), "no transfer impact assessments found")
+ })
+}
+
+func TestProcessingActivity_ExportPDF_RBAC(t *testing.T) {
+ t.Parallel()
+
+ t.Run("owner can export PDF", func(t *testing.T) {
+ owner := testutil.NewClient(t, testutil.RoleOwner)
+ _ = factory.NewProcessingActivity(owner).WithName("RBAC Export Test").Create()
+
+ query := `
+ mutation ExportProcessingActivitiesPDF($input: ExportProcessingActivitiesPDFInput!) {
+ exportProcessingActivitiesPDF(input: $input) {
+ data
+ }
+ }
+ `
+
+ var result struct {
+ ExportProcessingActivitiesPDF struct {
+ Data string `json:"data"`
+ } `json:"exportProcessingActivitiesPDF"`
+ }
+
+ err := owner.Execute(query, map[string]any{
+ "input": map[string]any{
+ "organizationId": owner.GetOrganizationID().String(),
+ "filter": nil,
+ },
+ }, &result)
+ require.NoError(t, err, "owner should be able to export PDF")
+ assert.NotEmpty(t, result.ExportProcessingActivitiesPDF.Data)
+ })
+
+ t.Run("admin can export PDF", func(t *testing.T) {
+ owner := testutil.NewClient(t, testutil.RoleOwner)
+ admin := testutil.NewClientInOrg(t, testutil.RoleAdmin, owner)
+ _ = factory.NewProcessingActivity(owner).WithName("RBAC Export Test").Create()
+
+ query := `
+ mutation ExportProcessingActivitiesPDF($input: ExportProcessingActivitiesPDFInput!) {
+ exportProcessingActivitiesPDF(input: $input) {
+ data
+ }
+ }
+ `
+
+ var result struct {
+ ExportProcessingActivitiesPDF struct {
+ Data string `json:"data"`
+ } `json:"exportProcessingActivitiesPDF"`
+ }
+
+ err := admin.Execute(query, map[string]any{
+ "input": map[string]any{
+ "organizationId": admin.GetOrganizationID().String(),
+ "filter": nil,
+ },
+ }, &result)
+ require.NoError(t, err, "admin should be able to export PDF")
+ assert.NotEmpty(t, result.ExportProcessingActivitiesPDF.Data)
+ })
+
+ t.Run("viewer can export PDF", func(t *testing.T) {
+ owner := testutil.NewClient(t, testutil.RoleOwner)
+ viewer := testutil.NewClientInOrg(t, testutil.RoleViewer, owner)
+ _ = factory.NewProcessingActivity(owner).WithName("RBAC Export Test").Create()
+
+ query := `
+ mutation ExportProcessingActivitiesPDF($input: ExportProcessingActivitiesPDFInput!) {
+ exportProcessingActivitiesPDF(input: $input) {
+ data
+ }
+ }
+ `
+
+ var result struct {
+ ExportProcessingActivitiesPDF struct {
+ Data string `json:"data"`
+ } `json:"exportProcessingActivitiesPDF"`
+ }
+
+ err := viewer.Execute(query, map[string]any{
+ "input": map[string]any{
+ "organizationId": viewer.GetOrganizationID().String(),
+ "filter": nil,
+ },
+ }, &result)
+ require.NoError(t, err, "viewer should be able to export PDF")
+ assert.NotEmpty(t, result.ExportProcessingActivitiesPDF.Data)
+ })
+}
diff --git a/pkg/authz/permissions.go b/pkg/authz/permissions.go
index 3a7942837..4c490437a 100644
--- a/pkg/authz/permissions.go
+++ b/pkg/authz/permissions.go
@@ -92,7 +92,7 @@ const (
ActionListComplianceReports Action = "listComplianceReports"
ActionListContacts Action = "listContacts"
ActionListContinualImprovements Action = "listContinualImprovements"
- ActionListRightsRequests Action = "listRightsRequests"
+ ActionListRightsRequests Action = "listRightsRequests"
ActionListControls Action = "listControls"
ActionListData Action = "listData"
ActionListDocuments Action = "listDocuments"
@@ -235,39 +235,42 @@ const (
ActionDeleteVendorDataPrivacyAgreement Action = "deleteVendorDataPrivacyAgreement"
ActionDeleteVendorService Action = "deleteVendorService"
- ActionAcceptInvitation Action = "acceptInvitation"
- ActionAssessVendor Action = "assessVendor"
- ActionAssignTask Action = "assignTask"
- ActionBulkDeleteDocuments Action = "bulkDeleteDocuments"
- ActionBulkExportDocuments Action = "bulkExportDocuments"
- ActionBulkPublishDocumentVersions Action = "bulkPublishDocumentVersions"
- ActionBulkRequestSignatures Action = "bulkRequestSignatures"
- ActionCancelSignatureRequest Action = "cancelSignatureRequest"
- ActionSignDocument Action = "signDocument"
- ActionConfirmEmail Action = "confirmEmail"
- ActionDisableSAML Action = "disableSAML"
- ActionEnableSAML Action = "enableSAML"
- ActionExportDocumentVersionPDF Action = "exportDocumentVersionPDF"
- ActionExportSignableVersionDocumentPDF Action = "exportSignableVersionDocumentPDF"
- ActionExportFramework Action = "exportFramework"
- ActionGenerateDocumentChangelog Action = "generateDocumentChangelog"
- ActionGenerateFrameworkStateOfApplicability Action = "generateFrameworkStateOfApplicability"
- ActionImportFramework Action = "importFramework"
- ActionImportMeasure Action = "importMeasure"
- ActionInitiateDomainVerification Action = "initiateDomainVerification"
- ActionInviteUser Action = "inviteUser"
- ActionPublishDocumentVersion Action = "publishDocumentVersion"
- ActionRemoveMember Action = "removeMember"
- ActionRequestSignature Action = "requestSignature"
- ActionSendSigningNotifications Action = "sendSigningNotifications"
- ActionUnassignTask Action = "unassignTask"
- ActionUploadAuditReport Action = "uploadAuditReport"
- ActionUploadMeasureEvidence Action = "uploadMeasureEvidence"
- ActionUploadTrustCenterNDA Action = "uploadTrustCenterNDA"
- ActionUploadVendorBusinessAssociateAgreement Action = "uploadVendorBusinessAssociateAgreement"
- ActionUploadVendorComplianceReport Action = "uploadVendorComplianceReport"
- ActionUploadVendorDataPrivacyAgreement Action = "uploadVendorDataPrivacyAgreement"
- ActionVerifyDomain Action = "verifyDomain"
+ ActionAcceptInvitation Action = "acceptInvitation"
+ ActionAssessVendor Action = "assessVendor"
+ ActionAssignTask Action = "assignTask"
+ ActionBulkDeleteDocuments Action = "bulkDeleteDocuments"
+ ActionBulkExportDocuments Action = "bulkExportDocuments"
+ ActionBulkPublishDocumentVersions Action = "bulkPublishDocumentVersions"
+ ActionBulkRequestSignatures Action = "bulkRequestSignatures"
+ ActionCancelSignatureRequest Action = "cancelSignatureRequest"
+ ActionSignDocument Action = "signDocument"
+ ActionConfirmEmail Action = "confirmEmail"
+ ActionDisableSAML Action = "disableSAML"
+ ActionEnableSAML Action = "enableSAML"
+ ActionExportDocumentVersionPDF Action = "exportDocumentVersionPDF"
+ ActionExportSignableVersionDocumentPDF Action = "exportSignableVersionDocumentPDF"
+ ActionExportProcessingActivitiesPDF Action = "exportProcessingActivitiesPDF"
+ ActionExportDataProtectionImpactAssessmentsPDF Action = "exportDataProtectionImpactAssessmentsPDF"
+ ActionExportTransferImpactAssessmentsPDF Action = "exportTransferImpactAssessmentsPDF"
+ ActionExportFramework Action = "exportFramework"
+ ActionGenerateDocumentChangelog Action = "generateDocumentChangelog"
+ ActionGenerateFrameworkStateOfApplicability Action = "generateFrameworkStateOfApplicability"
+ ActionImportFramework Action = "importFramework"
+ ActionImportMeasure Action = "importMeasure"
+ ActionInitiateDomainVerification Action = "initiateDomainVerification"
+ ActionInviteUser Action = "inviteUser"
+ ActionPublishDocumentVersion Action = "publishDocumentVersion"
+ ActionRemoveMember Action = "removeMember"
+ ActionRequestSignature Action = "requestSignature"
+ ActionSendSigningNotifications Action = "sendSigningNotifications"
+ ActionUnassignTask Action = "unassignTask"
+ ActionUploadAuditReport Action = "uploadAuditReport"
+ ActionUploadMeasureEvidence Action = "uploadMeasureEvidence"
+ ActionUploadTrustCenterNDA Action = "uploadTrustCenterNDA"
+ ActionUploadVendorBusinessAssociateAgreement Action = "uploadVendorBusinessAssociateAgreement"
+ ActionUploadVendorComplianceReport Action = "uploadVendorComplianceReport"
+ ActionUploadVendorDataPrivacyAgreement Action = "uploadVendorDataPrivacyAgreement"
+ ActionVerifyDomain Action = "verifyDomain"
)
var (
@@ -287,27 +290,30 @@ var Permissions = map[uint16]map[Action][]Role{
ActionListSignableDocuments: InternalRoles,
- ActionListDocuments: NonEmployeeRoles,
- ActionGetHorizontalLogoUrl: NonEmployeeRoles,
- ActionPeoples: NonEmployeeRoles,
- ActionTotalCount: NonEmployeeRoles,
- ActionListFrameworks: NonEmployeeRoles,
- ActionListControls: NonEmployeeRoles,
- ActionListVendors: NonEmployeeRoles,
- ActionListPeople: NonEmployeeRoles,
- ActionListMeasures: NonEmployeeRoles,
- ActionListRisks: NonEmployeeRoles,
- ActionListAssets: NonEmployeeRoles,
- ActionListData: NonEmployeeRoles,
- ActionListAudits: NonEmployeeRoles,
- ActionListNonconformities: NonEmployeeRoles,
- ActionListObligations: NonEmployeeRoles,
- ActionListContinualImprovements: NonEmployeeRoles,
- ActionListRightsRequests: NonEmployeeRoles,
- ActionListProcessingActivities: NonEmployeeRoles,
- ActionListSnapshots: NonEmployeeRoles,
- ActionConfirmEmail: NonEmployeeRoles,
- ActionAcceptInvitation: NonEmployeeRoles,
+ ActionListDocuments: NonEmployeeRoles,
+ ActionGetHorizontalLogoUrl: NonEmployeeRoles,
+ ActionPeoples: NonEmployeeRoles,
+ ActionTotalCount: NonEmployeeRoles,
+ ActionListFrameworks: NonEmployeeRoles,
+ ActionListControls: NonEmployeeRoles,
+ ActionListVendors: NonEmployeeRoles,
+ ActionListPeople: NonEmployeeRoles,
+ ActionListMeasures: NonEmployeeRoles,
+ ActionListRisks: NonEmployeeRoles,
+ ActionListAssets: NonEmployeeRoles,
+ ActionListData: NonEmployeeRoles,
+ ActionListAudits: NonEmployeeRoles,
+ ActionListNonconformities: NonEmployeeRoles,
+ ActionListObligations: NonEmployeeRoles,
+ ActionListContinualImprovements: NonEmployeeRoles,
+ ActionListRightsRequests: NonEmployeeRoles,
+ ActionListProcessingActivities: NonEmployeeRoles,
+ ActionExportProcessingActivitiesPDF: NonEmployeeRoles,
+ ActionExportDataProtectionImpactAssessmentsPDF: NonEmployeeRoles,
+ ActionExportTransferImpactAssessmentsPDF: NonEmployeeRoles,
+ ActionListSnapshots: NonEmployeeRoles,
+ ActionConfirmEmail: NonEmployeeRoles,
+ ActionAcceptInvitation: NonEmployeeRoles,
ActionListTrustCenterFiles: CoreRoles,
ActionGetTrustCenter: CoreRoles,
@@ -694,6 +700,7 @@ var Permissions = map[uint16]map[Action][]Role{
ActionGetDataProtectionOfficer: NonEmployeeRoles,
ActionGetDataProtectionImpactAssessment: NonEmployeeRoles,
ActionGetTransferImpactAssessment: NonEmployeeRoles,
+ ActionExportProcessingActivitiesPDF: NonEmployeeRoles,
ActionUpdateProcessingActivity: EditRoles,
ActionDeleteProcessingActivity: EditRoles,
diff --git a/pkg/coredata/data_protection_impact_assessment.go b/pkg/coredata/data_protection_impact_assessment.go
index aa29d13db..e46532430 100644
--- a/pkg/coredata/data_protection_impact_assessment.go
+++ b/pkg/coredata/data_protection_impact_assessment.go
@@ -35,6 +35,12 @@ func (e ErrDataProtectionImpactAssessmentNotFound) Error() string {
return fmt.Sprintf("data protection impact assessment not found: %q", e.Identifier)
}
+type ErrNoDataProtectionImpactAssessmentsFound struct{}
+
+func (e ErrNoDataProtectionImpactAssessmentsFound) Error() string {
+ return "no data protection impact assessments found"
+}
+
type (
DataProtectionImpactAssessment struct {
ID gid.GID `db:"id"`
@@ -151,6 +157,56 @@ WHERE
return nil
}
+func (dpias *DataProtectionImpactAssessments) LoadAllByOrganizationID(
+ ctx context.Context,
+ conn pg.Conn,
+ scope Scoper,
+ organizationID gid.GID,
+ filter *DataProtectionImpactAssessmentFilter,
+) error {
+ q := `
+SELECT
+ id,
+ snapshot_id,
+ source_id,
+ organization_id,
+ processing_activity_id,
+ description,
+ necessity_and_proportionality,
+ potential_risk,
+ mitigations,
+ residual_risk,
+ created_at,
+ updated_at
+FROM
+ processing_activity_data_protection_impact_assessments
+WHERE
+ %s
+ AND organization_id = @organization_id
+ AND %s
+`
+
+ q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment())
+
+ args := pgx.StrictNamedArgs{"organization_id": organizationID}
+ maps.Copy(args, scope.SQLArguments())
+ maps.Copy(args, filter.SQLArguments())
+
+ rows, err := conn.Query(ctx, q, args)
+ if err != nil {
+ return fmt.Errorf("cannot query data protection impact assessments: %w", err)
+ }
+
+ results, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[DataProtectionImpactAssessment])
+ if err != nil {
+ return fmt.Errorf("cannot collect data protection impact assessments: %w", err)
+ }
+
+ *dpias = results
+
+ return nil
+}
+
func (dpia *DataProtectionImpactAssessment) LoadByID(
ctx context.Context,
conn pg.Conn,
@@ -429,4 +485,3 @@ WHERE dpia.tenant_id = @tenant_id AND dpia.organization_id = @organization_id AN
return nil
}
-
diff --git a/pkg/coredata/data_protection_impact_assessment_filter.go b/pkg/coredata/data_protection_impact_assessment_filter.go
index e22a6ef42..b1ff88b13 100644
--- a/pkg/coredata/data_protection_impact_assessment_filter.go
+++ b/pkg/coredata/data_protection_impact_assessment_filter.go
@@ -53,3 +53,9 @@ func (f *DataProtectionImpactAssessmentFilter) SQLFragment() string {
}
}
+func (f *DataProtectionImpactAssessmentFilter) SnapshotID() *gid.GID {
+ if f.snapshotID == nil || *f.snapshotID == nil {
+ return nil
+ }
+ return *f.snapshotID
+}
diff --git a/pkg/coredata/processing_activities.go b/pkg/coredata/processing_activities.go
index 7ee37f75d..64ef6f0a2 100644
--- a/pkg/coredata/processing_activities.go
+++ b/pkg/coredata/processing_activities.go
@@ -26,6 +26,12 @@ import (
"go.probo.inc/probo/pkg/page"
)
+type ErrNoProcessingActivitiesFound struct{}
+
+func (e ErrNoProcessingActivitiesFound) Error() string {
+ return "no processing activities found"
+}
+
type (
ProcessingActivity struct {
ID gid.GID `db:"id"`
@@ -231,6 +237,70 @@ WHERE
return nil
}
+func (p *ProcessingActivities) LoadAllByOrganizationID(
+ ctx context.Context,
+ conn pg.Conn,
+ scope Scoper,
+ organizationID gid.GID,
+ filter *ProcessingActivityFilter,
+) error {
+ q := `
+SELECT
+ id,
+ snapshot_id,
+ source_id,
+ organization_id,
+ name,
+ purpose,
+ data_subject_category,
+ personal_data_category,
+ special_or_criminal_data,
+ consent_evidence_link,
+ lawful_basis,
+ recipients,
+ location,
+ international_transfers,
+ transfer_safeguards,
+ retention_period,
+ security_measures,
+ data_protection_impact_assessment_needed,
+ transfer_impact_assessment_needed,
+ last_review_date,
+ next_review_date,
+ role,
+ data_protection_officer_id,
+ created_at,
+ updated_at
+FROM
+ processing_activities
+WHERE
+ %s
+ AND organization_id = @organization_id
+ AND %s
+ORDER BY created_at DESC
+`
+
+ q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment())
+
+ args := pgx.StrictNamedArgs{"organization_id": organizationID}
+ maps.Copy(args, scope.SQLArguments())
+ maps.Copy(args, filter.SQLArguments())
+
+ rows, err := conn.Query(ctx, q, args)
+ if err != nil {
+ return fmt.Errorf("cannot query processing activities: %w", err)
+ }
+
+ processingActivities, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[ProcessingActivity])
+ if err != nil {
+ return fmt.Errorf("cannot collect processing activities: %w", err)
+ }
+
+ *p = processingActivities
+
+ return nil
+}
+
func (p *ProcessingActivity) Insert(
ctx context.Context,
conn pg.Conn,
diff --git a/pkg/coredata/processing_activity_filter.go b/pkg/coredata/processing_activity_filter.go
index df6b5c123..688d715e1 100644
--- a/pkg/coredata/processing_activity_filter.go
+++ b/pkg/coredata/processing_activity_filter.go
@@ -52,3 +52,10 @@ func (f *ProcessingActivityFilter) SQLFragment() string {
return "snapshot_id = @filter_snapshot_id"
}
}
+
+func (f *ProcessingActivityFilter) SnapshotID() *gid.GID {
+ if f.snapshotID == nil || *f.snapshotID == nil {
+ return nil
+ }
+ return *f.snapshotID
+}
diff --git a/pkg/coredata/snapshot.go b/pkg/coredata/snapshot.go
index eb8848ab1..37bf88b9e 100644
--- a/pkg/coredata/snapshot.go
+++ b/pkg/coredata/snapshot.go
@@ -20,10 +20,10 @@ import (
"maps"
"time"
- "go.probo.inc/probo/pkg/gid"
- "go.probo.inc/probo/pkg/page"
"github.com/jackc/pgx/v5"
"go.gearno.de/kit/pg"
+ "go.probo.inc/probo/pkg/gid"
+ "go.probo.inc/probo/pkg/page"
)
type (
@@ -99,6 +99,7 @@ func (s *Snapshots) CountByOrganizationID(
conn pg.Conn,
scope Scoper,
organizationID gid.GID,
+ filter *SnapshotFilter,
) (int, error) {
q := `
SELECT
@@ -108,12 +109,14 @@ FROM
WHERE
%s
AND organization_id = @organization_id
+ AND %s
`
- q = fmt.Sprintf(q, scope.SQLFragment())
+ q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment())
args := pgx.StrictNamedArgs{"organization_id": organizationID}
maps.Copy(args, scope.SQLArguments())
+ maps.Copy(args, filter.SQLArguments())
row := conn.QueryRow(ctx, q, args)
diff --git a/pkg/coredata/snapshot_filter.go b/pkg/coredata/snapshot_filter.go
new file mode 100644
index 000000000..04afb99ce
--- /dev/null
+++ b/pkg/coredata/snapshot_filter.go
@@ -0,0 +1,65 @@
+// Copyright (c) 2025 Probo Inc .
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+package coredata
+
+import (
+ "time"
+
+ "github.com/jackc/pgx/v5"
+)
+
+type (
+ SnapshotFilter struct {
+ snapshotType *SnapshotsType
+ beforeDate *time.Time
+ }
+)
+
+func NewSnapshotFilter(snapshotType *SnapshotsType) *SnapshotFilter {
+ return &SnapshotFilter{
+ snapshotType: snapshotType,
+ }
+}
+
+func (f *SnapshotFilter) WithBeforeDate(beforeDate *time.Time) *SnapshotFilter {
+ f.beforeDate = beforeDate
+ return f
+}
+
+func (f *SnapshotFilter) SQLArguments() pgx.NamedArgs {
+ args := pgx.NamedArgs{
+ "filter_snapshot_type": f.snapshotType,
+ "filter_before_date": f.beforeDate,
+ }
+
+ return args
+}
+
+func (f *SnapshotFilter) SQLFragment() string {
+ return `
+(
+ CASE
+ WHEN @filter_snapshot_type::snapshots_type IS NOT NULL THEN
+ type = @filter_snapshot_type::snapshots_type
+ ELSE TRUE
+ END
+ AND
+ CASE
+ WHEN @filter_before_date::timestamptz IS NOT NULL THEN
+ created_at <= @filter_before_date::timestamptz
+ ELSE TRUE
+ END
+)`
+}
diff --git a/pkg/coredata/transfer_impact_assessment.go b/pkg/coredata/transfer_impact_assessment.go
index 2d890fa86..f60aa6bb2 100644
--- a/pkg/coredata/transfer_impact_assessment.go
+++ b/pkg/coredata/transfer_impact_assessment.go
@@ -35,6 +35,12 @@ func (e ErrTransferImpactAssessmentNotFound) Error() string {
return fmt.Sprintf("transfer impact assessment not found: %q", e.Identifier)
}
+type ErrNoTransferImpactAssessmentsFound struct{}
+
+func (e ErrNoTransferImpactAssessmentsFound) Error() string {
+ return "no transfer impact assessments found"
+}
+
type (
TransferImpactAssessment struct {
ID gid.GID `db:"id"`
@@ -151,6 +157,56 @@ WHERE
return nil
}
+func (tias *TransferImpactAssessments) LoadAllByOrganizationID(
+ ctx context.Context,
+ conn pg.Conn,
+ scope Scoper,
+ organizationID gid.GID,
+ filter *TransferImpactAssessmentFilter,
+) error {
+ q := `
+SELECT
+ id,
+ snapshot_id,
+ source_id,
+ organization_id,
+ processing_activity_id,
+ data_subjects,
+ legal_mechanism,
+ transfer,
+ local_law_risk,
+ supplementary_measures,
+ created_at,
+ updated_at
+FROM
+ processing_activity_transfer_impact_assessments
+WHERE
+ %s
+ AND organization_id = @organization_id
+ AND %s
+`
+
+ q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment())
+
+ args := pgx.StrictNamedArgs{"organization_id": organizationID}
+ maps.Copy(args, scope.SQLArguments())
+ maps.Copy(args, filter.SQLArguments())
+
+ rows, err := conn.Query(ctx, q, args)
+ if err != nil {
+ return fmt.Errorf("cannot query transfer impact assessments: %w", err)
+ }
+
+ results, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[TransferImpactAssessment])
+ if err != nil {
+ return fmt.Errorf("cannot collect transfer impact assessments: %w", err)
+ }
+
+ *tias = results
+
+ return nil
+}
+
func (tia *TransferImpactAssessment) LoadByID(
ctx context.Context,
conn pg.Conn,
@@ -429,4 +485,3 @@ WHERE tia.tenant_id = @tenant_id AND tia.organization_id = @organization_id AND
return nil
}
-
diff --git a/pkg/coredata/transfer_impact_assessment_filter.go b/pkg/coredata/transfer_impact_assessment_filter.go
index 23872839e..aa78d49b6 100644
--- a/pkg/coredata/transfer_impact_assessment_filter.go
+++ b/pkg/coredata/transfer_impact_assessment_filter.go
@@ -53,3 +53,9 @@ func (f *TransferImpactAssessmentFilter) SQLFragment() string {
}
}
+func (f *TransferImpactAssessmentFilter) SnapshotID() *gid.GID {
+ if f.snapshotID == nil || *f.snapshotID == nil {
+ return nil
+ }
+ return *f.snapshotID
+}
diff --git a/pkg/coredata/vendor.go b/pkg/coredata/vendor.go
index b948a4331..92464679e 100644
--- a/pkg/coredata/vendor.go
+++ b/pkg/coredata/vendor.go
@@ -21,10 +21,10 @@ import (
"maps"
"time"
- "go.probo.inc/probo/pkg/gid"
- "go.probo.inc/probo/pkg/page"
"github.com/jackc/pgx/v5"
"go.gearno.de/kit/pg"
+ "go.probo.inc/probo/pkg/gid"
+ "go.probo.inc/probo/pkg/page"
)
type (
@@ -850,6 +850,74 @@ WHERE %s
return nil
}
+func (v *Vendors) LoadAllByProcessingActivities(
+ ctx context.Context,
+ conn pg.Conn,
+ scope Scoper,
+ organizationID gid.GID,
+ filter *ProcessingActivityFilter,
+) (map[gid.GID][]string, error) {
+ q := `
+WITH filtered_processing_activities AS (
+ SELECT
+ pa.id
+ FROM
+ processing_activities pa
+ WHERE
+ pa.tenant_id = @tenant_id
+ AND pa.organization_id = @organization_id
+ AND %s
+),
+filtered_vendors AS (
+ SELECT
+ v.id,
+ v.name
+ FROM
+ vendors v
+ WHERE
+ v.tenant_id = @tenant_id
+)
+SELECT
+ pav.processing_activity_id,
+ fv.name
+FROM
+ processing_activity_vendors pav
+INNER JOIN
+ filtered_vendors fv ON fv.id = pav.vendor_id
+INNER JOIN
+ filtered_processing_activities fpa ON fpa.id = pav.processing_activity_id
+WHERE
+ pav.tenant_id = @tenant_id
+ORDER BY
+ pav.processing_activity_id, fv.name
+ `
+ q = fmt.Sprintf(q, filter.SQLFragment())
+
+ args := pgx.StrictNamedArgs{
+ "organization_id": organizationID,
+ }
+ maps.Copy(args, scope.SQLArguments())
+ maps.Copy(args, filter.SQLArguments())
+
+ rows, err := conn.Query(ctx, q, args)
+ if err != nil {
+ return nil, fmt.Errorf("cannot query vendors: %w", err)
+ }
+ defer rows.Close()
+
+ vendorMap := make(map[gid.GID][]string)
+ for rows.Next() {
+ var processingActivityID gid.GID
+ var vendorName string
+ if err := rows.Scan(&processingActivityID, &vendorName); err != nil {
+ return nil, fmt.Errorf("cannot scan vendor: %w", err)
+ }
+ vendorMap[processingActivityID] = append(vendorMap[processingActivityID], vendorName)
+ }
+
+ return vendorMap, nil
+}
+
func (d Vendors) InsertDataSnapshots(
ctx context.Context,
conn pg.Conn,
diff --git a/pkg/docgen/data_protection_impact_assessments_template.html b/pkg/docgen/data_protection_impact_assessments_template.html
new file mode 100644
index 000000000..fb8557bc9
--- /dev/null
+++ b/pkg/docgen/data_protection_impact_assessments_template.html
@@ -0,0 +1,315 @@
+
+
+
+
+
+ Data Protection Impact Assessments Export
+
+
+
+
+
+
+
Data Protection Impact Assessments
+
+
+
+
+
1. Purpose
+
+ This document contains Data Protection Impact Assessments (DPIAs) conducted for processing activities
+ that present a high risk to individuals' rights and freedoms. DPIAs are systematic assessments that
+ evaluate the necessity, proportionality, and risks associated with data processing operations, along
+ with the measures implemented to mitigate identified risks.
+
+
+
+
+ {{- range $index, $assessment := .Assessments}}
+
+ {{if eq $index 0}}
+
2. Records
+ {{end}}
+
2.{{add $index 1}} {{$assessment.ProcessingActivityName}}
+
+
+
Description
+
{{if .Description}}{{.Description}}{{else}}Not specified{{end}}
+
+
+
+
Necessity and Proportionality
+
{{if .NecessityAndProportionality}}{{.NecessityAndProportionality}}{{else}}Not specified{{end}}
+
+
+
+
Potential Risk
+
{{if .PotentialRisk}}{{.PotentialRisk}}{{else}}Not specified{{end}}
+
+
+
+
Mitigations
+
{{if .Mitigations}}{{.Mitigations}}{{else}}Not specified{{end}}
+
+
+
+
Residual Risk
+
{{if .ResidualRisk}}{{.ResidualRisk | formatResidualRisk}}{{else}}Not specified{{end}}
+
+
+ {{- end}}
+
+
+
3. Annexes
+
+
+
+
+
Residual Risk
+
+ -
+ Low:
+ The residual risk after implementing mitigation measures is considered low. The processing activity poses minimal risk to individuals' rights and freedoms.
+
+ -
+ Medium:
+ The residual risk after implementing mitigation measures is considered medium. The processing activity poses a moderate risk to individuals' rights and freedoms, requiring ongoing monitoring.
+
+ -
+ High:
+ The residual risk after implementing mitigation measures is considered high. The processing activity poses significant risk to individuals' rights and freedoms, requiring enhanced safeguards and regular review.
+
+
+
+
+
+
diff --git a/pkg/docgen/generator.go b/pkg/docgen/generator.go
index 371a14fa6..dbb4543b4 100644
--- a/pkg/docgen/generator.go
+++ b/pkg/docgen/generator.go
@@ -23,21 +23,36 @@ import (
"strings"
"time"
- "go.probo.inc/probo/pkg/coredata"
"github.com/yuin/goldmark"
"github.com/yuin/goldmark/extension"
gmhtml "github.com/yuin/goldmark/renderer/html"
+ "go.probo.inc/probo/pkg/coredata"
+)
+
+const (
+ firstPageTOCItems = 21
+ otherPageTOCItems = 28
)
var (
//go:embed template.html
htmlTemplateContent string
+ //go:embed processing_activities_template.html
+ processingActivitiesTemplateContent string
+
+ //go:embed data_protection_impact_assessments_template.html
+ dataProtectionImpactAssessmentsTemplateContent string
+
+ //go:embed transfer_impact_assessments_template.html
+ transferImpactAssessmentsTemplateContent string
+
templateFuncs = template.FuncMap{
"now": func() time.Time { return time.Now() },
- "eq": func(a, b string) bool { return a == b },
+ "eq": func(a, b any) bool { return a == b },
"string": func(v fmt.Stringer) string { return v.String() },
"lower": func(s string) string { return strings.ToLower(s) },
+ "add": func(a, b int) int { return a + b },
"classificationString": func(c Classification) string { return string(c) },
"formatContent": func(content string) template.HTML {
md := goldmark.New(
@@ -56,9 +71,111 @@ var (
"imgTag": func(src, alt, class string) template.HTML {
return template.HTML(fmt.Sprintf(`
`, html.EscapeString(src), html.EscapeString(alt), html.EscapeString(class)))
},
+ "formatLawfulBasis": func(basis coredata.ProcessingActivityLawfulBasis) string {
+ switch basis {
+ case coredata.ProcessingActivityLawfulBasisConsent:
+ return "Consent"
+ case coredata.ProcessingActivityLawfulBasisContractualNecessity:
+ return "Contractual Necessity"
+ case coredata.ProcessingActivityLawfulBasisLegalObligation:
+ return "Legal Obligation"
+ case coredata.ProcessingActivityLawfulBasisLegitimateInterest:
+ return "Legitimate Interest"
+ case coredata.ProcessingActivityLawfulBasisPublicTask:
+ return "Public Task"
+ case coredata.ProcessingActivityLawfulBasisVitalInterests:
+ return "Vital Interests"
+ default:
+ return basis.String()
+ }
+ },
+ "formatSpecialOrCriminalData": func(data coredata.ProcessingActivitySpecialOrCriminalDatum) string {
+ switch data {
+ case coredata.ProcessingActivitySpecialOrCriminalDatumYes:
+ return "Yes"
+ case coredata.ProcessingActivitySpecialOrCriminalDatumNo:
+ return "No"
+ case coredata.ProcessingActivitySpecialOrCriminalDatumPossible:
+ return "Possible"
+ default:
+ return data.String()
+ }
+ },
+ "formatTransferSafeguard": func(safeguard *coredata.ProcessingActivityTransferSafeguard) string {
+ if safeguard == nil {
+ return ""
+ }
+ switch *safeguard {
+ case coredata.ProcessingActivityTransferSafeguardStandardContractualClauses:
+ return "Standard Contractual Clauses"
+ case coredata.ProcessingActivityTransferSafeguardBindingCorporateRules:
+ return "Binding Corporate Rules"
+ case coredata.ProcessingActivityTransferSafeguardAdequacyDecision:
+ return "Adequacy Decision"
+ case coredata.ProcessingActivityTransferSafeguardDerogations:
+ return "Derogations"
+ case coredata.ProcessingActivityTransferSafeguardCodesOfConduct:
+ return "Codes of Conduct"
+ case coredata.ProcessingActivityTransferSafeguardCertificationMechanisms:
+ return "Certification Mechanisms"
+ default:
+ return safeguard.String()
+ }
+ },
+ "formatDPIANeeded": func(needed coredata.ProcessingActivityDataProtectionImpactAssessment) string {
+ switch needed {
+ case coredata.ProcessingActivityDataProtectionImpactAssessmentNeeded:
+ return "Yes"
+ case coredata.ProcessingActivityDataProtectionImpactAssessmentNotNeeded:
+ return "No"
+ default:
+ return needed.String()
+ }
+ },
+ "formatTIANeeded": func(needed coredata.ProcessingActivityTransferImpactAssessment) string {
+ switch needed {
+ case coredata.ProcessingActivityTransferImpactAssessmentNeeded:
+ return "Yes"
+ case coredata.ProcessingActivityTransferImpactAssessmentNotNeeded:
+ return "No"
+ default:
+ return needed.String()
+ }
+ },
+ "formatRole": func(role coredata.ProcessingActivityRole) string {
+ switch role {
+ case coredata.ProcessingActivityRoleController:
+ return "Controller"
+ case coredata.ProcessingActivityRoleProcessor:
+ return "Processor"
+ default:
+ return role.String()
+ }
+ },
+ "formatResidualRisk": func(risk *coredata.DataProtectionImpactAssessmentResidualRisk) string {
+ if risk == nil {
+ return ""
+ }
+ switch *risk {
+ case coredata.DataProtectionImpactAssessmentResidualRiskLow:
+ return "Low"
+ case coredata.DataProtectionImpactAssessmentResidualRiskMedium:
+ return "Medium"
+ case coredata.DataProtectionImpactAssessmentResidualRiskHigh:
+ return "High"
+ default:
+ return risk.String()
+ }
+ },
}
documentTemplate = template.Must(template.New("document").Funcs(templateFuncs).Parse(htmlTemplateContent))
+
+ processingActivitiesTemplate = template.Must(template.New("processingActivities").Funcs(templateFuncs).Parse(processingActivitiesTemplateContent))
+
+ dataProtectionImpactAssessmentsTemplate = template.Must(template.New("dataProtectionImpactAssessments").Funcs(templateFuncs).Parse(dataProtectionImpactAssessmentsTemplateContent))
+
+ transferImpactAssessmentsTemplate = template.Must(template.New("transferImpactAssessments").Funcs(templateFuncs).Parse(transferImpactAssessmentsTemplateContent))
)
type (
@@ -82,6 +199,71 @@ type (
State coredata.DocumentVersionSignatureState
RequestedAt time.Time
}
+
+ ProcessingActivityTableData struct {
+ CompanyName string
+ CompanyHorizontalLogoBase64 string
+ Version int
+ PublishedAt time.Time
+ Activities []ProcessingActivityRowData
+ }
+
+ ProcessingActivityRowData struct {
+ Name string
+ Purpose *string
+ DataSubjectCategory *string
+ PersonalDataCategory *string
+ SpecialOrCriminalData coredata.ProcessingActivitySpecialOrCriminalDatum
+ ConsentEvidenceLink *string
+ LawfulBasis coredata.ProcessingActivityLawfulBasis
+ Recipients *string
+ Location *string
+ InternationalTransfers bool
+ TransferSafeguards *coredata.ProcessingActivityTransferSafeguard
+ RetentionPeriod *string
+ SecurityMeasures *string
+ DataProtectionImpactAssessmentNeeded coredata.ProcessingActivityDataProtectionImpactAssessment
+ TransferImpactAssessmentNeeded coredata.ProcessingActivityTransferImpactAssessment
+ LastReviewDate *time.Time
+ NextReviewDate *time.Time
+ Role coredata.ProcessingActivityRole
+ DataProtectionOfficerFullName *string
+ Vendors string
+ }
+
+ DataProtectionImpactAssessmentTableData struct {
+ CompanyName string
+ CompanyHorizontalLogoBase64 string
+ Version int
+ PublishedAt time.Time
+ Assessments []DataProtectionImpactAssessmentRowData
+ }
+
+ DataProtectionImpactAssessmentRowData struct {
+ ProcessingActivityName string
+ Description *string
+ NecessityAndProportionality *string
+ PotentialRisk *string
+ Mitigations *string
+ ResidualRisk *coredata.DataProtectionImpactAssessmentResidualRisk
+ }
+
+ TransferImpactAssessmentTableData struct {
+ CompanyName string
+ CompanyHorizontalLogoBase64 string
+ Version int
+ PublishedAt time.Time
+ Assessments []TransferImpactAssessmentRowData
+ }
+
+ TransferImpactAssessmentRowData struct {
+ ProcessingActivityName string
+ DataSubjects *string
+ LegalMechanism *string
+ Transfer *string
+ LocalLawRisk *string
+ SupplementaryMeasures *string
+ }
)
const (
@@ -99,3 +281,30 @@ func RenderHTML(data DocumentData) ([]byte, error) {
return buf.Bytes(), nil
}
+
+func RenderProcessingActivitiesTableHTML(data ProcessingActivityTableData) ([]byte, error) {
+ var buf bytes.Buffer
+ if err := processingActivitiesTemplate.Execute(&buf, data); err != nil {
+ return nil, fmt.Errorf("cannot execute processing activities template: %w", err)
+ }
+
+ return buf.Bytes(), nil
+}
+
+func RenderDataProtectionImpactAssessmentsTableHTML(data DataProtectionImpactAssessmentTableData) ([]byte, error) {
+ var buf bytes.Buffer
+ if err := dataProtectionImpactAssessmentsTemplate.Execute(&buf, data); err != nil {
+ return nil, fmt.Errorf("cannot execute data protection impact assessments template: %w", err)
+ }
+
+ return buf.Bytes(), nil
+}
+
+func RenderTransferImpactAssessmentsTableHTML(data TransferImpactAssessmentTableData) ([]byte, error) {
+ var buf bytes.Buffer
+ if err := transferImpactAssessmentsTemplate.Execute(&buf, data); err != nil {
+ return nil, fmt.Errorf("cannot execute transfer impact assessments template: %w", err)
+ }
+
+ return buf.Bytes(), nil
+}
diff --git a/pkg/docgen/generator_test.go b/pkg/docgen/generator_test.go
index b05f6458b..592f4a5f7 100644
--- a/pkg/docgen/generator_test.go
+++ b/pkg/docgen/generator_test.go
@@ -195,7 +195,7 @@ func TestTemplateFunctions(t *testing.T) {
})
t.Run("eq function", func(t *testing.T) {
- eqFunc := templateFuncs["eq"].(func(string, string) bool)
+ eqFunc := templateFuncs["eq"].(func(any, any) bool)
assert.True(t, eqFunc("test", "test"))
assert.False(t, eqFunc("test", "other"))
})
@@ -266,7 +266,7 @@ func TestHTMLEscaping(t *testing.T) {
resultStr := string(result)
- // Verify dangerous content is escaped
+ // Verify dangerous content is escaped
assert.NotContains(t, resultStr, "")
assert.NotContains(t, resultStr, "tag")
assert.Contains(t, resultStr, "<script>")
diff --git a/pkg/docgen/processing_activities_template.html b/pkg/docgen/processing_activities_template.html
new file mode 100644
index 000000000..7bd07f0e4
--- /dev/null
+++ b/pkg/docgen/processing_activities_template.html
@@ -0,0 +1,535 @@
+
+
+
+
+
+ Processing Activities Export
+
+
+
+
+
+
+
Processing Activities
+
+
+
+
+
1. Purpose
+
+ This document provides a comprehensive overview of all processing activities within the organization.
+ It serves as a record of personal data processing operations, documenting the purposes, legal bases,
+ data categories, and associated safeguards for each activity.
+
+
+
+
+ {{- range $index, $activity := .Activities}}
+
+ {{if eq $index 0}}
+
2. Records
+ {{end}}
+
2.{{add $index 1}} {{$activity.Name}}
+
+
+
2.{{add $index 1}}.1 General Information
+
+
Purpose
+
{{if .Purpose}}{{.Purpose}}{{else}}Not specified{{end}}
+
+
+
+
Role
+
{{.Role | formatRole}}
+
+
+
+
+
+
2.{{add $index 1}}.2 Data Categories
+
+
+
Data Subject Category
+
{{if .DataSubjectCategory}}{{.DataSubjectCategory}}{{else}}Not specified{{end}}
+
+
+
Personal Data Category
+
{{if .PersonalDataCategory}}{{.PersonalDataCategory}}{{else}}Not specified{{end}}
+
+
+
Special/Criminal Data
+
{{.SpecialOrCriminalData | formatSpecialOrCriminalData}}
+
+
+
+
+
+
2.{{add $index 1}}.3 Legal Basis
+
+
+
Lawful Basis
+
{{.LawfulBasis | formatLawfulBasis}}
+
+
+
Consent Evidence Link
+
{{if .ConsentEvidenceLink}}{{.ConsentEvidenceLink}}{{else}}Not specified{{end}}
+
+
+
+
+
+
2.{{add $index 1}}.4 Data Sharing & Transfers
+
+
+
Recipients
+
{{if .Recipients}}{{.Recipients}}{{else}}Not specified{{end}}
+
+
+
Location
+
{{if .Location}}{{.Location}}{{else}}Not specified{{end}}
+
+
+
International Transfers
+
{{if .InternationalTransfers}}Yes{{else}}No{{end}}
+
+
+
Transfer Safeguards
+
{{if .TransferSafeguards}}{{.TransferSafeguards | formatTransferSafeguard}}{{else}}Not specified{{end}}
+
+
+
+
+
+
2.{{add $index 1}}.5 Retention & Security
+
+
+
Retention Period
+
{{if .RetentionPeriod}}{{.RetentionPeriod}}{{else}}Not specified{{end}}
+
+
+
+
Security Measures
+
{{if .SecurityMeasures}}{{.SecurityMeasures}}{{else}}Not specified{{end}}
+
+
+
+
+
2.{{add $index 1}}.6 Assessments & Reviews
+
+
+
DPIA Needed
+
{{.DataProtectionImpactAssessmentNeeded | formatDPIANeeded}}
+
+
+
TIA Needed
+
{{.TransferImpactAssessmentNeeded | formatTIANeeded}}
+
+
+
Last Review Date
+
{{if .LastReviewDate}}{{.LastReviewDate.Format "January 2, 2006"}}{{else}}Not specified{{end}}
+
+
+
Next Review Date
+
{{if .NextReviewDate}}{{.NextReviewDate.Format "January 2, 2006"}}{{else}}Not specified{{end}}
+
+
+
+
+
+
2.{{add $index 1}}.7 Responsible Parties
+
+
+
Data Protection Officer
+
{{if .DataProtectionOfficerFullName}}{{.DataProtectionOfficerFullName}}{{else}}Not assigned{{end}}
+
+
+
Vendors
+
{{if .Vendors}}{{.Vendors}}{{else}}None{{end}}
+
+
+
+
+ {{- end}}
+
+
+
3. Annexes
+
+
+
+
+
Role
+
+ -
+ Controller:
+ The entity that determines the purposes and means of processing personal data.
+
+ -
+ Processor:
+ The entity that processes personal data on behalf of the controller.
+
+
+
+
+
+
Lawful Basis
+
+ -
+ Consent:
+ The data subject has given consent to the processing of their personal data.
+
+ -
+ Contractual Necessity:
+ Processing is necessary for the performance of a contract to which the data subject is party.
+
+ -
+ Legal Obligation:
+ Processing is necessary for compliance with a legal obligation to which the controller is subject.
+
+ -
+ Legitimate Interest:
+ Processing is necessary for the purposes of the legitimate interests pursued by the controller or a third party.
+
+ -
+ Public Task:
+ Processing is necessary for the performance of a task carried out in the public interest or in the exercise of official authority.
+
+ -
+ Vital Interests:
+ Processing is necessary to protect the vital interests of the data subject or of another natural person.
+
+
+
+
+
+
Special/Criminal Data
+
+ -
+ Yes:
+ The processing activity involves special categories of personal data or data relating to criminal convictions and offences.
+
+ -
+ No:
+ The processing activity does not involve special categories of personal data or data relating to criminal convictions and offences.
+
+ -
+ Possible:
+ The processing activity may involve special categories of personal data or data relating to criminal convictions and offences.
+
+
+
+
+
+
Transfer Safeguards
+
+ -
+ Standard Contractual Clauses:
+ Standard contractual clauses approved by the European Commission are used to ensure adequate protection for international transfers.
+
+ -
+ Binding Corporate Rules:
+ Binding corporate rules approved by a supervisory authority are used to ensure adequate protection for international transfers.
+
+ -
+ Adequacy Decision:
+ The European Commission has determined that the third country ensures an adequate level of protection.
+
+ -
+ Derogations:
+ A derogation under Article 49 of the GDPR is used for the international transfer.
+
+ -
+ Codes of Conduct:
+ An approved code of conduct together with binding and enforceable commitments is used to ensure adequate protection.
+
+ -
+ Certification Mechanisms:
+ An approved certification mechanism together with binding and enforceable commitments is used to ensure adequate protection.
+
+
+
+
+
+
DPIA Needed
+
+ -
+ Yes:
+ A Data Protection Impact Assessment is required for this processing activity.
+
+ -
+ No:
+ A Data Protection Impact Assessment is not required for this processing activity.
+
+
+
+
+
+
TIA Needed
+
+ -
+ Yes:
+ A Transfer Impact Assessment is required for this processing activity.
+
+ -
+ No:
+ A Transfer Impact Assessment is not required for this processing activity.
+
+
+
+
+
+
diff --git a/pkg/docgen/transfer_impact_assessments_template.html b/pkg/docgen/transfer_impact_assessments_template.html
new file mode 100644
index 000000000..233db42f4
--- /dev/null
+++ b/pkg/docgen/transfer_impact_assessments_template.html
@@ -0,0 +1,288 @@
+
+
+
+
+
+ Transfer Impact Assessments Export
+
+
+
+
+
+
+
Transfer Impact Assessments
+
+
+
+
+
1. Purpose
+
+ This document contains Transfer Impact Assessments (TIAs) conducted for processing activities involving
+ international transfers of personal data to countries outside the European Economic Area (EEA). TIAs
+ evaluate the legal mechanisms used for transfers, assess risks related to local laws in destination
+ countries, and document supplementary measures implemented to ensure an adequate level of data protection.
+
+
+
+
+ {{- range $index, $assessment := .Assessments}}
+
+ {{if eq $index 0}}
+
2. Records
+ {{end}}
+
2.{{add $index 1}} {{$assessment.ProcessingActivityName}}
+
+
+
Data Subjects
+
{{if .DataSubjects}}{{.DataSubjects}}{{else}}Not specified{{end}}
+
+
+
+
Transfer
+
{{if .Transfer}}{{.Transfer}}{{else}}Not specified{{end}}
+
+
+
+
Legal Mechanism
+
{{if .LegalMechanism}}{{.LegalMechanism}}{{else}}Not specified{{end}}
+
+
+
+
Local Law Risk
+
{{if .LocalLawRisk}}{{.LocalLawRisk}}{{else}}Not specified{{end}}
+
+
+
+
Supplementary Measures
+
{{if .SupplementaryMeasures}}{{.SupplementaryMeasures}}{{else}}Not specified{{end}}
+
+
+ {{- end}}
+
+
diff --git a/pkg/probo/data_protection_impact_assessment_service.go b/pkg/probo/data_protection_impact_assessment_service.go
index e9efee3f2..e57810ca2 100644
--- a/pkg/probo/data_protection_impact_assessment_service.go
+++ b/pkg/probo/data_protection_impact_assessment_service.go
@@ -17,17 +17,21 @@ package probo
import (
"context"
"fmt"
+ "io"
"time"
"go.gearno.de/kit/pg"
"go.probo.inc/probo/pkg/coredata"
+ "go.probo.inc/probo/pkg/docgen"
"go.probo.inc/probo/pkg/gid"
+ "go.probo.inc/probo/pkg/html2pdf"
"go.probo.inc/probo/pkg/page"
"go.probo.inc/probo/pkg/validator"
)
type DataProtectionImpactAssessmentService struct {
- svc *TenantService
+ svc *TenantService
+ html2pdfConverter *html2pdf.Converter
}
type (
@@ -298,3 +302,130 @@ func (s *DataProtectionImpactAssessmentService) Delete(
return err
}
+func (s *DataProtectionImpactAssessmentService) ExportPDF(
+ ctx context.Context,
+ organizationID gid.GID,
+ filter *coredata.DataProtectionImpactAssessmentFilter,
+) ([]byte, error) {
+ var tableData docgen.DataProtectionImpactAssessmentTableData
+
+ err := s.svc.pg.WithTx(
+ ctx,
+ func(conn pg.Conn) error {
+ var assessments coredata.DataProtectionImpactAssessments
+ if err := assessments.LoadAllByOrganizationID(ctx, conn, s.svc.scope, organizationID, filter); err != nil {
+ return fmt.Errorf("cannot load data protection impact assessments: %w", err)
+ }
+
+ if len(assessments) == 0 {
+ return &coredata.ErrNoDataProtectionImpactAssessmentsFound{}
+ }
+
+ organization := &coredata.Organization{}
+ if err := organization.LoadByID(ctx, conn, s.svc.scope, organizationID); err != nil {
+ return fmt.Errorf("cannot load organization: %w", err)
+ }
+
+ horizontalLogoBase64 := ""
+ if organization.HorizontalLogoFileID != nil {
+ fileRecord := &coredata.File{}
+ fileErr := s.svc.pg.WithConn(ctx, func(conn pg.Conn) error {
+ return fileRecord.LoadByID(ctx, conn, s.svc.scope, *organization.HorizontalLogoFileID)
+ })
+ if fileErr == nil {
+ base64Data, mimeType, logoErr := s.svc.fileManager.GetFileBase64(ctx, fileRecord)
+ if logoErr == nil {
+ horizontalLogoBase64 = fmt.Sprintf("data:%s;base64,%s", mimeType, base64Data)
+ }
+ }
+ }
+
+ var snapshots coredata.Snapshots
+ snapshotType := coredata.SnapshotsTypeProcessingActivities
+
+ var version int
+ var publishedAt time.Time
+
+ if snapshotID := filter.SnapshotID(); snapshotID != nil {
+ snapshot := &coredata.Snapshot{}
+ if err := snapshot.LoadByID(ctx, conn, s.svc.scope, *snapshotID); err != nil {
+ return fmt.Errorf("cannot load snapshot: %w", err)
+ }
+ publishedAt = snapshot.CreatedAt
+ snapshotFilter := coredata.NewSnapshotFilter(&snapshotType).WithBeforeDate(&snapshot.CreatedAt)
+ snapshotCount, err := snapshots.CountByOrganizationID(ctx, conn, s.svc.scope, organizationID, snapshotFilter)
+ if err != nil {
+ return fmt.Errorf("cannot count processing activities snapshots: %w", err)
+ }
+ version = snapshotCount
+ } else {
+ publishedAt = time.Now()
+ snapshotFilter := coredata.NewSnapshotFilter(&snapshotType)
+ snapshotCount, err := snapshots.CountByOrganizationID(ctx, conn, s.svc.scope, organizationID, snapshotFilter)
+ if err != nil {
+ return fmt.Errorf("cannot count processing activities snapshots: %w", err)
+ }
+ version = snapshotCount + 1
+ }
+
+ assessmentRows := make([]docgen.DataProtectionImpactAssessmentRowData, len(assessments))
+ for i, assessment := range assessments {
+ processingActivity := &coredata.ProcessingActivity{}
+ if err := processingActivity.LoadByID(ctx, conn, s.svc.scope, assessment.ProcessingActivityID); err != nil {
+ return fmt.Errorf("cannot load processing activity: %w", err)
+ }
+
+ assessmentRows[i] = docgen.DataProtectionImpactAssessmentRowData{
+ ProcessingActivityName: processingActivity.Name,
+ Description: assessment.Description,
+ NecessityAndProportionality: assessment.NecessityAndProportionality,
+ PotentialRisk: assessment.PotentialRisk,
+ Mitigations: assessment.Mitigations,
+ ResidualRisk: assessment.ResidualRisk,
+ }
+ }
+
+ tableData = docgen.DataProtectionImpactAssessmentTableData{
+ CompanyName: organization.Name,
+ CompanyHorizontalLogoBase64: horizontalLogoBase64,
+ Version: version,
+ PublishedAt: publishedAt,
+ Assessments: assessmentRows,
+ }
+
+ return nil
+ },
+ )
+
+ if err != nil {
+ return nil, err
+ }
+
+ htmlContent, err := docgen.RenderDataProtectionImpactAssessmentsTableHTML(tableData)
+ if err != nil {
+ return nil, fmt.Errorf("cannot render HTML: %w", err)
+ }
+
+ cfg := html2pdf.RenderConfig{
+ PageFormat: html2pdf.PageFormatA4,
+ Orientation: html2pdf.OrientationPortrait,
+ MarginTop: html2pdf.NewMarginInches(0.98),
+ MarginBottom: html2pdf.NewMarginInches(0.98),
+ MarginLeft: html2pdf.NewMarginInches(0.98),
+ MarginRight: html2pdf.NewMarginInches(0.98),
+ PrintBackground: true,
+ Scale: 1.0,
+ }
+
+ pdfReader, err := s.html2pdfConverter.GeneratePDF(ctx, htmlContent, cfg)
+ if err != nil {
+ return nil, fmt.Errorf("cannot generate PDF: %w", err)
+ }
+
+ pdfData, err := io.ReadAll(pdfReader)
+ if err != nil {
+ return nil, fmt.Errorf("cannot read PDF data: %w", err)
+ }
+
+ return pdfData, nil
+}
diff --git a/pkg/probo/processing_activity_service.go b/pkg/probo/processing_activity_service.go
index dfdf480c0..584ac1914 100644
--- a/pkg/probo/processing_activity_service.go
+++ b/pkg/probo/processing_activity_service.go
@@ -17,17 +17,22 @@ package probo
import (
"context"
"fmt"
+ "io"
+ "strings"
"time"
"go.gearno.de/kit/pg"
"go.probo.inc/probo/pkg/coredata"
+ "go.probo.inc/probo/pkg/docgen"
"go.probo.inc/probo/pkg/gid"
+ "go.probo.inc/probo/pkg/html2pdf"
"go.probo.inc/probo/pkg/page"
"go.probo.inc/probo/pkg/validator"
)
type ProcessingActivityService struct {
- svc *TenantService
+ svc *TenantService
+ html2pdfConverter *html2pdf.Converter
}
type (
@@ -382,3 +387,159 @@ func (s ProcessingActivityService) CountForOrganizationID(
return count, nil
}
+
+func (s *ProcessingActivityService) ExportPDF(
+ ctx context.Context,
+ organizationID gid.GID,
+ filter *coredata.ProcessingActivityFilter,
+) ([]byte, error) {
+ var tableData docgen.ProcessingActivityTableData
+
+ err := s.svc.pg.WithTx(
+ ctx,
+ func(conn pg.Conn) error {
+ var processingActivities coredata.ProcessingActivities
+ if err := processingActivities.LoadAllByOrganizationID(ctx, conn, s.svc.scope, organizationID, filter); err != nil {
+ return fmt.Errorf("cannot load processing activities: %w", err)
+ }
+
+ if len(processingActivities) == 0 {
+ return &coredata.ErrNoProcessingActivitiesFound{}
+ }
+
+ organization := &coredata.Organization{}
+ if err := organization.LoadByID(ctx, conn, s.svc.scope, organizationID); err != nil {
+ return fmt.Errorf("cannot load organization: %w", err)
+ }
+
+ horizontalLogoBase64 := ""
+ if organization.HorizontalLogoFileID != nil {
+ fileRecord := &coredata.File{}
+ fileErr := s.svc.pg.WithConn(ctx, func(conn pg.Conn) error {
+ return fileRecord.LoadByID(ctx, conn, s.svc.scope, *organization.HorizontalLogoFileID)
+ })
+ if fileErr == nil {
+ base64Data, mimeType, logoErr := s.svc.fileManager.GetFileBase64(ctx, fileRecord)
+ if logoErr == nil {
+ horizontalLogoBase64 = fmt.Sprintf("data:%s;base64,%s", mimeType, base64Data)
+ }
+ }
+ }
+
+ var vendors coredata.Vendors
+ vendorMap, err := vendors.LoadAllByProcessingActivities(ctx, conn, s.svc.scope, organizationID, filter)
+ if err != nil {
+ return fmt.Errorf("cannot load vendors: %w", err)
+ }
+
+ var snapshots coredata.Snapshots
+ snapshotType := coredata.SnapshotsTypeProcessingActivities
+
+ var version int
+ var publishedAt time.Time
+
+ if snapshotID := filter.SnapshotID(); snapshotID != nil {
+ snapshot := &coredata.Snapshot{}
+ if err := snapshot.LoadByID(ctx, conn, s.svc.scope, *snapshotID); err != nil {
+ return fmt.Errorf("cannot load snapshot: %w", err)
+ }
+ publishedAt = snapshot.CreatedAt
+ snapshotFilter := coredata.NewSnapshotFilter(&snapshotType).WithBeforeDate(&snapshot.CreatedAt)
+ snapshotCount, err := snapshots.CountByOrganizationID(ctx, conn, s.svc.scope, organizationID, snapshotFilter)
+ if err != nil {
+ return fmt.Errorf("cannot count processing activities snapshots: %w", err)
+ }
+ version = snapshotCount
+ } else {
+ publishedAt = time.Now()
+ snapshotFilter := coredata.NewSnapshotFilter(&snapshotType)
+ snapshotCount, err := snapshots.CountByOrganizationID(ctx, conn, s.svc.scope, organizationID, snapshotFilter)
+ if err != nil {
+ return fmt.Errorf("cannot count processing activities snapshots: %w", err)
+ }
+ version = snapshotCount + 1
+ }
+
+ activities := make([]docgen.ProcessingActivityRowData, len(processingActivities))
+ for i, pa := range processingActivities {
+ dpoFullName := (*string)(nil)
+ if pa.DataProtectionOfficerID != nil {
+ dpo := &coredata.People{}
+ if err := dpo.LoadByID(ctx, conn, s.svc.scope, *pa.DataProtectionOfficerID); err == nil {
+ dpoFullName = &dpo.FullName
+ }
+ }
+
+ vendorsList := ""
+ if vendorNames, ok := vendorMap[pa.ID]; ok && len(vendorNames) > 0 {
+ vendorsList = strings.Join(vendorNames, ", ")
+ }
+
+ activities[i] = docgen.ProcessingActivityRowData{
+ Name: pa.Name,
+ Purpose: pa.Purpose,
+ DataSubjectCategory: pa.DataSubjectCategory,
+ PersonalDataCategory: pa.PersonalDataCategory,
+ SpecialOrCriminalData: pa.SpecialOrCriminalData,
+ ConsentEvidenceLink: pa.ConsentEvidenceLink,
+ LawfulBasis: pa.LawfulBasis,
+ Recipients: pa.Recipients,
+ Location: pa.Location,
+ InternationalTransfers: pa.InternationalTransfers,
+ TransferSafeguards: pa.TransferSafeguard,
+ RetentionPeriod: pa.RetentionPeriod,
+ SecurityMeasures: pa.SecurityMeasures,
+ DataProtectionImpactAssessmentNeeded: pa.DataProtectionImpactAssessmentNeeded,
+ TransferImpactAssessmentNeeded: pa.TransferImpactAssessmentNeeded,
+ LastReviewDate: pa.LastReviewDate,
+ NextReviewDate: pa.NextReviewDate,
+ Role: pa.Role,
+ DataProtectionOfficerFullName: dpoFullName,
+ Vendors: vendorsList,
+ }
+ }
+
+ tableData = docgen.ProcessingActivityTableData{
+ CompanyName: organization.Name,
+ CompanyHorizontalLogoBase64: horizontalLogoBase64,
+ Version: version,
+ PublishedAt: publishedAt,
+ Activities: activities,
+ }
+
+ return nil
+ },
+ )
+
+ if err != nil {
+ return nil, err
+ }
+
+ htmlContent, err := docgen.RenderProcessingActivitiesTableHTML(tableData)
+ if err != nil {
+ return nil, fmt.Errorf("cannot generate HTML: %w", err)
+ }
+
+ cfg := html2pdf.RenderConfig{
+ PageFormat: html2pdf.PageFormatA4,
+ Orientation: html2pdf.OrientationPortrait,
+ MarginTop: html2pdf.NewMarginInches(0.98),
+ MarginBottom: html2pdf.NewMarginInches(0.98),
+ MarginLeft: html2pdf.NewMarginInches(0.98),
+ MarginRight: html2pdf.NewMarginInches(0.98),
+ PrintBackground: true,
+ Scale: 1.0,
+ }
+
+ pdfReader, err := s.html2pdfConverter.GeneratePDF(ctx, htmlContent, cfg)
+ if err != nil {
+ return nil, fmt.Errorf("cannot generate PDF: %w", err)
+ }
+
+ pdfData, err := io.ReadAll(pdfReader)
+ if err != nil {
+ return nil, fmt.Errorf("cannot read PDF data: %w", err)
+ }
+
+ return pdfData, nil
+}
diff --git a/pkg/probo/service.go b/pkg/probo/service.go
index caa326409..4fa8327db 100644
--- a/pkg/probo/service.go
+++ b/pkg/probo/service.go
@@ -252,9 +252,18 @@ func (s *Service) WithTenant(tenantID gid.TenantID) *TenantService {
tenantService.Snapshots = &SnapshotService{svc: tenantService}
tenantService.ContinualImprovements = &ContinualImprovementService{svc: tenantService}
tenantService.RightsRequests = &RightsRequestService{svc: tenantService}
- tenantService.ProcessingActivities = &ProcessingActivityService{svc: tenantService}
- tenantService.DataProtectionImpactAssessments = &DataProtectionImpactAssessmentService{svc: tenantService}
- tenantService.TransferImpactAssessments = &TransferImpactAssessmentService{svc: tenantService}
+ tenantService.ProcessingActivities = &ProcessingActivityService{
+ svc: tenantService,
+ html2pdfConverter: s.html2pdfConverter,
+ }
+ tenantService.DataProtectionImpactAssessments = &DataProtectionImpactAssessmentService{
+ svc: tenantService,
+ html2pdfConverter: s.html2pdfConverter,
+ }
+ tenantService.TransferImpactAssessments = &TransferImpactAssessmentService{
+ svc: tenantService,
+ html2pdfConverter: s.html2pdfConverter,
+ }
tenantService.Files = &FileService{svc: tenantService}
tenantService.CustomDomains = &CustomDomainService{
svc: tenantService,
diff --git a/pkg/probo/snapshot_service.go b/pkg/probo/snapshot_service.go
index 28d9013e3..0742f572f 100644
--- a/pkg/probo/snapshot_service.go
+++ b/pkg/probo/snapshot_service.go
@@ -192,7 +192,8 @@ func (s *SnapshotService) CountForOrganizationID(
ctx,
func(conn pg.Conn) (err error) {
snapshots := coredata.Snapshots{}
- count, err = snapshots.CountByOrganizationID(ctx, conn, s.svc.scope, organizationID)
+ filter := coredata.NewSnapshotFilter(nil)
+ count, err = snapshots.CountByOrganizationID(ctx, conn, s.svc.scope, organizationID, filter)
if err != nil {
return fmt.Errorf("cannot count snapshots: %w", err)
}
diff --git a/pkg/probo/transfer_impact_assessment_service.go b/pkg/probo/transfer_impact_assessment_service.go
index 8668b1c7a..ed3563700 100644
--- a/pkg/probo/transfer_impact_assessment_service.go
+++ b/pkg/probo/transfer_impact_assessment_service.go
@@ -17,17 +17,21 @@ package probo
import (
"context"
"fmt"
+ "io"
"time"
"go.gearno.de/kit/pg"
"go.probo.inc/probo/pkg/coredata"
+ "go.probo.inc/probo/pkg/docgen"
"go.probo.inc/probo/pkg/gid"
+ "go.probo.inc/probo/pkg/html2pdf"
"go.probo.inc/probo/pkg/page"
"go.probo.inc/probo/pkg/validator"
)
type TransferImpactAssessmentService struct {
- svc *TenantService
+ svc *TenantService
+ html2pdfConverter *html2pdf.Converter
}
type (
@@ -298,3 +302,130 @@ func (s *TransferImpactAssessmentService) Delete(
return err
}
+func (s *TransferImpactAssessmentService) ExportPDF(
+ ctx context.Context,
+ organizationID gid.GID,
+ filter *coredata.TransferImpactAssessmentFilter,
+) ([]byte, error) {
+ var tableData docgen.TransferImpactAssessmentTableData
+
+ err := s.svc.pg.WithTx(
+ ctx,
+ func(conn pg.Conn) error {
+ var assessments coredata.TransferImpactAssessments
+ if err := assessments.LoadAllByOrganizationID(ctx, conn, s.svc.scope, organizationID, filter); err != nil {
+ return fmt.Errorf("cannot load transfer impact assessments: %w", err)
+ }
+
+ if len(assessments) == 0 {
+ return &coredata.ErrNoTransferImpactAssessmentsFound{}
+ }
+
+ organization := &coredata.Organization{}
+ if err := organization.LoadByID(ctx, conn, s.svc.scope, organizationID); err != nil {
+ return fmt.Errorf("cannot load organization: %w", err)
+ }
+
+ horizontalLogoBase64 := ""
+ if organization.HorizontalLogoFileID != nil {
+ fileRecord := &coredata.File{}
+ fileErr := s.svc.pg.WithConn(ctx, func(conn pg.Conn) error {
+ return fileRecord.LoadByID(ctx, conn, s.svc.scope, *organization.HorizontalLogoFileID)
+ })
+ if fileErr == nil {
+ base64Data, mimeType, logoErr := s.svc.fileManager.GetFileBase64(ctx, fileRecord)
+ if logoErr == nil {
+ horizontalLogoBase64 = fmt.Sprintf("data:%s;base64,%s", mimeType, base64Data)
+ }
+ }
+ }
+
+ var snapshots coredata.Snapshots
+ snapshotType := coredata.SnapshotsTypeProcessingActivities
+
+ var version int
+ var publishedAt time.Time
+
+ if snapshotID := filter.SnapshotID(); snapshotID != nil {
+ snapshot := &coredata.Snapshot{}
+ if err := snapshot.LoadByID(ctx, conn, s.svc.scope, *snapshotID); err != nil {
+ return fmt.Errorf("cannot load snapshot: %w", err)
+ }
+ publishedAt = snapshot.CreatedAt
+ snapshotFilter := coredata.NewSnapshotFilter(&snapshotType).WithBeforeDate(&snapshot.CreatedAt)
+ snapshotCount, err := snapshots.CountByOrganizationID(ctx, conn, s.svc.scope, organizationID, snapshotFilter)
+ if err != nil {
+ return fmt.Errorf("cannot count processing activities snapshots: %w", err)
+ }
+ version = snapshotCount
+ } else {
+ publishedAt = time.Now()
+ snapshotFilter := coredata.NewSnapshotFilter(&snapshotType)
+ snapshotCount, err := snapshots.CountByOrganizationID(ctx, conn, s.svc.scope, organizationID, snapshotFilter)
+ if err != nil {
+ return fmt.Errorf("cannot count processing activities snapshots: %w", err)
+ }
+ version = snapshotCount + 1
+ }
+
+ assessmentRows := make([]docgen.TransferImpactAssessmentRowData, len(assessments))
+ for i, assessment := range assessments {
+ processingActivity := &coredata.ProcessingActivity{}
+ if err := processingActivity.LoadByID(ctx, conn, s.svc.scope, assessment.ProcessingActivityID); err != nil {
+ return fmt.Errorf("cannot load processing activity: %w", err)
+ }
+
+ assessmentRows[i] = docgen.TransferImpactAssessmentRowData{
+ ProcessingActivityName: processingActivity.Name,
+ DataSubjects: assessment.DataSubjects,
+ LegalMechanism: assessment.LegalMechanism,
+ Transfer: assessment.Transfer,
+ LocalLawRisk: assessment.LocalLawRisk,
+ SupplementaryMeasures: assessment.SupplementaryMeasures,
+ }
+ }
+
+ tableData = docgen.TransferImpactAssessmentTableData{
+ CompanyName: organization.Name,
+ CompanyHorizontalLogoBase64: horizontalLogoBase64,
+ Version: version,
+ PublishedAt: publishedAt,
+ Assessments: assessmentRows,
+ }
+
+ return nil
+ },
+ )
+
+ if err != nil {
+ return nil, err
+ }
+
+ htmlContent, err := docgen.RenderTransferImpactAssessmentsTableHTML(tableData)
+ if err != nil {
+ return nil, fmt.Errorf("cannot render HTML: %w", err)
+ }
+
+ cfg := html2pdf.RenderConfig{
+ PageFormat: html2pdf.PageFormatA4,
+ Orientation: html2pdf.OrientationPortrait,
+ MarginTop: html2pdf.NewMarginInches(0.98),
+ MarginBottom: html2pdf.NewMarginInches(0.98),
+ MarginLeft: html2pdf.NewMarginInches(0.98),
+ MarginRight: html2pdf.NewMarginInches(0.98),
+ PrintBackground: true,
+ Scale: 1.0,
+ }
+
+ pdfReader, err := s.html2pdfConverter.GeneratePDF(ctx, htmlContent, cfg)
+ if err != nil {
+ return nil, fmt.Errorf("cannot generate PDF: %w", err)
+ }
+
+ pdfData, err := io.ReadAll(pdfReader)
+ if err != nil {
+ return nil, fmt.Errorf("cannot read PDF data: %w", err)
+ }
+
+ return pdfData, nil
+}
diff --git a/pkg/server/api/console/v1/schema.graphql b/pkg/server/api/console/v1/schema.graphql
index 289b40c70..4f12e87a2 100644
--- a/pkg/server/api/console/v1/schema.graphql
+++ b/pkg/server/api/console/v1/schema.graphql
@@ -3310,6 +3310,15 @@ type Mutation {
exportSignableVersionDocumentPDF(
input: ExportSignableDocumentVersionPDFInput!
): ExportSignableDocumentVersionPDFPayload!
+ exportProcessingActivitiesPDF(
+ input: ExportProcessingActivitiesPDFInput!
+ ): ExportProcessingActivitiesPDFPayload!
+ exportDataProtectionImpactAssessmentsPDF(
+ input: ExportDataProtectionImpactAssessmentsPDFInput!
+ ): ExportDataProtectionImpactAssessmentsPDFPayload!
+ exportTransferImpactAssessmentsPDF(
+ input: ExportTransferImpactAssessmentsPDFInput!
+ ): ExportTransferImpactAssessmentsPDFPayload!
createVendorRiskAssessment(
input: CreateVendorRiskAssessmentInput!
): CreateVendorRiskAssessmentPayload!
@@ -3941,6 +3950,21 @@ input ExportSignableDocumentVersionPDFInput {
documentVersionId: ID!
}
+input ExportProcessingActivitiesPDFInput {
+ organizationId: ID!
+ filter: ProcessingActivityFilter
+}
+
+input ExportDataProtectionImpactAssessmentsPDFInput {
+ organizationId: ID!
+ filter: DataProtectionImpactAssessmentFilter
+}
+
+input ExportTransferImpactAssessmentsPDFInput {
+ organizationId: ID!
+ filter: TransferImpactAssessmentFilter
+}
+
input DeleteDocumentInput {
documentId: ID!
}
@@ -4600,6 +4624,18 @@ type ExportSignableDocumentVersionPDFPayload {
data: String!
}
+type ExportProcessingActivitiesPDFPayload {
+ data: String!
+}
+
+type ExportDataProtectionImpactAssessmentsPDFPayload {
+ data: String!
+}
+
+type ExportTransferImpactAssessmentsPDFPayload {
+ data: String!
+}
+
type UpdateDocumentPayload {
document: Document!
}
diff --git a/pkg/server/api/console/v1/schema/schema.go b/pkg/server/api/console/v1/schema/schema.go
index a1369b395..b4435ab08 100644
--- a/pkg/server/api/console/v1/schema/schema.go
+++ b/pkg/server/api/console/v1/schema/schema.go
@@ -779,6 +779,10 @@ type ComplexityRoot struct {
Node func(childComplexity int) int
}
+ ExportDataProtectionImpactAssessmentsPDFPayload struct {
+ Data func(childComplexity int) int
+ }
+
ExportDocumentVersionPDFPayload struct {
Data func(childComplexity int) int
}
@@ -787,10 +791,18 @@ type ComplexityRoot struct {
ExportJobID func(childComplexity int) int
}
+ ExportProcessingActivitiesPDFPayload struct {
+ Data func(childComplexity int) int
+ }
+
ExportSignableDocumentVersionPDFPayload struct {
Data func(childComplexity int) int
}
+ ExportTransferImpactAssessmentsPDFPayload struct {
+ Data func(childComplexity int) int
+ }
+
File struct {
CreatedAt func(childComplexity int) int
DownloadURL func(childComplexity int) int
@@ -951,151 +963,154 @@ type ComplexityRoot struct {
}
Mutation struct {
- AcceptInvitation func(childComplexity int, input types.AcceptInvitationInput) int
- AssessVendor func(childComplexity int, input types.AssessVendorInput) int
- BulkDeleteDocuments func(childComplexity int, input types.BulkDeleteDocumentsInput) int
- BulkExportDocuments func(childComplexity int, input types.BulkExportDocumentsInput) int
- BulkPublishDocumentVersions func(childComplexity int, input types.BulkPublishDocumentVersionsInput) int
- BulkRequestSignatures func(childComplexity int, input types.BulkRequestSignaturesInput) int
- CancelSignatureRequest func(childComplexity int, input types.CancelSignatureRequestInput) int
- ConfirmEmail func(childComplexity int, input types.ConfirmEmailInput) int
- CreateAsset func(childComplexity int, input types.CreateAssetInput) int
- CreateAudit func(childComplexity int, input types.CreateAuditInput) int
- CreateContinualImprovement func(childComplexity int, input types.CreateContinualImprovementInput) int
- CreateControl func(childComplexity int, input types.CreateControlInput) int
- CreateControlAuditMapping func(childComplexity int, input types.CreateControlAuditMappingInput) int
- CreateControlDocumentMapping func(childComplexity int, input types.CreateControlDocumentMappingInput) int
- CreateControlMeasureMapping func(childComplexity int, input types.CreateControlMeasureMappingInput) int
- CreateControlSnapshotMapping func(childComplexity int, input types.CreateControlSnapshotMappingInput) int
- CreateCustomDomain func(childComplexity int, input types.CreateCustomDomainInput) int
- CreateDataProtectionImpactAssessment func(childComplexity int, input types.CreateDataProtectionImpactAssessmentInput) int
- CreateDatum func(childComplexity int, input types.CreateDatumInput) int
- CreateDocument func(childComplexity int, input types.CreateDocumentInput) int
- CreateDraftDocumentVersion func(childComplexity int, input types.CreateDraftDocumentVersionInput) int
- CreateFramework func(childComplexity int, input types.CreateFrameworkInput) int
- CreateMeasure func(childComplexity int, input types.CreateMeasureInput) int
- CreateMeeting func(childComplexity int, input types.CreateMeetingInput) int
- CreateNonconformity func(childComplexity int, input types.CreateNonconformityInput) int
- CreateObligation func(childComplexity int, input types.CreateObligationInput) int
- CreateOrganization func(childComplexity int, input types.CreateOrganizationInput) int
- CreatePeople func(childComplexity int, input types.CreatePeopleInput) int
- CreateProcessingActivity func(childComplexity int, input types.CreateProcessingActivityInput) int
- CreateRightsRequest func(childComplexity int, input types.CreateRightsRequestInput) int
- CreateRisk func(childComplexity int, input types.CreateRiskInput) int
- CreateRiskDocumentMapping func(childComplexity int, input types.CreateRiskDocumentMappingInput) int
- CreateRiskMeasureMapping func(childComplexity int, input types.CreateRiskMeasureMappingInput) int
- CreateRiskObligationMapping func(childComplexity int, input types.CreateRiskObligationMappingInput) int
- CreateSAMLConfiguration func(childComplexity int, input types.CreateSAMLConfigurationInput) int
- CreateSnapshot func(childComplexity int, input types.CreateSnapshotInput) int
- CreateTask func(childComplexity int, input types.CreateTaskInput) int
- CreateTransferImpactAssessment func(childComplexity int, input types.CreateTransferImpactAssessmentInput) int
- CreateTrustCenterAccess func(childComplexity int, input types.CreateTrustCenterAccessInput) int
- CreateTrustCenterFile func(childComplexity int, input types.CreateTrustCenterFileInput) int
- CreateTrustCenterReference func(childComplexity int, input types.CreateTrustCenterReferenceInput) int
- CreateVendor func(childComplexity int, input types.CreateVendorInput) int
- CreateVendorContact func(childComplexity int, input types.CreateVendorContactInput) int
- CreateVendorRiskAssessment func(childComplexity int, input types.CreateVendorRiskAssessmentInput) int
- CreateVendorService func(childComplexity int, input types.CreateVendorServiceInput) int
- DeleteAsset func(childComplexity int, input types.DeleteAssetInput) int
- DeleteAudit func(childComplexity int, input types.DeleteAuditInput) int
- DeleteAuditReport func(childComplexity int, input types.DeleteAuditReportInput) int
- DeleteContinualImprovement func(childComplexity int, input types.DeleteContinualImprovementInput) int
- DeleteControl func(childComplexity int, input types.DeleteControlInput) int
- DeleteControlAuditMapping func(childComplexity int, input types.DeleteControlAuditMappingInput) int
- DeleteControlDocumentMapping func(childComplexity int, input types.DeleteControlDocumentMappingInput) int
- DeleteControlMeasureMapping func(childComplexity int, input types.DeleteControlMeasureMappingInput) int
- DeleteControlSnapshotMapping func(childComplexity int, input types.DeleteControlSnapshotMappingInput) int
- DeleteCustomDomain func(childComplexity int, input types.DeleteCustomDomainInput) int
- DeleteDataProtectionImpactAssessment func(childComplexity int, input types.DeleteDataProtectionImpactAssessmentInput) int
- DeleteDatum func(childComplexity int, input types.DeleteDatumInput) int
- DeleteDocument func(childComplexity int, input types.DeleteDocumentInput) int
- DeleteDraftDocumentVersion func(childComplexity int, input types.DeleteDraftDocumentVersionInput) int
- DeleteEvidence func(childComplexity int, input types.DeleteEvidenceInput) int
- DeleteFramework func(childComplexity int, input types.DeleteFrameworkInput) int
- DeleteInvitation func(childComplexity int, input types.DeleteInvitationInput) int
- DeleteMeasure func(childComplexity int, input types.DeleteMeasureInput) int
- DeleteMeeting func(childComplexity int, input types.DeleteMeetingInput) int
- DeleteNonconformity func(childComplexity int, input types.DeleteNonconformityInput) int
- DeleteObligation func(childComplexity int, input types.DeleteObligationInput) int
- DeleteOrganization func(childComplexity int, input types.DeleteOrganizationInput) int
- DeleteOrganizationHorizontalLogo func(childComplexity int, input types.DeleteOrganizationHorizontalLogoInput) int
- DeletePeople func(childComplexity int, input types.DeletePeopleInput) int
- DeleteProcessingActivity func(childComplexity int, input types.DeleteProcessingActivityInput) int
- DeleteRightsRequest func(childComplexity int, input types.DeleteRightsRequestInput) int
- DeleteRisk func(childComplexity int, input types.DeleteRiskInput) int
- DeleteRiskDocumentMapping func(childComplexity int, input types.DeleteRiskDocumentMappingInput) int
- DeleteRiskMeasureMapping func(childComplexity int, input types.DeleteRiskMeasureMappingInput) int
- DeleteRiskObligationMapping func(childComplexity int, input types.DeleteRiskObligationMappingInput) int
- DeleteSAMLConfiguration func(childComplexity int, input types.DeleteSAMLConfigurationInput) int
- DeleteSnapshot func(childComplexity int, input types.DeleteSnapshotInput) int
- DeleteTask func(childComplexity int, input types.DeleteTaskInput) int
- DeleteTransferImpactAssessment func(childComplexity int, input types.DeleteTransferImpactAssessmentInput) int
- DeleteTrustCenterAccess func(childComplexity int, input types.DeleteTrustCenterAccessInput) int
- DeleteTrustCenterFile func(childComplexity int, input types.DeleteTrustCenterFileInput) int
- DeleteTrustCenterNda func(childComplexity int, input types.DeleteTrustCenterNDAInput) int
- DeleteTrustCenterReference func(childComplexity int, input types.DeleteTrustCenterReferenceInput) int
- DeleteVendor func(childComplexity int, input types.DeleteVendorInput) int
- DeleteVendorBusinessAssociateAgreement func(childComplexity int, input types.DeleteVendorBusinessAssociateAgreementInput) int
- DeleteVendorComplianceReport func(childComplexity int, input types.DeleteVendorComplianceReportInput) int
- DeleteVendorContact func(childComplexity int, input types.DeleteVendorContactInput) int
- DeleteVendorDataPrivacyAgreement func(childComplexity int, input types.DeleteVendorDataPrivacyAgreementInput) int
- DeleteVendorService func(childComplexity int, input types.DeleteVendorServiceInput) int
- DisableSaml func(childComplexity int, input types.DisableSAMLInput) int
- EnableSaml func(childComplexity int, input types.EnableSAMLInput) int
- ExportDocumentVersionPDF func(childComplexity int, input types.ExportDocumentVersionPDFInput) int
- ExportFramework func(childComplexity int, input types.ExportFrameworkInput) int
- ExportSignableVersionDocumentPDF func(childComplexity int, input types.ExportSignableDocumentVersionPDFInput) int
- GenerateDocumentChangelog func(childComplexity int, input types.GenerateDocumentChangelogInput) int
- GenerateFrameworkStateOfApplicability func(childComplexity int, input types.GenerateFrameworkStateOfApplicabilityInput) int
- GetTrustCenterFile func(childComplexity int, input types.GetTrustCenterFileInput) int
- ImportFramework func(childComplexity int, input types.ImportFrameworkInput) int
- ImportMeasure func(childComplexity int, input types.ImportMeasureInput) int
- InitiateDomainVerification func(childComplexity int, input types.InitiateDomainVerificationInput) int
- InviteUser func(childComplexity int, input types.InviteUserInput) int
- PublishDocumentVersion func(childComplexity int, input types.PublishDocumentVersionInput) int
- RemoveMember func(childComplexity int, input types.RemoveMemberInput) int
- RequestSignature func(childComplexity int, input types.RequestSignatureInput) int
- SendSigningNotifications func(childComplexity int, input types.SendSigningNotificationsInput) int
- SignDocument func(childComplexity int, input types.SignDocumentInput) int
- UpdateAsset func(childComplexity int, input types.UpdateAssetInput) int
- UpdateAudit func(childComplexity int, input types.UpdateAuditInput) int
- UpdateContinualImprovement func(childComplexity int, input types.UpdateContinualImprovementInput) int
- UpdateControl func(childComplexity int, input types.UpdateControlInput) int
- UpdateDataProtectionImpactAssessment func(childComplexity int, input types.UpdateDataProtectionImpactAssessmentInput) int
- UpdateDatum func(childComplexity int, input types.UpdateDatumInput) int
- UpdateDocument func(childComplexity int, input types.UpdateDocumentInput) int
- UpdateDocumentVersion func(childComplexity int, input types.UpdateDocumentVersionInput) int
- UpdateFramework func(childComplexity int, input types.UpdateFrameworkInput) int
- UpdateMeasure func(childComplexity int, input types.UpdateMeasureInput) int
- UpdateMeeting func(childComplexity int, input types.UpdateMeetingInput) int
- UpdateMembership func(childComplexity int, input types.UpdateMembershipInput) int
- UpdateNonconformity func(childComplexity int, input types.UpdateNonconformityInput) int
- UpdateObligation func(childComplexity int, input types.UpdateObligationInput) int
- UpdateOrganization func(childComplexity int, input types.UpdateOrganizationInput) int
- UpdateOrganizationContext func(childComplexity int, input types.UpdateOrganizationContextInput) int
- UpdatePeople func(childComplexity int, input types.UpdatePeopleInput) int
- UpdateProcessingActivity func(childComplexity int, input types.UpdateProcessingActivityInput) int
- UpdateRightsRequest func(childComplexity int, input types.UpdateRightsRequestInput) int
- UpdateRisk func(childComplexity int, input types.UpdateRiskInput) int
- UpdateSAMLConfiguration func(childComplexity int, input types.UpdateSAMLConfigurationInput) int
- UpdateTask func(childComplexity int, input types.UpdateTaskInput) int
- UpdateTransferImpactAssessment func(childComplexity int, input types.UpdateTransferImpactAssessmentInput) int
- UpdateTrustCenter func(childComplexity int, input types.UpdateTrustCenterInput) int
- UpdateTrustCenterAccess func(childComplexity int, input types.UpdateTrustCenterAccessInput) int
- UpdateTrustCenterFile func(childComplexity int, input types.UpdateTrustCenterFileInput) int
- UpdateTrustCenterReference func(childComplexity int, input types.UpdateTrustCenterReferenceInput) int
- UpdateVendor func(childComplexity int, input types.UpdateVendorInput) int
- UpdateVendorBusinessAssociateAgreement func(childComplexity int, input types.UpdateVendorBusinessAssociateAgreementInput) int
- UpdateVendorContact func(childComplexity int, input types.UpdateVendorContactInput) int
- UpdateVendorDataPrivacyAgreement func(childComplexity int, input types.UpdateVendorDataPrivacyAgreementInput) int
- UpdateVendorService func(childComplexity int, input types.UpdateVendorServiceInput) int
- UploadAuditReport func(childComplexity int, input types.UploadAuditReportInput) int
- UploadMeasureEvidence func(childComplexity int, input types.UploadMeasureEvidenceInput) int
- UploadTrustCenterNda func(childComplexity int, input types.UploadTrustCenterNDAInput) int
- UploadVendorBusinessAssociateAgreement func(childComplexity int, input types.UploadVendorBusinessAssociateAgreementInput) int
- UploadVendorComplianceReport func(childComplexity int, input types.UploadVendorComplianceReportInput) int
- UploadVendorDataPrivacyAgreement func(childComplexity int, input types.UploadVendorDataPrivacyAgreementInput) int
- VerifyDomain func(childComplexity int, input types.VerifyDomainInput) int
+ AcceptInvitation func(childComplexity int, input types.AcceptInvitationInput) int
+ AssessVendor func(childComplexity int, input types.AssessVendorInput) int
+ BulkDeleteDocuments func(childComplexity int, input types.BulkDeleteDocumentsInput) int
+ BulkExportDocuments func(childComplexity int, input types.BulkExportDocumentsInput) int
+ BulkPublishDocumentVersions func(childComplexity int, input types.BulkPublishDocumentVersionsInput) int
+ BulkRequestSignatures func(childComplexity int, input types.BulkRequestSignaturesInput) int
+ CancelSignatureRequest func(childComplexity int, input types.CancelSignatureRequestInput) int
+ ConfirmEmail func(childComplexity int, input types.ConfirmEmailInput) int
+ CreateAsset func(childComplexity int, input types.CreateAssetInput) int
+ CreateAudit func(childComplexity int, input types.CreateAuditInput) int
+ CreateContinualImprovement func(childComplexity int, input types.CreateContinualImprovementInput) int
+ CreateControl func(childComplexity int, input types.CreateControlInput) int
+ CreateControlAuditMapping func(childComplexity int, input types.CreateControlAuditMappingInput) int
+ CreateControlDocumentMapping func(childComplexity int, input types.CreateControlDocumentMappingInput) int
+ CreateControlMeasureMapping func(childComplexity int, input types.CreateControlMeasureMappingInput) int
+ CreateControlSnapshotMapping func(childComplexity int, input types.CreateControlSnapshotMappingInput) int
+ CreateCustomDomain func(childComplexity int, input types.CreateCustomDomainInput) int
+ CreateDataProtectionImpactAssessment func(childComplexity int, input types.CreateDataProtectionImpactAssessmentInput) int
+ CreateDatum func(childComplexity int, input types.CreateDatumInput) int
+ CreateDocument func(childComplexity int, input types.CreateDocumentInput) int
+ CreateDraftDocumentVersion func(childComplexity int, input types.CreateDraftDocumentVersionInput) int
+ CreateFramework func(childComplexity int, input types.CreateFrameworkInput) int
+ CreateMeasure func(childComplexity int, input types.CreateMeasureInput) int
+ CreateMeeting func(childComplexity int, input types.CreateMeetingInput) int
+ CreateNonconformity func(childComplexity int, input types.CreateNonconformityInput) int
+ CreateObligation func(childComplexity int, input types.CreateObligationInput) int
+ CreateOrganization func(childComplexity int, input types.CreateOrganizationInput) int
+ CreatePeople func(childComplexity int, input types.CreatePeopleInput) int
+ CreateProcessingActivity func(childComplexity int, input types.CreateProcessingActivityInput) int
+ CreateRightsRequest func(childComplexity int, input types.CreateRightsRequestInput) int
+ CreateRisk func(childComplexity int, input types.CreateRiskInput) int
+ CreateRiskDocumentMapping func(childComplexity int, input types.CreateRiskDocumentMappingInput) int
+ CreateRiskMeasureMapping func(childComplexity int, input types.CreateRiskMeasureMappingInput) int
+ CreateRiskObligationMapping func(childComplexity int, input types.CreateRiskObligationMappingInput) int
+ CreateSAMLConfiguration func(childComplexity int, input types.CreateSAMLConfigurationInput) int
+ CreateSnapshot func(childComplexity int, input types.CreateSnapshotInput) int
+ CreateTask func(childComplexity int, input types.CreateTaskInput) int
+ CreateTransferImpactAssessment func(childComplexity int, input types.CreateTransferImpactAssessmentInput) int
+ CreateTrustCenterAccess func(childComplexity int, input types.CreateTrustCenterAccessInput) int
+ CreateTrustCenterFile func(childComplexity int, input types.CreateTrustCenterFileInput) int
+ CreateTrustCenterReference func(childComplexity int, input types.CreateTrustCenterReferenceInput) int
+ CreateVendor func(childComplexity int, input types.CreateVendorInput) int
+ CreateVendorContact func(childComplexity int, input types.CreateVendorContactInput) int
+ CreateVendorRiskAssessment func(childComplexity int, input types.CreateVendorRiskAssessmentInput) int
+ CreateVendorService func(childComplexity int, input types.CreateVendorServiceInput) int
+ DeleteAsset func(childComplexity int, input types.DeleteAssetInput) int
+ DeleteAudit func(childComplexity int, input types.DeleteAuditInput) int
+ DeleteAuditReport func(childComplexity int, input types.DeleteAuditReportInput) int
+ DeleteContinualImprovement func(childComplexity int, input types.DeleteContinualImprovementInput) int
+ DeleteControl func(childComplexity int, input types.DeleteControlInput) int
+ DeleteControlAuditMapping func(childComplexity int, input types.DeleteControlAuditMappingInput) int
+ DeleteControlDocumentMapping func(childComplexity int, input types.DeleteControlDocumentMappingInput) int
+ DeleteControlMeasureMapping func(childComplexity int, input types.DeleteControlMeasureMappingInput) int
+ DeleteControlSnapshotMapping func(childComplexity int, input types.DeleteControlSnapshotMappingInput) int
+ DeleteCustomDomain func(childComplexity int, input types.DeleteCustomDomainInput) int
+ DeleteDataProtectionImpactAssessment func(childComplexity int, input types.DeleteDataProtectionImpactAssessmentInput) int
+ DeleteDatum func(childComplexity int, input types.DeleteDatumInput) int
+ DeleteDocument func(childComplexity int, input types.DeleteDocumentInput) int
+ DeleteDraftDocumentVersion func(childComplexity int, input types.DeleteDraftDocumentVersionInput) int
+ DeleteEvidence func(childComplexity int, input types.DeleteEvidenceInput) int
+ DeleteFramework func(childComplexity int, input types.DeleteFrameworkInput) int
+ DeleteInvitation func(childComplexity int, input types.DeleteInvitationInput) int
+ DeleteMeasure func(childComplexity int, input types.DeleteMeasureInput) int
+ DeleteMeeting func(childComplexity int, input types.DeleteMeetingInput) int
+ DeleteNonconformity func(childComplexity int, input types.DeleteNonconformityInput) int
+ DeleteObligation func(childComplexity int, input types.DeleteObligationInput) int
+ DeleteOrganization func(childComplexity int, input types.DeleteOrganizationInput) int
+ DeleteOrganizationHorizontalLogo func(childComplexity int, input types.DeleteOrganizationHorizontalLogoInput) int
+ DeletePeople func(childComplexity int, input types.DeletePeopleInput) int
+ DeleteProcessingActivity func(childComplexity int, input types.DeleteProcessingActivityInput) int
+ DeleteRightsRequest func(childComplexity int, input types.DeleteRightsRequestInput) int
+ DeleteRisk func(childComplexity int, input types.DeleteRiskInput) int
+ DeleteRiskDocumentMapping func(childComplexity int, input types.DeleteRiskDocumentMappingInput) int
+ DeleteRiskMeasureMapping func(childComplexity int, input types.DeleteRiskMeasureMappingInput) int
+ DeleteRiskObligationMapping func(childComplexity int, input types.DeleteRiskObligationMappingInput) int
+ DeleteSAMLConfiguration func(childComplexity int, input types.DeleteSAMLConfigurationInput) int
+ DeleteSnapshot func(childComplexity int, input types.DeleteSnapshotInput) int
+ DeleteTask func(childComplexity int, input types.DeleteTaskInput) int
+ DeleteTransferImpactAssessment func(childComplexity int, input types.DeleteTransferImpactAssessmentInput) int
+ DeleteTrustCenterAccess func(childComplexity int, input types.DeleteTrustCenterAccessInput) int
+ DeleteTrustCenterFile func(childComplexity int, input types.DeleteTrustCenterFileInput) int
+ DeleteTrustCenterNda func(childComplexity int, input types.DeleteTrustCenterNDAInput) int
+ DeleteTrustCenterReference func(childComplexity int, input types.DeleteTrustCenterReferenceInput) int
+ DeleteVendor func(childComplexity int, input types.DeleteVendorInput) int
+ DeleteVendorBusinessAssociateAgreement func(childComplexity int, input types.DeleteVendorBusinessAssociateAgreementInput) int
+ DeleteVendorComplianceReport func(childComplexity int, input types.DeleteVendorComplianceReportInput) int
+ DeleteVendorContact func(childComplexity int, input types.DeleteVendorContactInput) int
+ DeleteVendorDataPrivacyAgreement func(childComplexity int, input types.DeleteVendorDataPrivacyAgreementInput) int
+ DeleteVendorService func(childComplexity int, input types.DeleteVendorServiceInput) int
+ DisableSaml func(childComplexity int, input types.DisableSAMLInput) int
+ EnableSaml func(childComplexity int, input types.EnableSAMLInput) int
+ ExportDataProtectionImpactAssessmentsPDF func(childComplexity int, input types.ExportDataProtectionImpactAssessmentsPDFInput) int
+ ExportDocumentVersionPDF func(childComplexity int, input types.ExportDocumentVersionPDFInput) int
+ ExportFramework func(childComplexity int, input types.ExportFrameworkInput) int
+ ExportProcessingActivitiesPDF func(childComplexity int, input types.ExportProcessingActivitiesPDFInput) int
+ ExportSignableVersionDocumentPDF func(childComplexity int, input types.ExportSignableDocumentVersionPDFInput) int
+ ExportTransferImpactAssessmentsPDF func(childComplexity int, input types.ExportTransferImpactAssessmentsPDFInput) int
+ GenerateDocumentChangelog func(childComplexity int, input types.GenerateDocumentChangelogInput) int
+ GenerateFrameworkStateOfApplicability func(childComplexity int, input types.GenerateFrameworkStateOfApplicabilityInput) int
+ GetTrustCenterFile func(childComplexity int, input types.GetTrustCenterFileInput) int
+ ImportFramework func(childComplexity int, input types.ImportFrameworkInput) int
+ ImportMeasure func(childComplexity int, input types.ImportMeasureInput) int
+ InitiateDomainVerification func(childComplexity int, input types.InitiateDomainVerificationInput) int
+ InviteUser func(childComplexity int, input types.InviteUserInput) int
+ PublishDocumentVersion func(childComplexity int, input types.PublishDocumentVersionInput) int
+ RemoveMember func(childComplexity int, input types.RemoveMemberInput) int
+ RequestSignature func(childComplexity int, input types.RequestSignatureInput) int
+ SendSigningNotifications func(childComplexity int, input types.SendSigningNotificationsInput) int
+ SignDocument func(childComplexity int, input types.SignDocumentInput) int
+ UpdateAsset func(childComplexity int, input types.UpdateAssetInput) int
+ UpdateAudit func(childComplexity int, input types.UpdateAuditInput) int
+ UpdateContinualImprovement func(childComplexity int, input types.UpdateContinualImprovementInput) int
+ UpdateControl func(childComplexity int, input types.UpdateControlInput) int
+ UpdateDataProtectionImpactAssessment func(childComplexity int, input types.UpdateDataProtectionImpactAssessmentInput) int
+ UpdateDatum func(childComplexity int, input types.UpdateDatumInput) int
+ UpdateDocument func(childComplexity int, input types.UpdateDocumentInput) int
+ UpdateDocumentVersion func(childComplexity int, input types.UpdateDocumentVersionInput) int
+ UpdateFramework func(childComplexity int, input types.UpdateFrameworkInput) int
+ UpdateMeasure func(childComplexity int, input types.UpdateMeasureInput) int
+ UpdateMeeting func(childComplexity int, input types.UpdateMeetingInput) int
+ UpdateMembership func(childComplexity int, input types.UpdateMembershipInput) int
+ UpdateNonconformity func(childComplexity int, input types.UpdateNonconformityInput) int
+ UpdateObligation func(childComplexity int, input types.UpdateObligationInput) int
+ UpdateOrganization func(childComplexity int, input types.UpdateOrganizationInput) int
+ UpdateOrganizationContext func(childComplexity int, input types.UpdateOrganizationContextInput) int
+ UpdatePeople func(childComplexity int, input types.UpdatePeopleInput) int
+ UpdateProcessingActivity func(childComplexity int, input types.UpdateProcessingActivityInput) int
+ UpdateRightsRequest func(childComplexity int, input types.UpdateRightsRequestInput) int
+ UpdateRisk func(childComplexity int, input types.UpdateRiskInput) int
+ UpdateSAMLConfiguration func(childComplexity int, input types.UpdateSAMLConfigurationInput) int
+ UpdateTask func(childComplexity int, input types.UpdateTaskInput) int
+ UpdateTransferImpactAssessment func(childComplexity int, input types.UpdateTransferImpactAssessmentInput) int
+ UpdateTrustCenter func(childComplexity int, input types.UpdateTrustCenterInput) int
+ UpdateTrustCenterAccess func(childComplexity int, input types.UpdateTrustCenterAccessInput) int
+ UpdateTrustCenterFile func(childComplexity int, input types.UpdateTrustCenterFileInput) int
+ UpdateTrustCenterReference func(childComplexity int, input types.UpdateTrustCenterReferenceInput) int
+ UpdateVendor func(childComplexity int, input types.UpdateVendorInput) int
+ UpdateVendorBusinessAssociateAgreement func(childComplexity int, input types.UpdateVendorBusinessAssociateAgreementInput) int
+ UpdateVendorContact func(childComplexity int, input types.UpdateVendorContactInput) int
+ UpdateVendorDataPrivacyAgreement func(childComplexity int, input types.UpdateVendorDataPrivacyAgreementInput) int
+ UpdateVendorService func(childComplexity int, input types.UpdateVendorServiceInput) int
+ UploadAuditReport func(childComplexity int, input types.UploadAuditReportInput) int
+ UploadMeasureEvidence func(childComplexity int, input types.UploadMeasureEvidenceInput) int
+ UploadTrustCenterNda func(childComplexity int, input types.UploadTrustCenterNDAInput) int
+ UploadVendorBusinessAssociateAgreement func(childComplexity int, input types.UploadVendorBusinessAssociateAgreementInput) int
+ UploadVendorComplianceReport func(childComplexity int, input types.UploadVendorComplianceReportInput) int
+ UploadVendorDataPrivacyAgreement func(childComplexity int, input types.UploadVendorDataPrivacyAgreementInput) int
+ VerifyDomain func(childComplexity int, input types.VerifyDomainInput) int
}
Nonconformity struct {
@@ -2200,6 +2215,9 @@ type MutationResolver interface {
SignDocument(ctx context.Context, input types.SignDocumentInput) (*types.SignDocumentPayload, error)
ExportDocumentVersionPDF(ctx context.Context, input types.ExportDocumentVersionPDFInput) (*types.ExportDocumentVersionPDFPayload, error)
ExportSignableVersionDocumentPDF(ctx context.Context, input types.ExportSignableDocumentVersionPDFInput) (*types.ExportSignableDocumentVersionPDFPayload, error)
+ ExportProcessingActivitiesPDF(ctx context.Context, input types.ExportProcessingActivitiesPDFInput) (*types.ExportProcessingActivitiesPDFPayload, error)
+ ExportDataProtectionImpactAssessmentsPDF(ctx context.Context, input types.ExportDataProtectionImpactAssessmentsPDFInput) (*types.ExportDataProtectionImpactAssessmentsPDFPayload, error)
+ ExportTransferImpactAssessmentsPDF(ctx context.Context, input types.ExportTransferImpactAssessmentsPDFInput) (*types.ExportTransferImpactAssessmentsPDFPayload, error)
CreateVendorRiskAssessment(ctx context.Context, input types.CreateVendorRiskAssessmentInput) (*types.CreateVendorRiskAssessmentPayload, error)
AssessVendor(ctx context.Context, input types.AssessVendorInput) (*types.AssessVendorPayload, error)
CreateAsset(ctx context.Context, input types.CreateAssetInput) (*types.CreateAssetPayload, error)
@@ -4350,6 +4368,13 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
return e.complexity.EvidenceEdge.Node(childComplexity), true
+ case "ExportDataProtectionImpactAssessmentsPDFPayload.data":
+ if e.complexity.ExportDataProtectionImpactAssessmentsPDFPayload.Data == nil {
+ break
+ }
+
+ return e.complexity.ExportDataProtectionImpactAssessmentsPDFPayload.Data(childComplexity), true
+
case "ExportDocumentVersionPDFPayload.data":
if e.complexity.ExportDocumentVersionPDFPayload.Data == nil {
break
@@ -4364,6 +4389,13 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
return e.complexity.ExportFrameworkPayload.ExportJobID(childComplexity), true
+ case "ExportProcessingActivitiesPDFPayload.data":
+ if e.complexity.ExportProcessingActivitiesPDFPayload.Data == nil {
+ break
+ }
+
+ return e.complexity.ExportProcessingActivitiesPDFPayload.Data(childComplexity), true
+
case "ExportSignableDocumentVersionPDFPayload.data":
if e.complexity.ExportSignableDocumentVersionPDFPayload.Data == nil {
break
@@ -4371,6 +4403,13 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
return e.complexity.ExportSignableDocumentVersionPDFPayload.Data(childComplexity), true
+ case "ExportTransferImpactAssessmentsPDFPayload.data":
+ if e.complexity.ExportTransferImpactAssessmentsPDFPayload.Data == nil {
+ break
+ }
+
+ return e.complexity.ExportTransferImpactAssessmentsPDFPayload.Data(childComplexity), true
+
case "File.createdAt":
if e.complexity.File.CreatedAt == nil {
break
@@ -5943,6 +5982,17 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
}
return e.complexity.Mutation.EnableSaml(childComplexity, args["input"].(types.EnableSAMLInput)), true
+ case "Mutation.exportDataProtectionImpactAssessmentsPDF":
+ if e.complexity.Mutation.ExportDataProtectionImpactAssessmentsPDF == nil {
+ break
+ }
+
+ args, err := ec.field_Mutation_exportDataProtectionImpactAssessmentsPDF_args(ctx, rawArgs)
+ if err != nil {
+ return 0, false
+ }
+
+ return e.complexity.Mutation.ExportDataProtectionImpactAssessmentsPDF(childComplexity, args["input"].(types.ExportDataProtectionImpactAssessmentsPDFInput)), true
case "Mutation.exportDocumentVersionPDF":
if e.complexity.Mutation.ExportDocumentVersionPDF == nil {
break
@@ -5965,6 +6015,17 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
}
return e.complexity.Mutation.ExportFramework(childComplexity, args["input"].(types.ExportFrameworkInput)), true
+ case "Mutation.exportProcessingActivitiesPDF":
+ if e.complexity.Mutation.ExportProcessingActivitiesPDF == nil {
+ break
+ }
+
+ args, err := ec.field_Mutation_exportProcessingActivitiesPDF_args(ctx, rawArgs)
+ if err != nil {
+ return 0, false
+ }
+
+ return e.complexity.Mutation.ExportProcessingActivitiesPDF(childComplexity, args["input"].(types.ExportProcessingActivitiesPDFInput)), true
case "Mutation.exportSignableVersionDocumentPDF":
if e.complexity.Mutation.ExportSignableVersionDocumentPDF == nil {
break
@@ -5976,6 +6037,17 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
}
return e.complexity.Mutation.ExportSignableVersionDocumentPDF(childComplexity, args["input"].(types.ExportSignableDocumentVersionPDFInput)), true
+ case "Mutation.exportTransferImpactAssessmentsPDF":
+ if e.complexity.Mutation.ExportTransferImpactAssessmentsPDF == nil {
+ break
+ }
+
+ args, err := ec.field_Mutation_exportTransferImpactAssessmentsPDF_args(ctx, rawArgs)
+ if err != nil {
+ return 0, false
+ }
+
+ return e.complexity.Mutation.ExportTransferImpactAssessmentsPDF(childComplexity, args["input"].(types.ExportTransferImpactAssessmentsPDFInput)), true
case "Mutation.generateDocumentChangelog":
if e.complexity.Mutation.GenerateDocumentChangelog == nil {
break
@@ -10030,9 +10102,12 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler {
ec.unmarshalInputDocumentVersionSignatureOrder,
ec.unmarshalInputEnableSAMLInput,
ec.unmarshalInputEvidenceOrder,
+ ec.unmarshalInputExportDataProtectionImpactAssessmentsPDFInput,
ec.unmarshalInputExportDocumentVersionPDFInput,
ec.unmarshalInputExportFrameworkInput,
+ ec.unmarshalInputExportProcessingActivitiesPDFInput,
ec.unmarshalInputExportSignableDocumentVersionPDFInput,
+ ec.unmarshalInputExportTransferImpactAssessmentsPDFInput,
ec.unmarshalInputFrameworkOrder,
ec.unmarshalInputFulfillEvidenceInput,
ec.unmarshalInputGenerateDocumentChangelogInput,
@@ -13530,6 +13605,15 @@ type Mutation {
exportSignableVersionDocumentPDF(
input: ExportSignableDocumentVersionPDFInput!
): ExportSignableDocumentVersionPDFPayload!
+ exportProcessingActivitiesPDF(
+ input: ExportProcessingActivitiesPDFInput!
+ ): ExportProcessingActivitiesPDFPayload!
+ exportDataProtectionImpactAssessmentsPDF(
+ input: ExportDataProtectionImpactAssessmentsPDFInput!
+ ): ExportDataProtectionImpactAssessmentsPDFPayload!
+ exportTransferImpactAssessmentsPDF(
+ input: ExportTransferImpactAssessmentsPDFInput!
+ ): ExportTransferImpactAssessmentsPDFPayload!
createVendorRiskAssessment(
input: CreateVendorRiskAssessmentInput!
): CreateVendorRiskAssessmentPayload!
@@ -14161,6 +14245,21 @@ input ExportSignableDocumentVersionPDFInput {
documentVersionId: ID!
}
+input ExportProcessingActivitiesPDFInput {
+ organizationId: ID!
+ filter: ProcessingActivityFilter
+}
+
+input ExportDataProtectionImpactAssessmentsPDFInput {
+ organizationId: ID!
+ filter: DataProtectionImpactAssessmentFilter
+}
+
+input ExportTransferImpactAssessmentsPDFInput {
+ organizationId: ID!
+ filter: TransferImpactAssessmentFilter
+}
+
input DeleteDocumentInput {
documentId: ID!
}
@@ -14820,6 +14919,18 @@ type ExportSignableDocumentVersionPDFPayload {
data: String!
}
+type ExportProcessingActivitiesPDFPayload {
+ data: String!
+}
+
+type ExportDataProtectionImpactAssessmentsPDFPayload {
+ data: String!
+}
+
+type ExportTransferImpactAssessmentsPDFPayload {
+ data: String!
+}
+
type UpdateDocumentPayload {
document: Document!
}
@@ -17125,6 +17236,17 @@ func (ec *executionContext) field_Mutation_enableSAML_args(ctx context.Context,
return args, nil
}
+func (ec *executionContext) field_Mutation_exportDataProtectionImpactAssessmentsPDF_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
+ var err error
+ args := map[string]any{}
+ arg0, err := graphql.ProcessArgField(ctx, rawArgs, "input", ec.unmarshalNExportDataProtectionImpactAssessmentsPDFInput2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐExportDataProtectionImpactAssessmentsPDFInput)
+ if err != nil {
+ return nil, err
+ }
+ args["input"] = arg0
+ return args, nil
+}
+
func (ec *executionContext) field_Mutation_exportDocumentVersionPDF_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
var err error
args := map[string]any{}
@@ -17147,6 +17269,17 @@ func (ec *executionContext) field_Mutation_exportFramework_args(ctx context.Cont
return args, nil
}
+func (ec *executionContext) field_Mutation_exportProcessingActivitiesPDF_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
+ var err error
+ args := map[string]any{}
+ arg0, err := graphql.ProcessArgField(ctx, rawArgs, "input", ec.unmarshalNExportProcessingActivitiesPDFInput2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐExportProcessingActivitiesPDFInput)
+ if err != nil {
+ return nil, err
+ }
+ args["input"] = arg0
+ return args, nil
+}
+
func (ec *executionContext) field_Mutation_exportSignableVersionDocumentPDF_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
var err error
args := map[string]any{}
@@ -17158,6 +17291,17 @@ func (ec *executionContext) field_Mutation_exportSignableVersionDocumentPDF_args
return args, nil
}
+func (ec *executionContext) field_Mutation_exportTransferImpactAssessmentsPDF_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
+ var err error
+ args := map[string]any{}
+ arg0, err := graphql.ProcessArgField(ctx, rawArgs, "input", ec.unmarshalNExportTransferImpactAssessmentsPDFInput2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐExportTransferImpactAssessmentsPDFInput)
+ if err != nil {
+ return nil, err
+ }
+ args["input"] = arg0
+ return args, nil
+}
+
func (ec *executionContext) field_Mutation_generateDocumentChangelog_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
var err error
args := map[string]any{}
@@ -29640,6 +29784,35 @@ func (ec *executionContext) fieldContext_EvidenceEdge_node(_ context.Context, fi
return fc, nil
}
+func (ec *executionContext) _ExportDataProtectionImpactAssessmentsPDFPayload_data(ctx context.Context, field graphql.CollectedField, obj *types.ExportDataProtectionImpactAssessmentsPDFPayload) (ret graphql.Marshaler) {
+ return graphql.ResolveField(
+ ctx,
+ ec.OperationContext,
+ field,
+ ec.fieldContext_ExportDataProtectionImpactAssessmentsPDFPayload_data,
+ func(ctx context.Context) (any, error) {
+ return obj.Data, nil
+ },
+ nil,
+ ec.marshalNString2string,
+ true,
+ true,
+ )
+}
+
+func (ec *executionContext) fieldContext_ExportDataProtectionImpactAssessmentsPDFPayload_data(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "ExportDataProtectionImpactAssessmentsPDFPayload",
+ 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) _ExportDocumentVersionPDFPayload_data(ctx context.Context, field graphql.CollectedField, obj *types.ExportDocumentVersionPDFPayload) (ret graphql.Marshaler) {
return graphql.ResolveField(
ctx,
@@ -29698,6 +29871,35 @@ func (ec *executionContext) fieldContext_ExportFrameworkPayload_exportJobId(_ co
return fc, nil
}
+func (ec *executionContext) _ExportProcessingActivitiesPDFPayload_data(ctx context.Context, field graphql.CollectedField, obj *types.ExportProcessingActivitiesPDFPayload) (ret graphql.Marshaler) {
+ return graphql.ResolveField(
+ ctx,
+ ec.OperationContext,
+ field,
+ ec.fieldContext_ExportProcessingActivitiesPDFPayload_data,
+ func(ctx context.Context) (any, error) {
+ return obj.Data, nil
+ },
+ nil,
+ ec.marshalNString2string,
+ true,
+ true,
+ )
+}
+
+func (ec *executionContext) fieldContext_ExportProcessingActivitiesPDFPayload_data(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "ExportProcessingActivitiesPDFPayload",
+ 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) _ExportSignableDocumentVersionPDFPayload_data(ctx context.Context, field graphql.CollectedField, obj *types.ExportSignableDocumentVersionPDFPayload) (ret graphql.Marshaler) {
return graphql.ResolveField(
ctx,
@@ -29727,6 +29929,35 @@ func (ec *executionContext) fieldContext_ExportSignableDocumentVersionPDFPayload
return fc, nil
}
+func (ec *executionContext) _ExportTransferImpactAssessmentsPDFPayload_data(ctx context.Context, field graphql.CollectedField, obj *types.ExportTransferImpactAssessmentsPDFPayload) (ret graphql.Marshaler) {
+ return graphql.ResolveField(
+ ctx,
+ ec.OperationContext,
+ field,
+ ec.fieldContext_ExportTransferImpactAssessmentsPDFPayload_data,
+ func(ctx context.Context) (any, error) {
+ return obj.Data, nil
+ },
+ nil,
+ ec.marshalNString2string,
+ true,
+ true,
+ )
+}
+
+func (ec *executionContext) fieldContext_ExportTransferImpactAssessmentsPDFPayload_data(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "ExportTransferImpactAssessmentsPDFPayload",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type String does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
func (ec *executionContext) _File_id(ctx context.Context, field graphql.CollectedField, obj *types.File) (ret graphql.Marshaler) {
return graphql.ResolveField(
ctx,
@@ -37412,6 +37643,141 @@ func (ec *executionContext) fieldContext_Mutation_exportSignableVersionDocumentP
return fc, nil
}
+func (ec *executionContext) _Mutation_exportProcessingActivitiesPDF(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
+ return graphql.ResolveField(
+ ctx,
+ ec.OperationContext,
+ field,
+ ec.fieldContext_Mutation_exportProcessingActivitiesPDF,
+ func(ctx context.Context) (any, error) {
+ fc := graphql.GetFieldContext(ctx)
+ return ec.resolvers.Mutation().ExportProcessingActivitiesPDF(ctx, fc.Args["input"].(types.ExportProcessingActivitiesPDFInput))
+ },
+ nil,
+ ec.marshalNExportProcessingActivitiesPDFPayload2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐExportProcessingActivitiesPDFPayload,
+ true,
+ true,
+ )
+}
+
+func (ec *executionContext) fieldContext_Mutation_exportProcessingActivitiesPDF(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "Mutation",
+ Field: field,
+ IsMethod: true,
+ IsResolver: true,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ switch field.Name {
+ case "data":
+ return ec.fieldContext_ExportProcessingActivitiesPDFPayload_data(ctx, field)
+ }
+ return nil, fmt.Errorf("no field named %q was found under type ExportProcessingActivitiesPDFPayload", 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_exportProcessingActivitiesPDF_args(ctx, field.ArgumentMap(ec.Variables)); err != nil {
+ ec.Error(ctx, err)
+ return fc, err
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _Mutation_exportDataProtectionImpactAssessmentsPDF(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
+ return graphql.ResolveField(
+ ctx,
+ ec.OperationContext,
+ field,
+ ec.fieldContext_Mutation_exportDataProtectionImpactAssessmentsPDF,
+ func(ctx context.Context) (any, error) {
+ fc := graphql.GetFieldContext(ctx)
+ return ec.resolvers.Mutation().ExportDataProtectionImpactAssessmentsPDF(ctx, fc.Args["input"].(types.ExportDataProtectionImpactAssessmentsPDFInput))
+ },
+ nil,
+ ec.marshalNExportDataProtectionImpactAssessmentsPDFPayload2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐExportDataProtectionImpactAssessmentsPDFPayload,
+ true,
+ true,
+ )
+}
+
+func (ec *executionContext) fieldContext_Mutation_exportDataProtectionImpactAssessmentsPDF(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "Mutation",
+ Field: field,
+ IsMethod: true,
+ IsResolver: true,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ switch field.Name {
+ case "data":
+ return ec.fieldContext_ExportDataProtectionImpactAssessmentsPDFPayload_data(ctx, field)
+ }
+ return nil, fmt.Errorf("no field named %q was found under type ExportDataProtectionImpactAssessmentsPDFPayload", 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_exportDataProtectionImpactAssessmentsPDF_args(ctx, field.ArgumentMap(ec.Variables)); err != nil {
+ ec.Error(ctx, err)
+ return fc, err
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _Mutation_exportTransferImpactAssessmentsPDF(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
+ return graphql.ResolveField(
+ ctx,
+ ec.OperationContext,
+ field,
+ ec.fieldContext_Mutation_exportTransferImpactAssessmentsPDF,
+ func(ctx context.Context) (any, error) {
+ fc := graphql.GetFieldContext(ctx)
+ return ec.resolvers.Mutation().ExportTransferImpactAssessmentsPDF(ctx, fc.Args["input"].(types.ExportTransferImpactAssessmentsPDFInput))
+ },
+ nil,
+ ec.marshalNExportTransferImpactAssessmentsPDFPayload2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐExportTransferImpactAssessmentsPDFPayload,
+ true,
+ true,
+ )
+}
+
+func (ec *executionContext) fieldContext_Mutation_exportTransferImpactAssessmentsPDF(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "Mutation",
+ Field: field,
+ IsMethod: true,
+ IsResolver: true,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ switch field.Name {
+ case "data":
+ return ec.fieldContext_ExportTransferImpactAssessmentsPDFPayload_data(ctx, field)
+ }
+ return nil, fmt.Errorf("no field named %q was found under type ExportTransferImpactAssessmentsPDFPayload", 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_exportTransferImpactAssessmentsPDF_args(ctx, field.ArgumentMap(ec.Variables)); err != nil {
+ ec.Error(ctx, err)
+ return fc, err
+ }
+ return fc, nil
+}
+
func (ec *executionContext) _Mutation_createVendorRiskAssessment(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
return graphql.ResolveField(
ctx,
@@ -65022,6 +65388,40 @@ func (ec *executionContext) unmarshalInputEvidenceOrder(ctx context.Context, obj
return it, nil
}
+func (ec *executionContext) unmarshalInputExportDataProtectionImpactAssessmentsPDFInput(ctx context.Context, obj any) (types.ExportDataProtectionImpactAssessmentsPDFInput, error) {
+ var it types.ExportDataProtectionImpactAssessmentsPDFInput
+ asMap := map[string]any{}
+ for k, v := range obj.(map[string]any) {
+ asMap[k] = v
+ }
+
+ fieldsInOrder := [...]string{"organizationId", "filter"}
+ for _, k := range fieldsInOrder {
+ v, ok := asMap[k]
+ if !ok {
+ continue
+ }
+ switch k {
+ case "organizationId":
+ ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("organizationId"))
+ data, err := ec.unmarshalNID2goᚗproboᚗincᚋproboᚋpkgᚋgidᚐGID(ctx, v)
+ if err != nil {
+ return it, err
+ }
+ it.OrganizationID = data
+ case "filter":
+ ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("filter"))
+ data, err := ec.unmarshalODataProtectionImpactAssessmentFilter2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐDataProtectionImpactAssessmentFilter(ctx, v)
+ if err != nil {
+ return it, err
+ }
+ it.Filter = data
+ }
+ }
+
+ return it, nil
+}
+
func (ec *executionContext) unmarshalInputExportDocumentVersionPDFInput(ctx context.Context, obj any) (types.ExportDocumentVersionPDFInput, error) {
var it types.ExportDocumentVersionPDFInput
asMap := map[string]any{}
@@ -65097,6 +65497,40 @@ func (ec *executionContext) unmarshalInputExportFrameworkInput(ctx context.Conte
return it, nil
}
+func (ec *executionContext) unmarshalInputExportProcessingActivitiesPDFInput(ctx context.Context, obj any) (types.ExportProcessingActivitiesPDFInput, error) {
+ var it types.ExportProcessingActivitiesPDFInput
+ asMap := map[string]any{}
+ for k, v := range obj.(map[string]any) {
+ asMap[k] = v
+ }
+
+ fieldsInOrder := [...]string{"organizationId", "filter"}
+ for _, k := range fieldsInOrder {
+ v, ok := asMap[k]
+ if !ok {
+ continue
+ }
+ switch k {
+ case "organizationId":
+ ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("organizationId"))
+ data, err := ec.unmarshalNID2goᚗproboᚗincᚋproboᚋpkgᚋgidᚐGID(ctx, v)
+ if err != nil {
+ return it, err
+ }
+ it.OrganizationID = data
+ case "filter":
+ ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("filter"))
+ data, err := ec.unmarshalOProcessingActivityFilter2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐProcessingActivityFilter(ctx, v)
+ if err != nil {
+ return it, err
+ }
+ it.Filter = data
+ }
+ }
+
+ return it, nil
+}
+
func (ec *executionContext) unmarshalInputExportSignableDocumentVersionPDFInput(ctx context.Context, obj any) (types.ExportSignableDocumentVersionPDFInput, error) {
var it types.ExportSignableDocumentVersionPDFInput
asMap := map[string]any{}
@@ -65124,6 +65558,40 @@ func (ec *executionContext) unmarshalInputExportSignableDocumentVersionPDFInput(
return it, nil
}
+func (ec *executionContext) unmarshalInputExportTransferImpactAssessmentsPDFInput(ctx context.Context, obj any) (types.ExportTransferImpactAssessmentsPDFInput, error) {
+ var it types.ExportTransferImpactAssessmentsPDFInput
+ asMap := map[string]any{}
+ for k, v := range obj.(map[string]any) {
+ asMap[k] = v
+ }
+
+ fieldsInOrder := [...]string{"organizationId", "filter"}
+ for _, k := range fieldsInOrder {
+ v, ok := asMap[k]
+ if !ok {
+ continue
+ }
+ switch k {
+ case "organizationId":
+ ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("organizationId"))
+ data, err := ec.unmarshalNID2goᚗproboᚗincᚋproboᚋpkgᚋgidᚐGID(ctx, v)
+ if err != nil {
+ return it, err
+ }
+ it.OrganizationID = data
+ case "filter":
+ ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("filter"))
+ data, err := ec.unmarshalOTransferImpactAssessmentFilter2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐTransferImpactAssessmentFilter(ctx, v)
+ if err != nil {
+ return it, err
+ }
+ it.Filter = data
+ }
+ }
+
+ return it, nil
+}
+
func (ec *executionContext) unmarshalInputFrameworkOrder(ctx context.Context, obj any) (types.FrameworkOrderBy, error) {
var it types.FrameworkOrderBy
asMap := map[string]any{}
@@ -76415,6 +76883,45 @@ func (ec *executionContext) _EvidenceEdge(ctx context.Context, sel ast.Selection
return out
}
+var exportDataProtectionImpactAssessmentsPDFPayloadImplementors = []string{"ExportDataProtectionImpactAssessmentsPDFPayload"}
+
+func (ec *executionContext) _ExportDataProtectionImpactAssessmentsPDFPayload(ctx context.Context, sel ast.SelectionSet, obj *types.ExportDataProtectionImpactAssessmentsPDFPayload) graphql.Marshaler {
+ fields := graphql.CollectFields(ec.OperationContext, sel, exportDataProtectionImpactAssessmentsPDFPayloadImplementors)
+
+ 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("ExportDataProtectionImpactAssessmentsPDFPayload")
+ case "data":
+ out.Values[i] = ec._ExportDataProtectionImpactAssessmentsPDFPayload_data(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ default:
+ panic("unknown field " + strconv.Quote(field.Name))
+ }
+ }
+ out.Dispatch(ctx)
+ if out.Invalids > 0 {
+ return graphql.Null
+ }
+
+ atomic.AddInt32(&ec.deferred, int32(len(deferred)))
+
+ for label, dfs := range deferred {
+ ec.processDeferredGroup(graphql.DeferredGroup{
+ Label: label,
+ Path: graphql.GetPath(ctx),
+ FieldSet: dfs,
+ Context: ctx,
+ })
+ }
+
+ return out
+}
+
var exportDocumentVersionPDFPayloadImplementors = []string{"ExportDocumentVersionPDFPayload"}
func (ec *executionContext) _ExportDocumentVersionPDFPayload(ctx context.Context, sel ast.SelectionSet, obj *types.ExportDocumentVersionPDFPayload) graphql.Marshaler {
@@ -76493,6 +77000,45 @@ func (ec *executionContext) _ExportFrameworkPayload(ctx context.Context, sel ast
return out
}
+var exportProcessingActivitiesPDFPayloadImplementors = []string{"ExportProcessingActivitiesPDFPayload"}
+
+func (ec *executionContext) _ExportProcessingActivitiesPDFPayload(ctx context.Context, sel ast.SelectionSet, obj *types.ExportProcessingActivitiesPDFPayload) graphql.Marshaler {
+ fields := graphql.CollectFields(ec.OperationContext, sel, exportProcessingActivitiesPDFPayloadImplementors)
+
+ 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("ExportProcessingActivitiesPDFPayload")
+ case "data":
+ out.Values[i] = ec._ExportProcessingActivitiesPDFPayload_data(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ default:
+ panic("unknown field " + strconv.Quote(field.Name))
+ }
+ }
+ out.Dispatch(ctx)
+ if out.Invalids > 0 {
+ return graphql.Null
+ }
+
+ atomic.AddInt32(&ec.deferred, int32(len(deferred)))
+
+ for label, dfs := range deferred {
+ ec.processDeferredGroup(graphql.DeferredGroup{
+ Label: label,
+ Path: graphql.GetPath(ctx),
+ FieldSet: dfs,
+ Context: ctx,
+ })
+ }
+
+ return out
+}
+
var exportSignableDocumentVersionPDFPayloadImplementors = []string{"ExportSignableDocumentVersionPDFPayload"}
func (ec *executionContext) _ExportSignableDocumentVersionPDFPayload(ctx context.Context, sel ast.SelectionSet, obj *types.ExportSignableDocumentVersionPDFPayload) graphql.Marshaler {
@@ -76532,6 +77078,45 @@ func (ec *executionContext) _ExportSignableDocumentVersionPDFPayload(ctx context
return out
}
+var exportTransferImpactAssessmentsPDFPayloadImplementors = []string{"ExportTransferImpactAssessmentsPDFPayload"}
+
+func (ec *executionContext) _ExportTransferImpactAssessmentsPDFPayload(ctx context.Context, sel ast.SelectionSet, obj *types.ExportTransferImpactAssessmentsPDFPayload) graphql.Marshaler {
+ fields := graphql.CollectFields(ec.OperationContext, sel, exportTransferImpactAssessmentsPDFPayloadImplementors)
+
+ 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("ExportTransferImpactAssessmentsPDFPayload")
+ case "data":
+ out.Values[i] = ec._ExportTransferImpactAssessmentsPDFPayload_data(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ default:
+ panic("unknown field " + strconv.Quote(field.Name))
+ }
+ }
+ out.Dispatch(ctx)
+ if out.Invalids > 0 {
+ return graphql.Null
+ }
+
+ atomic.AddInt32(&ec.deferred, int32(len(deferred)))
+
+ for label, dfs := range deferred {
+ ec.processDeferredGroup(graphql.DeferredGroup{
+ Label: label,
+ Path: graphql.GetPath(ctx),
+ FieldSet: dfs,
+ Context: ctx,
+ })
+ }
+
+ return out
+}
+
var fileImplementors = []string{"File"}
func (ec *executionContext) _File(ctx context.Context, sel ast.SelectionSet, obj *types.File) graphql.Marshaler {
@@ -79042,6 +79627,27 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet)
if out.Values[i] == graphql.Null {
out.Invalids++
}
+ case "exportProcessingActivitiesPDF":
+ out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
+ return ec._Mutation_exportProcessingActivitiesPDF(ctx, field)
+ })
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ case "exportDataProtectionImpactAssessmentsPDF":
+ out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
+ return ec._Mutation_exportDataProtectionImpactAssessmentsPDF(ctx, field)
+ })
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ case "exportTransferImpactAssessmentsPDF":
+ out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
+ return ec._Mutation_exportTransferImpactAssessmentsPDF(ctx, field)
+ })
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
case "createVendorRiskAssessment":
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
return ec._Mutation_createVendorRiskAssessment(ctx, field)
@@ -93526,6 +94132,25 @@ var (
}
)
+func (ec *executionContext) unmarshalNExportDataProtectionImpactAssessmentsPDFInput2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐExportDataProtectionImpactAssessmentsPDFInput(ctx context.Context, v any) (types.ExportDataProtectionImpactAssessmentsPDFInput, error) {
+ res, err := ec.unmarshalInputExportDataProtectionImpactAssessmentsPDFInput(ctx, v)
+ return res, graphql.ErrorOnPath(ctx, err)
+}
+
+func (ec *executionContext) marshalNExportDataProtectionImpactAssessmentsPDFPayload2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐExportDataProtectionImpactAssessmentsPDFPayload(ctx context.Context, sel ast.SelectionSet, v types.ExportDataProtectionImpactAssessmentsPDFPayload) graphql.Marshaler {
+ return ec._ExportDataProtectionImpactAssessmentsPDFPayload(ctx, sel, &v)
+}
+
+func (ec *executionContext) marshalNExportDataProtectionImpactAssessmentsPDFPayload2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐExportDataProtectionImpactAssessmentsPDFPayload(ctx context.Context, sel ast.SelectionSet, v *types.ExportDataProtectionImpactAssessmentsPDFPayload) graphql.Marshaler {
+ if v == nil {
+ if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
+ graphql.AddErrorf(ctx, "the requested element is null which the schema does not allow")
+ }
+ return graphql.Null
+ }
+ return ec._ExportDataProtectionImpactAssessmentsPDFPayload(ctx, sel, v)
+}
+
func (ec *executionContext) unmarshalNExportDocumentVersionPDFInput2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐExportDocumentVersionPDFInput(ctx context.Context, v any) (types.ExportDocumentVersionPDFInput, error) {
res, err := ec.unmarshalInputExportDocumentVersionPDFInput(ctx, v)
return res, graphql.ErrorOnPath(ctx, err)
@@ -93564,6 +94189,25 @@ func (ec *executionContext) marshalNExportFrameworkPayload2ᚖgoᚗproboᚗinc
return ec._ExportFrameworkPayload(ctx, sel, v)
}
+func (ec *executionContext) unmarshalNExportProcessingActivitiesPDFInput2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐExportProcessingActivitiesPDFInput(ctx context.Context, v any) (types.ExportProcessingActivitiesPDFInput, error) {
+ res, err := ec.unmarshalInputExportProcessingActivitiesPDFInput(ctx, v)
+ return res, graphql.ErrorOnPath(ctx, err)
+}
+
+func (ec *executionContext) marshalNExportProcessingActivitiesPDFPayload2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐExportProcessingActivitiesPDFPayload(ctx context.Context, sel ast.SelectionSet, v types.ExportProcessingActivitiesPDFPayload) graphql.Marshaler {
+ return ec._ExportProcessingActivitiesPDFPayload(ctx, sel, &v)
+}
+
+func (ec *executionContext) marshalNExportProcessingActivitiesPDFPayload2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐExportProcessingActivitiesPDFPayload(ctx context.Context, sel ast.SelectionSet, v *types.ExportProcessingActivitiesPDFPayload) graphql.Marshaler {
+ if v == nil {
+ if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
+ graphql.AddErrorf(ctx, "the requested element is null which the schema does not allow")
+ }
+ return graphql.Null
+ }
+ return ec._ExportProcessingActivitiesPDFPayload(ctx, sel, v)
+}
+
func (ec *executionContext) unmarshalNExportSignableDocumentVersionPDFInput2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐExportSignableDocumentVersionPDFInput(ctx context.Context, v any) (types.ExportSignableDocumentVersionPDFInput, error) {
res, err := ec.unmarshalInputExportSignableDocumentVersionPDFInput(ctx, v)
return res, graphql.ErrorOnPath(ctx, err)
@@ -93583,6 +94227,25 @@ func (ec *executionContext) marshalNExportSignableDocumentVersionPDFPayload2ᚖg
return ec._ExportSignableDocumentVersionPDFPayload(ctx, sel, v)
}
+func (ec *executionContext) unmarshalNExportTransferImpactAssessmentsPDFInput2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐExportTransferImpactAssessmentsPDFInput(ctx context.Context, v any) (types.ExportTransferImpactAssessmentsPDFInput, error) {
+ res, err := ec.unmarshalInputExportTransferImpactAssessmentsPDFInput(ctx, v)
+ return res, graphql.ErrorOnPath(ctx, err)
+}
+
+func (ec *executionContext) marshalNExportTransferImpactAssessmentsPDFPayload2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐExportTransferImpactAssessmentsPDFPayload(ctx context.Context, sel ast.SelectionSet, v types.ExportTransferImpactAssessmentsPDFPayload) graphql.Marshaler {
+ return ec._ExportTransferImpactAssessmentsPDFPayload(ctx, sel, &v)
+}
+
+func (ec *executionContext) marshalNExportTransferImpactAssessmentsPDFPayload2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐExportTransferImpactAssessmentsPDFPayload(ctx context.Context, sel ast.SelectionSet, v *types.ExportTransferImpactAssessmentsPDFPayload) graphql.Marshaler {
+ if v == nil {
+ if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
+ graphql.AddErrorf(ctx, "the requested element is null which the schema does not allow")
+ }
+ return graphql.Null
+ }
+ return ec._ExportTransferImpactAssessmentsPDFPayload(ctx, sel, v)
+}
+
func (ec *executionContext) marshalNFramework2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐFramework(ctx context.Context, sel ast.SelectionSet, v types.Framework) graphql.Marshaler {
return ec._Framework(ctx, sel, &v)
}
diff --git a/pkg/server/api/console/v1/types/types.go b/pkg/server/api/console/v1/types/types.go
index 0b79864a8..2f92dd76b 100644
--- a/pkg/server/api/console/v1/types/types.go
+++ b/pkg/server/api/console/v1/types/types.go
@@ -1220,6 +1220,15 @@ type EvidenceEdge struct {
Node *Evidence `json:"node"`
}
+type ExportDataProtectionImpactAssessmentsPDFInput struct {
+ OrganizationID gid.GID `json:"organizationId"`
+ Filter *DataProtectionImpactAssessmentFilter `json:"filter,omitempty"`
+}
+
+type ExportDataProtectionImpactAssessmentsPDFPayload struct {
+ Data string `json:"data"`
+}
+
type ExportDocumentVersionPDFInput struct {
DocumentVersionID gid.GID `json:"documentVersionId"`
WithWatermark bool `json:"withWatermark"`
@@ -1239,6 +1248,15 @@ type ExportFrameworkPayload struct {
ExportJobID gid.GID `json:"exportJobId"`
}
+type ExportProcessingActivitiesPDFInput struct {
+ OrganizationID gid.GID `json:"organizationId"`
+ Filter *ProcessingActivityFilter `json:"filter,omitempty"`
+}
+
+type ExportProcessingActivitiesPDFPayload struct {
+ Data string `json:"data"`
+}
+
type ExportSignableDocumentVersionPDFInput struct {
DocumentVersionID gid.GID `json:"documentVersionId"`
}
@@ -1247,6 +1265,15 @@ type ExportSignableDocumentVersionPDFPayload struct {
Data string `json:"data"`
}
+type ExportTransferImpactAssessmentsPDFInput struct {
+ OrganizationID gid.GID `json:"organizationId"`
+ Filter *TransferImpactAssessmentFilter `json:"filter,omitempty"`
+}
+
+type ExportTransferImpactAssessmentsPDFPayload struct {
+ Data string `json:"data"`
+}
+
type File struct {
ID gid.GID `json:"id"`
MimeType string `json:"mimeType"`
diff --git a/pkg/server/api/console/v1/v1_resolver.go b/pkg/server/api/console/v1/v1_resolver.go
index 5d4a38ce9..71f3ba268 100644
--- a/pkg/server/api/console/v1/v1_resolver.go
+++ b/pkg/server/api/console/v1/v1_resolver.go
@@ -3745,6 +3745,84 @@ func (r *mutationResolver) ExportSignableVersionDocumentPDF(ctx context.Context,
}, nil
}
+// ExportProcessingActivitiesPDF is the resolver for the exportProcessingActivitiesPDF field.
+func (r *mutationResolver) ExportProcessingActivitiesPDF(ctx context.Context, input types.ExportProcessingActivitiesPDFInput) (*types.ExportProcessingActivitiesPDFPayload, error) {
+ r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionExportProcessingActivitiesPDF)
+
+ prb := r.ProboService(ctx, input.OrganizationID.TenantID())
+
+ var snapshotIDPtr *gid.GID
+ if input.Filter != nil {
+ snapshotIDPtr = input.Filter.SnapshotID
+ }
+ processingActivityFilter := coredata.NewProcessingActivityFilter(&snapshotIDPtr)
+
+ pdf, err := prb.ProcessingActivities.ExportPDF(ctx, input.OrganizationID, processingActivityFilter)
+ if err != nil {
+ var errNotFound *coredata.ErrNoProcessingActivitiesFound
+ if errors.As(err, &errNotFound) {
+ return nil, gqlutils.NotFound(errNotFound)
+ }
+ panic(fmt.Errorf("cannot export processing activities PDF: %w", err))
+ }
+
+ return &types.ExportProcessingActivitiesPDFPayload{
+ Data: fmt.Sprintf("data:application/pdf;base64,%s", base64.StdEncoding.EncodeToString(pdf)),
+ }, nil
+}
+
+// ExportDataProtectionImpactAssessmentsPDF is the resolver for the exportDataProtectionImpactAssessmentsPDF field.
+func (r *mutationResolver) ExportDataProtectionImpactAssessmentsPDF(ctx context.Context, input types.ExportDataProtectionImpactAssessmentsPDFInput) (*types.ExportDataProtectionImpactAssessmentsPDFPayload, error) {
+ r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionExportDataProtectionImpactAssessmentsPDF)
+
+ prb := r.ProboService(ctx, input.OrganizationID.TenantID())
+
+ var snapshotIDPtr *gid.GID
+ if input.Filter != nil {
+ snapshotIDPtr = input.Filter.SnapshotID
+ }
+ dpiaFilter := coredata.NewDataProtectionImpactAssessmentFilter(&snapshotIDPtr)
+
+ pdf, err := prb.DataProtectionImpactAssessments.ExportPDF(ctx, input.OrganizationID, dpiaFilter)
+ if err != nil {
+ var errNotFound *coredata.ErrNoDataProtectionImpactAssessmentsFound
+ if errors.As(err, &errNotFound) {
+ return nil, gqlutils.NotFound(errNotFound)
+ }
+ panic(fmt.Errorf("cannot export data protection impact assessments PDF: %w", err))
+ }
+
+ return &types.ExportDataProtectionImpactAssessmentsPDFPayload{
+ Data: fmt.Sprintf("data:application/pdf;base64,%s", base64.StdEncoding.EncodeToString(pdf)),
+ }, nil
+}
+
+// ExportTransferImpactAssessmentsPDF is the resolver for the exportTransferImpactAssessmentsPDF field.
+func (r *mutationResolver) ExportTransferImpactAssessmentsPDF(ctx context.Context, input types.ExportTransferImpactAssessmentsPDFInput) (*types.ExportTransferImpactAssessmentsPDFPayload, error) {
+ r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionExportTransferImpactAssessmentsPDF)
+
+ prb := r.ProboService(ctx, input.OrganizationID.TenantID())
+
+ var snapshotIDPtr *gid.GID
+ if input.Filter != nil {
+ snapshotIDPtr = input.Filter.SnapshotID
+ }
+ tiaFilter := coredata.NewTransferImpactAssessmentFilter(&snapshotIDPtr)
+
+ pdf, err := prb.TransferImpactAssessments.ExportPDF(ctx, input.OrganizationID, tiaFilter)
+ if err != nil {
+ var errNotFound *coredata.ErrNoTransferImpactAssessmentsFound
+ if errors.As(err, &errNotFound) {
+ return nil, gqlutils.NotFound(errNotFound)
+ }
+ panic(fmt.Errorf("cannot export transfer impact assessments PDF: %w", err))
+ }
+
+ return &types.ExportTransferImpactAssessmentsPDFPayload{
+ Data: fmt.Sprintf("data:application/pdf;base64,%s", base64.StdEncoding.EncodeToString(pdf)),
+ }, nil
+}
+
// CreateVendorRiskAssessment is the resolver for the createVendorRiskAssessment field.
func (r *mutationResolver) CreateVendorRiskAssessment(ctx context.Context, input types.CreateVendorRiskAssessmentInput) (*types.CreateVendorRiskAssessmentPayload, error) {
r.MustBeAuthorized(ctx, input.VendorID, authz.ActionCreateVendorRiskAssessment)