Add evidence type link
close #44 Signed-off-by: gearnode <bryan@frimin.fr>
This commit is contained in:
@@ -28,15 +28,18 @@ import (
|
||||
|
||||
type (
|
||||
Evidence struct {
|
||||
ID gid.GID `db:"id"`
|
||||
TaskID gid.GID `db:"task_id"`
|
||||
State EvidenceState `db:"state"`
|
||||
ObjectKey string `db:"object_key"`
|
||||
MimeType string `db:"mime_type"`
|
||||
Size uint64 `db:"size"`
|
||||
Filename string `db:"filename"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
ID gid.GID `db:"id"`
|
||||
TaskID gid.GID `db:"task_id"`
|
||||
State EvidenceState `db:"state"`
|
||||
Type EvidenceType `db:"type"`
|
||||
ObjectKey string `db:"object_key"`
|
||||
MimeType string `db:"mime_type"`
|
||||
Size uint64 `db:"size"`
|
||||
Filename string `db:"filename"`
|
||||
URL string `db:"url"`
|
||||
Description string `db:"description"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
}
|
||||
|
||||
Evidences []*Evidence
|
||||
@@ -66,7 +69,10 @@ INSERT INTO
|
||||
mime_type,
|
||||
size,
|
||||
state,
|
||||
type,
|
||||
filename,
|
||||
url,
|
||||
description,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
@@ -78,7 +84,10 @@ VALUES (
|
||||
@mime_type,
|
||||
@size,
|
||||
@state,
|
||||
@type,
|
||||
@filename,
|
||||
@url,
|
||||
@description,
|
||||
@created_at,
|
||||
@updated_at
|
||||
)
|
||||
@@ -95,6 +104,9 @@ VALUES (
|
||||
"created_at": e.CreatedAt,
|
||||
"updated_at": e.UpdatedAt,
|
||||
"state": e.State,
|
||||
"type": e.Type,
|
||||
"url": e.URL,
|
||||
"description": e.Description,
|
||||
}
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
return err
|
||||
@@ -111,10 +123,13 @@ SELECT
|
||||
id,
|
||||
task_id,
|
||||
state,
|
||||
type,
|
||||
object_key,
|
||||
mime_type,
|
||||
size,
|
||||
filename,
|
||||
url,
|
||||
description,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
@@ -157,10 +172,13 @@ SELECT
|
||||
id,
|
||||
task_id,
|
||||
state,
|
||||
type,
|
||||
object_key,
|
||||
mime_type,
|
||||
size,
|
||||
filename,
|
||||
url,
|
||||
description,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
|
||||
74
pkg/coredata/evidence_type.go
Normal file
74
pkg/coredata/evidence_type.go
Normal file
@@ -0,0 +1,74 @@
|
||||
// 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 (
|
||||
EvidenceType uint8
|
||||
)
|
||||
|
||||
const (
|
||||
EvidenceTypeFile EvidenceType = iota
|
||||
EvidenceTypeLink
|
||||
)
|
||||
|
||||
func (et EvidenceType) MarshalText() ([]byte, error) {
|
||||
return []byte(et.String()), nil
|
||||
}
|
||||
|
||||
func (et *EvidenceType) UnmarshalText(data []byte) error {
|
||||
val := string(data)
|
||||
|
||||
switch val {
|
||||
case EvidenceTypeFile.String():
|
||||
*et = EvidenceTypeFile
|
||||
case EvidenceTypeLink.String():
|
||||
*et = EvidenceTypeLink
|
||||
default:
|
||||
return fmt.Errorf("invalid EvidenceType value: %q", val)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (et EvidenceType) String() string {
|
||||
var val string
|
||||
|
||||
switch et {
|
||||
case EvidenceTypeFile:
|
||||
val = "FILE"
|
||||
case EvidenceTypeLink:
|
||||
val = "LINK"
|
||||
}
|
||||
|
||||
return val
|
||||
}
|
||||
|
||||
func (et *EvidenceType) Scan(value any) error {
|
||||
val, ok := value.(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid scan source for EvidenceType, expected string got %T", value)
|
||||
}
|
||||
|
||||
return et.UnmarshalText([]byte(val))
|
||||
}
|
||||
|
||||
func (et EvidenceType) Value() (driver.Value, error) {
|
||||
return et.String(), nil
|
||||
}
|
||||
15
pkg/coredata/migrations/20250320T162619Z.sql
Normal file
15
pkg/coredata/migrations/20250320T162619Z.sql
Normal file
@@ -0,0 +1,15 @@
|
||||
-- Add evidence type enum
|
||||
CREATE TYPE evidence_type AS ENUM (
|
||||
'FILE',
|
||||
'LINK'
|
||||
);
|
||||
|
||||
ALTER TABLE evidences
|
||||
ADD COLUMN type evidence_type NOT NULL DEFAULT 'FILE',
|
||||
ADD COLUMN url TEXT NOT NULL DEFAULT '',
|
||||
ADD COLUMN description TEXT NOT NULL DEFAULT '';
|
||||
|
||||
ALTER TABLE evidences
|
||||
ALTER COLUMN type DROP DEFAULT,
|
||||
ALTER COLUMN url DROP DEFAULT,
|
||||
ALTER COLUMN description DROP DEFAULT;
|
||||
@@ -37,9 +37,12 @@ type (
|
||||
}
|
||||
|
||||
CreateEvidenceRequest struct {
|
||||
TaskID gid.GID
|
||||
Name string
|
||||
File io.Reader
|
||||
TaskID gid.GID
|
||||
Name string
|
||||
Type coredata.EvidenceType
|
||||
File io.Reader
|
||||
URL string
|
||||
Description string
|
||||
}
|
||||
)
|
||||
|
||||
@@ -73,50 +76,61 @@ func (s EvidenceService) Create(
|
||||
return nil, fmt.Errorf("cannot create evidence global id: %w", err)
|
||||
}
|
||||
|
||||
contentType := "application/octet-stream"
|
||||
if req.Name != "" {
|
||||
if detectedType := mime.TypeByExtension(filepath.Ext(req.Name)); detectedType != "" {
|
||||
contentType = detectedType
|
||||
evidence := &coredata.Evidence{
|
||||
ID: evidenceID,
|
||||
TaskID: req.TaskID,
|
||||
State: coredata.EvidenceStateValid,
|
||||
Type: req.Type,
|
||||
Filename: req.Name,
|
||||
URL: req.URL,
|
||||
Description: req.Description,
|
||||
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)
|
||||
}
|
||||
objectKey, err := uuid.NewV7()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot generate object key: %w", err)
|
||||
}
|
||||
|
||||
putObjectOutput, 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)
|
||||
}
|
||||
putObjectOutput, 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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
fmt.Println("putObjectOutput", putObjectOutput)
|
||||
fmt.Println("putObjectOutput", putObjectOutput)
|
||||
|
||||
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 = ""
|
||||
}
|
||||
|
||||
task := &coredata.Task{}
|
||||
evidence := &coredata.Evidence{
|
||||
ID: evidenceID,
|
||||
TaskID: req.TaskID,
|
||||
State: coredata.EvidenceStateValid,
|
||||
ObjectKey: objectKey.String(),
|
||||
MimeType: contentType,
|
||||
Size: uint64(*headOutput.ContentLength),
|
||||
Filename: req.Name,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
|
||||
err = s.svc.pg.WithTx(
|
||||
ctx,
|
||||
@@ -134,7 +148,7 @@ func (s EvidenceService) Create(
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
// TODO try do delete file from s3
|
||||
// TODO try do delete file from s3 if it's a file type
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -151,6 +165,10 @@ func (s EvidenceService) GenerateFileURL(
|
||||
return nil, fmt.Errorf("cannot get evidence: %w", err)
|
||||
}
|
||||
|
||||
if evidence.Type == coredata.EvidenceTypeLink {
|
||||
return nil, fmt.Errorf("cannot generate file URL for link type evidence")
|
||||
}
|
||||
|
||||
presignClient := s3.NewPresignClient(s.svc.s3)
|
||||
|
||||
presignedReq, err := presignClient.PresignGetObject(ctx, &s3.GetObjectInput{
|
||||
|
||||
@@ -411,13 +411,22 @@ type EvidenceEdge {
|
||||
node: Evidence!
|
||||
}
|
||||
|
||||
enum EvidenceType
|
||||
@goModel(model: "github.com/getprobo/probo/pkg/coredata.EvidenceType") {
|
||||
FILE @goEnum(value: "github.com/getprobo/probo/pkg/coredata.EvidenceTypeFile")
|
||||
LINK @goEnum(value: "github.com/getprobo/probo/pkg/coredata.EvidenceTypeLink")
|
||||
}
|
||||
|
||||
type Evidence implements Node {
|
||||
id: ID!
|
||||
fileUrl: String! @goField(forceResolver: true)
|
||||
fileUrl: String @goField(forceResolver: true)
|
||||
mimeType: String!
|
||||
size: Int!
|
||||
state: EvidenceState!
|
||||
type: EvidenceType!
|
||||
filename: String!
|
||||
url: String
|
||||
description: String!
|
||||
|
||||
createdAt: Datetime!
|
||||
updatedAt: Datetime!
|
||||
@@ -707,7 +716,10 @@ type UpdateControlPayload {
|
||||
input UploadEvidenceInput {
|
||||
taskId: ID!
|
||||
name: String!
|
||||
file: Upload!
|
||||
file: Upload
|
||||
type: EvidenceType!
|
||||
url: String
|
||||
description: String!
|
||||
}
|
||||
|
||||
type UploadEvidencePayload {
|
||||
|
||||
@@ -141,14 +141,17 @@ type ComplexityRoot struct {
|
||||
}
|
||||
|
||||
Evidence struct {
|
||||
CreatedAt func(childComplexity int) int
|
||||
FileURL func(childComplexity int) int
|
||||
Filename func(childComplexity int) int
|
||||
ID func(childComplexity int) int
|
||||
MimeType func(childComplexity int) int
|
||||
Size func(childComplexity int) int
|
||||
State func(childComplexity int) int
|
||||
UpdatedAt func(childComplexity int) int
|
||||
CreatedAt func(childComplexity int) int
|
||||
Description func(childComplexity int) int
|
||||
FileURL func(childComplexity int) int
|
||||
Filename func(childComplexity int) int
|
||||
ID func(childComplexity int) int
|
||||
MimeType func(childComplexity int) int
|
||||
Size func(childComplexity int) int
|
||||
State func(childComplexity int) int
|
||||
Type func(childComplexity int) int
|
||||
URL func(childComplexity int) int
|
||||
UpdatedAt func(childComplexity int) int
|
||||
}
|
||||
|
||||
EvidenceConnection struct {
|
||||
@@ -420,7 +423,7 @@ type ControlResolver interface {
|
||||
Tasks(ctx context.Context, obj *types.Control, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.TaskOrderBy) (*types.TaskConnection, error)
|
||||
}
|
||||
type EvidenceResolver interface {
|
||||
FileURL(ctx context.Context, obj *types.Evidence) (string, error)
|
||||
FileURL(ctx context.Context, obj *types.Evidence) (*string, error)
|
||||
}
|
||||
type FrameworkResolver interface {
|
||||
Controls(ctx context.Context, obj *types.Framework, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ControlOrderBy) (*types.ControlConnection, error)
|
||||
@@ -711,6 +714,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||
|
||||
return e.complexity.Evidence.CreatedAt(childComplexity), true
|
||||
|
||||
case "Evidence.description":
|
||||
if e.complexity.Evidence.Description == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.Evidence.Description(childComplexity), true
|
||||
|
||||
case "Evidence.fileUrl":
|
||||
if e.complexity.Evidence.FileURL == nil {
|
||||
break
|
||||
@@ -753,6 +763,20 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||
|
||||
return e.complexity.Evidence.State(childComplexity), true
|
||||
|
||||
case "Evidence.type":
|
||||
if e.complexity.Evidence.Type == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.Evidence.Type(childComplexity), true
|
||||
|
||||
case "Evidence.url":
|
||||
if e.complexity.Evidence.URL == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.Evidence.URL(childComplexity), true
|
||||
|
||||
case "Evidence.updatedAt":
|
||||
if e.complexity.Evidence.UpdatedAt == nil {
|
||||
break
|
||||
@@ -2502,13 +2526,22 @@ type EvidenceEdge {
|
||||
node: Evidence!
|
||||
}
|
||||
|
||||
enum EvidenceType
|
||||
@goModel(model: "github.com/getprobo/probo/pkg/coredata.EvidenceType") {
|
||||
FILE @goEnum(value: "github.com/getprobo/probo/pkg/coredata.EvidenceTypeFile")
|
||||
LINK @goEnum(value: "github.com/getprobo/probo/pkg/coredata.EvidenceTypeLink")
|
||||
}
|
||||
|
||||
type Evidence implements Node {
|
||||
id: ID!
|
||||
fileUrl: String! @goField(forceResolver: true)
|
||||
fileUrl: String @goField(forceResolver: true)
|
||||
mimeType: String!
|
||||
size: Int!
|
||||
state: EvidenceState!
|
||||
type: EvidenceType!
|
||||
filename: String!
|
||||
url: String
|
||||
description: String!
|
||||
|
||||
createdAt: Datetime!
|
||||
updatedAt: Datetime!
|
||||
@@ -2798,7 +2831,10 @@ type UpdateControlPayload {
|
||||
input UploadEvidenceInput {
|
||||
taskId: ID!
|
||||
name: String!
|
||||
file: Upload!
|
||||
file: Upload
|
||||
type: EvidenceType!
|
||||
url: String
|
||||
description: String!
|
||||
}
|
||||
|
||||
type UploadEvidencePayload {
|
||||
@@ -5868,14 +5904,11 @@ func (ec *executionContext) _Evidence_fileUrl(ctx context.Context, field graphql
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
if !graphql.HasFieldError(ctx, fc) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(string)
|
||||
res := resTmp.(*string)
|
||||
fc.Result = res
|
||||
return ec.marshalNString2string(ctx, field.Selections, res)
|
||||
return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_Evidence_fileUrl(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
@@ -6005,6 +6038,44 @@ func (ec *executionContext) fieldContext_Evidence_state(_ context.Context, field
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Evidence_type(ctx context.Context, field graphql.CollectedField, obj *types.Evidence) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_Evidence_type(ctx, field)
|
||||
if err != nil {
|
||||
return graphql.Null
|
||||
}
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.Type, 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.(coredata.EvidenceType)
|
||||
fc.Result = res
|
||||
return ec.marshalNEvidenceType2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐEvidenceType(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_Evidence_type(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "Evidence",
|
||||
Field: field,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
return nil, errors.New("field of type EvidenceType does not have child fields")
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Evidence_filename(ctx context.Context, field graphql.CollectedField, obj *types.Evidence) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_Evidence_filename(ctx, field)
|
||||
if err != nil {
|
||||
@@ -6043,6 +6114,79 @@ func (ec *executionContext) fieldContext_Evidence_filename(_ context.Context, fi
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Evidence_url(ctx context.Context, field graphql.CollectedField, obj *types.Evidence) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_Evidence_url(ctx, field)
|
||||
if err != nil {
|
||||
return graphql.Null
|
||||
}
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.URL, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*string)
|
||||
fc.Result = res
|
||||
return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_Evidence_url(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "Evidence",
|
||||
Field: field,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
return nil, errors.New("field of type String does not have child fields")
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Evidence_description(ctx context.Context, field graphql.CollectedField, obj *types.Evidence) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_Evidence_description(ctx, field)
|
||||
if err != nil {
|
||||
return graphql.Null
|
||||
}
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.Description, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
if !graphql.HasFieldError(ctx, fc) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(string)
|
||||
fc.Result = res
|
||||
return ec.marshalNString2string(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_Evidence_description(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "Evidence",
|
||||
Field: field,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
return nil, errors.New("field of type String does not have child fields")
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Evidence_createdAt(ctx context.Context, field graphql.CollectedField, obj *types.Evidence) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_Evidence_createdAt(ctx, field)
|
||||
if err != nil {
|
||||
@@ -6292,8 +6436,14 @@ func (ec *executionContext) fieldContext_EvidenceEdge_node(_ context.Context, fi
|
||||
return ec.fieldContext_Evidence_size(ctx, field)
|
||||
case "state":
|
||||
return ec.fieldContext_Evidence_state(ctx, field)
|
||||
case "type":
|
||||
return ec.fieldContext_Evidence_type(ctx, field)
|
||||
case "filename":
|
||||
return ec.fieldContext_Evidence_filename(ctx, field)
|
||||
case "url":
|
||||
return ec.fieldContext_Evidence_url(ctx, field)
|
||||
case "description":
|
||||
return ec.fieldContext_Evidence_description(ctx, field)
|
||||
case "createdAt":
|
||||
return ec.fieldContext_Evidence_createdAt(ctx, field)
|
||||
case "updatedAt":
|
||||
@@ -15668,7 +15818,7 @@ func (ec *executionContext) unmarshalInputUploadEvidenceInput(ctx context.Contex
|
||||
asMap[k] = v
|
||||
}
|
||||
|
||||
fieldsInOrder := [...]string{"taskId", "name", "file"}
|
||||
fieldsInOrder := [...]string{"taskId", "name", "file", "type", "url", "description"}
|
||||
for _, k := range fieldsInOrder {
|
||||
v, ok := asMap[k]
|
||||
if !ok {
|
||||
@@ -15691,11 +15841,32 @@ func (ec *executionContext) unmarshalInputUploadEvidenceInput(ctx context.Contex
|
||||
it.Name = data
|
||||
case "file":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("file"))
|
||||
data, err := ec.unmarshalNUpload2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚐUpload(ctx, v)
|
||||
data, err := ec.unmarshalOUpload2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚐUpload(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
it.File = data
|
||||
case "type":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("type"))
|
||||
data, err := ec.unmarshalNEvidenceType2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐEvidenceType(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
it.Type = data
|
||||
case "url":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("url"))
|
||||
data, err := ec.unmarshalOString2ᚖstring(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
it.URL = data
|
||||
case "description":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("description"))
|
||||
data, err := ec.unmarshalNString2string(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
it.Description = data
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16652,11 +16823,8 @@ func (ec *executionContext) _Evidence(ctx context.Context, sel ast.SelectionSet,
|
||||
case "fileUrl":
|
||||
field := field
|
||||
|
||||
innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) {
|
||||
innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) {
|
||||
res = ec._Evidence_fileUrl(ctx, field, obj)
|
||||
if res == graphql.Null {
|
||||
atomic.AddUint32(&fs.Invalids, 1)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
@@ -16695,11 +16863,23 @@ func (ec *executionContext) _Evidence(ctx context.Context, sel ast.SelectionSet,
|
||||
if out.Values[i] == graphql.Null {
|
||||
atomic.AddUint32(&out.Invalids, 1)
|
||||
}
|
||||
case "type":
|
||||
out.Values[i] = ec._Evidence_type(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
atomic.AddUint32(&out.Invalids, 1)
|
||||
}
|
||||
case "filename":
|
||||
out.Values[i] = ec._Evidence_filename(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
atomic.AddUint32(&out.Invalids, 1)
|
||||
}
|
||||
case "url":
|
||||
out.Values[i] = ec._Evidence_url(ctx, field, obj)
|
||||
case "description":
|
||||
out.Values[i] = ec._Evidence_description(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
atomic.AddUint32(&out.Invalids, 1)
|
||||
}
|
||||
case "createdAt":
|
||||
out.Values[i] = ec._Evidence_createdAt(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
@@ -20101,6 +20281,33 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
func (ec *executionContext) unmarshalNEvidenceType2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐEvidenceType(ctx context.Context, v any) (coredata.EvidenceType, error) {
|
||||
tmp, err := graphql.UnmarshalString(v)
|
||||
res := unmarshalNEvidenceType2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐEvidenceType[tmp]
|
||||
return res, graphql.ErrorOnPath(ctx, err)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNEvidenceType2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐEvidenceType(ctx context.Context, sel ast.SelectionSet, v coredata.EvidenceType) graphql.Marshaler {
|
||||
res := graphql.MarshalString(marshalNEvidenceType2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐEvidenceType[v])
|
||||
if res == graphql.Null {
|
||||
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
||||
ec.Errorf(ctx, "the requested element is null which the schema does not allow")
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
var (
|
||||
unmarshalNEvidenceType2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐEvidenceType = map[string]coredata.EvidenceType{
|
||||
"FILE": coredata.EvidenceTypeFile,
|
||||
"LINK": coredata.EvidenceTypeLink,
|
||||
}
|
||||
marshalNEvidenceType2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐEvidenceType = map[coredata.EvidenceType]string{
|
||||
coredata.EvidenceTypeFile: "FILE",
|
||||
coredata.EvidenceTypeLink: "LINK",
|
||||
}
|
||||
)
|
||||
|
||||
func (ec *executionContext) marshalNFramework2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐFramework(ctx context.Context, sel ast.SelectionSet, v *types.Framework) graphql.Marshaler {
|
||||
if v == nil {
|
||||
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
||||
|
||||
@@ -44,14 +44,25 @@ func NewEvidenceEdge(e *coredata.Evidence, orderBy coredata.EvidenceOrderField)
|
||||
}
|
||||
|
||||
func NewEvidence(e *coredata.Evidence) *Evidence {
|
||||
var fileURL *string = nil
|
||||
|
||||
var urlPtr *string = nil
|
||||
if e.URL != "" {
|
||||
urlCopy := e.URL
|
||||
urlPtr = &urlCopy
|
||||
}
|
||||
|
||||
return &Evidence{
|
||||
ID: e.ID,
|
||||
State: e.State,
|
||||
FileURL: "",
|
||||
Filename: e.Filename,
|
||||
MimeType: e.MimeType,
|
||||
Size: int(e.Size),
|
||||
CreatedAt: e.CreatedAt,
|
||||
UpdatedAt: e.UpdatedAt,
|
||||
ID: e.ID,
|
||||
State: e.State,
|
||||
Type: e.Type,
|
||||
FileURL: fileURL,
|
||||
Filename: e.Filename,
|
||||
MimeType: e.MimeType,
|
||||
Size: int(e.Size),
|
||||
URL: urlPtr,
|
||||
Description: e.Description,
|
||||
CreatedAt: e.CreatedAt,
|
||||
UpdatedAt: e.UpdatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,14 +195,17 @@ type DeleteVendorPayload struct {
|
||||
}
|
||||
|
||||
type Evidence struct {
|
||||
ID gid.GID `json:"id"`
|
||||
FileURL string `json:"fileUrl"`
|
||||
MimeType string `json:"mimeType"`
|
||||
Size int `json:"size"`
|
||||
State coredata.EvidenceState `json:"state"`
|
||||
Filename string `json:"filename"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
ID gid.GID `json:"id"`
|
||||
FileURL *string `json:"fileUrl,omitempty"`
|
||||
MimeType string `json:"mimeType"`
|
||||
Size int `json:"size"`
|
||||
State coredata.EvidenceState `json:"state"`
|
||||
Type coredata.EvidenceType `json:"type"`
|
||||
Filename string `json:"filename"`
|
||||
URL *string `json:"url,omitempty"`
|
||||
Description string `json:"description"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
}
|
||||
|
||||
func (Evidence) IsNode() {}
|
||||
@@ -495,9 +498,12 @@ type UpdateVendorPayload struct {
|
||||
}
|
||||
|
||||
type UploadEvidenceInput struct {
|
||||
TaskID gid.GID `json:"taskId"`
|
||||
Name string `json:"name"`
|
||||
File graphql.Upload `json:"file"`
|
||||
TaskID gid.GID `json:"taskId"`
|
||||
Name string `json:"name"`
|
||||
File *graphql.Upload `json:"file,omitempty"`
|
||||
Type coredata.EvidenceType `json:"type"`
|
||||
URL *string `json:"url,omitempty"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
type UploadEvidencePayload struct {
|
||||
|
||||
@@ -45,15 +45,20 @@ func (r *controlResolver) Tasks(ctx context.Context, obj *types.Control, first *
|
||||
}
|
||||
|
||||
// FileURL is the resolver for the fileUrl field.
|
||||
func (r *evidenceResolver) FileURL(ctx context.Context, obj *types.Evidence) (string, error) {
|
||||
func (r *evidenceResolver) FileURL(ctx context.Context, obj *types.Evidence) (*string, error) {
|
||||
svc := r.GetTenantServiceIfAuthorized(ctx, obj.ID.TenantID())
|
||||
|
||||
if obj.Type == coredata.EvidenceTypeLink {
|
||||
return obj.URL, nil
|
||||
}
|
||||
|
||||
fileURL, err := svc.Evidences.GenerateFileURL(ctx, obj.ID, 15*time.Minute)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("cannot generate file URL: %w", err)
|
||||
return nil, fmt.Errorf("cannot generate file URL: %w", err)
|
||||
}
|
||||
|
||||
return *fileURL, nil
|
||||
result := *fileURL
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// Controls is the resolver for the controls field.
|
||||
@@ -436,10 +441,28 @@ func (r *mutationResolver) UpdateControl(ctx context.Context, input types.Update
|
||||
func (r *mutationResolver) UploadEvidence(ctx context.Context, input types.UploadEvidenceInput) (*types.UploadEvidencePayload, error) {
|
||||
svc := r.GetTenantServiceIfAuthorized(ctx, input.TaskID.TenantID())
|
||||
|
||||
var url string
|
||||
if input.URL != nil {
|
||||
url = *input.URL
|
||||
}
|
||||
|
||||
req := probo.CreateEvidenceRequest{
|
||||
TaskID: input.TaskID,
|
||||
Name: input.Name,
|
||||
File: input.File.File,
|
||||
TaskID: input.TaskID,
|
||||
Name: input.Name,
|
||||
Type: input.Type,
|
||||
URL: url,
|
||||
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")
|
||||
}
|
||||
}
|
||||
|
||||
evidence, err := svc.Evidences.Create(ctx, req)
|
||||
|
||||
Reference in New Issue
Block a user