diff --git a/apps/console/src/hooks/graph/AuditGraph.ts b/apps/console/src/hooks/graph/AuditGraph.ts index 5a554d234..04a8f9346 100644 --- a/apps/console/src/hooks/graph/AuditGraph.ts +++ b/apps/console/src/hooks/graph/AuditGraph.ts @@ -170,6 +170,7 @@ export const useCreateAudit = (connectionId: string) => { validUntil?: string; reportKey?: string; state?: string; + file?: File | null; }) => { if (!input.organizationId) { return alert(__("Failed to create audit: organization is required")); @@ -188,9 +189,11 @@ export const useCreateAudit = (connectionId: string) => { validUntil: input.validUntil, reportKey: input.reportKey, state: input.state || "NOT_STARTED", + file: input.file ? null : undefined, }, connections: [connectionId], }, + ...(input.file ? { uploadables: { "input.file": input.file } } : {}), }); }; }; diff --git a/apps/console/src/pages/organizations/audits/dialogs/CreateAuditDialog.tsx b/apps/console/src/pages/organizations/audits/dialogs/CreateAuditDialog.tsx index 778915d25..99b4a329e 100644 --- a/apps/console/src/pages/organizations/audits/dialogs/CreateAuditDialog.tsx +++ b/apps/console/src/pages/organizations/audits/dialogs/CreateAuditDialog.tsx @@ -23,35 +23,15 @@ import { } from "@probo/ui"; import { Suspense } from "react"; import { type Control, Controller } from "react-hook-form"; -import { useLazyLoadQuery, useMutation } from "react-relay"; +import { useLazyLoadQuery } from "react-relay"; import { graphql } from "relay-runtime"; import { z } from "zod"; import type { CreateAuditDialogFrameworksQuery } from "#/__generated__/core/CreateAuditDialogFrameworksQuery.graphql"; -import type { CreateAuditDialogUploadReportMutation } from "#/__generated__/core/CreateAuditDialogUploadReportMutation.graphql"; import { ControlledField } from "#/components/form/ControlledField"; import { useCreateAudit } from "#/hooks/graph/AuditGraph"; import { useFormWithSchema } from "#/hooks/useFormWithSchema"; -const uploadAuditReportMutation = graphql` - mutation CreateAuditDialogUploadReportMutation( - $input: UploadAuditReportInput! - ) { - uploadAuditReport(input: $input) { - audit { - id - report { - id - filename - downloadUrl - createdAt - } - updatedAt - } - } - } -`; - const frameworksQuery = graphql` query CreateAuditDialogFrameworksQuery($organizationId: ID!) { organization: node(id: $organizationId) { @@ -115,68 +95,29 @@ export function CreateAuditDialog({ const internalRef = useDialogRef(); const ref = externalRef ?? internalRef; const createAudit = useCreateAudit(connection); - const [uploadMutate] = useMutation(uploadAuditReportMutation); const onSubmit = async (data: z.infer) => { try { - const response = await createAudit({ + await createAudit({ organizationId, frameworkId: data.frameworkId, name: data.name || null, validFrom: formatDatetime(data.validFrom), validUntil: formatDatetime(data.validUntil), state: data.state, + file: file ?? null, }); - const auditId = (response as { createAudit: { auditEdge: { node: { id: string } } } }) - .createAudit.auditEdge.node.id; - - if (file && auditId) { - try { - await new Promise((resolve, reject) => { - uploadMutate({ - variables: { - input: { - auditId, - file: null, - }, - }, - uploadables: { - "input.file": file, - }, - onCompleted: (_response, errors) => { - if (errors) { - reject(errors); - } else { - resolve(); - } - }, - onError: error => reject(error), - }); - }); - toast({ - title: __("Success"), - description: __("Audit created and report uploaded successfully"), - variant: "success", - }); - } catch { - toast({ - title: __("Warning"), - description: __("Audit created but report upload failed. You can upload the report from the audit detail page."), - variant: "warning", - }); - } - } else { - toast({ - title: __("Success"), - description: __("Audit created successfully"), - variant: "success", - }); - } - ref.current?.close(); reset(); onClose?.(); + toast({ + title: __("Success"), + description: file + ? __("Audit created and report uploaded successfully") + : __("Audit created successfully"), + variant: "success", + }); } catch (error) { toast({ title: __("Error"), diff --git a/pkg/server/api/console/v1/schema.graphql b/pkg/server/api/console/v1/schema.graphql index cf5d33f87..70c80e230 100644 --- a/pkg/server/api/console/v1/schema.graphql +++ b/pkg/server/api/console/v1/schema.graphql @@ -4459,6 +4459,7 @@ input CreateAuditInput { validUntil: Datetime state: AuditState trustCenterVisibility: TrustCenterVisibility + file: Upload } input UpdateAuditInput { diff --git a/pkg/server/api/console/v1/v1_resolver.go b/pkg/server/api/console/v1/v1_resolver.go index 573cf4cca..c6d9fd428 100644 --- a/pkg/server/api/console/v1/v1_resolver.go +++ b/pkg/server/api/console/v1/v1_resolver.go @@ -5338,6 +5338,27 @@ func (r *mutationResolver) CreateAudit(ctx context.Context, input types.CreateAu return nil, gqlutils.Internal(ctx) } + if input.File != nil { + uploadReq := probo.UploadAuditReportRequest{ + AuditID: audit.ID, + File: probo.File{ + Content: input.File.File, + Filename: input.File.Filename, + Size: input.File.Size, + ContentType: input.File.ContentType, + }, + } + + audit, err = prb.Audits.UploadReport(ctx, uploadReq) + if err != nil { + if validationErrors, ok := errors.AsType[validator.ValidationErrors](err); ok { + return nil, gqlutils.InvalidValidationErrors(ctx, validationErrors) + } + r.logger.ErrorCtx(ctx, "cannot upload audit report", log.Error(err)) + return nil, gqlutils.Internal(ctx) + } + } + return &types.CreateAuditPayload{ AuditEdge: types.NewAuditEdge(audit, coredata.AuditOrderFieldCreatedAt), }, nil