package v2 import ( "errors" "net/http" "strings" "github.com/1Panel-dev/1Panel/agent/app/api/v2/helper" "github.com/1Panel-dev/1Panel/agent/app/dto" "github.com/1Panel-dev/1Panel/agent/app/repo" "github.com/1Panel-dev/1Panel/agent/app/service" "github.com/1Panel-dev/1Panel/agent/global" "github.com/1Panel-dev/1Panel/agent/utils/firewall/filter" "github.com/gin-gonic/gin" ) func (b *BaseApi) UpdatePanelFirewallPort(c *gin.Context) { if !global.IsMaster { c.AbortWithStatus(http.StatusForbidden) return } var request struct { OldPort uint `json:"oldPort" validate:"required,min=1,max=65535"` NewPort uint `json:"newPort" validate:"required,min=1,max=65535"` } if err := helper.CheckBindAndValidate(&request, c); err != nil { return } if err := firewallService.UpdatePanelPort(c.Request.Context(), request.OldPort, request.NewPort); err != nil { helper.InternalServer(c, err) return } helper.Success(c) } // @Tags Firewall // @Summary Load firewall base info // @Accept json // @Param request body dto.OperationWithName true "request" // @Success 200 {object} dto.FirewallSubsystemStatus // @Security ApiKeyAuth // @Security Timestamp // @Router /hosts/firewall/base [post] func (b *BaseApi) LoadFirewallBaseInfo(c *gin.Context) { var request dto.OperationWithName if err := helper.CheckBindAndValidate(&request, c); err != nil { return } data, err := firewallService.LoadBaseInfo(request.Name) if err != nil { helper.InternalServer(c, err) return } helper.SuccessWithData(c, data) } // @Tags Firewall // @Summary Operate firewall // @Accept json // @Param request body dto.FirewallLifecycleOperation true "request" // @Success 200 {object} dto.FirewallLifecycleOperationResponse // @Security ApiKeyAuth // @Security Timestamp // @Router /hosts/firewall/operate [post] // @x-panel-log {"bodyKeys":["operation"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"[operation] 防火墙","formatEN":"[operation] firewall"} func (b *BaseApi) OperateFirewall(c *gin.Context) { var request dto.FirewallLifecycleOperation if err := helper.CheckBindAndValidate(&request, c); err != nil { return } result, err := firewallService.QueueFirewallOperation(request) if err != nil { helper.InternalServer(c, err) return } helper.SuccessWithData(c, result) } // @Tags Firewall // @Summary Load forwarding base info // @Accept json // @Success 200 {object} dto.FirewallSubsystemStatus // @Security ApiKeyAuth // @Security Timestamp // @Router /hosts/firewall/forward/base [post] func (b *BaseApi) LoadForwardingBaseInfo(c *gin.Context) { data, err := forwardingService.LoadBaseInfo() if err != nil { helper.InternalServer(c, err) return } helper.SuccessWithData(c, data) } // @Tags Firewall // @Summary Page forwarding rules // @Accept json // @Param request body dto.ForwardRuleSearch true "request" // @Success 200 {object} dto.PageResult // @Security ApiKeyAuth // @Security Timestamp // @Router /hosts/firewall/forward/search [post] func (b *BaseApi) SearchForwardingRules(c *gin.Context) { var request dto.ForwardRuleSearch if err := helper.CheckBindAndValidate(&request, c); err != nil { return } total, items, err := forwardingService.SearchRules(request) if err != nil { helper.InternalServer(c, err) return } helper.SuccessWithData(c, dto.PageResult{Items: items, Total: total}) } // @Tags Firewall // @Summary Operate forwarding rules // @Accept json // @Param request body dto.ForwardRuleOperate true "request" // @Success 200 {object} dto.FilterChainOperationResponse // @Security ApiKeyAuth // @Security Timestamp // @Router /hosts/firewall/forward/operate [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新端口转发规则","formatEN":"update port forward rules"} func (b *BaseApi) OperateForwardingRules(c *gin.Context) { var request dto.ForwardRuleOperate if err := helper.CheckBindAndValidate(&request, c); err != nil { return } result, err := forwardingService.OperateRules(request) if err != nil { helper.InternalServer(c, err) return } helper.SuccessWithData(c, result) } // @Tags Firewall // @Summary Enable forwarding // @Accept json // @Param request body dto.FirewallInitializationTask true "request" // @Success 200 {object} dto.FilterChainOperationResponse // @Security ApiKeyAuth // @Security Timestamp // @Router /hosts/firewall/forward/enable [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"初始化并启用端口转发","formatEN":"initialize and enable port forwarding"} func (b *BaseApi) EnableForwarding(c *gin.Context) { var request dto.FirewallInitializationTask if err := helper.CheckBindAndValidate(&request, c); err != nil { return } result, err := forwardingService.QueueInitialization(request) if err != nil { helper.InternalServer(c, err) return } helper.SuccessWithData(c, result) } // @Tags Firewall // @Summary Apply/Unload/Init firewall filter chain // @Accept json // @Param request body dto.FilterChainOperation true "request" // @Success 200 {object} dto.FilterChainOperationResponse // @Security ApiKeyAuth // @Security Timestamp // @Router /hosts/firewall/filter/operate [post] // @x-panel-log {"bodyKeys":["operate"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"[operate] 防火墙过滤链","formatEN":"[operate] firewall filter chain"} func (b *BaseApi) OperateFilterChain(c *gin.Context) { var request dto.FilterChainOperation if err := helper.CheckBindAndValidate(&request, c); err != nil { return } if request.Operate == "init-base" { result, err := firewallService.QueueFilterChainInitialization(request) if err != nil { helper.InternalServer(c, err) return } helper.SuccessWithData(c, result) return } if err := firewallService.OperateFilterChain(request); err != nil { helper.InternalServer(c, err) return } helper.SuccessWithData(c, dto.FilterChainOperationResponse{}) } // @Tags Firewall // @Summary List unified firewall v2 rules // @Accept json // @Param request body dto.FirewallRuleInventory true "request" // @Success 200 {object} dto.FirewallRuleInventoryResponse // @Failure 400 {object} dto.Response // @Security ApiKeyAuth // @Security Timestamp // @Router /hosts/firewall/rules/search [post] func (b *BaseApi) SearchFirewallRules(c *gin.Context) { var request dto.FirewallRuleInventory if err := helper.CheckBindAndValidate(&request, c); err != nil { return } inventory, err := firewallService.Inventory(c.Request.Context(), request) if err != nil { handleFirewallRuleError(c, err) return } helper.SuccessWithData(c, inventory) } // @Tags Firewall // @Summary Reset firewall rules // @Accept json // @Param request body dto.FirewallRuleReset true "request" // @Success 200 {object} dto.FirewallRuleResetResponse // @Failure 400 {object} dto.Response // @Security ApiKeyAuth // @Security Timestamp // @Router /hosts/firewall/rules/reset [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"重置防火墙规则","formatEN":"reset firewall rules"} func (b *BaseApi) ResetFirewallRules(c *gin.Context) { var request dto.FirewallRuleReset if err := helper.CheckBindAndValidate(&request, c); err != nil { return } result, err := firewallService.Reset(c.Request.Context(), request) if err != nil { handleFirewallRuleError(c, err) return } helper.SuccessWithData(c, result) } // @Tags Firewall // @Summary Load one provider-native firewall object definition // @Accept json // @Param request body dto.FirewallNativeDetail true "request" // @Success 200 {string} string // @Failure 400 {object} dto.Response // @Security ApiKeyAuth // @Security Timestamp // @Router /hosts/firewall/rules/native/detail [post] func (b *BaseApi) LoadFirewallNativeDetail(c *gin.Context) { var request dto.FirewallNativeDetail if err := helper.CheckBindAndValidate(&request, c); err != nil { return } info, err := firewallService.LoadFirewallNativeDetail(c.Request.Context(), request) if err != nil { handleFirewallRuleError(c, err) return } helper.SuccessWithData(c, info) } // @Tags Firewall // @Summary Adopt an external firewall rule // @Accept json // @Param request body dto.FirewallRuleAdopt true "request" // @Success 200 // @Failure 400 {object} dto.Response // @Security ApiKeyAuth // @Security Timestamp // @Router /hosts/firewall/rules/adopt [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"纳管防火墙规则","formatEN":"adopt firewall rule"} func (b *BaseApi) AdoptFirewallRule(c *gin.Context) { var request dto.FirewallRuleAdopt if err := helper.CheckBindAndValidate(&request, c); err != nil { return } if err := firewallService.Adopt(c.Request.Context(), request); err != nil { handleFirewallRuleError(c, err) return } helper.Success(c) } // @Tags Firewall // @Summary Queue firewall rule creation // @Description Creation and import return a taskID immediately; validation and execution results are written to the task log. // @Accept json // @Param request body dto.FirewallRuleCreate true "request" // @Success 200 {object} dto.FirewallRuleCreateResponse // @Failure 400 {object} dto.Response // @Failure 409 {object} dto.Response // @Security ApiKeyAuth // @Security Timestamp // @Router /hosts/firewall/rules [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"添加防火墙规则","formatEN":"create firewall rules"} func (b *BaseApi) CreateFirewallRules(c *gin.Context) { var request dto.FirewallRuleCreate if err := helper.CheckBindAndValidate(&request, c); err != nil { return } result, err := firewallService.Create(c.Request.Context(), request) if err != nil { handleFirewallRuleError(c, err) return } helper.SuccessWithData(c, result) } // @Tags Firewall // @Summary Preview firewall rule synchronization // @Accept json // @Param request body dto.FirewallRuleSyncRequest true "request" // @Success 200 {object} dto.FirewallRuleSyncPreview // @Failure 400 {object} dto.Response // @Security ApiKeyAuth // @Security Timestamp // @Router /hosts/firewall/rules/sync/preview [post] func (b *BaseApi) PreviewFirewallRuleSync(c *gin.Context) { var request dto.FirewallRuleSyncRequest if err := helper.CheckBindAndValidate(&request, c); err != nil { return } result, err := firewallService.PreviewRuleSync(c.Request.Context(), c.ClientIP(), request) if err != nil { handleFirewallRuleError(c, err) return } helper.SuccessWithData(c, result) } // @Tags Firewall // @Summary Load the currently executing firewall rule synchronization task // @Success 200 {object} dto.FirewallRuleSyncTask // @Security ApiKeyAuth // @Security Timestamp // @Router /hosts/firewall/rules/sync/task [get] func (b *BaseApi) LoadFirewallRuleSyncTask(c *gin.Context) { result, err := firewallService.CurrentRuleSyncTask() if err != nil { helper.InternalServer(c, err) return } helper.SuccessWithData(c, result) } // @Tags Firewall // @Summary Synchronize firewall rules to a target backend // @Accept json // @Param request body dto.FirewallRuleSyncRequest true "request" // @Success 200 {object} dto.FirewallRuleSyncResult // @Failure 400 {object} dto.Response // @Security ApiKeyAuth // @Security Timestamp // @Router /hosts/firewall/rules/sync [post] // @x-panel-log {"bodyKeys":["subsystem","sourceProvider","targetProvider"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"同步 [subsystem] 防火墙规则到 [targetProvider]","formatEN":"sync [subsystem] firewall rules to [targetProvider]"} func (b *BaseApi) SyncFirewallRules(c *gin.Context) { var request dto.FirewallRuleSyncRequest if err := helper.CheckBindAndValidate(&request, c); err != nil { return } result, err := firewallService.SyncRules(c.Request.Context(), c.ClientIP(), request) if err != nil { handleFirewallRuleError(c, err) return } helper.SuccessWithData(c, result) } // @Tags Firewall // @Summary Queue firewall rule deletion // @Description Deletes managed rules by UUID or unprotected before-chain rules by instance key. Returns a taskID immediately; results are written to the task log. // @Accept json // @Param request body dto.FirewallRuleDelete true "request" // @Success 200 {object} dto.FirewallRuleDeleteResponse // @Failure 400 {object} dto.Response // @Security ApiKeyAuth // @Security Timestamp // @Router /hosts/firewall/rules/delete [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"删除防火墙规则","formatEN":"delete firewall rules"} func (b *BaseApi) DeleteFirewallRules(c *gin.Context) { var request dto.FirewallRuleDelete if err := helper.CheckBindAndValidate(&request, c); err != nil { return } result, err := firewallService.Delete(c.Request.Context(), request) if err != nil { handleFirewallRuleError(c, err) return } helper.SuccessWithData(c, result) } // @Tags Firewall // @Summary Update a managed unified firewall v2 rule // @Accept json // @Param request body dto.FirewallRuleUpdate true "request" // @Success 200 // @Failure 400 {object} dto.Response // @Security ApiKeyAuth // @Security Timestamp // @Router /hosts/firewall/rules/update [post] // @x-panel-log {"bodyKeys":["uuid"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新防火墙规则 [uuid]","formatEN":"update firewall rule [uuid]"} func (b *BaseApi) UpdateFirewallRule(c *gin.Context) { var request dto.FirewallRuleUpdate if err := helper.CheckBindAndValidate(&request, c); err != nil { return } if !normalizeFirewallRuleUUID(c, &request.UUID) { return } if err := firewallService.Update(c.Request.Context(), c.ClientIP(), request); err != nil { handleFirewallRuleError(c, err) return } helper.Success(c) } // @Tags Firewall // @Summary Reorder a managed unified firewall v2 rule // @Accept json // @Param request body dto.FirewallRuleReorder true "request" // @Success 200 // @Failure 400 {object} dto.Response // @Security ApiKeyAuth // @Security Timestamp // @Router /hosts/firewall/rules/reorder [post] // @x-panel-log {"bodyKeys":["uuid"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"调整防火墙规则顺序 [uuid]","formatEN":"reorder firewall rule [uuid]"} func (b *BaseApi) ReorderFirewallRule(c *gin.Context) { var request dto.FirewallRuleReorder if err := helper.CheckBindAndValidate(&request, c); err != nil { return } if !normalizeFirewallRuleUUID(c, &request.UUID) { return } if err := firewallService.Reorder(c.Request.Context(), c.ClientIP(), request); err != nil { handleFirewallRuleError(c, err) return } helper.Success(c) } func normalizeFirewallRuleUUID(c *gin.Context, value *string) bool { if value == nil { helper.BadRequest(c, repo.ErrFirewallPersistenceInvalid) return false } *value = strings.TrimSpace(*value) if *value == "" { helper.BadRequest(c, repo.ErrFirewallPersistenceInvalid) return false } return true } func handleFirewallRuleError(c *gin.Context, err error) { switch { case errors.Is(err, filter.ErrProtectedRule): helper.ErrorWithBusinessCode(c, http.StatusBadRequest, "FW_LOCKOUT_RISK", "ErrInvalidParams", err) case errors.Is(err, filter.ErrRuleStale): helper.ErrorWithBusinessCode(c, http.StatusConflict, "FW_RULE_STALE", "ErrInvalidParams", err) case errors.Is(err, repo.ErrFirewallRuleRevisionConflict): helper.ErrorWithBusinessCode(c, http.StatusConflict, "FW_RULE_REVISION_CONFLICT", "ErrInvalidParams", err) case errors.Is(err, filter.ErrManagedScopeChange): helper.ErrorWithBusinessCode(c, http.StatusBadRequest, "FW_SCOPE_UNSUPPORTED", "ErrFirewallRuleScopeChange", err) case errors.Is(err, filter.ErrUnsupportedScope), errors.Is(err, filter.ErrInvalidScope), errors.Is(err, filter.ErrProviderUnavailable), errors.Is(err, filter.ErrAdapterUnavailable): helper.ErrorWithBusinessCode(c, http.StatusBadRequest, "FW_SCOPE_UNSUPPORTED", "ErrInvalidParams", err) case errors.Is(err, filter.ErrInvalidRule), errors.Is(err, filter.ErrRuleOperation), errors.Is(err, filter.ErrRuleConflict), errors.Is(err, repo.ErrFirewallPersistenceInvalid): helper.ErrorWithBusinessCode(c, http.StatusBadRequest, "FW_RULE_UNSUPPORTED", "ErrInvalidParams", err) case errors.Is(err, filter.ErrVerificationFailed): helper.ErrorWithBusinessCode(c, http.StatusInternalServerError, "FW_VERIFY_FAILED", "ErrInternalServer", err) default: helper.ErrorWithBusinessCode(c, http.StatusInternalServerError, "FW_APPLY_FAILED", "ErrInternalServer", err) } } // @Tags Firewall // @Summary Load firewall settings // @Success 200 {object} dto.FirewallSettings // @Security ApiKeyAuth // @Security Timestamp // @Router /hosts/firewall/settings [get] func (b *BaseApi) LoadFirewallSettings(c *gin.Context) { data, err := firewallSettingService.Load(c.Request.Context()) if err != nil { helper.InternalServer(c, err) return } helper.SuccessWithData(c, data) } // @Tags Firewall // @Summary Create firewall port whitelist rules // @Description Saves whitelist configuration only. Missing rules are added on startup, restart, initialization, or synchronization; existing rules are not removed. // @Accept json // @Param request body dto.FirewallPortWhitelistCreate true "request" // @Success 200 // @Security ApiKeyAuth // @Security Timestamp // @Router /hosts/firewall/settings/whitelist [post] // @x-panel-log {"bodyKeys":["rule"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建防火墙端口白名单","formatEN":"create firewall port whitelist"} func (b *BaseApi) CreateFirewallPortWhitelist(c *gin.Context) { var request dto.FirewallPortWhitelistCreate if err := helper.CheckBindAndValidate(&request, c); err != nil { return } if err := firewallSettingService.CreatePortWhitelist(c.Request.Context(), request); err != nil { helper.InternalServer(c, err) return } helper.Success(c) } // @Tags Firewall // @Summary Update firewall port whitelist rules // @Description Saves whitelist configuration only. Missing rules are added on startup, restart, initialization, or synchronization; existing rules are not removed. // @Accept json // @Param request body dto.FirewallPortWhitelistUpdate true "request" // @Success 200 // @Security ApiKeyAuth // @Security Timestamp // @Router /hosts/firewall/settings/whitelist/update [post] // @x-panel-log {"bodyKeys":["oldRule","rule"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"编辑防火墙端口白名单","formatEN":"update firewall port whitelist"} func (b *BaseApi) UpdateFirewallPortWhitelist(c *gin.Context) { var request dto.FirewallPortWhitelistUpdate if err := helper.CheckBindAndValidate(&request, c); err != nil { return } if err := firewallSettingService.UpdatePortWhitelist(c.Request.Context(), request); err != nil { helper.InternalServer(c, err) return } helper.Success(c) } // @Tags Firewall // @Summary Delete firewall port whitelist rules // @Description Saves whitelist configuration only. Missing rules are added on startup, restart, initialization, or synchronization; existing rules are not removed. // @Accept json // @Param request body dto.FirewallPortWhitelistDelete true "request" // @Success 200 // @Security ApiKeyAuth // @Security Timestamp // @Router /hosts/firewall/settings/whitelist/delete [post] // @x-panel-log {"bodyKeys":["rules"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"删除防火墙端口白名单","formatEN":"delete firewall port whitelist"} func (b *BaseApi) DeleteFirewallPortWhitelist(c *gin.Context) { var request dto.FirewallPortWhitelistDelete if err := helper.CheckBindAndValidate(&request, c); err != nil { return } if err := firewallSettingService.DeletePortWhitelist(c.Request.Context(), request); err != nil { helper.InternalServer(c, err) return } helper.Success(c) } // @Tags Firewall // @Summary Operate firewall backend // @Accept json // @Param request body dto.FirewallBackendOperation true "request" // @Success 200 // @Security ApiKeyAuth // @Security Timestamp // @Router /hosts/firewall/settings/operate [post] // @x-panel-log {"bodyKeys":["subsystem","backend","operation"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"防火墙子系统 [subsystem] 后端 [operation] [backend]","formatEN":"[operation] firewall [subsystem] backend [backend]"} func (b *BaseApi) OperateFirewallBackend(c *gin.Context) { var request dto.FirewallBackendOperation if err := helper.CheckBindAndValidate(&request, c); err != nil { return } if err := firewallSettingService.Operate(c.Request.Context(), request); err != nil { if errors.Is(err, service.ErrFirewallBackendCleanupRequired) { helper.ErrorWithBusinessCode( c, http.StatusConflict, "FW_BACKEND_CLEANUP_REQUIRED", "ErrInvalidParams", err, ) return } helper.InternalServer(c, err) return } helper.Success(c) } // @Tags Firewall // @Summary List Docker port guard status and policies // @Success 200 {object} dto.DockerPortGuardList // @Security ApiKeyAuth // @Security Timestamp // @Router /hosts/firewall/docker/ports [get] func (b *BaseApi) ListDockerPortGuard(c *gin.Context) { data, err := dockerPortGuardService.LoadOverview(c.Request.Context()) if err != nil { handleDockerPortGuardError(c, err) return } helper.SuccessWithData(c, data) } // @Tags Firewall // @Summary List Docker published ports // @Success 200 {array} dto.DockerPortGuardContainer // @Security ApiKeyAuth // @Security Timestamp // @Router /hosts/firewall/docker/endpoints [get] func (b *BaseApi) ListDockerPublishedPorts(c *gin.Context) { data, err := dockerPortGuardService.LoadPublishedPorts(c.Request.Context()) if err != nil { handleDockerPortGuardError(c, err) return } helper.SuccessWithData(c, data) } // @Tags Firewall // @Summary Sync Docker port guard rules // @Success 200 // @Security ApiKeyAuth // @Security Timestamp // @Router /hosts/firewall/docker/sync [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"同步 Docker 端口防护规则","formatEN":"sync Docker port guard rules"} func (b *BaseApi) SyncDockerPortGuard(c *gin.Context) { if err := dockerPortGuardService.Reconcile(c.Request.Context()); err != nil { handleDockerPortGuardError(c, err) return } helper.Success(c) } // @Tags Firewall // @Summary Operate Docker port guard // @Accept json // @Param request body dto.DockerPortGuardOperation true "request" // @Success 200 {object} dto.FilterChainOperationResponse // @Security ApiKeyAuth // @Security Timestamp // @Router /hosts/firewall/docker/operate [post] // @x-panel-log {"bodyKeys":["operation"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"[operation] Docker 端口防护","formatEN":"[operation] Docker port guard"} func (b *BaseApi) OperateDockerPortGuard(c *gin.Context) { var request dto.DockerPortGuardOperation if err := helper.CheckBindAndValidate(&request, c); err != nil { return } if request.Operation == "initialize" { result, err := dockerPortGuardService.QueueInitialization(request) if err != nil { handleDockerPortGuardError(c, err) return } helper.SuccessWithData(c, result) return } if err := dockerPortGuardService.Operate(c.Request.Context(), request); err != nil { handleDockerPortGuardError(c, err) return } helper.Success(c) } // @Tags Firewall // @Summary Delete Docker port guard policies // @Accept json // @Param request body dto.DockerPortGuardPolicyBatchDelete true "request" // @Success 200 {object} dto.FilterChainOperationResponse // @Security ApiKeyAuth // @Security Timestamp // @Router /hosts/firewall/docker/policies/delete/batch [post] // @x-panel-log {"bodyKeys":["uuids"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"删除 Docker 端口防护策略 [uuids]","formatEN":"delete Docker port guard policies [uuids]"} func (b *BaseApi) DeleteDockerPortGuardPolicies(c *gin.Context) { var request dto.DockerPortGuardPolicyBatchDelete if err := helper.CheckBindAndValidate(&request, c); err != nil { return } result, err := dockerPortGuardService.DeletePolicies(request) if err != nil { handleDockerPortGuardError(c, err) return } helper.SuccessWithData(c, result) } // @Tags Firewall // @Summary Batch upsert Docker port guard policies // @Accept json // @Param request body dto.DockerPortGuardPolicyBatch true "request" // @Success 200 {object} dto.FilterChainOperationResponse // @Security ApiKeyAuth // @Security Timestamp // @Router /hosts/firewall/docker/policies/batch [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"批量更新 Docker 端口防护策略","formatEN":"batch update Docker port guard policies"} func (b *BaseApi) UpsertDockerPortGuardPolicies(c *gin.Context) { var request dto.DockerPortGuardPolicyBatch if err := helper.CheckBindAndValidate(&request, c); err != nil { return } result, err := dockerPortGuardService.UpsertPolicies(request) if err != nil { handleDockerPortGuardError(c, err) return } helper.SuccessWithData(c, result) } func handleDockerPortGuardError(c *gin.Context, err error) { if errors.Is(err, service.ErrDockerIptablesChainUnavailable) { helper.ErrorWithBusinessCode(c, http.StatusServiceUnavailable, "FW_DOCKER_IPTABLES_CHAIN_UNAVAILABLE", "ErrDockerIptablesChainUnavailable", err) return } if errors.Is(err, service.ErrDockerNftablesChainUnavailable) { helper.ErrorWithBusinessCode(c, http.StatusServiceUnavailable, "FW_DOCKER_NFTABLES_CHAIN_UNAVAILABLE", "ErrDockerNftablesChainUnavailable", err) return } if errors.Is(err, service.ErrDockerGuardInvalid) { helper.ErrorWithBusinessCode(c, http.StatusBadRequest, "FW_DOCKER_GUARD_INVALID", "ErrInvalidParams", err) return } if errors.Is(err, service.ErrDockerUnavailable) { helper.ErrorWithBusinessCode(c, http.StatusServiceUnavailable, "FW_DOCKER_UNAVAILABLE", "ErrDockerFailed", err) return } helper.ErrorWithBusinessCode(c, http.StatusInternalServerError, "FW_DOCKER_GUARD_FAILED", "ErrInternalServer", err) }