Add watermark to public trust center documents
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
@@ -16,7 +16,6 @@ export interface TrustCenterAudit {
|
||||
report: {
|
||||
id: string;
|
||||
filename: string;
|
||||
downloadUrl: string | null;
|
||||
} | null;
|
||||
}
|
||||
|
||||
@@ -71,6 +70,12 @@ interface ExportDocumentPDFData {
|
||||
};
|
||||
}
|
||||
|
||||
interface ExportReportPDFData {
|
||||
exportReportPDF: {
|
||||
data: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface CreateTrustCenterAccessData {
|
||||
createTrustCenterAccess: {
|
||||
trustCenterAccess: {
|
||||
@@ -111,7 +116,13 @@ interface AcceptNonDisclosureAgreementVariables {
|
||||
};
|
||||
}
|
||||
|
||||
type GraphQLVariables = TrustCenterQueryVariables | ExportDocumentPDFVariables | CreateTrustCenterAccessVariables | AcceptNonDisclosureAgreementVariables | Record<string, never>;
|
||||
interface ExportReportPDFVariables {
|
||||
input: {
|
||||
reportId: string;
|
||||
};
|
||||
}
|
||||
|
||||
type GraphQLVariables = TrustCenterQueryVariables | ExportDocumentPDFVariables | ExportReportPDFVariables | CreateTrustCenterAccessVariables | AcceptNonDisclosureAgreementVariables | Record<string, never>;
|
||||
|
||||
async function trustCenterGraphQLRequest<T = unknown>(
|
||||
operationName: string,
|
||||
@@ -189,7 +200,6 @@ const TRUST_CENTER_QUERY = `
|
||||
report {
|
||||
id
|
||||
filename
|
||||
downloadUrl
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -219,6 +229,16 @@ const EXPORT_DOCUMENT_PDF_MUTATION = `
|
||||
}
|
||||
`;
|
||||
|
||||
const EXPORT_REPORT_PDF_MUTATION = `
|
||||
mutation PublicTrustCenterAuditsExportReportPDFMutation(
|
||||
$input: ExportReportPDFInput!
|
||||
) {
|
||||
exportReportPDF(input: $input) {
|
||||
data
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const CREATE_TRUST_CENTER_ACCESS_MUTATION = `
|
||||
mutation PublicTrustCenterAccessRequestDialogMutation(
|
||||
$input: CreateTrustCenterAccessInput!
|
||||
@@ -304,6 +324,30 @@ export function useExportDocumentPDF() {
|
||||
});
|
||||
}
|
||||
|
||||
export function useExportReportPDF() {
|
||||
return useMutation<ExportReportPDFData, Error, string>({
|
||||
mutationFn: async (reportId: string) => {
|
||||
const result = await trustCenterGraphQLRequest<ExportReportPDFData>(
|
||||
"PublicTrustCenterAuditsExportReportPDFMutation",
|
||||
EXPORT_REPORT_PDF_MUTATION,
|
||||
{ input: { reportId } }
|
||||
);
|
||||
|
||||
if (result.errors && result.errors.length > 0) {
|
||||
throw new Error(
|
||||
`GraphQL error: ${result.errors.map((e) => e.message).join(", ")}`
|
||||
);
|
||||
}
|
||||
|
||||
if (!result.data) {
|
||||
throw new Error("No data returned from mutation");
|
||||
}
|
||||
|
||||
return result.data;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useCreateTrustCenterAccess() {
|
||||
return useMutation<CreateTrustCenterAccessData, Error, { trustCenterId: string; email: string; name: string }>({
|
||||
mutationFn: async (input: { trustCenterId: string; email: string; name: string }) => {
|
||||
|
||||
@@ -9,11 +9,13 @@ import {
|
||||
Button,
|
||||
IconArrowDown,
|
||||
IconLock,
|
||||
useToast,
|
||||
} from "@probo/ui";
|
||||
import { useTranslate } from "@probo/i18n";
|
||||
import { sprintf } from "@probo/helpers";
|
||||
import { FrameworkLogo } from "/components/FrameworkLogo";
|
||||
import { PublicTrustCenterAccessRequestDialog } from "./PublicTrustCenterAccessRequestDialog";
|
||||
import { useExportReportPDF } from "../../hooks/useTrustCenterQueries";
|
||||
import type { TrustCenterAudit } from "../pages/PublicTrustCenterPage";
|
||||
|
||||
type Props = {
|
||||
@@ -30,6 +32,31 @@ export function PublicTrustCenterAudits({
|
||||
trustCenterId
|
||||
}: Props) {
|
||||
const { __ } = useTranslate();
|
||||
const { toast } = useToast();
|
||||
|
||||
const mutation = useExportReportPDF();
|
||||
|
||||
const handleDownload = (report: NonNullable<TrustCenterAudit["report"]>) => {
|
||||
mutation.mutate(report.id, {
|
||||
onSuccess: (data) => {
|
||||
if (data.exportReportPDF?.data) {
|
||||
const link = window.document.createElement("a");
|
||||
link.href = data.exportReportPDF.data;
|
||||
link.download = `${report.filename}`;
|
||||
window.document.body.appendChild(link);
|
||||
link.click();
|
||||
window.document.body.removeChild(link);
|
||||
}
|
||||
},
|
||||
onError: () => {
|
||||
toast({
|
||||
title: __("Download Failed"),
|
||||
description: __("Unable to download the report. Please try again."),
|
||||
variant: "error",
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
if (audits.length === 0) {
|
||||
return (
|
||||
@@ -67,8 +94,6 @@ export function PublicTrustCenterAudits({
|
||||
<Tbody>
|
||||
{audits.map((audit) => {
|
||||
const hasReport = audit.report !== null;
|
||||
const downloadUrl = audit.report?.downloadUrl;
|
||||
const reportName = audit.report?.filename || __("Compliance Report");
|
||||
|
||||
return (
|
||||
<Tr key={audit.id}>
|
||||
@@ -102,25 +127,15 @@ export function PublicTrustCenterAudits({
|
||||
trustCenterId={trustCenterId}
|
||||
organizationName={organizationName}
|
||||
/>
|
||||
) : downloadUrl ? (
|
||||
) : (
|
||||
<Button
|
||||
variant="secondary"
|
||||
icon={IconArrowDown}
|
||||
onClick={() => {
|
||||
const link = document.createElement('a');
|
||||
link.href = downloadUrl;
|
||||
link.download = reportName;
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
}}
|
||||
onClick={() => handleDownload(audit.report!)}
|
||||
disabled={mutation.isPending}
|
||||
>
|
||||
{__("Download")}
|
||||
{mutation.isPending ? __("Downloading...") : __("Download")}
|
||||
</Button>
|
||||
) : (
|
||||
<span className="text-txt-tertiary text-sm">
|
||||
{__("Not available")}
|
||||
</span>
|
||||
)}
|
||||
</Td>
|
||||
</Tr>
|
||||
|
||||
6
go.mod
6
go.mod
@@ -18,6 +18,7 @@ require (
|
||||
github.com/jackc/pgx/v5 v5.7.5
|
||||
github.com/jhillyerd/enmime v1.3.0
|
||||
github.com/openai/openai-go v1.8.2
|
||||
github.com/pdfcpu/pdfcpu v0.11.0
|
||||
github.com/prometheus/client_golang v1.22.0
|
||||
github.com/stretchr/testify v1.10.0
|
||||
github.com/vektah/gqlparser/v2 v2.5.30
|
||||
@@ -61,6 +62,9 @@ require (
|
||||
github.com/gorilla/websocket v1.5.3 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 // indirect
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
||||
github.com/hhrutter/lzw v1.0.0 // indirect
|
||||
github.com/hhrutter/pkcs7 v0.2.0 // indirect
|
||||
github.com/hhrutter/tiff v1.0.2 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
||||
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
||||
@@ -96,6 +100,7 @@ require (
|
||||
go.opentelemetry.io/otel/sdk v1.37.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.7.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
||||
golang.org/x/image v0.27.0 // indirect
|
||||
golang.org/x/mod v0.25.0 // indirect
|
||||
golang.org/x/net v0.41.0 // indirect
|
||||
golang.org/x/sync v0.15.0 // indirect
|
||||
@@ -106,6 +111,7 @@ require (
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect
|
||||
google.golang.org/grpc v1.73.0 // indirect
|
||||
google.golang.org/protobuf v1.36.6 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
sigs.k8s.io/yaml v1.5.0 // indirect
|
||||
)
|
||||
|
||||
14
go.sum
14
go.sum
@@ -92,6 +92,12 @@ github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 h1:X5VWvz21y3gzm9Nw/kaUeku/1+u
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1/go.mod h1:Zanoh4+gvIgluNqcfMVTJueD4wSS5hT7zTt4Mrutd90=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
||||
github.com/hhrutter/lzw v1.0.0 h1:laL89Llp86W3rRs83LvKbwYRx6INE8gDn0XNb1oXtm0=
|
||||
github.com/hhrutter/lzw v1.0.0/go.mod h1:2HC6DJSn/n6iAZfgM3Pg+cP1KxeWc3ezG8bBqW5+WEo=
|
||||
github.com/hhrutter/pkcs7 v0.2.0 h1:i4HN2XMbGQpZRnKBLsUwO3dSckzgX142TNqY/KfXg+I=
|
||||
github.com/hhrutter/pkcs7 v0.2.0/go.mod h1:aEzKz0+ZAlz7YaEMY47jDHL14hVWD6iXt0AgqgAvWgE=
|
||||
github.com/hhrutter/tiff v1.0.2 h1:7H3FQQpKu/i5WaSChoD1nnJbGx4MxU5TlNqqpxw55z8=
|
||||
github.com/hhrutter/tiff v1.0.2/go.mod h1:pcOeuK5loFUE7Y/WnzGw20YxUdnqjY1P0Jlcieb/cCw=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
||||
@@ -125,6 +131,8 @@ github.com/openai/openai-go v1.8.2 h1:UqSkJ1vCOPUpz9Ka5tS0324EJFEuOvMc+lA/EarJWP
|
||||
github.com/openai/openai-go v1.8.2/go.mod h1:g461MYGXEXBVdV5SaR/5tNzNbSfwTBBefwc+LlDCK0Y=
|
||||
github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde h1:x0TT0RDC7UhAVbbWWBzr41ElhJx5tXPWkIHA2HWPRuw=
|
||||
github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
|
||||
github.com/pdfcpu/pdfcpu v0.11.0 h1:mL18Y3hSHzSezmnrzA21TqlayBOXuAx7BUzzZyroLGM=
|
||||
github.com/pdfcpu/pdfcpu v0.11.0/go.mod h1:F1ca4GIVFdPtmgvIdvXAycAm88noyNxZwzr9CpTy+Mw=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
@@ -222,8 +230,8 @@ go.yaml.in/yaml/v3 v3.0.3 h1:bXOww4E/J3f66rav3pX3m8w6jDE4knZjGOw8b5Y6iNE=
|
||||
go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI=
|
||||
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
|
||||
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
|
||||
golang.org/x/image v0.25.0 h1:Y6uW6rH1y5y/LK1J8BPWZtr6yZ7hrsy6hFrXjgsc2fQ=
|
||||
golang.org/x/image v0.25.0/go.mod h1:tCAmOEGthTtkalusGp1g3xa2gke8J6c2N565dTyl9Rs=
|
||||
golang.org/x/image v0.27.0 h1:C8gA4oWU/tKkdCfYT6T2u4faJu3MeNS5O8UPWlPF61w=
|
||||
golang.org/x/image v0.27.0/go.mod h1:xbdrClrAUway1MUTEZDq9mz/UpRwYAkFFNUslZtcB+g=
|
||||
golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
|
||||
golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
||||
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
|
||||
@@ -248,6 +256,8 @@ google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
@@ -73,7 +73,6 @@ type Framework implements Node {
|
||||
type Report implements Node {
|
||||
id: ID!
|
||||
filename: String!
|
||||
downloadUrl: String @goField(forceResolver: true) @mustBeAuthenticated(role: USER)
|
||||
}
|
||||
|
||||
type Audit implements Node {
|
||||
@@ -249,6 +248,10 @@ input ExportDocumentPDFInput {
|
||||
documentId: ID!
|
||||
}
|
||||
|
||||
input ExportReportPDFInput {
|
||||
reportId: ID!
|
||||
}
|
||||
|
||||
input AcceptNonDisclosureAgreementInput {
|
||||
trustCenterId: ID!
|
||||
}
|
||||
@@ -257,6 +260,10 @@ type ExportDocumentPDFPayload {
|
||||
data: String!
|
||||
}
|
||||
|
||||
type ExportReportPDFPayload {
|
||||
data: String!
|
||||
}
|
||||
|
||||
type AcceptNonDisclosureAgreementPayload{
|
||||
success: Boolean!
|
||||
}
|
||||
@@ -274,6 +281,10 @@ type Mutation {
|
||||
input: ExportDocumentPDFInput!
|
||||
): ExportDocumentPDFPayload! @mustBeAuthenticated(role: USER)
|
||||
|
||||
exportReportPDF(
|
||||
input: ExportReportPDFInput!
|
||||
): ExportReportPDFPayload! @mustBeAuthenticated(role: USER)
|
||||
|
||||
acceptNonDisclosureAgreement(
|
||||
input: AcceptNonDisclosureAgreementInput!
|
||||
): AcceptNonDisclosureAgreementPayload! @mustBeAuthenticated(role: USER)
|
||||
|
||||
@@ -48,7 +48,6 @@ type ResolverRoot interface {
|
||||
Mutation() MutationResolver
|
||||
Organization() OrganizationResolver
|
||||
Query() QueryResolver
|
||||
Report() ReportResolver
|
||||
TrustCenter() TrustCenterResolver
|
||||
}
|
||||
|
||||
@@ -101,6 +100,10 @@ type ComplexityRoot struct {
|
||||
Data func(childComplexity int) int
|
||||
}
|
||||
|
||||
ExportReportPDFPayload struct {
|
||||
Data func(childComplexity int) int
|
||||
}
|
||||
|
||||
Framework struct {
|
||||
ID func(childComplexity int) int
|
||||
Name func(childComplexity int) int
|
||||
@@ -110,6 +113,7 @@ type ComplexityRoot struct {
|
||||
AcceptNonDisclosureAgreement func(childComplexity int, input types.AcceptNonDisclosureAgreementInput) int
|
||||
CreateTrustCenterAccess func(childComplexity int, input types.CreateTrustCenterAccessInput) int
|
||||
ExportDocumentPDF func(childComplexity int, input types.ExportDocumentPDFInput) int
|
||||
ExportReportPDF func(childComplexity int, input types.ExportReportPDFInput) int
|
||||
}
|
||||
|
||||
Organization struct {
|
||||
@@ -130,9 +134,8 @@ type ComplexityRoot struct {
|
||||
}
|
||||
|
||||
Report struct {
|
||||
DownloadURL func(childComplexity int) int
|
||||
Filename func(childComplexity int) int
|
||||
ID func(childComplexity int) int
|
||||
Filename func(childComplexity int) int
|
||||
ID func(childComplexity int) int
|
||||
}
|
||||
|
||||
TrustCenter struct {
|
||||
@@ -183,6 +186,7 @@ type AuditResolver interface {
|
||||
type MutationResolver interface {
|
||||
CreateTrustCenterAccess(ctx context.Context, input types.CreateTrustCenterAccessInput) (*types.CreateTrustCenterAccessPayload, error)
|
||||
ExportDocumentPDF(ctx context.Context, input types.ExportDocumentPDFInput) (*types.ExportDocumentPDFPayload, error)
|
||||
ExportReportPDF(ctx context.Context, input types.ExportReportPDFInput) (*types.ExportReportPDFPayload, error)
|
||||
AcceptNonDisclosureAgreement(ctx context.Context, input types.AcceptNonDisclosureAgreementInput) (*types.AcceptNonDisclosureAgreementPayload, error)
|
||||
}
|
||||
type OrganizationResolver interface {
|
||||
@@ -191,9 +195,6 @@ type OrganizationResolver interface {
|
||||
type QueryResolver interface {
|
||||
TrustCenterBySlug(ctx context.Context, slug string) (*types.TrustCenter, error)
|
||||
}
|
||||
type ReportResolver interface {
|
||||
DownloadURL(ctx context.Context, obj *types.Report) (*string, error)
|
||||
}
|
||||
type TrustCenterResolver interface {
|
||||
NdaFileURL(ctx context.Context, obj *types.TrustCenter) (*string, error)
|
||||
Organization(ctx context.Context, obj *types.TrustCenter) (*types.Organization, error)
|
||||
@@ -342,6 +343,13 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
|
||||
|
||||
return e.complexity.ExportDocumentPDFPayload.Data(childComplexity), true
|
||||
|
||||
case "ExportReportPDFPayload.data":
|
||||
if e.complexity.ExportReportPDFPayload.Data == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.ExportReportPDFPayload.Data(childComplexity), true
|
||||
|
||||
case "Framework.id":
|
||||
if e.complexity.Framework.ID == nil {
|
||||
break
|
||||
@@ -392,6 +400,18 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
|
||||
|
||||
return e.complexity.Mutation.ExportDocumentPDF(childComplexity, args["input"].(types.ExportDocumentPDFInput)), true
|
||||
|
||||
case "Mutation.exportReportPDF":
|
||||
if e.complexity.Mutation.ExportReportPDF == nil {
|
||||
break
|
||||
}
|
||||
|
||||
args, err := ec.field_Mutation_exportReportPDF_args(ctx, rawArgs)
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
return e.complexity.Mutation.ExportReportPDF(childComplexity, args["input"].(types.ExportReportPDFInput)), true
|
||||
|
||||
case "Organization.id":
|
||||
if e.complexity.Organization.ID == nil {
|
||||
break
|
||||
@@ -453,13 +473,6 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
|
||||
|
||||
return e.complexity.Query.TrustCenterBySlug(childComplexity, args["slug"].(string)), true
|
||||
|
||||
case "Report.downloadUrl":
|
||||
if e.complexity.Report.DownloadURL == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.Report.DownloadURL(childComplexity), true
|
||||
|
||||
case "Report.filename":
|
||||
if e.complexity.Report.Filename == nil {
|
||||
break
|
||||
@@ -675,6 +688,7 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler {
|
||||
ec.unmarshalInputAcceptNonDisclosureAgreementInput,
|
||||
ec.unmarshalInputCreateTrustCenterAccessInput,
|
||||
ec.unmarshalInputExportDocumentPDFInput,
|
||||
ec.unmarshalInputExportReportPDFInput,
|
||||
)
|
||||
first := true
|
||||
|
||||
@@ -847,7 +861,6 @@ type Framework implements Node {
|
||||
type Report implements Node {
|
||||
id: ID!
|
||||
filename: String!
|
||||
downloadUrl: String @goField(forceResolver: true) @mustBeAuthenticated(role: USER)
|
||||
}
|
||||
|
||||
type Audit implements Node {
|
||||
@@ -1023,6 +1036,10 @@ input ExportDocumentPDFInput {
|
||||
documentId: ID!
|
||||
}
|
||||
|
||||
input ExportReportPDFInput {
|
||||
reportId: ID!
|
||||
}
|
||||
|
||||
input AcceptNonDisclosureAgreementInput {
|
||||
trustCenterId: ID!
|
||||
}
|
||||
@@ -1031,6 +1048,10 @@ type ExportDocumentPDFPayload {
|
||||
data: String!
|
||||
}
|
||||
|
||||
type ExportReportPDFPayload {
|
||||
data: String!
|
||||
}
|
||||
|
||||
type AcceptNonDisclosureAgreementPayload{
|
||||
success: Boolean!
|
||||
}
|
||||
@@ -1048,6 +1069,10 @@ type Mutation {
|
||||
input: ExportDocumentPDFInput!
|
||||
): ExportDocumentPDFPayload! @mustBeAuthenticated(role: USER)
|
||||
|
||||
exportReportPDF(
|
||||
input: ExportReportPDFInput!
|
||||
): ExportReportPDFPayload! @mustBeAuthenticated(role: USER)
|
||||
|
||||
acceptNonDisclosureAgreement(
|
||||
input: AcceptNonDisclosureAgreementInput!
|
||||
): AcceptNonDisclosureAgreementPayload! @mustBeAuthenticated(role: USER)
|
||||
@@ -1157,6 +1182,29 @@ func (ec *executionContext) field_Mutation_exportDocumentPDF_argsInput(
|
||||
return zeroVal, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) field_Mutation_exportReportPDF_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
|
||||
var err error
|
||||
args := map[string]any{}
|
||||
arg0, err := ec.field_Mutation_exportReportPDF_argsInput(ctx, rawArgs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
args["input"] = arg0
|
||||
return args, nil
|
||||
}
|
||||
func (ec *executionContext) field_Mutation_exportReportPDF_argsInput(
|
||||
ctx context.Context,
|
||||
rawArgs map[string]any,
|
||||
) (types.ExportReportPDFInput, error) {
|
||||
ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("input"))
|
||||
if tmp, ok := rawArgs["input"]; ok {
|
||||
return ec.unmarshalNExportReportPDFInput2githubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐExportReportPDFInput(ctx, tmp)
|
||||
}
|
||||
|
||||
var zeroVal types.ExportReportPDFInput
|
||||
return zeroVal, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) field_Query___type_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
|
||||
var err error
|
||||
args := map[string]any{}
|
||||
@@ -1712,8 +1760,6 @@ func (ec *executionContext) fieldContext_Audit_report(_ context.Context, field g
|
||||
return ec.fieldContext_Report_id(ctx, field)
|
||||
case "filename":
|
||||
return ec.fieldContext_Report_filename(ctx, field)
|
||||
case "downloadUrl":
|
||||
return ec.fieldContext_Report_downloadUrl(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type Report", field.Name)
|
||||
},
|
||||
@@ -2353,6 +2399,50 @@ func (ec *executionContext) fieldContext_ExportDocumentPDFPayload_data(_ context
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _ExportReportPDFPayload_data(ctx context.Context, field graphql.CollectedField, obj *types.ExportReportPDFPayload) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_ExportReportPDFPayload_data(ctx, field)
|
||||
if err != nil {
|
||||
return graphql.Null
|
||||
}
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.Data, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
if !graphql.HasFieldError(ctx, fc) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(string)
|
||||
fc.Result = res
|
||||
return ec.marshalNString2string(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_ExportReportPDFPayload_data(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "ExportReportPDFPayload",
|
||||
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) _Framework_id(ctx context.Context, field graphql.CollectedField, obj *types.Framework) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_Framework_id(ctx, field)
|
||||
if err != nil {
|
||||
@@ -2613,6 +2703,92 @@ func (ec *executionContext) fieldContext_Mutation_exportDocumentPDF(ctx context.
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Mutation_exportReportPDF(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_Mutation_exportReportPDF(ctx, field)
|
||||
if err != nil {
|
||||
return graphql.Null
|
||||
}
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
|
||||
directive0 := func(rctx context.Context) (any, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return ec.resolvers.Mutation().ExportReportPDF(rctx, fc.Args["input"].(types.ExportReportPDFInput))
|
||||
}
|
||||
|
||||
directive1 := func(ctx context.Context) (any, error) {
|
||||
role, err := ec.unmarshalORole2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐRole(ctx, "USER")
|
||||
if err != nil {
|
||||
var zeroVal *types.ExportReportPDFPayload
|
||||
return zeroVal, err
|
||||
}
|
||||
if ec.directives.MustBeAuthenticated == nil {
|
||||
var zeroVal *types.ExportReportPDFPayload
|
||||
return zeroVal, errors.New("directive mustBeAuthenticated is not implemented")
|
||||
}
|
||||
return ec.directives.MustBeAuthenticated(ctx, nil, directive0, role)
|
||||
}
|
||||
|
||||
tmp, err := directive1(rctx)
|
||||
if err != nil {
|
||||
return nil, graphql.ErrorOnPath(ctx, err)
|
||||
}
|
||||
if tmp == nil {
|
||||
return nil, nil
|
||||
}
|
||||
if data, ok := tmp.(*types.ExportReportPDFPayload); ok {
|
||||
return data, nil
|
||||
}
|
||||
return nil, fmt.Errorf(`unexpected type %T from directive, should be *github.com/getprobo/probo/pkg/server/api/trust/v1/types.ExportReportPDFPayload`, tmp)
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
if !graphql.HasFieldError(ctx, fc) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*types.ExportReportPDFPayload)
|
||||
fc.Result = res
|
||||
return ec.marshalNExportReportPDFPayload2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐExportReportPDFPayload(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_Mutation_exportReportPDF(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_ExportReportPDFPayload_data(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type ExportReportPDFPayload", 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_exportReportPDF_args(ctx, field.ArgumentMap(ec.Variables)); err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return fc, err
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Mutation_acceptNonDisclosureAgreement(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_Mutation_acceptNonDisclosureAgreement(ctx, field)
|
||||
if err != nil {
|
||||
@@ -3320,74 +3496,6 @@ func (ec *executionContext) fieldContext_Report_filename(_ context.Context, fiel
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Report_downloadUrl(ctx context.Context, field graphql.CollectedField, obj *types.Report) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_Report_downloadUrl(ctx, field)
|
||||
if err != nil {
|
||||
return graphql.Null
|
||||
}
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
|
||||
directive0 := func(rctx context.Context) (any, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return ec.resolvers.Report().DownloadURL(rctx, obj)
|
||||
}
|
||||
|
||||
directive1 := func(ctx context.Context) (any, error) {
|
||||
role, err := ec.unmarshalORole2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐRole(ctx, "USER")
|
||||
if err != nil {
|
||||
var zeroVal *string
|
||||
return zeroVal, err
|
||||
}
|
||||
if ec.directives.MustBeAuthenticated == nil {
|
||||
var zeroVal *string
|
||||
return zeroVal, errors.New("directive mustBeAuthenticated is not implemented")
|
||||
}
|
||||
return ec.directives.MustBeAuthenticated(ctx, obj, directive0, role)
|
||||
}
|
||||
|
||||
tmp, err := directive1(rctx)
|
||||
if err != nil {
|
||||
return nil, graphql.ErrorOnPath(ctx, err)
|
||||
}
|
||||
if tmp == nil {
|
||||
return nil, nil
|
||||
}
|
||||
if data, ok := tmp.(*string); ok {
|
||||
return data, nil
|
||||
}
|
||||
return nil, fmt.Errorf(`unexpected type %T from directive, should be *string`, tmp)
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*string)
|
||||
fc.Result = res
|
||||
return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_Report_downloadUrl(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "Report",
|
||||
Field: field,
|
||||
IsMethod: true,
|
||||
IsResolver: true,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
return nil, errors.New("field of type String does not have child fields")
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _TrustCenter_id(ctx context.Context, field graphql.CollectedField, obj *types.TrustCenter) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_TrustCenter_id(ctx, field)
|
||||
if err != nil {
|
||||
@@ -6609,6 +6717,33 @@ func (ec *executionContext) unmarshalInputExportDocumentPDFInput(ctx context.Con
|
||||
return it, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalInputExportReportPDFInput(ctx context.Context, obj any) (types.ExportReportPDFInput, error) {
|
||||
var it types.ExportReportPDFInput
|
||||
asMap := map[string]any{}
|
||||
for k, v := range obj.(map[string]any) {
|
||||
asMap[k] = v
|
||||
}
|
||||
|
||||
fieldsInOrder := [...]string{"reportId"}
|
||||
for _, k := range fieldsInOrder {
|
||||
v, ok := asMap[k]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
switch k {
|
||||
case "reportId":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("reportId"))
|
||||
data, err := ec.unmarshalNID2githubᚗcomᚋgetproboᚋproboᚋpkgᚋgidᚐGID(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
it.ReportID = data
|
||||
}
|
||||
}
|
||||
|
||||
return it, nil
|
||||
}
|
||||
|
||||
// endregion **************************** input.gotpl *****************************
|
||||
|
||||
// region ************************** interface.gotpl ***************************
|
||||
@@ -7132,6 +7267,45 @@ func (ec *executionContext) _ExportDocumentPDFPayload(ctx context.Context, sel a
|
||||
return out
|
||||
}
|
||||
|
||||
var exportReportPDFPayloadImplementors = []string{"ExportReportPDFPayload"}
|
||||
|
||||
func (ec *executionContext) _ExportReportPDFPayload(ctx context.Context, sel ast.SelectionSet, obj *types.ExportReportPDFPayload) graphql.Marshaler {
|
||||
fields := graphql.CollectFields(ec.OperationContext, sel, exportReportPDFPayloadImplementors)
|
||||
|
||||
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("ExportReportPDFPayload")
|
||||
case "data":
|
||||
out.Values[i] = ec._ExportReportPDFPayload_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 frameworkImplementors = []string{"Framework", "Node"}
|
||||
|
||||
func (ec *executionContext) _Framework(ctx context.Context, sel ast.SelectionSet, obj *types.Framework) graphql.Marshaler {
|
||||
@@ -7209,6 +7383,13 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet)
|
||||
if out.Values[i] == graphql.Null {
|
||||
out.Invalids++
|
||||
}
|
||||
case "exportReportPDF":
|
||||
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
|
||||
return ec._Mutation_exportReportPDF(ctx, field)
|
||||
})
|
||||
if out.Values[i] == graphql.Null {
|
||||
out.Invalids++
|
||||
}
|
||||
case "acceptNonDisclosureAgreement":
|
||||
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
|
||||
return ec._Mutation_acceptNonDisclosureAgreement(ctx, field)
|
||||
@@ -7447,46 +7628,13 @@ func (ec *executionContext) _Report(ctx context.Context, sel ast.SelectionSet, o
|
||||
case "id":
|
||||
out.Values[i] = ec._Report_id(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
atomic.AddUint32(&out.Invalids, 1)
|
||||
out.Invalids++
|
||||
}
|
||||
case "filename":
|
||||
out.Values[i] = ec._Report_filename(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
atomic.AddUint32(&out.Invalids, 1)
|
||||
out.Invalids++
|
||||
}
|
||||
case "downloadUrl":
|
||||
field := field
|
||||
|
||||
innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
}
|
||||
}()
|
||||
res = ec._Report_downloadUrl(ctx, field, obj)
|
||||
return res
|
||||
}
|
||||
|
||||
if field.Deferrable != nil {
|
||||
dfs, ok := deferred[field.Deferrable.Label]
|
||||
di := 0
|
||||
if ok {
|
||||
dfs.AddField(field)
|
||||
di = len(dfs.Values) - 1
|
||||
} else {
|
||||
dfs = graphql.NewFieldSet([]graphql.CollectedField{field})
|
||||
deferred[field.Deferrable.Label] = dfs
|
||||
}
|
||||
dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler {
|
||||
return innerFunc(ctx, dfs)
|
||||
})
|
||||
|
||||
// don't run the out.Concurrently() call below
|
||||
out.Values[i] = graphql.Null
|
||||
continue
|
||||
}
|
||||
|
||||
out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) })
|
||||
default:
|
||||
panic("unknown field " + strconv.Quote(field.Name))
|
||||
}
|
||||
@@ -8636,6 +8784,25 @@ func (ec *executionContext) marshalNExportDocumentPDFPayload2ᚖgithubᚗcomᚋg
|
||||
return ec._ExportDocumentPDFPayload(ctx, sel, v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalNExportReportPDFInput2githubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐExportReportPDFInput(ctx context.Context, v any) (types.ExportReportPDFInput, error) {
|
||||
res, err := ec.unmarshalInputExportReportPDFInput(ctx, v)
|
||||
return res, graphql.ErrorOnPath(ctx, err)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNExportReportPDFPayload2githubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐExportReportPDFPayload(ctx context.Context, sel ast.SelectionSet, v types.ExportReportPDFPayload) graphql.Marshaler {
|
||||
return ec._ExportReportPDFPayload(ctx, sel, &v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNExportReportPDFPayload2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐExportReportPDFPayload(ctx context.Context, sel ast.SelectionSet, v *types.ExportReportPDFPayload) graphql.Marshaler {
|
||||
if v == nil {
|
||||
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
||||
ec.Errorf(ctx, "the requested element is null which the schema does not allow")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
return ec._ExportReportPDFPayload(ctx, sel, v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNFramework2githubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐFramework(ctx context.Context, sel ast.SelectionSet, v types.Framework) graphql.Marshaler {
|
||||
return ec._Framework(ctx, sel, &v)
|
||||
}
|
||||
|
||||
@@ -83,6 +83,14 @@ type ExportDocumentPDFPayload struct {
|
||||
Data string `json:"data"`
|
||||
}
|
||||
|
||||
type ExportReportPDFInput struct {
|
||||
ReportID gid.GID `json:"reportId"`
|
||||
}
|
||||
|
||||
type ExportReportPDFPayload struct {
|
||||
Data string `json:"data"`
|
||||
}
|
||||
|
||||
type Framework struct {
|
||||
ID gid.GID `json:"id"`
|
||||
Name string `json:"name"`
|
||||
@@ -114,9 +122,8 @@ type Query struct {
|
||||
}
|
||||
|
||||
type Report struct {
|
||||
ID gid.GID `json:"id"`
|
||||
Filename string `json:"filename"`
|
||||
DownloadURL *string `json:"downloadUrl,omitempty"`
|
||||
ID gid.GID `json:"id"`
|
||||
Filename string `json:"filename"`
|
||||
}
|
||||
|
||||
func (Report) IsNode() {}
|
||||
|
||||
@@ -105,7 +105,15 @@ func (r *mutationResolver) ExportDocumentPDF(ctx context.Context, input types.Ex
|
||||
return nil, fmt.Errorf("user has not accepted NDA")
|
||||
}
|
||||
|
||||
pdf, err := privateTrustService.Documents.ExportPDF(ctx, input.DocumentID)
|
||||
userEmail := ""
|
||||
if userData != nil {
|
||||
userEmail = userData.EmailAddress
|
||||
}
|
||||
if tokenData != nil {
|
||||
userEmail = tokenData.GetEmail()
|
||||
}
|
||||
|
||||
pdf, err := privateTrustService.Documents.ExportPDF(ctx, input.DocumentID, userEmail)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot export document PDF: %w", err))
|
||||
}
|
||||
@@ -115,6 +123,49 @@ func (r *mutationResolver) ExportDocumentPDF(ctx context.Context, input types.Ex
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ExportReportPDF is the resolver for the exportReportPDF field.
|
||||
func (r *mutationResolver) ExportReportPDF(ctx context.Context, input types.ExportReportPDFInput) (*types.ExportReportPDFPayload, error) {
|
||||
privateTrustService, err := r.PrivateTrustService(ctx, input.ReportID.TenantID())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot export report PDF: %w", err)
|
||||
}
|
||||
|
||||
hasAcceptedNDA := false
|
||||
userData := r.UserFromContext(ctx)
|
||||
if userData != nil {
|
||||
hasAcceptedNDA = true
|
||||
}
|
||||
|
||||
tokenData := TokenAccessFromContext(ctx)
|
||||
if tokenData != nil {
|
||||
hasAcceptedNDA, err = privateTrustService.TrustCenterAccesses.HasAcceptedNonDisclosureAgreement(ctx, tokenData.TrustCenterID, tokenData.GetEmail())
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot check if user has accepted NDA: %w", err))
|
||||
}
|
||||
}
|
||||
|
||||
if !hasAcceptedNDA {
|
||||
return nil, fmt.Errorf("user has not accepted NDA")
|
||||
}
|
||||
|
||||
userEmail := ""
|
||||
if userData != nil {
|
||||
userEmail = userData.EmailAddress
|
||||
}
|
||||
if tokenData != nil {
|
||||
userEmail = tokenData.GetEmail()
|
||||
}
|
||||
|
||||
pdf, err := privateTrustService.Reports.ExportPDF(ctx, input.ReportID, userEmail)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot export report PDF: %w", err))
|
||||
}
|
||||
|
||||
return &types.ExportReportPDFPayload{
|
||||
Data: fmt.Sprintf("data:application/pdf;base64,%s", base64.StdEncoding.EncodeToString(pdf)),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// AcceptNonDisclosureAgreement is the resolver for the acceptNonDisclosureAgreement field.
|
||||
func (r *mutationResolver) AcceptNonDisclosureAgreement(ctx context.Context, input types.AcceptNonDisclosureAgreementInput) (*types.AcceptNonDisclosureAgreementPayload, error) {
|
||||
privateTrustService, err := r.PrivateTrustService(ctx, input.TrustCenterID.TenantID())
|
||||
@@ -171,39 +222,6 @@ func (r *queryResolver) TrustCenterBySlug(ctx context.Context, slug string) (*ty
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// DownloadURL is the resolver for the downloadUrl field.
|
||||
func (r *reportResolver) DownloadURL(ctx context.Context, obj *types.Report) (*string, error) {
|
||||
privateTrustService, err := r.PrivateTrustService(ctx, obj.ID.TenantID())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot generate download URL: %w", err)
|
||||
}
|
||||
|
||||
hasAcceptedNDA := false
|
||||
userData := UserFromContext(ctx)
|
||||
if userData != nil {
|
||||
hasAcceptedNDA = true
|
||||
}
|
||||
|
||||
tokenData := TokenAccessFromContext(ctx)
|
||||
if tokenData != nil {
|
||||
hasAcceptedNDA, err = privateTrustService.TrustCenterAccesses.HasAcceptedNonDisclosureAgreement(ctx, tokenData.TrustCenterID, tokenData.GetEmail())
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot check if user has accepted NDA: %w", err))
|
||||
}
|
||||
}
|
||||
|
||||
if !hasAcceptedNDA {
|
||||
return nil, fmt.Errorf("user has not accepted NDA")
|
||||
}
|
||||
|
||||
url, err := privateTrustService.Reports.GenerateDownloadURL(ctx, obj.ID, r.trustAuthCfg.ReportURLDuration)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot generate download URL: %w", err))
|
||||
}
|
||||
|
||||
return url, nil
|
||||
}
|
||||
|
||||
// NdaFileURL is the resolver for the ndaFileUrl field.
|
||||
func (r *trustCenterResolver) NdaFileURL(ctx context.Context, obj *types.TrustCenter) (*string, error) {
|
||||
privateTrustService, err := r.PrivateTrustService(ctx, obj.ID.TenantID())
|
||||
@@ -324,9 +342,6 @@ func (r *Resolver) Organization() schema.OrganizationResolver { return &organiza
|
||||
// Query returns schema.QueryResolver implementation.
|
||||
func (r *Resolver) Query() schema.QueryResolver { return &queryResolver{r} }
|
||||
|
||||
// Report returns schema.ReportResolver implementation.
|
||||
func (r *Resolver) Report() schema.ReportResolver { return &reportResolver{r} }
|
||||
|
||||
// TrustCenter returns schema.TrustCenterResolver implementation.
|
||||
func (r *Resolver) TrustCenter() schema.TrustCenterResolver { return &trustCenterResolver{r} }
|
||||
|
||||
@@ -334,5 +349,4 @@ type auditResolver struct{ *Resolver }
|
||||
type mutationResolver struct{ *Resolver }
|
||||
type organizationResolver struct{ *Resolver }
|
||||
type queryResolver struct{ *Resolver }
|
||||
type reportResolver struct{ *Resolver }
|
||||
type trustCenterResolver struct{ *Resolver }
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
"github.com/getprobo/probo/pkg/gid"
|
||||
"github.com/getprobo/probo/pkg/html2pdf"
|
||||
"github.com/getprobo/probo/pkg/page"
|
||||
"github.com/getprobo/probo/pkg/watermarkpdf"
|
||||
"go.gearno.de/kit/pg"
|
||||
)
|
||||
|
||||
@@ -86,6 +87,7 @@ func (s *DocumentService) ListForOrganizationId(
|
||||
func (s *DocumentService) ExportPDF(
|
||||
ctx context.Context,
|
||||
documentID gid.GID,
|
||||
email string,
|
||||
) ([]byte, error) {
|
||||
document := &coredata.Document{}
|
||||
version := &coredata.DocumentVersion{}
|
||||
@@ -169,5 +171,11 @@ func (s *DocumentService) ExportPDF(
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot read PDF data: %w", err)
|
||||
}
|
||||
return pdfData, nil
|
||||
|
||||
watermarkedPDF, err := watermarkpdf.AddConfidentialWithTimestamp(pdfData, email)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot add watermark to PDF: %w", err)
|
||||
}
|
||||
|
||||
return watermarkedPDF, nil
|
||||
}
|
||||
|
||||
@@ -17,12 +17,14 @@ package trust
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||
"github.com/getprobo/probo/pkg/coredata"
|
||||
"github.com/getprobo/probo/pkg/gid"
|
||||
"github.com/getprobo/probo/pkg/watermarkpdf"
|
||||
"go.gearno.de/kit/pg"
|
||||
)
|
||||
|
||||
@@ -82,3 +84,35 @@ func (s ReportService) GenerateDownloadURL(
|
||||
|
||||
return &presignedReq.URL, nil
|
||||
}
|
||||
|
||||
func (s ReportService) ExportPDF(
|
||||
ctx context.Context,
|
||||
reportID gid.GID,
|
||||
email string,
|
||||
) ([]byte, error) {
|
||||
report, err := s.Get(ctx, reportID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot get report: %w", err)
|
||||
}
|
||||
|
||||
result, err := s.svc.s3.GetObject(ctx, &s3.GetObjectInput{
|
||||
Bucket: aws.String(s.svc.bucket),
|
||||
Key: aws.String(report.ObjectKey),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot download PDF from S3: %w", err)
|
||||
}
|
||||
defer result.Body.Close()
|
||||
|
||||
pdfData, err := io.ReadAll(result.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot read PDF data: %w", err)
|
||||
}
|
||||
|
||||
watermarkedPDF, err := watermarkpdf.AddConfidentialWithTimestamp(pdfData, email)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot add watermark to PDF: %w", err)
|
||||
}
|
||||
|
||||
return watermarkedPDF, nil
|
||||
}
|
||||
|
||||
58
pkg/watermarkpdf/watermarkpdf.go
Normal file
58
pkg/watermarkpdf/watermarkpdf.go
Normal file
@@ -0,0 +1,58 @@
|
||||
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
|
||||
//
|
||||
// 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 watermarkpdf
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/pdfcpu/pdfcpu/pkg/api"
|
||||
"github.com/pdfcpu/pdfcpu/pkg/pdfcpu/model"
|
||||
)
|
||||
|
||||
func AddConfidentialWithTimestamp(pdfData []byte, email string) ([]byte, error) {
|
||||
reader := bytes.NewReader(pdfData)
|
||||
var buf bytes.Buffer
|
||||
|
||||
// Replace email with invisible characters to prevent auto-linking
|
||||
formattedEmail := strings.ReplaceAll(email, "@", "\u200B@\u200B")
|
||||
formattedEmail = strings.ReplaceAll(formattedEmail, ".", "\u200B.\u200B")
|
||||
|
||||
watermarkText := strings.Join([]string{
|
||||
"Confidential",
|
||||
formattedEmail,
|
||||
time.Now().Format("02/01/2006"),
|
||||
}, "\n")
|
||||
|
||||
watermarkConf := model.DefaultWatermarkConfig()
|
||||
watermarkConf.Mode = model.WMText
|
||||
watermarkConf.TextString = watermarkText
|
||||
watermarkConf.FontName = "Helvetica"
|
||||
watermarkConf.FontSize = 120
|
||||
watermarkConf.Rotation = 55
|
||||
watermarkConf.Opacity = 0.20
|
||||
watermarkConf.OnTop = true
|
||||
watermarkConf.ScaleAbs = true
|
||||
watermarkConf.Update = false
|
||||
|
||||
err := api.AddWatermarks(reader, &buf, nil, watermarkConf, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to add watermark: %w", err)
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
Reference in New Issue
Block a user