Add export

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
This commit is contained in:
Bryan Frimin
2025-05-20 15:37:27 -07:00
parent 52a17a6132
commit 518b1824b4
7 changed files with 660 additions and 41 deletions

View File

@@ -23,6 +23,7 @@ import type { FrameworkLayoutViewDeleteMutation } from "./__generated__/Framewor
import { PageTemplate } from "@/components/PageTemplate"; import { PageTemplate } from "@/components/PageTemplate";
import { FrameworkLayoutViewSkeleton } from "./FrameworkLayout"; import { FrameworkLayoutViewSkeleton } from "./FrameworkLayout";
import { ControlList } from "./FrameworkLayoutView/ControlList"; import { ControlList } from "./FrameworkLayoutView/ControlList";
import { FrameworkLayoutViewExportAuditMutation } from "./__generated__/FrameworkLayoutViewExportAuditMutation.graphql";
const FrameworkLayoutViewQuery = graphql` const FrameworkLayoutViewQuery = graphql`
query FrameworkLayoutViewQuery($frameworkId: ID!) { query FrameworkLayoutViewQuery($frameworkId: ID!) {
@@ -60,6 +61,14 @@ const DeleteFrameworkMutation = graphql`
} }
`; `;
const exportAuditMutation = graphql`
mutation FrameworkLayoutViewExportAuditMutation($input: ExportAuditInput!) {
exportAudit(input: $input) {
success
}
}
`;
function FrameworkLayoutViewContent({ function FrameworkLayoutViewContent({
queryRef, queryRef,
}: { }: {
@@ -73,17 +82,28 @@ function FrameworkLayoutViewContent({
const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false); const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false);
const [isDeleting, setIsDeleting] = useState(false); const [isDeleting, setIsDeleting] = useState(false);
const [exportAudit, _] =
useMutation<FrameworkLayoutViewExportAuditMutation>(exportAuditMutation);
// Setup delete mutation // Setup delete mutation
const [commitDeleteMutation] = useMutation<FrameworkLayoutViewDeleteMutation>( const [commitDeleteMutation] = useMutation<FrameworkLayoutViewDeleteMutation>(
DeleteFrameworkMutation, DeleteFrameworkMutation
); );
const handleExportAudit = useCallback(() => {
exportAudit({
variables: {
input: { frameworkId: framework.id },
},
});
}, [exportAudit, framework.id]);
const handleDeleteFramework = useCallback(() => { const handleDeleteFramework = useCallback(() => {
setIsDeleting(true); setIsDeleting(true);
const connectionId = ConnectionHandler.getConnectionID( const connectionId = ConnectionHandler.getConnectionID(
organizationId!, organizationId!,
"FrameworkListView_frameworks", "FrameworkListView_frameworks"
); );
commitDeleteMutation({ commitDeleteMutation({
@@ -140,6 +160,9 @@ function FrameworkLayoutViewContent({
Edit Framework Edit Framework
</Link> </Link>
</Button> </Button>
<Button variant="secondary" onClick={() => handleExportAudit()}>
Export Audit
</Button>
<Button <Button
variant="destructive" variant="destructive"
onClick={() => setIsDeleteDialogOpen(true)} onClick={() => setIsDeleteDialogOpen(true)}
@@ -189,7 +212,7 @@ function FrameworkLayoutViewContent({
export default function FrameworkLayoutView() { export default function FrameworkLayoutView() {
const { frameworkId } = useParams(); const { frameworkId } = useParams();
const [queryRef, loadQuery] = useQueryLoader<FrameworkLayoutViewQueryType>( const [queryRef, loadQuery] = useQueryLoader<FrameworkLayoutViewQueryType>(
FrameworkLayoutViewQuery, FrameworkLayoutViewQuery
); );
useEffect(() => { useEffect(() => {

View File

@@ -0,0 +1,92 @@
/**
* @generated SignedSource<<c25a5f65159da12ec86ca608b7583a67>>
* @lightSyntaxTransform
* @nogrep
*/
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type ExportAuditInput = {
frameworkId: string;
};
export type FrameworkLayoutViewExportAuditMutation$variables = {
input: ExportAuditInput;
};
export type FrameworkLayoutViewExportAuditMutation$data = {
readonly exportAudit: {
readonly success: boolean;
};
};
export type FrameworkLayoutViewExportAuditMutation = {
response: FrameworkLayoutViewExportAuditMutation$data;
variables: FrameworkLayoutViewExportAuditMutation$variables;
};
const node: ConcreteRequest = (function(){
var v0 = [
{
"defaultValue": null,
"kind": "LocalArgument",
"name": "input"
}
],
v1 = [
{
"alias": null,
"args": [
{
"kind": "Variable",
"name": "input",
"variableName": "input"
}
],
"concreteType": "ExportAuditPayload",
"kind": "LinkedField",
"name": "exportAudit",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "success",
"storageKey": null
}
],
"storageKey": null
}
];
return {
"fragment": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "FrameworkLayoutViewExportAuditMutation",
"selections": (v1/*: any*/),
"type": "Mutation",
"abstractKey": null
},
"kind": "Request",
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "FrameworkLayoutViewExportAuditMutation",
"selections": (v1/*: any*/)
},
"params": {
"cacheID": "a0f656b50acde2ef3c3fef73e2155e9f",
"id": null,
"metadata": {},
"name": "FrameworkLayoutViewExportAuditMutation",
"operationKind": "mutation",
"text": "mutation FrameworkLayoutViewExportAuditMutation(\n $input: ExportAuditInput!\n) {\n exportAudit(input: $input) {\n success\n }\n}\n"
}
};
})();
(node as any).hash = "b7347f4f8e292580e056793df6c270a5";
export default node;

View File

@@ -17,8 +17,13 @@ package probo
import ( import (
"context" "context"
"fmt" "fmt"
"io"
"os"
"path/filepath"
"time" "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/coredata"
"github.com/getprobo/probo/pkg/gid" "github.com/getprobo/probo/pkg/gid"
"github.com/getprobo/probo/pkg/page" "github.com/getprobo/probo/pkg/page"
@@ -238,3 +243,157 @@ func (s FrameworkService) Import(
return framework, nil return framework, nil
} }
func (s FrameworkService) ExportAudit(
ctx context.Context,
frameworkID gid.GID,
) ([]*coredata.Control, error) {
err := s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
framework := &coredata.Framework{}
if err := framework.LoadByID(ctx, conn, s.svc.scope, frameworkID); err != nil {
return fmt.Errorf("cannot load framework: %w", err)
}
now := time.Now()
exportDir := filepath.Join(os.TempDir(), "probo-export", framework.Name, now.Format("2006-01-02-15-04-05"))
if err := os.MkdirAll(exportDir, 0755); err != nil {
return fmt.Errorf("cannot create export directory: %w", err)
}
fmt.Println("Exporting framework", framework.Name, "to", exportDir)
cursor := page.NewCursor(
0,
nil,
page.Head,
page.OrderBy[coredata.ControlOrderField]{
Field: coredata.ControlOrderFieldCreatedAt,
Direction: page.OrderDirectionAsc,
},
)
controls := coredata.Controls{}
if err := controls.LoadByFrameworkID(ctx, conn, s.svc.scope, frameworkID, cursor); err != nil {
return fmt.Errorf("cannot load controls: %w", err)
}
for _, control := range controls {
controlDir := filepath.Join(exportDir, control.ReferenceID)
if err := os.MkdirAll(controlDir, 0755); err != nil {
return fmt.Errorf("cannot create control directory: %w", err)
}
measures := coredata.Measures{}
cursor := page.NewCursor(
0,
nil,
page.Head,
page.OrderBy[coredata.MeasureOrderField]{
Field: coredata.MeasureOrderFieldCreatedAt,
Direction: page.OrderDirectionAsc,
},
)
if err := measures.LoadByControlID(ctx, conn, s.svc.scope, control.ID, cursor); err != nil {
return fmt.Errorf("cannot load measures: %w", err)
}
policies := coredata.Policies{}
cursor2 := page.NewCursor(
0,
nil,
page.Head,
page.OrderBy[coredata.PolicyOrderField]{
Field: coredata.PolicyOrderFieldCreatedAt,
Direction: page.OrderDirectionAsc,
},
)
if err := policies.LoadByControlID(ctx, conn, s.svc.scope, control.ID, cursor2); err != nil {
return fmt.Errorf("cannot load policies: %w", err)
}
for _, policy := range policies {
policyDir := filepath.Join(controlDir, policy.Title)
if err := os.MkdirAll(policyDir, 0755); err != nil {
return fmt.Errorf("cannot create policy directory: %w", err)
}
version := coredata.PolicyVersion{}
if err := version.LoadLatestVersion(ctx, conn, s.svc.scope, policy.ID); err != nil {
return fmt.Errorf("cannot load policy version: %w", err)
}
policyFile := filepath.Join(policyDir, "policy.md")
if err := os.WriteFile(policyFile, []byte(version.Content), 0644); err != nil {
return fmt.Errorf("cannot write policy file: %w", err)
}
}
for _, measure := range measures {
measureDir := filepath.Join(controlDir, measure.Name)
if err := os.MkdirAll(measureDir, 0755); err != nil {
return fmt.Errorf("cannot create measure directory: %w", err)
}
evidences := coredata.Evidences{}
cursor := page.NewCursor(
0,
nil,
page.Head,
page.OrderBy[coredata.EvidenceOrderField]{
Field: coredata.EvidenceOrderFieldCreatedAt,
Direction: page.OrderDirectionAsc,
},
)
if err := evidences.LoadByMeasureID(ctx, conn, s.svc.scope, measure.ID, cursor); err != nil {
return fmt.Errorf("cannot load evidences: %w", err)
}
for _, evidence := range evidences {
evidenceFile := filepath.Join(measureDir, evidence.Filename)
if evidence.Type == coredata.EvidenceTypeFile && evidence.ObjectKey != "" {
output, err := s.svc.s3.GetObject(
ctx,
&s3.GetObjectInput{
Bucket: aws.String(s.svc.bucket),
Key: aws.String(evidence.ObjectKey),
},
)
if err != nil {
return fmt.Errorf("cannot download evidence file: %w", err)
}
defer output.Body.Close()
file, err := os.Create(evidenceFile)
if err != nil {
return fmt.Errorf("cannot create evidence file: %w", err)
}
defer file.Close()
_, err = io.Copy(file, output.Body)
if err != nil {
return fmt.Errorf("cannot write evidence file: %w", err)
}
}
}
}
}
return nil
},
)
if err != nil {
return nil, err
}
return nil, nil
}

View File

@@ -12,7 +12,6 @@ directive @goModel(
directive @goEnum(value: String) on ENUM_VALUE directive @goEnum(value: String) on ENUM_VALUE
# Scalars # Scalars
scalar CursorKey scalar CursorKey
scalar Void scalar Void
@@ -97,7 +96,9 @@ enum PolicyStatus
DRAFT DRAFT
@goEnum(value: "github.com/getprobo/probo/pkg/coredata.PolicyStatusDraft") @goEnum(value: "github.com/getprobo/probo/pkg/coredata.PolicyStatusDraft")
PUBLISHED PUBLISHED
@goEnum(value: "github.com/getprobo/probo/pkg/coredata.PolicyStatusPublished") @goEnum(
value: "github.com/getprobo/probo/pkg/coredata.PolicyStatusPublished"
)
} }
enum EvidenceType enum EvidenceType
@@ -249,27 +250,36 @@ enum DataSensitivity
LOW LOW
@goEnum(value: "github.com/getprobo/probo/pkg/coredata.DataSensitivityLow") @goEnum(value: "github.com/getprobo/probo/pkg/coredata.DataSensitivityLow")
MEDIUM MEDIUM
@goEnum(value: "github.com/getprobo/probo/pkg/coredata.DataSensitivityMedium") @goEnum(
value: "github.com/getprobo/probo/pkg/coredata.DataSensitivityMedium"
)
HIGH HIGH
@goEnum(value: "github.com/getprobo/probo/pkg/coredata.DataSensitivityHigh") @goEnum(value: "github.com/getprobo/probo/pkg/coredata.DataSensitivityHigh")
CRITICAL CRITICAL
@goEnum(value: "github.com/getprobo/probo/pkg/coredata.DataSensitivityCritical") @goEnum(
value: "github.com/getprobo/probo/pkg/coredata.DataSensitivityCritical"
)
} }
enum BusinessImpact enum BusinessImpact
@goModel(model: "github.com/getprobo/probo/pkg/coredata.BusinessImpact") { @goModel(model: "github.com/getprobo/probo/pkg/coredata.BusinessImpact") {
LOW LOW @goEnum(value: "github.com/getprobo/probo/pkg/coredata.BusinessImpactLow")
@goEnum(value: "github.com/getprobo/probo/pkg/coredata.BusinessImpactLow")
MEDIUM MEDIUM
@goEnum(value: "github.com/getprobo/probo/pkg/coredata.BusinessImpactMedium") @goEnum(
value: "github.com/getprobo/probo/pkg/coredata.BusinessImpactMedium"
)
HIGH HIGH
@goEnum(value: "github.com/getprobo/probo/pkg/coredata.BusinessImpactHigh") @goEnum(value: "github.com/getprobo/probo/pkg/coredata.BusinessImpactHigh")
CRITICAL CRITICAL
@goEnum(value: "github.com/getprobo/probo/pkg/coredata.BusinessImpactCritical") @goEnum(
value: "github.com/getprobo/probo/pkg/coredata.BusinessImpactCritical"
)
} }
enum PolicyVersionOrderField enum PolicyVersionOrderField
@goModel(model: "github.com/getprobo/probo/pkg/coredata.PolicyVersionOrderField") { @goModel(
model: "github.com/getprobo/probo/pkg/coredata.PolicyVersionOrderField"
) {
VERSION VERSION
@goEnum( @goEnum(
value: "github.com/getprobo/probo/pkg/coredata.PolicyVersionOrderFieldVersion" value: "github.com/getprobo/probo/pkg/coredata.PolicyVersionOrderFieldVersion"
@@ -1016,8 +1026,12 @@ type Mutation {
requestEvidence(input: RequestEvidenceInput!): RequestEvidencePayload! requestEvidence(input: RequestEvidenceInput!): RequestEvidencePayload!
fulfillEvidence(input: FulfillEvidenceInput!): FulfillEvidencePayload! fulfillEvidence(input: FulfillEvidenceInput!): FulfillEvidencePayload!
deleteEvidence(input: DeleteEvidenceInput!): DeleteEvidencePayload! deleteEvidence(input: DeleteEvidenceInput!): DeleteEvidencePayload!
uploadTaskEvidence(input: UploadTaskEvidenceInput!): UploadTaskEvidencePayload! uploadTaskEvidence(
uploadMeasureEvidence(input: UploadMeasureEvidenceInput!): UploadMeasureEvidencePayload! input: UploadTaskEvidenceInput!
): UploadTaskEvidencePayload!
uploadMeasureEvidence(
input: UploadMeasureEvidenceInput!
): UploadMeasureEvidencePayload!
# Vendor Compliance Report mutations # Vendor Compliance Report mutations
uploadVendorComplianceReport( uploadVendorComplianceReport(
@@ -1030,13 +1044,25 @@ type Mutation {
# Policy mutations # Policy mutations
createPolicy(input: CreatePolicyInput!): CreatePolicyPayload! createPolicy(input: CreatePolicyInput!): CreatePolicyPayload!
deletePolicy(input: DeletePolicyInput!): DeletePolicyPayload! deletePolicy(input: DeletePolicyInput!): DeletePolicyPayload!
publishPolicyVersion(input: PublishPolicyVersionInput!): PublishPolicyVersionPayload! publishPolicyVersion(
createDraftPolicyVersion(input: CreateDraftPolicyVersionInput!): CreateDraftPolicyVersionPayload! input: PublishPolicyVersionInput!
updatePolicyVersion(input: UpdatePolicyVersionInput!): UpdatePolicyVersionPayload! ): PublishPolicyVersionPayload!
createDraftPolicyVersion(
input: CreateDraftPolicyVersionInput!
): CreateDraftPolicyVersionPayload!
updatePolicyVersion(
input: UpdatePolicyVersionInput!
): UpdatePolicyVersionPayload!
requestSignature(input: RequestSignatureInput!): RequestSignaturePayload! requestSignature(input: RequestSignatureInput!): RequestSignaturePayload!
sendSigningNotifications(input: SendSigningNotificationsInput!): SendSigningNotificationsPayload! sendSigningNotifications(
input: SendSigningNotificationsInput!
): SendSigningNotificationsPayload!
createVendorRiskAssessment(input: CreateVendorRiskAssessmentInput!): CreateVendorRiskAssessmentPayload! createVendorRiskAssessment(
input: CreateVendorRiskAssessmentInput!
): CreateVendorRiskAssessmentPayload!
exportAudit(input: ExportAuditInput!): ExportAuditPayload!
} }
# Input Types # Input Types
@@ -1531,7 +1557,9 @@ type VendorRiskAssessment implements Node {
} }
enum VendorRiskAssessmentOrderField enum VendorRiskAssessmentOrderField
@goModel(model: "github.com/getprobo/probo/pkg/coredata.VendorRiskAssessmentOrderField") { @goModel(
model: "github.com/getprobo/probo/pkg/coredata.VendorRiskAssessmentOrderField"
) {
CREATED_AT CREATED_AT
@goEnum( @goEnum(
value: "github.com/getprobo/probo/pkg/coredata.VendorRiskAssessmentOrderFieldCreatedAt" value: "github.com/getprobo/probo/pkg/coredata.VendorRiskAssessmentOrderFieldCreatedAt"
@@ -1605,7 +1633,9 @@ input PolicyVersionSignatureOrder {
} }
enum PolicyVersionSignatureState enum PolicyVersionSignatureState
@goModel(model: "github.com/getprobo/probo/pkg/coredata.PolicyVersionSignatureState") { @goModel(
model: "github.com/getprobo/probo/pkg/coredata.PolicyVersionSignatureState"
) {
REQUESTED REQUESTED
@goEnum( @goEnum(
value: "github.com/getprobo/probo/pkg/coredata.PolicyVersionSignatureStateRequested" value: "github.com/getprobo/probo/pkg/coredata.PolicyVersionSignatureStateRequested"
@@ -1617,7 +1647,9 @@ enum PolicyVersionSignatureState
} }
enum PolicyVersionSignatureOrderField enum PolicyVersionSignatureOrderField
@goModel(model: "github.com/getprobo/probo/pkg/coredata.PolicyVersionSignatureOrderField") { @goModel(
model: "github.com/getprobo/probo/pkg/coredata.PolicyVersionSignatureOrderField"
) {
CREATED_AT CREATED_AT
@goEnum( @goEnum(
value: "github.com/getprobo/probo/pkg/coredata.PolicyVersionSignatureOrderFieldCreatedAt" value: "github.com/getprobo/probo/pkg/coredata.PolicyVersionSignatureOrderFieldCreatedAt"
@@ -1700,3 +1732,11 @@ input UploadMeasureEvidenceInput {
measureId: ID! measureId: ID!
file: Upload! file: Upload!
} }
input ExportAuditInput {
frameworkId: ID!
}
type ExportAuditPayload {
success: Boolean!
}

View File

@@ -256,6 +256,10 @@ type ComplexityRoot struct {
Node func(childComplexity int) int Node func(childComplexity int) int
} }
ExportAuditPayload struct {
Success func(childComplexity int) int
}
Framework struct { Framework struct {
Controls func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ControlOrderBy) int Controls func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ControlOrderBy) int
CreatedAt func(childComplexity int) int CreatedAt func(childComplexity int) int
@@ -347,6 +351,7 @@ type ComplexityRoot struct {
DeleteTask func(childComplexity int, input types.DeleteTaskInput) int DeleteTask func(childComplexity int, input types.DeleteTaskInput) int
DeleteVendor func(childComplexity int, input types.DeleteVendorInput) int DeleteVendor func(childComplexity int, input types.DeleteVendorInput) int
DeleteVendorComplianceReport func(childComplexity int, input types.DeleteVendorComplianceReportInput) int DeleteVendorComplianceReport func(childComplexity int, input types.DeleteVendorComplianceReportInput) int
ExportAudit func(childComplexity int, input types.ExportAuditInput) int
FulfillEvidence func(childComplexity int, input types.FulfillEvidenceInput) int FulfillEvidence func(childComplexity int, input types.FulfillEvidenceInput) int
ImportFramework func(childComplexity int, input types.ImportFrameworkInput) int ImportFramework func(childComplexity int, input types.ImportFrameworkInput) int
ImportMeasure func(childComplexity int, input types.ImportMeasureInput) int ImportMeasure func(childComplexity int, input types.ImportMeasureInput) int
@@ -810,6 +815,7 @@ type MutationResolver interface {
RequestSignature(ctx context.Context, input types.RequestSignatureInput) (*types.RequestSignaturePayload, error) RequestSignature(ctx context.Context, input types.RequestSignatureInput) (*types.RequestSignaturePayload, error)
SendSigningNotifications(ctx context.Context, input types.SendSigningNotificationsInput) (*types.SendSigningNotificationsPayload, error) SendSigningNotifications(ctx context.Context, input types.SendSigningNotificationsInput) (*types.SendSigningNotificationsPayload, error)
CreateVendorRiskAssessment(ctx context.Context, input types.CreateVendorRiskAssessmentInput) (*types.CreateVendorRiskAssessmentPayload, error) CreateVendorRiskAssessment(ctx context.Context, input types.CreateVendorRiskAssessmentInput) (*types.CreateVendorRiskAssessmentPayload, error)
ExportAudit(ctx context.Context, input types.ExportAuditInput) (*types.ExportAuditPayload, error)
} }
type OrganizationResolver interface { type OrganizationResolver interface {
LogoURL(ctx context.Context, obj *types.Organization) (*string, error) LogoURL(ctx context.Context, obj *types.Organization) (*string, error)
@@ -1409,6 +1415,13 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
return e.complexity.EvidenceEdge.Node(childComplexity), true return e.complexity.EvidenceEdge.Node(childComplexity), true
case "ExportAuditPayload.success":
if e.complexity.ExportAuditPayload.Success == nil {
break
}
return e.complexity.ExportAuditPayload.Success(childComplexity), true
case "Framework.controls": case "Framework.controls":
if e.complexity.Framework.Controls == nil { if e.complexity.Framework.Controls == nil {
break break
@@ -2004,6 +2017,18 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
return e.complexity.Mutation.DeleteVendorComplianceReport(childComplexity, args["input"].(types.DeleteVendorComplianceReportInput)), true return e.complexity.Mutation.DeleteVendorComplianceReport(childComplexity, args["input"].(types.DeleteVendorComplianceReportInput)), true
case "Mutation.exportAudit":
if e.complexity.Mutation.ExportAudit == nil {
break
}
args, err := ec.field_Mutation_exportAudit_args(ctx, rawArgs)
if err != nil {
return 0, false
}
return e.complexity.Mutation.ExportAudit(childComplexity, args["input"].(types.ExportAuditInput)), true
case "Mutation.fulfillEvidence": case "Mutation.fulfillEvidence":
if e.complexity.Mutation.FulfillEvidence == nil { if e.complexity.Mutation.FulfillEvidence == nil {
break break
@@ -3810,6 +3835,7 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler {
ec.unmarshalInputDeleteVendorComplianceReportInput, ec.unmarshalInputDeleteVendorComplianceReportInput,
ec.unmarshalInputDeleteVendorInput, ec.unmarshalInputDeleteVendorInput,
ec.unmarshalInputEvidenceOrder, ec.unmarshalInputEvidenceOrder,
ec.unmarshalInputExportAuditInput,
ec.unmarshalInputFrameworkOrder, ec.unmarshalInputFrameworkOrder,
ec.unmarshalInputFulfillEvidenceInput, ec.unmarshalInputFulfillEvidenceInput,
ec.unmarshalInputImportFrameworkInput, ec.unmarshalInputImportFrameworkInput,
@@ -3957,7 +3983,6 @@ directive @goModel(
directive @goEnum(value: String) on ENUM_VALUE directive @goEnum(value: String) on ENUM_VALUE
# Scalars # Scalars
scalar CursorKey scalar CursorKey
scalar Void scalar Void
@@ -4042,7 +4067,9 @@ enum PolicyStatus
DRAFT DRAFT
@goEnum(value: "github.com/getprobo/probo/pkg/coredata.PolicyStatusDraft") @goEnum(value: "github.com/getprobo/probo/pkg/coredata.PolicyStatusDraft")
PUBLISHED PUBLISHED
@goEnum(value: "github.com/getprobo/probo/pkg/coredata.PolicyStatusPublished") @goEnum(
value: "github.com/getprobo/probo/pkg/coredata.PolicyStatusPublished"
)
} }
enum EvidenceType enum EvidenceType
@@ -4194,27 +4221,36 @@ enum DataSensitivity
LOW LOW
@goEnum(value: "github.com/getprobo/probo/pkg/coredata.DataSensitivityLow") @goEnum(value: "github.com/getprobo/probo/pkg/coredata.DataSensitivityLow")
MEDIUM MEDIUM
@goEnum(value: "github.com/getprobo/probo/pkg/coredata.DataSensitivityMedium") @goEnum(
value: "github.com/getprobo/probo/pkg/coredata.DataSensitivityMedium"
)
HIGH HIGH
@goEnum(value: "github.com/getprobo/probo/pkg/coredata.DataSensitivityHigh") @goEnum(value: "github.com/getprobo/probo/pkg/coredata.DataSensitivityHigh")
CRITICAL CRITICAL
@goEnum(value: "github.com/getprobo/probo/pkg/coredata.DataSensitivityCritical") @goEnum(
value: "github.com/getprobo/probo/pkg/coredata.DataSensitivityCritical"
)
} }
enum BusinessImpact enum BusinessImpact
@goModel(model: "github.com/getprobo/probo/pkg/coredata.BusinessImpact") { @goModel(model: "github.com/getprobo/probo/pkg/coredata.BusinessImpact") {
LOW LOW @goEnum(value: "github.com/getprobo/probo/pkg/coredata.BusinessImpactLow")
@goEnum(value: "github.com/getprobo/probo/pkg/coredata.BusinessImpactLow")
MEDIUM MEDIUM
@goEnum(value: "github.com/getprobo/probo/pkg/coredata.BusinessImpactMedium") @goEnum(
value: "github.com/getprobo/probo/pkg/coredata.BusinessImpactMedium"
)
HIGH HIGH
@goEnum(value: "github.com/getprobo/probo/pkg/coredata.BusinessImpactHigh") @goEnum(value: "github.com/getprobo/probo/pkg/coredata.BusinessImpactHigh")
CRITICAL CRITICAL
@goEnum(value: "github.com/getprobo/probo/pkg/coredata.BusinessImpactCritical") @goEnum(
value: "github.com/getprobo/probo/pkg/coredata.BusinessImpactCritical"
)
} }
enum PolicyVersionOrderField enum PolicyVersionOrderField
@goModel(model: "github.com/getprobo/probo/pkg/coredata.PolicyVersionOrderField") { @goModel(
model: "github.com/getprobo/probo/pkg/coredata.PolicyVersionOrderField"
) {
VERSION VERSION
@goEnum( @goEnum(
value: "github.com/getprobo/probo/pkg/coredata.PolicyVersionOrderFieldVersion" value: "github.com/getprobo/probo/pkg/coredata.PolicyVersionOrderFieldVersion"
@@ -4961,8 +4997,12 @@ type Mutation {
requestEvidence(input: RequestEvidenceInput!): RequestEvidencePayload! requestEvidence(input: RequestEvidenceInput!): RequestEvidencePayload!
fulfillEvidence(input: FulfillEvidenceInput!): FulfillEvidencePayload! fulfillEvidence(input: FulfillEvidenceInput!): FulfillEvidencePayload!
deleteEvidence(input: DeleteEvidenceInput!): DeleteEvidencePayload! deleteEvidence(input: DeleteEvidenceInput!): DeleteEvidencePayload!
uploadTaskEvidence(input: UploadTaskEvidenceInput!): UploadTaskEvidencePayload! uploadTaskEvidence(
uploadMeasureEvidence(input: UploadMeasureEvidenceInput!): UploadMeasureEvidencePayload! input: UploadTaskEvidenceInput!
): UploadTaskEvidencePayload!
uploadMeasureEvidence(
input: UploadMeasureEvidenceInput!
): UploadMeasureEvidencePayload!
# Vendor Compliance Report mutations # Vendor Compliance Report mutations
uploadVendorComplianceReport( uploadVendorComplianceReport(
@@ -4975,13 +5015,25 @@ type Mutation {
# Policy mutations # Policy mutations
createPolicy(input: CreatePolicyInput!): CreatePolicyPayload! createPolicy(input: CreatePolicyInput!): CreatePolicyPayload!
deletePolicy(input: DeletePolicyInput!): DeletePolicyPayload! deletePolicy(input: DeletePolicyInput!): DeletePolicyPayload!
publishPolicyVersion(input: PublishPolicyVersionInput!): PublishPolicyVersionPayload! publishPolicyVersion(
createDraftPolicyVersion(input: CreateDraftPolicyVersionInput!): CreateDraftPolicyVersionPayload! input: PublishPolicyVersionInput!
updatePolicyVersion(input: UpdatePolicyVersionInput!): UpdatePolicyVersionPayload! ): PublishPolicyVersionPayload!
createDraftPolicyVersion(
input: CreateDraftPolicyVersionInput!
): CreateDraftPolicyVersionPayload!
updatePolicyVersion(
input: UpdatePolicyVersionInput!
): UpdatePolicyVersionPayload!
requestSignature(input: RequestSignatureInput!): RequestSignaturePayload! requestSignature(input: RequestSignatureInput!): RequestSignaturePayload!
sendSigningNotifications(input: SendSigningNotificationsInput!): SendSigningNotificationsPayload! sendSigningNotifications(
input: SendSigningNotificationsInput!
): SendSigningNotificationsPayload!
createVendorRiskAssessment(input: CreateVendorRiskAssessmentInput!): CreateVendorRiskAssessmentPayload! createVendorRiskAssessment(
input: CreateVendorRiskAssessmentInput!
): CreateVendorRiskAssessmentPayload!
exportAudit(input: ExportAuditInput!): ExportAuditPayload!
} }
# Input Types # Input Types
@@ -5476,7 +5528,9 @@ type VendorRiskAssessment implements Node {
} }
enum VendorRiskAssessmentOrderField enum VendorRiskAssessmentOrderField
@goModel(model: "github.com/getprobo/probo/pkg/coredata.VendorRiskAssessmentOrderField") { @goModel(
model: "github.com/getprobo/probo/pkg/coredata.VendorRiskAssessmentOrderField"
) {
CREATED_AT CREATED_AT
@goEnum( @goEnum(
value: "github.com/getprobo/probo/pkg/coredata.VendorRiskAssessmentOrderFieldCreatedAt" value: "github.com/getprobo/probo/pkg/coredata.VendorRiskAssessmentOrderFieldCreatedAt"
@@ -5550,7 +5604,9 @@ input PolicyVersionSignatureOrder {
} }
enum PolicyVersionSignatureState enum PolicyVersionSignatureState
@goModel(model: "github.com/getprobo/probo/pkg/coredata.PolicyVersionSignatureState") { @goModel(
model: "github.com/getprobo/probo/pkg/coredata.PolicyVersionSignatureState"
) {
REQUESTED REQUESTED
@goEnum( @goEnum(
value: "github.com/getprobo/probo/pkg/coredata.PolicyVersionSignatureStateRequested" value: "github.com/getprobo/probo/pkg/coredata.PolicyVersionSignatureStateRequested"
@@ -5562,7 +5618,9 @@ enum PolicyVersionSignatureState
} }
enum PolicyVersionSignatureOrderField enum PolicyVersionSignatureOrderField
@goModel(model: "github.com/getprobo/probo/pkg/coredata.PolicyVersionSignatureOrderField") { @goModel(
model: "github.com/getprobo/probo/pkg/coredata.PolicyVersionSignatureOrderField"
) {
CREATED_AT CREATED_AT
@goEnum( @goEnum(
value: "github.com/getprobo/probo/pkg/coredata.PolicyVersionSignatureOrderFieldCreatedAt" value: "github.com/getprobo/probo/pkg/coredata.PolicyVersionSignatureOrderFieldCreatedAt"
@@ -5645,6 +5703,14 @@ input UploadMeasureEvidenceInput {
measureId: ID! measureId: ID!
file: Upload! file: Upload!
} }
input ExportAuditInput {
frameworkId: ID!
}
type ExportAuditPayload {
success: Boolean!
}
`, BuiltIn: false}, `, BuiltIn: false},
} }
var parsedSchema = gqlparser.MustLoadSchema(sources...) var parsedSchema = gqlparser.MustLoadSchema(sources...)
@@ -7008,6 +7074,29 @@ func (ec *executionContext) field_Mutation_deleteVendor_argsInput(
return zeroVal, nil return zeroVal, nil
} }
func (ec *executionContext) field_Mutation_exportAudit_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
var err error
args := map[string]any{}
arg0, err := ec.field_Mutation_exportAudit_argsInput(ctx, rawArgs)
if err != nil {
return nil, err
}
args["input"] = arg0
return args, nil
}
func (ec *executionContext) field_Mutation_exportAudit_argsInput(
ctx context.Context,
rawArgs map[string]any,
) (types.ExportAuditInput, error) {
ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("input"))
if tmp, ok := rawArgs["input"]; ok {
return ec.unmarshalNExportAuditInput2githubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐExportAuditInput(ctx, tmp)
}
var zeroVal types.ExportAuditInput
return zeroVal, nil
}
func (ec *executionContext) field_Mutation_fulfillEvidence_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { func (ec *executionContext) field_Mutation_fulfillEvidence_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
var err error var err error
args := map[string]any{} args := map[string]any{}
@@ -12900,6 +12989,50 @@ func (ec *executionContext) fieldContext_EvidenceEdge_node(_ context.Context, fi
return fc, nil return fc, nil
} }
func (ec *executionContext) _ExportAuditPayload_success(ctx context.Context, field graphql.CollectedField, obj *types.ExportAuditPayload) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_ExportAuditPayload_success(ctx, field)
if err != nil {
return graphql.Null
}
ctx = graphql.WithFieldContext(ctx, fc)
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
}()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
ctx = rctx // use context from middleware stack in children
return obj.Success, nil
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
if !graphql.HasFieldError(ctx, fc) {
ec.Errorf(ctx, "must not be null")
}
return graphql.Null
}
res := resTmp.(bool)
fc.Result = res
return ec.marshalNBoolean2bool(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_ExportAuditPayload_success(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "ExportAuditPayload",
Field: field,
IsMethod: false,
IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
return nil, errors.New("field of type Boolean does not have child fields")
},
}
return fc, nil
}
func (ec *executionContext) _Framework_id(ctx context.Context, field graphql.CollectedField, obj *types.Framework) (ret graphql.Marshaler) { 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) fc, err := ec.fieldContext_Framework_id(ctx, field)
if err != nil { if err != nil {
@@ -17438,6 +17571,65 @@ func (ec *executionContext) fieldContext_Mutation_createVendorRiskAssessment(ctx
return fc, nil return fc, nil
} }
func (ec *executionContext) _Mutation_exportAudit(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Mutation_exportAudit(ctx, field)
if err != nil {
return graphql.Null
}
ctx = graphql.WithFieldContext(ctx, fc)
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
}()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
ctx = rctx // use context from middleware stack in children
return ec.resolvers.Mutation().ExportAudit(rctx, fc.Args["input"].(types.ExportAuditInput))
})
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.ExportAuditPayload)
fc.Result = res
return ec.marshalNExportAuditPayload2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐExportAuditPayload(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_Mutation_exportAudit(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "Mutation",
Field: field,
IsMethod: true,
IsResolver: true,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
switch field.Name {
case "success":
return ec.fieldContext_ExportAuditPayload_success(ctx, field)
}
return nil, fmt.Errorf("no field named %q was found under type ExportAuditPayload", 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_exportAudit_args(ctx, field.ArgumentMap(ec.Variables)); err != nil {
ec.Error(ctx, err)
return fc, err
}
return fc, nil
}
func (ec *executionContext) _Organization_id(ctx context.Context, field graphql.CollectedField, obj *types.Organization) (ret graphql.Marshaler) { func (ec *executionContext) _Organization_id(ctx context.Context, field graphql.CollectedField, obj *types.Organization) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Organization_id(ctx, field) fc, err := ec.fieldContext_Organization_id(ctx, field)
if err != nil { if err != nil {
@@ -31253,6 +31445,33 @@ func (ec *executionContext) unmarshalInputEvidenceOrder(ctx context.Context, obj
return it, nil return it, nil
} }
func (ec *executionContext) unmarshalInputExportAuditInput(ctx context.Context, obj any) (types.ExportAuditInput, error) {
var it types.ExportAuditInput
asMap := map[string]any{}
for k, v := range obj.(map[string]any) {
asMap[k] = v
}
fieldsInOrder := [...]string{"frameworkId"}
for _, k := range fieldsInOrder {
v, ok := asMap[k]
if !ok {
continue
}
switch k {
case "frameworkId":
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("frameworkId"))
data, err := ec.unmarshalNID2githubᚗcomᚋgetproboᚋproboᚋpkgᚋgidᚐGID(ctx, v)
if err != nil {
return it, err
}
it.FrameworkID = data
}
}
return it, nil
}
func (ec *executionContext) unmarshalInputFrameworkOrder(ctx context.Context, obj any) (types.FrameworkOrderBy, error) { func (ec *executionContext) unmarshalInputFrameworkOrder(ctx context.Context, obj any) (types.FrameworkOrderBy, error) {
var it types.FrameworkOrderBy var it types.FrameworkOrderBy
asMap := map[string]any{} asMap := map[string]any{}
@@ -34792,6 +35011,45 @@ func (ec *executionContext) _EvidenceEdge(ctx context.Context, sel ast.Selection
return out return out
} }
var exportAuditPayloadImplementors = []string{"ExportAuditPayload"}
func (ec *executionContext) _ExportAuditPayload(ctx context.Context, sel ast.SelectionSet, obj *types.ExportAuditPayload) graphql.Marshaler {
fields := graphql.CollectFields(ec.OperationContext, sel, exportAuditPayloadImplementors)
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("ExportAuditPayload")
case "success":
out.Values[i] = ec._ExportAuditPayload_success(ctx, field, obj)
if out.Values[i] == graphql.Null {
out.Invalids++
}
default:
panic("unknown field " + strconv.Quote(field.Name))
}
}
out.Dispatch(ctx)
if out.Invalids > 0 {
return graphql.Null
}
atomic.AddInt32(&ec.deferred, int32(len(deferred)))
for label, dfs := range deferred {
ec.processDeferredGroup(graphql.DeferredGroup{
Label: label,
Path: graphql.GetPath(ctx),
FieldSet: dfs,
Context: ctx,
})
}
return out
}
var frameworkImplementors = []string{"Framework", "Node"} var frameworkImplementors = []string{"Framework", "Node"}
func (ec *executionContext) _Framework(ctx context.Context, sel ast.SelectionSet, obj *types.Framework) graphql.Marshaler { func (ec *executionContext) _Framework(ctx context.Context, sel ast.SelectionSet, obj *types.Framework) graphql.Marshaler {
@@ -35844,6 +36102,13 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet)
if out.Values[i] == graphql.Null { if out.Values[i] == graphql.Null {
out.Invalids++ out.Invalids++
} }
case "exportAudit":
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
return ec._Mutation_exportAudit(ctx, field)
})
if out.Values[i] == graphql.Null {
out.Invalids++
}
default: default:
panic("unknown field " + strconv.Quote(field.Name)) panic("unknown field " + strconv.Quote(field.Name))
} }
@@ -41331,6 +41596,25 @@ var (
} }
) )
func (ec *executionContext) unmarshalNExportAuditInput2githubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐExportAuditInput(ctx context.Context, v any) (types.ExportAuditInput, error) {
res, err := ec.unmarshalInputExportAuditInput(ctx, v)
return res, graphql.ErrorOnPath(ctx, err)
}
func (ec *executionContext) marshalNExportAuditPayload2githubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐExportAuditPayload(ctx context.Context, sel ast.SelectionSet, v types.ExportAuditPayload) graphql.Marshaler {
return ec._ExportAuditPayload(ctx, sel, &v)
}
func (ec *executionContext) marshalNExportAuditPayload2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐExportAuditPayload(ctx context.Context, sel ast.SelectionSet, v *types.ExportAuditPayload) 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._ExportAuditPayload(ctx, sel, v)
}
func (ec *executionContext) marshalNFramework2githubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐFramework(ctx context.Context, sel ast.SelectionSet, v types.Framework) graphql.Marshaler { func (ec *executionContext) marshalNFramework2githubᚗcomᚋgetproboᚋ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) return ec._Framework(ctx, sel, &v)
} }

View File

@@ -411,6 +411,14 @@ type EvidenceEdge struct {
Node *Evidence `json:"node"` Node *Evidence `json:"node"`
} }
type ExportAuditInput struct {
FrameworkID gid.GID `json:"frameworkId"`
}
type ExportAuditPayload struct {
Success bool `json:"success"`
}
type Framework struct { type Framework struct {
ID gid.GID `json:"id"` ID gid.GID `json:"id"`
Name string `json:"name"` Name string `json:"name"`

View File

@@ -1289,6 +1289,19 @@ func (r *mutationResolver) CreateVendorRiskAssessment(ctx context.Context, input
}, nil }, nil
} }
// ExportAudit is the resolver for the exportAudit field.
func (r *mutationResolver) ExportAudit(ctx context.Context, input types.ExportAuditInput) (*types.ExportAuditPayload, error) {
svc := GetTenantService(ctx, r.proboSvc, input.FrameworkID.TenantID())
_, err := svc.Frameworks.ExportAudit(ctx, input.FrameworkID)
if err != nil {
panic(fmt.Errorf("cannot export audit: %w", err))
}
return &types.ExportAuditPayload{
Success: true,
}, nil
}
// LogoURL is the resolver for the logoUrl field. // LogoURL is the resolver for the logoUrl field.
func (r *organizationResolver) LogoURL(ctx context.Context, obj *types.Organization) (*string, error) { func (r *organizationResolver) LogoURL(ctx context.Context, obj *types.Organization) (*string, error) {
svc := GetTenantService(ctx, r.proboSvc, obj.ID.TenantID()) svc := GetTenantService(ctx, r.proboSvc, obj.ID.TenantID())