committed by
Sacha Al Himdani
parent
a11dfdb244
commit
d47cac911d
@@ -49,4 +49,5 @@ const (
|
|||||||
SnapshotEntityType
|
SnapshotEntityType
|
||||||
ContinualImprovementRegistryEntityType
|
ContinualImprovementRegistryEntityType
|
||||||
ProcessingActivityRegistryEntityType
|
ProcessingActivityRegistryEntityType
|
||||||
|
FrameworkExportEntityType
|
||||||
)
|
)
|
||||||
|
|||||||
163
pkg/coredata/framework_export.go
Normal file
163
pkg/coredata/framework_export.go
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
// 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 coredata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"maps"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/getprobo/probo/pkg/gid"
|
||||||
|
"github.com/getprobo/probo/pkg/page"
|
||||||
|
"github.com/jackc/pgx/v5"
|
||||||
|
"go.gearno.de/kit/pg"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
FrameworkExport struct {
|
||||||
|
ID gid.GID `db:"id"`
|
||||||
|
FrameworkID gid.GID `db:"framework_id"`
|
||||||
|
Status FrameworkExportStatus `db:"status"`
|
||||||
|
FileID *gid.GID `db:"file_id"`
|
||||||
|
CreatedAt time.Time `db:"created_at"`
|
||||||
|
StartedAt *time.Time `db:"started_at"`
|
||||||
|
CompletedAt *time.Time `db:"completed_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
FrameworkExports []*FrameworkExport
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrNoFrameworkExportAvailable = errors.New("no framework export available")
|
||||||
|
)
|
||||||
|
|
||||||
|
func (fe FrameworkExport) CursorKey(orderBy FrameworkExportOrderField) page.CursorKey {
|
||||||
|
switch orderBy {
|
||||||
|
case FrameworkExportOrderFieldCreatedAt:
|
||||||
|
return page.NewCursorKey(fe.ID, fe.CreatedAt)
|
||||||
|
}
|
||||||
|
|
||||||
|
panic(fmt.Sprintf("unsupported order by: %s", orderBy))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fe *FrameworkExport) Insert(
|
||||||
|
ctx context.Context,
|
||||||
|
conn pg.Conn,
|
||||||
|
scope Scoper,
|
||||||
|
) error {
|
||||||
|
q := `
|
||||||
|
INSERT INTO framework_exports (
|
||||||
|
id,
|
||||||
|
tenant_id,
|
||||||
|
framework_id,
|
||||||
|
status,
|
||||||
|
created_at,
|
||||||
|
expires_at
|
||||||
|
) VALUES (
|
||||||
|
@id,
|
||||||
|
@tenant_id,
|
||||||
|
@framework_id,
|
||||||
|
@status,
|
||||||
|
@created_at,
|
||||||
|
@expires_at
|
||||||
|
)`
|
||||||
|
|
||||||
|
args := pgx.StrictNamedArgs{
|
||||||
|
"id": fe.ID,
|
||||||
|
"tenant_id": scope.GetTenantID(),
|
||||||
|
"framework_id": fe.FrameworkID,
|
||||||
|
"status": fe.Status,
|
||||||
|
"created_at": fe.CreatedAt,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := conn.Exec(ctx, q, args)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fe *FrameworkExport) Update(
|
||||||
|
ctx context.Context,
|
||||||
|
conn pg.Conn,
|
||||||
|
scope Scoper,
|
||||||
|
) error {
|
||||||
|
q := `
|
||||||
|
UPDATE
|
||||||
|
framework_exports
|
||||||
|
SET
|
||||||
|
status = @status,
|
||||||
|
file_id = @file_id,
|
||||||
|
started_at = @started_at,
|
||||||
|
completed_at = @completed_at
|
||||||
|
WHERE
|
||||||
|
%s
|
||||||
|
AND id = @id
|
||||||
|
`
|
||||||
|
|
||||||
|
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||||
|
|
||||||
|
args := pgx.StrictNamedArgs{
|
||||||
|
"status": fe.Status,
|
||||||
|
"file_id": fe.FileID,
|
||||||
|
"started_at": fe.StartedAt,
|
||||||
|
"completed_at": fe.CompletedAt,
|
||||||
|
"id": fe.ID,
|
||||||
|
}
|
||||||
|
maps.Copy(args, scope.SQLArguments())
|
||||||
|
|
||||||
|
_, err := conn.Exec(ctx, q, args)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fe *FrameworkExport) LoadNextPendingForUpdateSkipLocked(
|
||||||
|
ctx context.Context,
|
||||||
|
conn pg.Conn,
|
||||||
|
) error {
|
||||||
|
q := `
|
||||||
|
SELECT
|
||||||
|
id,
|
||||||
|
framework_id,
|
||||||
|
status,
|
||||||
|
created_at,
|
||||||
|
started_at,
|
||||||
|
completed_at
|
||||||
|
FROM
|
||||||
|
framework_exports
|
||||||
|
WHERE
|
||||||
|
status = @status
|
||||||
|
ORDER BY
|
||||||
|
created_at ASC
|
||||||
|
LIMIT 1
|
||||||
|
FOR UPDATE SKIP LOCKED
|
||||||
|
`
|
||||||
|
|
||||||
|
args := pgx.StrictNamedArgs{"status": FrameworkExportStatusPending}
|
||||||
|
|
||||||
|
rows, err := conn.Query(ctx, q, args)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fe2, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[FrameworkExport])
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, pgx.ErrNoRows) {
|
||||||
|
return ErrNoFrameworkExportAvailable
|
||||||
|
}
|
||||||
|
return fmt.Errorf("cannot collect framework export: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
*fe = fe2
|
||||||
|
return nil
|
||||||
|
}
|
||||||
40
pkg/coredata/framework_export_order_field.go
Normal file
40
pkg/coredata/framework_export_order_field.go
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
// 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 coredata
|
||||||
|
|
||||||
|
type (
|
||||||
|
FrameworkExportOrderField string
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
FrameworkExportOrderFieldCreatedAt FrameworkExportOrderField = "CREATED_AT"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (p FrameworkExportOrderField) Column() string {
|
||||||
|
return string(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p FrameworkExportOrderField) String() string {
|
||||||
|
return string(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p FrameworkExportOrderField) MarshalText() ([]byte, error) {
|
||||||
|
return []byte(p.String()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *FrameworkExportOrderField) UnmarshalText(text []byte) error {
|
||||||
|
*p = FrameworkExportOrderField(text)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
86
pkg/coredata/framework_export_status.go
Normal file
86
pkg/coredata/framework_export_status.go
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
// 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 coredata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql/driver"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
FrameworkExportStatus string
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
FrameworkExportStatusPending FrameworkExportStatus = "pending"
|
||||||
|
FrameworkExportStatusProcessing FrameworkExportStatus = "processing"
|
||||||
|
FrameworkExportStatusCompleted FrameworkExportStatus = "completed"
|
||||||
|
FrameworkExportStatusFailed FrameworkExportStatus = "failed"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (pvs FrameworkExportStatus) MarshalText() ([]byte, error) {
|
||||||
|
return []byte(pvs.String()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pvs *FrameworkExportStatus) UnmarshalText(data []byte) error {
|
||||||
|
val := string(data)
|
||||||
|
|
||||||
|
switch val {
|
||||||
|
case FrameworkExportStatusPending.String():
|
||||||
|
*pvs = FrameworkExportStatusPending
|
||||||
|
case FrameworkExportStatusProcessing.String():
|
||||||
|
*pvs = FrameworkExportStatusProcessing
|
||||||
|
case FrameworkExportStatusCompleted.String():
|
||||||
|
*pvs = FrameworkExportStatusCompleted
|
||||||
|
case FrameworkExportStatusFailed.String():
|
||||||
|
*pvs = FrameworkExportStatusFailed
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("invalid FrameworkExportStatus value: %q", val)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pvs FrameworkExportStatus) String() string {
|
||||||
|
var val string
|
||||||
|
|
||||||
|
switch pvs {
|
||||||
|
case FrameworkExportStatusPending:
|
||||||
|
val = "pending"
|
||||||
|
case FrameworkExportStatusProcessing:
|
||||||
|
val = "processing"
|
||||||
|
case FrameworkExportStatusCompleted:
|
||||||
|
val = "completed"
|
||||||
|
case FrameworkExportStatusFailed:
|
||||||
|
val = "failed"
|
||||||
|
default:
|
||||||
|
panic(fmt.Errorf("invalid FrameworkExportStatus value: %q", string(pvs)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pvs *FrameworkExportStatus) Scan(value any) error {
|
||||||
|
val, ok := value.(string)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("invalid scan source for FrameworkExportStatus, expected string got %T", value)
|
||||||
|
}
|
||||||
|
|
||||||
|
return pvs.UnmarshalText([]byte(val))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pvs FrameworkExportStatus) Value() (driver.Value, error) {
|
||||||
|
return pvs.String(), nil
|
||||||
|
}
|
||||||
@@ -249,6 +249,8 @@ WHERE %s
|
|||||||
`
|
`
|
||||||
q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment(), cursor.SQLFragment())
|
q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment(), cursor.SQLFragment())
|
||||||
|
|
||||||
|
fmt.Printf("\n%s\n", q)
|
||||||
|
|
||||||
args := pgx.NamedArgs{"control_id": controlID}
|
args := pgx.NamedArgs{"control_id": controlID}
|
||||||
maps.Copy(args, scope.SQLArguments())
|
maps.Copy(args, scope.SQLArguments())
|
||||||
maps.Copy(args, filter.SQLArguments())
|
maps.Copy(args, filter.SQLArguments())
|
||||||
|
|||||||
20
pkg/coredata/migrations/20250828T091522Z.sql
Normal file
20
pkg/coredata/migrations/20250828T091522Z.sql
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
CREATE TYPE framework_export_status AS ENUM (
|
||||||
|
'pending',
|
||||||
|
'processing',
|
||||||
|
'completed',
|
||||||
|
'failed'
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE framework_exports (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
tenant_id TEXT NOT NULL,
|
||||||
|
framework_id TEXT NOT NULL,
|
||||||
|
status framework_export_status NOT NULL,
|
||||||
|
file_id TEXT,
|
||||||
|
created_at TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||||
|
started_at TIMESTAMP WITH TIME ZONE,
|
||||||
|
completed_at TIMESTAMP WITH TIME ZONE
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1097,65 +1097,14 @@ func (s *DocumentService) ExportPDF(
|
|||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
documentVersionID gid.GID,
|
documentVersionID gid.GID,
|
||||||
) ([]byte, error) {
|
) ([]byte, error) {
|
||||||
document := &coredata.Document{}
|
var data []byte
|
||||||
version := &coredata.DocumentVersion{}
|
|
||||||
owner := &coredata.People{}
|
|
||||||
publishedBy := &coredata.People{}
|
|
||||||
signatures := coredata.DocumentVersionSignatures{}
|
|
||||||
peopleMap := make(map[gid.GID]*coredata.People)
|
|
||||||
|
|
||||||
err := s.svc.pg.WithConn(
|
err := s.svc.pg.WithTx(
|
||||||
ctx,
|
ctx,
|
||||||
func(conn pg.Conn) error {
|
func(conn pg.Conn) (err error) {
|
||||||
if err := version.LoadByID(ctx, conn, s.svc.scope, documentVersionID); err != nil {
|
data, err = exportDocumentPDF(ctx, s.html2pdfConverter, conn, s.svc.scope, documentVersionID)
|
||||||
return fmt.Errorf("cannot load document version: %w", err)
|
if err != nil {
|
||||||
}
|
return fmt.Errorf("cannot export document PDF: %w", err)
|
||||||
|
|
||||||
if err := document.LoadByID(ctx, conn, s.svc.scope, version.DocumentID); err != nil {
|
|
||||||
return fmt.Errorf("cannot load document: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if version.PublishedBy != nil {
|
|
||||||
if err := publishedBy.LoadByID(ctx, conn, s.svc.scope, *version.PublishedBy); err != nil {
|
|
||||||
return fmt.Errorf("cannot load published by person: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cursor := page.NewCursor(
|
|
||||||
100,
|
|
||||||
nil,
|
|
||||||
page.Head,
|
|
||||||
page.OrderBy[coredata.DocumentVersionSignatureOrderField]{
|
|
||||||
Field: coredata.DocumentVersionSignatureOrderFieldCreatedAt,
|
|
||||||
Direction: page.OrderDirectionAsc,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
if err := signatures.LoadByDocumentVersionID(ctx, conn, s.svc.scope, documentVersionID, cursor); err != nil {
|
|
||||||
return fmt.Errorf("cannot load document version signatures: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := owner.LoadByID(ctx, conn, s.svc.scope, document.OwnerID); err != nil {
|
|
||||||
return fmt.Errorf("cannot load document owner: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: refactor this to use a single query
|
|
||||||
for _, sig := range signatures {
|
|
||||||
if _, ok := peopleMap[sig.SignedBy]; !ok {
|
|
||||||
people := &coredata.People{}
|
|
||||||
if err := people.LoadByID(ctx, conn, s.svc.scope, sig.SignedBy); err != nil {
|
|
||||||
return fmt.Errorf("cannot load people %q: %w", sig.SignedBy, err)
|
|
||||||
}
|
|
||||||
peopleMap[sig.SignedBy] = people
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := peopleMap[sig.RequestedBy]; !ok {
|
|
||||||
people := &coredata.People{}
|
|
||||||
if err := people.LoadByID(ctx, conn, s.svc.scope, sig.RequestedBy); err != nil {
|
|
||||||
return fmt.Errorf("cannot load people %q: %w", sig.RequestedBy, err)
|
|
||||||
}
|
|
||||||
peopleMap[sig.RequestedBy] = people
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -1166,6 +1115,74 @@ func (s *DocumentService) ExportPDF(
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func exportDocumentPDF(
|
||||||
|
ctx context.Context,
|
||||||
|
html2pdfConverter *html2pdf.Converter,
|
||||||
|
conn pg.Conn,
|
||||||
|
scope coredata.Scoper,
|
||||||
|
documentVersionID gid.GID,
|
||||||
|
) ([]byte, error) {
|
||||||
|
document := &coredata.Document{}
|
||||||
|
version := &coredata.DocumentVersion{}
|
||||||
|
owner := &coredata.People{}
|
||||||
|
publishedBy := &coredata.People{}
|
||||||
|
signatures := coredata.DocumentVersionSignatures{}
|
||||||
|
peopleMap := make(map[gid.GID]*coredata.People)
|
||||||
|
|
||||||
|
if err := version.LoadByID(ctx, conn, scope, documentVersionID); err != nil {
|
||||||
|
return nil, fmt.Errorf("cannot load document version: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := document.LoadByID(ctx, conn, scope, version.DocumentID); err != nil {
|
||||||
|
return nil, fmt.Errorf("cannot load document: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if version.PublishedBy != nil {
|
||||||
|
if err := publishedBy.LoadByID(ctx, conn, scope, *version.PublishedBy); err != nil {
|
||||||
|
return nil, fmt.Errorf("cannot load published by person: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor := page.NewCursor(
|
||||||
|
100,
|
||||||
|
nil,
|
||||||
|
page.Head,
|
||||||
|
page.OrderBy[coredata.DocumentVersionSignatureOrderField]{
|
||||||
|
Field: coredata.DocumentVersionSignatureOrderFieldCreatedAt,
|
||||||
|
Direction: page.OrderDirectionAsc,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
if err := signatures.LoadByDocumentVersionID(ctx, conn, scope, documentVersionID, cursor); err != nil {
|
||||||
|
return nil, fmt.Errorf("cannot load document version signatures: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := owner.LoadByID(ctx, conn, scope, document.OwnerID); err != nil {
|
||||||
|
return nil, fmt.Errorf("cannot load document owner: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: refactor this to use a single query
|
||||||
|
for _, sig := range signatures {
|
||||||
|
if _, ok := peopleMap[sig.SignedBy]; !ok {
|
||||||
|
people := &coredata.People{}
|
||||||
|
if err := people.LoadByID(ctx, conn, scope, sig.SignedBy); err != nil {
|
||||||
|
return nil, fmt.Errorf("cannot load people %q: %w", sig.SignedBy, err)
|
||||||
|
}
|
||||||
|
peopleMap[sig.SignedBy] = people
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := peopleMap[sig.RequestedBy]; !ok {
|
||||||
|
people := &coredata.People{}
|
||||||
|
if err := people.LoadByID(ctx, conn, scope, sig.RequestedBy); err != nil {
|
||||||
|
return nil, fmt.Errorf("cannot load people %q: %w", sig.RequestedBy, err)
|
||||||
|
}
|
||||||
|
peopleMap[sig.RequestedBy] = people
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
classification := docgen.ClassificationInternal
|
classification := docgen.ClassificationInternal
|
||||||
switch document.DocumentType {
|
switch document.DocumentType {
|
||||||
case coredata.DocumentTypePolicy:
|
case coredata.DocumentTypePolicy:
|
||||||
@@ -1212,7 +1229,7 @@ func (s *DocumentService) ExportPDF(
|
|||||||
Scale: 1.0,
|
Scale: 1.0,
|
||||||
}
|
}
|
||||||
|
|
||||||
pdfReader, err := s.html2pdfConverter.GeneratePDF(ctx, htmlContent, cfg)
|
pdfReader, err := html2pdfConverter.GeneratePDF(ctx, htmlContent, cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("cannot generate PDF: %w", err)
|
return nil, fmt.Errorf("cannot generate PDF: %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,12 +15,17 @@
|
|||||||
package probo
|
package probo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"archive/zip"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"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/html2pdf"
|
||||||
"github.com/getprobo/probo/pkg/page"
|
"github.com/getprobo/probo/pkg/page"
|
||||||
"github.com/getprobo/probo/pkg/slug"
|
"github.com/getprobo/probo/pkg/slug"
|
||||||
"github.com/getprobo/probo/pkg/soagen"
|
"github.com/getprobo/probo/pkg/soagen"
|
||||||
@@ -30,14 +35,12 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
maxStateOfApplicabilityLimit = 10_000
|
maxStateOfApplicabilityLimit = 10_000
|
||||||
maxControlsLimit = 10000
|
|
||||||
maxItemsLimit = 1000
|
|
||||||
presignExpiry = 15 * time.Minute
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
FrameworkService struct {
|
FrameworkService struct {
|
||||||
svc *TenantService
|
svc *TenantService
|
||||||
|
html2pdfConverter *html2pdf.Converter
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateFrameworkRequest struct {
|
CreateFrameworkRequest struct {
|
||||||
@@ -65,6 +68,207 @@ type (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (s FrameworkService) RequestExport(
|
||||||
|
ctx context.Context,
|
||||||
|
frameworkID gid.GID,
|
||||||
|
) error {
|
||||||
|
return s.svc.pg.WithTx(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()
|
||||||
|
|
||||||
|
frameworkExport := &coredata.FrameworkExport{
|
||||||
|
ID: gid.New(framework.ID.TenantID(), coredata.FrameworkExportEntityType),
|
||||||
|
FrameworkID: frameworkID,
|
||||||
|
Status: coredata.FrameworkExportStatusPending,
|
||||||
|
CreatedAt: now,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := frameworkExport.Insert(ctx, conn, s.svc.scope); err != nil {
|
||||||
|
return fmt.Errorf("cannot insert framework export: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s FrameworkService) Export(
|
||||||
|
ctx context.Context,
|
||||||
|
frameworkID gid.GID,
|
||||||
|
file io.Writer,
|
||||||
|
) error {
|
||||||
|
archive := zip.NewWriter(file)
|
||||||
|
defer archive.Close()
|
||||||
|
|
||||||
|
return s.svc.pg.WithTx(
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
controls := coredata.Controls{}
|
||||||
|
err := controls.LoadByFrameworkID(
|
||||||
|
ctx,
|
||||||
|
conn,
|
||||||
|
s.svc.scope,
|
||||||
|
frameworkID,
|
||||||
|
page.NewCursor(
|
||||||
|
10_000,
|
||||||
|
nil,
|
||||||
|
page.Head,
|
||||||
|
page.OrderBy[coredata.ControlOrderField]{
|
||||||
|
Field: coredata.ControlOrderFieldSectionTitle,
|
||||||
|
Direction: page.OrderDirectionAsc,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
coredata.NewControlFilter(nil),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot load controls: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, control := range controls {
|
||||||
|
_, err := archive.Create(fmt.Sprintf("%s/%s/", framework.Name, control.SectionTitle))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot create control directory in archive: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
measures := coredata.Measures{}
|
||||||
|
err = measures.LoadByControlID(
|
||||||
|
ctx,
|
||||||
|
conn,
|
||||||
|
s.svc.scope,
|
||||||
|
control.ID,
|
||||||
|
page.NewCursor(
|
||||||
|
10_000,
|
||||||
|
nil,
|
||||||
|
page.Head,
|
||||||
|
page.OrderBy[coredata.MeasureOrderField]{
|
||||||
|
Field: coredata.MeasureOrderFieldCreatedAt,
|
||||||
|
Direction: page.OrderDirectionAsc,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
coredata.NewMeasureFilter(nil),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot load measures: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, measure := range measures {
|
||||||
|
_, err := archive.Create(fmt.Sprintf("%s/%s/%s/", framework.Name, control.SectionTitle, measure.Name))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot create measure directory in archive: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
evidences := coredata.Evidences{}
|
||||||
|
err = evidences.LoadByMeasureID(
|
||||||
|
ctx,
|
||||||
|
conn,
|
||||||
|
s.svc.scope,
|
||||||
|
measure.ID,
|
||||||
|
page.NewCursor(
|
||||||
|
10_000,
|
||||||
|
nil,
|
||||||
|
page.Head,
|
||||||
|
page.OrderBy[coredata.EvidenceOrderField]{
|
||||||
|
Field: coredata.EvidenceOrderFieldCreatedAt,
|
||||||
|
Direction: page.OrderDirectionAsc,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot load evidences: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, evidence := range evidences {
|
||||||
|
object, 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: %w", err)
|
||||||
|
}
|
||||||
|
defer object.Body.Close()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot download evidence: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
w, err := archive.Create(fmt.Sprintf("%s/%s/%s/%s", framework.Name, control.SectionTitle, measure.Name, evidence.Filename))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot create evidence in archive: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = io.Copy(w, object.Body)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot write evidence to archive: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
documents := coredata.Documents{}
|
||||||
|
err = documents.LoadByControlID(
|
||||||
|
ctx,
|
||||||
|
conn,
|
||||||
|
s.svc.scope,
|
||||||
|
control.ID,
|
||||||
|
page.NewCursor(
|
||||||
|
10_000,
|
||||||
|
nil,
|
||||||
|
page.Head,
|
||||||
|
page.OrderBy[coredata.DocumentOrderField]{
|
||||||
|
Field: coredata.DocumentOrderFieldCreatedAt,
|
||||||
|
Direction: page.OrderDirectionAsc,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
coredata.NewDocumentFilter(nil),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot load documents: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, document := range documents {
|
||||||
|
documentVersion := &coredata.DocumentVersion{}
|
||||||
|
if err := documentVersion.LoadLatestPublishedVersion(ctx, conn, s.svc.scope, document.ID); err != nil {
|
||||||
|
return fmt.Errorf("cannot load document version: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
exportedPDF, err := exportDocumentPDF(
|
||||||
|
ctx,
|
||||||
|
s.html2pdfConverter,
|
||||||
|
conn,
|
||||||
|
s.svc.scope,
|
||||||
|
documentVersion.ID,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot export document PDF: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
w, err := archive.Create(fmt.Sprintf("%s/%s/%s.pdf", framework.Name, control.SectionTitle, document.Title))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot create document in archive: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = w.Write(exportedPDF)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot write document to archive: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
func (s FrameworkService) Create(
|
func (s FrameworkService) Create(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
req CreateFrameworkRequest,
|
req CreateFrameworkRequest,
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ package probo
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||||
@@ -27,7 +28,9 @@ import (
|
|||||||
"github.com/getprobo/probo/pkg/gid"
|
"github.com/getprobo/probo/pkg/gid"
|
||||||
"github.com/getprobo/probo/pkg/html2pdf"
|
"github.com/getprobo/probo/pkg/html2pdf"
|
||||||
"github.com/getprobo/probo/pkg/usrmgr"
|
"github.com/getprobo/probo/pkg/usrmgr"
|
||||||
|
"go.gearno.de/crypto/uuid"
|
||||||
"go.gearno.de/kit/pg"
|
"go.gearno.de/kit/pg"
|
||||||
|
"go.gearno.de/x/ref"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@@ -136,7 +139,10 @@ func (s *Service) WithTenant(tenantID gid.TenantID) *TenantService {
|
|||||||
agent: agents.NewAgent(nil, s.agentConfig),
|
agent: agents.NewAgent(nil, s.agentConfig),
|
||||||
}
|
}
|
||||||
|
|
||||||
tenantService.Frameworks = &FrameworkService{svc: tenantService}
|
tenantService.Frameworks = &FrameworkService{
|
||||||
|
svc: tenantService,
|
||||||
|
html2pdfConverter: s.html2pdfConverter,
|
||||||
|
}
|
||||||
tenantService.Measures = &MeasureService{svc: tenantService}
|
tenantService.Measures = &MeasureService{svc: tenantService}
|
||||||
tenantService.Tasks = &TaskService{svc: tenantService}
|
tenantService.Tasks = &TaskService{svc: tenantService}
|
||||||
tenantService.Evidences = &EvidenceService{
|
tenantService.Evidences = &EvidenceService{
|
||||||
@@ -184,3 +190,144 @@ func (s *Service) WithTenant(tenantID gid.TenantID) *TenantService {
|
|||||||
tenantService.ProcessingActivityRegistries = &ProcessingActivityRegistryService{svc: tenantService}
|
tenantService.ProcessingActivityRegistries = &ProcessingActivityRegistryService{svc: tenantService}
|
||||||
return tenantService
|
return tenantService
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Service) ExportFrameworkJob(ctx context.Context) error {
|
||||||
|
return s.pg.WithTx(
|
||||||
|
ctx,
|
||||||
|
func(tx pg.Conn) error {
|
||||||
|
fe := &coredata.FrameworkExport{}
|
||||||
|
if err := fe.LoadNextPendingForUpdateSkipLocked(ctx, tx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
scope := coredata.NewScope(fe.ID.TenantID())
|
||||||
|
framework := &coredata.Framework{}
|
||||||
|
if err := framework.LoadByID(ctx, tx, scope, fe.FrameworkID); err != nil {
|
||||||
|
fe.Status = coredata.FrameworkExportStatusFailed
|
||||||
|
fe.CompletedAt = ref.Ref(time.Now())
|
||||||
|
if err := fe.Update(ctx, tx, scope); err != nil {
|
||||||
|
return fmt.Errorf("cannot update framework export: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// s.logger.Error(ctx, "cannot load framework", "error", err)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
tenantService := s.WithTenant(fe.ID.TenantID())
|
||||||
|
|
||||||
|
tempDir := os.TempDir()
|
||||||
|
tempFile, err := os.CreateTemp(tempDir, "probo-framework-export-*.zip")
|
||||||
|
if err != nil {
|
||||||
|
fe.Status = coredata.FrameworkExportStatusFailed
|
||||||
|
fe.CompletedAt = ref.Ref(time.Now())
|
||||||
|
if err := fe.Update(ctx, tx, scope); err != nil {
|
||||||
|
return fmt.Errorf("cannot update framework export: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// s.logger.Error(ctx, "cannot create temp file", "error", err)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
defer tempFile.Close()
|
||||||
|
defer os.Remove(tempFile.Name())
|
||||||
|
|
||||||
|
err = tenantService.Frameworks.Export(ctx, fe.FrameworkID, tempFile)
|
||||||
|
if err != nil {
|
||||||
|
fe.Status = coredata.FrameworkExportStatusFailed
|
||||||
|
fe.CompletedAt = ref.Ref(time.Now())
|
||||||
|
if err := fe.Update(ctx, tx, scope); err != nil {
|
||||||
|
return fmt.Errorf("cannot update framework export: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// s.logger.Error(ctx, "cannot export framework", "error", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
uuid, err := uuid.NewV4()
|
||||||
|
if err != nil {
|
||||||
|
fe.Status = coredata.FrameworkExportStatusFailed
|
||||||
|
fe.CompletedAt = ref.Ref(time.Now())
|
||||||
|
if err := fe.Update(ctx, tx, scope); err != nil {
|
||||||
|
return fmt.Errorf("cannot update framework export: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// s.logger.Error(ctx, "cannot generate UUID", "error", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := tempFile.Seek(0, 0); err != nil {
|
||||||
|
fe.Status = coredata.FrameworkExportStatusFailed
|
||||||
|
fe.CompletedAt = ref.Ref(time.Now())
|
||||||
|
if err := fe.Update(ctx, tx, scope); err != nil {
|
||||||
|
return fmt.Errorf("cannot update framework export: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// s.logger.Error(ctx, "cannot seek temp file", "error", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
fileInfo, err := tempFile.Stat()
|
||||||
|
if err != nil {
|
||||||
|
fe.Status = coredata.FrameworkExportStatusFailed
|
||||||
|
fe.CompletedAt = ref.Ref(time.Now())
|
||||||
|
if err := fe.Update(ctx, tx, scope); err != nil {
|
||||||
|
return fmt.Errorf("cannot update framework export: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// s.logger.Error(ctx, "cannot get temp file info", "error", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = s.s3.PutObject(
|
||||||
|
ctx,
|
||||||
|
&s3.PutObjectInput{
|
||||||
|
Bucket: ref.Ref(s.bucket),
|
||||||
|
Key: ref.Ref(uuid.String()),
|
||||||
|
Body: tempFile,
|
||||||
|
ContentLength: ref.Ref(fileInfo.Size()),
|
||||||
|
ContentType: ref.Ref("application/zip"),
|
||||||
|
Metadata: map[string]string{
|
||||||
|
"framework-id": framework.ID.String(),
|
||||||
|
"framework-export-id": fe.ID.String(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
fe.Status = coredata.FrameworkExportStatusFailed
|
||||||
|
fe.CompletedAt = ref.Ref(time.Now())
|
||||||
|
if err := fe.Update(ctx, tx, scope); err != nil {
|
||||||
|
return fmt.Errorf("cannot update framework export: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// s.logger.Error(ctx, "cannot upload file to S3", "error", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
|
||||||
|
file := coredata.File{
|
||||||
|
ID: gid.New(fe.ID.TenantID(), coredata.FileEntityType),
|
||||||
|
BucketName: s.bucket,
|
||||||
|
MimeType: "application/zip",
|
||||||
|
FileName: fmt.Sprintf("%s Archive %s.zip", framework.Name, time.Now().Format("2006-01-02")),
|
||||||
|
FileKey: uuid.String(),
|
||||||
|
CreatedAt: now,
|
||||||
|
UpdatedAt: now,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := file.Insert(ctx, tx, scope); err != nil {
|
||||||
|
return fmt.Errorf("cannot insert file: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fe.FileID = &file.ID
|
||||||
|
fe.CompletedAt = &now
|
||||||
|
fe.Status = coredata.FrameworkExportStatusCompleted
|
||||||
|
if err := fe.Update(ctx, tx, scope); err != nil {
|
||||||
|
return fmt.Errorf("cannot update framework export: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
@@ -2265,6 +2265,7 @@ type Mutation {
|
|||||||
generateFrameworkStateOfApplicability(
|
generateFrameworkStateOfApplicability(
|
||||||
input: GenerateFrameworkStateOfApplicabilityInput!
|
input: GenerateFrameworkStateOfApplicabilityInput!
|
||||||
): GenerateFrameworkStateOfApplicabilityPayload!
|
): GenerateFrameworkStateOfApplicabilityPayload!
|
||||||
|
exportFramework(input: ExportFrameworkInput!): ExportFrameworkPayload!
|
||||||
|
|
||||||
# Control mutations
|
# Control mutations
|
||||||
createControl(input: CreateControlInput!): CreateControlPayload!
|
createControl(input: CreateControlInput!): CreateControlPayload!
|
||||||
@@ -2656,6 +2657,10 @@ input DeleteFrameworkInput {
|
|||||||
frameworkId: ID!
|
frameworkId: ID!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input ExportFrameworkInput {
|
||||||
|
frameworkId: ID!
|
||||||
|
}
|
||||||
|
|
||||||
input CreateMeasureInput {
|
input CreateMeasureInput {
|
||||||
organizationId: ID!
|
organizationId: ID!
|
||||||
name: String!
|
name: String!
|
||||||
@@ -3219,6 +3224,10 @@ type DeleteFrameworkPayload {
|
|||||||
deletedFrameworkId: ID!
|
deletedFrameworkId: ID!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ExportFrameworkPayload {
|
||||||
|
exportJobId: ID!
|
||||||
|
}
|
||||||
|
|
||||||
type CreateMeasurePayload {
|
type CreateMeasurePayload {
|
||||||
measureEdge: MeasureEdge!
|
measureEdge: MeasureEdge!
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -663,6 +663,10 @@ type ComplexityRoot struct {
|
|||||||
Data func(childComplexity int) int
|
Data func(childComplexity int) int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExportFrameworkPayload struct {
|
||||||
|
ExportJobID 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, filter *types.ControlFilter) int
|
Controls func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ControlOrderBy, filter *types.ControlFilter) int
|
||||||
CreatedAt func(childComplexity int) int
|
CreatedAt func(childComplexity int) int
|
||||||
@@ -801,6 +805,7 @@ type ComplexityRoot struct {
|
|||||||
DeleteVendorDataPrivacyAgreement func(childComplexity int, input types.DeleteVendorDataPrivacyAgreementInput) int
|
DeleteVendorDataPrivacyAgreement func(childComplexity int, input types.DeleteVendorDataPrivacyAgreementInput) int
|
||||||
DeleteVendorService func(childComplexity int, input types.DeleteVendorServiceInput) int
|
DeleteVendorService func(childComplexity int, input types.DeleteVendorServiceInput) int
|
||||||
ExportDocumentVersionPDF func(childComplexity int, input types.ExportDocumentVersionPDFInput) int
|
ExportDocumentVersionPDF func(childComplexity int, input types.ExportDocumentVersionPDFInput) int
|
||||||
|
ExportFramework func(childComplexity int, input types.ExportFrameworkInput) int
|
||||||
FulfillEvidence func(childComplexity int, input types.FulfillEvidenceInput) int
|
FulfillEvidence func(childComplexity int, input types.FulfillEvidenceInput) int
|
||||||
GenerateDocumentChangelog func(childComplexity int, input types.GenerateDocumentChangelogInput) int
|
GenerateDocumentChangelog func(childComplexity int, input types.GenerateDocumentChangelogInput) int
|
||||||
GenerateFrameworkStateOfApplicability func(childComplexity int, input types.GenerateFrameworkStateOfApplicabilityInput) int
|
GenerateFrameworkStateOfApplicability func(childComplexity int, input types.GenerateFrameworkStateOfApplicabilityInput) int
|
||||||
@@ -1570,6 +1575,7 @@ type MutationResolver interface {
|
|||||||
ImportFramework(ctx context.Context, input types.ImportFrameworkInput) (*types.ImportFrameworkPayload, error)
|
ImportFramework(ctx context.Context, input types.ImportFrameworkInput) (*types.ImportFrameworkPayload, error)
|
||||||
DeleteFramework(ctx context.Context, input types.DeleteFrameworkInput) (*types.DeleteFrameworkPayload, error)
|
DeleteFramework(ctx context.Context, input types.DeleteFrameworkInput) (*types.DeleteFrameworkPayload, error)
|
||||||
GenerateFrameworkStateOfApplicability(ctx context.Context, input types.GenerateFrameworkStateOfApplicabilityInput) (*types.GenerateFrameworkStateOfApplicabilityPayload, error)
|
GenerateFrameworkStateOfApplicability(ctx context.Context, input types.GenerateFrameworkStateOfApplicabilityInput) (*types.GenerateFrameworkStateOfApplicabilityPayload, error)
|
||||||
|
ExportFramework(ctx context.Context, input types.ExportFrameworkInput) (*types.ExportFrameworkPayload, error)
|
||||||
CreateControl(ctx context.Context, input types.CreateControlInput) (*types.CreateControlPayload, error)
|
CreateControl(ctx context.Context, input types.CreateControlInput) (*types.CreateControlPayload, error)
|
||||||
UpdateControl(ctx context.Context, input types.UpdateControlInput) (*types.UpdateControlPayload, error)
|
UpdateControl(ctx context.Context, input types.UpdateControlInput) (*types.UpdateControlPayload, error)
|
||||||
DeleteControl(ctx context.Context, input types.DeleteControlInput) (*types.DeleteControlPayload, error)
|
DeleteControl(ctx context.Context, input types.DeleteControlInput) (*types.DeleteControlPayload, error)
|
||||||
@@ -3681,6 +3687,13 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
|
|||||||
|
|
||||||
return e.complexity.ExportDocumentVersionPDFPayload.Data(childComplexity), true
|
return e.complexity.ExportDocumentVersionPDFPayload.Data(childComplexity), true
|
||||||
|
|
||||||
|
case "ExportFrameworkPayload.exportJobId":
|
||||||
|
if e.complexity.ExportFrameworkPayload.ExportJobID == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.complexity.ExportFrameworkPayload.ExportJobID(childComplexity), true
|
||||||
|
|
||||||
case "Framework.controls":
|
case "Framework.controls":
|
||||||
if e.complexity.Framework.Controls == nil {
|
if e.complexity.Framework.Controls == nil {
|
||||||
break
|
break
|
||||||
@@ -4748,6 +4761,18 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
|
|||||||
|
|
||||||
return e.complexity.Mutation.ExportDocumentVersionPDF(childComplexity, args["input"].(types.ExportDocumentVersionPDFInput)), true
|
return e.complexity.Mutation.ExportDocumentVersionPDF(childComplexity, args["input"].(types.ExportDocumentVersionPDFInput)), true
|
||||||
|
|
||||||
|
case "Mutation.exportFramework":
|
||||||
|
if e.complexity.Mutation.ExportFramework == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
args, err := ec.field_Mutation_exportFramework_args(ctx, rawArgs)
|
||||||
|
if err != nil {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.complexity.Mutation.ExportFramework(childComplexity, args["input"].(types.ExportFrameworkInput)), true
|
||||||
|
|
||||||
case "Mutation.fulfillEvidence":
|
case "Mutation.fulfillEvidence":
|
||||||
if e.complexity.Mutation.FulfillEvidence == nil {
|
if e.complexity.Mutation.FulfillEvidence == nil {
|
||||||
break
|
break
|
||||||
@@ -7806,6 +7831,7 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler {
|
|||||||
ec.unmarshalInputDocumentVersionSignatureOrder,
|
ec.unmarshalInputDocumentVersionSignatureOrder,
|
||||||
ec.unmarshalInputEvidenceOrder,
|
ec.unmarshalInputEvidenceOrder,
|
||||||
ec.unmarshalInputExportDocumentVersionPDFInput,
|
ec.unmarshalInputExportDocumentVersionPDFInput,
|
||||||
|
ec.unmarshalInputExportFrameworkInput,
|
||||||
ec.unmarshalInputFrameworkOrder,
|
ec.unmarshalInputFrameworkOrder,
|
||||||
ec.unmarshalInputFulfillEvidenceInput,
|
ec.unmarshalInputFulfillEvidenceInput,
|
||||||
ec.unmarshalInputGenerateDocumentChangelogInput,
|
ec.unmarshalInputGenerateDocumentChangelogInput,
|
||||||
@@ -10234,6 +10260,7 @@ type Mutation {
|
|||||||
generateFrameworkStateOfApplicability(
|
generateFrameworkStateOfApplicability(
|
||||||
input: GenerateFrameworkStateOfApplicabilityInput!
|
input: GenerateFrameworkStateOfApplicabilityInput!
|
||||||
): GenerateFrameworkStateOfApplicabilityPayload!
|
): GenerateFrameworkStateOfApplicabilityPayload!
|
||||||
|
exportFramework(input: ExportFrameworkInput!): ExportFrameworkPayload!
|
||||||
|
|
||||||
# Control mutations
|
# Control mutations
|
||||||
createControl(input: CreateControlInput!): CreateControlPayload!
|
createControl(input: CreateControlInput!): CreateControlPayload!
|
||||||
@@ -10625,6 +10652,10 @@ input DeleteFrameworkInput {
|
|||||||
frameworkId: ID!
|
frameworkId: ID!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input ExportFrameworkInput {
|
||||||
|
frameworkId: ID!
|
||||||
|
}
|
||||||
|
|
||||||
input CreateMeasureInput {
|
input CreateMeasureInput {
|
||||||
organizationId: ID!
|
organizationId: ID!
|
||||||
name: String!
|
name: String!
|
||||||
@@ -11188,6 +11219,10 @@ type DeleteFrameworkPayload {
|
|||||||
deletedFrameworkId: ID!
|
deletedFrameworkId: ID!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ExportFrameworkPayload {
|
||||||
|
exportJobId: ID!
|
||||||
|
}
|
||||||
|
|
||||||
type CreateMeasurePayload {
|
type CreateMeasurePayload {
|
||||||
measureEdge: MeasureEdge!
|
measureEdge: MeasureEdge!
|
||||||
}
|
}
|
||||||
@@ -14952,6 +14987,29 @@ func (ec *executionContext) field_Mutation_exportDocumentVersionPDF_argsInput(
|
|||||||
return zeroVal, nil
|
return zeroVal, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) field_Mutation_exportFramework_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
|
||||||
|
var err error
|
||||||
|
args := map[string]any{}
|
||||||
|
arg0, err := ec.field_Mutation_exportFramework_argsInput(ctx, rawArgs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
args["input"] = arg0
|
||||||
|
return args, nil
|
||||||
|
}
|
||||||
|
func (ec *executionContext) field_Mutation_exportFramework_argsInput(
|
||||||
|
ctx context.Context,
|
||||||
|
rawArgs map[string]any,
|
||||||
|
) (types.ExportFrameworkInput, error) {
|
||||||
|
ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("input"))
|
||||||
|
if tmp, ok := rawArgs["input"]; ok {
|
||||||
|
return ec.unmarshalNExportFrameworkInput2githubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐExportFrameworkInput(ctx, tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
var zeroVal types.ExportFrameworkInput
|
||||||
|
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{}
|
||||||
@@ -32208,6 +32266,50 @@ func (ec *executionContext) fieldContext_ExportDocumentVersionPDFPayload_data(_
|
|||||||
return fc, nil
|
return fc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) _ExportFrameworkPayload_exportJobId(ctx context.Context, field graphql.CollectedField, obj *types.ExportFrameworkPayload) (ret graphql.Marshaler) {
|
||||||
|
fc, err := ec.fieldContext_ExportFrameworkPayload_exportJobId(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.ExportJobID, 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.(gid.GID)
|
||||||
|
fc.Result = res
|
||||||
|
return ec.marshalNID2githubᚗcomᚋgetproboᚋproboᚋpkgᚋgidᚐGID(ctx, field.Selections, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) fieldContext_ExportFrameworkPayload_exportJobId(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||||
|
fc = &graphql.FieldContext{
|
||||||
|
Object: "ExportFrameworkPayload",
|
||||||
|
Field: field,
|
||||||
|
IsMethod: false,
|
||||||
|
IsResolver: false,
|
||||||
|
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||||
|
return nil, errors.New("field of type ID 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 {
|
||||||
@@ -35532,6 +35634,65 @@ func (ec *executionContext) fieldContext_Mutation_generateFrameworkStateOfApplic
|
|||||||
return fc, nil
|
return fc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) _Mutation_exportFramework(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||||
|
fc, err := ec.fieldContext_Mutation_exportFramework(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().ExportFramework(rctx, fc.Args["input"].(types.ExportFrameworkInput))
|
||||||
|
})
|
||||||
|
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.ExportFrameworkPayload)
|
||||||
|
fc.Result = res
|
||||||
|
return ec.marshalNExportFrameworkPayload2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐExportFrameworkPayload(ctx, field.Selections, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) fieldContext_Mutation_exportFramework(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 "exportJobId":
|
||||||
|
return ec.fieldContext_ExportFrameworkPayload_exportJobId(ctx, field)
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("no field named %q was found under type ExportFrameworkPayload", 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_exportFramework_args(ctx, field.ArgumentMap(ec.Variables)); err != nil {
|
||||||
|
ec.Error(ctx, err)
|
||||||
|
return fc, err
|
||||||
|
}
|
||||||
|
return fc, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) _Mutation_createControl(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
func (ec *executionContext) _Mutation_createControl(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||||
fc, err := ec.fieldContext_Mutation_createControl(ctx, field)
|
fc, err := ec.fieldContext_Mutation_createControl(ctx, field)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -63306,6 +63467,33 @@ func (ec *executionContext) unmarshalInputExportDocumentVersionPDFInput(ctx cont
|
|||||||
return it, nil
|
return it, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) unmarshalInputExportFrameworkInput(ctx context.Context, obj any) (types.ExportFrameworkInput, error) {
|
||||||
|
var it types.ExportFrameworkInput
|
||||||
|
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{}
|
||||||
@@ -72518,6 +72706,45 @@ func (ec *executionContext) _ExportDocumentVersionPDFPayload(ctx context.Context
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var exportFrameworkPayloadImplementors = []string{"ExportFrameworkPayload"}
|
||||||
|
|
||||||
|
func (ec *executionContext) _ExportFrameworkPayload(ctx context.Context, sel ast.SelectionSet, obj *types.ExportFrameworkPayload) graphql.Marshaler {
|
||||||
|
fields := graphql.CollectFields(ec.OperationContext, sel, exportFrameworkPayloadImplementors)
|
||||||
|
|
||||||
|
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("ExportFrameworkPayload")
|
||||||
|
case "exportJobId":
|
||||||
|
out.Values[i] = ec._ExportFrameworkPayload_exportJobId(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 {
|
||||||
@@ -73552,6 +73779,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 "exportFramework":
|
||||||
|
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
|
||||||
|
return ec._Mutation_exportFramework(ctx, field)
|
||||||
|
})
|
||||||
|
if out.Values[i] == graphql.Null {
|
||||||
|
out.Invalids++
|
||||||
|
}
|
||||||
case "createControl":
|
case "createControl":
|
||||||
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
|
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
|
||||||
return ec._Mutation_createControl(ctx, field)
|
return ec._Mutation_createControl(ctx, field)
|
||||||
@@ -83960,6 +84194,25 @@ func (ec *executionContext) marshalNExportDocumentVersionPDFPayload2ᚖgithubᚗ
|
|||||||
return ec._ExportDocumentVersionPDFPayload(ctx, sel, v)
|
return ec._ExportDocumentVersionPDFPayload(ctx, sel, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) unmarshalNExportFrameworkInput2githubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐExportFrameworkInput(ctx context.Context, v any) (types.ExportFrameworkInput, error) {
|
||||||
|
res, err := ec.unmarshalInputExportFrameworkInput(ctx, v)
|
||||||
|
return res, graphql.ErrorOnPath(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) marshalNExportFrameworkPayload2githubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐExportFrameworkPayload(ctx context.Context, sel ast.SelectionSet, v types.ExportFrameworkPayload) graphql.Marshaler {
|
||||||
|
return ec._ExportFrameworkPayload(ctx, sel, &v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) marshalNExportFrameworkPayload2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐExportFrameworkPayload(ctx context.Context, sel ast.SelectionSet, v *types.ExportFrameworkPayload) 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._ExportFrameworkPayload(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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1029,6 +1029,14 @@ type ExportDocumentVersionPDFPayload struct {
|
|||||||
Data string `json:"data"`
|
Data string `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ExportFrameworkInput struct {
|
||||||
|
FrameworkID gid.GID `json:"frameworkId"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ExportFrameworkPayload struct {
|
||||||
|
ExportJobID gid.GID `json:"exportJobId"`
|
||||||
|
}
|
||||||
|
|
||||||
type Framework struct {
|
type Framework struct {
|
||||||
ID gid.GID `json:"id"`
|
ID gid.GID `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
|||||||
@@ -1678,6 +1678,11 @@ func (r *mutationResolver) GenerateFrameworkStateOfApplicability(ctx context.Con
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExportFramework is the resolver for the exportFramework field.
|
||||||
|
func (r *mutationResolver) ExportFramework(ctx context.Context, input types.ExportFrameworkInput) (*types.ExportFrameworkPayload, error) {
|
||||||
|
panic(fmt.Errorf("not implemented: ExportFramework - exportFramework"))
|
||||||
|
}
|
||||||
|
|
||||||
// CreateControl is the resolver for the createControl field.
|
// CreateControl is the resolver for the createControl field.
|
||||||
func (r *mutationResolver) CreateControl(ctx context.Context, input types.CreateControlInput) (*types.CreateControlPayload, error) {
|
func (r *mutationResolver) CreateControl(ctx context.Context, input types.CreateControlInput) (*types.CreateControlPayload, error) {
|
||||||
prb := r.ProboService(ctx, input.FrameworkID.TenantID())
|
prb := r.ProboService(ctx, input.FrameworkID.TenantID())
|
||||||
@@ -3958,6 +3963,10 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error
|
|||||||
|
|
||||||
return types.NewVendor(vendor), nil
|
return types.NewVendor(vendor), nil
|
||||||
case coredata.FrameworkEntityType:
|
case coredata.FrameworkEntityType:
|
||||||
|
if err := prb.Frameworks.Export(ctx, id, nil); err != nil {
|
||||||
|
panic(fmt.Errorf("cannot export organization frameworks: %w", err))
|
||||||
|
}
|
||||||
|
|
||||||
framework, err := prb.Frameworks.Get(ctx, id)
|
framework, err := prb.Frameworks.Get(ctx, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Errorf("cannot get framework: %w", err))
|
panic(fmt.Errorf("cannot get framework: %w", err))
|
||||||
|
|||||||
Reference in New Issue
Block a user