Add controls crud

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
Sacha Al Himdani
2025-06-05 15:25:37 -07:00
parent c1c19ba9f2
commit 4b34157ba3
37 changed files with 2988 additions and 715 deletions

View File

@@ -169,6 +169,10 @@ enum ControlOrderField
@goEnum(
value: "github.com/getprobo/probo/pkg/coredata.ControlOrderFieldCreatedAt"
)
SECTION_TITLE
@goEnum(
value: "github.com/getprobo/probo/pkg/coredata.ControlOrderFieldSectionTitle"
)
}
enum MeasureOrderField
@@ -683,7 +687,7 @@ type Framework implements Node {
type Control implements Node {
id: ID!
referenceId: String!
sectionTitle: String!
name: String!
description: String!
@@ -1087,6 +1091,11 @@ type Mutation {
importFramework(input: ImportFrameworkInput!): ImportFrameworkPayload!
deleteFramework(input: DeleteFrameworkInput!): DeleteFrameworkPayload!
# Control mutations
createControl(input: CreateControlInput!): CreateControlPayload!
updateControl(input: UpdateControlInput!): UpdateControlPayload!
deleteControl(input: DeleteControlInput!): DeleteControlPayload!
# Measure mutations
createMeasure(input: CreateMeasureInput!): CreateMeasurePayload!
updateMeasure(input: UpdateMeasureInput!): UpdateMeasurePayload!
@@ -1502,6 +1511,24 @@ input RemoveUserInput {
userId: ID!
}
input CreateControlInput {
frameworkId: ID!
sectionTitle: String!
name: String!
description: String!
}
input UpdateControlInput {
id: ID!
sectionTitle: String
name: String
description: String
}
input DeleteControlInput {
controlId: ID!
}
# Payload Types
type CreateOrganizationPayload {
organizationEdge: OrganizationEdge!
@@ -1515,6 +1542,18 @@ type DeleteOrganizationPayload {
deletedOrganizationId: ID!
}
type CreateControlPayload {
controlEdge: ControlEdge!
}
type UpdateControlPayload {
control: Control!
}
type DeleteControlPayload {
deletedControlId: ID!
}
type CreateVendorPayload {
vendorEdge: VendorEdge!
}

File diff suppressed because it is too large Load Diff

View File

@@ -45,11 +45,11 @@ func NewControlEdge(c *coredata.Control, orderBy coredata.ControlOrderField) *Co
func NewControl(c *coredata.Control) *Control {
return &Control{
ID: c.ID,
ReferenceID: c.ReferenceID,
Name: c.Name,
Description: c.Description,
CreatedAt: c.CreatedAt,
UpdatedAt: c.UpdatedAt,
ID: c.ID,
SectionTitle: c.SectionTitle,
Name: c.Name,
Description: c.Description,
CreatedAt: c.CreatedAt,
UpdatedAt: c.UpdatedAt,
}
}

View File

@@ -119,15 +119,15 @@ type ConnectorOrder struct {
}
type Control struct {
ID gid.GID `json:"id"`
ReferenceID string `json:"referenceId"`
Name string `json:"name"`
Description string `json:"description"`
Framework *Framework `json:"framework"`
Measures *MeasureConnection `json:"measures"`
Documents *DocumentConnection `json:"documents"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
ID gid.GID `json:"id"`
SectionTitle string `json:"sectionTitle"`
Name string `json:"name"`
Description string `json:"description"`
Framework *Framework `json:"framework"`
Measures *MeasureConnection `json:"measures"`
Documents *DocumentConnection `json:"documents"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
func (Control) IsNode() {}
@@ -168,6 +168,13 @@ type CreateControlDocumentMappingPayload struct {
DocumentEdge *DocumentEdge `json:"documentEdge"`
}
type CreateControlInput struct {
FrameworkID gid.GID `json:"frameworkId"`
SectionTitle string `json:"sectionTitle"`
Name string `json:"name"`
Description string `json:"description"`
}
type CreateControlMeasureMappingInput struct {
ControlID gid.GID `json:"controlId"`
MeasureID gid.GID `json:"measureId"`
@@ -178,6 +185,10 @@ type CreateControlMeasureMappingPayload struct {
MeasureEdge *MeasureEdge `json:"measureEdge"`
}
type CreateControlPayload struct {
ControlEdge *ControlEdge `json:"controlEdge"`
}
type CreateDatumInput struct {
OrganizationID gid.GID `json:"organizationId"`
Name string `json:"name"`
@@ -406,6 +417,10 @@ type DeleteControlDocumentMappingPayload struct {
DeletedDocumentID gid.GID `json:"deletedDocumentId"`
}
type DeleteControlInput struct {
ControlID gid.GID `json:"controlId"`
}
type DeleteControlMeasureMappingInput struct {
ControlID gid.GID `json:"controlId"`
MeasureID gid.GID `json:"measureId"`
@@ -416,6 +431,10 @@ type DeleteControlMeasureMappingPayload struct {
DeletedMeasureID gid.GID `json:"deletedMeasureId"`
}
type DeleteControlPayload struct {
DeletedControlID gid.GID `json:"deletedControlId"`
}
type DeleteDatumInput struct {
DatumID gid.GID `json:"datumId"`
}
@@ -980,6 +999,17 @@ type UpdateAssetPayload struct {
Asset *Asset `json:"asset"`
}
type UpdateControlInput struct {
ID gid.GID `json:"id"`
SectionTitle *string `json:"sectionTitle,omitempty"`
Name *string `json:"name,omitempty"`
Description *string `json:"description,omitempty"`
}
type UpdateControlPayload struct {
Control *Control `json:"control"`
}
type UpdateDatumInput struct {
ID gid.GID `json:"id"`
Name *string `json:"name,omitempty"`

View File

@@ -967,6 +967,59 @@ func (r *mutationResolver) DeleteFramework(ctx context.Context, input types.Dele
}, nil
}
// CreateControl is the resolver for the createControl field.
func (r *mutationResolver) CreateControl(ctx context.Context, input types.CreateControlInput) (*types.CreateControlPayload, error) {
svc := GetTenantService(ctx, r.proboSvc, input.FrameworkID.TenantID())
control, err := svc.Controls.Create(ctx, probo.CreateControlRequest{
FrameworkID: input.FrameworkID,
Name: input.Name,
Description: input.Description,
SectionTitle: input.SectionTitle,
})
if err != nil {
return nil, fmt.Errorf("cannot create control: %w", err)
}
return &types.CreateControlPayload{
ControlEdge: types.NewControlEdge(control, coredata.ControlOrderFieldCreatedAt),
}, nil
}
// UpdateControl is the resolver for the updateControl field.
func (r *mutationResolver) UpdateControl(ctx context.Context, input types.UpdateControlInput) (*types.UpdateControlPayload, error) {
svc := GetTenantService(ctx, r.proboSvc, input.ID.TenantID())
control, err := svc.Controls.Update(ctx, probo.UpdateControlRequest{
ID: input.ID,
Name: input.Name,
Description: input.Description,
SectionTitle: input.SectionTitle,
})
if err != nil {
return nil, fmt.Errorf("cannot update control: %w", err)
}
return &types.UpdateControlPayload{
Control: types.NewControl(control),
}, nil
}
// DeleteControl is the resolver for the deleteControl field.
func (r *mutationResolver) DeleteControl(ctx context.Context, input types.DeleteControlInput) (*types.DeleteControlPayload, error) {
svc := GetTenantService(ctx, r.proboSvc, input.ControlID.TenantID())
err := svc.Controls.Delete(ctx, input.ControlID)
if err != nil {
return nil, fmt.Errorf("cannot delete control: %w", err)
}
return &types.DeleteControlPayload{
DeletedControlID: input.ControlID,
}, nil
}
// // CreateMeasure is the resolver for the createMeasure field.
func (r *mutationResolver) CreateMeasure(ctx context.Context, input types.CreateMeasureInput) (*types.CreateMeasurePayload, error) {
svc := GetTenantService(ctx, r.proboSvc, input.OrganizationID.TenantID())