fix: enhance security header profile handling in ProxyHost to support UUIDs and improve form data normalization

This commit is contained in:
GitHub Actions
2026-02-28 12:58:59 +00:00
parent cdf7948575
commit 5fe1cf9265
3 changed files with 63 additions and 8 deletions

View File

@@ -216,6 +216,38 @@ func (h *ProxyHostHandler) resolveAccessListReference(value any) (*uint, error)
return &id, nil
}
func (h *ProxyHostHandler) resolveSecurityHeaderProfileReference(value any) (*uint, error) {
if value == nil {
return nil, nil
}
parsedID, _, parseErr := parseNullableUintField(value, "security_header_profile_id")
if parseErr == nil {
return parsedID, nil
}
uuidValue, isString := value.(string)
if !isString {
return nil, parseErr
}
trimmed := strings.TrimSpace(uuidValue)
if trimmed == "" {
return nil, nil
}
var profile models.SecurityHeaderProfile
if err := h.db.Select("id").Where("uuid = ?", trimmed).First(&profile).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return nil, fmt.Errorf("security header profile not found")
}
return nil, fmt.Errorf("failed to resolve security header profile")
}
id := profile.ID
return &id, nil
}
func parseForwardPortField(value any) (int, error) {
switch v := value.(type) {
case float64:
@@ -301,6 +333,15 @@ func (h *ProxyHostHandler) Create(c *gin.Context) {
payload["access_list_id"] = resolvedAccessListID
}
if rawSecurityHeaderRef, ok := payload["security_header_profile_id"]; ok {
resolvedSecurityHeaderID, resolveErr := h.resolveSecurityHeaderProfileReference(rawSecurityHeaderRef)
if resolveErr != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": resolveErr.Error()})
return
}
payload["security_header_profile_id"] = resolvedSecurityHeaderID
}
payloadBytes, marshalErr := json.Marshal(payload)
if marshalErr != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request payload"})
@@ -508,12 +549,12 @@ func (h *ProxyHostHandler) Update(c *gin.Context) {
// Security Header Profile: update only if provided
if v, ok := payload["security_header_profile_id"]; ok {
parsedID, _, parseErr := parseNullableUintField(v, "security_header_profile_id")
if parseErr != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": parseErr.Error()})
resolvedSecurityHeaderID, resolveErr := h.resolveSecurityHeaderProfileReference(v)
if resolveErr != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": resolveErr.Error()})
return
}
host.SecurityHeaderProfileID = parsedID
host.SecurityHeaderProfileID = resolvedSecurityHeaderID
}
// Locations: replace only if provided

View File

@@ -49,10 +49,10 @@ export interface ProxyHost {
description: string;
type: string;
} | null;
security_header_profile_id?: number | null;
security_header_profile_id?: number | string | null;
dns_provider_id?: number | null;
security_header_profile?: {
id: number;
id?: number;
uuid: string;
name: string;
description: string;

View File

@@ -124,7 +124,7 @@ function buildInitialFormData(host?: ProxyHost): Partial<ProxyHost> & {
enabled: host?.enabled ?? true,
certificate_id: host?.certificate_id,
access_list_id: host?.access_list?.uuid ?? host?.access_list_id,
security_header_profile_id: host?.security_header_profile_id,
security_header_profile_id: host?.security_header_profile?.uuid ?? host?.security_header_profile_id,
dns_provider_id: host?.dns_provider_id || null,
}
}
@@ -173,6 +173,20 @@ function normalizeAccessListReference(value: unknown): number | string | null |
return trimmed === '' ? null : trimmed
}
function normalizeSecurityHeaderReference(value: unknown): number | string | null | undefined {
const numericValue = normalizeNullableID(value)
if (numericValue !== undefined) {
return numericValue
}
if (typeof value !== 'string') {
return undefined
}
const trimmed = value.trim()
return trimmed === '' ? null : trimmed
}
function resolveSelectToken(value: number | string | null | undefined): string {
if (value === null || value === undefined) {
return 'none'
@@ -546,7 +560,7 @@ export default function ProxyHostForm({ host, onSubmit, onCancel }: ProxyHostFor
const submitPayload: Partial<ProxyHost> = {
...payloadWithoutUptime,
access_list_id: normalizeAccessListReference(payloadWithoutUptime.access_list_id),
security_header_profile_id: normalizeNullableID(payloadWithoutUptime.security_header_profile_id),
security_header_profile_id: normalizeSecurityHeaderReference(payloadWithoutUptime.security_header_profile_id),
}
const res = await onSubmit(submitPayload)