Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 59 additions & 74 deletions internal/api/handler/oscal/component_definition.go
Original file line number Diff line number Diff line change
Expand Up @@ -601,26 +601,24 @@ func (h *ComponentDefinitionHandler) CreateComponents(ctx echo.Context) error {
return ctx.JSON(http.StatusBadRequest, api.NewError(err))
}

var components []oscalTypes_1_1_3.DefinedComponent
if err := ctx.Bind(&components); err != nil {
var component oscalTypes_1_1_3.DefinedComponent
if err := ctx.Bind(&component); err != nil {
h.sugar.Warnw("Failed to bind components", "error", err)
return ctx.JSON(http.StatusBadRequest, api.NewError(err))
}

// Validate required fields for each component
for _, component := range components {
if component.Type == "" {
return ctx.JSON(http.StatusBadRequest, api.NewError(errors.New("component type is required")))
}
if component.Title == "" {
return ctx.JSON(http.StatusBadRequest, api.NewError(errors.New("component title is required")))
}
if component.Description == "" {
return ctx.JSON(http.StatusBadRequest, api.NewError(errors.New("component description is required")))
}
if component.Purpose == "" {
return ctx.JSON(http.StatusBadRequest, api.NewError(errors.New("component purpose is required")))
}
if component.Type == "" {
return ctx.JSON(http.StatusBadRequest, api.NewError(errors.New("component type is required")))
}
if component.Title == "" {
return ctx.JSON(http.StatusBadRequest, api.NewError(errors.New("component title is required")))
}
if component.Description == "" {
return ctx.JSON(http.StatusBadRequest, api.NewError(errors.New("component description is required")))
}
if component.Purpose == "" {
return ctx.JSON(http.StatusBadRequest, api.NewError(errors.New("component purpose is required")))
}

// Begin a transaction
Expand All @@ -630,22 +628,15 @@ func (h *ComponentDefinitionHandler) CreateComponents(ctx echo.Context) error {
return ctx.JSON(http.StatusInternalServerError, api.NewError(tx.Error))
}

// Convert to relational model
var newComponents []relational.DefinedComponent
for _, component := range components {
relationalComponent := relational.DefinedComponent{}
relationalComponent.UnmarshalOscal(component)
relationalComponent.ComponentDefinitionID = &id
newComponents = append(newComponents, relationalComponent)
}
relationalComponent := relational.DefinedComponent{}
relationalComponent.UnmarshalOscal(component)
relationalComponent.ComponentDefinitionID = &id

// Create each component individually
for _, component := range newComponents {
if err := tx.Create(&component).Error; err != nil {
tx.Rollback()
h.sugar.Errorf("Failed to create component: %v", err)
return ctx.JSON(http.StatusInternalServerError, api.NewError(err))
}
if err := tx.Create(&relationalComponent).Error; err != nil {
tx.Rollback()
h.sugar.Errorf("Failed to create component: %v", err)
return ctx.JSON(http.StatusInternalServerError, api.NewError(err))
}

// Update metadata
Expand All @@ -666,8 +657,8 @@ func (h *ComponentDefinitionHandler) CreateComponents(ctx echo.Context) error {
return ctx.JSON(http.StatusInternalServerError, api.NewError(err))
}

return ctx.JSON(http.StatusOK, handler.GenericDataListResponse[oscalTypes_1_1_3.DefinedComponent]{
Data: components,
return ctx.JSON(http.StatusOK, handler.GenericDataResponse[oscalTypes_1_1_3.DefinedComponent]{
Data: component,
})
}

Expand Down Expand Up @@ -1589,40 +1580,38 @@ func (h *ComponentDefinitionHandler) CreateCapabilities(ctx echo.Context) error
return ctx.JSON(http.StatusBadRequest, api.NewError(err))
}

var capabilities []oscalTypes_1_1_3.Capability
if err := ctx.Bind(&capabilities); err != nil {
h.sugar.Warnw("Failed to bind capabilities", "error", err)
var capability oscalTypes_1_1_3.Capability
if err := ctx.Bind(&capability); err != nil {
h.sugar.Warnw("Failed to bind capability", "error", err)
return ctx.JSON(http.StatusBadRequest, api.NewError(err))
}

// Validate required fields
for _, capability := range capabilities {
if capability.Name == "" {
return ctx.JSON(http.StatusBadRequest, api.NewError(errors.New("capability name is required")))
}
if capability.Description == "" {
return ctx.JSON(http.StatusBadRequest, api.NewError(errors.New("capability description is required")))
}
if capability.ControlImplementations != nil {
for _, impl := range *capability.ControlImplementations {
if impl.Description == "" {
return ctx.JSON(http.StatusBadRequest, api.NewError(errors.New("control implementation description is required")))
}
for _, req := range impl.ImplementedRequirements {
if req.ControlId == "" {
return ctx.JSON(http.StatusBadRequest, api.NewError(errors.New("control ID is required")))
}
if capability.Name == "" {
return ctx.JSON(http.StatusBadRequest, api.NewError(errors.New("capability name is required")))
}
if capability.Description == "" {
return ctx.JSON(http.StatusBadRequest, api.NewError(errors.New("capability description is required")))
}
if capability.ControlImplementations != nil {
for _, impl := range *capability.ControlImplementations {
if impl.Description == "" {
return ctx.JSON(http.StatusBadRequest, api.NewError(errors.New("control implementation description is required")))
}
for _, req := range impl.ImplementedRequirements {
if req.ControlId == "" {
return ctx.JSON(http.StatusBadRequest, api.NewError(errors.New("control ID is required")))
}
}
}
if capability.IncorporatesComponents != nil {
for _, component := range *capability.IncorporatesComponents {
if component.ComponentUuid == "" {
return ctx.JSON(http.StatusBadRequest, api.NewError(errors.New("component UUID is required for incorporates component")))
}
if component.Description == "" {
return ctx.JSON(http.StatusBadRequest, api.NewError(errors.New("description is required for incorporates component")))
}
}
if capability.IncorporatesComponents != nil {
for _, component := range *capability.IncorporatesComponents {
if component.ComponentUuid == "" {
return ctx.JSON(http.StatusBadRequest, api.NewError(errors.New("component UUID is required for incorporates component")))
}
if component.Description == "" {
return ctx.JSON(http.StatusBadRequest, api.NewError(errors.New("description is required for incorporates component")))
}
}
}
Expand All @@ -1635,21 +1624,17 @@ func (h *ComponentDefinitionHandler) CreateCapabilities(ctx echo.Context) error
}

// Convert to relational model
var newCapabilities []relational.Capability
for _, capability := range capabilities {
relationalCapability := relational.Capability{}
relationalCapability.UnmarshalOscal(capability)
relationalCapability.ComponentDefinitionId = id
newCapabilities = append(newCapabilities, relationalCapability)
}
var newCapability relational.Capability
relationalCapability := relational.Capability{}
relationalCapability.UnmarshalOscal(capability)
relationalCapability.ComponentDefinitionId = id
newCapability = relationalCapability
Comment on lines +1628 to +1631
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The redundant variable assignment is unnecessary. The variable 'newCapability' is declared on line 1636, then 'relationalCapability' is created on line 1637, populated on lines 1638-1639, and then assigned to 'newCapability' on line 1640. You can simplify this by using 'newCapability' directly instead of creating an intermediate 'relationalCapability' variable.

Suggested change
relationalCapability := relational.Capability{}
relationalCapability.UnmarshalOscal(capability)
relationalCapability.ComponentDefinitionId = id
newCapability = relationalCapability
newCapability.UnmarshalOscal(capability)
newCapability.ComponentDefinitionId = id

Copilot uses AI. Check for mistakes.

// Create the capabilities
for _, capability := range newCapabilities {
if err := tx.Create(&capability).Error; err != nil {
tx.Rollback()
h.sugar.Errorf("Failed to create capability: %v", err)
return ctx.JSON(http.StatusInternalServerError, api.NewError(err))
}
// Create the capability
if err := tx.Create(&newCapability).Error; err != nil {
tx.Rollback()
h.sugar.Errorf("Failed to create capability: %v", err)
return ctx.JSON(http.StatusInternalServerError, api.NewError(err))
}

// Commit the transaction
Expand All @@ -1658,8 +1643,8 @@ func (h *ComponentDefinitionHandler) CreateCapabilities(ctx echo.Context) error
return ctx.JSON(http.StatusInternalServerError, api.NewError(err))
}

return ctx.JSON(http.StatusOK, handler.GenericDataListResponse[oscalTypes_1_1_3.Capability]{
Data: capabilities,
return ctx.JSON(http.StatusOK, handler.GenericDataResponse[oscalTypes_1_1_3.Capability]{
Data: capability,
})
}

Expand Down
Loading