Move evidence to measure level
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
This commit is contained in:
@@ -29,7 +29,8 @@ import (
|
||||
type (
|
||||
Evidence struct {
|
||||
ID gid.GID `db:"id"`
|
||||
TaskID gid.GID `db:"task_id"`
|
||||
MeasureID gid.GID `db:"measure_id"`
|
||||
TaskID *gid.GID `db:"task_id"`
|
||||
State EvidenceState `db:"state"`
|
||||
ReferenceID string `db:"reference_id"`
|
||||
Type EvidenceType `db:"type"`
|
||||
@@ -65,6 +66,7 @@ INSERT INTO
|
||||
evidences (
|
||||
tenant_id,
|
||||
id,
|
||||
measure_id,
|
||||
task_id,
|
||||
reference_id,
|
||||
object_key,
|
||||
@@ -81,6 +83,7 @@ INSERT INTO
|
||||
VALUES (
|
||||
@tenant_id,
|
||||
@evidence_id,
|
||||
@measure_id,
|
||||
@task_id,
|
||||
@reference_id,
|
||||
@object_key,
|
||||
@@ -104,6 +107,7 @@ WHERE evidences.state = 'REQUESTED';
|
||||
args := pgx.StrictNamedArgs{
|
||||
"tenant_id": scope.GetTenantID(),
|
||||
"evidence_id": e.ID,
|
||||
"measure_id": e.MeasureID,
|
||||
"task_id": e.TaskID,
|
||||
"reference_id": e.ReferenceID,
|
||||
"object_key": e.ObjectKey,
|
||||
@@ -131,6 +135,7 @@ INSERT INTO
|
||||
evidences (
|
||||
tenant_id,
|
||||
id,
|
||||
measure_id,
|
||||
task_id,
|
||||
reference_id,
|
||||
object_key,
|
||||
@@ -147,6 +152,7 @@ INSERT INTO
|
||||
VALUES (
|
||||
@tenant_id,
|
||||
@evidence_id,
|
||||
@measure_id,
|
||||
@task_id,
|
||||
@reference_id,
|
||||
@object_key,
|
||||
@@ -165,6 +171,7 @@ VALUES (
|
||||
args := pgx.StrictNamedArgs{
|
||||
"tenant_id": scope.GetTenantID(),
|
||||
"evidence_id": e.ID,
|
||||
"measure_id": e.MeasureID,
|
||||
"task_id": e.TaskID,
|
||||
"reference_id": e.ReferenceID,
|
||||
"object_key": e.ObjectKey,
|
||||
@@ -192,6 +199,7 @@ func (e *Evidence) LoadByID(
|
||||
SELECT
|
||||
id,
|
||||
task_id,
|
||||
measure_id,
|
||||
reference_id,
|
||||
state,
|
||||
type,
|
||||
@@ -231,6 +239,58 @@ LIMIT 1;
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Evidences) LoadByMeasureID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
measureID gid.GID,
|
||||
cursor *page.Cursor[EvidenceOrderField],
|
||||
) error {
|
||||
q := `
|
||||
SELECT
|
||||
id,
|
||||
measure_id,
|
||||
task_id,
|
||||
reference_id,
|
||||
state,
|
||||
type,
|
||||
object_key,
|
||||
mime_type,
|
||||
size,
|
||||
filename,
|
||||
url,
|
||||
description,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
evidences
|
||||
WHERE
|
||||
%s
|
||||
AND measure_id = @measure_id
|
||||
AND %s
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment(), cursor.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{"measure_id": measureID}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
maps.Copy(args, cursor.SQLArguments())
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot query evidence: %w", err)
|
||||
}
|
||||
|
||||
evidences, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[Evidence])
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot collect evidence: %w", err)
|
||||
}
|
||||
|
||||
*e = evidences
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Evidences) LoadByTaskID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
@@ -241,6 +301,7 @@ func (e *Evidences) LoadByTaskID(
|
||||
q := `
|
||||
SELECT
|
||||
id,
|
||||
measure_id,
|
||||
task_id,
|
||||
reference_id,
|
||||
state,
|
||||
|
||||
9
pkg/coredata/migrations/20250503T142200Z.sql
Normal file
9
pkg/coredata/migrations/20250503T142200Z.sql
Normal file
@@ -0,0 +1,9 @@
|
||||
ALTER TABLE evidences ALTER COLUMN task_id DROP NOT NULL;
|
||||
ALTER TABLE evidences ADD COLUMN measure_id TEXT REFERENCES measures(id);
|
||||
|
||||
UPDATE evidences e
|
||||
SET measure_id = t.measure_id
|
||||
FROM tasks t
|
||||
WHERE e.task_id = t.id AND e.measure_id IS NULL;
|
||||
|
||||
ALTER TABLE evidences ALTER COLUMN measure_id SET NOT NULL;
|
||||
@@ -37,8 +37,16 @@ type (
|
||||
svc *TenantService
|
||||
}
|
||||
|
||||
File struct {
|
||||
Content io.Reader
|
||||
Filename string
|
||||
Size int64
|
||||
ContentType string
|
||||
}
|
||||
|
||||
RequestEvidenceRequest struct {
|
||||
TaskID gid.GID
|
||||
MeasureID *gid.GID
|
||||
TaskID *gid.GID
|
||||
Type coredata.EvidenceType
|
||||
Name string
|
||||
Description string
|
||||
@@ -51,13 +59,14 @@ type (
|
||||
Filename *string
|
||||
}
|
||||
|
||||
CreateEvidenceRequest struct {
|
||||
TaskID gid.GID
|
||||
Name string
|
||||
Type coredata.EvidenceType
|
||||
File io.Reader
|
||||
URL string
|
||||
Description string
|
||||
UploadTaskEvidenceRequest struct {
|
||||
TaskID gid.GID
|
||||
File File
|
||||
}
|
||||
|
||||
UploadMeasureEvidenceRequest struct {
|
||||
MeasureID gid.GID
|
||||
File File
|
||||
}
|
||||
)
|
||||
|
||||
@@ -90,7 +99,6 @@ func (s EvidenceService) Request(
|
||||
|
||||
evidence := &coredata.Evidence{
|
||||
ID: evidenceID,
|
||||
TaskID: req.TaskID,
|
||||
State: coredata.EvidenceStateRequested,
|
||||
Type: req.Type,
|
||||
Filename: req.Name,
|
||||
@@ -99,9 +107,23 @@ func (s EvidenceService) Request(
|
||||
UpdatedAt: now,
|
||||
}
|
||||
|
||||
err := s.svc.pg.WithConn(
|
||||
err := s.svc.pg.WithTx(
|
||||
ctx,
|
||||
func(conn pg.Conn) error {
|
||||
task := &coredata.Task{}
|
||||
if req.TaskID != nil {
|
||||
if err := task.LoadByID(ctx, conn, s.svc.scope, *req.TaskID); err != nil {
|
||||
return fmt.Errorf("cannot load task: %w", err)
|
||||
}
|
||||
|
||||
evidence.TaskID = req.TaskID
|
||||
evidence.MeasureID = task.MeasureID
|
||||
} else if req.MeasureID != nil {
|
||||
evidence.MeasureID = *req.MeasureID
|
||||
} else {
|
||||
return fmt.Errorf("measure id or task id is required")
|
||||
}
|
||||
|
||||
return evidence.Insert(ctx, conn, s.svc.scope)
|
||||
},
|
||||
)
|
||||
@@ -183,9 +205,9 @@ func (s EvidenceService) Fulfill(
|
||||
return evidence, nil
|
||||
}
|
||||
|
||||
func (s EvidenceService) Create(
|
||||
func (s EvidenceService) UploadTaskEvidence(
|
||||
ctx context.Context,
|
||||
req CreateEvidenceRequest,
|
||||
req UploadTaskEvidenceRequest,
|
||||
) (*coredata.Evidence, error) {
|
||||
now := time.Now()
|
||||
evidenceID := gid.New(s.svc.scope.GetTenantID(), coredata.EvidenceEntityType)
|
||||
@@ -197,66 +219,130 @@ func (s EvidenceService) Create(
|
||||
|
||||
evidence := &coredata.Evidence{
|
||||
ID: evidenceID,
|
||||
TaskID: req.TaskID,
|
||||
TaskID: &req.TaskID,
|
||||
State: coredata.EvidenceStateFulfilled,
|
||||
ReferenceID: "custom-evidence-" + referenceID.String(),
|
||||
Type: req.Type,
|
||||
Filename: req.Name,
|
||||
URL: req.URL,
|
||||
Description: req.Description,
|
||||
Type: coredata.EvidenceTypeFile,
|
||||
Filename: req.File.Filename,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
|
||||
if req.Type == coredata.EvidenceTypeFile {
|
||||
contentType := "application/octet-stream"
|
||||
if req.Name != "" {
|
||||
if detectedType := mime.TypeByExtension(filepath.Ext(req.Name)); detectedType != "" {
|
||||
contentType = detectedType
|
||||
}
|
||||
}
|
||||
|
||||
objectKey, err := uuid.NewV7()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot generate object key: %w", err)
|
||||
}
|
||||
|
||||
_, err = s.svc.s3.PutObject(ctx, &s3.PutObjectInput{
|
||||
Bucket: aws.String(s.svc.bucket),
|
||||
Key: aws.String(objectKey.String()),
|
||||
Body: req.File,
|
||||
ContentType: aws.String(contentType),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot upload file to S3: %w", err)
|
||||
}
|
||||
|
||||
headOutput, err := s.svc.s3.HeadObject(ctx, &s3.HeadObjectInput{
|
||||
Bucket: aws.String(s.svc.bucket),
|
||||
Key: aws.String(objectKey.String()),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot get object metadata: %w", err)
|
||||
}
|
||||
|
||||
evidence.ObjectKey = objectKey.String()
|
||||
evidence.MimeType = contentType
|
||||
evidence.Size = uint64(*headOutput.ContentLength)
|
||||
} else if req.Type == coredata.EvidenceTypeLink {
|
||||
evidence.MimeType = "text/uri-list"
|
||||
evidence.Size = uint64(len(req.URL))
|
||||
evidence.ObjectKey = ""
|
||||
// TODO validate content type
|
||||
if req.File.ContentType == "" {
|
||||
req.File.ContentType = "application/octet-stream"
|
||||
}
|
||||
|
||||
task := &coredata.Task{}
|
||||
objectKey, err := uuid.NewV7()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot generate object key: %w", err)
|
||||
}
|
||||
|
||||
_, err = s.svc.s3.PutObject(
|
||||
ctx,
|
||||
&s3.PutObjectInput{
|
||||
Bucket: aws.String(s.svc.bucket),
|
||||
Key: aws.String(objectKey.String()),
|
||||
Body: req.File.Content,
|
||||
ContentType: aws.String(req.File.ContentType),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot upload file to S3: %w", err)
|
||||
}
|
||||
|
||||
evidence.ObjectKey = objectKey.String()
|
||||
evidence.MimeType = req.File.ContentType
|
||||
evidence.Size = uint64(req.File.Size)
|
||||
|
||||
err = s.svc.pg.WithTx(
|
||||
ctx,
|
||||
func(conn pg.Conn) error {
|
||||
task := &coredata.Task{}
|
||||
|
||||
if err := task.LoadByID(ctx, conn, s.svc.scope, req.TaskID); err != nil {
|
||||
return fmt.Errorf("cannot load task %q: %w", req.TaskID, err)
|
||||
}
|
||||
|
||||
evidence.MeasureID = task.MeasureID
|
||||
|
||||
if err := evidence.Insert(ctx, conn, s.svc.scope); err != nil {
|
||||
return fmt.Errorf("cannot insert evidence: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
// TODO try do delete file from s3 if it's a file type
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return evidence, nil
|
||||
}
|
||||
|
||||
func (s EvidenceService) UploadMeasureEvidence(
|
||||
ctx context.Context,
|
||||
req UploadMeasureEvidenceRequest,
|
||||
) (*coredata.Evidence, error) {
|
||||
now := time.Now()
|
||||
evidenceID := gid.New(s.svc.scope.GetTenantID(), coredata.EvidenceEntityType)
|
||||
|
||||
referenceID, err := uuid.NewV4()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot generate reference id: %w", err)
|
||||
}
|
||||
|
||||
evidence := &coredata.Evidence{
|
||||
ID: evidenceID,
|
||||
MeasureID: req.MeasureID,
|
||||
State: coredata.EvidenceStateFulfilled,
|
||||
ReferenceID: "custom-evidence-" + referenceID.String(),
|
||||
Type: coredata.EvidenceTypeFile,
|
||||
Filename: req.File.Filename,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
|
||||
// TODO validate content type
|
||||
if req.File.ContentType == "" {
|
||||
req.File.ContentType = "application/octet-stream"
|
||||
}
|
||||
|
||||
objectKey, err := uuid.NewV7()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot generate object key: %w", err)
|
||||
}
|
||||
|
||||
_, err = s.svc.s3.PutObject(
|
||||
ctx,
|
||||
&s3.PutObjectInput{
|
||||
Bucket: aws.String(s.svc.bucket),
|
||||
Key: aws.String(objectKey.String()),
|
||||
Body: req.File.Content,
|
||||
ContentType: aws.String(req.File.ContentType),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot upload file to S3: %w", err)
|
||||
}
|
||||
|
||||
evidence.ObjectKey = objectKey.String()
|
||||
evidence.MimeType = req.File.ContentType
|
||||
evidence.Size = uint64(req.File.Size)
|
||||
|
||||
err = s.svc.pg.WithTx(
|
||||
ctx,
|
||||
func(conn pg.Conn) error {
|
||||
measure := &coredata.Measure{}
|
||||
|
||||
if err := measure.LoadByID(ctx, conn, s.svc.scope, req.MeasureID); err != nil {
|
||||
return fmt.Errorf("cannot load measure %q: %w", req.MeasureID, err)
|
||||
}
|
||||
|
||||
evidence.MeasureID = req.MeasureID
|
||||
|
||||
if err := evidence.Insert(ctx, conn, s.svc.scope); err != nil {
|
||||
return fmt.Errorf("cannot insert evidence: %w", err)
|
||||
}
|
||||
@@ -310,6 +396,33 @@ func (s EvidenceService) GenerateFileURL(
|
||||
return &presignedReq.URL, nil
|
||||
}
|
||||
|
||||
func (s EvidenceService) ListForMeasureID(
|
||||
ctx context.Context,
|
||||
measureID gid.GID,
|
||||
cursor *page.Cursor[coredata.EvidenceOrderField],
|
||||
) (*page.Page[*coredata.Evidence, coredata.EvidenceOrderField], error) {
|
||||
var evidences coredata.Evidences
|
||||
|
||||
err := s.svc.pg.WithConn(
|
||||
ctx,
|
||||
func(conn pg.Conn) error {
|
||||
return evidences.LoadByMeasureID(
|
||||
ctx,
|
||||
conn,
|
||||
s.svc.scope,
|
||||
measureID,
|
||||
cursor,
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return page.NewPage(evidences, cursor), nil
|
||||
}
|
||||
|
||||
func (s EvidenceService) ListForTaskID(
|
||||
ctx context.Context,
|
||||
taskID gid.GID,
|
||||
|
||||
@@ -188,7 +188,7 @@ func (s MeasureService) Import(
|
||||
evidence := &coredata.Evidence{
|
||||
State: coredata.EvidenceStateRequested,
|
||||
ID: evidenceID,
|
||||
TaskID: task.ID,
|
||||
TaskID: &task.ID,
|
||||
ReferenceID: req.Measures[i].Tasks[j].RequestedEvidences[k].ReferenceID,
|
||||
Type: req.Measures[i].Tasks[j].RequestedEvidences[k].Type,
|
||||
Description: req.Measures[i].Tasks[j].RequestedEvidences[k].Name,
|
||||
|
||||
@@ -596,6 +596,14 @@ type Measure implements Node {
|
||||
description: String!
|
||||
state: MeasureState!
|
||||
|
||||
evidences(
|
||||
first: Int
|
||||
after: CursorKey
|
||||
last: Int
|
||||
before: CursorKey
|
||||
orderBy: EvidenceOrder
|
||||
): EvidenceConnection! @goField(forceResolver: true)
|
||||
|
||||
tasks(
|
||||
first: Int
|
||||
after: CursorKey
|
||||
@@ -987,8 +995,9 @@ type Mutation {
|
||||
# Evidence mutations
|
||||
requestEvidence(input: RequestEvidenceInput!): RequestEvidencePayload!
|
||||
fulfillEvidence(input: FulfillEvidenceInput!): FulfillEvidencePayload!
|
||||
createEvidence(input: CreateEvidenceInput!): CreateEvidencePayload!
|
||||
deleteEvidence(input: DeleteEvidenceInput!): DeleteEvidencePayload!
|
||||
uploadTaskEvidence(input: UploadTaskEvidenceInput!): UploadTaskEvidencePayload!
|
||||
uploadMeasureEvidence(input: UploadMeasureEvidenceInput!): UploadMeasureEvidencePayload!
|
||||
|
||||
# Vendor Compliance Report mutations
|
||||
uploadVendorComplianceReport(
|
||||
@@ -1651,4 +1660,22 @@ input SendSigningNotificationsInput {
|
||||
|
||||
type SendSigningNotificationsPayload {
|
||||
success: Boolean!
|
||||
}
|
||||
}
|
||||
|
||||
type UploadTaskEvidencePayload {
|
||||
evidenceEdge: EvidenceEdge!
|
||||
}
|
||||
|
||||
type UploadMeasureEvidencePayload {
|
||||
evidenceEdge: EvidenceEdge!
|
||||
}
|
||||
|
||||
input UploadTaskEvidenceInput {
|
||||
taskId: ID!
|
||||
file: Upload!
|
||||
}
|
||||
|
||||
input UploadMeasureEvidenceInput {
|
||||
measureId: ID!
|
||||
file: Upload!
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -473,6 +473,7 @@ type Measure struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
State coredata.MeasureState `json:"state"`
|
||||
Evidences *EvidenceConnection `json:"evidences"`
|
||||
Tasks *TaskConnection `json:"tasks"`
|
||||
Risks *RiskConnection `json:"risks"`
|
||||
Controls *ControlConnection `json:"controls"`
|
||||
@@ -886,6 +887,24 @@ type UpdateVendorPayload struct {
|
||||
Vendor *Vendor `json:"vendor"`
|
||||
}
|
||||
|
||||
type UploadMeasureEvidenceInput struct {
|
||||
MeasureID gid.GID `json:"measureId"`
|
||||
File graphql.Upload `json:"file"`
|
||||
}
|
||||
|
||||
type UploadMeasureEvidencePayload struct {
|
||||
EvidenceEdge *EvidenceEdge `json:"evidenceEdge"`
|
||||
}
|
||||
|
||||
type UploadTaskEvidenceInput struct {
|
||||
TaskID gid.GID `json:"taskId"`
|
||||
File graphql.Upload `json:"file"`
|
||||
}
|
||||
|
||||
type UploadTaskEvidencePayload struct {
|
||||
EvidenceEdge *EvidenceEdge `json:"evidenceEdge"`
|
||||
}
|
||||
|
||||
type UploadVendorComplianceReportInput struct {
|
||||
VendorID gid.GID `json:"vendorId"`
|
||||
ReportDate time.Time `json:"reportDate"`
|
||||
|
||||
@@ -112,6 +112,31 @@ func (r *frameworkResolver) Controls(ctx context.Context, obj *types.Framework,
|
||||
return types.NewControlConnection(page), nil
|
||||
}
|
||||
|
||||
// Evidences is the resolver for the evidences field.
|
||||
func (r *measureResolver) Evidences(ctx context.Context, obj *types.Measure, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.EvidenceOrderBy) (*types.EvidenceConnection, error) {
|
||||
svc := GetTenantService(ctx, r.proboSvc, obj.ID.TenantID())
|
||||
|
||||
pageOrderBy := page.OrderBy[coredata.EvidenceOrderField]{
|
||||
Field: coredata.EvidenceOrderFieldCreatedAt,
|
||||
Direction: page.OrderDirectionDesc,
|
||||
}
|
||||
if orderBy != nil {
|
||||
pageOrderBy = page.OrderBy[coredata.EvidenceOrderField]{
|
||||
Field: orderBy.Field,
|
||||
Direction: orderBy.Direction,
|
||||
}
|
||||
}
|
||||
|
||||
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
|
||||
|
||||
page, err := svc.Evidences.ListForMeasureID(ctx, obj.ID, cursor)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot list measure evidences: %w", err)
|
||||
}
|
||||
|
||||
return types.NewEvidenceConnection(page), nil
|
||||
}
|
||||
|
||||
// Tasks is the resolver for the tasks field.
|
||||
func (r *measureResolver) Tasks(ctx context.Context, obj *types.Measure, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.TaskOrderBy) (*types.TaskConnection, error) {
|
||||
svc := GetTenantService(ctx, r.proboSvc, obj.ID.TenantID())
|
||||
@@ -875,7 +900,7 @@ func (r *mutationResolver) RequestEvidence(ctx context.Context, input types.Requ
|
||||
evidence, err := svc.Evidences.Request(
|
||||
ctx,
|
||||
probo.RequestEvidenceRequest{
|
||||
TaskID: input.TaskID,
|
||||
TaskID: &input.TaskID,
|
||||
Name: input.Name,
|
||||
Type: input.Type,
|
||||
Description: input.Description,
|
||||
@@ -917,39 +942,6 @@ func (r *mutationResolver) FulfillEvidence(ctx context.Context, input types.Fulf
|
||||
}, nil
|
||||
}
|
||||
|
||||
// CreateEvidence is the resolver for the createEvidence field.
|
||||
func (r *mutationResolver) CreateEvidence(ctx context.Context, input types.CreateEvidenceInput) (*types.CreateEvidencePayload, error) {
|
||||
svc := GetTenantService(ctx, r.proboSvc, input.TaskID.TenantID())
|
||||
|
||||
req := probo.CreateEvidenceRequest{
|
||||
TaskID: input.TaskID,
|
||||
Name: input.Name,
|
||||
Type: input.Type,
|
||||
Description: input.Description,
|
||||
}
|
||||
|
||||
if input.Type == coredata.EvidenceTypeFile {
|
||||
if input.File == nil {
|
||||
return nil, fmt.Errorf("file is required for FILE type evidence")
|
||||
}
|
||||
req.File = input.File.File
|
||||
} else if input.Type == coredata.EvidenceTypeLink {
|
||||
if input.URL == nil || *input.URL == "" {
|
||||
return nil, fmt.Errorf("URL is required for LINK type evidence")
|
||||
}
|
||||
req.URL = *input.URL
|
||||
}
|
||||
|
||||
evidence, err := svc.Evidences.Create(ctx, req)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("failed to create evidence: %w", err))
|
||||
}
|
||||
|
||||
return &types.CreateEvidencePayload{
|
||||
EvidenceEdge: types.NewEvidenceEdge(evidence, coredata.EvidenceOrderFieldCreatedAt),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// DeleteEvidence is the resolver for the deleteEvidence field.
|
||||
func (r *mutationResolver) DeleteEvidence(ctx context.Context, input types.DeleteEvidenceInput) (*types.DeleteEvidencePayload, error) {
|
||||
svc := GetTenantService(ctx, r.proboSvc, input.EvidenceID.TenantID())
|
||||
@@ -964,6 +956,56 @@ func (r *mutationResolver) DeleteEvidence(ctx context.Context, input types.Delet
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UploadTaskEvidence is the resolver for the uploadTaskEvidence field.
|
||||
func (r *mutationResolver) UploadTaskEvidence(ctx context.Context, input types.UploadTaskEvidenceInput) (*types.UploadTaskEvidencePayload, error) {
|
||||
svc := GetTenantService(ctx, r.proboSvc, input.TaskID.TenantID())
|
||||
|
||||
evidence, err := svc.Evidences.UploadTaskEvidence(
|
||||
ctx,
|
||||
probo.UploadTaskEvidenceRequest{
|
||||
TaskID: input.TaskID,
|
||||
File: probo.File{
|
||||
Content: input.File.File,
|
||||
Filename: input.File.Filename,
|
||||
Size: input.File.Size,
|
||||
ContentType: input.File.ContentType,
|
||||
},
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot upload task evidence: %w", err))
|
||||
}
|
||||
|
||||
return &types.UploadTaskEvidencePayload{
|
||||
EvidenceEdge: types.NewEvidenceEdge(evidence, coredata.EvidenceOrderFieldCreatedAt),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UploadMeasureEvidence is the resolver for the uploadMeasureEvidence field.
|
||||
func (r *mutationResolver) UploadMeasureEvidence(ctx context.Context, input types.UploadMeasureEvidenceInput) (*types.UploadMeasureEvidencePayload, error) {
|
||||
svc := GetTenantService(ctx, r.proboSvc, input.MeasureID.TenantID())
|
||||
|
||||
evidence, err := svc.Evidences.UploadMeasureEvidence(
|
||||
ctx,
|
||||
probo.UploadMeasureEvidenceRequest{
|
||||
MeasureID: input.MeasureID,
|
||||
File: probo.File{
|
||||
Content: input.File.File,
|
||||
Filename: input.File.Filename,
|
||||
Size: input.File.Size,
|
||||
ContentType: input.File.ContentType,
|
||||
},
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot upload measure evidence: %w", err))
|
||||
}
|
||||
|
||||
return &types.UploadMeasureEvidencePayload{
|
||||
EvidenceEdge: types.NewEvidenceEdge(evidence, coredata.EvidenceOrderFieldCreatedAt),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UploadVendorComplianceReport is the resolver for the uploadVendorComplianceReport field.
|
||||
func (r *mutationResolver) UploadVendorComplianceReport(ctx context.Context, input types.UploadVendorComplianceReportInput) (*types.UploadVendorComplianceReportPayload, error) {
|
||||
svc := GetTenantService(ctx, r.proboSvc, input.VendorID.TenantID())
|
||||
|
||||
Reference in New Issue
Block a user