Add evidence type link

close #44

Signed-off-by: gearnode <bryan@frimin.fr>
This commit is contained in:
gearnode
2025-03-20 17:25:29 +01:00
parent 7117c6a210
commit b8bbeaba11
13 changed files with 798 additions and 167 deletions

View File

@@ -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 {

View File

@@ -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)) {

View File

@@ -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,
}
}

View File

@@ -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 {

View File

@@ -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)