Skip to content
Merged
Show file tree
Hide file tree
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
33 changes: 18 additions & 15 deletions platform-api/src/internal/dto/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,24 @@ import (

// CreateGatewayRequest represents the request body for registering a new gateway
type CreateGatewayRequest struct {
Name string `json:"name" binding:"required"`
DisplayName string `json:"displayName" binding:"required"`
Description string `json:"description,omitempty"`
Vhost string `json:"vhost" binding:"required"`
IsCritical bool `json:"isCritical,omitempty"`
FunctionalityType string `json:"functionalityType" binding:"required"`
Name string `json:"name" binding:"required"`
DisplayName string `json:"displayName" binding:"required"`
Description string `json:"description,omitempty"`
Vhost string `json:"vhost" binding:"required"`
IsCritical bool `json:"isCritical,omitempty"`
FunctionalityType string `json:"functionalityType" binding:"required"`
Properties map[string]interface{} `json:"properties,omitempty"`
}

// GatewayResponse represents a gateway in API responses
type GatewayResponse struct {
ID string `json:"id"`
OrganizationID string `json:"organizationId"`
Name string `json:"name"`
DisplayName string `json:"displayName"`
Description string `json:"description,omitempty"`
Vhost string `json:"vhost"`
ID string `json:"id"`
OrganizationID string `json:"organizationId"`
Name string `json:"name"`
DisplayName string `json:"displayName"`
Description string `json:"description,omitempty"`
Properties map[string]interface{} `json:"properties,omitempty"`
Vhost string `json:"vhost"`
IsCritical bool `json:"isCritical"`
FunctionalityType string `json:"functionalityType"`
IsActive bool `json:"isActive"`
Expand All @@ -55,9 +57,10 @@ type GatewayListResponse struct {

// UpdateGatewayRequest represents the request body for updating gateway details
type UpdateGatewayRequest struct {
DisplayName *string `json:"displayName,omitempty"`
Description *string `json:"description,omitempty"`
IsCritical *bool `json:"isCritical,omitempty"`
DisplayName *string `json:"displayName,omitempty"`
Description *string `json:"description,omitempty"`
IsCritical *bool `json:"isCritical,omitempty"`
Properties *map[string]interface{} `json:"properties,omitempty"`
}

// TokenRotationResponse represents the response when rotating a gateway token
Expand Down
4 changes: 2 additions & 2 deletions platform-api/src/internal/handler/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func (h *GatewayHandler) CreateGateway(c *gin.Context) {
}

response, err := h.gatewayService.RegisterGateway(orgId, req.Name, req.DisplayName, req.Description, req.Vhost,
req.IsCritical, req.FunctionalityType)
req.IsCritical, req.FunctionalityType, req.Properties)
if err != nil {
errMsg := err.Error()

Expand Down Expand Up @@ -214,7 +214,7 @@ func (h *GatewayHandler) UpdateGateway(c *gin.Context) {
return
}

gateway, err := h.gatewayService.UpdateGateway(gatewayId, orgId, req.Description, req.DisplayName, req.IsCritical)
gateway, err := h.gatewayService.UpdateGateway(gatewayId, orgId, req.Description, req.DisplayName, req.IsCritical, req.Properties)
if err != nil {
if errors.Is(err, constants.ErrGatewayNotFound) {
utils.LogError("Gateway not found during update", err)
Expand Down
14 changes: 8 additions & 6 deletions platform-api/src/internal/model/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,13 @@ import (

// Gateway represents a registered gateway instance within an organization
type Gateway struct {
ID string `json:"id" db:"uuid"`
OrganizationID string `json:"organizationId" db:"organization_uuid"`
Name string `json:"name" db:"name"`
DisplayName string `json:"displayName" db:"display_name"`
Description string `json:"description" db:"description"`
Vhost string `json:"vhost" db:"vhost"`
ID string `json:"id" db:"uuid"`
OrganizationID string `json:"organizationId" db:"organization_uuid"`
Name string `json:"name" db:"name"`
DisplayName string `json:"displayName" db:"display_name"`
Description string `json:"description" db:"description"`
Properties map[string]interface{} `json:"properties,omitempty" db:"properties"`
Vhost string `json:"vhost" db:"vhost"`
IsCritical bool `json:"isCritical" db:"is_critical"`
FunctionalityType string `json:"functionalityType" db:"gateway_functionality_type"`
IsActive bool `json:"isActive" db:"is_active"`
Expand Down Expand Up @@ -77,6 +78,7 @@ type APIGatewayWithDetails struct {
Name string `json:"name" db:"name"`
DisplayName string `json:"displayName" db:"display_name"`
Description string `json:"description" db:"description"`
Properties map[string]interface{} `json:"properties,omitempty" db:"properties"`
Vhost string `json:"vhost" db:"vhost"`
IsCritical bool `json:"isCritical" db:"is_critical"`
FunctionalityType string `json:"functionalityType" db:"functionality_type"`
Expand Down
9 changes: 9 additions & 0 deletions platform-api/src/internal/repository/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -1709,6 +1709,7 @@ func (r *APIRepo) GetAPIGatewaysWithDetails(apiUUID, orgUUID string) ([]*model.A
g.name,
g.display_name,
g.description,
g.properties,
g.vhost,
g.is_critical,
g.gateway_functionality_type as functionality_type,
Expand Down Expand Up @@ -1736,6 +1737,7 @@ func (r *APIRepo) GetAPIGatewaysWithDetails(apiUUID, orgUUID string) ([]*model.A
var gateways []*model.APIGatewayWithDetails
for rows.Next() {
gateway := &model.APIGatewayWithDetails{}
var propertiesJSON string
var deployedAt sql.NullTime
var deploymentId sql.NullString

Expand All @@ -1745,6 +1747,7 @@ func (r *APIRepo) GetAPIGatewaysWithDetails(apiUUID, orgUUID string) ([]*model.A
&gateway.Name,
&gateway.DisplayName,
&gateway.Description,
&propertiesJSON,
&gateway.Vhost,
&gateway.IsCritical,
&gateway.FunctionalityType,
Expand All @@ -1761,6 +1764,12 @@ func (r *APIRepo) GetAPIGatewaysWithDetails(apiUUID, orgUUID string) ([]*model.A
return nil, err
}

if propertiesJSON != "" && propertiesJSON != "{}" {
if err := json.Unmarshal([]byte(propertiesJSON), &gateway.Properties); err != nil {
return nil, fmt.Errorf("failed to unmarshal gateway properties: %w", err)
}
}

if deploymentId.Valid {
gateway.DeploymentID = &deploymentId.String
}
Expand Down
88 changes: 75 additions & 13 deletions platform-api/src/internal/repository/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ package repository

import (
"database/sql"
"encoding/json"
"errors"
"fmt"
"time"

"platform-api/src/internal/database"
Expand All @@ -42,42 +44,63 @@ func (r *GatewayRepo) Create(gateway *model.Gateway) error {
gateway.UpdatedAt = time.Now()
gateway.IsActive = false // Set default value to false at registration

// Serialize properties to JSON
var propertiesJSON string
if gateway.Properties != nil {
jsonBytes, err := json.Marshal(gateway.Properties)
if err != nil {
return fmt.Errorf("failed to marshal properties: %w", err)
}
propertiesJSON = string(jsonBytes)
} else {
propertiesJSON = "{}"
}

query := `
INSERT INTO gateways (uuid, organization_uuid, name, display_name, description, vhost, is_critical,
INSERT INTO gateways (uuid, organization_uuid, name, display_name, description, properties, vhost, is_critical,
gateway_functionality_type, is_active, created_at, updated_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`
_, err := r.db.Exec(r.db.Rebind(query), gateway.ID, gateway.OrganizationID, gateway.Name, gateway.DisplayName,
gateway.Description, gateway.Vhost, gateway.IsCritical, gateway.FunctionalityType, gateway.IsActive,
gateway.Description, propertiesJSON, gateway.Vhost, gateway.IsCritical, gateway.FunctionalityType, gateway.IsActive,
gateway.CreatedAt, gateway.UpdatedAt)
return err
}

// GetByUUID retrieves a gateway by ID
func (r *GatewayRepo) GetByUUID(gatewayId string) (*model.Gateway, error) {
gateway := &model.Gateway{}
var propertiesJSON string
query := `
SELECT uuid, organization_uuid, name, display_name, description, vhost, is_critical, gateway_functionality_type, is_active,
SELECT uuid, organization_uuid, name, display_name, description, properties, vhost, is_critical, gateway_functionality_type, is_active,
created_at, updated_at
FROM gateways
WHERE uuid = ?
`
err := r.db.QueryRow(r.db.Rebind(query), gatewayId).Scan(
&gateway.ID, &gateway.OrganizationID, &gateway.Name, &gateway.DisplayName, &gateway.Description, &gateway.Vhost,
&gateway.ID, &gateway.OrganizationID, &gateway.Name, &gateway.DisplayName, &gateway.Description, &propertiesJSON, &gateway.Vhost,
&gateway.IsCritical, &gateway.FunctionalityType, &gateway.IsActive, &gateway.CreatedAt, &gateway.UpdatedAt)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, nil
}
return nil, err
}

// Deserialize properties from JSON
if propertiesJSON != "" && propertiesJSON != "{}" {
if err := json.Unmarshal([]byte(propertiesJSON), &gateway.Properties); err != nil {
return nil, fmt.Errorf("failed to unmarshal properties: %w", err)
}
}

return gateway, nil
}

// GetByOrganizationID retrieves all gateways for an organization
func (r *GatewayRepo) GetByOrganizationID(orgID string) ([]*model.Gateway, error) {
query := `
SELECT uuid, organization_uuid, name, display_name, description, vhost, is_critical, gateway_functionality_type, is_active,
SELECT uuid, organization_uuid, name, display_name, description, properties, vhost, is_critical, gateway_functionality_type, is_active,
created_at, updated_at
FROM gateways
WHERE organization_uuid = ?
Expand All @@ -92,12 +115,21 @@ func (r *GatewayRepo) GetByOrganizationID(orgID string) ([]*model.Gateway, error
var gateways []*model.Gateway
for rows.Next() {
gateway := &model.Gateway{}
var propertiesJSON string
err := rows.Scan(
&gateway.ID, &gateway.OrganizationID, &gateway.Name, &gateway.DisplayName, &gateway.Description, &gateway.Vhost,
&gateway.ID, &gateway.OrganizationID, &gateway.Name, &gateway.DisplayName, &gateway.Description, &propertiesJSON, &gateway.Vhost,
&gateway.IsCritical, &gateway.FunctionalityType, &gateway.IsActive, &gateway.CreatedAt, &gateway.UpdatedAt)
if err != nil {
return nil, err
}

// Deserialize properties from JSON
if propertiesJSON != "" && propertiesJSON != "{}" {
if err := json.Unmarshal([]byte(propertiesJSON), &gateway.Properties); err != nil {
return nil, fmt.Errorf("failed to unmarshal properties: %w", err)
}
}

gateways = append(gateways, gateway)
}
return gateways, nil
Expand All @@ -106,28 +138,37 @@ func (r *GatewayRepo) GetByOrganizationID(orgID string) ([]*model.Gateway, error
// GetByNameAndOrgID checks if a gateway with the given name exists within an organization
func (r *GatewayRepo) GetByNameAndOrgID(name, orgID string) (*model.Gateway, error) {
gateway := &model.Gateway{}
var propertiesJSON string
query := `
SELECT uuid, organization_uuid, name, display_name, description, vhost, is_critical, gateway_functionality_type, is_active,
SELECT uuid, organization_uuid, name, display_name, description, properties, vhost, is_critical, gateway_functionality_type, is_active,
created_at, updated_at
FROM gateways
WHERE name = ? AND organization_uuid = ?
`
err := r.db.QueryRow(r.db.Rebind(query), name, orgID).Scan(
&gateway.ID, &gateway.OrganizationID, &gateway.Name, &gateway.DisplayName, &gateway.Description, &gateway.Vhost,
&gateway.ID, &gateway.OrganizationID, &gateway.Name, &gateway.DisplayName, &gateway.Description, &propertiesJSON, &gateway.Vhost,
&gateway.IsCritical, &gateway.FunctionalityType, &gateway.IsActive, &gateway.CreatedAt, &gateway.UpdatedAt)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, nil
}
return nil, err
}

// Deserialize properties from JSON
if propertiesJSON != "" && propertiesJSON != "{}" {
if err := json.Unmarshal([]byte(propertiesJSON), &gateway.Properties); err != nil {
return nil, fmt.Errorf("failed to unmarshal properties: %w", err)
}
}

return gateway, nil
}

// List retrieves all gateways
func (r *GatewayRepo) List() ([]*model.Gateway, error) {
query := `
SELECT uuid, organization_uuid, name, display_name, description, vhost, is_critical, gateway_functionality_type, is_active,
SELECT uuid, organization_uuid, name, display_name, description, properties, vhost, is_critical, gateway_functionality_type, is_active,
created_at, updated_at
FROM gateways
ORDER BY created_at DESC
Expand All @@ -141,12 +182,21 @@ func (r *GatewayRepo) List() ([]*model.Gateway, error) {
var gateways []*model.Gateway
for rows.Next() {
gateway := &model.Gateway{}
var propertiesJSON string
err := rows.Scan(
&gateway.ID, &gateway.OrganizationID, &gateway.Name, &gateway.DisplayName, &gateway.Description, &gateway.Vhost,
&gateway.ID, &gateway.OrganizationID, &gateway.Name, &gateway.DisplayName, &gateway.Description, &propertiesJSON, &gateway.Vhost,
&gateway.IsCritical, &gateway.FunctionalityType, &gateway.IsActive, &gateway.CreatedAt, &gateway.UpdatedAt)
if err != nil {
return nil, err
}

// Deserialize properties from JSON
if propertiesJSON != "" && propertiesJSON != "{}" {
if err := json.Unmarshal([]byte(propertiesJSON), &gateway.Properties); err != nil {
return nil, fmt.Errorf("failed to unmarshal properties: %w", err)
}
}

gateways = append(gateways, gateway)
}
return gateways, nil
Expand Down Expand Up @@ -192,12 +242,24 @@ func (r *GatewayRepo) Delete(gatewayID, organizationID string) error {

// UpdateGateway updates gateway details
func (r *GatewayRepo) UpdateGateway(gateway *model.Gateway) error {
// Serialize properties to JSON
var propertiesJSON string
if gateway.Properties != nil {
jsonBytes, err := json.Marshal(gateway.Properties)
if err != nil {
return fmt.Errorf("failed to marshal properties: %w", err)
}
propertiesJSON = string(jsonBytes)
} else {
propertiesJSON = "{}"
}

query := `
UPDATE gateways
SET display_name = ?, description = ?, is_critical = ?, updated_at = ?
SET display_name = ?, description = ?, is_critical = ?, properties = ?, updated_at = ?
WHERE uuid = ?
`
_, err := r.db.Exec(r.db.Rebind(query), gateway.DisplayName, gateway.Description, gateway.IsCritical, gateway.UpdatedAt, gateway.ID)
_, err := r.db.Exec(r.db.Rebind(query), gateway.DisplayName, gateway.Description, gateway.IsCritical, propertiesJSON, gateway.UpdatedAt, gateway.ID)
return err
}

Expand Down
12 changes: 10 additions & 2 deletions platform-api/src/internal/service/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func NewGatewayService(gatewayRepo repository.GatewayRepository, orgRepo reposit

// RegisterGateway registers a new gateway with organization validation
func (s *GatewayService) RegisterGateway(orgID, name, displayName, description, vhost string, isCritical bool,
functionalityType string) (*dto.GatewayResponse, error) {
functionalityType string, properties map[string]interface{}) (*dto.GatewayResponse, error) {
// 1. Validate inputs
if err := s.validateGatewayInput(orgID, name, displayName, vhost, functionalityType); err != nil {
return nil, err
Expand Down Expand Up @@ -90,6 +90,7 @@ func (s *GatewayService) RegisterGateway(orgID, name, displayName, description,
Name: name,
DisplayName: displayName,
Description: description,
Properties: properties,
Vhost: vhost,
IsCritical: isCritical,
FunctionalityType: functionalityType,
Expand Down Expand Up @@ -141,6 +142,7 @@ func (s *GatewayService) RegisterGateway(orgID, name, displayName, description,
Name: gateway.Name,
DisplayName: gateway.DisplayName,
Description: gateway.Description,
Properties: gateway.Properties,
Vhost: gateway.Vhost,
IsCritical: gateway.IsCritical,
FunctionalityType: gateway.FunctionalityType,
Expand Down Expand Up @@ -177,6 +179,7 @@ func (s *GatewayService) ListGateways(orgID *string) (*dto.GatewayListResponse,
Name: gw.Name,
DisplayName: gw.DisplayName,
Description: gw.Description,
Properties: gw.Properties,
Vhost: gw.Vhost,
IsCritical: gw.IsCritical,
FunctionalityType: gw.FunctionalityType,
Expand Down Expand Up @@ -226,6 +229,7 @@ func (s *GatewayService) GetGateway(gatewayId, orgId string) (*dto.GatewayRespon
Name: gateway.Name,
DisplayName: gateway.DisplayName,
Description: gateway.Description,
Properties: gateway.Properties,
Vhost: gateway.Vhost,
IsCritical: gateway.IsCritical,
FunctionalityType: gateway.FunctionalityType,
Expand All @@ -239,7 +243,7 @@ func (s *GatewayService) GetGateway(gatewayId, orgId string) (*dto.GatewayRespon

// UpdateGateway updates gateway details
func (s *GatewayService) UpdateGateway(gatewayId, orgId string, description, displayName *string,
isCritical *bool) (*dto.GatewayResponse, error) {
isCritical *bool, properties *map[string]interface{}) (*dto.GatewayResponse, error) {
// Get existing gateway
gateway, err := s.gatewayRepo.GetByUUID(gatewayId)
if err != nil {
Expand All @@ -261,6 +265,9 @@ func (s *GatewayService) UpdateGateway(gatewayId, orgId string, description, dis
if isCritical != nil {
gateway.IsCritical = *isCritical
}
if properties != nil {
gateway.Properties = *properties
}
gateway.UpdatedAt = time.Now()

err = s.gatewayRepo.UpdateGateway(gateway)
Expand All @@ -274,6 +281,7 @@ func (s *GatewayService) UpdateGateway(gatewayId, orgId string, description, dis
Name: gateway.Name,
DisplayName: gateway.DisplayName,
Description: gateway.Description,
Properties: gateway.Properties,
Vhost: gateway.Vhost,
IsCritical: gateway.IsCritical,
FunctionalityType: gateway.FunctionalityType,
Expand Down
Loading
Loading