@@ -19,6 +19,9 @@ omit_panic_handler: true
|
||||
call_argument_directives_with_null: true
|
||||
|
||||
models:
|
||||
ID:
|
||||
model:
|
||||
- "github.com/getprobo/probo/pkg/api/console/v1/types.GIDScalar"
|
||||
Datetime:
|
||||
model:
|
||||
- "github.com/99designs/gqlgen/graphql.Time"
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/99designs/gqlgen/graphql"
|
||||
"github.com/99designs/gqlgen/graphql/introspection"
|
||||
"github.com/getprobo/probo/pkg/api/console/v1/types"
|
||||
"github.com/getprobo/probo/pkg/probo/coredata/gid"
|
||||
"github.com/getprobo/probo/pkg/probo/coredata/page"
|
||||
gqlparser "github.com/vektah/gqlparser/v2"
|
||||
"github.com/vektah/gqlparser/v2/ast"
|
||||
@@ -104,7 +105,7 @@ type ComplexityRoot struct {
|
||||
}
|
||||
|
||||
Query struct {
|
||||
Node func(childComplexity int, id string) int
|
||||
Node func(childComplexity int, id gid.GID) int
|
||||
}
|
||||
|
||||
Task struct {
|
||||
@@ -135,7 +136,7 @@ type OrganizationResolver interface {
|
||||
Frameworks(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.FrameworkConnection, error)
|
||||
}
|
||||
type QueryResolver interface {
|
||||
Node(ctx context.Context, id string) (types.Node, error)
|
||||
Node(ctx context.Context, id gid.GID) (types.Node, error)
|
||||
}
|
||||
|
||||
type executableSchema struct {
|
||||
@@ -385,7 +386,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||
return 0, false
|
||||
}
|
||||
|
||||
return e.complexity.Query.Node(childComplexity, args["id"].(string)), true
|
||||
return e.complexity.Query.Node(childComplexity, args["id"].(gid.GID)), true
|
||||
|
||||
case "Task.createdAt":
|
||||
if e.complexity.Task.CreatedAt == nil {
|
||||
@@ -915,13 +916,13 @@ func (ec *executionContext) field_Query_node_args(ctx context.Context, rawArgs m
|
||||
func (ec *executionContext) field_Query_node_argsID(
|
||||
ctx context.Context,
|
||||
rawArgs map[string]any,
|
||||
) (string, error) {
|
||||
) (gid.GID, error) {
|
||||
ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("id"))
|
||||
if tmp, ok := rawArgs["id"]; ok {
|
||||
return ec.unmarshalNID2string(ctx, tmp)
|
||||
return ec.unmarshalNID2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚋgidᚐGID(ctx, tmp)
|
||||
}
|
||||
|
||||
var zeroVal string
|
||||
var zeroVal gid.GID
|
||||
return zeroVal, nil
|
||||
}
|
||||
|
||||
@@ -999,9 +1000,9 @@ func (ec *executionContext) _Control_id(ctx context.Context, field graphql.Colle
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(string)
|
||||
res := resTmp.(gid.GID)
|
||||
fc.Result = res
|
||||
return ec.marshalNID2string(ctx, field.Selections, res)
|
||||
return ec.marshalNID2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚋgidᚐGID(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_Control_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
@@ -1420,9 +1421,9 @@ func (ec *executionContext) _Framework_id(ctx context.Context, field graphql.Col
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(string)
|
||||
res := resTmp.(gid.GID)
|
||||
fc.Result = res
|
||||
return ec.marshalNID2string(ctx, field.Selections, res)
|
||||
return ec.marshalNID2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚋgidᚐGID(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_Framework_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
@@ -1841,9 +1842,9 @@ func (ec *executionContext) _Organization_id(ctx context.Context, field graphql.
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(string)
|
||||
res := resTmp.(gid.GID)
|
||||
fc.Result = res
|
||||
return ec.marshalNID2string(ctx, field.Selections, res)
|
||||
return ec.marshalNID2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚋgidᚐGID(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_Organization_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
@@ -2176,7 +2177,7 @@ func (ec *executionContext) _Query_node(ctx context.Context, field graphql.Colle
|
||||
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 ec.resolvers.Query().Node(rctx, fc.Args["id"].(string))
|
||||
return ec.resolvers.Query().Node(rctx, fc.Args["id"].(gid.GID))
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
@@ -2342,9 +2343,9 @@ func (ec *executionContext) _Task_id(ctx context.Context, field graphql.Collecte
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(string)
|
||||
res := resTmp.(gid.GID)
|
||||
fc.Result = res
|
||||
return ec.marshalNID2string(ctx, field.Selections, res)
|
||||
return ec.marshalNID2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚋgidᚐGID(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_Task_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
@@ -5461,13 +5462,13 @@ func (ec *executionContext) marshalNFrameworkEdge2ᚖgithubᚗcomᚋgetproboᚋp
|
||||
return ec._FrameworkEdge(ctx, sel, v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalNID2string(ctx context.Context, v any) (string, error) {
|
||||
res, err := graphql.UnmarshalID(v)
|
||||
func (ec *executionContext) unmarshalNID2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚋgidᚐGID(ctx context.Context, v any) (gid.GID, error) {
|
||||
res, err := types.UnmarshalGIDScalar(v)
|
||||
return res, graphql.ErrorOnPath(ctx, err)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNID2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {
|
||||
res := graphql.MarshalID(v)
|
||||
func (ec *executionContext) marshalNID2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚋgidᚐGID(ctx context.Context, sel ast.SelectionSet, v gid.GID) graphql.Marshaler {
|
||||
res := types.MarshalGIDScalar(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")
|
||||
|
||||
44
pkg/api/console/v1/types/gid.go
Normal file
44
pkg/api/console/v1/types/gid.go
Normal file
@@ -0,0 +1,44 @@
|
||||
// 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 types
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"strconv"
|
||||
|
||||
"github.com/99designs/gqlgen/graphql"
|
||||
"github.com/getprobo/probo/pkg/probo/coredata/gid"
|
||||
)
|
||||
|
||||
func MarshalGIDScalar(id gid.GID) graphql.Marshaler {
|
||||
return graphql.WriterFunc(func(w io.Writer) {
|
||||
w.Write([]byte(strconv.Quote(id.String())))
|
||||
})
|
||||
}
|
||||
|
||||
func UnmarshalGIDScalar(v interface{}) (gid.GID, error) {
|
||||
s, ok := v.(string)
|
||||
if !ok {
|
||||
return gid.Nil, errors.New("must be a string")
|
||||
}
|
||||
|
||||
id, err := gid.ParseGID(s)
|
||||
if err != nil {
|
||||
return gid.Nil, err
|
||||
}
|
||||
|
||||
return id, nil
|
||||
}
|
||||
@@ -5,16 +5,17 @@ package types
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/getprobo/probo/pkg/probo/coredata/gid"
|
||||
"github.com/getprobo/probo/pkg/probo/coredata/page"
|
||||
)
|
||||
|
||||
type Node interface {
|
||||
IsNode()
|
||||
GetID() string
|
||||
GetID() gid.GID
|
||||
}
|
||||
|
||||
type Control struct {
|
||||
ID string `json:"id"`
|
||||
ID gid.GID `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Tasks *TaskConnection `json:"tasks"`
|
||||
@@ -22,8 +23,8 @@ type Control struct {
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
}
|
||||
|
||||
func (Control) IsNode() {}
|
||||
func (this Control) GetID() string { return this.ID }
|
||||
func (Control) IsNode() {}
|
||||
func (this Control) GetID() gid.GID { return this.ID }
|
||||
|
||||
type ControlConnection struct {
|
||||
Edges []*ControlEdge `json:"edges"`
|
||||
@@ -36,7 +37,7 @@ type ControlEdge struct {
|
||||
}
|
||||
|
||||
type Framework struct {
|
||||
ID string `json:"id"`
|
||||
ID gid.GID `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Controls *ControlConnection `json:"controls"`
|
||||
@@ -44,8 +45,8 @@ type Framework struct {
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
}
|
||||
|
||||
func (Framework) IsNode() {}
|
||||
func (this Framework) GetID() string { return this.ID }
|
||||
func (Framework) IsNode() {}
|
||||
func (this Framework) GetID() gid.GID { return this.ID }
|
||||
|
||||
type FrameworkConnection struct {
|
||||
Edges []*FrameworkEdge `json:"edges"`
|
||||
@@ -58,15 +59,15 @@ type FrameworkEdge struct {
|
||||
}
|
||||
|
||||
type Organization struct {
|
||||
ID string `json:"id"`
|
||||
ID gid.GID `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Frameworks *FrameworkConnection `json:"frameworks"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
}
|
||||
|
||||
func (Organization) IsNode() {}
|
||||
func (this Organization) GetID() string { return this.ID }
|
||||
func (Organization) IsNode() {}
|
||||
func (this Organization) GetID() gid.GID { return this.ID }
|
||||
|
||||
type PageInfo struct {
|
||||
HasNextPage bool `json:"hasNextPage"`
|
||||
@@ -79,14 +80,14 @@ type Query struct {
|
||||
}
|
||||
|
||||
type Task struct {
|
||||
ID string `json:"id"`
|
||||
ID gid.GID `json:"id"`
|
||||
Name string `json:"name"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
}
|
||||
|
||||
func (Task) IsNode() {}
|
||||
func (this Task) GetID() string { return this.ID }
|
||||
func (Task) IsNode() {}
|
||||
func (this Task) GetID() gid.GID { return this.ID }
|
||||
|
||||
type TaskConnection struct {
|
||||
Edges []*TaskEdge `json:"edges"`
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
|
||||
"github.com/getprobo/probo/pkg/api/console/v1/schema"
|
||||
"github.com/getprobo/probo/pkg/api/console/v1/types"
|
||||
"github.com/getprobo/probo/pkg/probo/coredata/gid"
|
||||
"github.com/getprobo/probo/pkg/probo/coredata/page"
|
||||
)
|
||||
|
||||
@@ -50,7 +51,7 @@ func (r *organizationResolver) Frameworks(ctx context.Context, obj *types.Organi
|
||||
}
|
||||
|
||||
// Node is the resolver for the node field.
|
||||
func (r *queryResolver) Node(ctx context.Context, id string) (types.Node, error) {
|
||||
func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error) {
|
||||
panic(fmt.Errorf("not implemented: Node - node"))
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ func (c *Controls) LoadByFrameworkID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope *Scope,
|
||||
frameworkID string,
|
||||
frameworkID gid.GID,
|
||||
cursor *page.Cursor,
|
||||
) error {
|
||||
q := `
|
||||
|
||||
@@ -60,7 +60,7 @@ func (f *Frameworks) LoadByOrganizationID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope *Scope,
|
||||
organizationID string,
|
||||
organizationID gid.GID,
|
||||
cursor *page.Cursor,
|
||||
) error {
|
||||
q := `
|
||||
@@ -115,7 +115,7 @@ func (f *Framework) LoadByID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope *Scope,
|
||||
frameworkID string,
|
||||
frameworkID gid.GID,
|
||||
) error {
|
||||
q := `
|
||||
SELECT
|
||||
|
||||
@@ -27,15 +27,30 @@ type (
|
||||
GID uuid.UUID
|
||||
)
|
||||
|
||||
var (
|
||||
Nil = GID(uuid.Nil)
|
||||
)
|
||||
|
||||
func ParseGID(encoded string) (GID, error) {
|
||||
gid := GID{}
|
||||
|
||||
err := gid.UnmarshalText([]byte(encoded))
|
||||
if err != nil {
|
||||
return Nil, err
|
||||
}
|
||||
|
||||
return gid, nil
|
||||
}
|
||||
|
||||
func NewGID(et uint32) (GID, error) {
|
||||
id, err := uuid.NewV7()
|
||||
if err != nil {
|
||||
return GID(uuid.Nil), err
|
||||
return Nil, err
|
||||
}
|
||||
|
||||
binary.BigEndian.PutUint32(id[10:14], et)
|
||||
|
||||
return GID(id), nil
|
||||
return Nil, nil
|
||||
}
|
||||
|
||||
func (gid GID) Value() (driver.Value, error) {
|
||||
|
||||
@@ -47,7 +47,7 @@ func (o *Organization) LoadByID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope *Scope,
|
||||
organizationID string,
|
||||
organizationID gid.GID,
|
||||
) error {
|
||||
q := `
|
||||
SELECT
|
||||
|
||||
@@ -58,7 +58,7 @@ func (t *Tasks) LoadByControlID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope *Scope,
|
||||
controlID string,
|
||||
controlID gid.GID,
|
||||
cursor *page.Cursor,
|
||||
) error {
|
||||
q := `
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/getprobo/probo/pkg/probo/coredata"
|
||||
"github.com/getprobo/probo/pkg/probo/coredata/gid"
|
||||
"github.com/getprobo/probo/pkg/probo/coredata/page"
|
||||
"go.gearno.de/kit/pg"
|
||||
)
|
||||
@@ -38,7 +39,7 @@ func NewService(ctx context.Context, pgClient *pg.Client) *Service {
|
||||
|
||||
func (s *Service) GetOrganization(
|
||||
ctx context.Context,
|
||||
organizationID string,
|
||||
organizationID gid.GID,
|
||||
) (*coredata.Organization, error) {
|
||||
organization := &coredata.Organization{}
|
||||
|
||||
@@ -63,7 +64,7 @@ func (s *Service) GetOrganization(
|
||||
|
||||
func (s *Service) ListOrganizationFrameworks(
|
||||
ctx context.Context,
|
||||
organizationID string,
|
||||
organizationID gid.GID,
|
||||
cursor *page.Cursor,
|
||||
) (*page.Page[*coredata.Framework], error) {
|
||||
var frameworks coredata.Frameworks
|
||||
@@ -90,7 +91,7 @@ func (s *Service) ListOrganizationFrameworks(
|
||||
|
||||
func (s *Service) ListFrameworkControls(
|
||||
ctx context.Context,
|
||||
frameworkID string,
|
||||
frameworkID gid.GID,
|
||||
cursor *page.Cursor,
|
||||
) (*page.Page[*coredata.Control], error) {
|
||||
var controls coredata.Controls
|
||||
@@ -117,7 +118,7 @@ func (s *Service) ListFrameworkControls(
|
||||
|
||||
func (s *Service) ListControlTasks(
|
||||
ctx context.Context,
|
||||
controlID string,
|
||||
controlID gid.GID,
|
||||
cursor *page.Cursor,
|
||||
) (*page.Page[*coredata.Task], error) {
|
||||
var tasks coredata.Tasks
|
||||
|
||||
Reference in New Issue
Block a user