Remove access review framework controls
Signed-off-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Bryan FRIMIN <bryan@frimin.fr>
This commit is contained in:
committed by
Bryan Frimin
parent
9822b39ece
commit
79285d97df
@@ -349,50 +349,6 @@ func TestAccessReviewCampaign_Create(t *testing.T) {
|
|||||||
assert.Len(t, node.CampaignSources, 2)
|
assert.Len(t, node.CampaignSources, 2)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("with framework controls", func(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
const query = `
|
|
||||||
mutation($input: CreateAccessReviewCampaignInput!) {
|
|
||||||
createAccessReviewCampaign(input: $input) {
|
|
||||||
accessReviewCampaignEdge {
|
|
||||||
node {
|
|
||||||
id
|
|
||||||
name
|
|
||||||
frameworkControls
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
var result struct {
|
|
||||||
CreateAccessReviewCampaign struct {
|
|
||||||
AccessReviewCampaignEdge struct {
|
|
||||||
Node struct {
|
|
||||||
ID string `json:"id"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
FrameworkControls []string `json:"frameworkControls"`
|
|
||||||
} `json:"node"`
|
|
||||||
} `json:"accessReviewCampaignEdge"`
|
|
||||||
} `json:"createAccessReviewCampaign"`
|
|
||||||
}
|
|
||||||
|
|
||||||
err := owner.Execute(query, map[string]any{
|
|
||||||
"input": map[string]any{
|
|
||||||
"organizationId": orgID,
|
|
||||||
"name": "SOC2 Campaign",
|
|
||||||
"frameworkControls": []string{"CC6.1", "CC6.2"},
|
|
||||||
},
|
|
||||||
}, &result)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
node := result.CreateAccessReviewCampaign.AccessReviewCampaignEdge.Node
|
|
||||||
assert.NotEmpty(t, node.ID)
|
|
||||||
assert.Equal(t, "SOC2 Campaign", node.Name)
|
|
||||||
assert.Contains(t, node.FrameworkControls, "CC6.1")
|
|
||||||
assert.Contains(t, node.FrameworkControls, "CC6.2")
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAccessReviewCampaign_Update(t *testing.T) {
|
func TestAccessReviewCampaign_Update(t *testing.T) {
|
||||||
|
|||||||
@@ -36,14 +36,13 @@ func (s *Service) CreateCampaign(
|
|||||||
|
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
campaign := &coredata.AccessReviewCampaign{
|
campaign := &coredata.AccessReviewCampaign{
|
||||||
ID: gid.New(scope.GetTenantID(), coredata.AccessReviewCampaignEntityType),
|
ID: gid.New(scope.GetTenantID(), coredata.AccessReviewCampaignEntityType),
|
||||||
OrganizationID: req.OrganizationID,
|
OrganizationID: req.OrganizationID,
|
||||||
Name: req.Name,
|
Name: req.Name,
|
||||||
Description: req.Description,
|
Description: req.Description,
|
||||||
Status: coredata.AccessReviewCampaignStatusDraft,
|
Status: coredata.AccessReviewCampaignStatusDraft,
|
||||||
FrameworkControls: req.FrameworkControls,
|
CreatedAt: now,
|
||||||
CreatedAt: now,
|
UpdatedAt: now,
|
||||||
UpdatedAt: now,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err := s.pg.WithTx(
|
err := s.pg.WithTx(
|
||||||
@@ -160,10 +159,6 @@ func (s *Service) UpdateCampaign(
|
|||||||
campaign.Description = **req.Description
|
campaign.Description = **req.Description
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.FrameworkControls != nil {
|
|
||||||
campaign.FrameworkControls = *req.FrameworkControls
|
|
||||||
}
|
|
||||||
|
|
||||||
campaign.UpdatedAt = time.Now()
|
campaign.UpdatedAt = time.Now()
|
||||||
|
|
||||||
if err := campaign.Update(ctx, conn, scope); err != nil {
|
if err := campaign.Update(ctx, conn, scope); err != nil {
|
||||||
|
|||||||
@@ -27,15 +27,13 @@ type (
|
|||||||
OrganizationID gid.GID
|
OrganizationID gid.GID
|
||||||
Name string
|
Name string
|
||||||
Description string
|
Description string
|
||||||
FrameworkControls []string
|
|
||||||
AccessReviewSourceIDs []gid.GID
|
AccessReviewSourceIDs []gid.GID
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateAccessReviewCampaignRequest struct {
|
UpdateAccessReviewCampaignRequest struct {
|
||||||
CampaignID gid.GID
|
CampaignID gid.GID
|
||||||
Name **string
|
Name **string
|
||||||
Description **string
|
Description **string
|
||||||
FrameworkControls *[]string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AddCampaignSourceRequest struct {
|
AddCampaignSourceRequest struct {
|
||||||
|
|||||||
@@ -47,10 +47,9 @@ type updateResponse struct {
|
|||||||
|
|
||||||
func NewCmdUpdate(f *cmdutil.Factory) *cobra.Command {
|
func NewCmdUpdate(f *cmdutil.Factory) *cobra.Command {
|
||||||
var (
|
var (
|
||||||
flagName string
|
flagName string
|
||||||
flagDescription string
|
flagDescription string
|
||||||
flagFrameworkControl []string
|
flagOutput *string
|
||||||
flagOutput *string
|
|
||||||
)
|
)
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
@@ -92,10 +91,6 @@ func NewCmdUpdate(f *cmdutil.Factory) *cobra.Command {
|
|||||||
input["description"] = flagDescription
|
input["description"] = flagDescription
|
||||||
}
|
}
|
||||||
|
|
||||||
if cmd.Flags().Changed("framework-control") {
|
|
||||||
input["frameworkControls"] = flagFrameworkControl
|
|
||||||
}
|
|
||||||
|
|
||||||
data, err := client.Do(
|
data, err := client.Do(
|
||||||
updateMutation,
|
updateMutation,
|
||||||
map[string]any{"input": input},
|
map[string]any{"input": input},
|
||||||
@@ -125,12 +120,6 @@ func NewCmdUpdate(f *cmdutil.Factory) *cobra.Command {
|
|||||||
|
|
||||||
cmd.Flags().StringVar(&flagName, "name", "", "Campaign name")
|
cmd.Flags().StringVar(&flagName, "name", "", "Campaign name")
|
||||||
cmd.Flags().StringVar(&flagDescription, "description", "", "Campaign description")
|
cmd.Flags().StringVar(&flagDescription, "description", "", "Campaign description")
|
||||||
cmd.Flags().StringSliceVar(
|
|
||||||
&flagFrameworkControl,
|
|
||||||
"framework-control",
|
|
||||||
nil,
|
|
||||||
"Framework control IDs (can be repeated)",
|
|
||||||
)
|
|
||||||
flagOutput = cmdutil.AddOutputFlag(cmd)
|
flagOutput = cmdutil.AddOutputFlag(cmd)
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
|
|||||||
@@ -30,16 +30,15 @@ import (
|
|||||||
|
|
||||||
type (
|
type (
|
||||||
AccessReviewCampaign struct {
|
AccessReviewCampaign struct {
|
||||||
ID gid.GID `db:"id"`
|
ID gid.GID `db:"id"`
|
||||||
OrganizationID gid.GID `db:"organization_id"`
|
OrganizationID gid.GID `db:"organization_id"`
|
||||||
Name string `db:"name"`
|
Name string `db:"name"`
|
||||||
Description string `db:"description"`
|
Description string `db:"description"`
|
||||||
Status AccessReviewCampaignStatus `db:"status"`
|
Status AccessReviewCampaignStatus `db:"status"`
|
||||||
StartedAt *time.Time `db:"started_at"`
|
StartedAt *time.Time `db:"started_at"`
|
||||||
CompletedAt *time.Time `db:"completed_at"`
|
CompletedAt *time.Time `db:"completed_at"`
|
||||||
FrameworkControls []string `db:"framework_controls"`
|
CreatedAt time.Time `db:"created_at"`
|
||||||
CreatedAt time.Time `db:"created_at"`
|
UpdatedAt time.Time `db:"updated_at"`
|
||||||
UpdatedAt time.Time `db:"updated_at"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AccessReviewCampaigns []*AccessReviewCampaign
|
AccessReviewCampaigns []*AccessReviewCampaign
|
||||||
@@ -136,7 +135,6 @@ SELECT
|
|||||||
status,
|
status,
|
||||||
started_at,
|
started_at,
|
||||||
completed_at,
|
completed_at,
|
||||||
framework_controls,
|
|
||||||
created_at,
|
created_at,
|
||||||
updated_at
|
updated_at
|
||||||
FROM
|
FROM
|
||||||
@@ -186,7 +184,6 @@ INSERT INTO
|
|||||||
status,
|
status,
|
||||||
started_at,
|
started_at,
|
||||||
completed_at,
|
completed_at,
|
||||||
framework_controls,
|
|
||||||
created_at,
|
created_at,
|
||||||
updated_at
|
updated_at
|
||||||
)
|
)
|
||||||
@@ -199,24 +196,22 @@ VALUES (
|
|||||||
@status,
|
@status,
|
||||||
@started_at,
|
@started_at,
|
||||||
@completed_at,
|
@completed_at,
|
||||||
@framework_controls,
|
|
||||||
@created_at,
|
@created_at,
|
||||||
@updated_at
|
@updated_at
|
||||||
);
|
);
|
||||||
`
|
`
|
||||||
|
|
||||||
args := pgx.StrictNamedArgs{
|
args := pgx.StrictNamedArgs{
|
||||||
"id": c.ID,
|
"id": c.ID,
|
||||||
"tenant_id": scope.GetTenantID(),
|
"tenant_id": scope.GetTenantID(),
|
||||||
"organization_id": c.OrganizationID,
|
"organization_id": c.OrganizationID,
|
||||||
"name": c.Name,
|
"name": c.Name,
|
||||||
"description": c.Description,
|
"description": c.Description,
|
||||||
"status": c.Status,
|
"status": c.Status,
|
||||||
"started_at": c.StartedAt,
|
"started_at": c.StartedAt,
|
||||||
"completed_at": c.CompletedAt,
|
"completed_at": c.CompletedAt,
|
||||||
"framework_controls": c.FrameworkControls,
|
"created_at": c.CreatedAt,
|
||||||
"created_at": c.CreatedAt,
|
"updated_at": c.UpdatedAt,
|
||||||
"updated_at": c.UpdatedAt,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := conn.Exec(ctx, q, args)
|
_, err := conn.Exec(ctx, q, args)
|
||||||
@@ -240,7 +235,6 @@ SET
|
|||||||
status = @status,
|
status = @status,
|
||||||
started_at = @started_at,
|
started_at = @started_at,
|
||||||
completed_at = @completed_at,
|
completed_at = @completed_at,
|
||||||
framework_controls = @framework_controls,
|
|
||||||
updated_at = @updated_at
|
updated_at = @updated_at
|
||||||
WHERE
|
WHERE
|
||||||
%s
|
%s
|
||||||
@@ -249,14 +243,13 @@ WHERE
|
|||||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||||
|
|
||||||
args := pgx.StrictNamedArgs{
|
args := pgx.StrictNamedArgs{
|
||||||
"id": c.ID,
|
"id": c.ID,
|
||||||
"name": c.Name,
|
"name": c.Name,
|
||||||
"description": c.Description,
|
"description": c.Description,
|
||||||
"status": c.Status,
|
"status": c.Status,
|
||||||
"started_at": c.StartedAt,
|
"started_at": c.StartedAt,
|
||||||
"completed_at": c.CompletedAt,
|
"completed_at": c.CompletedAt,
|
||||||
"framework_controls": c.FrameworkControls,
|
"updated_at": c.UpdatedAt,
|
||||||
"updated_at": c.UpdatedAt,
|
|
||||||
}
|
}
|
||||||
maps.Copy(args, scope.SQLArguments())
|
maps.Copy(args, scope.SQLArguments())
|
||||||
|
|
||||||
@@ -310,7 +303,6 @@ SELECT
|
|||||||
status,
|
status,
|
||||||
started_at,
|
started_at,
|
||||||
completed_at,
|
completed_at,
|
||||||
framework_controls,
|
|
||||||
created_at,
|
created_at,
|
||||||
updated_at
|
updated_at
|
||||||
FROM
|
FROM
|
||||||
@@ -382,7 +374,6 @@ SELECT
|
|||||||
status,
|
status,
|
||||||
started_at,
|
started_at,
|
||||||
completed_at,
|
completed_at,
|
||||||
framework_controls,
|
|
||||||
created_at,
|
created_at,
|
||||||
updated_at
|
updated_at
|
||||||
FROM
|
FROM
|
||||||
|
|||||||
16
pkg/coredata/migrations/20260630T092731Z.sql
Normal file
16
pkg/coredata/migrations/20260630T092731Z.sql
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
-- Copyright (c) 2026 Probo Inc <hello@probo.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.
|
||||||
|
|
||||||
|
ALTER TABLE access_review_campaigns
|
||||||
|
DROP COLUMN framework_controls;
|
||||||
@@ -736,7 +736,6 @@ func (r *mutationResolver) CreateAccessReviewCampaign(ctx context.Context, input
|
|||||||
OrganizationID: input.OrganizationID,
|
OrganizationID: input.OrganizationID,
|
||||||
Name: input.Name,
|
Name: input.Name,
|
||||||
Description: description,
|
Description: description,
|
||||||
FrameworkControls: input.FrameworkControls,
|
|
||||||
AccessReviewSourceIDs: input.AccessReviewSourceIds,
|
AccessReviewSourceIDs: input.AccessReviewSourceIds,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -762,10 +761,9 @@ func (r *mutationResolver) UpdateAccessReviewCampaign(ctx context.Context, input
|
|||||||
ctx,
|
ctx,
|
||||||
scope,
|
scope,
|
||||||
accessreview.UpdateAccessReviewCampaignRequest{
|
accessreview.UpdateAccessReviewCampaignRequest{
|
||||||
CampaignID: input.AccessReviewCampaignID,
|
CampaignID: input.AccessReviewCampaignID,
|
||||||
Name: gqlutils.UnwrapOmittable(input.Name),
|
Name: gqlutils.UnwrapOmittable(input.Name),
|
||||||
Description: gqlutils.UnwrapOmittable(input.Description),
|
Description: gqlutils.UnwrapOmittable(input.Description),
|
||||||
FrameworkControls: gqlutils.UnwrapOmittable(input.FrameworkControls),
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -349,7 +349,6 @@ type AccessReviewCampaign implements Node {
|
|||||||
status: AccessReviewCampaignStatus!
|
status: AccessReviewCampaignStatus!
|
||||||
startedAt: Datetime
|
startedAt: Datetime
|
||||||
completedAt: Datetime
|
completedAt: Datetime
|
||||||
frameworkControls: [String!]
|
|
||||||
createdAt: Datetime!
|
createdAt: Datetime!
|
||||||
updatedAt: Datetime!
|
updatedAt: Datetime!
|
||||||
|
|
||||||
@@ -578,7 +577,6 @@ input CreateAccessReviewCampaignInput {
|
|||||||
organizationId: ID!
|
organizationId: ID!
|
||||||
name: String!
|
name: String!
|
||||||
description: String
|
description: String
|
||||||
frameworkControls: [String!]
|
|
||||||
accessReviewSourceIds: [ID!]
|
accessReviewSourceIds: [ID!]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -590,7 +588,6 @@ input UpdateAccessReviewCampaignInput {
|
|||||||
accessReviewCampaignId: ID!
|
accessReviewCampaignId: ID!
|
||||||
name: String @goField(omittable: true)
|
name: String @goField(omittable: true)
|
||||||
description: String @goField(omittable: true)
|
description: String @goField(omittable: true)
|
||||||
frameworkControls: [String!] @goField(omittable: true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type UpdateAccessReviewCampaignPayload {
|
type UpdateAccessReviewCampaignPayload {
|
||||||
|
|||||||
@@ -215,14 +215,13 @@ func NewAccessReviewCampaign(c *coredata.AccessReviewCampaign) *AccessReviewCamp
|
|||||||
Organization: &Organization{
|
Organization: &Organization{
|
||||||
ID: c.OrganizationID,
|
ID: c.OrganizationID,
|
||||||
},
|
},
|
||||||
Name: c.Name,
|
Name: c.Name,
|
||||||
Description: c.Description,
|
Description: c.Description,
|
||||||
Status: c.Status,
|
Status: c.Status,
|
||||||
StartedAt: c.StartedAt,
|
StartedAt: c.StartedAt,
|
||||||
CompletedAt: c.CompletedAt,
|
CompletedAt: c.CompletedAt,
|
||||||
FrameworkControls: c.FrameworkControls,
|
CreatedAt: c.CreatedAt,
|
||||||
CreatedAt: c.CreatedAt,
|
UpdatedAt: c.UpdatedAt,
|
||||||
UpdatedAt: c.UpdatedAt,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return campaign
|
return campaign
|
||||||
|
|||||||
@@ -3752,7 +3752,6 @@ func (r *Resolver) CreateAccessReviewCampaignTool(ctx context.Context, req *mcp.
|
|||||||
OrganizationID: input.OrganizationID,
|
OrganizationID: input.OrganizationID,
|
||||||
Name: input.Name,
|
Name: input.Name,
|
||||||
Description: description,
|
Description: description,
|
||||||
FrameworkControls: input.FrameworkControls,
|
|
||||||
AccessReviewSourceIDs: input.AccessReviewSourceIds,
|
AccessReviewSourceIDs: input.AccessReviewSourceIds,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -3784,22 +3783,6 @@ func (r *Resolver) UpdateAccessReviewCampaignTool(ctx context.Context, req *mcp.
|
|||||||
updateReq.Description = &input.Description
|
updateReq.Description = &input.Description
|
||||||
}
|
}
|
||||||
|
|
||||||
if rawControls := UnwrapOmittable(input.FrameworkControls); rawControls != nil {
|
|
||||||
if *rawControls != nil {
|
|
||||||
controls := make([]string, 0, len(**rawControls))
|
|
||||||
for _, v := range **rawControls {
|
|
||||||
if s, ok := v.(string); ok {
|
|
||||||
controls = append(controls, s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
updateReq.FrameworkControls = &controls
|
|
||||||
} else {
|
|
||||||
empty := []string{}
|
|
||||||
updateReq.FrameworkControls = &empty
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
campaign, err := r.accessReview.UpdateCampaign(ctx, scope, updateReq)
|
campaign, err := r.accessReview.UpdateCampaign(ctx, scope, updateReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, types.UpdateAccessReviewCampaignOutput{}, fmt.Errorf("cannot update access review campaign: %w", err)
|
return nil, types.UpdateAccessReviewCampaignOutput{}, fmt.Errorf("cannot update access review campaign: %w", err)
|
||||||
|
|||||||
@@ -7644,11 +7644,6 @@ components:
|
|||||||
- "null"
|
- "null"
|
||||||
format: date-time
|
format: date-time
|
||||||
description: Campaign completion time
|
description: Campaign completion time
|
||||||
framework_controls:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
description: Framework controls
|
|
||||||
created_at:
|
created_at:
|
||||||
type: string
|
type: string
|
||||||
format: date-time
|
format: date-time
|
||||||
@@ -8187,11 +8182,6 @@ components:
|
|||||||
description:
|
description:
|
||||||
type: string
|
type: string
|
||||||
description: Campaign description
|
description: Campaign description
|
||||||
framework_controls:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
description: Framework control references
|
|
||||||
access_review_source_ids:
|
access_review_source_ids:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
@@ -8220,15 +8210,6 @@ components:
|
|||||||
description:
|
description:
|
||||||
type: string
|
type: string
|
||||||
description: New campaign description
|
description: New campaign description
|
||||||
framework_controls:
|
|
||||||
type:
|
|
||||||
- array
|
|
||||||
- "null"
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
go.probo.inc/mcpgen/omittable: true
|
|
||||||
description: Framework control references (set to null to clear)
|
|
||||||
|
|
||||||
UpdateAccessReviewCampaignMCPOutput:
|
UpdateAccessReviewCampaignMCPOutput:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
|
|||||||
@@ -54,16 +54,15 @@ func NewListAccessReviewSourcesOutput(
|
|||||||
|
|
||||||
func NewAccessReviewCampaign(c *coredata.AccessReviewCampaign) *AccessReviewCampaign {
|
func NewAccessReviewCampaign(c *coredata.AccessReviewCampaign) *AccessReviewCampaign {
|
||||||
return &AccessReviewCampaign{
|
return &AccessReviewCampaign{
|
||||||
ID: c.ID,
|
ID: c.ID,
|
||||||
OrganizationID: c.OrganizationID,
|
OrganizationID: c.OrganizationID,
|
||||||
Name: c.Name,
|
Name: c.Name,
|
||||||
Description: &c.Description,
|
Description: &c.Description,
|
||||||
Status: c.Status,
|
Status: c.Status,
|
||||||
StartedAt: c.StartedAt,
|
StartedAt: c.StartedAt,
|
||||||
CompletedAt: c.CompletedAt,
|
CompletedAt: c.CompletedAt,
|
||||||
FrameworkControls: c.FrameworkControls,
|
CreatedAt: c.CreatedAt,
|
||||||
CreatedAt: c.CreatedAt,
|
UpdatedAt: c.UpdatedAt,
|
||||||
UpdatedAt: c.UpdatedAt,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user