diff --git a/pkg/server/api/trust/v1/schema/schema.go b/pkg/server/api/trust/v1/schema/schema.go index 6be74b2e4..a58b3de8a 100644 --- a/pkg/server/api/trust/v1/schema/schema.go +++ b/pkg/server/api/trust/v1/schema/schema.go @@ -135,6 +135,7 @@ type ComplexityRoot struct { } Query struct { + Node func(childComplexity int, id gid.GID) int TrustCenterBySlug func(childComplexity int, slug string) int } @@ -218,6 +219,7 @@ type OrganizationResolver interface { LogoURL(ctx context.Context, obj *types.Organization) (*string, error) } type QueryResolver interface { + Node(ctx context.Context, id gid.GID) (types.Node, error) TrustCenterBySlug(ctx context.Context, slug string) (*types.TrustCenter, error) } type TrustCenterResolver interface { @@ -518,6 +520,18 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin return e.complexity.PageInfo.StartCursor(childComplexity), true + case "Query.node": + if e.complexity.Query.Node == nil { + break + } + + args, err := ec.field_Query_node_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.Node(childComplexity, args["id"].(gid.GID)), true + case "Query.trustCenterBySlug": if e.complexity.Query.TrustCenterBySlug == nil { break @@ -1479,6 +1493,7 @@ type AcceptNonDisclosureAgreementPayload{ } type Query { + node(id: ID!): Node! trustCenterBySlug(slug: String!): TrustCenter @mustBeAuthenticated(role: NONE) } @@ -1650,6 +1665,29 @@ func (ec *executionContext) field_Query___type_argsName( return zeroVal, nil } +func (ec *executionContext) field_Query_node_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := ec.field_Query_node_argsID(ctx, rawArgs) + if err != nil { + return nil, err + } + args["id"] = arg0 + return args, nil +} +func (ec *executionContext) field_Query_node_argsID( + ctx context.Context, + rawArgs map[string]any, +) (gid.GID, error) { + ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + if tmp, ok := rawArgs["id"]; ok { + return ec.unmarshalNID2githubᚗcomᚋgetproboᚋproboᚋpkgᚋgidᚐGID(ctx, tmp) + } + + var zeroVal gid.GID + return zeroVal, nil +} + func (ec *executionContext) field_Query_trustCenterBySlug_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} @@ -3837,6 +3875,61 @@ func (ec *executionContext) fieldContext_PageInfo_endCursor(_ context.Context, f return fc, nil } +func (ec *executionContext) _Query_node(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_node(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.Query().Node(rctx, fc.Args["id"].(gid.GID)) + }) + 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.Node) + fc.Result = res + return ec.marshalNNode2githubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐNode(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_node(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("FieldContext.Child cannot be called on type INTERFACE") + }, + } + 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_Query_node_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + func (ec *executionContext) _Query_trustCenterBySlug(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_trustCenterBySlug(ctx, field) if err != nil { @@ -8783,6 +8876,28 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Query") + case "node": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_node(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) case "trustCenterBySlug": field := field @@ -11353,6 +11468,16 @@ func (ec *executionContext) marshalNID2githubᚗcomᚋgetproboᚋproboᚋpkgᚋg return res } +func (ec *executionContext) marshalNNode2githubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐNode(ctx context.Context, sel ast.SelectionSet, v types.Node) 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._Node(ctx, sel, v) +} + func (ec *executionContext) marshalNOrganization2githubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐOrganization(ctx context.Context, sel ast.SelectionSet, v types.Organization) graphql.Marshaler { return ec._Organization(ctx, sel, &v) } diff --git a/pkg/server/api/trust/v1/v1_resolver.go b/pkg/server/api/trust/v1/v1_resolver.go index d05878f38..63cfb3242 100644 --- a/pkg/server/api/trust/v1/v1_resolver.go +++ b/pkg/server/api/trust/v1/v1_resolver.go @@ -11,10 +11,12 @@ import ( "time" "github.com/getprobo/probo/pkg/coredata" + "github.com/getprobo/probo/pkg/gid" "github.com/getprobo/probo/pkg/page" "github.com/getprobo/probo/pkg/server/api/trust/v1/schema" "github.com/getprobo/probo/pkg/server/api/trust/v1/types" "github.com/getprobo/probo/pkg/trust" + "github.com/vektah/gqlparser/v2/gqlerror" ) // Framework is the resolver for the framework field. @@ -193,6 +195,72 @@ func (r *organizationResolver) LogoURL(ctx context.Context, obj *types.Organizat return publicTrustService.Organizations.GenerateLogoURL(ctx, obj.ID, 1*time.Hour) } +// Node is the resolver for the node field. +func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error) { + publicTrustService := r.PublicTrustService(ctx, id.TenantID()) + + switch id.EntityType() { + case coredata.OrganizationEntityType: + organization, err := publicTrustService.Organizations.Get(ctx, id) + if err != nil { + panic(fmt.Errorf("failed to get organization: %w", err)) + } + return types.NewOrganization(organization), nil + + case coredata.DocumentEntityType: + document, err := publicTrustService.Documents.Get(ctx, id) + if err != nil { + panic(fmt.Errorf("failed to get document: %w", err)) + } + return types.NewDocument(document), nil + + case coredata.FrameworkEntityType: + framework, err := publicTrustService.Frameworks.Get(ctx, id) + if err != nil { + panic(fmt.Errorf("failed to get framework: %w", err)) + } + return types.NewFramework(framework), nil + + case coredata.ReportEntityType: + report, err := publicTrustService.Reports.Get(ctx, id) + if err != nil { + panic(fmt.Errorf("failed to get report: %w", err)) + } + return types.NewReport(report), nil + + case coredata.AuditEntityType: + audit, err := publicTrustService.Audits.Get(ctx, id) + if err != nil { + panic(fmt.Errorf("failed to get audit: %w", err)) + } + return types.NewAudit(audit), nil + + case coredata.VendorEntityType: + vendor, err := publicTrustService.Vendors.Get(ctx, id) + if err != nil { + panic(fmt.Errorf("failed to get vendor: %w", err)) + } + return types.NewVendor(vendor), nil + + case coredata.TrustCenterEntityType: + trustCenter, file, err := publicTrustService.TrustCenters.Get(ctx, id) + if err != nil { + panic(fmt.Errorf("failed to get trust center: %w", err)) + } + return types.NewTrustCenter(trustCenter, file), nil + + case coredata.TrustCenterReferenceEntityType: + reference, err := publicTrustService.TrustCenterReferences.Get(ctx, id) + if err != nil { + panic(fmt.Errorf("failed to get trust center reference: %w", err)) + } + return types.NewTrustCenterReference(reference), nil + + default: + return nil, gqlerror.Errorf("node %q not found", id) + } +} + // TrustCenterBySlug is the resolver for the trustCenterBySlug field. func (r *queryResolver) TrustCenterBySlug(ctx context.Context, slug string) (*types.TrustCenter, error) { rootTrustService := r.RootTrustService(ctx) diff --git a/pkg/trust/document_service.go b/pkg/trust/document_service.go index c926021b2..bc9879998 100644 --- a/pkg/trust/document_service.go +++ b/pkg/trust/document_service.go @@ -171,3 +171,28 @@ func (s *DocumentService) ExportPDF( return watermarkedPDF, nil } + +func (s DocumentService) Get( + ctx context.Context, + documentID gid.GID, +) (*coredata.Document, error) { + document := &coredata.Document{} + + err := s.svc.pg.WithConn( + ctx, + func(conn pg.Conn) error { + err := document.LoadByID(ctx, conn, s.svc.scope, documentID) + if err != nil { + return fmt.Errorf("cannot load document: %w", err) + } + + return nil + }, + ) + + if err != nil { + return nil, err + } + + return document, nil +} diff --git a/pkg/trust/trust_center_reference_service.go b/pkg/trust/trust_center_reference_service.go index ace0c2ca6..90d55f80c 100644 --- a/pkg/trust/trust_center_reference_service.go +++ b/pkg/trust/trust_center_reference_service.go @@ -100,3 +100,28 @@ func (s TrustCenterReferenceService) GenerateLogoURL( return presignedReq.URL, nil } + +func (s TrustCenterReferenceService) Get( + ctx context.Context, + referenceID gid.GID, +) (*coredata.TrustCenterReference, error) { + reference := &coredata.TrustCenterReference{} + + err := s.svc.pg.WithConn( + ctx, + func(conn pg.Conn) error { + err := reference.LoadByID(ctx, conn, s.svc.scope, referenceID) + if err != nil { + return fmt.Errorf("cannot load trust center reference: %w", err) + } + + return nil + }, + ) + + if err != nil { + return nil, err + } + + return reference, nil +}